phoenix-firestorm/indra/llmessage/llproxy.h

250 lines
6.7 KiB
C++

/**
* @file llsocks5.h
* @brief Socks 5 implementation
*
* $LicenseInfo:firstyear=2011&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LL_PROXY_H
#define LL_PROXY_H
#include "llhost.h"
#include "lliosocket.h"
#include "llmemory.h"
#include "llsingleton.h"
#include <string>
// Error codes returned from the StartProxy method
#define SOCKS_OK 0
#define SOCKS_CONNECT_ERROR (-1)
#define SOCKS_NOT_PERMITTED (-2)
#define SOCKS_NOT_ACCEPTABLE (-3)
#define SOCKS_AUTH_FAIL (-4)
#define SOCKS_UDP_FWD_NOT_GRANTED (-5)
#define SOCKS_HOST_CONNECT_FAILED (-6)
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
#endif
#define SOCKS_VERSION 0x05 // we are using SOCKS 5
#define SOCKS_HEADER_SIZE 10
// SOCKS 5 address/hostname types
#define ADDRESS_IPV4 0x01
#define ADDRESS_HOSTNAME 0x03
#define ADDRESS_IPV6 0x04
// Lets just use our own ipv4 struct rather than dragging in system
// specific headers
union ipv4_address_t {
U8 octets[4];
U32 addr32;
};
// SOCKS 5 control channel commands
#define COMMAND_TCP_STREAM 0x01
#define COMMAND_TCP_BIND 0x02
#define COMMAND_UDP_ASSOCIATE 0x03
// SOCKS 5 command replies
#define REPLY_REQUEST_GRANTED 0x00
#define REPLY_GENERAL_FAIL 0x01
#define REPLY_RULESET_FAIL 0x02
#define REPLY_NETWORK_UNREACHABLE 0x03
#define REPLY_HOST_UNREACHABLE 0x04
#define REPLY_CONNECTION_REFUSED 0x05
#define REPLY_TTL_EXPIRED 0x06
#define REPLY_PROTOCOL_ERROR 0x07
#define REPLY_TYPE_NOT_SUPPORTED 0x08
#define FIELD_RESERVED 0x00
// The standard SOCKS 5 request packet
// Push current alignment to stack and set alignment to 1 byte boundary
// This enabled us to use structs directly to set up and receive network packets
// into the correct fields, without fear of boundary alignment causing issues
#pragma pack(push,1)
// SOCKS 5 command packet
struct socks_command_request_t {
U8 version;
U8 command;
U8 reserved;
U8 atype;
U32 address;
U16 port;
};
// Standard SOCKS 5 reply packet
struct socks_command_response_t {
U8 version;
U8 reply;
U8 reserved;
U8 atype;
U8 add_bytes[4];
U16 port;
};
#define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available
#define AUTH_SUCCESS 0x00 // reply if authentication successful
// SOCKS 5 authentication request, stating which methods the client supports
struct socks_auth_request_t {
U8 version;
U8 num_methods;
U8 methods; // We are only using a single method currently
};
// SOCKS 5 authentication response packet, stating server preferred method
struct socks_auth_response_t {
U8 version;
U8 method;
};
// SOCKS 5 password reply packet
struct authmethod_password_reply_t {
U8 version;
U8 status;
};
// SOCKS 5 UDP packet header
struct proxywrap_t {
U16 rsv;
U8 frag;
U8 atype;
U32 addr;
U16 port;
};
#pragma pack(pop) /* restore original alignment from stack */
// Currently selected HTTP proxy type
enum LLHttpProxyType
{
LLPROXY_SOCKS = 0,
LLPROXY_HTTP = 1
};
// Auth types
enum LLSocks5AuthType
{
METHOD_NOAUTH = 0x00, // Client supports no auth
METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported)
METHOD_PASSWORD = 0x02 // Client supports username/password
};
class LLProxy: public LLSingleton<LLProxy>
{
public:
LLProxy();
~LLProxy();
// Start a connection to the SOCKS 5 proxy
S32 startProxy(std::string host, U32 port);
// Disconnect and clean up any connection to the SOCKS 5 proxy
void stopProxy();
// Delete LLProxy singleton, destroying the APR pool used by the control channel.
static void cleanupClass();
// Set up to use Password auth when connecting to the SOCKS proxy
void setAuthPassword(const std::string &username, const std::string &password);
// Set up to use No Auth when connecting to the SOCKS proxy
void setAuthNone();
// get the currently selected auth method
LLSocks5AuthType getSelectedAuthMethod() const { return mAuthMethodSelected; }
// static check for enabled status for UDP packets
static bool isEnabled() { return sUDPProxyEnabled; }
// static check for enabled status for http packets
static bool isHTTPProxyEnabled() { return sHTTPProxyEnabled; }
// Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy
// as specified in type
void enableHTTPProxy(LLHost httpHost, LLHttpProxyType type);
// Stop proxying HTTP packets
void disableHTTPProxy() { sHTTPProxyEnabled = false; };
// Get the UDP proxy address and port
LLHost getUDPProxy() const { return mUDPProxy; }
// Get the SOCKS 5 TCP control channel address and port
LLHost getTCPProxy() const { return mTCPProxy; }
// Get the HTTP proxy address and port
LLHost getHTTPProxy() const { return mHTTPProxy; }
// Get the currently selected HTTP proxy type
LLHttpProxyType getHTTPProxyType() const { return mProxyType; }
// Get the username password in a curl compatible format
std::string getProxyUserPwdCURL() const { return (mSocksUsername + ":" + mSocksPassword); }
std::string getSocksPwd() const { return mSocksPassword; }
std::string getSocksUser() const { return mSocksUsername; }
private:
// Open a communication channel to the SOCKS 5 proxy proxy, at port messagePort
S32 proxyHandshake(LLHost proxy, U32 messagePort);
// socket handle to proxy TCP control channel
LLSocket::ptr_t mProxyControlChannel;
// is the UDP proxy enabled?
static bool sUDPProxyEnabled;
// is the http proxy enabled?
static bool sHTTPProxyEnabled;
// currently selected http proxy type
LLHttpProxyType mProxyType;
// UDP proxy address and port
LLHost mUDPProxy;
// TCP Proxy control channel address and port
LLHost mTCPProxy;
// HTTP proxy address and port
LLHost mHTTPProxy;
// SOCKS 5 auth method selected
LLSocks5AuthType mAuthMethodSelected;
// SOCKS 5 username
std::string mSocksUsername;
// SOCKS 5 password
std::string mSocksPassword;
// APR pool for the socket
apr_pool_t* mPool;
};
#endif