From 235b069e725b7b94a1d22f893f23467be0fd06a8 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Wed, 20 Aug 2014 16:30:16 -0400 Subject: [PATCH] bug 1003448 - HTTP/2 Alternate Service and Opportunistic Security [1/2 PSM] r=keeler --- netwerk/socket/nsISSLSocketControl.idl | 28 +++++- .../ssl/src/SSLServerCertVerification.cpp | 12 ++- security/manager/ssl/src/nsNSSIOLayer.cpp | 92 +++++++++++++++---- security/manager/ssl/src/nsNSSIOLayer.h | 18 ++++ 4 files changed, 131 insertions(+), 19 deletions(-) diff --git a/netwerk/socket/nsISSLSocketControl.idl b/netwerk/socket/nsISSLSocketControl.idl index 0288172dd0fc..4bbf08af638f 100644 --- a/netwerk/socket/nsISSLSocketControl.idl +++ b/netwerk/socket/nsISSLSocketControl.idl @@ -15,7 +15,7 @@ class nsCString; %} [ref] native nsCStringTArrayRef(nsTArray); -[scriptable, builtinclass, uuid(89b819dc-31b0-4d09-915a-66f8a3703483)] +[scriptable, builtinclass, uuid(f160ec31-01f3-47f2-b542-0e12a647b07f)] interface nsISSLSocketControl : nsISupports { attribute nsIInterfaceRequestor notificationCallbacks; @@ -53,6 +53,11 @@ interface nsISSLSocketControl : nsISupports { in ACString hostname, in long port); + /* Determine if existing connection should be trusted to convey information about + * a hostname. + */ + boolean isAcceptableForHost(in ACString hostname); + /* The Key Exchange Algorithm is used when determining whether or not to do false start and whether or not HTTP/2 can be used. @@ -103,5 +108,26 @@ interface nsISSLSocketControl : nsISupports { * the user or searching the set of rememebered user cert decisions. */ attribute nsIX509Cert clientCert; + + /** + * If you wish to verify the host certificate using a different name than + * was used for the tcp connection, but without using proxy semantics, you + * can set authenticationName and authenticationPort + */ + attribute ACString authenticationName; + [infallible] attribute long authenticationPort; + + /** + * set bypassAuthentication to true if the server certificate checks should + * not be enforced. This is to enable non-secure transport over TLS. + */ + [infallible] attribute boolean bypassAuthentication; + + /* + * failedVerification is true if any enforced certificate checks have failed. + * Connections that have not yet tried to verify, have verifications bypassed, + * or are using acceptable exceptions will all return false. + */ + [infallible] readonly attribute boolean failedVerification; }; diff --git a/security/manager/ssl/src/SSLServerCertVerification.cpp b/security/manager/ssl/src/SSLServerCertVerification.cpp index 41ee6b9fd830..224d008480b4 100644 --- a/security/manager/ssl/src/SSLServerCertVerification.cpp +++ b/security/manager/ssl/src/SSLServerCertVerification.cpp @@ -400,6 +400,16 @@ CertErrorRunnable::CheckCertOverrides() mDefaultErrorCodeToReport); } + nsCOMPtr sslSocketControl = do_QueryInterface( + NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject)); + if (sslSocketControl && + sslSocketControl->GetBypassAuthentication()) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("[%p][%p] Bypass Auth in CheckCertOverrides\n", + mFdForLogging, this)); + return new SSLServerCertVerificationResult(mInfoObject, 0); + } + int32_t port; mInfoObject->GetPort(&port); @@ -490,8 +500,6 @@ CertErrorRunnable::CheckCertOverrides() // First, deliver the technical details of the broken SSL status. // Try to get a nsIBadCertListener2 implementation from the socket consumer. - nsCOMPtr sslSocketControl = do_QueryInterface( - NS_ISUPPORTS_CAST(nsITransportSecurityInfo*, mInfoObject)); if (sslSocketControl) { nsCOMPtr cb; sslSocketControl->GetNotificationCallbacks(getter_AddRefs(cb)); diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 1150697ec658..0a1089e0d722 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -132,11 +132,13 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags) mJoined(false), mSentClientCert(false), mNotedTimeUntilReady(false), + mFailedVerification(false), mKEAUsed(nsISSLSocketControl::KEY_EXCHANGE_UNKNOWN), mKEAExpected(nsISSLSocketControl::KEY_EXCHANGE_UNKNOWN), mKEAKeyBits(0), mSSLVersionUsed(nsISSLSocketControl::SSL_VERSION_UNKNOWN), mMACAlgorithmUsed(nsISSLSocketControl::SSL_MAC_UNKNOWN), + mBypassAuthentication(false), mProviderFlags(providerFlags), mSocketCreationTimestamp(TimeStamp::Now()), mPlaintextBytesRead(0), @@ -226,6 +228,52 @@ nsNSSSocketInfo::SetClientCert(nsIX509Cert* aClientCert) return NS_OK; } +NS_IMETHODIMP +nsNSSSocketInfo::GetBypassAuthentication(bool* arg) +{ + *arg = mBypassAuthentication; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSSocketInfo::SetBypassAuthentication(bool arg) +{ + mBypassAuthentication = arg; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSSocketInfo::GetFailedVerification(bool* arg) +{ + *arg = mFailedVerification; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSSocketInfo::GetAuthenticationName(nsACString& aAuthenticationName) +{ + aAuthenticationName = GetHostName(); + return NS_OK; +} + +NS_IMETHODIMP +nsNSSSocketInfo::SetAuthenticationName(const nsACString& aAuthenticationName) +{ + return SetHostName(PromiseFlatCString(aAuthenticationName).get()); +} + +NS_IMETHODIMP +nsNSSSocketInfo::GetAuthenticationPort(int32_t* aAuthenticationPort) +{ + return GetPort(aAuthenticationPort); +} + +NS_IMETHODIMP +nsNSSSocketInfo::SetAuthenticationPort(int32_t aAuthenticationPort) +{ + return SetPort(aAuthenticationPort); +} + NS_IMETHODIMP nsNSSSocketInfo::GetRememberClientAuthCertificate(bool* aRemember) { @@ -378,21 +426,8 @@ nsNSSSocketInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN) } NS_IMETHODIMP -nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol, - const nsACString& hostname, - int32_t port, - bool* _retval) +nsNSSSocketInfo::IsAcceptableForHost(const nsACString& hostname, bool* _retval) { - *_retval = false; - - // Different ports may not be joined together - if (port != GetPort()) - return NS_OK; - - // Make sure NPN has been completed and matches requested npnProtocol - if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol)) - return NS_OK; - // If this is the same hostname then the certicate status does not // need to be considered. They are joinable. if (hostname.Equals(GetHostName())) { @@ -462,12 +497,36 @@ nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol, return NS_OK; } - // All tests pass - this is joinable - mJoined = true; + // All tests pass *_retval = true; return NS_OK; } +NS_IMETHODIMP +nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol, + const nsACString& hostname, + int32_t port, + bool* _retval) +{ + *_retval = false; + + // Different ports may not be joined together + if (port != GetPort()) + return NS_OK; + + // Make sure NPN has been completed and matches requested npnProtocol + if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol)) + return NS_OK; + + IsAcceptableForHost(hostname, _retval); + + if (*_retval) { + // All tests pass - this is joinable + mJoined = true; + } + return NS_OK; +} + bool nsNSSSocketInfo::GetForSTARTTLS() { @@ -632,6 +691,7 @@ nsNSSSocketInfo::SetCertVerificationResult(PRErrorCode errorCode, } if (errorCode) { + mFailedVerification = true; SetCanceled(errorCode, errorMessageType); } diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 149e0f71b666..4c7f8dd02031 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -113,6 +113,22 @@ public: void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; } + inline bool GetBypassAuthentication() + { + bool result = false; + mozilla::DebugOnly rv = GetBypassAuthentication(&result); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return result; + } + + inline int32_t GetAuthenticationPort() + { + int32_t result = -1; + mozilla::DebugOnly rv = GetAuthenticationPort(&result); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + return result; + } + protected: virtual ~nsNSSSocketInfo(); @@ -139,6 +155,7 @@ private: bool mJoined; bool mSentClientCert; bool mNotedTimeUntilReady; + bool mFailedVerification; // mKEA* are used in false start and http/2 detetermination // Values are from nsISSLSocketControl @@ -147,6 +164,7 @@ private: uint32_t mKEAKeyBits; int16_t mSSLVersionUsed; int16_t mMACAlgorithmUsed; + bool mBypassAuthentication; uint32_t mProviderFlags; mozilla::TimeStamp mSocketCreationTimestamp;