Chromium Code Reviews| 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; | |
| 279 | 278 |
| 280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | 279 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); |
| 281 | 280 |
| 282 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 281 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 282 | |
| 283 ssl_GetSSL3HandshakeLock(ss); | |
| 284 | |
| 283 do { | 285 do { |
| 284 PRBool handleRecordNow = PR_FALSE; | 286 PRBool handleRecordNow = PR_FALSE; |
| 285 | 287 |
| 286 ssl_GetSSL3HandshakeLock(ss); | |
| 287 | |
| 288 /* Without this, we may end up wrongly reporting | 288 /* Without this, we may end up wrongly reporting |
| 289 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the | 289 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the |
| 290 * peer while we are waiting to be restarted. | 290 * peer while we are waiting to be restarted. |
| 291 */ | 291 */ |
| 292 if (ss->ssl3.hs.restartTarget) { | 292 if (ss->ssl3.hs.restartTarget) { |
| 293 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 294 PORT_SetError(PR_WOULD_BLOCK_ERROR); | 293 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
| 295 » return (int) SECFailure; | 294 » rv = (int) SECFailure; |
| 295 » goto done; | |
| 296 } | 296 } |
| 297 | 297 |
| 298 /* Treat an empty msgState like a NULL msgState. (Most of the time | 298 /* Treat an empty msgState like a NULL msgState. (Most of the time |
| 299 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves | 299 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves |
| 300 * behind a non-NULL but zero-length msgState). | 300 * behind a non-NULL but zero-length msgState). |
| 301 * Test: async_cert_restart_server_sends_hello_request_first_in_separate _record | 301 * Test: async_cert_restart_server_sends_hello_request_first_in_separate _record |
| 302 */ | 302 */ |
| 303 if (ss->ssl3.hs.msgState.buf) { | 303 if (ss->ssl3.hs.msgState.buf) { |
| 304 if (ss->ssl3.hs.msgState.len == 0) { | 304 if (ss->ssl3.hs.msgState.len == 0) { |
| 305 ss->ssl3.hs.msgState.buf = NULL; | 305 ss->ssl3.hs.msgState.buf = NULL; |
| 306 } else { | 306 } else { |
| 307 handleRecordNow = PR_TRUE; | 307 handleRecordNow = PR_TRUE; |
| 308 } | 308 } |
| 309 } | 309 } |
| 310 | 310 |
| 311 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 312 | |
| 313 if (handleRecordNow) { | 311 if (handleRecordNow) { |
| 314 /* ssl3_HandleHandshake previously returned SECWouldBlock and the | 312 /* ssl3_HandleHandshake previously returned SECWouldBlock and the |
| 315 * as-yet-unprocessed plaintext of that previous handshake record. | 313 * as-yet-unprocessed plaintext of that previous handshake record. |
| 316 * We need to process it now before we overwrite it with the next | 314 * We need to process it now before we overwrite it with the next |
| 317 * handshake record. | 315 * handshake record. |
| 318 */ | 316 */ |
| 319 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); | 317 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); |
| 320 } else { | 318 } else { |
| 321 /* bring in the next sslv3 record. */ | 319 /* bring in the next sslv3 record. */ |
| 322 if (!IS_DTLS(ss)) { | 320 if (!IS_DTLS(ss)) { |
| 323 rv = ssl3_GatherData(ss, &ss->gs, flags); | 321 rv = ssl3_GatherData(ss, &ss->gs, flags); |
| 324 } else { | 322 } else { |
| 325 rv = dtls_GatherData(ss, &ss->gs, flags); | 323 rv = dtls_GatherData(ss, &ss->gs, flags); |
|
wtc
2013/10/17 15:28:14
I agree we should be holding the SSL3HandshakeLock
| |
| 326 | 324 |
| 327 /* If we got a would block error, that means that no data was | 325 /* If we got a would block error, that means that no data was |
| 328 * available, so we check the timer to see if it's time to | 326 * available, so we check the timer to see if it's time to |
| 329 * retransmit */ | 327 * retransmit */ |
| 330 if (rv == SECFailure && | 328 if (rv == SECFailure && |
| 331 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { | 329 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { |
| 332 ssl_GetSSL3HandshakeLock(ss); | |
| 333 dtls_CheckTimer(ss); | 330 dtls_CheckTimer(ss); |
| 334 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 335 /* Restore the error in case something succeeded */ | 331 /* Restore the error in case something succeeded */ |
| 336 PORT_SetError(PR_WOULD_BLOCK_ERROR); | 332 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
| 337 } | 333 } |
| 338 } | 334 } |
| 339 | 335 |
| 336 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
|
wtc
2013/10/17 00:10:53
Is this assertion necessary? We already checked th
briansmith
2013/10/17 01:42:40
Done.
| |
| 337 | |
| 340 if (rv <= 0) { | 338 if (rv <= 0) { |
| 341 » » return rv; | 339 » » goto done; |
| 342 } | 340 } |
| 343 | 341 |
| 344 /* decipher it, and handle it if it's a handshake. | 342 /* decipher it, and handle it if it's a handshake. |
| 345 * If it's application data, ss->gs.buf will not be empty upon retur n. | 343 * If it's application data, ss->gs.buf will not be empty upon retur n. |
| 346 * If it's a change cipher spec, alert, or handshake message, | 344 * If it's a change cipher spec, alert, or handshake message, |
| 347 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSucces s. | 345 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSucces s. |
| 348 */ | 346 */ |
| 349 cText.type = (SSL3ContentType)ss->gs.hdr[0]; | 347 cText.type = (SSL3ContentType)ss->gs.hdr[0]; |
| 350 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; | 348 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; |
| 351 | 349 |
| 352 if (IS_DTLS(ss)) { | 350 if (IS_DTLS(ss)) { |
| 353 int i; | 351 int i; |
| 354 | 352 |
| 355 cText.version = dtls_DTLSVersionToTLSVersion(cText.version); | 353 cText.version = dtls_DTLSVersionToTLSVersion(cText.version); |
| 356 /* DTLS sequence number */ | 354 /* DTLS sequence number */ |
| 357 cText.seq_num.high = 0; cText.seq_num.low = 0; | 355 cText.seq_num.high = 0; cText.seq_num.low = 0; |
| 358 for (i = 0; i < 4; i++) { | 356 for (i = 0; i < 4; i++) { |
| 359 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; | 357 cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; |
| 360 cText.seq_num.high |= ss->gs.hdr[3 + i]; | 358 cText.seq_num.high |= ss->gs.hdr[3 + i]; |
| 361 cText.seq_num.low |= ss->gs.hdr[7 + i]; | 359 cText.seq_num.low |= ss->gs.hdr[7 + i]; |
| 362 } | 360 } |
| 363 } | 361 } |
| 364 | 362 |
| 365 cText.buf = &ss->gs.inbuf; | 363 cText.buf = &ss->gs.inbuf; |
| 366 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | 364 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); |
| 365 | |
| 366 PORT_Assert(rv < 0 || ss->gs.buf.len == 0 || | |
| 367 cText.type == content_application_data); | |
|
wtc
2013/10/17 00:10:53
Can you explain this assertion with a comment?
briansmith
2013/10/17 01:42:40
Done.
briansmith
2013/10/25 19:17:14
Making this clearer, and fixing the locking accord
| |
| 367 } | 368 } |
| 368 if (rv < 0) { | 369 if (rv < 0) { |
| 369 » return ss->recvdCloseNotify ? 0 : rv; | 370 » rv = ss->recvdCloseNotify ? 0 : rv; |
| 370 » } | 371 » goto done; |
| 371 | |
| 372 » /* If we kicked off a false start in ssl3_HandleServerHelloDone, break | |
| 373 » * out of this loop early without finishing the handshake. | |
| 374 » */ | |
| 375 » if (ss->opt.enableFalseStart) { | |
| 376 » ssl_GetSSL3HandshakeLock(ss); | |
| 377 » canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher || | |
| 378 » » » ss->ssl3.hs.ws == wait_new_session_ticket) && | |
|
wtc
2013/10/17 00:10:53
Note that ss->ssl3.hs.ws == wait_finished is not p
briansmith
2013/10/17 01:44:46
The false start code, before this patch, was incon
briansmith
2013/10/24 20:57:04
I found a reason why we should probably care about
| |
| 379 » » ssl3_CanFalseStart(ss); | |
| 380 » ssl_ReleaseSSL3HandshakeLock(ss); | |
| 381 } | 372 } |
| 382 } while (ss->ssl3.hs.ws != idle_handshake && | 373 } while (ss->ssl3.hs.ws != idle_handshake && |
| 383 !canFalseStart && | 374 !ss->ssl3.hs.canFalseStart && |
| 384 ss->gs.buf.len == 0); | 375 ss->gs.buf.len == 0); |
| 385 | 376 |
| 386 ss->gs.readOffset = 0; | 377 ss->gs.readOffset = 0; |
| 387 ss->gs.writeOffset = ss->gs.buf.len; | 378 ss->gs.writeOffset = ss->gs.buf.len; |
| 388 return 1; | 379 rv = 1; |
| 380 | |
| 381 done: | |
| 382 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 383 return rv; | |
| 389 } | 384 } |
| 390 | 385 |
| 391 /* Repeatedly gather in a record and when complete, Handle that record. | 386 /* Repeatedly gather in a record and when complete, Handle that record. |
| 392 * Repeat this until some application data is received. | 387 * Repeat this until some application data is received. |
| 393 * | 388 * |
| 394 * Returns 1 when application data is available. | 389 * Returns 1 when application data is available. |
| 395 * Returns 0 if ssl3_GatherData hits EOF. | 390 * Returns 0 if ssl3_GatherData hits EOF. |
| 396 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | 391 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
| 397 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | 392 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
| 398 * | 393 * |
| 399 * Called from DoRecv in sslsecur.c | 394 * Called from DoRecv in sslsecur.c |
| 400 * Caller must hold the recv buf lock. | 395 * Caller must hold the recv buf lock. |
| 401 */ | 396 */ |
| 402 int | 397 int |
| 403 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) | 398 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
| 404 { | 399 { |
| 405 int rv; | 400 int rv; |
| 406 | 401 |
| 407 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 402 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); |
| 403 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 404 | |
| 408 do { | 405 do { |
| 409 rv = ssl3_GatherCompleteHandshake(ss, flags); | 406 rv = ssl3_GatherCompleteHandshake(ss, flags); |
| 410 } while (rv > 0 && ss->gs.buf.len == 0); | 407 } while (rv > 0 && ss->gs.buf.len == 0); |
| 411 | 408 |
| 412 return rv; | 409 return rv; |
| 413 } | 410 } |
| OLD | NEW |