llproxy.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /**
  2. * @file llsocks5.h
  3. * @brief Socks 5 implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_PROXY_H
  33. #define LL_PROXY_H
  34. #include <string>
  35. #include "curl/curl.h"
  36. #include "llatomic.h"
  37. #include "llhost.h"
  38. #include "lliosocket.h"
  39. #include "llsingleton.h"
  40. #include "llthread.h"
  41. // SOCKS error codes returned from the StartProxy method
  42. #define SOCKS_OK 0
  43. #define SOCKS_CONNECT_ERROR (-1)
  44. #define SOCKS_NOT_PERMITTED (-2)
  45. #define SOCKS_NOT_ACCEPTABLE (-3)
  46. #define SOCKS_AUTH_FAIL (-4)
  47. #define SOCKS_UDP_FWD_NOT_GRANTED (-5)
  48. #define SOCKS_HOST_CONNECT_FAILED (-6)
  49. #define SOCKS_INVALID_HOST (-7)
  50. #ifndef MAXHOSTNAMELEN
  51. #define MAXHOSTNAMELEN (255 + 1) /* socks5: 255, +1 for len. */
  52. #endif
  53. #define SOCKSMAXUSERNAMELEN 255
  54. #define SOCKSMAXPASSWORDLEN 255
  55. #define SOCKSMINUSERNAMELEN 1
  56. #define SOCKSMINPASSWORDLEN 1
  57. #define SOCKS_VERSION 0x05 // we are using SOCKS 5
  58. #define SOCKS_HEADER_SIZE 10
  59. // SOCKS 5 address/hostname types
  60. #define ADDRESS_IPV4 0x01
  61. #define ADDRESS_HOSTNAME 0x03
  62. #define ADDRESS_IPV6 0x04
  63. // Lets just use our own IPv4 struct rather than dragging in system specific
  64. // headers
  65. union ipv4_address_t
  66. {
  67. U8 octets[4];
  68. U32 addr32;
  69. };
  70. // SOCKS 5 control channel commands
  71. #define COMMAND_TCP_STREAM 0x01
  72. #define COMMAND_TCP_BIND 0x02
  73. #define COMMAND_UDP_ASSOCIATE 0x03
  74. // SOCKS 5 command replies
  75. #define REPLY_REQUEST_GRANTED 0x00
  76. #define REPLY_GENERAL_FAIL 0x01
  77. #define REPLY_RULESET_FAIL 0x02
  78. #define REPLY_NETWORK_UNREACHABLE 0x03
  79. #define REPLY_HOST_UNREACHABLE 0x04
  80. #define REPLY_CONNECTION_REFUSED 0x05
  81. #define REPLY_TTL_EXPIRED 0x06
  82. #define REPLY_PROTOCOL_ERROR 0x07
  83. #define REPLY_TYPE_NOT_SUPPORTED 0x08
  84. #define FIELD_RESERVED 0x00
  85. // The standard SOCKS 5 request packet
  86. // Push current alignment to stack and set alignment to 1 byte boundary
  87. // This enabled us to use structs directly to set up and receive network packets
  88. // into the correct fields, without fear of boundary alignment causing issues
  89. #pragma pack(push, 1)
  90. // SOCKS 5 command packet
  91. struct socks_command_request_t
  92. {
  93. U8 version;
  94. U8 command;
  95. U8 reserved;
  96. U8 atype;
  97. U32 address;
  98. U16 port;
  99. };
  100. // Standard SOCKS 5 reply packet
  101. struct socks_command_response_t
  102. {
  103. U8 version;
  104. U8 reply;
  105. U8 reserved;
  106. U8 atype;
  107. U8 add_bytes[4];
  108. U16 port;
  109. };
  110. #define AUTH_NOT_ACCEPTABLE 0xFF // reply if preferred methods are not available
  111. #define AUTH_SUCCESS 0x00 // reply if authentication successful
  112. // SOCKS 5 authentication request, stating which methods the client supports
  113. struct socks_auth_request_t
  114. {
  115. U8 version;
  116. U8 num_methods;
  117. U8 methods; // We are only using a single method currently
  118. };
  119. // SOCKS 5 authentication response packet, stating server preferred method
  120. struct socks_auth_response_t
  121. {
  122. U8 version;
  123. U8 method;
  124. };
  125. // SOCKS 5 password reply packet
  126. struct authmethod_password_reply_t
  127. {
  128. U8 version;
  129. U8 status;
  130. };
  131. // SOCKS 5 UDP packet header
  132. struct proxywrap_t
  133. {
  134. U16 rsv;
  135. U8 frag;
  136. U8 atype;
  137. U32 addr;
  138. U16 port;
  139. };
  140. #pragma pack(pop) // Restore original alignment from stack
  141. // Currently selected HTTP proxy type
  142. enum LLHttpProxyType
  143. {
  144. LLPROXY_SOCKS = 0,
  145. LLPROXY_HTTP = 1
  146. };
  147. // Auth types
  148. enum LLSocks5AuthType
  149. {
  150. METHOD_NOAUTH = 0x00, // Client supports no auth
  151. METHOD_GSSAPI = 0x01, // Client supports GSSAPI (Not currently supported)
  152. METHOD_PASSWORD = 0x02 // Client supports username/password
  153. };
  154. // LLProxy is responsible for managing two interconnected tasks, connecting to
  155. // a SOCKS 5 proxy for use by LLPacketRing to send UDP packets and managing
  156. // proxy settings for HTTP requests.
  157. //
  158. // Threading:
  159. // Because HTTP requests can be generated in threads outside the main thread,
  160. // it is necessary for some of the information stored by this class to be
  161. // available to other threads. The members that need to be read across threads
  162. // are in a labeled section below. To protect those members, a mutex,
  163. // mProxyMutex should be locked before reading or writing those members.
  164. // Methods that can lock mProxyMutex are in a labeled section below. Those
  165. // methods should not be called while the mutex is already locked.
  166. //
  167. // There is also a LLAtomic type flag (mHTTPProxyEnabled) that is used to track
  168. // whether the HTTP proxy is currently enabled. This allows for faster unlocked
  169. // checks to see if the proxy is enabled. This allows us to cut down on the
  170. // performance hit when the proxy is disabled compared to before this class was
  171. // introduced.
  172. //
  173. // UDP Proxying:
  174. // UDP datagrams are proxied via a SOCKS 5 proxy with the UDP associate
  175. // command. To initiate the proxy, a TCP socket connection is opened to the
  176. // SOCKS 5 host, and after a handshake exchange, the server returns a port and
  177. // address to send the UDP traffic that is to be proxied to. The LLProxy class
  178. // tracks this address and port after the exchange and provides it to
  179. // LLPacketRing when required to. All UDP proxy management occurs in the main
  180. // thread.
  181. //
  182. // HTTP Proxying:
  183. // This class allows all viewer HTTP packets to be sent through a proxy. The
  184. // user can select whether to send HTTP packets through a standard "web" HTTP
  185. // proxy, through a SOCKS 5 proxy, or to not proxy HTTP communication. This
  186. // class does not manage the integrated web browser proxy, which is handled in
  187. // llviewermedia.cpp.
  188. //
  189. // The implementation of HTTP proxying is handled by libcurl. LLProxy is
  190. // responsible for managing the HTTP proxy options and provides a thread-safe
  191. // method to apply those options to a curl request (via
  192. // LLProxy::applyProxySettings()). This method is overloaded to accommodate the
  193. // various abstraction libcurl layers that exist throughout the viewer (CURL).
  194. //
  195. // To ensure thread safety, all LLProxy members that relate to the HTTP proxy
  196. // require the LLProxyMutex to be locked before accessing.
  197. class LLProxy final : public LLSingleton<LLProxy>
  198. {
  199. friend class LLSingleton<LLProxy>;
  200. protected:
  201. LOG_CLASS(LLProxy);
  202. public:
  203. // ########################################################################
  204. // METHODS THAT DO NOT LOCK mProxyMutex !
  205. // ########################################################################
  206. // Constructor, cannot have parameters due to LLSingleton parent class.
  207. // Call from main thread only.
  208. LLProxy();
  209. // Static check for enabled status for UDP packets. Call from main thread
  210. // only.
  211. LL_INLINE static bool isSOCKSProxyEnabled() { return sUDPProxyEnabled; }
  212. // Get the UDP proxy address and port. Call from main thread only.
  213. LL_INLINE LLHost getUDPProxy() const { return mUDPProxy; }
  214. // ########################################################################
  215. // METHODS THAT DO LOCK mProxyMutex ! DO NOT CALL WHILE mProxyMutex IS
  216. // LOCKED !
  217. // ########################################################################
  218. // Destructor, closes open connections. Do not call directly, use
  219. // cleanupClass().
  220. ~LLProxy();
  221. // Delete LLProxy singleton. Allows the apr_socket used in the SOCKS 5
  222. // control channel to be destroyed before the call to apr_terminate. Call
  223. // from main thread only.
  224. static void cleanupClass();
  225. // Apply the current proxy settings to a curl request. Does not do anything
  226. // if mHTTPProxyEnabled is false. Safe to call from any thread.
  227. void applyProxySettings(CURL* handle);
  228. // Start a connection to the SOCKS 5 proxy. Call from main thread only.
  229. S32 startSOCKSProxy(LLHost host);
  230. // Disconnect and clean up any connection to the SOCKS 5 proxy. Call from
  231. // main thread only.
  232. void stopSOCKSProxy();
  233. // Use Password auth when connecting to the SOCKS proxy. Call from main
  234. // thread only.
  235. bool setAuthPassword(const std::string& username,
  236. const std::string& password);
  237. // Disable authentication when connecting to the SOCKS proxy. Call from
  238. // main thread only.
  239. void setAuthNone();
  240. // Proxy HTTP packets via httpHost, which can be a SOCKS 5 or a HTTP proxy.
  241. // as specified in type. Call from main thread only.
  242. bool enableHTTPProxy(LLHost http_host, LLHttpProxyType type);
  243. bool enableHTTPProxy();
  244. // Stop proxying HTTP packets. Call from main thread only.
  245. void disableHTTPProxy();
  246. private:
  247. // ########################################################################
  248. // METHODS THAT DO LOCK mProxyMutex ! DO NOT CALL WHILE mProxyMutex IS
  249. // LOCKED !
  250. // ########################################################################
  251. // Perform a SOCKS 5 authentication and UDP association with the proxy server.
  252. S32 proxyHandshake(LLHost proxy);
  253. // Get the currently selected auth method.
  254. LLSocks5AuthType getSelectedAuthMethod() const;
  255. // Get the currently selected HTTP proxy type
  256. LLHttpProxyType getHTTPProxyType() const;
  257. std::string getSocksPwd() const;
  258. std::string getSocksUser() const;
  259. private:
  260. // Is the HTTP proxy enabled ? Safe to read in any thread, but do not write
  261. // directly. Instead use enableHTTPProxy() and disableHTTPProxy() instead.
  262. mutable LLAtomicBool mHTTPProxyEnabled;
  263. // Mutex to protect shared members in non-main thread calls to
  264. // applyProxySettings().
  265. mutable LLMutex mProxyMutex;
  266. // ########################################################################
  267. // MEMBERS READ AND WRITTEN ONLY IN THE MAIN THREAD. DO NOT SHARE !
  268. // ########################################################################
  269. // Is the UDP proxy enabled ?
  270. static bool sUDPProxyEnabled;
  271. // UDP proxy address and port
  272. LLHost mUDPProxy;
  273. // TCP proxy control channel address and port
  274. LLHost mTCPProxy;
  275. // socket handle to proxy TCP control channel
  276. LLSocket::ptr_t mProxyControlChannel;
  277. // ########################################################################
  278. // MEMBERS WRITTEN IN MAIN THREAD AND READ IN ANY THREAD. ONLY READ OR
  279. // WRITE AFTER LOCKING mProxyMutex !
  280. // ########################################################################
  281. // HTTP proxy address and port
  282. LLHost mHTTPProxy;
  283. // Currently selected HTTP proxy type. Can be web or socks.
  284. LLHttpProxyType mProxyType;
  285. // SOCKS 5 selected authentication method.
  286. LLSocks5AuthType mAuthMethodSelected;
  287. // SOCKS 5 username
  288. std::string mSocksUsername;
  289. // SOCKS 5 password
  290. std::string mSocksPassword;
  291. };
  292. #endif