• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // socks4.hpp
3 // ~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef SOCKS4_HPP
12 #define SOCKS4_HPP
13 
14 #include <array>
15 #include <string>
16 #include <boost/asio/buffer.hpp>
17 #include <boost/asio/ip/tcp.hpp>
18 
19 namespace socks4 {
20 
21 const unsigned char version = 0x04;
22 
23 class request
24 {
25 public:
26   enum command_type
27   {
28     connect = 0x01,
29     bind = 0x02
30   };
31 
request(command_type cmd,const boost::asio::ip::tcp::endpoint & endpoint,const std::string & user_id)32   request(command_type cmd, const boost::asio::ip::tcp::endpoint& endpoint,
33       const std::string& user_id)
34     : version_(version),
35       command_(cmd),
36       user_id_(user_id),
37       null_byte_(0)
38   {
39     // Only IPv4 is supported by the SOCKS 4 protocol.
40     if (endpoint.protocol() != boost::asio::ip::tcp::v4())
41     {
42       throw boost::system::system_error(
43           boost::asio::error::address_family_not_supported);
44     }
45 
46     // Convert port number to network byte order.
47     unsigned short port = endpoint.port();
48     port_high_byte_ = (port >> 8) & 0xff;
49     port_low_byte_ = port & 0xff;
50 
51     // Save IP address in network byte order.
52     address_ = endpoint.address().to_v4().to_bytes();
53   }
54 
buffers() const55   std::array<boost::asio::const_buffer, 7> buffers() const
56   {
57     return
58     {
59       {
60         boost::asio::buffer(&version_, 1),
61         boost::asio::buffer(&command_, 1),
62         boost::asio::buffer(&port_high_byte_, 1),
63         boost::asio::buffer(&port_low_byte_, 1),
64         boost::asio::buffer(address_),
65         boost::asio::buffer(user_id_),
66         boost::asio::buffer(&null_byte_, 1)
67       }
68     };
69   }
70 
71 private:
72   unsigned char version_;
73   unsigned char command_;
74   unsigned char port_high_byte_;
75   unsigned char port_low_byte_;
76   boost::asio::ip::address_v4::bytes_type address_;
77   std::string user_id_;
78   unsigned char null_byte_;
79 };
80 
81 class reply
82 {
83 public:
84   enum status_type
85   {
86     request_granted = 0x5a,
87     request_failed = 0x5b,
88     request_failed_no_identd = 0x5c,
89     request_failed_bad_user_id = 0x5d
90   };
91 
reply()92   reply()
93     : null_byte_(0),
94       status_()
95   {
96   }
97 
buffers()98   std::array<boost::asio::mutable_buffer, 5> buffers()
99   {
100     return
101     {
102       {
103         boost::asio::buffer(&null_byte_, 1),
104         boost::asio::buffer(&status_, 1),
105         boost::asio::buffer(&port_high_byte_, 1),
106         boost::asio::buffer(&port_low_byte_, 1),
107         boost::asio::buffer(address_)
108       }
109     };
110   }
111 
success() const112   bool success() const
113   {
114     return null_byte_ == 0 && status_ == request_granted;
115   }
116 
status() const117   unsigned char status() const
118   {
119     return status_;
120   }
121 
endpoint() const122   boost::asio::ip::tcp::endpoint endpoint() const
123   {
124     unsigned short port = port_high_byte_;
125     port = (port << 8) & 0xff00;
126     port = port | port_low_byte_;
127 
128     boost::asio::ip::address_v4 address(address_);
129 
130     return boost::asio::ip::tcp::endpoint(address, port);
131   }
132 
133 private:
134   unsigned char null_byte_;
135   unsigned char status_;
136   unsigned char port_high_byte_;
137   unsigned char port_low_byte_;
138   boost::asio::ip::address_v4::bytes_type address_;
139 };
140 
141 } // namespace socks4
142 
143 #endif // SOCKS4_HPP
144