/src/libzmq/src/socks.cpp
Line | Count | Source |
1 | | /* SPDX-License-Identifier: MPL-2.0 */ |
2 | | |
3 | | #include "precompiled.hpp" |
4 | | #include <sys/types.h> |
5 | | |
6 | | #include "err.hpp" |
7 | | #include "socks.hpp" |
8 | | #include "tcp.hpp" |
9 | | #include "blob.hpp" |
10 | | |
11 | | #ifndef ZMQ_HAVE_WINDOWS |
12 | | #include <sys/socket.h> |
13 | | #include <netinet/in.h> |
14 | | #include <netdb.h> |
15 | | #endif |
16 | | |
17 | 0 | zmq::socks_greeting_t::socks_greeting_t (uint8_t method_) : num_methods (1) |
18 | 0 | { |
19 | 0 | methods[0] = method_; |
20 | 0 | } |
21 | | |
22 | | zmq::socks_greeting_t::socks_greeting_t (const uint8_t *methods_, |
23 | | uint8_t num_methods_) : |
24 | 0 | num_methods (num_methods_) |
25 | 0 | { |
26 | 0 | for (uint8_t i = 0; i < num_methods_; i++) |
27 | 0 | methods[i] = methods_[i]; |
28 | 0 | } |
29 | | |
30 | | zmq::socks_greeting_encoder_t::socks_greeting_encoder_t () : |
31 | 0 | _bytes_encoded (0), _bytes_written (0) |
32 | 0 | { |
33 | 0 | } |
34 | | |
35 | | void zmq::socks_greeting_encoder_t::encode (const socks_greeting_t &greeting_) |
36 | 0 | { |
37 | 0 | uint8_t *ptr = _buf; |
38 | |
|
39 | 0 | *ptr++ = 0x05; |
40 | 0 | *ptr++ = static_cast<uint8_t> (greeting_.num_methods); |
41 | 0 | for (uint8_t i = 0; i < greeting_.num_methods; i++) |
42 | 0 | *ptr++ = greeting_.methods[i]; |
43 | |
|
44 | 0 | _bytes_encoded = 2 + greeting_.num_methods; |
45 | 0 | _bytes_written = 0; |
46 | 0 | } |
47 | | |
48 | | int zmq::socks_greeting_encoder_t::output (fd_t fd_) |
49 | 0 | { |
50 | 0 | const int rc = |
51 | 0 | tcp_write (fd_, _buf + _bytes_written, _bytes_encoded - _bytes_written); |
52 | 0 | if (rc > 0) |
53 | 0 | _bytes_written += static_cast<size_t> (rc); |
54 | 0 | return rc; |
55 | 0 | } |
56 | | |
57 | | bool zmq::socks_greeting_encoder_t::has_pending_data () const |
58 | 0 | { |
59 | 0 | return _bytes_written < _bytes_encoded; |
60 | 0 | } |
61 | | |
62 | | void zmq::socks_greeting_encoder_t::reset () |
63 | 0 | { |
64 | 0 | _bytes_encoded = _bytes_written = 0; |
65 | 0 | } |
66 | | |
67 | 0 | zmq::socks_choice_t::socks_choice_t (unsigned char method_) : method (method_) |
68 | 0 | { |
69 | 0 | } |
70 | | |
71 | 0 | zmq::socks_choice_decoder_t::socks_choice_decoder_t () : _bytes_read (0) |
72 | 0 | { |
73 | 0 | } |
74 | | |
75 | | int zmq::socks_choice_decoder_t::input (fd_t fd_) |
76 | 0 | { |
77 | 0 | zmq_assert (_bytes_read < 2); |
78 | 0 | const int rc = tcp_read (fd_, _buf + _bytes_read, 2 - _bytes_read); |
79 | 0 | if (rc > 0) { |
80 | 0 | _bytes_read += static_cast<size_t> (rc); |
81 | 0 | if (_buf[0] != 0x05) |
82 | 0 | return -1; |
83 | 0 | } |
84 | 0 | return rc; |
85 | 0 | } |
86 | | |
87 | | bool zmq::socks_choice_decoder_t::message_ready () const |
88 | 0 | { |
89 | 0 | return _bytes_read == 2; |
90 | 0 | } |
91 | | |
92 | | zmq::socks_choice_t zmq::socks_choice_decoder_t::decode () |
93 | 0 | { |
94 | 0 | zmq_assert (message_ready ()); |
95 | 0 | return socks_choice_t (_buf[1]); |
96 | 0 | } |
97 | | |
98 | | void zmq::socks_choice_decoder_t::reset () |
99 | 0 | { |
100 | 0 | _bytes_read = 0; |
101 | 0 | } |
102 | | |
103 | | |
104 | | zmq::socks_basic_auth_request_t::socks_basic_auth_request_t ( |
105 | | const std::string &username_, const std::string &password_) : |
106 | 0 | username (username_), password (password_) |
107 | 0 | { |
108 | 0 | zmq_assert (username_.size () <= UINT8_MAX); |
109 | 0 | zmq_assert (password_.size () <= UINT8_MAX); |
110 | 0 | } |
111 | | |
112 | | |
113 | | zmq::socks_basic_auth_request_encoder_t::socks_basic_auth_request_encoder_t () : |
114 | 0 | _bytes_encoded (0), _bytes_written (0) |
115 | 0 | { |
116 | 0 | } |
117 | | |
118 | | void zmq::socks_basic_auth_request_encoder_t::encode ( |
119 | | const socks_basic_auth_request_t &req_) |
120 | 0 | { |
121 | 0 | unsigned char *ptr = _buf; |
122 | 0 | *ptr++ = 0x01; |
123 | 0 | *ptr++ = static_cast<unsigned char> (req_.username.size ()); |
124 | 0 | memcpy (ptr, req_.username.c_str (), req_.username.size ()); |
125 | 0 | ptr += req_.username.size (); |
126 | 0 | *ptr++ = static_cast<unsigned char> (req_.password.size ()); |
127 | 0 | memcpy (ptr, req_.password.c_str (), req_.password.size ()); |
128 | 0 | ptr += req_.password.size (); |
129 | |
|
130 | 0 | _bytes_encoded = ptr - _buf; |
131 | 0 | _bytes_written = 0; |
132 | 0 | } |
133 | | |
134 | | int zmq::socks_basic_auth_request_encoder_t::output (fd_t fd_) |
135 | 0 | { |
136 | 0 | const int rc = |
137 | 0 | tcp_write (fd_, _buf + _bytes_written, _bytes_encoded - _bytes_written); |
138 | 0 | if (rc > 0) |
139 | 0 | _bytes_written += static_cast<size_t> (rc); |
140 | 0 | return rc; |
141 | 0 | } |
142 | | |
143 | | bool zmq::socks_basic_auth_request_encoder_t::has_pending_data () const |
144 | 0 | { |
145 | 0 | return _bytes_written < _bytes_encoded; |
146 | 0 | } |
147 | | |
148 | | void zmq::socks_basic_auth_request_encoder_t::reset () |
149 | 0 | { |
150 | 0 | _bytes_encoded = _bytes_written = 0; |
151 | 0 | } |
152 | | |
153 | | |
154 | | zmq::socks_auth_response_t::socks_auth_response_t (uint8_t response_code_) : |
155 | 0 | response_code (response_code_) |
156 | 0 | { |
157 | 0 | } |
158 | | |
159 | | zmq::socks_auth_response_decoder_t::socks_auth_response_decoder_t () : |
160 | 0 | _bytes_read (0) |
161 | 0 | { |
162 | 0 | } |
163 | | |
164 | | int zmq::socks_auth_response_decoder_t::input (fd_t fd_) |
165 | 0 | { |
166 | 0 | zmq_assert (_bytes_read < 2); |
167 | 0 | const int rc = tcp_read (fd_, _buf + _bytes_read, 2 - _bytes_read); |
168 | 0 | if (rc > 0) { |
169 | 0 | _bytes_read += static_cast<size_t> (rc); |
170 | 0 | if (_buf[0] != 0x01) |
171 | 0 | return -1; |
172 | 0 | } |
173 | 0 | return rc; |
174 | 0 | } |
175 | | |
176 | | bool zmq::socks_auth_response_decoder_t::message_ready () const |
177 | 0 | { |
178 | 0 | return _bytes_read == 2; |
179 | 0 | } |
180 | | |
181 | | zmq::socks_auth_response_t zmq::socks_auth_response_decoder_t::decode () |
182 | 0 | { |
183 | 0 | zmq_assert (message_ready ()); |
184 | 0 | return socks_auth_response_t (_buf[1]); |
185 | 0 | } |
186 | | |
187 | | void zmq::socks_auth_response_decoder_t::reset () |
188 | 0 | { |
189 | 0 | _bytes_read = 0; |
190 | 0 | } |
191 | | |
192 | | |
193 | | zmq::socks_request_t::socks_request_t (uint8_t command_, |
194 | | std::string hostname_, |
195 | | uint16_t port_) : |
196 | 0 | command (command_), hostname (ZMQ_MOVE (hostname_)), port (port_) |
197 | 0 | { |
198 | 0 | zmq_assert (hostname.size () <= UINT8_MAX); |
199 | 0 | } |
200 | | |
201 | | zmq::socks_request_encoder_t::socks_request_encoder_t () : |
202 | 0 | _bytes_encoded (0), _bytes_written (0) |
203 | 0 | { |
204 | 0 | } |
205 | | |
206 | | void zmq::socks_request_encoder_t::encode (const socks_request_t &req_) |
207 | 0 | { |
208 | 0 | zmq_assert (req_.hostname.size () <= UINT8_MAX); |
209 | |
|
210 | 0 | unsigned char *ptr = _buf; |
211 | 0 | *ptr++ = 0x05; |
212 | 0 | *ptr++ = req_.command; |
213 | 0 | *ptr++ = 0x00; |
214 | |
|
215 | | #if defined ZMQ_HAVE_OPENVMS && defined __ia64 && __INITIAL_POINTER_SIZE == 64 |
216 | | __addrinfo64 hints, *res = NULL; |
217 | | #else |
218 | 0 | addrinfo hints, *res = NULL; |
219 | 0 | #endif |
220 | |
|
221 | 0 | memset (&hints, 0, sizeof hints); |
222 | | |
223 | | // Suppress potential DNS lookups. |
224 | 0 | hints.ai_flags = AI_NUMERICHOST; |
225 | |
|
226 | 0 | const int rc = getaddrinfo (req_.hostname.c_str (), NULL, &hints, &res); |
227 | 0 | if (rc == 0 && res->ai_family == AF_INET) { |
228 | 0 | const struct sockaddr_in *sockaddr_in = |
229 | 0 | reinterpret_cast<const struct sockaddr_in *> (res->ai_addr); |
230 | 0 | *ptr++ = 0x01; |
231 | 0 | memcpy (ptr, &sockaddr_in->sin_addr, 4); |
232 | 0 | ptr += 4; |
233 | 0 | } else if (rc == 0 && res->ai_family == AF_INET6) { |
234 | 0 | const struct sockaddr_in6 *sockaddr_in6 = |
235 | 0 | reinterpret_cast<const struct sockaddr_in6 *> (res->ai_addr); |
236 | 0 | *ptr++ = 0x04; |
237 | 0 | memcpy (ptr, &sockaddr_in6->sin6_addr, 16); |
238 | 0 | ptr += 16; |
239 | 0 | } else { |
240 | 0 | *ptr++ = 0x03; |
241 | 0 | *ptr++ = static_cast<unsigned char> (req_.hostname.size ()); |
242 | 0 | memcpy (ptr, req_.hostname.c_str (), req_.hostname.size ()); |
243 | 0 | ptr += req_.hostname.size (); |
244 | 0 | } |
245 | |
|
246 | 0 | if (rc == 0) |
247 | 0 | freeaddrinfo (res); |
248 | |
|
249 | 0 | *ptr++ = req_.port / 256; |
250 | 0 | *ptr++ = req_.port % 256; |
251 | |
|
252 | 0 | _bytes_encoded = ptr - _buf; |
253 | 0 | _bytes_written = 0; |
254 | 0 | } |
255 | | |
256 | | int zmq::socks_request_encoder_t::output (fd_t fd_) |
257 | 0 | { |
258 | 0 | const int rc = |
259 | 0 | tcp_write (fd_, _buf + _bytes_written, _bytes_encoded - _bytes_written); |
260 | 0 | if (rc > 0) |
261 | 0 | _bytes_written += static_cast<size_t> (rc); |
262 | 0 | return rc; |
263 | 0 | } |
264 | | |
265 | | bool zmq::socks_request_encoder_t::has_pending_data () const |
266 | 0 | { |
267 | 0 | return _bytes_written < _bytes_encoded; |
268 | 0 | } |
269 | | |
270 | | void zmq::socks_request_encoder_t::reset () |
271 | 0 | { |
272 | 0 | _bytes_encoded = _bytes_written = 0; |
273 | 0 | } |
274 | | |
275 | | zmq::socks_response_t::socks_response_t (uint8_t response_code_, |
276 | | const std::string &address_, |
277 | | uint16_t port_) : |
278 | 0 | response_code (response_code_), address (address_), port (port_) |
279 | 0 | { |
280 | 0 | } |
281 | | |
282 | 0 | zmq::socks_response_decoder_t::socks_response_decoder_t () : _bytes_read (0) |
283 | 0 | { |
284 | 0 | } |
285 | | |
286 | | int zmq::socks_response_decoder_t::input (fd_t fd_) |
287 | 0 | { |
288 | 0 | size_t n = 0; |
289 | |
|
290 | 0 | if (_bytes_read < 5) |
291 | 0 | n = 5 - _bytes_read; |
292 | 0 | else { |
293 | 0 | const uint8_t atyp = _buf[3]; |
294 | 0 | zmq_assert (atyp == 0x01 || atyp == 0x03 || atyp == 0x04); |
295 | 0 | if (atyp == 0x01) |
296 | 0 | n = 3 + 2; |
297 | 0 | else if (atyp == 0x03) |
298 | 0 | n = _buf[4] + 2; |
299 | 0 | else if (atyp == 0x04) |
300 | 0 | n = 15 + 2; |
301 | 0 | } |
302 | 0 | const int rc = tcp_read (fd_, _buf + _bytes_read, n); |
303 | 0 | if (rc > 0) { |
304 | 0 | _bytes_read += static_cast<size_t> (rc); |
305 | 0 | if (_buf[0] != 0x05) |
306 | 0 | return -1; |
307 | 0 | if (_bytes_read >= 2) |
308 | 0 | if (_buf[1] > 0x08) |
309 | 0 | return -1; |
310 | 0 | if (_bytes_read >= 3) |
311 | 0 | if (_buf[2] != 0x00) |
312 | 0 | return -1; |
313 | 0 | if (_bytes_read >= 4) { |
314 | 0 | const uint8_t atyp = _buf[3]; |
315 | 0 | if (atyp != 0x01 && atyp != 0x03 && atyp != 0x04) |
316 | 0 | return -1; |
317 | 0 | } |
318 | 0 | } |
319 | 0 | return rc; |
320 | 0 | } |
321 | | |
322 | | bool zmq::socks_response_decoder_t::message_ready () const |
323 | 0 | { |
324 | 0 | if (_bytes_read < 4) |
325 | 0 | return false; |
326 | | |
327 | 0 | const uint8_t atyp = _buf[3]; |
328 | 0 | zmq_assert (atyp == 0x01 || atyp == 0x03 || atyp == 0x04); |
329 | 0 | if (atyp == 0x01) |
330 | 0 | return _bytes_read == 10; |
331 | 0 | if (atyp == 0x03) |
332 | 0 | return _bytes_read > 4 && _bytes_read == 4 + 1 + _buf[4] + 2u; |
333 | | |
334 | 0 | return _bytes_read == 22; |
335 | 0 | } |
336 | | |
337 | | zmq::socks_response_t zmq::socks_response_decoder_t::decode () |
338 | 0 | { |
339 | 0 | zmq_assert (message_ready ()); |
340 | 0 | return socks_response_t (_buf[1], "", 0); |
341 | 0 | } |
342 | | |
343 | | void zmq::socks_response_decoder_t::reset () |
344 | 0 | { |
345 | 0 | _bytes_read = 0; |
346 | 0 | } |