/src/mozilla-central/security/nss/lib/ssl/ssl3gthr.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * Gather (Read) entire SSL3 records from socket into buffer. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
8 | | |
9 | | #include "cert.h" |
10 | | #include "ssl.h" |
11 | | #include "sslimpl.h" |
12 | | #include "sslproto.h" |
13 | | #include "ssl3prot.h" |
14 | | |
15 | | struct ssl2GatherStr { |
16 | | /* true when ssl3_GatherData encounters an SSLv2 handshake */ |
17 | | PRBool isV2; |
18 | | |
19 | | /* number of bytes of padding appended to the message content */ |
20 | | PRUint8 padding; |
21 | | }; |
22 | | |
23 | | typedef struct ssl2GatherStr ssl2Gather; |
24 | | |
25 | | /* Caller should hold RecvBufLock. */ |
26 | | SECStatus |
27 | | ssl3_InitGather(sslGather *gs) |
28 | 0 | { |
29 | 0 | SECStatus status; |
30 | 0 |
|
31 | 0 | gs->state = GS_INIT; |
32 | 0 | gs->writeOffset = 0; |
33 | 0 | gs->readOffset = 0; |
34 | 0 | gs->dtlsPacketOffset = 0; |
35 | 0 | gs->dtlsPacket.len = 0; |
36 | 0 | gs->rejectV2Records = PR_FALSE; |
37 | 0 | status = sslBuffer_Grow(&gs->buf, 4096); |
38 | 0 | return status; |
39 | 0 | } |
40 | | |
41 | | /* Caller must hold RecvBufLock. */ |
42 | | void |
43 | | ssl3_DestroyGather(sslGather *gs) |
44 | 0 | { |
45 | 0 | if (gs) { /* the PORT_*Free functions check for NULL pointers. */ |
46 | 0 | PORT_ZFree(gs->buf.buf, gs->buf.space); |
47 | 0 | PORT_Free(gs->inbuf.buf); |
48 | 0 | PORT_Free(gs->dtlsPacket.buf); |
49 | 0 | } |
50 | 0 | } |
51 | | |
52 | | /* Checks whether a given buffer is likely an SSLv3 record header. */ |
53 | | PRBool |
54 | | ssl3_isLikelyV3Hello(const unsigned char *buf) |
55 | 0 | { |
56 | 0 | /* Even if this was a V2 record header we couldn't possibly parse it |
57 | 0 | * correctly as the second bit denotes a vaguely-defined security escape. */ |
58 | 0 | if (buf[0] & 0x40) { |
59 | 0 | return PR_TRUE; |
60 | 0 | } |
61 | 0 |
|
62 | 0 | /* Check for a typical V3 record header. */ |
63 | 0 | return (PRBool)(buf[0] >= ssl_ct_change_cipher_spec && |
64 | 0 | buf[0] <= ssl_ct_application_data && |
65 | 0 | buf[1] == MSB(SSL_LIBRARY_VERSION_3_0)); |
66 | 0 | } |
67 | | |
68 | | /* |
69 | | * Attempt to read in an entire SSL3 record. |
70 | | * Blocks here for blocking sockets, otherwise returns -1 with |
71 | | * PR_WOULD_BLOCK_ERROR when socket would block. |
72 | | * |
73 | | * returns 1 if received a complete SSL3 record. |
74 | | * returns 0 if recv returns EOF |
75 | | * returns -1 if recv returns < 0 |
76 | | * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
77 | | * |
78 | | * Caller must hold the recv buf lock. |
79 | | * |
80 | | * The Gather state machine has 3 states: GS_INIT, GS_HEADER, GS_DATA. |
81 | | * GS_HEADER: waiting for the 5-byte SSL3 record header to come in. |
82 | | * GS_DATA: waiting for the body of the SSL3 record to come in. |
83 | | * |
84 | | * This loop returns when either |
85 | | * (a) an error or EOF occurs, |
86 | | * (b) PR_WOULD_BLOCK_ERROR, |
87 | | * (c) data (entire SSL3 record) has been received. |
88 | | */ |
89 | | static int |
90 | | ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags, ssl2Gather *ssl2gs) |
91 | 0 | { |
92 | 0 | unsigned char *bp; |
93 | 0 | unsigned char *lbp; |
94 | 0 | int nb; |
95 | 0 | int err; |
96 | 0 | int rv = 1; |
97 | 0 | PRUint8 v2HdrLength = 0; |
98 | 0 |
|
99 | 0 | PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
100 | 0 | if (gs->state == GS_INIT) { |
101 | 0 | gs->state = GS_HEADER; |
102 | 0 | gs->remainder = 5; |
103 | 0 | gs->offset = 0; |
104 | 0 | gs->writeOffset = 0; |
105 | 0 | gs->readOffset = 0; |
106 | 0 | gs->inbuf.len = 0; |
107 | 0 | } |
108 | 0 |
|
109 | 0 | lbp = gs->inbuf.buf; |
110 | 0 | for (;;) { |
111 | 0 | SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)", |
112 | 0 | SSL_GETPID(), ss->fd, gs->state, gs->remainder)); |
113 | 0 | bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset; |
114 | 0 | nb = ssl_DefRecv(ss, bp, gs->remainder, flags); |
115 | 0 |
|
116 | 0 | if (nb > 0) { |
117 | 0 | PRINT_BUF(60, (ss, "raw gather data:", bp, nb)); |
118 | 0 | } else if (nb == 0) { |
119 | 0 | /* EOF */ |
120 | 0 | SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
121 | 0 | rv = 0; |
122 | 0 | break; |
123 | 0 | } else /* if (nb < 0) */ { |
124 | 0 | SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
125 | 0 | PR_GetError())); |
126 | 0 | rv = SECFailure; |
127 | 0 | break; |
128 | 0 | } |
129 | 0 | |
130 | 0 | PORT_Assert((unsigned int)nb <= gs->remainder); |
131 | 0 | if ((unsigned int)nb > gs->remainder) { |
132 | 0 | /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */ |
133 | 0 | gs->state = GS_INIT; /* so we don't crash next time */ |
134 | 0 | rv = SECFailure; |
135 | 0 | break; |
136 | 0 | } |
137 | 0 |
|
138 | 0 | gs->offset += nb; |
139 | 0 | gs->remainder -= nb; |
140 | 0 | if (gs->state == GS_DATA) |
141 | 0 | gs->inbuf.len += nb; |
142 | 0 |
|
143 | 0 | /* if there's more to go, read some more. */ |
144 | 0 | if (gs->remainder > 0) { |
145 | 0 | continue; |
146 | 0 | } |
147 | 0 | |
148 | 0 | /* have received entire record header, or entire record. */ |
149 | 0 | switch (gs->state) { |
150 | 0 | case GS_HEADER: |
151 | 0 | /* Check for SSLv2 handshakes. Always assume SSLv3 on clients, |
152 | 0 | * support SSLv2 handshakes only when ssl2gs != NULL. |
153 | 0 | * Always assume v3 after we received the first record. */ |
154 | 0 | if (!ssl2gs || |
155 | 0 | ss->gs.rejectV2Records || |
156 | 0 | ssl3_isLikelyV3Hello(gs->hdr)) { |
157 | 0 | /* Should have a non-SSLv2 record header in gs->hdr. Extract |
158 | 0 | * the length of the following encrypted data, and then |
159 | 0 | * read in the rest of the record into gs->inbuf. */ |
160 | 0 | gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; |
161 | 0 | gs->hdrLen = SSL3_RECORD_HEADER_LENGTH; |
162 | 0 | } else { |
163 | 0 | /* Probably an SSLv2 record header. No need to handle any |
164 | 0 | * security escapes (gs->hdr[0] & 0x40) as we wouldn't get |
165 | 0 | * here if one was set. See ssl3_isLikelyV3Hello(). */ |
166 | 0 | gs->remainder = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1]; |
167 | 0 | ssl2gs->isV2 = PR_TRUE; |
168 | 0 | v2HdrLength = 2; |
169 | 0 |
|
170 | 0 | /* Is it a 3-byte header with padding? */ |
171 | 0 | if (!(gs->hdr[0] & 0x80)) { |
172 | 0 | ssl2gs->padding = gs->hdr[2]; |
173 | 0 | v2HdrLength++; |
174 | 0 | } |
175 | 0 | } |
176 | 0 |
|
177 | 0 | /* This is the max length for an encrypted SSLv3+ fragment. */ |
178 | 0 | if (!v2HdrLength && |
179 | 0 | gs->remainder > (MAX_FRAGMENT_LENGTH + 2048)) { |
180 | 0 | SSL3_SendAlert(ss, alert_fatal, record_overflow); |
181 | 0 | gs->state = GS_INIT; |
182 | 0 | PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
183 | 0 | return SECFailure; |
184 | 0 | } |
185 | 0 |
|
186 | 0 | gs->state = GS_DATA; |
187 | 0 | gs->offset = 0; |
188 | 0 | gs->inbuf.len = 0; |
189 | 0 |
|
190 | 0 | if (gs->remainder > gs->inbuf.space) { |
191 | 0 | err = sslBuffer_Grow(&gs->inbuf, gs->remainder); |
192 | 0 | if (err) { /* realloc has set error code to no mem. */ |
193 | 0 | return err; |
194 | 0 | } |
195 | 0 | lbp = gs->inbuf.buf; |
196 | 0 | } |
197 | 0 |
|
198 | 0 | /* When we encounter an SSLv2 hello we've read 2 or 3 bytes too |
199 | 0 | * many into the gs->hdr[] buffer. Copy them over into inbuf so |
200 | 0 | * that we can properly process the hello record later. */ |
201 | 0 | if (v2HdrLength) { |
202 | 0 | /* Reject v2 records that don't even carry enough data to |
203 | 0 | * resemble a valid ClientHello header. */ |
204 | 0 | if (gs->remainder < SSL_HL_CLIENT_HELLO_HBYTES) { |
205 | 0 | SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
206 | 0 | PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); |
207 | 0 | return SECFailure; |
208 | 0 | } |
209 | 0 |
|
210 | 0 | PORT_Assert(lbp); |
211 | 0 | gs->inbuf.len = 5 - v2HdrLength; |
212 | 0 | PORT_Memcpy(lbp, gs->hdr + v2HdrLength, gs->inbuf.len); |
213 | 0 | gs->remainder -= gs->inbuf.len; |
214 | 0 | lbp += gs->inbuf.len; |
215 | 0 | } |
216 | 0 |
|
217 | 0 | if (gs->remainder > 0) { |
218 | 0 | break; /* End this case. Continue around the loop. */ |
219 | 0 | } |
220 | 0 | |
221 | 0 | /* FALL THROUGH if (gs->remainder == 0) as we just received |
222 | 0 | * an empty record and there's really no point in calling |
223 | 0 | * ssl_DefRecv() with buf=NULL and len=0. */ |
224 | 0 | |
225 | 0 | case GS_DATA: |
226 | 0 | /* |
227 | 0 | ** SSL3 record has been completely received. |
228 | 0 | */ |
229 | 0 | SSL_TRC(10, ("%d: SSL[%d]: got record of %d bytes", |
230 | 0 | SSL_GETPID(), ss->fd, gs->inbuf.len)); |
231 | 0 |
|
232 | 0 | /* reject any v2 records from now on */ |
233 | 0 | ss->gs.rejectV2Records = PR_TRUE; |
234 | 0 |
|
235 | 0 | gs->state = GS_INIT; |
236 | 0 | return 1; |
237 | 0 | } |
238 | 0 | } |
239 | 0 |
|
240 | 0 | return rv; |
241 | 0 | } |
242 | | |
243 | | /* |
244 | | * Read in an entire DTLS record. |
245 | | * |
246 | | * Blocks here for blocking sockets, otherwise returns -1 with |
247 | | * PR_WOULD_BLOCK_ERROR when socket would block. |
248 | | * |
249 | | * This is simpler than SSL because we are reading on a datagram socket |
250 | | * and datagrams must contain >=1 complete records. |
251 | | * |
252 | | * returns 1 if received a complete DTLS record. |
253 | | * returns 0 if recv returns EOF |
254 | | * returns -1 if recv returns < 0 |
255 | | * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
256 | | * |
257 | | * Caller must hold the recv buf lock. |
258 | | * |
259 | | * This loop returns when either |
260 | | * (a) an error or EOF occurs, |
261 | | * (b) PR_WOULD_BLOCK_ERROR, |
262 | | * (c) data (entire DTLS record) has been received. |
263 | | */ |
264 | | static int |
265 | | dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) |
266 | 0 | { |
267 | 0 | int nb; |
268 | 0 | PRUint8 contentType; |
269 | 0 | unsigned int headerLen; |
270 | 0 | SECStatus rv; |
271 | 0 |
|
272 | 0 | SSL_TRC(30, ("dtls_GatherData")); |
273 | 0 |
|
274 | 0 | PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
275 | 0 |
|
276 | 0 | gs->state = GS_HEADER; |
277 | 0 | gs->offset = 0; |
278 | 0 |
|
279 | 0 | if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ |
280 | 0 | gs->dtlsPacketOffset = 0; |
281 | 0 | gs->dtlsPacket.len = 0; |
282 | 0 |
|
283 | 0 | /* Resize to the maximum possible size so we can fit a full datagram */ |
284 | 0 | /* This is the max fragment length for an encrypted fragment |
285 | 0 | ** plus the size of the record header. |
286 | 0 | ** This magic constant is copied from ssl3_GatherData, with 5 changed |
287 | 0 | ** to 13 (the size of the record header). |
288 | 0 | */ |
289 | 0 | if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { |
290 | 0 | rv = sslBuffer_Grow(&gs->dtlsPacket, |
291 | 0 | MAX_FRAGMENT_LENGTH + 2048 + 13); |
292 | 0 | if (rv != SECSuccess) { |
293 | 0 | return -1; /* Code already set. */ |
294 | 0 | } |
295 | 0 | } |
296 | 0 | |
297 | 0 | /* recv() needs to read a full datagram at a time */ |
298 | 0 | nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); |
299 | 0 | if (nb > 0) { |
300 | 0 | PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); |
301 | 0 | } else if (nb == 0) { |
302 | 0 | /* EOF */ |
303 | 0 | SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
304 | 0 | return 0; |
305 | 0 | } else /* if (nb < 0) */ { |
306 | 0 | SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
307 | 0 | PR_GetError())); |
308 | 0 | return -1; |
309 | 0 | } |
310 | 0 | |
311 | 0 | gs->dtlsPacket.len = nb; |
312 | 0 | } |
313 | 0 |
|
314 | 0 | contentType = gs->dtlsPacket.buf[gs->dtlsPacketOffset]; |
315 | 0 | if (dtls_IsLongHeader(ss->version, contentType)) { |
316 | 0 | headerLen = 13; |
317 | 0 | } else if (contentType == ssl_ct_application_data) { |
318 | 0 | headerLen = 7; |
319 | 0 | } else if ((contentType & 0xe0) == 0x20) { |
320 | 0 | headerLen = 2; |
321 | 0 | } else { |
322 | 0 | SSL_DBG(("%d: SSL3[%d]: invalid first octet (%d) for DTLS", |
323 | 0 | SSL_GETPID(), ss->fd, contentType)); |
324 | 0 | PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE); |
325 | 0 | gs->dtlsPacketOffset = 0; |
326 | 0 | gs->dtlsPacket.len = 0; |
327 | 0 | return -1; |
328 | 0 | } |
329 | 0 |
|
330 | 0 | /* At this point we should have >=1 complete records lined up in |
331 | 0 | * dtlsPacket. Read off the header. |
332 | 0 | */ |
333 | 0 | if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < headerLen) { |
334 | 0 | SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " |
335 | 0 | "too short to contain header", |
336 | 0 | SSL_GETPID(), ss->fd)); |
337 | 0 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
338 | 0 | gs->dtlsPacketOffset = 0; |
339 | 0 | gs->dtlsPacket.len = 0; |
340 | 0 | return -1; |
341 | 0 | } |
342 | 0 | memcpy(gs->hdr, SSL_BUFFER_BASE(&gs->dtlsPacket) + gs->dtlsPacketOffset, |
343 | 0 | headerLen); |
344 | 0 | gs->hdrLen = headerLen; |
345 | 0 | gs->dtlsPacketOffset += headerLen; |
346 | 0 |
|
347 | 0 | /* Have received SSL3 record header in gs->hdr. */ |
348 | 0 | if (headerLen == 13) { |
349 | 0 | gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; |
350 | 0 | } else if (headerLen == 7) { |
351 | 0 | gs->remainder = (gs->hdr[5] << 8) | gs->hdr[6]; |
352 | 0 | } else { |
353 | 0 | PORT_Assert(headerLen == 2); |
354 | 0 | gs->remainder = gs->dtlsPacket.len - gs->dtlsPacketOffset; |
355 | 0 | } |
356 | 0 |
|
357 | 0 | if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { |
358 | 0 | SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " |
359 | 0 | "to contain rest of body", |
360 | 0 | SSL_GETPID(), ss->fd)); |
361 | 0 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
362 | 0 | gs->dtlsPacketOffset = 0; |
363 | 0 | gs->dtlsPacket.len = 0; |
364 | 0 | return -1; |
365 | 0 | } |
366 | 0 |
|
367 | 0 | /* OK, we have at least one complete packet, copy into inbuf */ |
368 | 0 | gs->inbuf.len = 0; |
369 | 0 | rv = sslBuffer_Append(&gs->inbuf, |
370 | 0 | SSL_BUFFER_BASE(&gs->dtlsPacket) + gs->dtlsPacketOffset, |
371 | 0 | gs->remainder); |
372 | 0 | if (rv != SECSuccess) { |
373 | 0 | return -1; /* code already set. */ |
374 | 0 | } |
375 | 0 | gs->offset = gs->remainder; |
376 | 0 | gs->dtlsPacketOffset += gs->remainder; |
377 | 0 | gs->state = GS_INIT; |
378 | 0 |
|
379 | 0 | SSL_TRC(20, ("%d: SSL3[%d]: dtls gathered record type=%d len=%d", |
380 | 0 | SSL_GETPID(), ss->fd, contentType, gs->inbuf.len)); |
381 | 0 | return 1; |
382 | 0 | } |
383 | | |
384 | | /* Gather in a record and when complete, Handle that record. |
385 | | * Repeat this until the handshake is complete, |
386 | | * or until application data is available. |
387 | | * |
388 | | * Returns 1 when the handshake is completed without error, or |
389 | | * application data is available. |
390 | | * Returns 0 if ssl3_GatherData hits EOF. |
391 | | * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
392 | | * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
393 | | * |
394 | | * Called from ssl_GatherRecord1stHandshake in sslcon.c, |
395 | | * and from SSL_ForceHandshake in sslsecur.c |
396 | | * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). |
397 | | * |
398 | | * Caller must hold the recv buf lock. |
399 | | */ |
400 | | int |
401 | | ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) |
402 | 0 | { |
403 | 0 | int rv; |
404 | 0 | SSL3Ciphertext cText; |
405 | 0 | PRBool keepGoing = PR_TRUE; |
406 | 0 |
|
407 | 0 | if (ss->ssl3.fatalAlertSent) { |
408 | 0 | SSL_TRC(3, ("%d: SSL3[%d] Cannot gather data; fatal alert already sent", |
409 | 0 | SSL_GETPID(), ss->fd)); |
410 | 0 | PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED); |
411 | 0 | return SECFailure; |
412 | 0 | } |
413 | 0 |
|
414 | 0 | SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake", |
415 | 0 | SSL_GETPID(), ss->fd)); |
416 | 0 |
|
417 | 0 | /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, |
418 | 0 | * which requires the 1stHandshakeLock, which must be acquired before the |
419 | 0 | * RecvBufLock. |
420 | 0 | */ |
421 | 0 | PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); |
422 | 0 | PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
423 | 0 |
|
424 | 0 | do { |
425 | 0 | PRBool handleRecordNow = PR_FALSE; |
426 | 0 | PRBool processingEarlyData; |
427 | 0 |
|
428 | 0 | ssl_GetSSL3HandshakeLock(ss); |
429 | 0 |
|
430 | 0 | processingEarlyData = ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted; |
431 | 0 |
|
432 | 0 | /* Without this, we may end up wrongly reporting |
433 | 0 | * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the |
434 | 0 | * peer while we are waiting to be restarted. |
435 | 0 | */ |
436 | 0 | if (ss->ssl3.hs.restartTarget) { |
437 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
438 | 0 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
439 | 0 | return (int)SECFailure; |
440 | 0 | } |
441 | 0 |
|
442 | 0 | /* Treat an empty msgState like a NULL msgState. (Most of the time |
443 | 0 | * when ssl3_HandleHandshake returns SECWouldBlock, it leaves |
444 | 0 | * behind a non-NULL but zero-length msgState). |
445 | 0 | * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record |
446 | 0 | */ |
447 | 0 | if (ss->ssl3.hs.msgState.buf) { |
448 | 0 | if (ss->ssl3.hs.msgState.len == 0) { |
449 | 0 | ss->ssl3.hs.msgState.buf = NULL; |
450 | 0 | } else { |
451 | 0 | handleRecordNow = PR_TRUE; |
452 | 0 | } |
453 | 0 | } |
454 | 0 |
|
455 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
456 | 0 |
|
457 | 0 | if (handleRecordNow) { |
458 | 0 | /* ssl3_HandleHandshake previously returned SECWouldBlock and the |
459 | 0 | * as-yet-unprocessed plaintext of that previous handshake record. |
460 | 0 | * We need to process it now before we overwrite it with the next |
461 | 0 | * handshake record. |
462 | 0 | */ |
463 | 0 | SSL_DBG(("%d: SSL3[%d]: resuming handshake", |
464 | 0 | SSL_GETPID(), ss->fd)); |
465 | 0 | PORT_Assert(!IS_DTLS(ss)); |
466 | 0 | rv = ssl3_HandleNonApplicationData(ss, ssl_ct_handshake, |
467 | 0 | 0, 0, &ss->gs.buf); |
468 | 0 | } else { |
469 | 0 | /* State for SSLv2 client hello support. */ |
470 | 0 | ssl2Gather ssl2gs = { PR_FALSE, 0 }; |
471 | 0 | ssl2Gather *ssl2gs_ptr = NULL; |
472 | 0 |
|
473 | 0 | if (ss->sec.isServer && ss->opt.enableV2CompatibleHello && |
474 | 0 | ss->ssl3.hs.ws == wait_client_hello) { |
475 | 0 | ssl2gs_ptr = &ssl2gs; |
476 | 0 | } |
477 | 0 |
|
478 | 0 | /* bring in the next sslv3 record. */ |
479 | 0 | if (ss->recvdCloseNotify) { |
480 | 0 | /* RFC 5246 Section 7.2.1: |
481 | 0 | * Any data received after a closure alert is ignored. |
482 | 0 | */ |
483 | 0 | return 0; |
484 | 0 | } |
485 | 0 | |
486 | 0 | if (!IS_DTLS(ss)) { |
487 | 0 | /* Passing a non-NULL ssl2gs here enables detection of |
488 | 0 | * SSLv2-compatible ClientHello messages. */ |
489 | 0 | rv = ssl3_GatherData(ss, &ss->gs, flags, ssl2gs_ptr); |
490 | 0 | } else { |
491 | 0 | rv = dtls_GatherData(ss, &ss->gs, flags); |
492 | 0 |
|
493 | 0 | /* If we got a would block error, that means that no data was |
494 | 0 | * available, so we check the timer to see if it's time to |
495 | 0 | * retransmit */ |
496 | 0 | if (rv == SECFailure && |
497 | 0 | (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { |
498 | 0 | dtls_CheckTimer(ss); |
499 | 0 | /* Restore the error in case something succeeded */ |
500 | 0 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
501 | 0 | } |
502 | 0 | } |
503 | 0 |
|
504 | 0 | if (rv <= 0) { |
505 | 0 | return rv; |
506 | 0 | } |
507 | 0 | |
508 | 0 | if (ssl2gs.isV2) { |
509 | 0 | rv = ssl3_HandleV2ClientHello(ss, ss->gs.inbuf.buf, |
510 | 0 | ss->gs.inbuf.len, |
511 | 0 | ssl2gs.padding); |
512 | 0 | if (rv < 0) { |
513 | 0 | return rv; |
514 | 0 | } |
515 | 0 | } else { |
516 | 0 | /* decipher it, and handle it if it's a handshake. |
517 | 0 | * If it's application data, ss->gs.buf will not be empty upon return. |
518 | 0 | * If it's a change cipher spec, alert, or handshake message, |
519 | 0 | * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess. |
520 | 0 | * |
521 | 0 | * cText only needs to be valid for this next function call, so |
522 | 0 | * it can borrow gs.hdr. |
523 | 0 | */ |
524 | 0 | cText.hdr = ss->gs.hdr; |
525 | 0 | cText.hdrLen = ss->gs.hdrLen; |
526 | 0 | cText.buf = &ss->gs.inbuf; |
527 | 0 | rv = ssl3_HandleRecord(ss, &cText); |
528 | 0 | } |
529 | 0 | } |
530 | 0 | if (rv < 0) { |
531 | 0 | return ss->recvdCloseNotify ? 0 : rv; |
532 | 0 | } |
533 | 0 | if (ss->gs.buf.len > 0) { |
534 | 0 | /* We have application data to return to the application. This |
535 | 0 | * prioritizes returning application data to the application over |
536 | 0 | * completing any renegotiation handshake we may be doing. |
537 | 0 | */ |
538 | 0 | PORT_Assert(ss->firstHsDone); |
539 | 0 | break; |
540 | 0 | } |
541 | 0 |
|
542 | 0 | PORT_Assert(keepGoing); |
543 | 0 | ssl_GetSSL3HandshakeLock(ss); |
544 | 0 | if (ss->ssl3.hs.ws == idle_handshake) { |
545 | 0 | /* We are done with the current handshake so stop trying to |
546 | 0 | * handshake. Note that it would be safe to test ss->firstHsDone |
547 | 0 | * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, |
548 | 0 | * we prioritize completing a renegotiation handshake over sending |
549 | 0 | * application data. |
550 | 0 | */ |
551 | 0 | PORT_Assert(ss->firstHsDone); |
552 | 0 | PORT_Assert(!ss->ssl3.hs.canFalseStart); |
553 | 0 | keepGoing = PR_FALSE; |
554 | 0 | } else if (ss->ssl3.hs.canFalseStart) { |
555 | 0 | /* Prioritize sending application data over trying to complete |
556 | 0 | * the handshake if we're false starting. |
557 | 0 | * |
558 | 0 | * If we were to do this check at the beginning of the loop instead |
559 | 0 | * of here, then this function would become be a no-op after |
560 | 0 | * receiving the ServerHelloDone in the false start case, and we |
561 | 0 | * would never complete the handshake. |
562 | 0 | */ |
563 | 0 | PORT_Assert(!ss->firstHsDone); |
564 | 0 |
|
565 | 0 | if (ssl3_WaitingForServerSecondRound(ss)) { |
566 | 0 | keepGoing = PR_FALSE; |
567 | 0 | } else { |
568 | 0 | ss->ssl3.hs.canFalseStart = PR_FALSE; |
569 | 0 | } |
570 | 0 | } else if (processingEarlyData && |
571 | 0 | ss->ssl3.hs.zeroRttState == ssl_0rtt_done && |
572 | 0 | !PR_CLIST_IS_EMPTY(&ss->ssl3.hs.bufferedEarlyData)) { |
573 | 0 | /* If we were processing early data and we are no longer, then force |
574 | 0 | * the handshake to block. This ensures that early data is |
575 | 0 | * delivered to the application before the handshake completes. */ |
576 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
577 | 0 | PORT_SetError(PR_WOULD_BLOCK_ERROR); |
578 | 0 | return SECWouldBlock; |
579 | 0 | } |
580 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
581 | 0 | } while (keepGoing); |
582 | 0 |
|
583 | 0 | /* Service the DTLS timer so that the post-handshake timers |
584 | 0 | * fire. */ |
585 | 0 | if (IS_DTLS(ss) && (ss->ssl3.hs.ws == idle_handshake)) { |
586 | 0 | dtls_CheckTimer(ss); |
587 | 0 | } |
588 | 0 | ss->gs.readOffset = 0; |
589 | 0 | ss->gs.writeOffset = ss->gs.buf.len; |
590 | 0 | return 1; |
591 | 0 | } |
592 | | |
593 | | /* Repeatedly gather in a record and when complete, Handle that record. |
594 | | * Repeat this until some application data is received. |
595 | | * |
596 | | * Returns 1 when application data is available. |
597 | | * Returns 0 if ssl3_GatherData hits EOF. |
598 | | * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
599 | | * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
600 | | * |
601 | | * Called from DoRecv in sslsecur.c |
602 | | * Caller must hold the recv buf lock. |
603 | | */ |
604 | | int |
605 | | ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
606 | 0 | { |
607 | 0 | int rv; |
608 | 0 |
|
609 | 0 | /* ssl3_GatherCompleteHandshake requires both of these locks. */ |
610 | 0 | PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); |
611 | 0 | PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
612 | 0 |
|
613 | 0 | do { |
614 | 0 | rv = ssl3_GatherCompleteHandshake(ss, flags); |
615 | 0 | } while (rv > 0 && ss->gs.buf.len == 0); |
616 | 0 |
|
617 | 0 | return rv; |
618 | 0 | } |