author | Ben Bucksch <ben.bucksch@beonex.com> |
Tue, 24 Nov 2015 22:56:00 +0100 (2015-11-24) | |
changeset 274211 | 76cee391a698d2dcea75600b34fc04ddff7ea000 |
parent 274210 | 82c89f573e53c851f912e4d8f64278e1a398c87d |
child 274212 | ebb6fb453ccaf38e34add4fa109dc01bedaaab31 |
push id | 29727 |
push user | cbook@mozilla.com |
push date | Thu, 26 Nov 2015 15:54:54 +0000 (2015-11-26) |
treeherder | mozilla-central@74c7941a9e22 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | michal |
bugs | 1200802 |
milestone | 45.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/netwerk/base/nsIProtocolProxyService.idl +++ b/netwerk/base/nsIProtocolProxyService.idl @@ -13,17 +13,17 @@ interface nsIProtocolProxyChannelFilter; interface nsIProxyInfo; interface nsIChannel; interface nsIURI; /** * nsIProtocolProxyService provides methods to access information about * various network proxies. */ -[scriptable, uuid(deec8e08-a246-443c-90b6-f655632d1abf)] +[scriptable, uuid(ef57c8b6-e09d-4cd4-9222-2a5d2402e15d)] interface nsIProtocolProxyService : nsISupports { /** Flag 1 << 0 is unused **/ /** * When the proxy configuration is manual this flag may be passed to the * resolve and asyncResolve methods to request to prefer the SOCKS proxy * to HTTP ones. @@ -135,16 +135,55 @@ interface nsIProtocolProxyService : nsIS * parameter may be null. */ nsIProxyInfo newProxyInfo(in ACString aType, in AUTF8String aHost, in long aPort, in unsigned long aFlags, in unsigned long aFailoverTimeout, in nsIProxyInfo aFailoverProxy); /** + * This method may be called to construct a nsIProxyInfo instance for + * with the specified username and password. + * Currently implemented for SOCKS proxies only. + * @param aType + * The proxy type. This is a string value that identifies the proxy + * type. Standard values include: + * "socks" - specifies a SOCKS version 5 proxy + * "socks4" - specifies a SOCKS version 4 proxy + * The type name is case-insensitive. Other string values may be + * possible, and new types may be defined by a future version of + * this interface. + * @param aHost + * The proxy hostname or IP address. + * @param aPort + * The proxy port. + * @param aUsername + * The proxy username + * @param aPassword + * The proxy password + * @param aFlags + * Flags associated with this connection. See nsIProxyInfo.idl + * for currently defined flags. + * @param aFailoverTimeout + * Specifies the length of time (in seconds) to ignore this proxy if + * this proxy fails. Pass UINT32_MAX to specify the default + * timeout value, causing nsIProxyInfo::failoverTimeout to be + * assigned the default value. + * @param aFailoverProxy + * Specifies the next proxy to try if this proxy fails. This + * parameter may be null. + */ + nsIProxyInfo newProxyInfoWithAuth(in ACString aType, in AUTF8String aHost, + in long aPort, + in ACString aUsername, in ACString aPassword, + in unsigned long aFlags, + in unsigned long aFailoverTimeout, + in nsIProxyInfo aFailoverProxy); + + /** * If the proxy identified by aProxyInfo is unavailable for some reason, * this method may be called to access an alternate proxy that may be used * instead. As a side-effect, this method may affect future result values * from resolve/asyncResolve as well as from getFailoverForProxy. * * @param aProxyInfo * The proxy that was unavailable. * @param aURI
--- a/netwerk/base/nsIProxyInfo.idl +++ b/netwerk/base/nsIProxyInfo.idl @@ -3,17 +3,17 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" /** * This interface identifies a proxy server. */ -[scriptable, uuid(9e557d99-7af0-4895-95b7-e6dba28c9ad9)] +[scriptable, uuid(63fff172-2564-4138-96c6-3ae7d245fbed)] interface nsIProxyInfo : nsISupports { /** * This attribute specifies the hostname of the proxy server. */ readonly attribute AUTF8String host; /** @@ -46,16 +46,26 @@ interface nsIProxyInfo : nsISupports /** * This attribute specifies flags that were used by nsIProxyProtocolService when * creating this ProxyInfo element. */ readonly attribute unsigned long resolveFlags; /** + * Specifies a proxy username. + */ + readonly attribute ACString username; + + /** + * Specifies a proxy password. + */ + readonly attribute ACString password; + + /** * This attribute specifies the failover timeout in seconds for this proxy. * If a nsIProxyInfo is reported as failed via nsIProtocolProxyService:: * getFailoverForProxy, then the failed proxy will not be used again for this * many seconds. */ readonly attribute unsigned long failoverTimeout; /**
--- a/netwerk/base/nsProtocolProxyService.cpp +++ b/netwerk/base/nsProtocolProxyService.cpp @@ -1374,16 +1374,33 @@ NS_IMETHODIMP nsProtocolProxyService::NewProxyInfo(const nsACString &aType, const nsACString &aHost, int32_t aPort, uint32_t aFlags, uint32_t aFailoverTimeout, nsIProxyInfo *aFailoverProxy, nsIProxyInfo **aResult) { + return NewProxyInfoWithAuth(aType, aHost, aPort, + EmptyCString(), EmptyCString(), + aFlags, aFailoverTimeout, + aFailoverProxy, aResult); +} + +NS_IMETHODIMP +nsProtocolProxyService::NewProxyInfoWithAuth(const nsACString &aType, + const nsACString &aHost, + int32_t aPort, + const nsACString &aUsername, + const nsACString &aPassword, + uint32_t aFlags, + uint32_t aFailoverTimeout, + nsIProxyInfo *aFailoverProxy, + nsIProxyInfo **aResult) +{ static const char *types[] = { kProxyType_HTTP, kProxyType_HTTPS, kProxyType_SOCKS, kProxyType_SOCKS4, kProxyType_DIRECT }; @@ -1393,20 +1410,26 @@ nsProtocolProxyService::NewProxyInfo(con for (uint32_t i = 0; i < ArrayLength(types); ++i) { if (aType.LowerCaseEqualsASCII(types[i])) { type = types[i]; break; } } NS_ENSURE_TRUE(type, NS_ERROR_INVALID_ARG); - if (aPort <= 0) - aPort = -1; + // We have only implemented username/password for SOCKS proxies. + if ((!aUsername.IsEmpty() || !aPassword.IsEmpty()) && + !aType.LowerCaseEqualsASCII(kProxyType_SOCKS) && + !aType.LowerCaseEqualsASCII(kProxyType_SOCKS4)) { + return NS_ERROR_NOT_IMPLEMENTED; + } - return NewProxyInfo_Internal(type, aHost, aPort, aFlags, aFailoverTimeout, + return NewProxyInfo_Internal(type, aHost, aPort, + aUsername, aPassword, + aFlags, aFailoverTimeout, aFailoverProxy, 0, aResult); } NS_IMETHODIMP nsProtocolProxyService::GetFailoverForProxy(nsIProxyInfo *aProxy, nsIURI *aURI, nsresult aStatus, nsIProxyInfo **aResult) @@ -1712,35 +1735,42 @@ nsProtocolProxyService::GetProtocolInfo( rv = handler->GetDefaultPort(&info->defaultPort); return rv; } nsresult nsProtocolProxyService::NewProxyInfo_Internal(const char *aType, const nsACString &aHost, int32_t aPort, + const nsACString &aUsername, + const nsACString &aPassword, uint32_t aFlags, uint32_t aFailoverTimeout, nsIProxyInfo *aFailoverProxy, uint32_t aResolveFlags, nsIProxyInfo **aResult) { + if (aPort <= 0) + aPort = -1; + nsCOMPtr<nsProxyInfo> failover; if (aFailoverProxy) { failover = do_QueryInterface(aFailoverProxy); NS_ENSURE_ARG(failover); } nsProxyInfo *proxyInfo = new nsProxyInfo(); if (!proxyInfo) return NS_ERROR_OUT_OF_MEMORY; proxyInfo->mType = aType; proxyInfo->mHost = aHost; proxyInfo->mPort = aPort; + proxyInfo->mUsername = aUsername; + proxyInfo->mPassword = aPassword; proxyInfo->mFlags = aFlags; proxyInfo->mResolveFlags = aResolveFlags; proxyInfo->mTimeout = aFailoverTimeout == UINT32_MAX ? mFailedProxyTimeout : aFailoverTimeout; failover.swap(proxyInfo->mNext); NS_ADDREF(*aResult = proxyInfo); return NS_OK; @@ -1899,18 +1929,19 @@ nsProtocolProxyService::Resolve_Internal else type = kProxyType_SOCKS; port = mSOCKSProxyPort; if (mSOCKSProxyRemoteDNS) proxyFlags |= nsIProxyInfo::TRANSPARENT_PROXY_RESOLVES_HOST; } if (type) { - rv = NewProxyInfo_Internal(type, *host, port, proxyFlags, - UINT32_MAX, nullptr, flags, + rv = NewProxyInfo_Internal(type, *host, port, + EmptyCString(), EmptyCString(), + proxyFlags, UINT32_MAX, nullptr, flags, result); if (NS_FAILED(rv)) return rv; } return NS_OK; }
--- a/netwerk/base/nsProtocolProxyService.h +++ b/netwerk/base/nsProtocolProxyService.h @@ -172,30 +172,36 @@ protected: * that expects a string literal for the type. * * @param type * The proxy type. * @param host * The proxy host name (UTF-8 ok). * @param port * The proxy port number. + * @param username + * The username for the proxy (ASCII). May be "", but not null. + * @param password + * The password for the proxy (ASCII). May be "", but not null. * @param flags * The proxy flags (nsIProxyInfo::flags). * @param timeout * The failover timeout for this proxy. * @param next * The next proxy to try if this one fails. * @param aResolveFlags * The flags passed to resolve (from nsIProtocolProxyService). * @param result * The resulting nsIProxyInfo object. */ nsresult NewProxyInfo_Internal(const char *type, const nsACString &host, int32_t port, + const nsACString &username, + const nsACString &password, uint32_t flags, uint32_t timeout, nsIProxyInfo *next, uint32_t aResolveFlags, nsIProxyInfo **result); /** * This method is an internal version of Resolve that does not query PAC.
--- a/netwerk/base/nsProxyInfo.cpp +++ b/netwerk/base/nsProxyInfo.cpp @@ -43,16 +43,30 @@ nsProxyInfo::GetFlags(uint32_t *result) NS_IMETHODIMP nsProxyInfo::GetResolveFlags(uint32_t *result) { *result = mResolveFlags; return NS_OK; } NS_IMETHODIMP +nsProxyInfo::GetUsername(nsACString &result) +{ + result = mUsername; + return NS_OK; +} + +NS_IMETHODIMP +nsProxyInfo::GetPassword(nsACString &result) +{ + result = mPassword; + return NS_OK; +} + +NS_IMETHODIMP nsProxyInfo::GetFailoverTimeout(uint32_t *result) { *result = mTimeout; return NS_OK; } NS_IMETHODIMP nsProxyInfo::GetFailoverProxy(nsIProxyInfo **result)
--- a/netwerk/base/nsProxyInfo.h +++ b/netwerk/base/nsProxyInfo.h @@ -30,16 +30,18 @@ public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSIPROXYINFO // Cheap accessors for use within Necko const nsCString &Host() { return mHost; } int32_t Port() { return mPort; } const char *Type() { return mType; } uint32_t Flags() { return mFlags; } + const nsCString &Username() { return mUsername; } + const nsCString &Password() { return mPassword; } bool IsDirect(); bool IsHTTP(); bool IsHTTPS(); bool IsSOCKS(); private: friend class nsProtocolProxyService; @@ -55,16 +57,18 @@ private: ~nsProxyInfo() { NS_IF_RELEASE(mNext); } const char *mType; // pointer to statically allocated value nsCString mHost; + nsCString mUsername; + nsCString mPassword; int32_t mPort; uint32_t mFlags; uint32_t mResolveFlags; uint32_t mTimeout; nsProxyInfo *mNext; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsProxyInfo, NS_PROXYINFO_IID)
--- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -808,16 +808,17 @@ nsSocketTransport::Init(const char **typ mPort = port; } if (proxyInfo) { mHttpsProxy = proxyInfo->IsHTTPS(); } const char *proxyType = nullptr; + mProxyInfo = proxyInfo; if (proxyInfo) { mProxyPort = proxyInfo->Port(); mProxyHost = proxyInfo->Host(); // grab proxy type (looking for "socks" for example) proxyType = proxyInfo->Type(); if (proxyType && (proxyInfo->IsHTTP() || proxyInfo->IsHTTPS() || proxyInfo->IsDirect() || @@ -1100,18 +1101,17 @@ nsSocketTransport::BuildSocket(PRFileDes do_GetService(kSocketProviderServiceCID, &rv); if (NS_FAILED(rv)) return rv; // by setting host to mOriginHost, instead of mHost we send the // SocketProvider (e.g. PSM) the origin hostname but can still do DNS // on an explicit alternate service host name const char *host = mOriginHost.get(); int32_t port = (int32_t) mOriginPort; - const char *proxyHost = mProxyHost.IsEmpty() ? nullptr : mProxyHost.get(); - int32_t proxyPort = (int32_t) mProxyPort; + nsCOMPtr<nsIProxyInfo> proxyInfo = mProxyInfo; uint32_t controlFlags = 0; uint32_t i; for (i=0; i<mTypeCount; ++i) { nsCOMPtr<nsISocketProvider> provider; SOCKET_LOG((" pushing io layer [%u:%s]\n", i, mTypes[i])); @@ -1135,33 +1135,33 @@ nsSocketTransport::BuildSocket(PRFileDes if (i == 0) { // if this is the first type, we'll want the // service to allocate a new socket // when https proxying we want to just connect to the proxy as if // it were the end host (i.e. expect the proxy's cert) rv = provider->NewSocket(mNetAddr.raw.family, - mHttpsProxy ? proxyHost : host, - mHttpsProxy ? proxyPort : port, - proxyHost, proxyPort, + mHttpsProxy ? mProxyHost.get() : host, + mHttpsProxy ? mProxyPort : port, + proxyInfo, controlFlags, &fd, getter_AddRefs(secinfo)); if (NS_SUCCEEDED(rv) && !fd) { NS_NOTREACHED("NewSocket succeeded but failed to create a PRFileDesc"); rv = NS_ERROR_UNEXPECTED; } } else { // the socket has already been allocated, // so we just want the service to add itself // to the stack (such as pushing an io layer) rv = provider->AddToSocket(mNetAddr.raw.family, - host, port, proxyHost, proxyPort, + host, port, proxyInfo, controlFlags, fd, getter_AddRefs(secinfo)); } // controlFlags = 0; not used below this point... if (NS_FAILED(rv)) break; // if the service was ssl or starttls, we want to hold onto the socket info @@ -1181,18 +1181,17 @@ nsSocketTransport::BuildSocket(PRFileDes secCtrl->SetNotificationCallbacks(callbacks); // remember if socket type is SSL so we can ProxyStartSSL if need be. usingSSL = isSSL; } else if ((strcmp(mTypes[i], "socks") == 0) || (strcmp(mTypes[i], "socks4") == 0)) { // since socks is transparent, any layers above // it do not have to worry about proxy stuff - proxyHost = nullptr; - proxyPort = -1; + proxyInfo = nullptr; proxyTransparent = true; } } if (NS_FAILED(rv)) { SOCKET_LOG((" error pushing io layer [%u:%s rv=%x]\n", i, mTypes[i], rv)); if (fd) { PR_Close(fd);
--- a/netwerk/base/nsSocketTransport2.h +++ b/netwerk/base/nsSocketTransport2.h @@ -281,16 +281,17 @@ private: // socket type info: char **mTypes; uint32_t mTypeCount; nsCString mHost; nsCString mProxyHost; nsCString mOriginHost; uint16_t mPort; + nsCOMPtr<nsIProxyInfo> mProxyInfo; uint16_t mProxyPort; uint16_t mOriginPort; bool mProxyTransparent; bool mProxyTransparentResolvesHost; bool mHttpsProxy; uint32_t mConnectionFlags; uint16_t SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
--- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -73,17 +73,17 @@ TLSFilterTransaction::TLSFilterTransacti sLayerMethodsPtr = &sLayerMethods; } mFD = PR_CreateIOLayerStub(sLayerIdentity, &sLayerMethods); if (provider && mFD) { mFD->secret = reinterpret_cast<PRFilePrivate *>(this); provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr, - 0, 0, mFD, getter_AddRefs(mSecInfo)); + 0, mFD, getter_AddRefs(mSecInfo)); } if (mTransaction) { nsCOMPtr<nsIInterfaceRequestor> callbacks; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks)); nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(mSecInfo)); if (secCtrl) { secCtrl->SetNotificationCallbacks(callbacks);
--- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp +++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp @@ -11,16 +11,40 @@ #undef LOG #define LOG(args) LOG5(args) #undef LOG_ENABLED #define LOG_ENABLED() LOG5_ENABLED() #include "nsHttpConnectionInfo.h" #include "mozilla/net/DNS.h" #include "prnetdb.h" +#include "nsICryptoHash.h" + +static nsresult +SHA256(const char* aPlainText, nsAutoCString& aResult) +{ + static nsICryptoHash* hasher = nullptr; + nsresult rv; + if (!hasher) { + rv = CallCreateInstance("@mozilla.org/security/hash;1", &hasher); + if (NS_FAILED(rv)) { + LOG(("nsHttpDigestAuth: no crypto hash!\n")); + return rv; + } + } + + rv = hasher->Init(nsICryptoHash::SHA256); + NS_ENSURE_SUCCESS(rv, rv); + + rv = hasher->Update((unsigned char*) aPlainText, strlen(aPlainText)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = hasher->Finish(false, aResult); + return rv; +} namespace mozilla { namespace net { nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &originHost, int32_t originPort, const nsACString &npnToken, const nsACString &username, @@ -146,25 +170,42 @@ void nsHttpConnectionInfo::BuildHashKey( // right protocol even if our proxy preferences change). // // NOTE: for SSL tunnels add the proxy information to the cache key. // We cannot use the proxy as the host parameter (as we do for non SSL) // because this is a single host tunnel, but we need to include the proxy // information so that a change in proxy config will mean this connection // is not reused + // NOTE: Adding the username and the password provides a means to isolate + // keep-alive to the URL bar domain as well: If the username is the URL bar + // domain, keep-alive connections are not reused by resources bound to + // different URL bar domains as the respective hash keys are not matching. + if ((!mUsingHttpProxy && ProxyHost()) || (mUsingHttpProxy && mUsingConnect)) { mHashKey.AppendLiteral(" ("); mHashKey.Append(ProxyType()); mHashKey.Append(':'); mHashKey.Append(ProxyHost()); mHashKey.Append(':'); mHashKey.AppendInt(ProxyPort()); mHashKey.Append(')'); + mHashKey.Append('['); + mHashKey.Append(ProxyUsername()); + mHashKey.Append(':'); + const char* password = ProxyPassword(); + if (strlen(password) > 0) { + nsAutoCString digestedPassword; + nsresult rv = SHA256(password, digestedPassword); + if (rv == NS_OK) { + mHashKey.Append(digestedPassword); + } + } + mHashKey.Append(']'); } if(!mRoutedHost.IsEmpty()) { mHashKey.AppendLiteral(" <ROUTE-via "); mHashKey.Append(mRoutedHost); mHashKey.Append(':'); mHashKey.AppendInt(mRoutedPort); mHashKey.Append('>');
--- a/netwerk/protocol/http/nsHttpConnectionInfo.h +++ b/netwerk/protocol/http/nsHttpConnectionInfo.h @@ -79,16 +79,18 @@ public: // OK to treat these as an infalible allocation nsHttpConnectionInfo* Clone() const; void CloneAsDirectRoute(nsHttpConnectionInfo **outParam); nsresult CreateWildCard(nsHttpConnectionInfo **outParam); const char *ProxyHost() const { return mProxyInfo ? mProxyInfo->Host().get() : nullptr; } int32_t ProxyPort() const { return mProxyInfo ? mProxyInfo->Port() : -1; } const char *ProxyType() const { return mProxyInfo ? mProxyInfo->Type() : nullptr; } + const char *ProxyUsername() const { return mProxyInfo ? mProxyInfo->Username().get() : nullptr; } + const char *ProxyPassword() const { return mProxyInfo ? mProxyInfo->Password().get() : nullptr; } // Compare this connection info to another... // Two connections are 'equal' if they end up talking the same // protocol to the same server. This is needed to properly manage // persistent connections to proxies // Note that we don't care about transparent proxies - // it doesn't matter if we're talking via socks or not, since // a request will end up at the same host.
--- a/netwerk/socket/nsISocketProvider.idl +++ b/netwerk/socket/nsISocketProvider.idl @@ -1,21 +1,22 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" +interface nsIProxyInfo; [ptr] native PRFileDescStar(struct PRFileDesc); /** * nsISocketProvider */ -[scriptable, uuid(00b3df92-e830-11d8-d48e-0004e22243f8)] +[scriptable, uuid(508d5469-9e1e-4a08-b5b0-7cfebba1e51a)] interface nsISocketProvider : nsISupports { /** * newSocket * * @param aFamily * The address family for this socket (PR_AF_INET or PR_AF_INET6). * @param aHost @@ -33,18 +34,17 @@ interface nsISocketProvider : nsISupport * @param aSecurityInfo * Any security info that should be associated with aFileDesc. This * object typically implements nsITransportSecurityInfo. */ [noscript] void newSocket(in long aFamily, in string aHost, in long aPort, - in string aProxyHost, - in long aProxyPort, + in nsIProxyInfo aProxy, in unsigned long aFlags, out PRFileDescStar aFileDesc, out nsISupports aSecurityInfo); /** * addToSocket * * This function is called to allow the socket provider to layer a @@ -53,18 +53,17 @@ interface nsISocketProvider : nsISupport * * Parameters are the same as newSocket with the exception of aFileDesc, * which is an in-param instead. */ [noscript] void addToSocket(in long aFamily, in string aHost, in long aPort, - in string aProxyHost, - in long aProxyPort, + in nsIProxyInfo aProxy, in unsigned long aFlags, in PRFileDescStar aFileDesc, out nsISupports aSecurityInfo); /** * PROXY_RESOLVES_HOST * * This flag is set if the proxy is to perform hostname resolution instead
--- a/netwerk/socket/nsSOCKSIOLayer.cpp +++ b/netwerk/socket/nsSOCKSIOLayer.cpp @@ -42,39 +42,42 @@ class nsSOCKSSocketInfo : public nsISOCK SOCKS_INITIAL, SOCKS_DNS_IN_PROGRESS, SOCKS_DNS_COMPLETE, SOCKS_CONNECTING_TO_PROXY, SOCKS4_WRITE_CONNECT_REQUEST, SOCKS4_READ_CONNECT_RESPONSE, SOCKS5_WRITE_AUTH_REQUEST, SOCKS5_READ_AUTH_RESPONSE, + SOCKS5_WRITE_USERNAME_REQUEST, + SOCKS5_READ_USERNAME_RESPONSE, SOCKS5_WRITE_CONNECT_REQUEST, SOCKS5_READ_CONNECT_RESPONSE_TOP, SOCKS5_READ_CONNECT_RESPONSE_BOTTOM, SOCKS_CONNECTED, SOCKS_FAILED }; - // A buffer of 265 bytes should be enough for any request and response + // A buffer of 520 bytes should be enough for any request and response // in case of SOCKS4 as well as SOCKS5 - static const uint32_t BUFFER_SIZE = 265; + static const uint32_t BUFFER_SIZE = 520; static const uint32_t MAX_HOSTNAME_LEN = 255; + static const uint32_t MAX_USERNAME_LEN = 255; + static const uint32_t MAX_PASSWORD_LEN = 255; public: nsSOCKSSocketInfo(); NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSISOCKSSOCKETINFO NS_DECL_NSIDNSLISTENER void Init(int32_t version, int32_t family, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, const char *destinationHost, uint32_t flags); void SetConnectTimeout(PRIntervalTime to); PRStatus DoHandshake(PRFileDesc *fd, int16_t oflags = -1); int16_t GetPollFlags() const; bool IsConnected() const { return mState == SOCKS_CONNECTED; } void ForgetFD() { mFD = nullptr; } @@ -86,16 +89,18 @@ private: PRStatus StartDNS(PRFileDesc *fd); PRStatus ConnectToProxy(PRFileDesc *fd); void FixupAddressFamily(PRFileDesc *fd, NetAddr *proxy); PRStatus ContinueConnectingToProxy(PRFileDesc *fd, int16_t oflags); PRStatus WriteV4ConnectRequest(); PRStatus ReadV4ConnectResponse(); PRStatus WriteV5AuthRequest(); PRStatus ReadV5AuthResponse(); + PRStatus WriteV5UsernameRequest(); + PRStatus ReadV5UsernameResponse(); PRStatus WriteV5ConnectRequest(); PRStatus ReadV5AddrTypeAndLength(uint8_t *type, uint32_t *len); PRStatus ReadV5ConnectResponseTop(); PRStatus ReadV5ConnectResponseBottom(); uint8_t ReadUint8(); uint16_t ReadUint16(); uint32_t ReadUint32(); @@ -114,34 +119,33 @@ private: uint32_t mReadOffset; uint32_t mAmountToRead; nsCOMPtr<nsIDNSRecord> mDnsRec; nsCOMPtr<nsICancelable> mLookup; nsresult mLookupStatus; PRFileDesc *mFD; nsCString mDestinationHost; - nsCString mProxyHost; - int32_t mProxyPort; + nsCOMPtr<nsIProxyInfo> mProxy; int32_t mVersion; // SOCKS version 4 or 5 int32_t mDestinationFamily; uint32_t mFlags; NetAddr mInternalProxyAddr; NetAddr mExternalProxyAddr; NetAddr mDestinationAddr; PRIntervalTime mTimeout; + nsCString mProxyUsername; // Cache, from mProxy }; nsSOCKSSocketInfo::nsSOCKSSocketInfo() : mState(SOCKS_INITIAL) , mDataIoPtr(nullptr) , mDataLength(0) , mReadOffset(0) , mAmountToRead(0) - , mProxyPort(-1) , mVersion(-1) , mDestinationFamily(AF_INET) , mFlags(0) , mTimeout(PR_INTERVAL_NO_TIMEOUT) { mData = new uint8_t[BUFFER_SIZE]; mInternalProxyAddr.raw.family = AF_INET; @@ -262,24 +266,24 @@ private: } uint8_t* mBuf; size_t mLength; }; void -nsSOCKSSocketInfo::Init(int32_t version, int32_t family, const char *proxyHost, int32_t proxyPort, const char *host, uint32_t flags) +nsSOCKSSocketInfo::Init(int32_t version, int32_t family, nsIProxyInfo *proxy, const char *host, uint32_t flags) { mVersion = version; mDestinationFamily = family; - mProxyHost = proxyHost; - mProxyPort = proxyPort; + mProxy = proxy; mDestinationHost = host; mFlags = flags; + mProxy->GetUsername(mProxyUsername); // cache } NS_IMPL_ISUPPORTS(nsSOCKSSocketInfo, nsISOCKSSocketInfo, nsIDNSListener) NS_IMETHODIMP nsSOCKSSocketInfo::GetExternalProxyAddr(NetAddr * *aExternalProxyAddr) { memcpy(*aExternalProxyAddr, &mExternalProxyAddr, sizeof(NetAddr)); @@ -356,24 +360,27 @@ nsSOCKSSocketInfo::StartDNS(PRFileDesc * { MOZ_ASSERT(!mDnsRec && mState == SOCKS_INITIAL, "Must be in initial state to make DNS Lookup"); nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID); if (!dns) return PR_FAILURE; + nsCString proxyHost; + mProxy->GetHost(proxyHost); + mFD = fd; - nsresult rv = dns->AsyncResolve(mProxyHost, 0, this, + nsresult rv = dns->AsyncResolve(proxyHost, 0, this, NS_GetCurrentThread(), getter_AddRefs(mLookup)); if (NS_FAILED(rv)) { LOGERROR(("socks: DNS lookup for SOCKS proxy %s failed", - mProxyHost.get())); + proxyHost.get())); return PR_FAILURE; } mState = SOCKS_DNS_IN_PROGRESS; PR_SetError(PR_IN_PROGRESS_ERROR, 0); return PR_FAILURE; } NS_IMETHODIMP @@ -408,26 +415,31 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFile } // Try socks5 if the destination addrress is IPv6 if (mVersion == 4 && mDestinationAddr.raw.family == AF_INET6) { mVersion = 5; } + int32_t proxyPort; + mProxy->GetPort(&proxyPort); + int32_t addresses = 0; do { if (addresses++) - mDnsRec->ReportUnusable(mProxyPort); + mDnsRec->ReportUnusable(proxyPort); - rv = mDnsRec->GetNextAddr(mProxyPort, &mInternalProxyAddr); + rv = mDnsRec->GetNextAddr(proxyPort, &mInternalProxyAddr); // No more addresses to try? If so, we'll need to bail if (NS_FAILED(rv)) { + nsCString proxyHost; + mProxy->GetHost(proxyHost); LOGERROR(("socks: unable to connect to SOCKS proxy, %s", - mProxyHost.get())); + proxyHost.get())); return PR_FAILURE; } if (MOZ_LOG_TEST(gSOCKSLog, LogLevel::Debug)) { char buf[kIPv6CStrBufSize]; NetAddrToString(&mInternalProxyAddr, buf, sizeof(buf)); LOGDEBUG(("socks: trying proxy server, %s:%hu", buf, ntohs(mInternalProxyAddr.inet.port))); @@ -534,16 +546,22 @@ nsSOCKSSocketInfo::ContinueConnectingToP if (mVersion == 4) return WriteV4ConnectRequest(); return WriteV5AuthRequest(); } PRStatus nsSOCKSSocketInfo::WriteV4ConnectRequest() { + if (mProxyUsername.Length() > MAX_USERNAME_LEN) { + LOGERROR(("socks username is too long")); + HandshakeFinished(PR_UNKNOWN_ERROR); + return PR_FAILURE; + } + NetAddr *addr = &mDestinationAddr; int32_t proxy_resolve; MOZ_ASSERT(mState == SOCKS_CONNECTING_TO_PROXY, "Invalid state!"); proxy_resolve = mFlags & nsISocketProvider::PROXY_RESOLVES_HOST; @@ -563,28 +581,32 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest // use a buffer with no further writes allowed. Buffer<0> buf3; if (proxy_resolve) { // Add the full name, null-terminated, to the request // according to SOCKS 4a. A fake IP address, with the first // four bytes set to 0 and the last byte set to something other // than 0, is used to notify the proxy that this is a SOCKS 4a // request. This request type works for Tor and perhaps others. + // Passwords not supported by V4. auto buf2 = buf.WriteUint32(htonl(0x00000001)) // Fake IP - .WriteUint8(0x00) // Send an emtpy username + .WriteString<MAX_USERNAME_LEN>(mProxyUsername) + .WriteUint8(0x00) // Null-terminate username .WriteString<MAX_HOSTNAME_LEN>(mDestinationHost); // Hostname if (!buf2) { LOGERROR(("socks4: destination host name is too long!")); HandshakeFinished(PR_BAD_ADDRESS_ERROR); return PR_FAILURE; } buf3 = buf2.WriteUint8(0x00); } else if (addr->raw.family == AF_INET) { + // Passwords not supported by V4. buf3 = buf.WriteNetAddr(addr) // Add the IPv4 address - .WriteUint8(0x00); // Send an emtpy username + .WriteString<MAX_USERNAME_LEN>(mProxyUsername) + .WriteUint8(0x00); // Null-terminate username } else { LOGERROR(("socks: SOCKS 4 can only handle IPv4 addresses!")); HandshakeFinished(PR_BAD_ADDRESS_ERROR); return PR_FAILURE; } mDataLength = buf3.Written(); return PR_SUCCESS; @@ -618,24 +640,26 @@ nsSOCKSSocketInfo::ReadV4ConnectResponse return PR_FAILURE; } PRStatus nsSOCKSSocketInfo::WriteV5AuthRequest() { MOZ_ASSERT(mVersion == 5, "SOCKS version must be 5!"); + mDataLength = 0; mState = SOCKS5_WRITE_AUTH_REQUEST; // Send an initial SOCKS 5 greeting LOGDEBUG(("socks5: sending auth methods")); mDataLength = Buffer<BUFFER_SIZE>(mData) .WriteUint8(0x05) // version -- 5 - .WriteUint8(0x01) // # auth methods -- 1 - .WriteUint8(0x00) // we don't support authentication + .WriteUint8(0x01) // # of auth methods -- 1 + // Use authenticate iff we have a proxy username. + .WriteUint8(mProxyUsername.IsEmpty() ? 0x00 : 0x02) .Written(); return PR_SUCCESS; } PRStatus nsSOCKSSocketInfo::ReadV5AuthResponse() { @@ -648,22 +672,91 @@ nsSOCKSSocketInfo::ReadV5AuthResponse() // Check version number if (ReadUint8() != 0x05) { LOGERROR(("socks5: unexpected version in the reply")); HandshakeFinished(PR_CONNECT_REFUSED_ERROR); return PR_FAILURE; } - // Make sure our authentication choice was accepted - if (ReadUint8() != 0x00) { + // Make sure our authentication choice was accepted, + // and continue accordingly + uint8_t authMethod = ReadUint8(); + if (mProxyUsername.IsEmpty() && authMethod == 0x00) { // no auth + LOGDEBUG(("socks5: server allows connection without authentication")); + return WriteV5ConnectRequest(); + } else if (!mProxyUsername.IsEmpty() && authMethod == 0x02) { // username/pw + LOGDEBUG(("socks5: auth method accepted by server")); + return WriteV5UsernameRequest(); + } else { // 0xFF signals error LOGERROR(("socks5: server did not accept our authentication method")); HandshakeFinished(PR_CONNECT_REFUSED_ERROR); return PR_FAILURE; } +} + +PRStatus +nsSOCKSSocketInfo::WriteV5UsernameRequest() +{ + MOZ_ASSERT(mVersion == 5, "SOCKS version must be 5!"); + + if (mProxyUsername.Length() > MAX_USERNAME_LEN) { + LOGERROR(("socks username is too long")); + HandshakeFinished(PR_UNKNOWN_ERROR); + return PR_FAILURE; + } + + nsCString password; + mProxy->GetPassword(password); + if (password.Length() > MAX_PASSWORD_LEN) { + LOGERROR(("socks password is too long")); + HandshakeFinished(PR_UNKNOWN_ERROR); + return PR_FAILURE; + } + + mDataLength = 0; + mState = SOCKS5_WRITE_USERNAME_REQUEST; + + // RFC 1929 Username/password auth for SOCKS 5 + LOGDEBUG(("socks5: sending username and password")); + mDataLength = Buffer<BUFFER_SIZE>(mData) + .WriteUint8(0x01) // version 1 (not 5) + .WriteUint8(mProxyUsername.Length()) // username length + .WriteString<MAX_USERNAME_LEN>(mProxyUsername) // username + .WriteUint8(password.Length()) // password length + .WriteString<MAX_PASSWORD_LEN>(password) // password. WARNING: Sent unencrypted! + .Written(); + + return PR_SUCCESS; +} + +PRStatus +nsSOCKSSocketInfo::ReadV5UsernameResponse() +{ + MOZ_ASSERT(mState == SOCKS5_READ_USERNAME_RESPONSE, + "Handling SOCKS 5 username/password reply in wrong state!"); + + MOZ_ASSERT(mDataLength == 2, + "SOCKS 5 username reply must be 2 bytes"); + + // Check version number, must be 1 (not 5) + if (ReadUint8() != 0x01) { + LOGERROR(("socks5: unexpected version in the reply")); + HandshakeFinished(PR_CONNECT_REFUSED_ERROR); + return PR_FAILURE; + } + + // Check whether username/password were accepted + if (ReadUint8() != 0x00) { // 0 = success + LOGERROR(("socks5: username/password not accepted")); + HandshakeFinished(PR_CONNECT_REFUSED_ERROR); + return PR_FAILURE; + } + + LOGDEBUG(("socks5: username/password accepted by server")); return WriteV5ConnectRequest(); } PRStatus nsSOCKSSocketInfo::WriteV5ConnectRequest() { // Send SOCKS 5 connect request @@ -902,16 +995,26 @@ nsSOCKSSocketInfo::DoHandshake(PRFileDes return PR_FAILURE; WantRead(2); mState = SOCKS5_READ_AUTH_RESPONSE; return PR_SUCCESS; case SOCKS5_READ_AUTH_RESPONSE: if (ReadFromSocket(fd) != PR_SUCCESS) return PR_FAILURE; return ReadV5AuthResponse(); + case SOCKS5_WRITE_USERNAME_REQUEST: + if (WriteToSocket(fd) != PR_SUCCESS) + return PR_FAILURE; + WantRead(2); + mState = SOCKS5_READ_USERNAME_RESPONSE; + return PR_SUCCESS; + case SOCKS5_READ_USERNAME_RESPONSE: + if (ReadFromSocket(fd) != PR_SUCCESS) + return PR_FAILURE; + return ReadV5UsernameResponse(); case SOCKS5_WRITE_CONNECT_REQUEST: if (WriteToSocket(fd) != PR_SUCCESS) return PR_FAILURE; // The SOCKS 5 response to the connection request is variable // length. First, we'll read enough to tell how long the response // is, and will read the rest later. WantRead(5); @@ -946,20 +1049,22 @@ nsSOCKSSocketInfo::GetPollFlags() const { switch (mState) { case SOCKS_DNS_IN_PROGRESS: case SOCKS_DNS_COMPLETE: case SOCKS_CONNECTING_TO_PROXY: return PR_POLL_EXCEPT | PR_POLL_WRITE; case SOCKS4_WRITE_CONNECT_REQUEST: case SOCKS5_WRITE_AUTH_REQUEST: + case SOCKS5_WRITE_USERNAME_REQUEST: case SOCKS5_WRITE_CONNECT_REQUEST: return PR_POLL_WRITE; case SOCKS4_READ_CONNECT_RESPONSE: case SOCKS5_READ_AUTH_RESPONSE: + case SOCKS5_READ_USERNAME_RESPONSE: case SOCKS5_READ_CONNECT_RESPONSE_TOP: case SOCKS5_READ_CONNECT_RESPONSE_BOTTOM: return PR_POLL_READ; default: break; } return 0; @@ -1264,18 +1369,17 @@ nsSOCKSIOLayerListen(PRFileDesc *fd, int return fd->lower->methods->listen(fd->lower, backlog); } // add SOCKS IO layer to an existing socket nsresult nsSOCKSIOLayerAddToSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, int32_t socksVersion, uint32_t flags, PRFileDesc *fd, nsISupports** info) { NS_ENSURE_TRUE((socksVersion == 4) || (socksVersion == 5), NS_ERROR_NOT_INITIALIZED); @@ -1327,17 +1431,17 @@ nsSOCKSIOLayerAddToSocket(int32_t family { // clean up IOLayerStub LOGERROR(("Failed to create nsSOCKSSocketInfo().")); PR_DELETE(layer); return NS_ERROR_FAILURE; } NS_ADDREF(infoObject); - infoObject->Init(socksVersion, family, proxyHost, proxyPort, host, flags); + infoObject->Init(socksVersion, family, proxy, host, flags); layer->secret = (PRFilePrivate*) infoObject; rv = PR_PushIOLayer(fd, PR_GetLayersIdentity(fd), layer); if (rv == PR_FAILURE) { LOGERROR(("PR_PushIOLayer() failed. rv = %x.", rv)); NS_RELEASE(infoObject); PR_DELETE(layer); return NS_ERROR_FAILURE;
--- a/netwerk/socket/nsSOCKSIOLayer.h +++ b/netwerk/socket/nsSOCKSIOLayer.h @@ -4,20 +4,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsSOCKSIOLayer_h__ #define nsSOCKSIOLayer_h__ #include "prio.h" #include "nscore.h" +#include "nsIProxyInfo.h" nsresult nsSOCKSIOLayerAddToSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxyInfo, int32_t socksVersion, uint32_t flags, PRFileDesc *fd, nsISupports **info); #endif /* nsSOCKSIOLayer_h__ */
--- a/netwerk/socket/nsSOCKSSocketProvider.cpp +++ b/netwerk/socket/nsSOCKSSocketProvider.cpp @@ -39,60 +39,56 @@ nsSOCKSSocketProvider::CreateV5(nsISuppo rv = inst->QueryInterface(aIID, aResult); return rv; } NS_IMETHODIMP nsSOCKSSocketProvider::NewSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc **result, nsISupports **socksInfo) { PRFileDesc *sock; sock = PR_OpenTCPSocket(family); if (!sock) return NS_ERROR_OUT_OF_MEMORY; nsresult rv = nsSOCKSIOLayerAddToSocket(family, host, port, - proxyHost, - proxyPort, + proxy, mVersion, flags, sock, socksInfo); if (NS_SUCCEEDED(rv)) { *result = sock; return NS_OK; } return NS_ERROR_SOCKET_CREATE_FAILED; } NS_IMETHODIMP nsSOCKSSocketProvider::AddToSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc *sock, nsISupports **socksInfo) { nsresult rv = nsSOCKSIOLayerAddToSocket(family, host, port, - proxyHost, - proxyPort, + proxy, mVersion, flags, sock, socksInfo); if (NS_FAILED(rv)) rv = NS_ERROR_SOCKET_CREATE_FAILED; return rv;
--- a/netwerk/socket/nsUDPSocketProvider.cpp +++ b/netwerk/socket/nsUDPSocketProvider.cpp @@ -11,18 +11,17 @@ NS_IMPL_ISUPPORTS(nsUDPSocketProvider, n nsUDPSocketProvider::~nsUDPSocketProvider() { } NS_IMETHODIMP nsUDPSocketProvider::NewSocket(int32_t aFamily, const char *aHost, int32_t aPort, - const char *aProxyHost, - int32_t aProxyPort, + nsIProxyInfo *aProxy, uint32_t aFlags, PRFileDesc * *aFileDesc, nsISupports **aSecurityInfo) { NS_ENSURE_ARG_POINTER(aFileDesc); PRFileDesc* udpFD = PR_OpenUDPSocket(aFamily); if (!udpFD) @@ -31,18 +30,17 @@ nsUDPSocketProvider::NewSocket(int32_t a *aFileDesc = udpFD; return NS_OK; } NS_IMETHODIMP nsUDPSocketProvider::AddToSocket(int32_t aFamily, const char *aHost, int32_t aPort, - const char *aProxyHost, - int32_t aProxyPort, + nsIProxyInfo *aProxy, uint32_t aFlags, struct PRFileDesc * aFileDesc, nsISupports **aSecurityInfo) { // does not make sense to strap a UDP socket onto an existing socket NS_NOTREACHED("Cannot layer UDP socket on an existing socket"); return NS_ERROR_UNEXPECTED; }
--- a/security/manager/ssl/nsNSSIOLayer.cpp +++ b/security/manager/ssl/nsNSSIOLayer.cpp @@ -1812,28 +1812,27 @@ nsSSLIOLayerHelpers::treatUnsafeNegotiat MutexAutoLock lock(mutex); return mTreatUnsafeNegotiationAsBroken; } 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, uint32_t flags) { 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); return rv; } *fd = sock; return NS_OK; @@ -2508,21 +2507,21 @@ loser: if (sslSock) { PR_Close(sslSock); } return nullptr; } 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; } } SSLVersionRange range; if (SSL_VersionRangeGet(fd, &range) != SECSuccess) { return NS_ERROR_FAILURE; @@ -2589,18 +2588,17 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, b return NS_OK; } 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, uint32_t providerFlags) { nsNSSShutDownPreventionLock locker; PRFileDesc* layer = nullptr; PRFileDesc* plaintextLayer = nullptr; @@ -2612,16 +2610,23 @@ nsSSLIOLayerAddToSocket(int32_t family, nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags); if (!infoObject) return NS_ERROR_FAILURE; NS_ADDREF(infoObject); infoObject->SetForSTARTTLS(forSTARTTLS); 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, &nsSSLIOLayerHelpers::nsSSLPlaintextLayerMethods); if (plaintextLayer) { plaintextLayer->secret = (PRFilePrivate*) infoObject; stat = PR_PushIOLayer(fd, PR_TOP_IO_LAYER, plaintextLayer); if (stat == PR_FAILURE) { @@ -2633,17 +2638,17 @@ nsSSLIOLayerAddToSocket(int32_t family, PRFileDesc* sslSock = nsSSLIOLayerImportFD(fd, infoObject, host); if (!sslSock) { NS_ASSERTION(false, "NSS: Error importing socket"); goto loser; } infoObject->SetFileDescPtr(sslSock); - rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, proxyHost, host, port, + rv = nsSSLIOLayerSetOptions(sslSock, forSTARTTLS, haveProxy, host, port, infoObject); if (NS_FAILED(rv)) goto loser; // Now, layer ourselves on top of the SSL socket... layer = PR_CreateIOLayerStub(nsSSLIOLayerHelpers::nsSSLIOLayerIdentity, &nsSSLIOLayerHelpers::nsSSLIOLayerMethods); @@ -2656,17 +2661,17 @@ nsSSLIOLayerAddToSocket(int32_t family, if (stat == PR_FAILURE) { goto loser; } MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("[%p] Socket set up\n", (void*) sslSock)); infoObject->QueryInterface(NS_GET_IID(nsISupports), (void**) (info)); // We are going use a clear connection first // - if (forSTARTTLS || proxyHost) { + if (forSTARTTLS || haveProxy) { infoObject->SetHandshakeNotPending(); } infoObject->SharedState().NoteSocketCreated(); return NS_OK; loser: NS_IF_RELEASE(infoObject);
--- a/security/manager/ssl/nsNSSIOLayer.h +++ b/security/manager/ssl/nsNSSIOLayer.h @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _NSNSSIOLAYER_H #define _NSNSSIOLAYER_H #include "TransportSecurityInfo.h" #include "nsISSLSocketControl.h" #include "nsIClientAuthDialogs.h" +#include "nsIProxyInfo.h" #include "nsNSSCertificate.h" #include "nsDataHashtable.h" #include "nsTHashtable.h" #include "mozilla/TimeStamp.h" #include "sslt.h" namespace mozilla { namespace psm { @@ -237,28 +238,26 @@ public: private: mozilla::Mutex mutex; nsCOMPtr<nsIObserver> mPrefObserver; }; nsresult nsSSLIOLayerNewSocket(int32_t family, const char* host, int32_t port, - const char* proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, PRFileDesc** fd, nsISupports** securityInfo, bool forSTARTTLS, uint32_t flags); nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port, - const char* proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, PRFileDesc* fd, nsISupports** securityInfo, bool forSTARTTLS, uint32_t flags); nsresult nsSSLIOLayerFreeTLSIntolerantSites(); nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo* infoObject, int error);
--- a/security/manager/ssl/nsSSLSocketProvider.cpp +++ b/security/manager/ssl/nsSSLSocketProvider.cpp @@ -17,49 +17,45 @@ nsSSLSocketProvider::~nsSSLSocketProvide } NS_IMPL_ISUPPORTS(nsSSLSocketProvider, nsISocketProvider) NS_IMETHODIMP nsSSLSocketProvider::NewSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc **_result, nsISupports **securityInfo) { nsresult rv = nsSSLIOLayerNewSocket(family, host, port, - proxyHost, - proxyPort, + proxy, _result, securityInfo, false, flags); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; } // Add the SSL IO layer to an existing socket NS_IMETHODIMP nsSSLSocketProvider::AddToSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc *aSocket, nsISupports **securityInfo) { nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, - proxyHost, - proxyPort, + proxy, aSocket, securityInfo, false, flags); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; }
--- a/security/manager/ssl/nsTLSSocketProvider.cpp +++ b/security/manager/ssl/nsTLSSocketProvider.cpp @@ -17,50 +17,46 @@ nsTLSSocketProvider::~nsTLSSocketProvide } NS_IMPL_ISUPPORTS(nsTLSSocketProvider, nsISocketProvider) NS_IMETHODIMP nsTLSSocketProvider::NewSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc **_result, nsISupports **securityInfo) { nsresult rv = nsSSLIOLayerNewSocket(family, host, port, - proxyHost, - proxyPort, + proxy, _result, securityInfo, true, flags); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; } // Add the SSL IO layer to an existing socket NS_IMETHODIMP nsTLSSocketProvider::AddToSocket(int32_t family, const char *host, int32_t port, - const char *proxyHost, - int32_t proxyPort, + nsIProxyInfo *proxy, uint32_t flags, PRFileDesc *aSocket, nsISupports **securityInfo) { nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, - proxyHost, - proxyPort, + proxy, aSocket, securityInfo, true, flags); return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK; }