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