Line data Source code
1 : /*
2 : Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 :
4 : This file is part of libzmq, the ZeroMQ core engine in C++.
5 :
6 : libzmq is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU Lesser General Public License (LGPL) as published
8 : by the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : As a special exception, the Contributors give you permission to link
12 : this library with independent modules to produce an executable,
13 : regardless of the license terms of these independent modules, and to
14 : copy and distribute the resulting executable under terms of your choice,
15 : provided that you also meet, for each linked independent module, the
16 : terms and conditions of the license of that module. An independent
17 : module is a module which is not derived from or based on this library.
18 : If you modify this library, you must extend this exception to your
19 : version of the library.
20 :
21 : libzmq is distributed in the hope that it will be useful, but WITHOUT
22 : ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24 : License for more details.
25 :
26 : You should have received a copy of the GNU Lesser General Public License
27 : along with this program. If not, see <http://www.gnu.org/licenses/>.
28 : */
29 :
30 : #include "precompiled.hpp"
31 : #include <sys/types.h>
32 :
33 : #include "err.hpp"
34 : #include "platform.hpp"
35 : #include "socks.hpp"
36 : #include "tcp.hpp"
37 :
38 : #ifndef ZMQ_HAVE_WINDOWS
39 : #include <sys/socket.h>
40 : #include <netinet/in.h>
41 : #include <netdb.h>
42 : #endif
43 :
44 0 : zmq::socks_greeting_t::socks_greeting_t (uint8_t method_) :
45 0 : num_methods (1)
46 : {
47 0 : methods [0] = method_;
48 0 : }
49 :
50 0 : zmq::socks_greeting_t::socks_greeting_t (
51 : uint8_t *methods_, uint8_t num_methods_)
52 0 : : num_methods (num_methods_)
53 : {
54 0 : for (uint8_t i = 0; i < num_methods_; i++)
55 0 : methods [i] = methods_ [i];
56 0 : }
57 :
58 0 : zmq::socks_greeting_encoder_t::socks_greeting_encoder_t ()
59 0 : : bytes_encoded (0), bytes_written (0)
60 0 : {}
61 :
62 0 : void zmq::socks_greeting_encoder_t::encode (const socks_greeting_t &greeting_)
63 : {
64 0 : uint8_t *ptr = buf;
65 :
66 0 : *ptr++ = 0x05;
67 0 : *ptr++ = (uint8_t) greeting_.num_methods;
68 0 : for (uint8_t i = 0; i < greeting_.num_methods; i++)
69 0 : *ptr++ = greeting_.methods [i];
70 :
71 0 : bytes_encoded = 2 + greeting_.num_methods;
72 0 : bytes_written = 0;
73 0 : }
74 :
75 0 : int zmq::socks_greeting_encoder_t::output (fd_t fd_)
76 : {
77 : const int rc = tcp_write (
78 0 : fd_, buf + bytes_written, bytes_encoded - bytes_written);
79 0 : if (rc > 0)
80 0 : bytes_written += static_cast <size_t> (rc);
81 0 : return rc;
82 : }
83 :
84 0 : bool zmq::socks_greeting_encoder_t::has_pending_data () const
85 : {
86 0 : return bytes_written < bytes_encoded;
87 : }
88 :
89 0 : void zmq::socks_greeting_encoder_t::reset ()
90 : {
91 0 : bytes_encoded = bytes_written = 0;
92 0 : }
93 :
94 0 : zmq::socks_choice_t::socks_choice_t (unsigned char method_)
95 0 : : method (method_)
96 0 : {}
97 :
98 0 : zmq::socks_choice_decoder_t::socks_choice_decoder_t ()
99 0 : : bytes_read (0)
100 0 : {}
101 :
102 0 : int zmq::socks_choice_decoder_t::input (fd_t fd_)
103 : {
104 0 : zmq_assert (bytes_read < 2);
105 0 : const int rc = tcp_read (fd_, buf + bytes_read, 2 - bytes_read);
106 0 : if (rc > 0) {
107 0 : bytes_read += static_cast <size_t> (rc);
108 0 : if (buf [0] != 0x05)
109 : return -1;
110 : }
111 0 : return rc;
112 : }
113 :
114 0 : bool zmq::socks_choice_decoder_t::message_ready () const
115 : {
116 0 : return bytes_read == 2;
117 : }
118 :
119 0 : zmq::socks_choice_t zmq::socks_choice_decoder_t::decode ()
120 : {
121 0 : zmq_assert (message_ready ());
122 0 : return socks_choice_t (buf [1]);
123 : }
124 :
125 0 : void zmq::socks_choice_decoder_t::reset ()
126 : {
127 0 : bytes_read = 0;
128 0 : }
129 :
130 :
131 0 : zmq::socks_request_t::socks_request_t (
132 : uint8_t command_, std::string hostname_, uint16_t port_)
133 0 : : command (command_), hostname (hostname_), port (port_)
134 : {
135 0 : zmq_assert (hostname_.size () <= UINT8_MAX);
136 0 : }
137 :
138 0 : zmq::socks_request_encoder_t::socks_request_encoder_t ()
139 0 : : bytes_encoded (0), bytes_written (0)
140 0 : {}
141 :
142 0 : void zmq::socks_request_encoder_t::encode (const socks_request_t &req)
143 : {
144 0 : zmq_assert (req.hostname.size() <= UINT8_MAX);
145 :
146 0 : unsigned char *ptr = buf;
147 0 : *ptr++ = 0x05;
148 0 : *ptr++ = req.command;
149 0 : *ptr++ = 0x00;
150 :
151 : #if defined ZMQ_HAVE_OPENVMS && defined __ia64 && __INITIAL_POINTER_SIZE == 64
152 : __addrinfo64 hints, *res = NULL;
153 : #else
154 0 : addrinfo hints, *res = NULL;
155 : #endif
156 :
157 : memset (&hints, 0, sizeof hints);
158 :
159 : // Suppress potential DNS lookups.
160 0 : hints.ai_flags = AI_NUMERICHOST;
161 :
162 0 : const int rc = getaddrinfo (req.hostname.c_str (), NULL, &hints, &res);
163 0 : if (rc == 0 && res->ai_family == AF_INET) {
164 : struct sockaddr_in *sockaddr_in =
165 0 : reinterpret_cast <struct sockaddr_in *> (res->ai_addr);
166 0 : *ptr++ = 0x01;
167 0 : memcpy (ptr, &sockaddr_in->sin_addr, 4);
168 0 : ptr += 4;
169 : }
170 : else
171 0 : if (rc == 0 && res->ai_family == AF_INET6) {
172 : struct sockaddr_in6 *sockaddr_in6 =
173 0 : reinterpret_cast <struct sockaddr_in6 *> (res->ai_addr);
174 0 : *ptr++ = 0x04;
175 0 : memcpy (ptr, &sockaddr_in6->sin6_addr, 16);
176 0 : ptr += 16;
177 : }
178 : else {
179 0 : *ptr++ = 0x03;
180 0 : *ptr++ = (unsigned char) req.hostname.size ();
181 0 : memcpy (ptr, req.hostname.c_str (), req.hostname.size ());
182 0 : ptr += req.hostname.size ();
183 : }
184 :
185 0 : if (rc == 0)
186 0 : freeaddrinfo (res);
187 :
188 0 : *ptr++ = req.port / 256;
189 0 : *ptr++ = req.port % 256;
190 :
191 0 : bytes_encoded = ptr - buf;
192 0 : bytes_written = 0;
193 0 : }
194 :
195 0 : int zmq::socks_request_encoder_t::output (fd_t fd_)
196 : {
197 : const int rc = tcp_write (
198 0 : fd_, buf + bytes_written, bytes_encoded - bytes_written);
199 0 : if (rc > 0)
200 0 : bytes_written += static_cast <size_t> (rc);
201 0 : return rc;
202 : }
203 :
204 0 : bool zmq::socks_request_encoder_t::has_pending_data () const
205 : {
206 0 : return bytes_written < bytes_encoded;
207 : }
208 :
209 0 : void zmq::socks_request_encoder_t::reset ()
210 : {
211 0 : bytes_encoded = bytes_written = 0;
212 0 : }
213 :
214 0 : zmq::socks_response_t::socks_response_t (
215 : uint8_t response_code_, std::string address_, uint16_t port_)
216 0 : : response_code (response_code_), address (address_), port (port_)
217 0 : {}
218 :
219 0 : zmq::socks_response_decoder_t::socks_response_decoder_t ()
220 0 : : bytes_read (0)
221 0 : {}
222 :
223 0 : int zmq::socks_response_decoder_t::input (fd_t fd_)
224 : {
225 0 : size_t n = 0;
226 :
227 0 : if (bytes_read < 5)
228 0 : n = 5 - bytes_read;
229 : else {
230 0 : const uint8_t atyp = buf [3];
231 0 : zmq_assert (atyp == 0x01 || atyp == 0x03 || atyp == 0x04);
232 0 : if (atyp == 0x01)
233 : n = 3 + 2;
234 : else
235 0 : if (atyp == 0x03)
236 0 : n = buf [4] + 2;
237 : else
238 0 : if (atyp == 0x04)
239 0 : n = 15 + 2;
240 : }
241 0 : const int rc = tcp_read (fd_, buf + bytes_read, n);
242 0 : if (rc > 0) {
243 0 : bytes_read += static_cast <size_t> (rc);
244 0 : if (buf [0] != 0x05)
245 : return -1;
246 0 : if (bytes_read >= 2)
247 0 : if (buf [1] > 0x08)
248 : return -1;
249 0 : if (bytes_read >= 3)
250 0 : if (buf [2] != 0x00)
251 : return -1;
252 0 : if (bytes_read >= 4) {
253 0 : const uint8_t atyp = buf [3];
254 0 : if (atyp != 0x01 && atyp != 0x03 && atyp != 0x04)
255 : return -1;
256 : }
257 : }
258 0 : return rc;
259 : }
260 :
261 0 : bool zmq::socks_response_decoder_t::message_ready () const
262 : {
263 0 : if (bytes_read < 4)
264 : return false;
265 : else {
266 0 : const uint8_t atyp = buf [3];
267 0 : zmq_assert (atyp == 0x01 || atyp == 0x03 || atyp == 0x04);
268 0 : if (atyp == 0x01)
269 0 : return bytes_read == 10;
270 : else
271 0 : if (atyp == 0x03)
272 0 : return bytes_read > 4 && bytes_read == 4 + 1 + buf [4] + 2u;
273 : else
274 0 : return bytes_read == 22;
275 : }
276 : }
277 :
278 0 : zmq::socks_response_t zmq::socks_response_decoder_t::decode ()
279 : {
280 0 : zmq_assert (message_ready ());
281 0 : return socks_response_t (buf [1], "", 0);
282 : }
283 :
284 0 : void zmq::socks_response_decoder_t::reset ()
285 : {
286 0 : bytes_read = 0;
287 0 : }
|