249 lines
7.0 KiB
C++
249 lines
7.0 KiB
C++
/**
|
|
* @file llsocks5.h
|
|
* @brief Socks 5 implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2001-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at
|
|
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#ifndef LL_SOCKS5_H
|
|
#define LL_SOCKS5_H
|
|
|
|
#include "llhost.h"
|
|
#include "llmemory.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
|
|
|
|
// 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 {
|
|
unsigned char octects[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 replys
|
|
#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 socks5 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)
|
|
|
|
// Socks5 command packet
|
|
struct socks_command_request_t {
|
|
unsigned char version;
|
|
unsigned char command;
|
|
unsigned char flag;
|
|
unsigned char atype;
|
|
U32 address;
|
|
U16 port;
|
|
};
|
|
|
|
// Standard socks5 reply packet
|
|
struct socks_command_response_t {
|
|
unsigned char version;
|
|
unsigned char reply;
|
|
unsigned char flag;
|
|
unsigned char atype;
|
|
unsigned char add_bytes[4];
|
|
U16 port;
|
|
};
|
|
|
|
#define AUTH_NOT_ACCEPTABLE 0xFF // reply if prefered methods are not avaiable
|
|
#define AUTH_SUCCESS 0x00 // reply if authentication successfull
|
|
|
|
// socks 5 authentication request, stating which methods the client supports
|
|
struct socks_auth_request_t {
|
|
unsigned char version;
|
|
unsigned char num_methods;
|
|
unsigned char methods; // We are only using a single method currently
|
|
};
|
|
|
|
// socks 5 authentication response packet, stating server prefered method
|
|
struct socks_auth_response_t {
|
|
unsigned char version;
|
|
unsigned char method;
|
|
};
|
|
|
|
// socks 5 password reply packet
|
|
struct authmethod_password_reply_t {
|
|
unsigned char version;
|
|
unsigned char 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 LLSocks: public LLSingleton<LLSocks>
|
|
{
|
|
public:
|
|
LLSocks();
|
|
|
|
// Start a connection to the socks 5 proxy
|
|
int startProxy(std::string host,U32 port);
|
|
int startProxy(LLHost proxy,U32 messagePort);
|
|
|
|
// Disconnect and clean up any connection to the socks 5 proxy
|
|
void stopProxy();
|
|
|
|
// Set up to use Password auth when connecting to the socks proxy
|
|
void setAuthPassword(std::string username,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() { 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 Socks5 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 getUDPPproxy(){return mUDPProxy;};
|
|
// get the socks 5 TCP control channel address and port
|
|
LLHost getTCPProxy(){return mTCPProxy;};
|
|
//get the http proxy address and port
|
|
LLHost getHTTPProxy(){return mHTTPProxy;};
|
|
|
|
// get the currently selected http proxy type
|
|
LLHttpProxyType getHttpProxyType(){return mProxyType;};
|
|
|
|
// mark that we need an update due to a settings change
|
|
void updated() { mNeedUpdate = true; };
|
|
// report if the current settings are applied or dirty pending a startProxy
|
|
bool needsUpdate() { return mNeedUpdate; };
|
|
|
|
//Get the username password in a curl compatible format
|
|
std::string getProxyUserPwd(){ return (mSocksUsername+":"+mSocksPassword);};
|
|
|
|
private:
|
|
|
|
// Open a communication channel to the socks5 proxy proxy, at port messagePort
|
|
int proxyHandshake(LLHost proxy,U32 messagePort);
|
|
|
|
// socket handle to proxy tcp control channel
|
|
S32 hProxyControlChannel;
|
|
|
|
// is the UDP proxy enabled
|
|
static bool sUdpProxyEnabled;
|
|
// is the http proxy enabled
|
|
static bool sHttpProxyEnabled;
|
|
|
|
// Have all settings been applied
|
|
bool mNeedUpdate;
|
|
|
|
// 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;
|
|
};
|
|
|
|
#endif
|