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) ); |
283 do { | 288 |
| 289 for (;;) { |
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) { |
293 ssl_ReleaseSSL3HandshakeLock(ss); | 299 ssl_ReleaseSSL3HandshakeLock(ss); |
(...skipping 63 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 } |
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 SSL_ForceHandshake would become be a no-op after |
| 406 » * receiving the ServerHelloDone. By doing this check here, we |
| 407 » * ensure that SSL_ForceHandshake always tries to make a little |
| 408 » * progress. |
| 409 » */ |
| 410 » PORT_Assert(!ss->firstHsDone); |
| 411 |
| 412 » if (ssl3_WaitingForStartOfServerSecondRound(ss)) { |
| 413 » » keepGoing = PR_FALSE; |
| 414 » } else { |
| 415 » » ss->ssl3.hs.canFalseStart = PR_FALSE; |
| 416 » } |
381 } | 417 } |
382 } while (ss->ssl3.hs.ws != idle_handshake && | 418 » ssl_ReleaseSSL3HandshakeLock(ss); |
383 !canFalseStart && | 419 » if (!keepGoing) { |
384 ss->gs.buf.len == 0); | 420 » break; |
| 421 » } |
| 422 } |
385 | 423 |
386 ss->gs.readOffset = 0; | 424 ss->gs.readOffset = 0; |
387 ss->gs.writeOffset = ss->gs.buf.len; | 425 ss->gs.writeOffset = ss->gs.buf.len; |
388 return 1; | 426 return 1; |
389 } | 427 } |
390 | 428 |
391 /* Repeatedly gather in a record and when complete, Handle that record. | 429 /* Repeatedly gather in a record and when complete, Handle that record. |
392 * Repeat this until some application data is received. | 430 * Repeat this until some application data is received. |
393 * | 431 * |
394 * Returns 1 when application data is available. | 432 * Returns 1 when application data is available. |
395 * Returns 0 if ssl3_GatherData hits EOF. | 433 * Returns 0 if ssl3_GatherData hits EOF. |
396 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | 434 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
397 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | 435 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
398 * | 436 * |
399 * Called from DoRecv in sslsecur.c | 437 * Called from DoRecv in sslsecur.c |
400 * Caller must hold the recv buf lock. | 438 * Caller must hold the recv buf lock. |
401 */ | 439 */ |
402 int | 440 int |
403 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) | 441 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
404 { | 442 { |
405 int rv; | 443 int rv; |
406 | 444 |
| 445 /* ssl3_GatherCompleteHandshake requires both of these locks. */ |
| 446 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); |
407 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 447 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 448 |
408 do { | 449 do { |
409 rv = ssl3_GatherCompleteHandshake(ss, flags); | 450 rv = ssl3_GatherCompleteHandshake(ss, flags); |
410 } while (rv > 0 && ss->gs.buf.len == 0); | 451 } while (rv > 0 && ss->gs.buf.len == 0); |
411 | 452 |
412 return rv; | 453 return rv; |
413 } | 454 } |
OLD | NEW |