/** * @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 // 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 { 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