commit e0eaf6b471ae3bbc06066232a00f3b27c2bedeee
Author: Arthur Edelstein <arthuredelstein(a)gmail.com>
Date: Tue Oct 21 02:17:55 2014 -0700
Bug #3455.2. Allow RFC1929 authentication (username/password) to SOCKS servers.
---
netwerk/base/public/nsIProtocolProxyService.idl | 29 ++++
netwerk/base/public/nsIProxyInfo.idl | 12 +-
netwerk/base/src/nsProtocolProxyService.cpp | 39 ++++-
netwerk/base/src/nsProtocolProxyService.h | 8 +
netwerk/base/src/nsProxyInfo.cpp | 14 ++
netwerk/base/src/nsProxyInfo.h | 2 +
netwerk/base/src/nsSocketTransport2.cpp | 84 +++++++---
netwerk/base/src/nsSocketTransport2.h | 15 +-
netwerk/socket/nsISocketProvider.idl | 9 +-
netwerk/socket/nsSOCKSIOLayer.cpp | 196 +++++++++++++++++-----
netwerk/socket/nsSOCKSIOLayer.h | 4 +-
netwerk/socket/nsSOCKSSocketProvider.cpp | 12 +-
netwerk/socket/nsUDPSocketProvider.cpp | 6 +-
security/manager/ssl/src/nsNSSIOLayer.cpp | 23 ++-
security/manager/ssl/src/nsNSSIOLayer.h | 7 +-
security/manager/ssl/src/nsSSLSocketProvider.cpp | 12 +-
security/manager/ssl/src/nsTLSSocketProvider.cpp | 12 +-
17 files changed, 361 insertions(+), 123 deletions(-)
diff --git a/netwerk/base/public/nsIProtocolProxyService.idl b/netwerk/base/public/nsIProtocolProxyService.idl
index 9365658..f974f40 100644
--- a/netwerk/base/public/nsIProtocolProxyService.idl
+++ b/netwerk/base/public/nsIProtocolProxyService.idl
@@ -136,6 +136,35 @@ interface nsIProtocolProxyService : nsISupports
in nsIProxyInfo aFailoverProxy);
/**
+ * This method may be called to construct a nsIProxyInfo instance for
+ * a SOCKS connection, with the specified username and password.
+ * @param aHost
+ * The proxy hostname or IP address.
+ * @param aPort
+ * The proxy port.
+ * @param aUsername
+ * The SOCKS5 username
+ * @param aPassword
+ * The SOCKS5 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 newSOCKSProxyInfo(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
diff --git a/netwerk/base/public/nsIProxyInfo.idl b/netwerk/base/public/nsIProxyInfo.idl
index f6f0bf3..56beb02 100644
--- a/netwerk/base/public/nsIProxyInfo.idl
+++ b/netwerk/base/public/nsIProxyInfo.idl
@@ -8,7 +8,7 @@
/**
* This interface identifies a proxy server.
*/
-[scriptable, uuid(9e557d99-7af0-4895-95b7-e6dba28c9ad9)]
+[scriptable, uuid(63fff172-2564-4138-96c6-3ae7d245fbed)]
interface nsIProxyInfo : nsISupports
{
/**
@@ -50,6 +50,16 @@ interface nsIProxyInfo : nsISupports
readonly attribute unsigned long resolveFlags;
/**
+ * Specifies a SOCKS5 username.
+ */
+ readonly attribute ACString username;
+
+ /**
+ * Specifies a SOCKS5 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
diff --git a/netwerk/base/src/nsProtocolProxyService.cpp b/netwerk/base/src/nsProtocolProxyService.cpp
index 3878c58d..ed8b311 100644
--- a/netwerk/base/src/nsProtocolProxyService.cpp
+++ b/netwerk/base/src/nsProtocolProxyService.cpp
@@ -516,6 +516,12 @@ nsProtocolProxyService::PrefsChanged(nsIPrefBranch *prefBranch,
if (!pref || !strcmp(pref, PROXY_PREF("socks_port")))
proxy_GetIntPref(prefBranch, PROXY_PREF("socks_port"), mSOCKSProxyPort);
+ if (!pref || !strcmp(pref, PROXY_PREF("socks_username")))
+ proxy_GetStringPref(prefBranch, PROXY_PREF("socks_username"), mSOCKSProxyUsername);
+
+ if (!pref || !strcmp(pref, PROXY_PREF("socks_password")))
+ proxy_GetStringPref(prefBranch, PROXY_PREF("socks_password"), mSOCKSProxyPassword);
+
if (!pref || !strcmp(pref, PROXY_PREF("socks_version"))) {
int32_t version;
proxy_GetIntPref(prefBranch, PROXY_PREF("socks_version"), version);
@@ -1188,10 +1194,25 @@ nsProtocolProxyService::NewProxyInfo(const nsACString &aType,
}
NS_ENSURE_TRUE(type, NS_ERROR_INVALID_ARG);
- if (aPort <= 0)
- aPort = -1;
+ return NewProxyInfo_Internal(type, aHost, aPort,
+ mSOCKSProxyUsername, mSOCKSProxyPassword,
+ aFlags, aFailoverTimeout,
+ aFailoverProxy, 0, aResult);
+}
- return NewProxyInfo_Internal(type, aHost, aPort, aFlags, aFailoverTimeout,
+NS_IMETHODIMP
+nsProtocolProxyService::NewSOCKSProxyInfo(const nsACString &aHost,
+ int32_t aPort,
+ const nsACString &aUsername,
+ const nsACString &aPassword,
+ uint32_t aFlags,
+ uint32_t aFailoverTimeout,
+ nsIProxyInfo *aFailoverProxy,
+ nsIProxyInfo **aResult)
+{
+ return NewProxyInfo_Internal(kProxyType_SOCKS, aHost, aPort,
+ aUsername, aPassword,
+ aFlags, aFailoverTimeout,
aFailoverProxy, 0, aResult);
}
@@ -1496,12 +1517,17 @@ 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);
@@ -1515,6 +1541,8 @@ nsProtocolProxyService::NewProxyInfo_Internal(const char *aType,
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
@@ -1680,8 +1708,9 @@ nsProtocolProxyService::Resolve_Internal(nsIChannel *channel,
}
if (type) {
- rv = NewProxyInfo_Internal(type, *host, port, proxyFlags,
- UINT32_MAX, nullptr, flags,
+ rv = NewProxyInfo_Internal(type, *host, port,
+ mSOCKSProxyUsername, mSOCKSProxyPassword,
+ proxyFlags, UINT32_MAX, nullptr, flags,
result);
if (NS_FAILED(rv))
return rv;
diff --git a/netwerk/base/src/nsProtocolProxyService.h b/netwerk/base/src/nsProtocolProxyService.h
index 9ef68b9..04c642f 100644
--- a/netwerk/base/src/nsProtocolProxyService.h
+++ b/netwerk/base/src/nsProtocolProxyService.h
@@ -177,6 +177,10 @@ protected:
* 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
@@ -191,6 +195,8 @@ protected:
NS_HIDDEN_(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,
@@ -374,6 +380,8 @@ protected:
int32_t mSOCKSProxyPort;
int32_t mSOCKSProxyVersion;
bool mSOCKSProxyRemoteDNS;
+ nsCString mSOCKSProxyUsername;
+ nsCString mSOCKSProxyPassword;
nsRefPtr<nsPACMan> mPACMan; // non-null if we are using PAC
nsCOMPtr<nsISystemProxySettings> mSystemProxySettings;
diff --git a/netwerk/base/src/nsProxyInfo.cpp b/netwerk/base/src/nsProxyInfo.cpp
index 4e727c4..66a78a4 100644
--- a/netwerk/base/src/nsProxyInfo.cpp
+++ b/netwerk/base/src/nsProxyInfo.cpp
@@ -48,6 +48,20 @@ nsProxyInfo::GetResolveFlags(uint32_t *result)
}
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;
diff --git a/netwerk/base/src/nsProxyInfo.h b/netwerk/base/src/nsProxyInfo.h
index 550bbf2..5432d95 100644
--- a/netwerk/base/src/nsProxyInfo.h
+++ b/netwerk/base/src/nsProxyInfo.h
@@ -59,6 +59,8 @@ private:
const char *mType; // pointer to statically allocated value
nsCString mHost;
+ nsCString mUsername;
+ nsCString mPassword;
int32_t mPort;
uint32_t mFlags;
uint32_t mResolveFlags;
diff --git a/netwerk/base/src/nsSocketTransport2.cpp b/netwerk/base/src/nsSocketTransport2.cpp
index e202044..ea0dd68 100644
--- a/netwerk/base/src/nsSocketTransport2.cpp
+++ b/netwerk/base/src/nsSocketTransport2.cpp
@@ -751,7 +751,8 @@ nsSocketTransport::nsSocketTransport()
: mTypes(nullptr)
, mTypeCount(0)
, mPort(0)
- , mProxyPort(0)
+ , mHttpsProxy(false)
+ , mProxyUse(false)
, mProxyTransparent(false)
, mProxyTransparentResolvesHost(false)
, mConnectionFlags(0)
@@ -813,18 +814,25 @@ nsSocketTransport::Init(const char **types, uint32_t typeCount,
const char *proxyType = nullptr;
if (proxyInfo) {
- mProxyPort = proxyInfo->Port();
- mProxyHost = proxyInfo->Host();
+ mProxyInfo = proxyInfo;
// grab proxy type (looking for "socks" for example)
proxyType = proxyInfo->Type();
if (proxyType && (strcmp(proxyType, "http") == 0 ||
strcmp(proxyType, "direct") == 0 ||
strcmp(proxyType, "unknown") == 0))
proxyType = nullptr;
+
+ mProxyUse = true;
+ // check that we don't have a proxyInfo without proxy
+ nsCString proxyHost;
+ proxyInfo->GetHost(proxyHost);
+ if (!proxyType || proxyHost.IsEmpty()) {
+ mProxyUse = false;
+ }
}
- SOCKET_LOG(("nsSocketTransport::Init [this=%p host=%s:%hu proxy=%s:%hu]\n",
- this, mHost.get(), mPort, mProxyHost.get(), mProxyPort));
+ SOCKET_LOG(("nsSocketTransport::Init [this=%x host=%s:%hu proxy=%s]\n",
+ this, mHost.get(), mPort, mProxyUse ? "yes" : "no"));
// include proxy type as a socket type if proxy type is not "http"
mTypeCount = typeCount + (proxyType != nullptr);
@@ -997,7 +1005,7 @@ nsSocketTransport::ResolveHost()
nsresult rv;
- if (!mProxyHost.IsEmpty()) {
+ if (mProxyUse) {
if (!mProxyTransparent || mProxyTransparentResolvesHost) {
#if defined(XP_UNIX)
NS_ABORT_IF_FALSE(!mNetAddrIsSet || mNetAddr.raw.family != AF_LOCAL,
@@ -1079,9 +1087,8 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
const char *host = mHost.get();
int32_t port = (int32_t) mPort;
- const char *proxyHost = mProxyHost.IsEmpty() ? nullptr : mProxyHost.get();
- int32_t proxyPort = (int32_t) mProxyPort;
uint32_t proxyFlags = 0;
+ nsCOMPtr<nsIProxyInfo> proxy = mProxyInfo;
uint32_t i;
for (i=0; i<mTypeCount; ++i) {
@@ -1102,12 +1109,19 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
if (mConnectionFlags & nsISocketTransport::NO_PERMANENT_STORAGE)
proxyFlags |= nsISocketProvider::NO_PERMANENT_STORAGE;
+
nsCOMPtr<nsISupports> secinfo;
if (i == 0) {
// if this is the first type, we'll want the
// service to allocate a new socket
+ nsCString proxyHost;
+ GetHost(proxyHost);
+ int32_t proxyPort;
+ GetPort(&proxyPort);
rv = provider->NewSocket(mNetAddr.raw.family,
- host, port, proxyHost, proxyPort,
+ mHttpsProxy ? proxyHost.get() : host,
+ mHttpsProxy ? proxyPort : port,
+ proxy,
proxyFlags, &fd,
getter_AddRefs(secinfo));
@@ -1121,7 +1135,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
// 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, proxy,
proxyFlags, fd,
getter_AddRefs(secinfo));
}
@@ -1151,8 +1165,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
(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;
+ proxy = nullptr;
proxyTransparent = true;
}
}
@@ -1211,10 +1224,14 @@ nsSocketTransport::InitiateSocket()
netAddrCString.BeginWriting(),
kIPv6CStrBufSize))
netAddrCString = NS_LITERAL_CSTRING("<IP-to-string failed>");
+ nsCString proxyHost;
+ GetHost(proxyHost);
+ int32_t proxyPort;
+ GetPort(&proxyPort);
SOCKET_LOG(("nsSocketTransport::InitiateSocket skipping "
"speculative connection for host [%s:%d] proxy "
"[%s:%d] with Local IP address [%s]",
- mHost.get(), mPort, mProxyHost.get(), mProxyPort,
+ mHost.get(), mPort, proxyHost.get(), proxyPort,
netAddrCString.get()));
}
#endif
@@ -1363,7 +1380,7 @@ nsSocketTransport::InitiateSocket()
//
OnSocketConnected();
- if (mSecInfo && !mProxyHost.IsEmpty() && proxyTransparent && usingSSL) {
+ if (mSecInfo && mProxyUse && proxyTransparent && usingSSL) {
// if the connection phase is finished, and the ssl layer has
// been pushed, and we were proxying (transparently; ie. nothing
// has to happen in the protocol layer above us), it's time for
@@ -1387,8 +1404,7 @@ nsSocketTransport::InitiateSocket()
// the OS error
//
else if (PR_UNKNOWN_ERROR == code &&
- mProxyTransparent &&
- !mProxyHost.IsEmpty()) {
+ mProxyUse && mProxyTransparent) {
code = PR_GetOSError();
rv = ErrorAccordingToNSPR(code);
}
@@ -1397,7 +1413,7 @@ nsSocketTransport::InitiateSocket()
//
else {
rv = ErrorAccordingToNSPR(code);
- if ((rv == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
+ if (rv == NS_ERROR_CONNECTION_REFUSED && mProxyUse)
rv = NS_ERROR_PROXY_CONNECTION_REFUSED;
}
}
@@ -1709,8 +1725,8 @@ nsSocketTransport::OnSocketEvent(uint32_t type, nsresult status, nsISupports *pa
// For SOCKS proxies (mProxyTransparent == true), the socket
// transport resolves the real host here, so there's no fixup
// (see bug 226943).
- if ((status == NS_ERROR_UNKNOWN_HOST) && !mProxyTransparent &&
- !mProxyHost.IsEmpty())
+ if (status == NS_ERROR_UNKNOWN_HOST && !mProxyTransparent &&
+ mProxyUse)
mCondition = NS_ERROR_UNKNOWN_PROXY_HOST;
else
mCondition = status;
@@ -1835,8 +1851,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
// The SOCKS proxy rejected our request. Find out why.
//
else if (PR_UNKNOWN_ERROR == code &&
- mProxyTransparent &&
- !mProxyHost.IsEmpty()) {
+ mProxyUse && mProxyTransparent) {
code = PR_GetOSError();
mCondition = ErrorAccordingToNSPR(code);
}
@@ -1845,7 +1860,7 @@ nsSocketTransport::OnSocketReady(PRFileDesc *fd, int16_t outFlags)
// else, the connection failed...
//
mCondition = ErrorAccordingToNSPR(code);
- if ((mCondition == NS_ERROR_CONNECTION_REFUSED) && !mProxyHost.IsEmpty())
+ if (mCondition == NS_ERROR_CONNECTION_REFUSED && mProxyUse)
mCondition = NS_ERROR_PROXY_CONNECTION_REFUSED;
SOCKET_LOG((" connection failed! [reason=%x]\n", mCondition));
}
@@ -2168,6 +2183,31 @@ nsSocketTransport::GetPort(int32_t *port)
return NS_OK;
}
+const nsCString &
+nsSocketTransport::SocketHost()
+{
+ if (mProxyInfo && !mProxyTransparent) {
+ if (mProxyHostCache.IsEmpty()) {
+ mProxyInfo->GetHost(mProxyHostCache);
+ }
+ return mProxyHostCache;
+ }
+ else
+ return mHost;
+}
+
+uint16_t
+nsSocketTransport::SocketPort()
+{
+ if (mProxyInfo && !mProxyTransparent) {
+ int32_t result;
+ mProxyInfo->GetPort(&result);
+ return (uint16_t) result;
+ }
+ else
+ return mPort;
+}
+
NS_IMETHODIMP
nsSocketTransport::GetPeerAddr(NetAddr *addr)
{
diff --git a/netwerk/base/src/nsSocketTransport2.h b/netwerk/base/src/nsSocketTransport2.h
index 8d822bf..73f750e 100644
--- a/netwerk/base/src/nsSocketTransport2.h
+++ b/netwerk/base/src/nsSocketTransport2.h
@@ -266,15 +266,18 @@ private:
char **mTypes;
uint32_t mTypeCount;
nsCString mHost;
- nsCString mProxyHost;
uint16_t mPort;
- uint16_t mProxyPort;
- bool mProxyTransparent;
- bool mProxyTransparentResolvesHost;
+ bool mHttpsProxy;
+
+ nsCOMPtr<nsIProxyInfo> mProxyInfo;
+ bool mProxyUse;
+ bool mProxyTransparent;
+ bool mProxyTransparentResolvesHost;
uint32_t mConnectionFlags;
- uint16_t SocketPort() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyPort : mPort; }
- const nsCString &SocketHost() { return (!mProxyHost.IsEmpty() && !mProxyTransparent) ? mProxyHost : mHost; }
+ uint16_t SocketPort();
+ const nsCString &SocketHost();
+ nsCString mProxyHostCache; // for SocketHost() only
//-------------------------------------------------------------------------
// members accessible only on the socket transport thread:
diff --git a/netwerk/socket/nsISocketProvider.idl b/netwerk/socket/nsISocketProvider.idl
index 57f6c4d..0dd316c 100644
--- a/netwerk/socket/nsISocketProvider.idl
+++ b/netwerk/socket/nsISocketProvider.idl
@@ -5,12 +5,13 @@
#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
{
/**
@@ -38,8 +39,7 @@ interface nsISocketProvider : nsISupports
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);
@@ -58,8 +58,7 @@ interface nsISocketProvider : nsISupports
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);
diff --git a/netwerk/socket/nsSOCKSIOLayer.cpp b/netwerk/socket/nsSOCKSIOLayer.cpp
index e03b94c..f3250b9 100644
--- a/netwerk/socket/nsSOCKSIOLayer.cpp
+++ b/netwerk/socket/nsSOCKSIOLayer.cpp
@@ -50,6 +50,8 @@ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
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,
@@ -57,10 +59,12 @@ class nsSOCKSSocketInfo : public nsISOCKSSocketInfo
SOCKS_FAILED
};
- // A buffer of 262 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 = 262;
+ 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();
@@ -72,8 +76,7 @@ public:
void Init(int32_t version,
int32_t family,
- const char *proxyHost,
- int32_t proxyPort,
+ nsIProxyInfo *proxy,
const char *destinationHost,
uint32_t flags);
@@ -95,6 +98,8 @@ private:
PRStatus ReadV4ConnectResponse();
PRStatus WriteV5AuthRequest();
PRStatus ReadV5AuthResponse();
+ PRStatus WriteV5UsernameRequest();
+ PRStatus ReadV5UsernameResponse();
PRStatus WriteV5ConnectRequest();
PRStatus ReadV5AddrTypeAndLength(uint8_t *type, uint32_t *len);
PRStatus ReadV5ConnectResponseTop();
@@ -130,8 +135,7 @@ private:
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;
@@ -139,6 +143,7 @@ private:
NetAddr mExternalProxyAddr;
NetAddr mDestinationAddr;
PRIntervalTime mTimeout;
+ nsCString mProxyUsername; // Cache, from mProxy
};
nsSOCKSSocketInfo::nsSOCKSSocketInfo()
@@ -147,7 +152,6 @@ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
, mDataLength(0)
, mReadOffset(0)
, mAmountToRead(0)
- , mProxyPort(-1)
, mVersion(-1)
, mDestinationFamily(AF_INET)
, mFlags(0)
@@ -169,14 +173,14 @@ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
}
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)
@@ -263,14 +267,17 @@ nsSOCKSSocketInfo::StartDNS(PRFileDesc *fd)
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;
@@ -315,16 +322,21 @@ nsSOCKSSocketInfo::ConnectToProxy(PRFileDesc *fd)
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;
}
@@ -440,6 +452,12 @@ nsSOCKSSocketInfo::ContinueConnectingToProxy(PRFileDesc *fd, int16_t oflags)
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;
@@ -465,7 +483,9 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest()
// than 0, is used to notify the proxy that this is a SOCKS 4a
// request. This request type works for Tor and perhaps others.
WriteUint32(htonl(0x00000001)); // Fake IP
- WriteUint8(0x00); // Send an emtpy username
+ WriteString(mProxyUsername); // Send username. May be empty.
+ WriteUint8(0x00); // Null-terminate username
+ // Password not supported by V4.
if (mDestinationHost.Length() > MAX_HOSTNAME_LEN) {
LOGERROR(("socks4: destination host name is too long!"));
HandshakeFinished(PR_BAD_ADDRESS_ERROR);
@@ -475,7 +495,9 @@ nsSOCKSSocketInfo::WriteV4ConnectRequest()
WriteUint8(0x00);
} else if (addr->raw.family == AF_INET) {
WriteNetAddr(addr); // Add the IPv4 address
- WriteUint8(0x00); // Send an emtpy username
+ WriteString(mProxyUsername); // Send username. May be empty.
+ WriteUint8(0x00); // Null-terminate username
+ // Password not supported by V4.
} else if (addr->raw.family == AF_INET6) {
LOGERROR(("socks: SOCKS 4 can't handle IPv6 addresses!"));
HandshakeFinished(PR_BAD_ADDRESS_ERROR);
@@ -490,11 +512,15 @@ nsSOCKSSocketInfo::ReadV4ConnectResponse()
{
NS_ABORT_IF_FALSE(mState == SOCKS4_READ_CONNECT_RESPONSE,
"Handling SOCKS 4 connection reply in wrong state!");
- NS_ABORT_IF_FALSE(mDataLength == 8,
- "SOCKS 4 connection reply must be 8 bytes!");
LOGDEBUG(("socks4: checking connection reply"));
+ if (mDataLength != 8) {
+ LOGERROR(("SOCKS 4 connection reply must be 8 bytes!"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
if (ReadUint8() != 0x00) {
LOGERROR(("socks4: wrong connection reply"));
HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
@@ -518,13 +544,18 @@ nsSOCKSSocketInfo::WriteV5AuthRequest()
{
NS_ABORT_IF_FALSE(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"));
WriteUint8(0x05); // version -- 5
- WriteUint8(0x01); // # auth methods -- 1
- WriteUint8(0x00); // we don't support authentication
+ WriteUint8(0x01); // # of auth methods -- 1
+ if (mProxyUsername.IsEmpty()) {
+ WriteUint8(0x00); // no authentication
+ } else {
+ WriteUint8(0x02); // username/password
+ }
return PR_SUCCESS;
}
@@ -534,10 +565,12 @@ nsSOCKSSocketInfo::ReadV5AuthResponse()
{
NS_ABORT_IF_FALSE(mState == SOCKS5_READ_AUTH_RESPONSE,
"Handling SOCKS 5 auth method reply in wrong state!");
- NS_ABORT_IF_FALSE(mDataLength == 2,
- "SOCKS 5 auth method reply must be 2 bytes!");
- LOGDEBUG(("socks5: checking auth method reply"));
+ if (mDataLength != 2) {
+ LOGERROR(("SOCKS 5 auth method reply must be 2 bytes"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
// Check version number
if (ReadUint8() != 0x05) {
@@ -546,12 +579,82 @@ nsSOCKSSocketInfo::ReadV5AuthResponse()
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()
+{
+ NS_ABORT_IF_FALSE(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;
+
+ LOGDEBUG(("socks5: sending username and password"));
+ // RFC 1929 Username/password auth for SOCKS 5
+ WriteUint8(0x01); // version 1 (not 5)
+ WriteUint8(mProxyUsername.Length()); // username length
+ WriteString(mProxyUsername); // username
+ WriteUint8(password.Length()); // password length
+ WriteString(password); // password. WARNING: Sent unencrypted!
+
+ return PR_SUCCESS;
+}
+
+PRStatus
+nsSOCKSSocketInfo::ReadV5UsernameResponse()
+{
+ NS_ABORT_IF_FALSE(mState == SOCKS5_READ_USERNAME_RESPONSE,
+ "Handling SOCKS 5 username/password reply in wrong state!");
+
+ if (mDataLength != 2) {
+ LOGERROR(("SOCKS 5 username reply must be 2 bytes"));
+ HandshakeFinished(PR_CONNECT_REFUSED_ERROR);
+ return PR_FAILURE;
+ }
+
+ // 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();
}
@@ -795,6 +898,16 @@ nsSOCKSSocketInfo::DoHandshake(PRFileDesc *fd, int16_t oflags)
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;
@@ -839,10 +952,12 @@ nsSOCKSSocketInfo::GetPollFlags() const
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;
@@ -856,7 +971,7 @@ nsSOCKSSocketInfo::GetPollFlags() const
inline void
nsSOCKSSocketInfo::WriteUint8(uint8_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
mData[mDataLength] = v;
mDataLength += sizeof(v);
@@ -865,7 +980,7 @@ nsSOCKSSocketInfo::WriteUint8(uint8_t v)
inline void
nsSOCKSSocketInfo::WriteUint16(uint16_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, &v, sizeof(v));
mDataLength += sizeof(v);
@@ -874,7 +989,7 @@ nsSOCKSSocketInfo::WriteUint16(uint16_t v)
inline void
nsSOCKSSocketInfo::WriteUint32(uint32_t v)
{
- NS_ABORT_IF_FALSE(mDataLength + sizeof(v) <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sizeof(v) <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, &v, sizeof(v));
mDataLength += sizeof(v);
@@ -894,8 +1009,8 @@ nsSOCKSSocketInfo::WriteNetAddr(const NetAddr *addr)
len = sizeof(addr->inet6.ip.u8);
}
- NS_ABORT_IF_FALSE(ip != nullptr, "Unknown address");
- NS_ABORT_IF_FALSE(mDataLength + len <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(ip != nullptr, "Unknown address");
+ MOZ_RELEASE_ASSERT(mDataLength + len <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, ip, len);
@@ -911,7 +1026,7 @@ nsSOCKSSocketInfo::WriteNetPort(const NetAddr *addr)
void
nsSOCKSSocketInfo::WriteString(const nsACString &str)
{
- NS_ABORT_IF_FALSE(mDataLength + str.Length() <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + str.Length() <= BUFFER_SIZE,
"Can't write that much data!");
memcpy(mData + mDataLength, str.Data(), str.Length());
mDataLength += str.Length();
@@ -921,7 +1036,7 @@ inline uint8_t
nsSOCKSSocketInfo::ReadUint8()
{
uint8_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint8_t!");
rv = mData[mReadOffset];
mReadOffset += sizeof(rv);
@@ -932,7 +1047,7 @@ inline uint16_t
nsSOCKSSocketInfo::ReadUint16()
{
uint16_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint16_t!");
memcpy(&rv, mData + mReadOffset, sizeof(rv));
mReadOffset += sizeof(rv);
@@ -943,7 +1058,7 @@ inline uint32_t
nsSOCKSSocketInfo::ReadUint32()
{
uint32_t rv;
- NS_ABORT_IF_FALSE(mReadOffset + sizeof(rv) <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + sizeof(rv) <= mDataLength,
"Not enough space to pop a uint32_t!");
memcpy(&rv, mData + mReadOffset, sizeof(rv));
mReadOffset += sizeof(rv);
@@ -959,12 +1074,12 @@ nsSOCKSSocketInfo::ReadNetAddr(NetAddr *addr, uint16_t fam)
addr->raw.family = fam;
if (fam == AF_INET) {
amt = sizeof(addr->inet.ip);
- NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + amt <= mDataLength,
"Not enough space to pop an ipv4 addr!");
memcpy(&addr->inet.ip, ip, amt);
} else if (fam == AF_INET6) {
amt = sizeof(addr->inet6.ip.u8);
- NS_ABORT_IF_FALSE(mReadOffset + amt <= mDataLength,
+ MOZ_RELEASE_ASSERT(mReadOffset + amt <= mDataLength,
"Not enough space to pop an ipv6 addr!");
memcpy(addr->inet6.ip.u8, ip, amt);
}
@@ -983,7 +1098,7 @@ nsSOCKSSocketInfo::WantRead(uint32_t sz)
{
NS_ABORT_IF_FALSE(mDataIoPtr == nullptr,
"WantRead() called while I/O already in progress!");
- NS_ABORT_IF_FALSE(mDataLength + sz <= BUFFER_SIZE,
+ MOZ_RELEASE_ASSERT(mDataLength + sz <= BUFFER_SIZE,
"Can't read that much data!");
mAmountToRead = sz;
}
@@ -1221,8 +1336,7 @@ 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,
@@ -1289,7 +1403,7 @@ nsSOCKSIOLayerAddToSocket(int32_t family,
}
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);
diff --git a/netwerk/socket/nsSOCKSIOLayer.h b/netwerk/socket/nsSOCKSIOLayer.h
index dfe7c0c..54d936e 100644
--- a/netwerk/socket/nsSOCKSIOLayer.h
+++ b/netwerk/socket/nsSOCKSIOLayer.h
@@ -9,12 +9,12 @@
#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,
diff --git a/netwerk/socket/nsSOCKSSocketProvider.cpp b/netwerk/socket/nsSOCKSSocketProvider.cpp
index af7c9b5..c5a5655 100644
--- a/netwerk/socket/nsSOCKSSocketProvider.cpp
+++ b/netwerk/socket/nsSOCKSSocketProvider.cpp
@@ -44,8 +44,7 @@ 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)
@@ -59,8 +58,7 @@ nsSOCKSSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
mVersion,
flags,
sock,
@@ -77,8 +75,7 @@ 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)
@@ -86,8 +83,7 @@ nsSOCKSSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
mVersion,
flags,
sock,
diff --git a/netwerk/socket/nsUDPSocketProvider.cpp b/netwerk/socket/nsUDPSocketProvider.cpp
index 4ca7b29..f03b624 100644
--- a/netwerk/socket/nsUDPSocketProvider.cpp
+++ b/netwerk/socket/nsUDPSocketProvider.cpp
@@ -16,8 +16,7 @@ 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)
@@ -36,8 +35,7 @@ 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)
diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp
index 43bb013..a71f265 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.cpp
+++ b/security/manager/ssl/src/nsNSSIOLayer.cpp
@@ -1598,8 +1598,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 +1608,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);
@@ -2274,11 +2273,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;
}
@@ -2350,8 +2349,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 +2371,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 +2399,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 +2424,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();
}
diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h
index fca0ce8..6ba745d 100644
--- a/security/manager/ssl/src/nsNSSIOLayer.h
+++ b/security/manager/ssl/src/nsNSSIOLayer.h
@@ -10,6 +10,7 @@
#include "TransportSecurityInfo.h"
#include "nsISSLSocketControl.h"
#include "nsIClientAuthDialogs.h"
+#include "nsIProxyInfo.h"
#include "nsNSSCertificate.h"
#include "nsDataHashtable.h"
#include "nsTHashtable.h"
@@ -202,8 +203,7 @@ private:
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,
@@ -212,8 +212,7 @@ nsresult nsSSLIOLayerNewSocket(int32_t family,
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,
diff --git a/security/manager/ssl/src/nsSSLSocketProvider.cpp b/security/manager/ssl/src/nsSSLSocketProvider.cpp
index fd37f4c..0666082 100644
--- a/security/manager/ssl/src/nsSSLSocketProvider.cpp
+++ b/security/manager/ssl/src/nsSSLSocketProvider.cpp
@@ -22,8 +22,7 @@ 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)
@@ -31,8 +30,7 @@ nsSSLSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSSLIOLayerNewSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
_result,
securityInfo,
false,
@@ -45,8 +43,7 @@ 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)
@@ -54,8 +51,7 @@ nsSSLSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSSLIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
aSocket,
securityInfo,
false,
diff --git a/security/manager/ssl/src/nsTLSSocketProvider.cpp b/security/manager/ssl/src/nsTLSSocketProvider.cpp
index 029b2c5..09dd2bd 100644
--- a/security/manager/ssl/src/nsTLSSocketProvider.cpp
+++ b/security/manager/ssl/src/nsTLSSocketProvider.cpp
@@ -22,8 +22,7 @@ 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)
@@ -31,8 +30,7 @@ nsTLSSocketProvider::NewSocket(int32_t family,
nsresult rv = nsSSLIOLayerNewSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
_result,
securityInfo,
true,
@@ -46,8 +44,7 @@ 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)
@@ -55,8 +52,7 @@ nsTLSSocketProvider::AddToSocket(int32_t family,
nsresult rv = nsSSLIOLayerAddToSocket(family,
host,
port,
- proxyHost,
- proxyPort,
+ proxy,
aSocket,
securityInfo,
true,