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 |