|
1 /* |
|
2 * Gather (Read) entire SSL3 records from socket into buffer. |
|
3 * |
|
4 * This Source Code Form is subject to the terms of the Mozilla Public |
|
5 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
7 |
|
8 #include "cert.h" |
|
9 #include "ssl.h" |
|
10 #include "sslimpl.h" |
|
11 #include "ssl3prot.h" |
|
12 |
|
13 /* |
|
14 * Attempt to read in an entire SSL3 record. |
|
15 * Blocks here for blocking sockets, otherwise returns -1 with |
|
16 * PR_WOULD_BLOCK_ERROR when socket would block. |
|
17 * |
|
18 * returns 1 if received a complete SSL3 record. |
|
19 * returns 0 if recv returns EOF |
|
20 * returns -1 if recv returns < 0 |
|
21 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
|
22 * |
|
23 * Caller must hold the recv buf lock. |
|
24 * |
|
25 * The Gather state machine has 3 states: GS_INIT, GS_HEADER, GS_DATA. |
|
26 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in. |
|
27 * GS_DATA: waiting for the body of the SSL3 record to come in. |
|
28 * |
|
29 * This loop returns when either |
|
30 * (a) an error or EOF occurs, |
|
31 * (b) PR_WOULD_BLOCK_ERROR, |
|
32 * (c) data (entire SSL3 record) has been received. |
|
33 */ |
|
34 static int |
|
35 ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags) |
|
36 { |
|
37 unsigned char *bp; |
|
38 unsigned char *lbp; |
|
39 int nb; |
|
40 int err; |
|
41 int rv = 1; |
|
42 |
|
43 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
|
44 if (gs->state == GS_INIT) { |
|
45 gs->state = GS_HEADER; |
|
46 gs->remainder = 5; |
|
47 gs->offset = 0; |
|
48 gs->writeOffset = 0; |
|
49 gs->readOffset = 0; |
|
50 gs->inbuf.len = 0; |
|
51 } |
|
52 |
|
53 lbp = gs->inbuf.buf; |
|
54 for(;;) { |
|
55 SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)", |
|
56 SSL_GETPID(), ss->fd, gs->state, gs->remainder)); |
|
57 bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset; |
|
58 nb = ssl_DefRecv(ss, bp, gs->remainder, flags); |
|
59 |
|
60 if (nb > 0) { |
|
61 PRINT_BUF(60, (ss, "raw gather data:", bp, nb)); |
|
62 } else if (nb == 0) { |
|
63 /* EOF */ |
|
64 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
|
65 rv = 0; |
|
66 break; |
|
67 } else /* if (nb < 0) */ { |
|
68 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
|
69 PR_GetError())); |
|
70 rv = SECFailure; |
|
71 break; |
|
72 } |
|
73 |
|
74 PORT_Assert( nb <= gs->remainder ); |
|
75 if (nb > gs->remainder) { |
|
76 /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */ |
|
77 gs->state = GS_INIT; /* so we don't crash next time */ |
|
78 rv = SECFailure; |
|
79 break; |
|
80 } |
|
81 |
|
82 gs->offset += nb; |
|
83 gs->remainder -= nb; |
|
84 if (gs->state == GS_DATA) |
|
85 gs->inbuf.len += nb; |
|
86 |
|
87 /* if there's more to go, read some more. */ |
|
88 if (gs->remainder > 0) { |
|
89 continue; |
|
90 } |
|
91 |
|
92 /* have received entire record header, or entire record. */ |
|
93 switch (gs->state) { |
|
94 case GS_HEADER: |
|
95 /* |
|
96 ** Have received SSL3 record header in gs->hdr. |
|
97 ** Now extract the length of the following encrypted data, |
|
98 ** and then read in the rest of the SSL3 record into gs->inbuf. |
|
99 */ |
|
100 gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; |
|
101 |
|
102 /* This is the max fragment length for an encrypted fragment |
|
103 ** plus the size of the record header. |
|
104 */ |
|
105 if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) { |
|
106 SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
|
107 gs->state = GS_INIT; |
|
108 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
|
109 return SECFailure; |
|
110 } |
|
111 |
|
112 gs->state = GS_DATA; |
|
113 gs->offset = 0; |
|
114 gs->inbuf.len = 0; |
|
115 |
|
116 if (gs->remainder > gs->inbuf.space) { |
|
117 err = sslBuffer_Grow(&gs->inbuf, gs->remainder); |
|
118 if (err) { /* realloc has set error code to no mem. */ |
|
119 return err; |
|
120 } |
|
121 lbp = gs->inbuf.buf; |
|
122 } |
|
123 break; /* End this case. Continue around the loop. */ |
|
124 |
|
125 |
|
126 case GS_DATA: |
|
127 /* |
|
128 ** SSL3 record has been completely received. |
|
129 */ |
|
130 gs->state = GS_INIT; |
|
131 return 1; |
|
132 } |
|
133 } |
|
134 |
|
135 return rv; |
|
136 } |
|
137 |
|
138 /* |
|
139 * Read in an entire DTLS record. |
|
140 * |
|
141 * Blocks here for blocking sockets, otherwise returns -1 with |
|
142 * PR_WOULD_BLOCK_ERROR when socket would block. |
|
143 * |
|
144 * This is simpler than SSL because we are reading on a datagram socket |
|
145 * and datagrams must contain >=1 complete records. |
|
146 * |
|
147 * returns 1 if received a complete DTLS record. |
|
148 * returns 0 if recv returns EOF |
|
149 * returns -1 if recv returns < 0 |
|
150 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
|
151 * |
|
152 * Caller must hold the recv buf lock. |
|
153 * |
|
154 * This loop returns when either |
|
155 * (a) an error or EOF occurs, |
|
156 * (b) PR_WOULD_BLOCK_ERROR, |
|
157 * (c) data (entire DTLS record) has been received. |
|
158 */ |
|
159 static int |
|
160 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) |
|
161 { |
|
162 int nb; |
|
163 int err; |
|
164 int rv = 1; |
|
165 |
|
166 SSL_TRC(30, ("dtls_GatherData")); |
|
167 |
|
168 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
|
169 |
|
170 gs->state = GS_HEADER; |
|
171 gs->offset = 0; |
|
172 |
|
173 if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ |
|
174 gs->dtlsPacketOffset = 0; |
|
175 gs->dtlsPacket.len = 0; |
|
176 |
|
177 /* Resize to the maximum possible size so we can fit a full datagram */ |
|
178 /* This is the max fragment length for an encrypted fragment |
|
179 ** plus the size of the record header. |
|
180 ** This magic constant is copied from ssl3_GatherData, with 5 changed |
|
181 ** to 13 (the size of the record header). |
|
182 */ |
|
183 if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { |
|
184 err = sslBuffer_Grow(&gs->dtlsPacket, |
|
185 MAX_FRAGMENT_LENGTH + 2048 + 13); |
|
186 if (err) { /* realloc has set error code to no mem. */ |
|
187 return err; |
|
188 } |
|
189 } |
|
190 |
|
191 /* recv() needs to read a full datagram at a time */ |
|
192 nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); |
|
193 |
|
194 if (nb > 0) { |
|
195 PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); |
|
196 } else if (nb == 0) { |
|
197 /* EOF */ |
|
198 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
|
199 rv = 0; |
|
200 return rv; |
|
201 } else /* if (nb < 0) */ { |
|
202 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
|
203 PR_GetError())); |
|
204 rv = SECFailure; |
|
205 return rv; |
|
206 } |
|
207 |
|
208 gs->dtlsPacket.len = nb; |
|
209 } |
|
210 |
|
211 /* At this point we should have >=1 complete records lined up in |
|
212 * dtlsPacket. Read off the header. |
|
213 */ |
|
214 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { |
|
215 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " |
|
216 "too short to contain header", SSL_GETPID(), ss->fd)); |
|
217 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
|
218 gs->dtlsPacketOffset = 0; |
|
219 gs->dtlsPacket.len = 0; |
|
220 rv = SECFailure; |
|
221 return rv; |
|
222 } |
|
223 memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13); |
|
224 gs->dtlsPacketOffset += 13; |
|
225 |
|
226 /* Have received SSL3 record header in gs->hdr. */ |
|
227 gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; |
|
228 |
|
229 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { |
|
230 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " |
|
231 "to contain rest of body", SSL_GETPID(), ss->fd)); |
|
232 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
|
233 gs->dtlsPacketOffset = 0; |
|
234 gs->dtlsPacket.len = 0; |
|
235 rv = SECFailure; |
|
236 return rv; |
|
237 } |
|
238 |
|
239 /* OK, we have at least one complete packet, copy into inbuf */ |
|
240 if (gs->remainder > gs->inbuf.space) { |
|
241 err = sslBuffer_Grow(&gs->inbuf, gs->remainder); |
|
242 if (err) { /* realloc has set error code to no mem. */ |
|
243 return err; |
|
244 } |
|
245 } |
|
246 |
|
247 memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, |
|
248 gs->remainder); |
|
249 gs->inbuf.len = gs->remainder; |
|
250 gs->offset = gs->remainder; |
|
251 gs->dtlsPacketOffset += gs->remainder; |
|
252 gs->state = GS_INIT; |
|
253 |
|
254 return 1; |
|
255 } |
|
256 |
|
257 /* Gather in a record and when complete, Handle that record. |
|
258 * Repeat this until the handshake is complete, |
|
259 * or until application data is available. |
|
260 * |
|
261 * Returns 1 when the handshake is completed without error, or |
|
262 * application data is available. |
|
263 * Returns 0 if ssl3_GatherData hits EOF. |
|
264 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
|
265 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
|
266 * |
|
267 * Called from ssl_GatherRecord1stHandshake in sslcon.c, |
|
268 * and from SSL_ForceHandshake in sslsecur.c |
|
269 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). |
|
270 * |
|
271 * Caller must hold the recv buf lock. |
|
272 */ |
|
273 int |
|
274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) |
|
275 { |
|
276 SSL3Ciphertext cText; |
|
277 int rv; |
|
278 PRBool keepGoing = PR_TRUE; |
|
279 |
|
280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); |
|
281 |
|
282 /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, |
|
283 * which requires the 1stHandshakeLock, which must be acquired before the |
|
284 * RecvBufLock. |
|
285 */ |
|
286 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); |
|
287 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
|
288 |
|
289 do { |
|
290 PRBool handleRecordNow = PR_FALSE; |
|
291 |
|
292 ssl_GetSSL3HandshakeLock(ss); |
|
293 |
|
294 /* Without this, we may end up wrongly reporting |
|
295 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the |
|
296 * peer while we are waiting to be restarted. |
|
297 */ |
|
298 if (ss->ssl3.hs.restartTarget) { |
|
299 ssl_ReleaseSSL3HandshakeLock(ss); |
|
300 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
|
301 return (int) SECFailure; |
|
302 } |
|
303 |
|
304 /* Treat an empty msgState like a NULL msgState. (Most of the time |
|
305 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves |
|
306 * behind a non-NULL but zero-length msgState). |
|
307 * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record |
|
308 */ |
|
309 if (ss->ssl3.hs.msgState.buf) { |
|
310 if (ss->ssl3.hs.msgState.len == 0) { |
|
311 ss->ssl3.hs.msgState.buf = NULL; |
|
312 } else { |
|
313 handleRecordNow = PR_TRUE; |
|
314 } |
|
315 } |
|
316 |
|
317 ssl_ReleaseSSL3HandshakeLock(ss); |
|
318 |
|
319 if (handleRecordNow) { |
|
320 /* ssl3_HandleHandshake previously returned SECWouldBlock and the |
|
321 * as-yet-unprocessed plaintext of that previous handshake record. |
|
322 * We need to process it now before we overwrite it with the next |
|
323 * handshake record. |
|
324 */ |
|
325 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); |
|
326 } else { |
|
327 /* bring in the next sslv3 record. */ |
|
328 if (ss->recvdCloseNotify) { |
|
329 /* RFC 5246 Section 7.2.1: |
|
330 * Any data received after a closure alert is ignored. |
|
331 */ |
|
332 return 0; |
|
333 } |
|
334 if (!IS_DTLS(ss)) { |
|
335 rv = ssl3_GatherData(ss, &ss->gs, flags); |
|
336 } else { |
|
337 rv = dtls_GatherData(ss, &ss->gs, flags); |
|
338 |
|
339 /* If we got a would block error, that means that no data was |
|
340 * available, so we check the timer to see if it's time to |
|
341 * retransmit */ |
|
342 if (rv == SECFailure && |
|
343 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { |
|
344 ssl_GetSSL3HandshakeLock(ss); |
|
345 dtls_CheckTimer(ss); |
|
346 ssl_ReleaseSSL3HandshakeLock(ss); |
|
347 /* Restore the error in case something succeeded */ |
|
348 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
|
349 } |
|
350 } |
|
351 |
|
352 if (rv <= 0) { |
|
353 return rv; |
|
354 } |
|
355 |
|
356 /* decipher it, and handle it if it's a handshake. |
|
357 * If it's application data, ss->gs.buf will not be empty upon return. |
|
358 * If it's a change cipher spec, alert, or handshake message, |
|
359 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess. |
|
360 */ |
|
361 cText.type = (SSL3ContentType)ss->gs.hdr[0]; |
|
362 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; |
|
363 |
|
364 if (IS_DTLS(ss)) { |
|
365 int i; |
|
366 |
|
367 cText.version = dtls_DTLSVersionToTLSVersion(cText.version); |
|
368 /* DTLS sequence number */ |
|
369 cText.seq_num.high = 0; cText.seq_num.low = 0; |
|
370 for (i = 0; i < 4; i++) { |
|
371 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; |
|
372 cText.seq_num.high |= ss->gs.hdr[3 + i]; |
|
373 cText.seq_num.low |= ss->gs.hdr[7 + i]; |
|
374 } |
|
375 } |
|
376 |
|
377 cText.buf = &ss->gs.inbuf; |
|
378 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); |
|
379 } |
|
380 if (rv < 0) { |
|
381 return ss->recvdCloseNotify ? 0 : rv; |
|
382 } |
|
383 if (ss->gs.buf.len > 0) { |
|
384 /* We have application data to return to the application. This |
|
385 * prioritizes returning application data to the application over |
|
386 * completing any renegotiation handshake we may be doing. |
|
387 */ |
|
388 PORT_Assert(ss->firstHsDone); |
|
389 PORT_Assert(cText.type == content_application_data); |
|
390 break; |
|
391 } |
|
392 |
|
393 PORT_Assert(keepGoing); |
|
394 ssl_GetSSL3HandshakeLock(ss); |
|
395 if (ss->ssl3.hs.ws == idle_handshake) { |
|
396 /* We are done with the current handshake so stop trying to |
|
397 * handshake. Note that it would be safe to test ss->firstHsDone |
|
398 * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, |
|
399 * we prioritize completing a renegotiation handshake over sending |
|
400 * application data. |
|
401 */ |
|
402 PORT_Assert(ss->firstHsDone); |
|
403 PORT_Assert(!ss->ssl3.hs.canFalseStart); |
|
404 keepGoing = PR_FALSE; |
|
405 } else if (ss->ssl3.hs.canFalseStart) { |
|
406 /* Prioritize sending application data over trying to complete |
|
407 * the handshake if we're false starting. |
|
408 * |
|
409 * If we were to do this check at the beginning of the loop instead |
|
410 * of here, then this function would become be a no-op after |
|
411 * receiving the ServerHelloDone in the false start case, and we |
|
412 * would never complete the handshake. |
|
413 */ |
|
414 PORT_Assert(!ss->firstHsDone); |
|
415 |
|
416 if (ssl3_WaitingForStartOfServerSecondRound(ss)) { |
|
417 keepGoing = PR_FALSE; |
|
418 } else { |
|
419 ss->ssl3.hs.canFalseStart = PR_FALSE; |
|
420 } |
|
421 } |
|
422 ssl_ReleaseSSL3HandshakeLock(ss); |
|
423 } while (keepGoing); |
|
424 |
|
425 ss->gs.readOffset = 0; |
|
426 ss->gs.writeOffset = ss->gs.buf.len; |
|
427 return 1; |
|
428 } |
|
429 |
|
430 /* Repeatedly gather in a record and when complete, Handle that record. |
|
431 * Repeat this until some application data is received. |
|
432 * |
|
433 * Returns 1 when application data is available. |
|
434 * Returns 0 if ssl3_GatherData hits EOF. |
|
435 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
|
436 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
|
437 * |
|
438 * Called from DoRecv in sslsecur.c |
|
439 * Caller must hold the recv buf lock. |
|
440 */ |
|
441 int |
|
442 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
|
443 { |
|
444 int rv; |
|
445 |
|
446 /* ssl3_GatherCompleteHandshake requires both of these locks. */ |
|
447 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); |
|
448 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
|
449 |
|
450 do { |
|
451 rv = ssl3_GatherCompleteHandshake(ss, flags); |
|
452 } while (rv > 0 && ss->gs.buf.len == 0); |
|
453 |
|
454 return rv; |
|
455 } |