socks.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:15k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * main.cxx
  3.  *
  4.  * PWLib application source file for GetCyberPatrol
  5.  *
  6.  * Main program entry point.
  7.  *
  8.  * Copyright 98 Equivalence
  9.  *
  10.  * $Log: socks.cxx,v $
  11.  * Revision 1.4  1999/11/23 08:45:10  robertj
  12.  * Fixed bug in user/pass authentication version, thanks Dmitry <dipa@linkline.com>
  13.  *
  14.  * Revision 1.3  1999/02/16 08:08:06  robertj
  15.  * MSVC 6.0 compatibility changes.
  16.  *
  17.  * Revision 1.2  1998/12/23 00:35:28  robertj
  18.  * UDP support.
  19.  *
  20.  * Revision 1.1  1998/12/22 10:30:24  robertj
  21.  * Initial revision
  22.  *
  23.  */
  24. #include <ptlib.h>
  25. #include <ptclib/socks.h>
  26. #define new PNEW
  27. #define SOCKS_VERSION_4 ((BYTE)4)
  28. #define SOCKS_VERSION_5 ((BYTE)5)
  29. #define SOCKS_CMD_CONNECT       ((BYTE)1)
  30. #define SOCKS_CMD_BIND          ((BYTE)2)
  31. #define SOCKS_CMD_UDP_ASSOCIATE ((BYTE)3)
  32. #define SOCKS_AUTH_NONE      ((BYTE)0)
  33. #define SOCKS_AUTH_USER_PASS ((BYTE)2)
  34. #define SOCKS_AUTH_FAILED    ((BYTE)0xff)
  35. #define SOCKS_ADDR_IPV4       ((BYTE)1)
  36. #define SOCKS_ADDR_DOMAINNAME ((BYTE)3)
  37. #define SOCKS_ADDR_IPV6       ((BYTE)4)
  38. ///////////////////////////////////////////////////////////////////////////////
  39. PSocksProtocol::PSocksProtocol(WORD port)
  40.   : serverHost("proxy")
  41. {
  42.   serverPort = DefaultServerPort;
  43.   remotePort = port;
  44.   localPort = 0;
  45.   // get proxy information
  46.   PConfig config(PConfig::System, "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\");
  47.   // get the proxy configuration string
  48.   PString str = config.GetString("Internet Settings", "ProxyServer", "");
  49.   if (str.Find('=') == P_MAX_INDEX)
  50.     SetServer("socks");
  51.   else {
  52.     PStringArray tokens = str.Tokenise(";");
  53.     PINDEX i;
  54.     for (i = 0; i < tokens.GetSize(); i++) {
  55.       str = tokens[i];
  56.       PINDEX equalPos = str.Find('=');
  57.       if (equalPos != P_MAX_INDEX && (str.Left(equalPos) *= "socks")) {
  58.         SetServer(str.Mid(equalPos+1));
  59.         break;
  60.       }
  61.     }
  62.   }
  63. }
  64. BOOL PSocksProtocol::SetServer(const PString & hostname, const char * service)
  65. {
  66.   return SetServer(hostname, PIPSocket::GetPortByService("tcp", service));
  67. }
  68. BOOL PSocksProtocol::SetServer(const PString & hostname, WORD port)
  69. {
  70.   PINDEX colon = hostname.Find(':');
  71.   if (colon == P_MAX_INDEX)
  72.     serverHost = hostname;
  73.   else {
  74.     unsigned portnum = hostname.Mid(colon+1).AsUnsigned();
  75.     if (portnum == 0)
  76.       serverHost = hostname;
  77.     else {
  78.       serverHost = hostname.Left(colon);
  79.       port = (WORD)portnum;
  80.     }
  81.   }
  82.   if (port == 0)
  83.     port = DefaultServerPort;
  84.   serverPort = port;
  85.   return TRUE;
  86. }
  87. void PSocksProtocol::SetAuthentication(const PString & username, const PString & password)
  88. {
  89.   PAssert(authenticationUsername.GetLength() < 256, PInvalidParameter);
  90.   authenticationUsername = username;
  91.   PAssert(authenticationPassword.GetLength() < 256, PInvalidParameter);
  92.   authenticationPassword = password;
  93. }
  94. BOOL PSocksProtocol::ConnectSocksServer(PTCPSocket & socket)
  95. {
  96.   PIPSocket::Address ipnum;
  97.   if (!PIPSocket::GetHostAddress(serverHost, ipnum))
  98.     return FALSE;
  99.   remotePort = socket.GetPort();
  100.   socket.SetPort(serverPort);
  101.   return socket.PTCPSocket::Connect(0, ipnum);
  102. }
  103. BOOL PSocksProtocol::SendSocksCommand(PTCPSocket & socket,
  104.                                       BYTE command,
  105.                                       const char * hostname,
  106.                                       PIPSocket::Address addr)
  107. {
  108.   if (!socket.IsOpen()) {
  109.     if (!ConnectSocksServer(socket))
  110.       return FALSE;
  111.     socket << SOCKS_VERSION_5
  112.            << (authenticationUsername.IsEmpty() ? '01' : '02') // length
  113.            << SOCKS_AUTH_NONE;
  114.     if (!authenticationUsername)
  115.       socket << SOCKS_AUTH_USER_PASS;  // Simple cleartext username/password
  116.     socket.flush();
  117.     BYTE auth_pdu[2];
  118.     if (!socket.ReadBlock(auth_pdu, sizeof(auth_pdu)))  // Should get 2 byte reply
  119.       return FALSE;
  120.     if (auth_pdu[0] != SOCKS_VERSION_5 || auth_pdu[1] == SOCKS_AUTH_FAILED) {
  121.       socket.Close();
  122.       SetErrorCodes(PChannel::AccessDenied, EACCES);
  123.       return FALSE;
  124.     }
  125.     if (auth_pdu[1] == SOCKS_AUTH_USER_PASS) {
  126.       // Send username and pasword
  127.       socket << 'x01'
  128.              << (BYTE)authenticationUsername.GetLength()  // Username length as single byte
  129.              << authenticationUsername
  130.              << (BYTE)authenticationPassword.GetLength()  // Password length as single byte
  131.              << authenticationPassword
  132.              << ::flush;
  133.       if (!socket.ReadBlock(auth_pdu, sizeof(auth_pdu)))  // Should get 2 byte reply
  134.         return FALSE;
  135.       if (auth_pdu[0] != SOCKS_VERSION_5 || auth_pdu[1] != 0) {
  136.         socket.Close();
  137.         SetErrorCodes(PChannel::AccessDenied, EACCES);
  138.         return FALSE;
  139.       }
  140.     }
  141.   }
  142.   socket << SOCKS_VERSION_5
  143.          << command
  144.          << '00'; // Reserved
  145.   if (hostname != NULL)
  146.     socket << SOCKS_ADDR_DOMAINNAME << (BYTE)strlen(hostname) << hostname;
  147.   else
  148.     socket << SOCKS_ADDR_IPV4
  149.            << addr.Byte1() << addr.Byte2() << addr.Byte3() << addr.Byte4();
  150.   socket << (BYTE)(remotePort >> 8) << (BYTE)remotePort
  151.          << ::flush;
  152.   return ReceiveSocksResponse(socket, localAddress, localPort);
  153. }
  154. BOOL PSocksProtocol::ReceiveSocksResponse(PTCPSocket & socket,
  155.                                           PIPSocket::Address & addr,
  156.                                           WORD & port)
  157. {
  158.   int reply;
  159.   if ((reply = socket.ReadChar()) < 0)
  160.     return FALSE;
  161.   if (reply != SOCKS_VERSION_5) {
  162.     SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  163.     return FALSE;
  164.   }
  165.   if ((reply = socket.ReadChar()) < 0)
  166.     return FALSE;
  167.   switch (reply) {
  168.     case 0 :  // No error
  169.       break;
  170.     case 2 :  // Refused permission
  171.       SetErrorCodes(PChannel::AccessDenied, EACCES);
  172.       return FALSE;
  173.     case 3 : // Network unreachable
  174.       SetErrorCodes(PChannel::NotFound, ENETUNREACH);
  175.       return FALSE;
  176.     case 4 : // Host unreachable
  177.       SetErrorCodes(PChannel::NotFound, EHOSTUNREACH);
  178.       return FALSE;
  179.     case 5 : // Connection refused
  180.       SetErrorCodes(PChannel::NotFound, EHOSTUNREACH);
  181.       return FALSE;
  182.     default :
  183.       SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  184.       return FALSE;
  185.   }
  186.   // Ignore next byte (reserved)
  187.   if ((reply = socket.ReadChar()) < 0)
  188.     return FALSE;
  189.   // Get type byte for bound address
  190.   if ((reply = socket.ReadChar()) < 0)
  191.     return FALSE;
  192.   switch (reply) {
  193.     case SOCKS_ADDR_DOMAINNAME :
  194.       // Get length
  195.       if ((reply = socket.ReadChar()) < 0)
  196.         return FALSE;
  197.       if (!PIPSocket::GetHostAddress(socket.ReadString(reply), addr))
  198.         return FALSE;
  199.       break;
  200.     case SOCKS_ADDR_IPV4 :
  201.       if (!socket.ReadBlock(&addr, sizeof(addr)))
  202.         return FALSE;
  203.       break;
  204.     default :
  205.       SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  206.       return FALSE;
  207.   }
  208.   WORD rxPort;
  209.   if (!socket.ReadBlock(&rxPort, sizeof(rxPort)))
  210.     return FALSE;
  211.   port = PSocket::Net2Host(rxPort);
  212.   return TRUE;
  213. }
  214. ///////////////////////////////////////////////////////////////////////////////
  215. PSocksSocket::PSocksSocket(WORD port)
  216.   : PSocksProtocol(port)
  217. {
  218. }
  219. BOOL PSocksSocket::Connect(const PString & address)
  220. {
  221.   if (!SendSocksCommand(*this, SOCKS_CMD_CONNECT, address, 0))
  222.     return FALSE;
  223.   port = remotePort;
  224.   return TRUE;
  225. }
  226. BOOL PSocksSocket::Connect(const Address & addr)
  227. {
  228.   if (!SendSocksCommand(*this, SOCKS_CMD_CONNECT, NULL, addr))
  229.     return FALSE;
  230.   port = remotePort;
  231.   return TRUE;
  232. }
  233. BOOL PSocksSocket::Connect(WORD, const Address &)
  234. {
  235.   PAssertAlways(PUnsupportedFeature);
  236.   return FALSE;
  237. }
  238. BOOL PSocksSocket::Listen(unsigned, WORD newPort, Reusability reuse)
  239. {
  240.   PAssert(newPort == 0 && port == 0, PUnsupportedFeature);
  241.   PAssert(reuse, PUnsupportedFeature);
  242.   if (!SendSocksCommand(*this, SOCKS_CMD_BIND, NULL, 0))
  243.     return FALSE;
  244.   port = localPort;
  245.   return TRUE;
  246. }
  247. BOOL PSocksSocket::Accept()
  248. {
  249.   if (!IsOpen())
  250.     return FALSE;
  251.   return ReceiveSocksResponse(*this, remoteAddress, remotePort);
  252. }
  253. BOOL PSocksSocket::Accept(PSocket & socket)
  254. {
  255.   // If is right class, transfer the SOCKS socket to class to receive the accept
  256.   // The "listener" socket is implicitly closed as there is really only one
  257.   // handle in a SOCKS BIND operation.
  258.   PAssert(socket.IsDescendant(PSocksSocket::Class()), PUnsupportedFeature);
  259.   os_handle = ((PSocksSocket &)socket).TransferHandle(*this);
  260.   return Accept();
  261. }
  262. int PSocksSocket::TransferHandle(PSocksSocket & destination)
  263. {
  264.   // This "transfers" the socket from one onstance to another.
  265.   int the_handle = os_handle;
  266.   destination.SetReadTimeout(readTimeout);
  267.   destination.SetWriteTimeout(writeTimeout);
  268.   // Close the instance of the socket but don't actually close handle.
  269.   os_handle = -1;
  270.   return the_handle;
  271. }
  272. BOOL PSocksSocket::GetLocalAddress(Address & addr)
  273. {
  274.   if (!IsOpen())
  275.     return FALSE;
  276.   addr = localAddress;
  277.   return TRUE;
  278. }
  279. BOOL PSocksSocket::GetLocalAddress(Address & addr, WORD & port)
  280. {
  281.   if (!IsOpen())
  282.     return FALSE;
  283.   addr = localAddress;
  284.   port = localPort;
  285.   return TRUE;
  286. }
  287. BOOL PSocksSocket::GetPeerAddress(Address & addr)
  288. {
  289.   if (!IsOpen())
  290.     return FALSE;
  291.   addr = remoteAddress;
  292.   return TRUE;
  293. }
  294. BOOL PSocksSocket::GetPeerAddress(Address & addr, WORD & port)
  295. {
  296.   if (!IsOpen())
  297.     return FALSE;
  298.   addr = remoteAddress;
  299.   port = remotePort;
  300.   return TRUE;
  301. }
  302. void PSocksSocket::SetErrorCodes(PChannel::Errors errCode, int osErr)
  303. {
  304.   lastError = errCode;
  305.   osError = osErr;
  306. }
  307. ///////////////////////////////////////////////////////////////////////////////
  308. PSocks4Socket::PSocks4Socket(WORD port)
  309.   : PSocksSocket(port)
  310. {
  311. }
  312. PSocks4Socket::PSocks4Socket(const PString & host, WORD port)
  313.   : PSocksSocket(port)
  314. {
  315.   Connect(host);
  316. }
  317. PObject * PSocks4Socket::Clone() const
  318. {
  319.   return new PSocks4Socket(remotePort);
  320. }
  321. BOOL PSocks4Socket::SendSocksCommand(PTCPSocket & socket,
  322.                                      BYTE command,
  323.                                      const char * hostname,
  324.                                      Address addr)
  325. {
  326.   if (hostname != NULL) {
  327.     if (!GetHostAddress(hostname, addr))
  328.       return FALSE;
  329.   }
  330.   if (!IsOpen()) {
  331.     if (!ConnectSocksServer(*this))
  332.       return FALSE;
  333.   }
  334.   PString user = PProcess::Current().GetUserName();
  335.   socket << SOCKS_VERSION_4
  336.          << command
  337.          << (BYTE)user.GetLength() << user
  338.          << (BYTE)(remotePort >> 8) << (BYTE)remotePort
  339.          << addr.Byte1() << addr.Byte2() << addr.Byte3() << addr.Byte4()
  340.          << ::flush;
  341.   return ReceiveSocksResponse(socket, localAddress, localPort);
  342. }
  343. BOOL PSocks4Socket::ReceiveSocksResponse(PTCPSocket & socket,
  344.                                          Address & addr,
  345.                                          WORD & port)
  346. {
  347.   int reply;
  348.   if ((reply = socket.ReadChar()) < 0)
  349.     return FALSE;
  350.   if (reply != SOCKS_VERSION_4) {
  351.     SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  352.     return FALSE;
  353.   }
  354.   if ((reply = socket.ReadChar()) < 0)
  355.     return FALSE;
  356.   switch (reply) {
  357.     case 90 :  // No error
  358.       break;
  359.     case 91 : // Connection refused
  360.       SetErrorCodes(PChannel::NotFound, EHOSTUNREACH);
  361.       return FALSE;
  362.     case 92 :  // Refused permission
  363.       SetErrorCodes(PChannel::AccessDenied, EACCES);
  364.       return FALSE;
  365.     default :
  366.       SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  367.       return FALSE;
  368.   }
  369.   WORD rxPort;
  370.   if (!socket.ReadBlock(&rxPort, sizeof(rxPort)))
  371.     return FALSE;
  372.   port = PSocket::Net2Host(rxPort);
  373.   return socket.ReadBlock(&addr, sizeof(addr));
  374. }
  375. ///////////////////////////////////////////////////////////////////////////////
  376. PSocks5Socket::PSocks5Socket(WORD port)
  377.   : PSocksSocket(port)
  378. {
  379. }
  380. PSocks5Socket::PSocks5Socket(const PString & host, WORD port)
  381.   : PSocksSocket(port)
  382. {
  383.   Connect(host);
  384. }
  385. PObject * PSocks5Socket::Clone() const
  386. {
  387.   return new PSocks5Socket(remotePort);
  388. }
  389. ///////////////////////////////////////////////////////////////////////////////
  390. PSocksUDPSocket::PSocksUDPSocket(WORD port)
  391.   : PSocksProtocol(port)
  392. {
  393. }
  394. PSocksUDPSocket::PSocksUDPSocket(const PString & host, WORD port)
  395.   : PSocksProtocol(port)
  396. {
  397.   Connect(host);
  398. }
  399. PObject * PSocksUDPSocket::Clone() const
  400. {
  401.   return new PSocksUDPSocket(port);
  402. }
  403. BOOL PSocksUDPSocket::Connect(const PString & address)
  404. {
  405.   if (!SendSocksCommand(socksControl, SOCKS_CMD_UDP_ASSOCIATE, address, 0))
  406.     return FALSE;
  407.   socksControl.GetPeerAddress(serverAddress);
  408.   return TRUE;
  409. }
  410. BOOL PSocksUDPSocket::Connect(const Address & addr)
  411. {
  412.   if (!SendSocksCommand(socksControl, SOCKS_CMD_UDP_ASSOCIATE, NULL, addr))
  413.     return FALSE;
  414.   socksControl.GetPeerAddress(serverAddress);
  415.   return TRUE;
  416. }
  417. BOOL PSocksUDPSocket::Connect(WORD, const Address &)
  418. {
  419.   PAssertAlways(PUnsupportedFeature);
  420.   return FALSE;
  421. }
  422. BOOL PSocksUDPSocket::Listen(unsigned, WORD newPort, Reusability reuse)
  423. {
  424.   PAssert(newPort == 0 && port == 0, PUnsupportedFeature);
  425.   PAssert(reuse, PUnsupportedFeature);
  426.   if (!SendSocksCommand(socksControl, SOCKS_CMD_UDP_ASSOCIATE, NULL, 0))
  427.     return FALSE;
  428.   socksControl.GetPeerAddress(serverAddress);
  429.   port = localPort;
  430.   return TRUE;
  431. }
  432. BOOL PSocksUDPSocket::GetLocalAddress(Address & addr)
  433. {
  434.   if (!IsOpen())
  435.     return FALSE;
  436.   addr = localAddress;
  437.   return TRUE;
  438. }
  439. BOOL PSocksUDPSocket::GetLocalAddress(Address & addr, WORD & port)
  440. {
  441.   if (!IsOpen())
  442.     return FALSE;
  443.   addr = localAddress;
  444.   port = localPort;
  445.   return TRUE;
  446. }
  447. BOOL PSocksUDPSocket::GetPeerAddress(Address & addr)
  448. {
  449.   if (!IsOpen())
  450.     return FALSE;
  451.   addr = remoteAddress;
  452.   return TRUE;
  453. }
  454. BOOL PSocksUDPSocket::GetPeerAddress(Address & addr, WORD & port)
  455. {
  456.   if (!IsOpen())
  457.     return FALSE;
  458.   addr = remoteAddress;
  459.   port = remotePort;
  460.   return TRUE;
  461. }
  462. BOOL PSocksUDPSocket::ReadFrom(void * buf, PINDEX len, Address & addr, WORD & port)
  463. {
  464.   PBYTEArray newbuf(len+262);
  465.   Address rx_addr;
  466.   WORD rx_port;
  467.   if (!PUDPSocket::ReadFrom(newbuf.GetPointer(), newbuf.GetSize(), rx_addr, rx_port))
  468.     return FALSE;
  469.   if (rx_addr != serverAddress || rx_port != serverPort)
  470.     return FALSE;
  471.   PINDEX port_pos;
  472.   switch (newbuf[3]) {
  473.     case SOCKS_ADDR_DOMAINNAME :
  474.       if (!PIPSocket::GetHostAddress(PString((const char *)&newbuf[5], (PINDEX)newbuf[4]), addr))
  475.         return FALSE;
  476.       port_pos = newbuf[4]+5;
  477.       break;
  478.     case SOCKS_ADDR_IPV4 :
  479.       memcpy(&addr, &newbuf[4], 4);
  480.       port_pos = 4;
  481.       break;
  482.     default :
  483.       SetErrorCodes(PChannel::Miscellaneous, EINVAL);
  484.       return FALSE;
  485.   }
  486.   port = (WORD)((newbuf[port_pos] << 8)|newbuf[port_pos+1]);
  487.   memcpy(buf, &newbuf[port_pos+2], len);
  488.   return TRUE;
  489. }
  490. BOOL PSocksUDPSocket::WriteTo(const void * buf, PINDEX len, const Address & addr, WORD port)
  491. {
  492.   PBYTEArray newbuf(len+10);
  493.   BYTE * bufptr = newbuf.GetPointer();
  494.   // Build header, bytes 0, 1 & 2 are zero
  495.   bufptr[3] = SOCKS_ADDR_IPV4;
  496.   memcpy(bufptr+4, &addr, 4);
  497.   bufptr[8] = (BYTE)(port >> 8);
  498.   bufptr[9] = (BYTE)port;
  499.   memcpy(bufptr+10, buf, len);
  500.   return PUDPSocket::WriteTo(newbuf, newbuf.GetSize(), serverAddress, serverPort);
  501. }
  502. void PSocksUDPSocket::SetErrorCodes(PChannel::Errors errCode, int osErr)
  503. {
  504.   lastError = errCode;
  505.   osError = osErr;
  506. }
  507. // End of File ///////////////////////////////////////////////////////////////