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

Contents of /trunk/Src/wptSOCKS.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 180 - (show 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 /* 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