OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Gather (Read) entire SSL3 records from socket into buffer. | 2 * Gather (Read) entire SSL3 records from socket into buffer. |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 #include "cert.h" | 8 #include "cert.h" |
9 #include "ssl.h" | 9 #include "ssl.h" |
10 #include "sslimpl.h" | 10 #include "sslimpl.h" |
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 * and from SSL_ForceHandshake in sslsecur.c | 268 * and from SSL_ForceHandshake in sslsecur.c |
269 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). | 269 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). |
270 * | 270 * |
271 * Caller must hold the recv buf lock. | 271 * Caller must hold the recv buf lock. |
272 */ | 272 */ |
273 int | 273 int |
274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) | 274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) |
275 { | 275 { |
276 SSL3Ciphertext cText; | 276 SSL3Ciphertext cText; |
277 int rv; | 277 int rv; |
278 PRBool canFalseStart = PR_FALSE; | 278 PRBool keepGoing = PR_TRUE; |
279 | 279 |
280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | 280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); |
281 | 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) ); | |
282 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 287 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
288 | |
283 do { | 289 do { |
284 PRBool handleRecordNow = PR_FALSE; | 290 PRBool handleRecordNow = PR_FALSE; |
285 | 291 |
286 ssl_GetSSL3HandshakeLock(ss); | 292 ssl_GetSSL3HandshakeLock(ss); |
287 | 293 |
288 /* Without this, we may end up wrongly reporting | 294 /* Without this, we may end up wrongly reporting |
289 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the | 295 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the |
290 * peer while we are waiting to be restarted. | 296 * peer while we are waiting to be restarted. |
291 */ | 297 */ |
292 if (ss->ssl3.hs.restartTarget) { | 298 if (ss->ssl3.hs.restartTarget) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
357 cText.seq_num.high = 0; cText.seq_num.low = 0; | 363 cText.seq_num.high = 0; cText.seq_num.low = 0; |
358 for (i = 0; i < 4; i++) { | 364 for (i = 0; i < 4; i++) { |
359 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; | 365 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; |
360 cText.seq_num.high |= ss->gs.hdr[3 + i]; | 366 cText.seq_num.high |= ss->gs.hdr[3 + i]; |
361 cText.seq_num.low |= ss->gs.hdr[7 + i]; | 367 cText.seq_num.low |= ss->gs.hdr[7 + i]; |
362 } | 368 } |
363 } | 369 } |
364 | 370 |
365 cText.buf = &ss->gs.inbuf; | 371 cText.buf = &ss->gs.inbuf; |
366 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | 372 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); |
373 | |
374 if (rv == (int) SECSuccess && ss->gs.buf.len > 0) { | |
375 /* We have application data to return to the application. This | |
376 * prioritizes returning application data to the application ove r | |
377 * completing any renegotiation handshake we may be doing. | |
378 */ | |
379 PORT_Assert(ss->firstHsDone); | |
380 PORT_Assert(cText.type == content_application_data); | |
381 break; | |
382 } | |
wtc
2013/11/26 02:45:17
Brian: to match the original code better, it seems
| |
367 } | 383 } |
368 if (rv < 0) { | 384 if (rv < 0) { |
369 return ss->recvdCloseNotify ? 0 : rv; | 385 return ss->recvdCloseNotify ? 0 : rv; |
370 } | 386 } |
371 | 387 |
372 » /* If we kicked off a false start in ssl3_HandleServerHelloDone, break | 388 » PORT_Assert(keepGoing); |
373 » * out of this loop early without finishing the handshake. | 389 » ssl_GetSSL3HandshakeLock(ss); |
374 » */ | 390 » if (ss->ssl3.hs.ws == idle_handshake) { |
375 » if (ss->opt.enableFalseStart) { | 391 » /* We are done with the current handshake so stop trying to |
376 » ssl_GetSSL3HandshakeLock(ss); | 392 » * handshake. Note that it would be safe to test ss->firstHsDone |
377 » canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher || | 393 » * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, |
378 » » » ss->ssl3.hs.ws == wait_new_session_ticket) && | 394 » * we prioritize completing a renegotiation handshake over sending |
379 » » ssl3_CanFalseStart(ss); | 395 » * application data. |
380 » ssl_ReleaseSSL3HandshakeLock(ss); | 396 » */ |
397 » PORT_Assert(ss->firstHsDone); | |
398 » PORT_Assert(!ss->ssl3.hs.canFalseStart); | |
399 » keepGoing = PR_FALSE; | |
400 » } else if (ss->ssl3.hs.canFalseStart) { | |
401 » /* Prioritize sending application data over trying to complete | |
402 » * the handshake if we're false starting. | |
403 » * | |
404 » * If we were to do this check at the beginning of the loop instead | |
405 » * of here, then this function would become be a no-op after | |
406 » * receiving the ServerHelloDone in the false start case, and we | |
407 » * would never complete the handshake. | |
408 » */ | |
409 » PORT_Assert(!ss->firstHsDone); | |
410 | |
411 » if (ssl3_WaitingForStartOfServerSecondRound(ss)) { | |
412 » » keepGoing = PR_FALSE; | |
413 » } else { | |
414 » » ss->ssl3.hs.canFalseStart = PR_FALSE; | |
415 » } | |
381 } | 416 } |
382 } while (ss->ssl3.hs.ws != idle_handshake && | 417 » ssl_ReleaseSSL3HandshakeLock(ss); |
383 !canFalseStart && | 418 } while (keepGoing); |
384 ss->gs.buf.len == 0); | |
385 | 419 |
386 ss->gs.readOffset = 0; | 420 ss->gs.readOffset = 0; |
387 ss->gs.writeOffset = ss->gs.buf.len; | 421 ss->gs.writeOffset = ss->gs.buf.len; |
388 return 1; | 422 return 1; |
389 } | 423 } |
390 | 424 |
391 /* Repeatedly gather in a record and when complete, Handle that record. | 425 /* Repeatedly gather in a record and when complete, Handle that record. |
392 * Repeat this until some application data is received. | 426 * Repeat this until some application data is received. |
393 * | 427 * |
394 * Returns 1 when application data is available. | 428 * Returns 1 when application data is available. |
395 * Returns 0 if ssl3_GatherData hits EOF. | 429 * Returns 0 if ssl3_GatherData hits EOF. |
396 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | 430 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
397 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | 431 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
398 * | 432 * |
399 * Called from DoRecv in sslsecur.c | 433 * Called from DoRecv in sslsecur.c |
400 * Caller must hold the recv buf lock. | 434 * Caller must hold the recv buf lock. |
401 */ | 435 */ |
402 int | 436 int |
403 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) | 437 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
404 { | 438 { |
405 int rv; | 439 int rv; |
406 | 440 |
441 /* ssl3_GatherCompleteHandshake requires both of these locks. */ | |
442 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
407 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 443 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
444 | |
408 do { | 445 do { |
409 rv = ssl3_GatherCompleteHandshake(ss, flags); | 446 rv = ssl3_GatherCompleteHandshake(ss, flags); |
410 } while (rv > 0 && ss->gs.buf.len == 0); | 447 } while (rv > 0 && ss->gs.buf.len == 0); |
411 | 448 |
412 return rv; | 449 return rv; |
413 } | 450 } |
OLD | NEW |