aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmessage/llsocks5.h
blob: d422d20c2e9ddc4c3eebe08763255fa1182c29d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/** 
 * @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