1//
2// This file is part of the aMule Project.
3//
4// Copyright (c) 2004-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5// Copyright (c) 2004-2011 Marcelo Roberto Jimenez ( phoenix@amule.org )
6//
7// Any parts of this program derived from the xMule, lMule or eMule project,
8// or contributed by third-party developers are copyrighted by their
9// respective authors.
10//
11// This program is free software; you can redistribute it and/or modify
12// it under the terms of the GNU General Public License as published by
13// the Free Software Foundation; either version 2 of the License, or
14// (at your option) any later version.
15//
16// This program is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19// GNU General Public License for more details.
20//
21// You should have received a copy of the GNU General Public License
22// along with this program; if not, write to the Free Software
23// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24//
25
26#ifndef __PROXY_H__
27#define __PROXY_H__
28
29#include <wx/wx.h>
30
31#include "amuleIPV4Address.h"	// For amuleIPV4address
32#include "StateMachine.h"	// For CStateMachine
33
34/******************************************************************************/
35
36/*
37 * SOCKS4 protocol implementation according to:
38 * - "SOCKS: A protocol for TCP proxy across firewalls":
39 *   amule-root/docs/socks4.protocol
40 */
41const unsigned char SOCKS4_VERSION = 0x04;
42
43const unsigned char SOCKS4_CMD_CONNECT	= 0x01;
44const unsigned char SOCKS4_CMD_BIND	= 0x02;
45
46const unsigned char SOCKS4_REPLY_CODE				= 0;
47const unsigned char SOCKS4_REPLY_GRANTED			= 90;
48const unsigned char SOCKS4_REPLY_FAILED				= 91;
49const unsigned char SOCKS4_REPLY_FAILED_NO_IDENTD		= 92;
50const unsigned char SOCKS4_REPLY_FAILED_DIFFERENT_USERIDS	= 93;
51
52/*
53 * SOCKS5 protocol implementation according to:
54 * - RFC-1928: SOCKS Protocol Version 5
55 * - RFC-1929: username/password Authentication for SOCKS V5
56 *
57 * Also, for the future :) :
58 * - RFC-1961: GSS-API Authentication Method for SOCKS Version 5
59 * - RFC-1508: Generic Security Service Application Program Interface
60 * - RFC-1509: Genecic Security Service API: C-bindings
61 *
62 */
63
64const unsigned char SOCKS5_VERSION = 0x05;
65
66const unsigned char SOCKS5_AUTH_METHOD_NO_AUTH_REQUIRED		= 0x00;
67const unsigned char SOCKS5_AUTH_METHOD_GSSAPI			= 0x01;
68const unsigned char SOCKS5_AUTH_METHOD_USERNAME_PASSWORD	= 0x02;
69const unsigned char SOCKS5_AUTH_METHOD_NO_ACCEPTABLE_METHODS	= 0xFF;
70
71const unsigned char SOCKS5_AUTH_VERSION_USERNAME_PASSWORD	= 0x01;
72
73const unsigned char SOCKS5_CMD_CONNECT		= 0x01;
74const unsigned char SOCKS5_CMD_BIND		= 0x02;
75const unsigned char SOCKS5_CMD_UDP_ASSOCIATE	= 0x03;
76
77const unsigned char SOCKS5_RSV = 0x00;
78
79const unsigned char SOCKS5_ATYP_IPV4_ADDRESS	= 0x01;
80const unsigned char SOCKS5_ATYP_DOMAINNAME	= 0x03;
81const unsigned char SOCKS5_ATYP_IPV6_ADDRESS	= 0x04;
82
83const unsigned char SOCKS5_REPLY_SUCCEED		= 0x00;
84const unsigned char SOCKS5_REPLY_GENERAL_SERVER_FAILURE	= 0x01;
85const unsigned char SOCKS5_REPLY_CONNECTION_NOT_ALLOWED	= 0x02;
86const unsigned char SOCKS5_REPLY_NETWORK_UNREACHABLE	= 0x03;
87const unsigned char SOCKS5_REPLY_HOST_UNREACHABLE	= 0x04;
88const unsigned char SOCKS5_REPLY_CONNECTION_REFUSED	= 0x05;
89const unsigned char SOCKS5_REPLY_TTL_EXPIRED		= 0x06;
90const unsigned char SOCKS5_REPLY_COMMAND_NOT_SUPPORTED	= 0x07;
91const unsigned char SOCKS5_REPLY_ATYP_NOT_SUPPORTED	= 0x08;
92
93//------------------------------------------------------------------------------
94// CProxyType
95//------------------------------------------------------------------------------
96
97/*
98 * These constants must match the integer values saved in the configuration file,
99 * DO NOT CHANGE THIS ORDER!!!
100 */
101enum CProxyType {
102	PROXY_NONE = -1,
103	PROXY_SOCKS5,
104	PROXY_SOCKS4,
105	PROXY_HTTP,
106	PROXY_SOCKS4a
107};
108
109
110//------------------------------------------------------------------------------
111// CProxyData
112//------------------------------------------------------------------------------
113/**
114 * The ProxyData class will hold information about the proxy server to be used.
115 */
116class CProxyData
117{
118public:
119	/**
120	 * Default constructor.
121	 */
122	CProxyData();
123	/**
124	 * Constructor.
125	 *
126	 * @param proxyEnable	Whether proxy is enabled or not.
127	 * @param proxyType	The type of the proxy server.
128	 * @param proxyHostName	The proxy host name or IP address.
129	 * @param proxyPort	The proxy port number.
130	 * @param enablePassword Whether authentication should be performed.
131	 * @param userName	The user name to authenticate to the server.
132	 * @param password	The password to authenticate to the server.
133	 */
134	CProxyData(
135		bool		proxyEnable,
136		CProxyType	proxyType,
137		const wxString	&proxyHostName,
138		unsigned short	proxyPort,
139		bool		enablePassword,
140		const wxString	&userName,
141		const wxString	&password
142	);
143	/**
144	 * Clears the object contents.
145	 */
146	void Clear();
147
148public:
149	//! Whether proxy is enabled or not.
150	bool		m_proxyEnable;
151	//! The type of the proxy server.
152	CProxyType	m_proxyType;
153	//! The proxy host name or IP address.
154	wxString	m_proxyHostName;
155	//! The proxy port number.
156	unsigned short	m_proxyPort;
157	//! Whether authentication should be performed.
158	bool		m_enablePassword;
159	//! The user name to authenticate to the server.
160	wxString	m_userName;
161	//! The password to authenticate to the server.
162	wxString	m_password;
163};
164
165//------------------------------------------------------------------------------
166// CProxyEventHandler
167//------------------------------------------------------------------------------
168/**
169 * Event handler object used during proxy negotiation.
170 */
171class CProxyEventHandler : public wxEvtHandler {
172public:
173	/**
174	 * Constructor.
175	 */
176	CProxyEventHandler();
177
178private:
179	/**
180	 * Event handler function.
181	 */
182	void ProxySocketHandler(wxSocketEvent &event);
183	DECLARE_EVENT_TABLE()
184};
185
186//------------------------------------------------------------------------------
187// CProxyStateMachine
188//------------------------------------------------------------------------------
189/* This size is just to be a little bit greater than the UDP buffer used in aMule.
190 * Proxy protocol needs much less than this. 1024 would be ok. Other options are
191 * - Default ethernet MTU - Eth-II - IP - UDP: 1,514 - 14 - 20 - 8 = 1472 bytes;
192 * - Default token ring MTU 4,202 - overheads = ??.
193 * It would be really more efficient if the final object was less than
194 * a page (4096 bytes) in size.
195 */
196//const unsigned int PROXY_BUFFER_SIZE = 1024;
197const unsigned int PROXY_BUFFER_SIZE = 5*1024;
198
199enum CProxyCommand {
200	PROXY_CMD_CONNECT,
201	PROXY_CMD_BIND,
202	PROXY_CMD_UDP_ASSOCIATE
203};
204
205enum CProxyState {
206	PROXY_STATE_START = 0,
207	PROXY_STATE_END = 1
208};
209
210/**
211 * The ProxyStateMachine class is the ancestor of all proxy classes.
212 *
213 * CProxyStateMachine will do all the common work that a proxy class must do
214 * and provide the necessary variables.
215 */
216class CProxyStateMachine : public CStateMachine
217{
218public:
219	/**
220	 * Constructor.
221	 *
222	 * @param name		The name of the state machine. For debug messages only.
223	 * @param max_states	The maximum number of states that this machine will have.
224	 * @param proxyData	The necessary proxy information.
225	 * @param cmd		The type of proxy command to run.
226	 */
227	CProxyStateMachine(
228		wxString name,
229		const unsigned int max_states,
230		const CProxyData &proxyData,
231		CProxyCommand cmd);
232	/**
233	 * Destructor.
234	 */
235	virtual ~CProxyStateMachine();
236	/**
237	 * Adds a small string to the state machine name, containing the proxy command.
238	 *
239	 * @param s	The original state machine name.
240	 * @param cmd	The proxy command.
241	 */
242	static wxString	&NewName(wxString &s, CProxyCommand cmd);
243
244	/* Interface */
245	bool		Start(const wxIPaddress &peerAddress, wxSocketClient *proxyClientSocket);
246	t_sm_state	HandleEvent(t_sm_event event);
247	void		AddDummyEvent();
248	void		ReactivateSocket();
249	char 		*GetBuffer()				{ return m_buffer; }
250	wxIPaddress	&GetProxyBoundAddress(void) const	{ return *m_proxyBoundAddress; }
251	unsigned char	GetLastReply(void) const		{ return m_lastReply; }
252	bool		IsEndState() const			{ return GetState() == PROXY_STATE_END; }
253
254protected:
255	wxSocketBase		&ProxyWrite(wxSocketBase &socket, const void *buffer, wxUint32 nbytes);
256	wxSocketBase		&ProxyRead(wxSocketBase &socket, void *buffer);
257	bool		CanReceive() const;
258	bool		CanSend() const;
259	//
260	// Initialized at constructor
261	//
262	const CProxyData	&m_proxyData;
263	CProxyCommand		m_proxyCommand;
264	//
265	// Member variables
266	//
267	char			m_buffer[PROXY_BUFFER_SIZE];
268	bool			m_isLost;
269	bool			m_isConnected;
270	bool			m_canReceive;
271	bool			m_canSend;
272	bool			m_ok;
273	unsigned int		m_lastRead;
274	unsigned int		m_lastWritten;
275	wxSocketError		m_lastError;
276	//
277	// Will be initialized at Start()
278	//
279	wxIPaddress		*m_peerAddress;
280	wxSocketClient		*m_proxyClientSocket;
281	wxIPaddress		*m_proxyBoundAddress;
282	amuleIPV4Address	m_proxyBoundAddressIPV4;
283	//wxIPV6address		m_proxyBoundAddressIPV6;
284	//
285	// Temporary variables
286	//
287	unsigned char		m_lastReply;
288	unsigned int		m_packetLenght;
289};
290
291//------------------------------------------------------------------------------
292// CSocks5StateMachine
293//------------------------------------------------------------------------------
294class CSocks5StateMachine;
295typedef void (CSocks5StateMachine::*Socks5StateProcessor)(bool entry);
296class CSocks5StateMachine : public CProxyStateMachine
297{
298private:
299	static const unsigned int SOCKS5_MAX_STATES = 14;
300
301	enum Socks5State {
302		SOCKS5_STATE_START = PROXY_STATE_START,
303		SOCKS5_STATE_END = PROXY_STATE_END,
304		SOCKS5_STATE_SEND_QUERY_AUTHENTICATION_METHOD,
305		SOCKS5_STATE_RECEIVE_AUTHENTICATION_METHOD,
306		SOCKS5_STATE_PROCESS_AUTHENTICATION_METHOD,
307		SOCKS5_STATE_SEND_AUTHENTICATION_GSSAPI,
308		SOCKS5_STATE_RECEIVE_AUTHENTICATION_GSSAPI,
309		SOCKS5_STATE_PROCESS_AUTHENTICATION_GSSAPI,
310		SOCKS5_STATE_SEND_AUTHENTICATION_USERNAME_PASSWORD,
311		SOCKS5_STATE_RECEIVE_AUTHENTICATION_USERNAME_PASSWORD,
312		SOCKS5_STATE_PROCESS_AUTHENTICATION_USERNAME_PASSWORD,
313		SOCKS5_STATE_SEND_COMMAND_REQUEST,
314		SOCKS5_STATE_RECEIVE_COMMAND_REPLY,
315		SOCKS5_STATE_PROCESS_COMMAND_REPLY
316	};
317
318public:
319	/* Constructor */
320	CSocks5StateMachine(
321		const CProxyData &proxyData,
322		CProxyCommand proxyCommand);
323	void process_state(t_sm_state state, bool entry);
324	t_sm_state next_state(t_sm_event event);
325
326private:
327	/* State Processors */
328	void process_start(bool entry);
329	void process_send_query_authentication_method(bool entry);
330	void process_receive_authentication_method(bool entry);
331	void process_process_authentication_method(bool entry);
332	void process_send_authentication_gssapi(bool entry);
333	void process_receive_authentication_gssapi(bool entry);
334	void process_process_authentication_gssapi(bool entry);
335	void process_send_authentication_username_password(bool entry);
336	void process_receive_authentication_username_password(bool entry);
337	void process_process_authentication_username_password(bool entry);
338	void process_send_command_request(bool entry);
339	void process_receive_command_reply(bool entry);
340	void process_process_command_reply(bool entry);
341	void process_end(bool entry);
342	/* Private Vars */
343	Socks5StateProcessor m_process_state[SOCKS5_MAX_STATES];
344	wxString m_state_name[SOCKS5_MAX_STATES];
345};
346
347//------------------------------------------------------------------------------
348// CSocks4StateMachine
349//------------------------------------------------------------------------------
350class CSocks4StateMachine;
351typedef void (CSocks4StateMachine::*Socks4StateProcessor)(bool entry);
352class CSocks4StateMachine : public CProxyStateMachine
353{
354private:
355	static const unsigned int SOCKS4_MAX_STATES = 5;
356
357	enum Socks4State {
358		SOCKS4_STATE_START = PROXY_STATE_START,
359		SOCKS4_STATE_END = PROXY_STATE_END,
360		SOCKS4_STATE_SEND_COMMAND_REQUEST,
361		SOCKS4_STATE_RECEIVE_COMMAND_REPLY,
362		SOCKS4_STATE_PROCESS_COMMAND_REPLY
363	};
364
365public:
366	/* Constructor */
367	CSocks4StateMachine(
368		const CProxyData &proxyData,
369		CProxyCommand proxyCommand);
370	void process_state(t_sm_state state, bool entry);
371	t_sm_state next_state(t_sm_event event);
372
373private:
374	/* State Processors */
375	void process_start(bool entry);
376	void process_send_command_request(bool entry);
377	void process_receive_command_reply(bool entry);
378	void process_process_command_reply(bool entry);
379	void process_end(bool entry);
380	/* Private Vars */
381	Socks4StateProcessor m_process_state[SOCKS4_MAX_STATES];
382	wxString m_state_name[SOCKS4_MAX_STATES];
383};
384
385//------------------------------------------------------------------------------
386// CHttpStateMachine
387//------------------------------------------------------------------------------
388class CHttpStateMachine;
389typedef void (CHttpStateMachine::*HttpStateProcessor)(bool entry);
390class CHttpStateMachine : public CProxyStateMachine
391{
392private:
393	static const unsigned int HTTP_MAX_STATES = 5;
394
395	enum HttpState {
396		HTTP_STATE_START = PROXY_STATE_START,
397		HTTP_STATE_END = PROXY_STATE_END,
398		HTTP_STATE_SEND_COMMAND_REQUEST,
399		HTTP_STATE_RECEIVE_COMMAND_REPLY,
400		HTTP_STATE_PROCESS_COMMAND_REPLY
401	};
402
403public:
404	/* Constructor */
405	CHttpStateMachine(
406		const CProxyData &proxyData,
407		CProxyCommand proxyCommand);
408	void process_state(t_sm_state state, bool entry);
409	t_sm_state next_state(t_sm_event event);
410
411private:
412	/* State Processors */
413	void process_start(bool entry);
414	void process_send_command_request(bool entry);
415	void process_receive_command_reply(bool entry);
416	void process_process_command_reply(bool entry);
417	void process_end(bool entry);
418	/* Private Vars */
419	HttpStateProcessor m_process_state[HTTP_MAX_STATES];
420	wxString m_state_name[HTTP_MAX_STATES];
421};
422
423//------------------------------------------------------------------------------
424// CProxySocket
425//------------------------------------------------------------------------------
426
427class CDatagramSocketProxy;
428
429class CProxySocket : public wxSocketClient
430{
431friend class CProxyEventHandler;
432public:
433	/* Constructor */
434	CProxySocket(
435		wxSocketFlags flags = wxSOCKET_NONE,
436		const CProxyData *proxyData = NULL,
437		CProxyCommand proxyCommand = PROXY_CMD_CONNECT,
438		CDatagramSocketProxy *udpSocket = NULL);
439
440	/* Destructor */
441	~CProxySocket();
442
443	/* I know, this is not very good, because SetEventHandler is not
444	 * virtual in wxSocketBase, but I need to GetEventHandler in Proxy.cpp,
445	 * so...
446	 */
447	void SetEventHandler(wxEvtHandler &handler, int id = wxID_ANY)
448	{
449		m_socketEventHandler = &handler;
450		m_socketEventHandlerId = id;
451		wxSocketClient::SetEventHandler(handler, id);
452	}
453	wxEvtHandler *GetEventHandler(void)	const { return m_socketEventHandler; }
454	int GetEventHandlerId(void)		const { return m_socketEventHandlerId; }
455	void SaveEventHandler(void)
456	{
457		m_savedSocketEventHandler = m_socketEventHandler;
458		m_savedSocketEventHandlerId = m_socketEventHandlerId;
459	}
460	void RestoreEventHandler(void)
461	{
462		m_socketEventHandler = m_savedSocketEventHandler;
463		m_socketEventHandlerId = m_savedSocketEventHandlerId;
464		SetEventHandler(*m_socketEventHandler, m_socketEventHandlerId);
465	}
466
467	/* Interface */
468	void		SetProxyData(const CProxyData *proxyData);
469	bool		GetUseProxy() const	{ return m_useProxy; }
470	char 		*GetBuffer()		{ return m_proxyStateMachine->GetBuffer(); }
471	wxIPaddress	&GetProxyBoundAddress(void) const
472						{ return m_proxyStateMachine->GetProxyBoundAddress(); }
473	bool Start(const wxIPaddress &peerAddress);
474	bool ProxyIsCapableOf(CProxyCommand proxyCommand) const;
475	bool ProxyNegotiationIsOver() const	{ return m_proxyStateMachine->IsEndState(); }
476	CDatagramSocketProxy *GetUDPSocket() const { return m_udpSocket; }
477
478private:
479	bool			m_useProxy;
480	CProxyData		m_proxyData;
481	amuleIPV4Address	m_proxyAddress;
482	CProxyStateMachine	*m_proxyStateMachine;
483	CDatagramSocketProxy	*m_udpSocket;
484	wxEvtHandler		*m_socketEventHandler;
485	int			m_socketEventHandlerId;
486	wxEvtHandler		*m_savedSocketEventHandler;
487	int			m_savedSocketEventHandlerId;
488};
489
490//------------------------------------------------------------------------------
491// CSocketClientProxy
492//------------------------------------------------------------------------------
493
494class CSocketClientProxy : public CProxySocket
495{
496public:
497	/* Constructor */
498	CSocketClientProxy(
499		wxSocketFlags flags = wxSOCKET_NONE,
500		const CProxyData *proxyData = NULL);
501
502	/* Interface */
503	bool Connect(wxIPaddress &address, bool wait);
504	CSocketClientProxy& Read(void *buffer, wxUint32 nbytes);
505	CSocketClientProxy& Write(const void *buffer, wxUint32 nbytes);
506
507private:
508	wxMutex			m_socketLocker;
509};
510
511//------------------------------------------------------------------------------
512// CSocketServerProxy
513//------------------------------------------------------------------------------
514
515class CSocketServerProxy : public wxSocketServer
516{
517public:
518	/* Constructor */
519	CSocketServerProxy(
520		wxIPaddress &address,
521		wxSocketFlags flags = wxSOCKET_NONE,
522		const CProxyData *proxyData = NULL);
523
524	/* Interface */
525	CSocketServerProxy& Read(void *buffer, wxUint32 nbytes);
526	CSocketServerProxy& Write(const void *buffer, wxUint32 nbytes);
527
528private:
529	wxMutex			m_socketLocker;
530};
531
532//------------------------------------------------------------------------------
533// CDatagramSocketProxy
534//------------------------------------------------------------------------------
535
536enum UDPOperation {
537	UDP_OPERATION_NONE,
538	UDP_OPERATION_RECV_FROM,
539	UDP_OPERATION_SEND_TO
540};
541
542const unsigned int PROXY_UDP_OVERHEAD_IPV4 		= 10;
543const unsigned int PROXY_UDP_OVERHEAD_DOMAIN_NAME	= 262;
544const unsigned int PROXY_UDP_OVERHEAD_IPV6		= 20;
545const unsigned int PROXY_UDP_MAXIMUM_OVERHEAD		= PROXY_UDP_OVERHEAD_DOMAIN_NAME;
546
547class CDatagramSocketProxy : public wxDatagramSocket
548{
549public:
550	/* Constructor */
551	CDatagramSocketProxy(
552		wxIPaddress &address,
553		wxSocketFlags flags = wxSOCKET_NONE,
554		const CProxyData *proxyData = NULL);
555
556	/* Destructor */
557	~CDatagramSocketProxy();
558
559	/* Interface */
560	void SetUDPSocketOk() { m_udpSocketOk = true; }
561
562	/* wxDatagramSocket Interface */
563	virtual wxDatagramSocket& RecvFrom(
564		wxSockAddress& addr, void* buf, wxUint32 nBytes );
565	virtual wxDatagramSocket& SendTo(
566		wxIPaddress& addr, const void* buf, wxUint32 nBytes );
567	virtual wxUint32 LastCount(void) const;
568
569private:
570	bool			m_udpSocketOk;
571	CProxySocket		m_proxyTCPSocket;
572	enum UDPOperation	m_lastUDPOperation;
573	unsigned int		m_lastUDPOverhead;
574	wxMutex			m_socketLocker;
575};
576
577/******************************************************************************/
578
579#endif /* __PROXY_H__ */
580
581// File_checked_for_headers
582