/[winpt]/trunk/Src/wptSOCKS.cpp
ViewVC logotype

Contents of /trunk/Src/wptSOCKS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 328 - (show annotations)
Fri Sep 25 16:07:38 2009 UTC (15 years, 5 months ago) by twoaday
File size: 8098 byte(s)


1 #if 0
2 /* wptSOCKS.cpp - SOCKS proxy support
3 * Copyright (C) 2006 Timo Schulz
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <windows.h>
26
27 #include "wptTypes.h"
28 #include "wptGPG.h"
29 #include "wptKeyserver.h"
30 #include "wptErrors.h"
31 #include "wptNLS.h"
32
33 /* Known socks errors. */
34 enum socks5_error_t {
35 ERR_SUCCESS = 0x00,
36 ERR_GENERAL = 0x01,
37 ERR_NOTALLOWED = 0x02,
38 ERR_NETUNREACH = 0x03,
39 ERR_HOSTUNREACH = 0x04,
40 ERR_CONNREFUSED = 0x05,
41 ERR_INVADDR = 0x08
42 };
43
44 /* Known socks address types. */
45 enum socks5_addr_t {
46 ADDR_IPV4 = 0x01,
47 ADDR_DOMAIN = 0x03,
48 ADDR_IPV6 = 0x04
49 };
50
51 /* Known socks authentication methods. */
52 enum socks5_method_t {
53 METH_NOAUTH = 0x00,
54 METH_GSSAPI = 0x01,
55 METH_USERPASS = 0x02,
56 METH_ERR = 0xFF
57 };
58
59
60 /* Return human readable SOCKS error. */
61 static const char*
62 socks_strerror (int err)
63 {
64 switch (err) {
65 case ERR_SUCCESS: _("No error"); break;
66 case ERR_GENERAL: _("General SOCKS error"); break;
67 case ERR_NOTALLOWED: _("Connection not allowed by ruleset"); break;
68 case ERR_NETUNREACH: _("Network is unreachable"); break;
69 case ERR_HOSTUNREACH: _("Host could not be resolved"); break;
70 case ERR_CONNREFUSED: _("Connection refused"); break;
71 case ERR_INVADDR: _("Address type is not supported"); break;
72 }
73 return _("Unknown SOCKS error");
74 }
75
76
77 /* Send initial method packet. */
78 static int
79 send_methods (int conn_fd)
80 {
81 BYTE pkt[4];
82
83 pkt[0] = 0x05;
84 pkt[1] = 0x02;
85 pkt[2] = METH_NOAUTH;
86 pkt[3] = METH_USERPASS;
87 if (send (conn_fd, (const char*)pkt, DIM (pkt), 0) == SOCKET_ERROR) {
88 log_debug ("send_methods failed ec=%d\n", (int)WSAGetLastError ());
89 return -1;
90 }
91 return 0;
92 }
93
94
95 /* Parse the chosen server method. */
96 static int
97 recv_method (int conn_fd)
98 {
99 BYTE pkt[2];
100
101 if (recv (conn_fd, (char*)pkt, DIM (pkt), 0) == SOCKET_ERROR) {
102 log_debug ("recv_method failed ec=%d\n", (int)WSAGetLastError ());
103 return -1;
104 }
105 if (pkt[0] != 0x05) {
106 log_debug ("recv_method: protocol violation\n");
107 return -1;
108 }
109 return pkt[1];
110 }
111
112
113 /*
114 +----+------+----------+------+----------+
115 |VER | ULEN | UNAME | PLEN | PASSWD |
116 +----+------+----------+------+----------+
117 | 1 | 1 | 1 to 255 | 1 | 1 to 255 |
118 +----+------+----------+------+----------+
119 Do user/password authentication.
120 */
121 static int
122 do_userpass_auth (int conn_fd, keyserver_proxy_t ctx, int *err)
123 {
124 BYTE *pkt;
125 DWORD pktlen;
126
127 *err = 0;
128 pktlen = 1+1+strlen (ctx->user)+1+strlen (ctx->pass);
129 pkt = (BYTE*)malloc (pktlen);
130 pkt[0] = 0x05;
131 pkt[1] = strlen (ctx->user);
132 memcpy (pkt+2, ctx->user, strlen (ctx->user));
133 pkt[2+strlen (ctx->user)] = strlen (ctx->pass);
134 memcpy (pkt+2+strlen (ctx->user)+1, ctx->pass, strlen (ctx->pass));
135 if (send (conn_fd, (const char*)pkt, pktlen, 0) == SOCKET_ERROR) {
136 log_debug ("do_userpass_auth failed ec=%d\n", (int)WSAGetLastError ());
137 free (pkt);
138 return -1;
139 }
140 /* Parse reply [VER 1|STATUS 1] */
141 if (recv (conn_fd, (char*)pkt, 2, 0) == SOCKET_ERROR) {
142 log_debug ("do_userpass_auth failed ec=%d\n", (int)WSAGetLastError ());
143 free (pkt);
144 return -1;
145 }
146 *err = pkt[1];
147 free (pkt);
148 if (*err != ERR_SUCCESS)
149 return -1;
150 return 0;
151 }
152
153
154 /* Do the actual authentication. */
155 static int
156 do_auth (int conn_fd, int auth_method, keyserver_proxy_t ctx, int *err)
157 {
158 switch (auth_method) {
159 case PROXY_AUTH_NONE:
160 *err = 0;
161 return 0;
162
163 case PROXY_AUTH_PLAIN:
164 return do_userpass_auth (conn_fd, ctx, err);
165
166 default:
167 return -1;
168 }
169 return 0;
170 }
171
172
173 /*
174 +----+-----+-------+------+----------+----------+
175 |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
176 +----+-----+-------+------+----------+----------+
177 | 1 | 1 | X'00' | 1 | Variable | 2 |
178 +----+-----+-------+------+----------+----------+
179 Send a connection reqeust for host @host and port @port.
180 */
181 static int
182 send_connect_request (int conn_fd, const char *host, WORD port)
183 {
184 struct hostent *hp;
185 DWORD addr;
186 BYTE pkt[10];
187
188 addr = inet_addr (host);
189 if (addr == INADDR_NONE) {
190 hp = gethostbyname (host);
191 if (hp != NULL)
192 memcpy ((char*)&addr, hp->h_addr_list, hp->h_length);
193 else {
194 log_debug ("gethostbyname() failed ec=%d\n", (int)WSAGetLastError ());
195 return -1;
196 }
197 }
198
199 pkt[0] = 0x05;
200 pkt[1] = 0x01; /*CONNECT*/
201 pkt[2] = 0x00;
202 pkt[3] = ADDR_IPV4;
203 pkt[4] = (BYTE)addr >> 24;
204 pkt[5] = (BYTE)addr >> 16;
205 pkt[6] = (BYTE)addr >> 8;
206 pkt[7] = (BYTE)addr >> 0;
207 pkt[8] = (BYTE)port >> 8;
208 pkt[9] = (BYTE)port >> 0;
209 if (send (conn_fd, (const char*)pkt, 10, 0) == SOCKET_ERROR) {
210 log_debug ("send_connect_request failed ec=%d\n", (int)WSAGetLastError ());
211 return -1;
212 }
213
214 return 0;
215 }
216
217
218 /*
219 +----+-----+-------+------+----------+----------+
220 |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT |
221 +----+-----+-------+------+----------+----------+
222 | 1 | 1 | X'00' | 1 | Variable | 2 |
223 +----+-----+-------+------+----------+----------+
224 Parse the connect reply.
225 Set @err with the specific error value.
226 */
227 static int
228 recv_connect_reply (int conn_fd, int *err)
229 {
230 BYTE pkt[4], addr[16], port[2];
231 int ndomain;
232
233 *err = 0;
234 if (recv (conn_fd, (char*)pkt, DIM (pkt), 0) == SOCKET_ERROR) {
235 log_debug ("recv_connect_reply: recv() failed ec=%d\n",
236 (int)WSAGetLastError ());
237 return -1;
238 }
239 if (pkt[0] != 0x05 || pkt[2] != 0x00) {
240 log_debug ("recv_connect_reply: protocol violation.\n");
241 return -1;
242 }
243 *err = pkt[1];
244 if (pkt[1] != ERR_SUCCESS)
245 return -1;
246 switch (pkt[3]) {
247 case ADDR_IPV4:
248 if (recv (conn_fd, (char*)addr, 4, 0) == SOCKET_ERROR)
249 return -1;
250 break;
251
252 case ADDR_DOMAIN:
253 recv (conn_fd, (char*)addr, 1, 0);
254 ndomain = addr[0];
255 /* Ignore the output, just empty the socket buffer. */
256 while (ndomain-- > 0)
257 recv (conn_fd, (char*)addr, 1, 0);
258 break;
259
260 case ADDR_IPV6:
261 if (recv (conn_fd, (char*)addr, DIM (addr), 0) == SOCKET_ERROR)
262 return -1;
263 break;
264 }
265 if (recv (conn_fd, (char*)port, DIM (port), 0) == SOCKET_ERROR)
266 return -1;
267 return 0;
268 }
269
270
271 /* Perform all needed steps to initiate a SOCKSv5 proxy connection .*/
272 int
273 socks_handshake (keyserver_proxy_t ctx, int conn_fd,
274 const char *hostname, WORD port)
275 {
276 int method, err=0;
277
278 if (send_methods (conn_fd))
279 return -1;
280 method = recv_method (conn_fd);
281 if (method == METH_ERR) {
282 msg_box (NULL, _("No acceptable methods"), _("SOCKS Proxy"), MB_ERR);
283 return -1;
284 }
285 if (do_auth (conn_fd, method, ctx, &err)) {
286 if (!err)
287 msg_box (NULL, _("Authentication failed or unspported"),
288 _("SOCKS Proxy"), MB_ERR);
289 else
290 msg_box (NULL, socks_strerror (err), _("SOCKS Proxy"), MB_ERR);
291 return -1;
292 }
293 if (send_connect_request (conn_fd, hostname, port)) {
294 msg_box (NULL, _("Could not send SOCKS request"),
295 _("SOCKS Proxy"), MB_ERR);
296 return -1;
297 }
298 if (recv_connect_reply (conn_fd, &err)) {
299 if (!err)
300 msg_box (NULL, _("Error while parsing SOCKS reply"),
301 _("SOCKS Proxy"), MB_ERR);
302 else
303 msg_box (NULL, socks_strerror (err), _("SOCKS Proxy"), MB_ERR);
304 return -1;
305 }
306 return 0;
307 }
308 #endif

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26