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

Annotation of /trunk/Src/wptSOCKS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 180 - (hide annotations)
Mon Mar 6 14:41:58 2006 UTC (18 years, 11 months ago) by twoaday
File size: 7849 byte(s)
2006-02-27  Timo Schulz  <twoaday@freakmail.de>
 
        * wptSOCKS.cpp (socks_handshake): New.
        * wptMainProc.cpp (winpt_main_proc): A dbl-click forces
        the key manager in teh foreground if possible.
        * wptHotkey.cpp (hotkey_unregister): Unregister all hotkeys.
        * wptRegistry.cpp (get_reg_proxy_prefs,
        set_reg_proxy_prefs): Use directly the proxy context.
        Changed all callers.
        * wptProxySettingsDlg.cpp (init_proxy_protocols): New.
        (keyserver_proxy_dlg_proc): Use directly the proxy context.
        * wptKeyserver.cpp (kserver_connect): Better proxy support.
        (kserver_send_request, kserver_recvkey_request): Likewise.
        * wptKeyserverDlg.cpp (name_from_proto): New.
        (set_proxy): Adjusted for the new code.


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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26