security/nss/lib/ssl/ssl3gthr.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/ssl/ssl3gthr.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,455 @@
     1.4 +/*
     1.5 + * Gather (Read) entire SSL3 records from socket into buffer.  
     1.6 + *
     1.7 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#include "cert.h"
    1.12 +#include "ssl.h"
    1.13 +#include "sslimpl.h"
    1.14 +#include "ssl3prot.h"
    1.15 +
    1.16 +/* 
    1.17 + * Attempt to read in an entire SSL3 record.
    1.18 + * Blocks here for blocking sockets, otherwise returns -1 with 
    1.19 + * 	PR_WOULD_BLOCK_ERROR when socket would block.
    1.20 + *
    1.21 + * returns  1 if received a complete SSL3 record.
    1.22 + * returns  0 if recv returns EOF
    1.23 + * returns -1 if recv returns < 0  
    1.24 + *	(The error value may have already been set to PR_WOULD_BLOCK_ERROR)
    1.25 + *
    1.26 + * Caller must hold the recv buf lock.
    1.27 + *
    1.28 + * The Gather state machine has 3 states:  GS_INIT, GS_HEADER, GS_DATA.
    1.29 + * GS_HEADER: waiting for the 5-byte SSL3 record header to come in.
    1.30 + * GS_DATA:   waiting for the body of the SSL3 record   to come in.
    1.31 + *
    1.32 + * This loop returns when either
    1.33 + *      (a) an error or EOF occurs,
    1.34 + *	(b) PR_WOULD_BLOCK_ERROR,
    1.35 + * 	(c) data (entire SSL3 record) has been received.
    1.36 + */
    1.37 +static int
    1.38 +ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
    1.39 +{
    1.40 +    unsigned char *bp;
    1.41 +    unsigned char *lbp;
    1.42 +    int            nb;
    1.43 +    int            err;
    1.44 +    int            rv		= 1;
    1.45 +
    1.46 +    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
    1.47 +    if (gs->state == GS_INIT) {
    1.48 +	gs->state       = GS_HEADER;
    1.49 +	gs->remainder   = 5;
    1.50 +	gs->offset      = 0;
    1.51 +	gs->writeOffset = 0;
    1.52 +	gs->readOffset  = 0;
    1.53 +	gs->inbuf.len   = 0;
    1.54 +    }
    1.55 +    
    1.56 +    lbp = gs->inbuf.buf;
    1.57 +    for(;;) {
    1.58 +	SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
    1.59 +		SSL_GETPID(), ss->fd, gs->state, gs->remainder));
    1.60 +	bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
    1.61 +	nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
    1.62 +
    1.63 +	if (nb > 0) {
    1.64 +	    PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
    1.65 +	} else if (nb == 0) {
    1.66 +	    /* EOF */
    1.67 +	    SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
    1.68 +	    rv = 0;
    1.69 +	    break;
    1.70 +	} else /* if (nb < 0) */ {
    1.71 +	    SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
    1.72 +		     PR_GetError()));
    1.73 +	    rv = SECFailure;
    1.74 +	    break;
    1.75 +	}
    1.76 +
    1.77 +	PORT_Assert( nb <= gs->remainder );
    1.78 +	if (nb > gs->remainder) {
    1.79 +	    /* ssl_DefRecv is misbehaving!  this error is fatal to SSL. */
    1.80 +	    gs->state = GS_INIT;         /* so we don't crash next time */
    1.81 +	    rv = SECFailure;
    1.82 +	    break;
    1.83 +	}
    1.84 +
    1.85 +	gs->offset    += nb;
    1.86 +	gs->remainder -= nb;
    1.87 +	if (gs->state == GS_DATA)
    1.88 +	    gs->inbuf.len += nb;
    1.89 +
    1.90 +	/* if there's more to go, read some more. */
    1.91 +	if (gs->remainder > 0) {
    1.92 +	    continue;
    1.93 +	}
    1.94 +
    1.95 +	/* have received entire record header, or entire record. */
    1.96 +	switch (gs->state) {
    1.97 +	case GS_HEADER:
    1.98 +	    /*
    1.99 +	    ** Have received SSL3 record header in gs->hdr.
   1.100 +	    ** Now extract the length of the following encrypted data, 
   1.101 +	    ** and then read in the rest of the SSL3 record into gs->inbuf.
   1.102 +	    */
   1.103 +	    gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
   1.104 +
   1.105 +	    /* This is the max fragment length for an encrypted fragment
   1.106 +	    ** plus the size of the record header.
   1.107 +	    */
   1.108 +	    if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
   1.109 +		SSL3_SendAlert(ss, alert_fatal, unexpected_message);
   1.110 +		gs->state = GS_INIT;
   1.111 +		PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
   1.112 +		return SECFailure;
   1.113 +	    }
   1.114 +
   1.115 +	    gs->state     = GS_DATA;
   1.116 +	    gs->offset    = 0;
   1.117 +	    gs->inbuf.len = 0;
   1.118 +
   1.119 +	    if (gs->remainder > gs->inbuf.space) {
   1.120 +		err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
   1.121 +		if (err) {	/* realloc has set error code to no mem. */
   1.122 +		    return err;
   1.123 +		}
   1.124 +		lbp = gs->inbuf.buf;
   1.125 +	    }
   1.126 +	    break;	/* End this case.  Continue around the loop. */
   1.127 +
   1.128 +
   1.129 +	case GS_DATA:
   1.130 +	    /* 
   1.131 +	    ** SSL3 record has been completely received.
   1.132 +	    */
   1.133 +	    gs->state = GS_INIT;
   1.134 +	    return 1;
   1.135 +	}
   1.136 +    }
   1.137 +
   1.138 +    return rv;
   1.139 +}
   1.140 +
   1.141 +/*
   1.142 + * Read in an entire DTLS record.
   1.143 + *
   1.144 + * Blocks here for blocking sockets, otherwise returns -1 with
   1.145 + * 	PR_WOULD_BLOCK_ERROR when socket would block.
   1.146 + *
   1.147 + * This is simpler than SSL because we are reading on a datagram socket
   1.148 + * and datagrams must contain >=1 complete records.
   1.149 + *
   1.150 + * returns  1 if received a complete DTLS record.
   1.151 + * returns  0 if recv returns EOF
   1.152 + * returns -1 if recv returns < 0
   1.153 + *	(The error value may have already been set to PR_WOULD_BLOCK_ERROR)
   1.154 + *
   1.155 + * Caller must hold the recv buf lock.
   1.156 + *
   1.157 + * This loop returns when either
   1.158 + *      (a) an error or EOF occurs,
   1.159 + *	(b) PR_WOULD_BLOCK_ERROR,
   1.160 + * 	(c) data (entire DTLS record) has been received.
   1.161 + */
   1.162 +static int
   1.163 +dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
   1.164 +{
   1.165 +    int            nb;
   1.166 +    int            err;
   1.167 +    int            rv		= 1;
   1.168 +
   1.169 +    SSL_TRC(30, ("dtls_GatherData"));
   1.170 +
   1.171 +    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
   1.172 +
   1.173 +    gs->state = GS_HEADER;
   1.174 +    gs->offset = 0;
   1.175 +
   1.176 +    if (gs->dtlsPacketOffset == gs->dtlsPacket.len) {  /* No data left */
   1.177 +        gs->dtlsPacketOffset = 0;
   1.178 +        gs->dtlsPacket.len = 0;
   1.179 +
   1.180 +        /* Resize to the maximum possible size so we can fit a full datagram */
   1.181 +	/* This is the max fragment length for an encrypted fragment
   1.182 +	** plus the size of the record header.
   1.183 +	** This magic constant is copied from ssl3_GatherData, with 5 changed
   1.184 +	** to 13 (the size of the record header).
   1.185 +	*/
   1.186 +        if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
   1.187 +            err = sslBuffer_Grow(&gs->dtlsPacket,
   1.188 +				 MAX_FRAGMENT_LENGTH + 2048 + 13);
   1.189 +            if (err) {	/* realloc has set error code to no mem. */
   1.190 +                return err;
   1.191 +            }
   1.192 +        }
   1.193 +
   1.194 +        /* recv() needs to read a full datagram at a time */
   1.195 +        nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);
   1.196 +
   1.197 +        if (nb > 0) {
   1.198 +            PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
   1.199 +        } else if (nb == 0) {
   1.200 +            /* EOF */
   1.201 +            SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
   1.202 +            rv = 0;
   1.203 +            return rv;
   1.204 +        } else /* if (nb < 0) */ {
   1.205 +            SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
   1.206 +                     PR_GetError()));
   1.207 +            rv = SECFailure;
   1.208 +            return rv;
   1.209 +        }
   1.210 +
   1.211 +        gs->dtlsPacket.len = nb;
   1.212 +    }
   1.213 +
   1.214 +    /* At this point we should have >=1 complete records lined up in
   1.215 +     * dtlsPacket. Read off the header.
   1.216 +     */
   1.217 +    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
   1.218 +        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
   1.219 +		 "too short to contain header", SSL_GETPID(), ss->fd));
   1.220 +        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
   1.221 +        gs->dtlsPacketOffset = 0;
   1.222 +        gs->dtlsPacket.len = 0;
   1.223 +        rv = SECFailure;
   1.224 +        return rv;
   1.225 +    }
   1.226 +    memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
   1.227 +    gs->dtlsPacketOffset += 13;
   1.228 +
   1.229 +    /* Have received SSL3 record header in gs->hdr. */
   1.230 +    gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];
   1.231 +
   1.232 +    if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
   1.233 +        SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
   1.234 +		 "to contain rest of body", SSL_GETPID(), ss->fd));
   1.235 +        PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
   1.236 +        gs->dtlsPacketOffset = 0;
   1.237 +        gs->dtlsPacket.len = 0;
   1.238 +        rv = SECFailure;
   1.239 +        return rv;
   1.240 +    }
   1.241 +
   1.242 +    /* OK, we have at least one complete packet, copy into inbuf */
   1.243 +    if (gs->remainder > gs->inbuf.space) {
   1.244 +	err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
   1.245 +	if (err) {	/* realloc has set error code to no mem. */
   1.246 +	    return err;
   1.247 +	}
   1.248 +    }
   1.249 +
   1.250 +    memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
   1.251 +	   gs->remainder);
   1.252 +    gs->inbuf.len = gs->remainder;
   1.253 +    gs->offset = gs->remainder;
   1.254 +    gs->dtlsPacketOffset += gs->remainder;
   1.255 +    gs->state = GS_INIT;
   1.256 +
   1.257 +    return 1;
   1.258 +}
   1.259 +
   1.260 +/* Gather in a record and when complete, Handle that record.
   1.261 + * Repeat this until the handshake is complete, 
   1.262 + * or until application data is available.
   1.263 + *
   1.264 + * Returns  1 when the handshake is completed without error, or 
   1.265 + *                 application data is available.
   1.266 + * Returns  0 if ssl3_GatherData hits EOF.
   1.267 + * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
   1.268 + * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
   1.269 + *
   1.270 + * Called from ssl_GatherRecord1stHandshake       in sslcon.c, 
   1.271 + *    and from SSL_ForceHandshake in sslsecur.c
   1.272 + *    and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c).
   1.273 + *
   1.274 + * Caller must hold the recv buf lock.
   1.275 + */
   1.276 +int
   1.277 +ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
   1.278 +{
   1.279 +    SSL3Ciphertext cText;
   1.280 +    int            rv;
   1.281 +    PRBool         keepGoing = PR_TRUE;
   1.282 +
   1.283 +    SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
   1.284 +
   1.285 +    /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
   1.286 +     * which requires the 1stHandshakeLock, which must be acquired before the
   1.287 +     * RecvBufLock.
   1.288 +     */
   1.289 +    PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
   1.290 +    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
   1.291 +
   1.292 +    do {
   1.293 +	PRBool handleRecordNow = PR_FALSE;
   1.294 +
   1.295 +	ssl_GetSSL3HandshakeLock(ss);
   1.296 +
   1.297 +	/* Without this, we may end up wrongly reporting
   1.298 +	 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
   1.299 +	 * peer while we are waiting to be restarted.
   1.300 +	 */
   1.301 +	if (ss->ssl3.hs.restartTarget) {
   1.302 +	    ssl_ReleaseSSL3HandshakeLock(ss);
   1.303 +	    PORT_SetError(PR_WOULD_BLOCK_ERROR);
   1.304 +	    return (int) SECFailure;
   1.305 +	}
   1.306 +
   1.307 +	/* Treat an empty msgState like a NULL msgState. (Most of the time
   1.308 +	 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
   1.309 +	 * behind a non-NULL but zero-length msgState).
   1.310 +	 * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
   1.311 +	 */
   1.312 +	if (ss->ssl3.hs.msgState.buf) {
   1.313 +	    if (ss->ssl3.hs.msgState.len == 0) {
   1.314 +		ss->ssl3.hs.msgState.buf = NULL;
   1.315 +	    } else {
   1.316 +		handleRecordNow = PR_TRUE;
   1.317 +	    }
   1.318 +	}
   1.319 +
   1.320 +	ssl_ReleaseSSL3HandshakeLock(ss);
   1.321 +
   1.322 +	if (handleRecordNow) {
   1.323 +	    /* ssl3_HandleHandshake previously returned SECWouldBlock and the
   1.324 +	     * as-yet-unprocessed plaintext of that previous handshake record.
   1.325 +	     * We need to process it now before we overwrite it with the next
   1.326 +	     * handshake record.
   1.327 +	     */
   1.328 +	    rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
   1.329 +	} else {
   1.330 +	    /* bring in the next sslv3 record. */
   1.331 +	    if (ss->recvdCloseNotify) {
   1.332 +		/* RFC 5246 Section 7.2.1:
   1.333 +		 *   Any data received after a closure alert is ignored.
   1.334 +		 */
   1.335 +		return 0;
   1.336 +	    }
   1.337 +	    if (!IS_DTLS(ss)) {
   1.338 +		rv = ssl3_GatherData(ss, &ss->gs, flags);
   1.339 +	    } else {
   1.340 +		rv = dtls_GatherData(ss, &ss->gs, flags);
   1.341 +		
   1.342 +		/* If we got a would block error, that means that no data was
   1.343 +		 * available, so we check the timer to see if it's time to
   1.344 +		 * retransmit */
   1.345 +		if (rv == SECFailure &&
   1.346 +		    (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
   1.347 +		    ssl_GetSSL3HandshakeLock(ss);
   1.348 +		    dtls_CheckTimer(ss);
   1.349 +		    ssl_ReleaseSSL3HandshakeLock(ss);
   1.350 +		    /* Restore the error in case something succeeded */
   1.351 +		    PORT_SetError(PR_WOULD_BLOCK_ERROR);
   1.352 +		}
   1.353 +	    }
   1.354 +
   1.355 +	    if (rv <= 0) {
   1.356 +		return rv;
   1.357 +	    }
   1.358 +
   1.359 +	    /* decipher it, and handle it if it's a handshake.
   1.360 +	     * If it's application data, ss->gs.buf will not be empty upon return.
   1.361 +	     * If it's a change cipher spec, alert, or handshake message,
   1.362 +	     * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
   1.363 +	     */
   1.364 +	    cText.type    = (SSL3ContentType)ss->gs.hdr[0];
   1.365 +	    cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
   1.366 +
   1.367 +	    if (IS_DTLS(ss)) {
   1.368 +		int i;
   1.369 +
   1.370 +		cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
   1.371 +		/* DTLS sequence number */
   1.372 +		cText.seq_num.high = 0; cText.seq_num.low = 0;
   1.373 +		for (i = 0; i < 4; i++) {
   1.374 +		    cText.seq_num.high <<= 8; cText.seq_num.low <<= 8;
   1.375 +		    cText.seq_num.high |= ss->gs.hdr[3 + i];
   1.376 +		    cText.seq_num.low |= ss->gs.hdr[7 + i];
   1.377 +		}
   1.378 +	    }
   1.379 +
   1.380 +	    cText.buf     = &ss->gs.inbuf;
   1.381 +	    rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
   1.382 +	}
   1.383 +	if (rv < 0) {
   1.384 +	    return ss->recvdCloseNotify ? 0 : rv;
   1.385 +	}
   1.386 +	if (ss->gs.buf.len > 0) {
   1.387 +	    /* We have application data to return to the application. This
   1.388 +	     * prioritizes returning application data to the application over
   1.389 +	     * completing any renegotiation handshake we may be doing.
   1.390 +	     */
   1.391 +	    PORT_Assert(ss->firstHsDone);
   1.392 +	    PORT_Assert(cText.type == content_application_data);
   1.393 +	    break;
   1.394 +	}
   1.395 +
   1.396 +	PORT_Assert(keepGoing);
   1.397 +	ssl_GetSSL3HandshakeLock(ss);
   1.398 +	if (ss->ssl3.hs.ws == idle_handshake) {
   1.399 +	    /* We are done with the current handshake so stop trying to
   1.400 +	     * handshake. Note that it would be safe to test ss->firstHsDone
   1.401 +	     * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
   1.402 +	     * we prioritize completing a renegotiation handshake over sending
   1.403 +	     * application data.
   1.404 +	     */
   1.405 +	    PORT_Assert(ss->firstHsDone);
   1.406 +	    PORT_Assert(!ss->ssl3.hs.canFalseStart);
   1.407 +	    keepGoing = PR_FALSE;
   1.408 +	} else if (ss->ssl3.hs.canFalseStart) {
   1.409 +	    /* Prioritize sending application data over trying to complete
   1.410 +	     * the handshake if we're false starting.
   1.411 +	     *
   1.412 +	     * If we were to do this check at the beginning of the loop instead
   1.413 +	     * of here, then this function would become be a no-op after
   1.414 +	     * receiving the ServerHelloDone in the false start case, and we
   1.415 +	     * would never complete the handshake.
   1.416 +	     */
   1.417 +	    PORT_Assert(!ss->firstHsDone);
   1.418 +
   1.419 +	    if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
   1.420 +		keepGoing = PR_FALSE;
   1.421 +	    } else {
   1.422 +		ss->ssl3.hs.canFalseStart = PR_FALSE;
   1.423 +	    }
   1.424 +	}
   1.425 +	ssl_ReleaseSSL3HandshakeLock(ss);
   1.426 +    } while (keepGoing);
   1.427 +
   1.428 +    ss->gs.readOffset = 0;
   1.429 +    ss->gs.writeOffset = ss->gs.buf.len;
   1.430 +    return 1;
   1.431 +}
   1.432 +
   1.433 +/* Repeatedly gather in a record and when complete, Handle that record.
   1.434 + * Repeat this until some application data is received.
   1.435 + *
   1.436 + * Returns  1 when application data is available.
   1.437 + * Returns  0 if ssl3_GatherData hits EOF.
   1.438 + * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
   1.439 + * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
   1.440 + *
   1.441 + * Called from DoRecv in sslsecur.c
   1.442 + * Caller must hold the recv buf lock.
   1.443 + */
   1.444 +int
   1.445 +ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
   1.446 +{
   1.447 +    int            rv;
   1.448 +
   1.449 +    /* ssl3_GatherCompleteHandshake requires both of these locks. */
   1.450 +    PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
   1.451 +    PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
   1.452 +
   1.453 +    do {
   1.454 +	rv = ssl3_GatherCompleteHandshake(ss, flags);
   1.455 +    } while (rv > 0 && ss->gs.buf.len == 0);
   1.456 +
   1.457 +    return rv;
   1.458 +}

mercurial