| Index: net/third_party/nss/ssl/sslsock.c
|
| ===================================================================
|
| --- net/third_party/nss/ssl/sslsock.c (revision 124359)
|
| +++ net/third_party/nss/ssl/sslsock.c (working copy)
|
| @@ -40,7 +40,7 @@
|
| * the terms of any one of the MPL, the GPL or the LGPL.
|
| *
|
| * ***** END LICENSE BLOCK ***** */
|
| -/* $Id: sslsock.c,v 1.67.2.1 2010/07/31 04:33:52 wtc%google.com Exp $ */
|
| +/* $Id: sslsock.c,v 1.82 2012/02/15 21:52:08 kaie%kuix.de Exp $ */
|
| #include "seccomon.h"
|
| #include "cert.h"
|
| #include "keyhi.h"
|
| @@ -163,19 +163,19 @@
|
| ** default settings for socket enables
|
| */
|
| static sslOptions ssl_defaults = {
|
| - { siBuffer, NULL, 0 }, /* nextProtoNego */
|
| + { siBuffer, NULL, 0 }, /* nextProtoNego */
|
| PR_TRUE, /* useSecurity */
|
| PR_FALSE, /* useSocks */
|
| PR_FALSE, /* requestCertificate */
|
| 2, /* requireCertificate */
|
| PR_FALSE, /* handshakeAsClient */
|
| PR_FALSE, /* handshakeAsServer */
|
| - PR_TRUE, /* enableSSL2 */
|
| + PR_FALSE, /* enableSSL2 */ /* now defaults to off in NSS 3.13 */
|
| PR_TRUE, /* enableSSL3 */
|
| PR_TRUE, /* enableTLS */ /* now defaults to on in NSS 3.0 */
|
| PR_FALSE, /* noCache */
|
| PR_FALSE, /* fdx */
|
| - PR_TRUE, /* v2CompatibleHello */
|
| + PR_FALSE, /* v2CompatibleHello */ /* now defaults to off in NSS 3.13 */
|
| PR_TRUE, /* detectRollBack */
|
| PR_FALSE, /* noStepDown */
|
| PR_FALSE, /* bypassPKCS11 */
|
| @@ -185,8 +185,8 @@
|
| 2, /* enableRenegotiation (default: requires extension) */
|
| PR_FALSE, /* requireSafeNegotiation */
|
| PR_FALSE, /* enableFalseStart */
|
| + PR_TRUE, /* cbcRandomIV */
|
| PR_FALSE, /* enableOCSPStapling */
|
| - PR_FALSE, /* enableCachedInfo */
|
| PR_FALSE, /* enableOBCerts */
|
| PR_FALSE, /* encryptClientCerts */
|
| };
|
| @@ -211,6 +211,7 @@
|
| /* forward declarations. */
|
| static sslSocket *ssl_NewSocket(PRBool makeLocks);
|
| static SECStatus ssl_MakeLocks(sslSocket *ss);
|
| +static void ssl_SetDefaultsFromEnvironment(void);
|
| static PRStatus ssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack,
|
| PRDescIdentity id);
|
|
|
| @@ -447,10 +448,7 @@
|
| ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
|
| ss->ephemeralECDHKeyPair = NULL;
|
| }
|
| - if (ss->opt.nextProtoNego.data) {
|
| - PORT_Free(ss->opt.nextProtoNego.data);
|
| - ss->opt.nextProtoNego.data = NULL;
|
| - }
|
| + SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
|
| PORT_Assert(!ss->xtnData.sniNameArr);
|
| if (ss->xtnData.sniNameArr) {
|
| PORT_Free(ss->xtnData.sniNameArr);
|
| @@ -746,14 +744,14 @@
|
| ss->opt.enableFalseStart = on;
|
| break;
|
|
|
| + case SSL_CBC_RANDOM_IV:
|
| + ss->opt.cbcRandomIV = on;
|
| + break;
|
| +
|
| case SSL_ENABLE_OCSP_STAPLING:
|
| ss->opt.enableOCSPStapling = on;
|
| break;
|
|
|
| - case SSL_ENABLE_CACHED_INFO:
|
| - ss->opt.enableCachedInfo = on;
|
| - break;
|
| -
|
| case SSL_ENABLE_OB_CERTS:
|
| ss->opt.enableOBCerts = on;
|
| break;
|
| @@ -826,8 +824,8 @@
|
| case SSL_REQUIRE_SAFE_NEGOTIATION:
|
| on = ss->opt.requireSafeNegotiation; break;
|
| case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
|
| + case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
|
| case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
|
| - case SSL_ENABLE_CACHED_INFO: on = ss->opt.enableCachedInfo; break;
|
| case SSL_ENABLE_OB_CERTS: on = ss->opt.enableOBCerts; break;
|
| case SSL_ENCRYPT_CLIENT_CERTS:
|
| on = ss->opt.encryptClientCerts; break;
|
| @@ -855,6 +853,8 @@
|
| return SECFailure;
|
| }
|
|
|
| + ssl_SetDefaultsFromEnvironment();
|
| +
|
| switch (which) {
|
| case SSL_SOCKS: on = PR_FALSE; break;
|
| case SSL_SECURITY: on = ssl_defaults.useSecurity; break;
|
| @@ -882,10 +882,10 @@
|
| on = ssl_defaults.requireSafeNegotiation;
|
| break;
|
| case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
|
| + case SSL_CBC_RANDOM_IV: on = ssl_defaults.cbcRandomIV; break;
|
| case SSL_ENABLE_OCSP_STAPLING:
|
| on = ssl_defaults.enableOCSPStapling;
|
| break;
|
| - case SSL_ENABLE_CACHED_INFO: on = ssl_defaults.enableCachedInfo; break;
|
| case SSL_ENABLE_OB_CERTS: on = ssl_defaults.enableOBCerts; break;
|
| case SSL_ENCRYPT_CLIENT_CERTS:
|
| on = ssl_defaults.encryptClientCerts; break;
|
| @@ -909,6 +909,14 @@
|
| SECStatus
|
| SSL_OptionSetDefault(PRInt32 which, PRBool on)
|
| {
|
| + SECStatus status = ssl_Init();
|
| +
|
| + if (status != SECSuccess) {
|
| + return status;
|
| + }
|
| +
|
| + ssl_SetDefaultsFromEnvironment();
|
| +
|
| switch (which) {
|
| case SSL_SOCKS:
|
| ssl_defaults.useSocks = PR_FALSE;
|
| @@ -1036,14 +1044,14 @@
|
| ssl_defaults.enableFalseStart = on;
|
| break;
|
|
|
| + case SSL_CBC_RANDOM_IV:
|
| + ssl_defaults.cbcRandomIV = on;
|
| + break;
|
| +
|
| case SSL_ENABLE_OCSP_STAPLING:
|
| ssl_defaults.enableOCSPStapling = on;
|
| break;
|
|
|
| - case SSL_ENABLE_CACHED_INFO:
|
| - ssl_defaults.enableCachedInfo = on;
|
| - break;
|
| -
|
| case SSL_ENABLE_OB_CERTS:
|
| ssl_defaults.enableOBCerts = on;
|
| break;
|
| @@ -1095,8 +1103,12 @@
|
| SECStatus
|
| SSL_CipherPolicySet(PRInt32 which, PRInt32 policy)
|
| {
|
| - SECStatus rv;
|
| + SECStatus rv = ssl_Init();
|
|
|
| + if (rv != SECSuccess) {
|
| + return rv;
|
| + }
|
| +
|
| if (ssl_IsRemovedCipherSuite(which)) {
|
| rv = SECSuccess;
|
| } else if (SSL_IS_SSL2_CIPHER(which)) {
|
| @@ -1150,8 +1162,12 @@
|
| SECStatus
|
| SSL_CipherPrefSetDefault(PRInt32 which, PRBool enabled)
|
| {
|
| - SECStatus rv;
|
| + SECStatus rv = ssl_Init();
|
|
|
| + if (rv != SECSuccess) {
|
| + return rv;
|
| + }
|
| +
|
| if (ssl_IsRemovedCipherSuite(which))
|
| return SECSuccess;
|
| if (enabled && ssl_defaults.noStepDown && SSL_IsExportCipherSuite(which)) {
|
| @@ -1239,7 +1255,6 @@
|
| SECStatus
|
| NSS_SetDomesticPolicy(void)
|
| {
|
| -#ifndef EXPORT_VERSION
|
| SECStatus status = SECSuccess;
|
| cipherPolicy * policy;
|
|
|
| @@ -1249,37 +1264,18 @@
|
| break;
|
| }
|
| return status;
|
| -#else
|
| - return NSS_SetExportPolicy();
|
| -#endif
|
| }
|
|
|
| SECStatus
|
| NSS_SetExportPolicy(void)
|
| {
|
| - SECStatus status = SECSuccess;
|
| - cipherPolicy * policy;
|
| -
|
| - for (policy = ssl_ciphers; policy->cipher != 0; ++policy) {
|
| - status = SSL_SetPolicy(policy->cipher, policy->export);
|
| - if (status != SECSuccess)
|
| - break;
|
| - }
|
| - return status;
|
| + return NSS_SetDomesticPolicy();
|
| }
|
|
|
| SECStatus
|
| NSS_SetFrancePolicy(void)
|
| {
|
| - SECStatus status = SECSuccess;
|
| - cipherPolicy * policy;
|
| -
|
| - for (policy = ssl_ciphers; policy->cipher != 0; ++policy) {
|
| - status = SSL_SetPolicy(policy->cipher, policy->france);
|
| - if (status != SECSuccess)
|
| - break;
|
| - }
|
| - return status;
|
| + return NSS_SetDomesticPolicy();
|
| }
|
|
|
|
|
| @@ -1291,7 +1287,12 @@
|
| sslSocket * ns = NULL;
|
| PRStatus rv;
|
| PRNetAddr addr;
|
| + SECStatus status = ssl_Init();
|
|
|
| + if (status != SECSuccess) {
|
| + return NULL;
|
| + }
|
| +
|
| if (model == NULL) {
|
| /* Just create a default socket if we're given NULL for the model */
|
| ns = ssl_NewSocket((PRBool)(!ssl_defaults.noLocks));
|
| @@ -1324,15 +1325,14 @@
|
| }
|
|
|
| SECStatus
|
| -SSL_SetNextProtoCallback(PRFileDesc *fd,
|
| - SSLNextProtoCallback callback,
|
| - void *arg) {
|
| +SSL_SetNextProtoCallback(PRFileDesc *fd, SSLNextProtoCallback callback,
|
| + void *arg)
|
| +{
|
| sslSocket *ss = ssl_FindSocket(fd);
|
|
|
| if (!ss) {
|
| - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID(),
|
| - fd));
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoCallback", SSL_GETPID(),
|
| + fd));
|
| return SECFailure;
|
| }
|
|
|
| @@ -1340,25 +1340,29 @@
|
| ss->nextProtoCallback = callback;
|
| ss->nextProtoArg = arg;
|
| ssl_ReleaseSSL3HandshakeLock(ss);
|
| +
|
| return SECSuccess;
|
| }
|
|
|
| -/* NextProtoStandardCallback is set as an NPN callback for the case when the
|
| - * user of the sockets wants the standard selection algorithm. */
|
| +/* NextProtoStandardCallback is set as an NPN callback for the case when
|
| + * SSL_SetNextProtoNego is used.
|
| + */
|
| static SECStatus
|
| -NextProtoStandardCallback(void *arg,
|
| - PRFileDesc *fd,
|
| - const unsigned char *protos,
|
| - unsigned int protos_len,
|
| - unsigned char *protoOut,
|
| - unsigned int *protoOutLen)
|
| +ssl_NextProtoNegoCallback(void *arg, PRFileDesc *fd,
|
| + const unsigned char *protos, unsigned int protos_len,
|
| + unsigned char *protoOut, unsigned int *protoOutLen,
|
| + unsigned int protoMaxLen)
|
| {
|
| unsigned int i, j;
|
| const unsigned char *result;
|
| -
|
| sslSocket *ss = ssl_FindSocket(fd);
|
| - PORT_Assert(ss);
|
|
|
| + if (!ss) {
|
| + SSL_DBG(("%d: SSL[%d]: bad socket in ssl_NextProtoNegoCallback",
|
| + SSL_GETPID(), fd));
|
| + return SECFailure;
|
| + }
|
| +
|
| if (protos_len == 0) {
|
| /* The server supports the extension, but doesn't have any protocols
|
| * configured. In this case we request our favoured protocol. */
|
| @@ -1369,16 +1373,16 @@
|
| for (i = 0; i < protos_len; ) {
|
| for (j = 0; j < ss->opt.nextProtoNego.len; ) {
|
| if (protos[i] == ss->opt.nextProtoNego.data[j] &&
|
| - memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1],
|
| - protos[i]) == 0) {
|
| + PORT_Memcmp(&protos[i+1], &ss->opt.nextProtoNego.data[j+1],
|
| + protos[i]) == 0) {
|
| /* We found a match. */
|
| ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
|
| result = &protos[i];
|
| goto found;
|
| }
|
| - j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1;
|
| + j += 1 + (unsigned int)ss->opt.nextProtoNego.data[j];
|
| }
|
| - i += (unsigned int)protos[i] + 1;
|
| + i += 1 + (unsigned int)protos[i];
|
| }
|
|
|
| pick_first:
|
| @@ -1386,8 +1390,12 @@
|
| result = ss->opt.nextProtoNego.data;
|
|
|
| found:
|
| + *protoOutLen = result[0];
|
| + if (protoMaxLen < result[0]) {
|
| + PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
| + return SECFailure;
|
| + }
|
| memcpy(protoOut, result + 1, result[0]);
|
| - *protoOutLen = result[0];
|
| return SECSuccess;
|
| }
|
|
|
| @@ -1395,14 +1403,14 @@
|
| SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
|
| unsigned int length)
|
| {
|
| + sslSocket *ss;
|
| SECStatus rv;
|
| + SECItem dataItem = { siBuffer, (unsigned char *) data, length };
|
|
|
| - sslSocket *ss = ssl_FindSocket(fd);
|
| -
|
| + ss = ssl_FindSocket(fd);
|
| if (!ss) {
|
| SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego",
|
| SSL_GETPID(), fd));
|
| - PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| return SECFailure;
|
| }
|
|
|
| @@ -1410,43 +1418,46 @@
|
| return SECFailure;
|
|
|
| ssl_GetSSL3HandshakeLock(ss);
|
| - if (ss->opt.nextProtoNego.data)
|
| - PORT_Free(ss->opt.nextProtoNego.data);
|
| - ss->opt.nextProtoNego.data = PORT_Alloc(length);
|
| - if (!ss->opt.nextProtoNego.data) {
|
| - ssl_ReleaseSSL3HandshakeLock(ss);
|
| - return SECFailure;
|
| - }
|
| - memcpy(ss->opt.nextProtoNego.data, data, length);
|
| - ss->opt.nextProtoNego.len = length;
|
| - ss->opt.nextProtoNego.type = siBuffer;
|
| + SECITEM_FreeItem(&ss->opt.nextProtoNego, PR_FALSE);
|
| + rv = SECITEM_CopyItem(NULL, &ss->opt.nextProtoNego, &dataItem);
|
| ssl_ReleaseSSL3HandshakeLock(ss);
|
|
|
| - return SSL_SetNextProtoCallback(fd, NextProtoStandardCallback, NULL);
|
| + if (rv != SECSuccess)
|
| + return rv;
|
| +
|
| + return SSL_SetNextProtoCallback(fd, ssl_NextProtoNegoCallback, NULL);
|
| }
|
|
|
| SECStatus
|
| -SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf,
|
| - unsigned int *length, unsigned int buf_len)
|
| +SSL_GetNextProto(PRFileDesc *fd, SSLNextProtoState *state, unsigned char *buf,
|
| + unsigned int *bufLen, unsigned int bufLenMax)
|
| {
|
| sslSocket *ss = ssl_FindSocket(fd);
|
|
|
| if (!ss) {
|
| SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(),
|
| - fd));
|
| + fd));
|
| return SECFailure;
|
| }
|
|
|
| + if (!state || !buf || !bufLen) {
|
| + PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| + return SECFailure;
|
| + }
|
| +
|
| *state = ss->ssl3.nextProtoState;
|
|
|
| if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
|
| ss->ssl3.nextProto.data) {
|
| - *length = ss->ssl3.nextProto.len;
|
| - if (*length > buf_len)
|
| - *length = buf_len;
|
| - PORT_Memcpy(buf, ss->ssl3.nextProto.data, *length);
|
| + *bufLen = ss->ssl3.nextProto.len;
|
| + if (*bufLen > bufLenMax) {
|
| + PORT_SetError(SEC_ERROR_OUTPUT_LEN);
|
| + *bufLen = 0;
|
| + return SECFailure;
|
| + }
|
| + PORT_Memcpy(buf, ss->ssl3.nextProto.data, ss->ssl3.nextProto.len);
|
| } else {
|
| - *length = 0;
|
| + *bufLen = 0;
|
| }
|
|
|
| return SECSuccess;
|
| @@ -1462,8 +1473,8 @@
|
| #if 0
|
| sslSocket * sm = NULL, *ss = NULL;
|
| int i;
|
| - sslServerCerts * mc = sm->serverCerts;
|
| - sslServerCerts * sc = ss->serverCerts;
|
| + sslServerCerts * mc = NULL;
|
| + sslServerCerts * sc = NULL;
|
|
|
| if (model == NULL) {
|
| PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
|
| @@ -1492,7 +1503,9 @@
|
| /* This int should be SSLKEAType, but CC on Irix complains,
|
| * during the for loop.
|
| */
|
| - for (i=kt_null; i < kt_kea_size; i++, mc++, sc++) {
|
| + for (i=kt_null; i < kt_kea_size; i++) {
|
| + mc = &(sm->serverCerts[i]);
|
| + sc = &(ss->serverCerts[i]);
|
| if (mc->serverCert && mc->serverCertChain) {
|
| if (sc->serverCert) {
|
| CERT_DestroyCertificate(sc->serverCert);
|
| @@ -2053,7 +2066,36 @@
|
| } else if ((ss->lastWriteBlocked) && (how_flags & PR_POLL_READ) &&
|
| (ss->pendingBuf.len != 0)) { /* write data waiting to be sent */
|
| new_flags |= PR_POLL_WRITE; /* also select on write. */
|
| - }
|
| + }
|
| +
|
| + if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
|
| + ss->ssl3.hs.restartTarget != NULL) {
|
| + /* Read and write will block until the asynchronous callback completes
|
| + * (e.g. until SSL_AuthCertificateComplete is called), so don't tell
|
| + * the caller to poll the socket unless there is pending write data.
|
| + */
|
| + if (ss->lastWriteBlocked && ss->pendingBuf.len != 0) {
|
| + /* Ignore any newly-received data on the socket, but do wait for
|
| + * the socket to become writable again. Here, it is OK for an error
|
| + * to be detected, because our logic for sending pending write data
|
| + * will allow us to report the error to the caller without the risk
|
| + * of the application spinning.
|
| + */
|
| + new_flags &= (PR_POLL_WRITE | PR_POLL_EXCEPT);
|
| + } else {
|
| + /* Unfortunately, clearing new_flags will make it impossible for
|
| + * the application to detect errors that it would otherwise be
|
| + * able to detect with PR_POLL_EXCEPT, until the asynchronous
|
| + * callback completes. However, we must clear all the flags to
|
| + * prevent the application from spinning (alternating between
|
| + * calling PR_Poll that would return PR_POLL_EXCEPT, and send/recv
|
| + * which won't actually report the I/O error while we are waiting
|
| + * for the asynchronous callback to complete).
|
| + */
|
| + new_flags = 0;
|
| + }
|
| + }
|
| +
|
| if (new_flags && (fd->lower->methods->poll != NULL)) {
|
| PRInt16 lower_out_flags = 0;
|
| PRInt16 lower_new_flags;
|
| @@ -2428,7 +2470,9 @@
|
| PRStatus status;
|
|
|
| if (!ssl_inited) {
|
| - PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
|
| + status = PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer);
|
| + if (status != PR_SUCCESS)
|
| + goto loser;
|
| }
|
|
|
| if (ns == NULL)
|
| @@ -2504,13 +2548,9 @@
|
|
|
| #define LOWER(x) (x | 0x20) /* cheap ToLower function ignores LOCALE */
|
|
|
| -/*
|
| -** Create a newsocket structure for a file descriptor.
|
| -*/
|
| -static sslSocket *
|
| -ssl_NewSocket(PRBool makeLocks)
|
| +static void
|
| +ssl_SetDefaultsFromEnvironment(void)
|
| {
|
| - sslSocket *ss;
|
| #if defined( NSS_HAVE_GETENV )
|
| static int firsttime = 1;
|
|
|
| @@ -2579,8 +2619,25 @@
|
| SSL_TRACE(("SSL: requireSafeNegotiation set to %d",
|
| PR_TRUE));
|
| }
|
| + ev = getenv("NSS_SSL_CBC_RANDOM_IV");
|
| + if (ev && ev[0] == '0') {
|
| + ssl_defaults.cbcRandomIV = PR_FALSE;
|
| + SSL_TRACE(("SSL: cbcRandomIV set to 0"));
|
| + }
|
| }
|
| #endif /* NSS_HAVE_GETENV */
|
| +}
|
| +
|
| +/*
|
| +** Create a newsocket structure for a file descriptor.
|
| +*/
|
| +static sslSocket *
|
| +ssl_NewSocket(PRBool makeLocks)
|
| +{
|
| + sslSocket *ss;
|
| +
|
| + ssl_SetDefaultsFromEnvironment();
|
| +
|
| if (ssl_force_locks)
|
| makeLocks = PR_TRUE;
|
|
|
| @@ -2654,3 +2711,4 @@
|
| }
|
| return ss;
|
| }
|
| +
|
|
|