gecko-dev/netwerk/socket/nsSOCKSSocketProvider.cpp

157 строки
5.0 KiB
C++
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
2012-05-21 15:12:37 +04:00
* 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 "nsIServiceManager.h"
#include "nsNamedPipeIOLayer.h"
#include "nsSOCKSSocketProvider.h"
#include "nsSOCKSIOLayer.h"
#include "nsCOMPtr.h"
#include "nsError.h"
using mozilla::OriginAttributes;
//////////////////////////////////////////////////////////////////////////
NS_IMPL_ISUPPORTS(nsSOCKSSocketProvider, nsISocketProvider)
nsresult
nsSOCKSSocketProvider::CreateV4(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsCOMPtr<nsISocketProvider> inst =
new nsSOCKSSocketProvider(NS_SOCKS_VERSION_4);
if (!inst)
rv = NS_ERROR_OUT_OF_MEMORY;
else
rv = inst->QueryInterface(aIID, aResult);
return rv;
}
nsresult
nsSOCKSSocketProvider::CreateV5(nsISupports *aOuter, REFNSIID aIID, void **aResult)
{
nsresult rv;
nsCOMPtr<nsISocketProvider> inst =
new nsSOCKSSocketProvider(NS_SOCKS_VERSION_5);
if (!inst)
rv = NS_ERROR_OUT_OF_MEMORY;
else
rv = inst->QueryInterface(aIID, aResult);
return rv;
}
Bug 1441327 - Allow for seccomp filtering of socket(AF_INET/AF_INET_6) calls on Linux when using UNIX Domain Sockets for SOCKS Proxy. r=bagder The initialization path for the SOCKS proxy in firefox involves creating a generic AF_INET socket, and then replacing it if the actual configuration requires something else (either AF_INET6 or AF_LOCAL). With syscall filtering configured to return an error in the event of AF_INET or AF_INET6 socket creation, this initialization path fails. We would like this capability so that we can prevent firefox from making network requests outside of the Tor proxy. This patch adds a check in the initial socket creation path to see if the SOCKS proxy host begins with file:// with the assumption that such URIs point to a UNIX Domain Socket (on Linux+macOS only). In that case, we create an AF_LOCAL socket rather than the requested type. A similar check for Windows already exists to determine if the proxy is actually a named pipe. In the subsequent replacing step no work occurs as the passed in socket matches the type we need, so no changes need to be made there. NOTE: With this change there is still a one-time request for an AF_INET6 socket that occurs. This code path exists to determine whether the system supports IPv6; if socket(AF_INET6...) fails then it is assumed that the system does not. However, this check only affects code that is unreachable when using AF_LOCAL sockets so it seems safe leave as it is. However, this does mean that firefox will still be incompatible with seccomp policies which kill the calling thread in the event of a socket(AF_INET6,...) call.
2018-03-07 20:58:00 +03:00
// Per-platform implemenation of OpenTCPSocket helper function
// Different platforms have special cases to handle
#if defined(XP_WIN)
// The proxy host on Windows may be a named pipe uri, in which
// case a named-pipe (rather than a socket) should be returned
static PRFileDesc*
OpenTCPSocket(int32_t family,
nsIProxyInfo *proxy)
{
PRFileDesc* sock = nullptr;
nsAutoCString proxyHost;
proxy->GetHost(proxyHost);
if (IsNamedPipePath(proxyHost)) {
sock = CreateNamedPipeLayer();
} else {
sock = PR_OpenTCPSocket(family);
}
return sock;
}
#elif defined(XP_UNIX)
// The proxy host on UNIX systems may point to a local file uri
// in which case we should create an AF_LOCAL (UNIX Domain) socket
// instead of the requested AF_INET or AF_INET6 socket.
// Normally,this socket would get thrown out and recreated later on
// with the proper family, but we want to do it early here so that
// we can enforce seccomp policy to blacklist socket(AF_INET) calls
// to prevent the content sandbox from creating network requests
static PRFileDesc*
OpenTCPSocket(int32_t family,
nsIProxyInfo *proxy)
{
nsAutoCString proxyHost;
proxy->GetHost(proxyHost);
if (StringBeginsWith(proxyHost, NS_LITERAL_CSTRING("file://"))) {
family = AF_LOCAL;
}
return PR_OpenTCPSocket(family);
}
#else
// Default, pass-through to PR_OpenTCPSocket
static PRFileDesc*
OpenTCPSocket(int32_t family,
nsIProxyInfo*)
{
return PR_OpenTCPSocket(family);
}
#endif
NS_IMETHODIMP
nsSOCKSSocketProvider::NewSocket(int32_t family,
const char *host,
int32_t port,
nsIProxyInfo *proxy,
const OriginAttributes &originAttributes,
uint32_t flags,
uint32_t tlsFlags,
PRFileDesc **result,
nsISupports **socksInfo)
{
Bug 1441327 - Allow for seccomp filtering of socket(AF_INET/AF_INET_6) calls on Linux when using UNIX Domain Sockets for SOCKS Proxy. r=bagder The initialization path for the SOCKS proxy in firefox involves creating a generic AF_INET socket, and then replacing it if the actual configuration requires something else (either AF_INET6 or AF_LOCAL). With syscall filtering configured to return an error in the event of AF_INET or AF_INET6 socket creation, this initialization path fails. We would like this capability so that we can prevent firefox from making network requests outside of the Tor proxy. This patch adds a check in the initial socket creation path to see if the SOCKS proxy host begins with file:// with the assumption that such URIs point to a UNIX Domain Socket (on Linux+macOS only). In that case, we create an AF_LOCAL socket rather than the requested type. A similar check for Windows already exists to determine if the proxy is actually a named pipe. In the subsequent replacing step no work occurs as the passed in socket matches the type we need, so no changes need to be made there. NOTE: With this change there is still a one-time request for an AF_INET6 socket that occurs. This code path exists to determine whether the system supports IPv6; if socket(AF_INET6...) fails then it is assumed that the system does not. However, this check only affects code that is unreachable when using AF_LOCAL sockets so it seems safe leave as it is. However, this does mean that firefox will still be incompatible with seccomp policies which kill the calling thread in the event of a socket(AF_INET6,...) call.
2018-03-07 20:58:00 +03:00
PRFileDesc *sock = OpenTCPSocket(family, proxy);
if (!sock) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
proxy,
mVersion,
flags,
tlsFlags,
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,
nsIProxyInfo *proxy,
const OriginAttributes &originAttributes,
uint32_t flags,
uint32_t tlsFlags,
PRFileDesc *sock,
nsISupports **socksInfo)
{
nsresult rv = nsSOCKSIOLayerAddToSocket(family,
host,
port,
proxy,
mVersion,
flags,
tlsFlags,
sock,
socksInfo);
if (NS_FAILED(rv))
rv = NS_ERROR_SOCKET_CREATE_FAILED;
return rv;
}