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