$OpenBSD$ index 43bb013..b6fe0fd 100644 --- security/manager/ssl/src/nsNSSIOLayer.cpp.orig Fri Feb 20 15:40:38 2015 +++ security/manager/ssl/src/nsNSSIOLayer.cpp Fri Feb 20 15:40:38 2015 @@ -956,6 +956,17 @@ retryDueToTLSIntolerance(PRErrorCode err, nsNSSSocketInfo* socketInfo) uint32_t reason; switch (err) { + case SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT: + // This is a clear signal that we've fallen back too many versions. Treat + // this as a hard failure now, but also mark the next higher version as + // being tolerant so that later attempts don't use this version (i.e., + // range.max), which makes the error unrecoverable without a full restart. + socketInfo->SharedState().IOLayerHelpers() + .rememberTolerantAtVersion(socketInfo->GetHostName(), + socketInfo->GetPort(), + range.max + 1); + return false; + case SSL_ERROR_BAD_MAC_ALERT: reason = 1; break; case SSL_ERROR_BAD_MAC_READ: reason = 2; break; case SSL_ERROR_HANDSHAKE_FAILURE_ALERT: reason = 3; break; @@ -1598,8 +1609,7 @@ nsresult nsSSLIOLayerNewSocket(int32_t family, const char* host, int32_t port, - const char* proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, PRFileDesc** fd, nsISupports** info, bool forSTARTTLS, @@ -1609,7 +1619,7 @@ nsSSLIOLayerNewSocket(int32_t family, PRFileDesc* sock = PR_OpenTCPSocket(family); if (!sock) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort, + nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxy, sock, info, forSTARTTLS, flags); if (NS_FAILED(rv)) { PR_Close(sock); @@ -1723,16 +1733,16 @@ nsGetUserCertChoice(SSM_UserCertChoice* certChoice) { char* mode = nullptr; nsresult ret; - + NS_ENSURE_ARG_POINTER(certChoice); - + nsCOMPtr pref = do_GetService(NS_PREFSERVICE_CONTRACTID); - + ret = pref->GetCharPref("security.default_personal_cert", &mode); if (NS_FAILED(ret)) { goto loser; } - + if (PL_strcmp(mode, "Select Automatically") == 0) { *certChoice = AUTO; } else if (PL_strcmp(mode, "Ask Every Time") == 0) { @@ -2274,11 +2284,11 @@ loser: static nsresult nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS, - const char* proxyHost, const char* host, int32_t port, + bool haveProxy, const char* host, int32_t port, nsNSSSocketInfo* infoObject) { nsNSSShutDownPreventionLock locker; - if (forSTARTTLS || proxyHost) { + if (forSTARTTLS || haveProxy) { if (SECSuccess != SSL_OptionSet(fd, SSL_SECURITY, false)) { return NS_ERROR_FAILURE; } @@ -2294,6 +2304,8 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS, return NS_ERROR_FAILURE; } + uint16_t maxEnabledVersion = range.max; + infoObject->SharedState().IOLayerHelpers() .adjustForTLSIntolerance(infoObject->GetHostName(), infoObject->GetPort(), range); @@ -2307,6 +2319,16 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS, } infoObject->SetTLSVersionRange(range); + // when adjustForTLSIntolerance tweaks the maximum version downward, + // we tell the server using this SCSV so they can detect a downgrade attack + if (range.max < maxEnabledVersion) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("[%p] nsSSLIOLayerSetOptions: enabling TLS_FALLBACK_SCSV\n", fd)); + if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_FALLBACK_SCSV, true)) { + return NS_ERROR_FAILURE; + } + } + bool enabled = infoObject->SharedState().IsOCSPStaplingEnabled(); if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_OCSP_STAPLING, enabled)) { return NS_ERROR_FAILURE; @@ -2350,8 +2372,7 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port, - const char* proxyHost, - int32_t proxyPort, + nsIProxyInfo* proxy, PRFileDesc* fd, nsISupports** info, bool forSTARTTLS, @@ -2373,6 +2394,13 @@ nsSSLIOLayerAddToSocket(int32_t family, infoObject->SetHostName(host); infoObject->SetPort(port); + bool haveProxy = false; + if (proxy) { + nsCString proxyHost; + proxy->GetHost(proxyHost); + haveProxy = !proxyHost.IsEmpty(); + } + // A plaintext observer shim is inserted so we can observe some protocol // details without modifying nss plaintextLayer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity, @@ -2394,7 +2422,7 @@ nsSSLIOLayerAddToSocket(int32_t family, infoObject->SetFileDescPtr(sslSock); - rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port, + rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host, port, infoObject); if (NS_FAILED(rv)) @@ -2419,7 +2447,7 @@ nsSSLIOLayerAddToSocket(int32_t family, infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info)); // We are going use a clear connection first // - if (forSTARTTLS || proxyHost) { + if (forSTARTTLS || haveProxy) { infoObject->SetHandshakeNotPending(); }