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

Annotation of /trunk/Src/wptSOCKS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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


1 twoaday 328 #if 0
2 twoaday 180 /* 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 twoaday 271 #include "wptGPG.h"
29 twoaday 180 #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 twoaday 273 if (send (conn_fd, (const char*)pkt, DIM (pkt), 0) == SOCKET_ERROR) {
88 twoaday 180 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 twoaday 273 if (recv (conn_fd, (char*)pkt, DIM (pkt), 0) == SOCKET_ERROR) {
102 twoaday 180 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 twoaday 273 if (send (conn_fd, (const char*)pkt, 10, 0) == SOCKET_ERROR) {
210 twoaday 180 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 twoaday 273 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 twoaday 180 return -1;
238 twoaday 273 }
239 twoaday 180 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 twoaday 273 /* Ignore the output, just empty the socket buffer. */
256 twoaday 180 while (ndomain-- > 0)
257     recv (conn_fd, (char*)addr, 1, 0);
258     break;
259    
260     case ADDR_IPV6:
261 twoaday 273 if (recv (conn_fd, (char*)addr, DIM (addr), 0) == SOCKET_ERROR)
262 twoaday 180 return -1;
263     break;
264     }
265 twoaday 273 if (recv (conn_fd, (char*)port, DIM (port), 0) == SOCKET_ERROR)
266 twoaday 180 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 twoaday 328 int method, err=0;
277 twoaday 180
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 twoaday 273 msg_box (NULL, _("Authentication failed or unspported"),
288     _("SOCKS Proxy"), MB_ERR);
289 twoaday 180 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 twoaday 273 msg_box (NULL, _("Could not send SOCKS request"),
295     _("SOCKS Proxy"), MB_ERR);
296 twoaday 180 return -1;
297     }
298     if (recv_connect_reply (conn_fd, &err)) {
299     if (!err)
300 twoaday 273 msg_box (NULL, _("Error while parsing SOCKS reply"),
301     _("SOCKS Proxy"), MB_ERR);
302 twoaday 180 else
303     msg_box (NULL, socks_strerror (err), _("SOCKS Proxy"), MB_ERR);
304     return -1;
305     }
306     return 0;
307     }
308 twoaday 328 #endif

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26