From e006a137519563ca7e67fbbd7f4a839c9eb22995 Mon Sep 17 00:00:00 2001 From: "bjarne@runitsoft.com" Date: Tue, 17 Feb 2009 14:06:52 -0800 Subject: [PATCH] Bug 466080 - Make more things honor the LOAD_ANONYMOUS flag r=sicking,MisterSSL, sr=sicking --- netwerk/base/public/nsISocketTransport.idl | 8 +++++ netwerk/base/src/nsSocketTransport2.cpp | 5 ++- netwerk/protocol/http/src/nsHttp.h | 4 +++ netwerk/protocol/http/src/nsHttpChannel.cpp | 5 +++ .../protocol/http/src/nsHttpConnection.cpp | 8 ++++- netwerk/socket/base/nsISocketProvider.idl | 9 +++++ security/manager/ssl/src/nsNSSIOLayer.cpp | 34 ++++++++++++++----- security/manager/ssl/src/nsNSSIOLayer.h | 6 ++-- .../manager/ssl/src/nsSSLSocketProvider.cpp | 6 ++-- .../manager/ssl/src/nsTLSSocketProvider.cpp | 6 ++-- 10 files changed, 74 insertions(+), 17 deletions(-) diff --git a/netwerk/base/public/nsISocketTransport.idl b/netwerk/base/public/nsISocketTransport.idl index 5af0ddbae22b..5d4b591a441e 100644 --- a/netwerk/base/public/nsISocketTransport.idl +++ b/netwerk/base/public/nsISocketTransport.idl @@ -150,6 +150,14 @@ interface nsISocketTransport : nsITransport */ const unsigned long BYPASS_CACHE = (1 << 0); + /** + * When setting this flag, the socket will not apply any + * credentials when establishing a connection. For example, + * an SSL connection would not send any client-certificates + * if this flag is set. + */ + const unsigned long ANONYMOUS_CONNECT = (1 << 1); + }; %{C++ diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp index 86a18b1ae524..e528163b13cb 100644 --- a/netwerk/base/src/nsSocketTransport2.cpp +++ b/netwerk/base/src/nsSocketTransport2.cpp @@ -1002,6 +1002,9 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool if (mProxyTransparentResolvesHost) proxyFlags |= nsISocketProvider::PROXY_RESOLVES_HOST; + + if (mConnectionFlags & nsISocketTransport::ANONYMOUS_CONNECT) + proxyFlags |= nsISocketProvider::ANONYMOUS_CONNECT; nsCOMPtr secinfo; if (i == 0) { @@ -1026,7 +1029,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, PRBool &proxyTransparent, PRBool proxyFlags, fd, getter_AddRefs(secinfo)); } - proxyFlags = 0; + // proxyFlags = 0; not used below this point... if (NS_FAILED(rv)) break; diff --git a/netwerk/protocol/http/src/nsHttp.h b/netwerk/protocol/http/src/nsHttp.h index ab167e75fa71..78aeadfe756f 100644 --- a/netwerk/protocol/http/src/nsHttp.h +++ b/netwerk/protocol/http/src/nsHttp.h @@ -108,6 +108,10 @@ typedef PRUint8 nsHttpVersion; // bypass the local DNS cache #define NS_HTTP_REFRESH_DNS (1<<3) +// a transaction with this caps flag will not pass SSL client-certificates +// to the server (see bug #466080), but is may also be used for other things +#define NS_HTTP_LOAD_ANONYMOUS (1<<4) + //----------------------------------------------------------------------------- // some default values //----------------------------------------------------------------------------- diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index 21ddb8160794..e3595559ae93 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -673,6 +673,11 @@ nsHttpChannel::SetupTransaction() return NS_ERROR_OUT_OF_MEMORY; NS_ADDREF(mTransaction); + // See bug #466080. Transfer LOAD_ANONYMOUS flag to socket-layer. + if (mLoadFlags & LOAD_ANONYMOUS) { + mCaps |= NS_HTTP_LOAD_ANONYMOUS; + } + nsCOMPtr responseStream; rv = mTransaction->Init(mCaps, mConnectionInfo, &mRequestHead, mUploadStream, mUploadStreamHasHeaders, diff --git a/netwerk/protocol/http/src/nsHttpConnection.cpp b/netwerk/protocol/http/src/nsHttpConnection.cpp index fbea4ff8cb24..2c18c0350dbf 100644 --- a/netwerk/protocol/http/src/nsHttpConnection.cpp +++ b/netwerk/protocol/http/src/nsHttpConnection.cpp @@ -452,8 +452,14 @@ nsHttpConnection::CreateTransport(PRUint8 caps) getter_AddRefs(strans)); if (NS_FAILED(rv)) return rv; + PRUint32 tmpFlags = 0; if (caps & NS_HTTP_REFRESH_DNS) - strans->SetConnectionFlags(nsISocketTransport::BYPASS_CACHE); + tmpFlags = nsISocketTransport::BYPASS_CACHE; + + if (caps & NS_HTTP_LOAD_ANONYMOUS) + tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT; + + strans->SetConnectionFlags(tmpFlags); // NOTE: these create cyclical references, which we break inside // nsHttpConnection::Close diff --git a/netwerk/socket/base/nsISocketProvider.idl b/netwerk/socket/base/nsISocketProvider.idl index fd6127982cc1..ecebec26f2f7 100644 --- a/netwerk/socket/base/nsISocketProvider.idl +++ b/netwerk/socket/base/nsISocketProvider.idl @@ -106,6 +106,15 @@ interface nsISocketProvider : nsISupports * later connect et al. request. */ const long PROXY_RESOLVES_HOST = 1 << 0; + + /** + * When setting this flag, the socket will not apply any + * credentials when establishing a connection. For example, + * an SSL connection would not send any client-certificates + * if this flag is set. + */ + const long ANONYMOUS_CONNECT = 1 << 1; + }; %{C++ diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 2f549ae84c92..c0f0cc2db635 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -2004,14 +2004,15 @@ nsSSLIOLayerNewSocket(PRInt32 family, PRInt32 proxyPort, PRFileDesc **fd, nsISupports** info, - PRBool forSTARTTLS) + PRBool forSTARTTLS, + PRBool anonymousLoad) { PRFileDesc* sock = PR_OpenTCPSocket(family); if (!sock) return NS_ERROR_OUT_OF_MEMORY; nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxyHost, proxyPort, - sock, info, forSTARTTLS); + sock, info, forSTARTTLS, anonymousLoad); if (NS_FAILED(rv)) { PR_Close(sock); return rv; @@ -3118,7 +3119,8 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) static PRFileDesc* nsSSLIOLayerImportFD(PRFileDesc *fd, nsNSSSocketInfo *infoObject, - const char *host) + const char *host, + PRBool anonymousLoad) { nsNSSShutDownPreventionLock locker; PRFileDesc* sslSock = SSL_ImportFD(nsnull, fd); @@ -3128,9 +3130,15 @@ nsSSLIOLayerImportFD(PRFileDesc *fd, } SSL_SetPKCS11PinArg(sslSock, (nsIInterfaceRequestor*)infoObject); SSL_HandshakeCallback(sslSock, HandshakeCallback, infoObject); - SSL_GetClientAuthDataHook(sslSock, + + // Disable this hook if we connect anonymously. See bug 466080. + if (anonymousLoad) { + SSL_GetClientAuthDataHook(sslSock, NULL, infoObject); + } else { + SSL_GetClientAuthDataHook(sslSock, (SSLGetClientAuthData)nsNSS_SSLGetClientAuthData, infoObject); + } SSL_AuthCertificateHook(sslSock, AuthCertificateCallback, 0); PRInt32 ret = SSL_SetURL(sslSock, host); @@ -3149,7 +3157,7 @@ loser: static nsresult nsSSLIOLayerSetOptions(PRFileDesc *fd, PRBool forSTARTTLS, const char *proxyHost, const char *host, PRInt32 port, - nsNSSSocketInfo *infoObject) + PRBool anonymousLoad, nsNSSSocketInfo *infoObject) { nsNSSShutDownPreventionLock locker; if (forSTARTTLS || proxyHost) { @@ -3200,7 +3208,13 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, PRBool forSTARTTLS, } // Set the Peer ID so that SSL proxy connections work properly. - char *peerId = PR_smprintf("%s:%d", host, port); + char *peerId; + if (anonymousLoad) { // See bug #466080. Separate the caches. + peerId = PR_smprintf("anon:%s:%d", host, port); + } else { + peerId = PR_smprintf("%s:%d", host, port); + } + if (SECSuccess != SSL_SetSockPeerID(fd, peerId)) { PR_smprintf_free(peerId); return NS_ERROR_FAILURE; @@ -3218,7 +3232,8 @@ nsSSLIOLayerAddToSocket(PRInt32 family, PRInt32 proxyPort, PRFileDesc* fd, nsISupports** info, - PRBool forSTARTTLS) + PRBool forSTARTTLS, + PRBool anonymousLoad) { nsNSSShutDownPreventionLock locker; PRFileDesc* layer = nsnull; @@ -3232,7 +3247,7 @@ nsSSLIOLayerAddToSocket(PRInt32 family, infoObject->SetHostName(host); infoObject->SetPort(port); - PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host); + PRFileDesc *sslSock = nsSSLIOLayerImportFD(fd, infoObject, host, anonymousLoad); if (!sslSock) { NS_ASSERTION(PR_FALSE, "NSS: Error importing socket"); goto loser; @@ -3240,7 +3255,8 @@ nsSSLIOLayerAddToSocket(PRInt32 family, infoObject->SetFileDescPtr(sslSock); - rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port, + rv = nsSSLIOLayerSetOptions(sslSock, + forSTARTTLS, proxyHost, host, port, anonymousLoad, infoObject); if (NS_FAILED(rv)) diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index b530d98f9f89..21f9c28b9f0f 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -272,7 +272,8 @@ nsresult nsSSLIOLayerNewSocket(PRInt32 family, PRInt32 proxyPort, PRFileDesc **fd, nsISupports **securityInfo, - PRBool forSTARTTLS); + PRBool forSTARTTLS, + PRBool anonymousLoad); nsresult nsSSLIOLayerAddToSocket(PRInt32 family, const char *host, @@ -281,7 +282,8 @@ nsresult nsSSLIOLayerAddToSocket(PRInt32 family, PRInt32 proxyPort, PRFileDesc *fd, nsISupports **securityInfo, - PRBool forSTARTTLS); + PRBool forSTARTTLS, + PRBool anonymousLoad); nsresult nsSSLIOLayerFreeTLSIntolerantSites(); nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo *infoObject, int error); diff --git a/security/manager/ssl/src/nsSSLSocketProvider.cpp b/security/manager/ssl/src/nsSSLSocketProvider.cpp index e88793f9fd33..90f8e1a3fb72 100644 --- a/security/manager/ssl/src/nsSSLSocketProvider.cpp +++ b/security/manager/ssl/src/nsSSLSocketProvider.cpp @@ -68,7 +68,8 @@ nsSSLSocketProvider::NewSocket(PRInt32 family, proxyPort, _result, securityInfo, - PR_FALSE); + PR_FALSE, + flags & ANONYMOUS_CONNECT); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; } @@ -90,7 +91,8 @@ nsSSLSocketProvider::AddToSocket(PRInt32 family, proxyPort, aSocket, securityInfo, - PR_FALSE); + PR_FALSE, + flags & ANONYMOUS_CONNECT); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; } diff --git a/security/manager/ssl/src/nsTLSSocketProvider.cpp b/security/manager/ssl/src/nsTLSSocketProvider.cpp index 5e34748098b1..e3bb8f8a9a46 100644 --- a/security/manager/ssl/src/nsTLSSocketProvider.cpp +++ b/security/manager/ssl/src/nsTLSSocketProvider.cpp @@ -68,7 +68,8 @@ nsTLSSocketProvider::NewSocket(PRInt32 family, proxyPort, _result, securityInfo, - PR_TRUE); + PR_TRUE, + flags & ANONYMOUS_CONNECT); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; } @@ -91,7 +92,8 @@ nsTLSSocketProvider::AddToSocket(PRInt32 family, proxyPort, aSocket, securityInfo, - PR_TRUE); + PR_TRUE, + flags & ANONYMOUS_CONNECT); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; }