OLD | NEW |
| (Empty) |
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((unsigned int)nb <= gs->remainder); | |
75 if ((unsigned int)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 case GS_DATA: | |
126 /* | |
127 ** SSL3 record has been completely received. | |
128 */ | |
129 gs->state = GS_INIT; | |
130 return 1; | |
131 } | |
132 } | |
133 | |
134 return rv; | |
135 } | |
136 | |
137 /* | |
138 * Read in an entire DTLS record. | |
139 * | |
140 * Blocks here for blocking sockets, otherwise returns -1 with | |
141 * PR_WOULD_BLOCK_ERROR when socket would block. | |
142 * | |
143 * This is simpler than SSL because we are reading on a datagram socket | |
144 * and datagrams must contain >=1 complete records. | |
145 * | |
146 * returns 1 if received a complete DTLS record. | |
147 * returns 0 if recv returns EOF | |
148 * returns -1 if recv returns < 0 | |
149 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) | |
150 * | |
151 * Caller must hold the recv buf lock. | |
152 * | |
153 * This loop returns when either | |
154 * (a) an error or EOF occurs, | |
155 * (b) PR_WOULD_BLOCK_ERROR, | |
156 * (c) data (entire DTLS record) has been received. | |
157 */ | |
158 static int | |
159 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) | |
160 { | |
161 int nb; | |
162 int err; | |
163 int rv = 1; | |
164 | |
165 SSL_TRC(30, ("dtls_GatherData")); | |
166 | |
167 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
168 | |
169 gs->state = GS_HEADER; | |
170 gs->offset = 0; | |
171 | |
172 if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ | |
173 gs->dtlsPacketOffset = 0; | |
174 gs->dtlsPacket.len = 0; | |
175 | |
176 /* Resize to the maximum possible size so we can fit a full datagram */ | |
177 /* This is the max fragment length for an encrypted fragment | |
178 ** plus the size of the record header. | |
179 ** This magic constant is copied from ssl3_GatherData, with 5 changed | |
180 ** to 13 (the size of the record header). | |
181 */ | |
182 if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { | |
183 err = sslBuffer_Grow(&gs->dtlsPacket, | |
184 MAX_FRAGMENT_LENGTH + 2048 + 13); | |
185 if (err) { /* realloc has set error code to no mem. */ | |
186 return err; | |
187 } | |
188 } | |
189 | |
190 /* recv() needs to read a full datagram at a time */ | |
191 nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); | |
192 | |
193 if (nb > 0) { | |
194 PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); | |
195 } else if (nb == 0) { | |
196 /* EOF */ | |
197 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); | |
198 rv = 0; | |
199 return rv; | |
200 } else /* if (nb < 0) */ { | |
201 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, | |
202 PR_GetError())); | |
203 rv = SECFailure; | |
204 return rv; | |
205 } | |
206 | |
207 gs->dtlsPacket.len = nb; | |
208 } | |
209 | |
210 /* At this point we should have >=1 complete records lined up in | |
211 * dtlsPacket. Read off the header. | |
212 */ | |
213 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { | |
214 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " | |
215 "too short to contain header", | |
216 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", | |
232 SSL_GETPID(), ss->fd)); | |
233 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | |
234 gs->dtlsPacketOffset = 0; | |
235 gs->dtlsPacket.len = 0; | |
236 rv = SECFailure; | |
237 return rv; | |
238 } | |
239 | |
240 /* OK, we have at least one complete packet, copy into inbuf */ | |
241 if (gs->remainder > gs->inbuf.space) { | |
242 err = sslBuffer_Grow(&gs->inbuf, gs->remainder); | |
243 if (err) { /* realloc has set error code to no mem. */ | |
244 return err; | |
245 } | |
246 } | |
247 | |
248 memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, | |
249 gs->remainder); | |
250 gs->inbuf.len = gs->remainder; | |
251 gs->offset = gs->remainder; | |
252 gs->dtlsPacketOffset += gs->remainder; | |
253 gs->state = GS_INIT; | |
254 | |
255 return 1; | |
256 } | |
257 | |
258 /* Gather in a record and when complete, Handle that record. | |
259 * Repeat this until the handshake is complete, | |
260 * or until application data is available. | |
261 * | |
262 * Returns 1 when the handshake is completed without error, or | |
263 * application data is available. | |
264 * Returns 0 if ssl3_GatherData hits EOF. | |
265 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | |
266 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | |
267 * | |
268 * Called from ssl_GatherRecord1stHandshake in sslcon.c, | |
269 * and from SSL_ForceHandshake in sslsecur.c | |
270 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). | |
271 * | |
272 * Caller must hold the recv buf lock. | |
273 */ | |
274 int | |
275 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) | |
276 { | |
277 SSL3Ciphertext cText; | |
278 int rv; | |
279 PRBool keepGoing = PR_TRUE; | |
280 | |
281 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | |
282 | |
283 /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, | |
284 * which requires the 1stHandshakeLock, which must be acquired before the | |
285 * RecvBufLock. | |
286 */ | |
287 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); | |
288 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
289 | |
290 do { | |
291 PRBool handleRecordNow = PR_FALSE; | |
292 | |
293 ssl_GetSSL3HandshakeLock(ss); | |
294 | |
295 /* Without this, we may end up wrongly reporting | |
296 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the | |
297 * peer while we are waiting to be restarted. | |
298 */ | |
299 if (ss->ssl3.hs.restartTarget) { | |
300 ssl_ReleaseSSL3HandshakeLock(ss); | |
301 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
302 return (int)SECFailure; | |
303 } | |
304 | |
305 /* Treat an empty msgState like a NULL msgState. (Most of the time | |
306 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves | |
307 * behind a non-NULL but zero-length msgState). | |
308 * Test: async_cert_restart_server_sends_hello_request_first_in_separate
_record | |
309 */ | |
310 if (ss->ssl3.hs.msgState.buf) { | |
311 if (ss->ssl3.hs.msgState.len == 0) { | |
312 ss->ssl3.hs.msgState.buf = NULL; | |
313 } else { | |
314 handleRecordNow = PR_TRUE; | |
315 } | |
316 } | |
317 | |
318 ssl_ReleaseSSL3HandshakeLock(ss); | |
319 | |
320 if (handleRecordNow) { | |
321 /* ssl3_HandleHandshake previously returned SECWouldBlock and the | |
322 * as-yet-unprocessed plaintext of that previous handshake record. | |
323 * We need to process it now before we overwrite it with the next | |
324 * handshake record. | |
325 */ | |
326 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); | |
327 } else { | |
328 /* bring in the next sslv3 record. */ | |
329 if (ss->recvdCloseNotify) { | |
330 /* RFC 5246 Section 7.2.1: | |
331 * Any data received after a closure alert is ignored. | |
332 */ | |
333 return 0; | |
334 } | |
335 if (!IS_DTLS(ss)) { | |
336 rv = ssl3_GatherData(ss, &ss->gs, flags); | |
337 } else { | |
338 rv = dtls_GatherData(ss, &ss->gs, flags); | |
339 | |
340 /* If we got a would block error, that means that no data was | |
341 * available, so we check the timer to see if it's time to | |
342 * retransmit */ | |
343 if (rv == SECFailure && | |
344 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { | |
345 ssl_GetSSL3HandshakeLock(ss); | |
346 dtls_CheckTimer(ss); | |
347 ssl_ReleaseSSL3HandshakeLock(ss); | |
348 /* Restore the error in case something succeeded */ | |
349 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
350 } | |
351 } | |
352 | |
353 if (rv <= 0) { | |
354 return rv; | |
355 } | |
356 | |
357 /* decipher it, and handle it if it's a handshake. | |
358 * If it's application data, ss->gs.buf will not be empty upon retur
n. | |
359 * If it's a change cipher spec, alert, or handshake message, | |
360 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSucces
s. | |
361 */ | |
362 cText.type = (SSL3ContentType)ss->gs.hdr[0]; | |
363 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; | |
364 | |
365 if (IS_DTLS(ss)) { | |
366 int i; | |
367 | |
368 cText.version = dtls_DTLSVersionToTLSVersion(cText.version); | |
369 /* DTLS sequence number */ | |
370 cText.seq_num.high = 0; | |
371 cText.seq_num.low = 0; | |
372 for (i = 0; i < 4; i++) { | |
373 cText.seq_num.high <<= 8; | |
374 cText.seq_num.low <<= 8; | |
375 cText.seq_num.high |= ss->gs.hdr[3 + i]; | |
376 cText.seq_num.low |= ss->gs.hdr[7 + i]; | |
377 } | |
378 } | |
379 | |
380 cText.buf = &ss->gs.inbuf; | |
381 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | |
382 } | |
383 if (rv < 0) { | |
384 return ss->recvdCloseNotify ? 0 : rv; | |
385 } | |
386 if (ss->gs.buf.len > 0) { | |
387 /* We have application data to return to the application. This | |
388 * prioritizes returning application data to the application over | |
389 * completing any renegotiation handshake we may be doing. | |
390 */ | |
391 PORT_Assert(ss->firstHsDone); | |
392 PORT_Assert(cText.type == content_application_data); | |
393 break; | |
394 } | |
395 | |
396 PORT_Assert(keepGoing); | |
397 ssl_GetSSL3HandshakeLock(ss); | |
398 if (ss->ssl3.hs.ws == idle_handshake) { | |
399 /* We are done with the current handshake so stop trying to | |
400 * handshake. Note that it would be safe to test ss->firstHsDone | |
401 * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, | |
402 * we prioritize completing a renegotiation handshake over sending | |
403 * application data. | |
404 */ | |
405 PORT_Assert(ss->firstHsDone); | |
406 PORT_Assert(!ss->ssl3.hs.canFalseStart); | |
407 keepGoing = PR_FALSE; | |
408 } else if (ss->ssl3.hs.canFalseStart) { | |
409 /* Prioritize sending application data over trying to complete | |
410 * the handshake if we're false starting. | |
411 * | |
412 * If we were to do this check at the beginning of the loop instead | |
413 * of here, then this function would become be a no-op after | |
414 * receiving the ServerHelloDone in the false start case, and we | |
415 * would never complete the handshake. | |
416 */ | |
417 PORT_Assert(!ss->firstHsDone); | |
418 | |
419 if (ssl3_WaitingForServerSecondRound(ss)) { | |
420 keepGoing = PR_FALSE; | |
421 } else { | |
422 ss->ssl3.hs.canFalseStart = PR_FALSE; | |
423 } | |
424 } | |
425 ssl_ReleaseSSL3HandshakeLock(ss); | |
426 } while (keepGoing); | |
427 | |
428 ss->gs.readOffset = 0; | |
429 ss->gs.writeOffset = ss->gs.buf.len; | |
430 return 1; | |
431 } | |
432 | |
433 /* Repeatedly gather in a record and when complete, Handle that record. | |
434 * Repeat this until some application data is received. | |
435 * | |
436 * Returns 1 when application data is available. | |
437 * Returns 0 if ssl3_GatherData hits EOF. | |
438 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | |
439 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | |
440 * | |
441 * Called from DoRecv in sslsecur.c | |
442 * Caller must hold the recv buf lock. | |
443 */ | |
444 int | |
445 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) | |
446 { | |
447 int rv; | |
448 | |
449 /* ssl3_GatherCompleteHandshake requires both of these locks. */ | |
450 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); | |
451 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
452 | |
453 do { | |
454 rv = ssl3_GatherCompleteHandshake(ss, flags); | |
455 } while (rv > 0 && ss->gs.buf.len == 0); | |
456 | |
457 return rv; | |
458 } | |
OLD | NEW |