summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/ssl/sslsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/sslsock.c')
-rw-r--r--security/nss/lib/ssl/sslsock.c282
1 files changed, 191 insertions, 91 deletions
diff --git a/security/nss/lib/ssl/sslsock.c b/security/nss/lib/ssl/sslsock.c
index f089c75e0..99828c85b 100644
--- a/security/nss/lib/ssl/sslsock.c
+++ b/security/nss/lib/ssl/sslsock.c
@@ -330,6 +330,10 @@ ssl_DupSocket(sslSocket *os)
ss->getClientAuthDataArg = os->getClientAuthDataArg;
ss->sniSocketConfig = os->sniSocketConfig;
ss->sniSocketConfigArg = os->sniSocketConfigArg;
+ ss->alertReceivedCallback = os->alertReceivedCallback;
+ ss->alertReceivedCallbackArg = os->alertReceivedCallbackArg;
+ ss->alertSentCallback = os->alertSentCallback;
+ ss->alertSentCallbackArg = os->alertSentCallbackArg;
ss->handleBadCert = os->handleBadCert;
ss->badCertArg = os->badCertArg;
ss->handshakeCallback = os->handshakeCallback;
@@ -2148,6 +2152,14 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
ss->sniSocketConfig = sm->sniSocketConfig;
if (sm->sniSocketConfigArg)
ss->sniSocketConfigArg = sm->sniSocketConfigArg;
+ if (sm->alertReceivedCallback) {
+ ss->alertReceivedCallback = sm->alertReceivedCallback;
+ ss->alertReceivedCallbackArg = sm->alertReceivedCallbackArg;
+ }
+ if (sm->alertSentCallback) {
+ ss->alertSentCallback = sm->alertSentCallback;
+ ss->alertSentCallbackArg = sm->alertSentCallbackArg;
+ }
if (sm->handleBadCert)
ss->handleBadCert = sm->handleBadCert;
if (sm->badCertArg)
@@ -2161,61 +2173,82 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
return fd;
}
-/*
- * Get the user supplied range
- */
-static SECStatus
-ssl3_GetRangePolicy(SSLProtocolVariant protocolVariant, SSLVersionRange *prange)
+SECStatus
+ssl3_GetEffectiveVersionPolicy(SSLProtocolVariant variant,
+ SSLVersionRange *effectivePolicy)
{
SECStatus rv;
- PRUint32 policy;
- PRInt32 option;
+ PRUint32 policyFlag;
+ PRInt32 minPolicy, maxPolicy;
- /* only use policy constraints if we've set the apply ssl policy bit */
- rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policy);
- if ((rv != SECSuccess) || !(policy & NSS_USE_POLICY_IN_SSL)) {
- return SECFailure;
+ if (variant == ssl_variant_stream) {
+ effectivePolicy->min = SSL_LIBRARY_VERSION_MIN_SUPPORTED_STREAM;
+ effectivePolicy->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
+ } else {
+ effectivePolicy->min = SSL_LIBRARY_VERSION_MIN_SUPPORTED_DATAGRAM;
+ effectivePolicy->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
}
- rv = NSS_OptionGet(VERSIONS_POLICY_MIN(protocolVariant), &option);
+
+ rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, &policyFlag);
+ if ((rv != SECSuccess) || !(policyFlag & NSS_USE_POLICY_IN_SSL)) {
+ /* Policy is not active, report library extents. */
+ return SECSuccess;
+ }
+
+ rv = NSS_OptionGet(VERSIONS_POLICY_MIN(variant), &minPolicy);
if (rv != SECSuccess) {
- return rv;
+ return SECFailure;
}
- prange->min = (PRUint16)option;
- rv = NSS_OptionGet(VERSIONS_POLICY_MAX(protocolVariant), &option);
+ rv = NSS_OptionGet(VERSIONS_POLICY_MAX(variant), &maxPolicy);
if (rv != SECSuccess) {
- return rv;
+ return SECFailure;
}
- prange->max = (PRUint16)option;
- if (prange->max < prange->min) {
- return SECFailure; /* don't accept an invalid policy */
+
+ if (minPolicy > effectivePolicy->max ||
+ maxPolicy < effectivePolicy->min ||
+ minPolicy > maxPolicy) {
+ return SECFailure;
}
+ effectivePolicy->min = PR_MAX(effectivePolicy->min, minPolicy);
+ effectivePolicy->max = PR_MIN(effectivePolicy->max, maxPolicy);
return SECSuccess;
}
-/*
- * Constrain a single protocol variant's range based on the user policy
+/*
+ * Assumes that rangeParam values are within the supported boundaries,
+ * but should contain all potentially allowed versions, even if they contain
+ * conflicting versions.
+ * Will return the overlap, or a NONE range if system policy is invalid.
*/
static SECStatus
-ssl3_ConstrainVariantRangeByPolicy(SSLProtocolVariant protocolVariant)
+ssl3_CreateOverlapWithPolicy(SSLProtocolVariant protocolVariant,
+ SSLVersionRange *input,
+ SSLVersionRange *overlap)
{
- SSLVersionRange vrange;
- SSLVersionRange pvrange;
SECStatus rv;
+ SSLVersionRange effectivePolicyBoundary;
+ SSLVersionRange vrange;
- vrange = *VERSIONS_DEFAULTS(protocolVariant);
- rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
- if (rv != SECSuccess) {
- return SECSuccess; /* we don't have any policy */
+ PORT_Assert(input != NULL);
+
+ rv = ssl3_GetEffectiveVersionPolicy(protocolVariant,
+ &effectivePolicyBoundary);
+ if (rv == SECFailure) {
+ /* SECFailure means internal failure or invalid configuration. */
+ overlap->min = overlap->max = SSL_LIBRARY_VERSION_NONE;
+ return SECFailure;
}
- vrange.min = PR_MAX(vrange.min, pvrange.min);
- vrange.max = PR_MIN(vrange.max, pvrange.max);
- if (vrange.max >= vrange.min) {
- *VERSIONS_DEFAULTS(protocolVariant) = vrange;
- } else {
+
+ vrange.min = PR_MAX(input->min, effectivePolicyBoundary.min);
+ vrange.max = PR_MIN(input->max, effectivePolicyBoundary.max);
+
+ if (vrange.max < vrange.min) {
/* there was no overlap, turn off range altogether */
- pvrange.min = pvrange.max = SSL_LIBRARY_VERSION_NONE;
- *VERSIONS_DEFAULTS(protocolVariant) = pvrange;
+ overlap->min = overlap->max = SSL_LIBRARY_VERSION_NONE;
+ return SECFailure;
}
+
+ *overlap = vrange;
return SECSuccess;
}
@@ -2223,16 +2256,17 @@ static PRBool
ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant,
SSL3ProtocolVersion version)
{
- SSLVersionRange pvrange;
SECStatus rv;
+ SSLVersionRange effectivePolicyBoundary;
- rv = ssl3_GetRangePolicy(protocolVariant, &pvrange);
- if (rv == SECSuccess) {
- if ((version > pvrange.max) || (version < pvrange.min)) {
- return PR_FALSE; /* disallowed by policy */
- }
+ rv = ssl3_GetEffectiveVersionPolicy(protocolVariant,
+ &effectivePolicyBoundary);
+ if (rv == SECFailure) {
+ /* SECFailure means internal failure or invalid configuration. */
+ return PR_FALSE;
}
- return PR_TRUE;
+ return version >= effectivePolicyBoundary.min &&
+ version <= effectivePolicyBoundary.max;
}
/*
@@ -2242,52 +2276,44 @@ ssl_VersionIsSupportedByPolicy(SSLProtocolVariant protocolVariant,
SECStatus
ssl3_ConstrainRangeByPolicy(void)
{
- SECStatus rv;
- rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_stream);
- if (rv != SECSuccess) {
- return rv;
- }
- rv = ssl3_ConstrainVariantRangeByPolicy(ssl_variant_datagram);
- if (rv != SECSuccess) {
- return rv;
- }
+ /* We ignore failures in ssl3_CreateOverlapWithPolicy. Although an empty
+ * overlap disables all connectivity, it's an allowed state.
+ */
+ ssl3_CreateOverlapWithPolicy(ssl_variant_stream,
+ VERSIONS_DEFAULTS(ssl_variant_stream),
+ VERSIONS_DEFAULTS(ssl_variant_stream));
+ ssl3_CreateOverlapWithPolicy(ssl_variant_datagram,
+ VERSIONS_DEFAULTS(ssl_variant_datagram),
+ VERSIONS_DEFAULTS(ssl_variant_datagram));
return SECSuccess;
}
PRBool
-ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
- SSL3ProtocolVersion version)
+ssl3_VersionIsSupportedByCode(SSLProtocolVariant protocolVariant,
+ SSL3ProtocolVersion version)
{
- if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) {
- return PR_FALSE;
- }
switch (protocolVariant) {
case ssl_variant_stream:
- return (version >= SSL_LIBRARY_VERSION_3_0 &&
+ return (version >= SSL_LIBRARY_VERSION_MIN_SUPPORTED_STREAM &&
version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
case ssl_variant_datagram:
- return (version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
+ return (version >= SSL_LIBRARY_VERSION_MIN_SUPPORTED_DATAGRAM &&
version <= SSL_LIBRARY_VERSION_MAX_SUPPORTED);
- default:
- /* Can't get here */
- PORT_Assert(PR_FALSE);
- return PR_FALSE;
}
+
+ /* Can't get here */
+ PORT_Assert(PR_FALSE);
+ return PR_FALSE;
}
-/* Returns PR_TRUE if the given version range is valid and
-** fully supported; otherwise, returns PR_FALSE.
-*/
-static PRBool
-ssl3_VersionRangeIsValid(SSLProtocolVariant protocolVariant,
- const SSLVersionRange *vrange)
+PRBool
+ssl3_VersionIsSupported(SSLProtocolVariant protocolVariant,
+ SSL3ProtocolVersion version)
{
- return vrange &&
- vrange->min <= vrange->max &&
- ssl3_VersionIsSupported(protocolVariant, vrange->min) &&
- ssl3_VersionIsSupported(protocolVariant, vrange->max) &&
- (vrange->min > SSL_LIBRARY_VERSION_3_0 ||
- vrange->max < SSL_LIBRARY_VERSION_TLS_1_3);
+ if (!ssl_VersionIsSupportedByPolicy(protocolVariant, version)) {
+ return PR_FALSE;
+ }
+ return ssl3_VersionIsSupportedByCode(protocolVariant, version);
}
const SECItem *
@@ -2313,6 +2339,8 @@ SECStatus
SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
SSLVersionRange *vrange)
{
+ SECStatus rv;
+
if (!vrange) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -2320,15 +2348,15 @@ SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
switch (protocolVariant) {
case ssl_variant_stream:
- vrange->min = SSL_LIBRARY_VERSION_3_0;
+ vrange->min = SSL_LIBRARY_VERSION_MIN_SUPPORTED_STREAM;
vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
- // We don't allow SSLv3 and TLSv1.3 together.
- if (vrange->max == SSL_LIBRARY_VERSION_TLS_1_3) {
- vrange->min = SSL_LIBRARY_VERSION_TLS_1_0;
- }
+ /* We don't allow SSLv3 and TLSv1.3 together.
+ * However, don't check yet, apply the policy first.
+ * Because if the effective supported range doesn't use TLS 1.3,
+ * then we don't need to increase the minimum. */
break;
case ssl_variant_datagram:
- vrange->min = SSL_LIBRARY_VERSION_TLS_1_1;
+ vrange->min = SSL_LIBRARY_VERSION_MIN_SUPPORTED_DATAGRAM;
vrange->max = SSL_LIBRARY_VERSION_MAX_SUPPORTED;
break;
default:
@@ -2336,6 +2364,17 @@ SSL_VersionRangeGetSupported(SSLProtocolVariant protocolVariant,
return SECFailure;
}
+ rv = ssl3_CreateOverlapWithPolicy(protocolVariant, vrange, vrange);
+ if (rv != SECSuccess) {
+ /* Library default and policy don't overlap. */
+ return rv;
+ }
+
+ /* We don't allow SSLv3 and TLSv1.3 together */
+ if (vrange->max >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
+ }
+
return SECSuccess;
}
@@ -2351,6 +2390,43 @@ SSL_VersionRangeGetDefault(SSLProtocolVariant protocolVariant,
}
*vrange = *VERSIONS_DEFAULTS(protocolVariant);
+ return ssl3_CreateOverlapWithPolicy(protocolVariant, vrange, vrange);
+}
+
+static PRBool
+ssl3_HasConflictingSSLVersions(const SSLVersionRange *vrange)
+{
+ return (vrange->min <= SSL_LIBRARY_VERSION_3_0 &&
+ vrange->max >= SSL_LIBRARY_VERSION_TLS_1_3);
+}
+
+static SECStatus
+ssl3_CheckRangeValidAndConstrainByPolicy(SSLProtocolVariant protocolVariant,
+ SSLVersionRange *vrange)
+{
+ SECStatus rv;
+
+ if (vrange->min > vrange->max ||
+ !ssl3_VersionIsSupportedByCode(protocolVariant, vrange->min) ||
+ !ssl3_VersionIsSupportedByCode(protocolVariant, vrange->max) ||
+ ssl3_HasConflictingSSLVersions(vrange)) {
+ PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
+ return SECFailure;
+ }
+
+ /* Try to adjust the received range using our policy.
+ * If there's overlap, we'll use the (possibly reduced) range.
+ * If there isn't overlap, it's failure. */
+
+ rv = ssl3_CreateOverlapWithPolicy(protocolVariant, vrange, vrange);
+ if (rv != SECSuccess) {
+ return rv;
+ }
+
+ /* We don't allow SSLv3 and TLSv1.3 together */
+ if (vrange->max >= SSL_LIBRARY_VERSION_TLS_1_3) {
+ vrange->min = PR_MAX(vrange->min, SSL_LIBRARY_VERSION_TLS_1_0);
+ }
return SECSuccess;
}
@@ -2359,13 +2435,21 @@ SECStatus
SSL_VersionRangeSetDefault(SSLProtocolVariant protocolVariant,
const SSLVersionRange *vrange)
{
- if (!ssl3_VersionRangeIsValid(protocolVariant, vrange)) {
- PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
+ SSLVersionRange constrainedRange;
+ SECStatus rv;
+
+ if (!vrange) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
- *VERSIONS_DEFAULTS(protocolVariant) = *vrange;
+ constrainedRange = *vrange;
+ rv = ssl3_CheckRangeValidAndConstrainByPolicy(protocolVariant,
+ &constrainedRange);
+ if (rv != SECSuccess)
+ return rv;
+ *VERSIONS_DEFAULTS(protocolVariant) = constrainedRange;
return SECSuccess;
}
@@ -2393,24 +2477,33 @@ SSL_VersionRangeGet(PRFileDesc *fd, SSLVersionRange *vrange)
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
- return SECSuccess;
+ return ssl3_CreateOverlapWithPolicy(ss->protocolVariant, vrange, vrange);
}
SECStatus
SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
{
- sslSocket *ss = ssl_FindSocket(fd);
+ SSLVersionRange constrainedRange;
+ sslSocket *ss;
+ SECStatus rv;
+
+ if (!vrange) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ ss = ssl_FindSocket(fd);
if (!ss) {
SSL_DBG(("%d: SSL[%d]: bad socket in SSL_VersionRangeSet",
SSL_GETPID(), fd));
return SECFailure;
}
- if (!ssl3_VersionRangeIsValid(ss->protocolVariant, vrange)) {
- PORT_SetError(SSL_ERROR_INVALID_VERSION_RANGE);
- return SECFailure;
- }
+ constrainedRange = *vrange;
+ rv = ssl3_CheckRangeValidAndConstrainByPolicy(ss->protocolVariant,
+ &constrainedRange);
+ if (rv != SECSuccess)
+ return rv;
ssl_Get1stHandshakeLock(ss);
ssl_GetSSL3HandshakeLock(ss);
@@ -2423,7 +2516,7 @@ SSL_VersionRangeSet(PRFileDesc *fd, const SSLVersionRange *vrange)
return SECFailure;
}
- ss->vrange = *vrange;
+ ss->vrange = constrainedRange;
ssl_ReleaseSSL3HandshakeLock(ss);
ssl_Release1stHandshakeLock(ss);
@@ -3672,7 +3765,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
ss->opt.noLocks = !makeLocks;
ss->vrange = *VERSIONS_DEFAULTS(protocolVariant);
ss->protocolVariant = protocolVariant;
-
+ /* Ignore overlap failures, because returning NULL would trigger assertion
+ * failures elsewhere. We don't want this scenario to be fatal, it's just
+ * a state where no SSL connectivity is possible. */
+ ssl3_CreateOverlapWithPolicy(ss->protocolVariant, &ss->vrange, &ss->vrange);
ss->peerID = NULL;
ss->rTimeout = PR_INTERVAL_NO_TIMEOUT;
ss->wTimeout = PR_INTERVAL_NO_TIMEOUT;
@@ -3690,6 +3786,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant)
ss->sniSocketConfig = NULL;
ss->sniSocketConfigArg = NULL;
ss->getClientAuthData = NULL;
+ ss->alertReceivedCallback = NULL;
+ ss->alertReceivedCallbackArg = NULL;
+ ss->alertSentCallback = NULL;
+ ss->alertSentCallbackArg = NULL;
ss->handleBadCert = NULL;
ss->badCertArg = NULL;
ss->pkcs11PinArg = NULL;