Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / socks.c
blob60d2b92abdefd25d1f694c5a26e84a1fcce667bf
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
8 * Copyright (C) 2002-2009 OpenVPN Technologies, Inc. <sales@openvpn.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * 2004-01-30: Added Socks5 proxy support
27 * (Christof Meerwald, http://cmeerw.org)
29 * see RFC 1928, only supports "no authentication"
32 #include "syshead.h"
34 #ifdef ENABLE_SOCKS
36 #include "common.h"
37 #include "misc.h"
38 #include "win32.h"
39 #include "socket.h"
40 #include "fdmisc.h"
41 #include "proxy.h"
43 #include "memdbg.h"
46 void
47 socks_adjust_frame_parameters (struct frame *frame, int proto)
49 if (proto == PROTO_UDPv4)
50 frame_add_to_extra_link (frame, 10);
53 struct socks_proxy_info *
54 socks_proxy_new (const char *server,
55 int port,
56 bool retry,
57 struct auto_proxy_info *auto_proxy_info)
59 struct socks_proxy_info *p;
61 if (auto_proxy_info)
63 if (!server)
65 if (!auto_proxy_info->socks.server)
66 return NULL;
68 server = auto_proxy_info->socks.server;
69 port = auto_proxy_info->socks.port;
73 ALLOC_OBJ_CLEAR (p, struct socks_proxy_info);
75 ASSERT (server);
76 ASSERT (legal_ipv4_port (port));
78 strncpynt (p->server, server, sizeof (p->server));
79 p->port = port;
80 p->retry = retry;
81 p->defined = true;
83 return p;
86 void
87 socks_proxy_close (struct socks_proxy_info *sp)
89 free (sp);
92 static bool
93 socks_handshake (socket_descriptor_t sd, volatile int *signal_received)
95 char buf[2];
96 int len = 0;
97 const int timeout_sec = 5;
99 /* VER = 5, NMETHODS = 1, METHODS = [0] */
100 const ssize_t size = send (sd, "\x05\x01\x00", 3, MSG_NOSIGNAL);
101 if (size != 3)
103 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "socks_handshake: TCP port write failed on send()");
104 return false;
107 while (len < 2)
109 int status;
110 ssize_t size;
111 fd_set reads;
112 struct timeval tv;
113 char c;
115 FD_ZERO (&reads);
116 FD_SET (sd, &reads);
117 tv.tv_sec = timeout_sec;
118 tv.tv_usec = 0;
120 status = select (sd + 1, &reads, NULL, NULL, &tv);
122 get_signal (signal_received);
123 if (*signal_received)
124 return false;
126 /* timeout? */
127 if (status == 0)
129 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "socks_handshake: TCP port read timeout expired");
130 return false;
133 /* error */
134 if (status < 0)
136 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "socks_handshake: TCP port read failed on select()");
137 return false;
140 /* read single char */
141 size = recv(sd, &c, 1, MSG_NOSIGNAL);
143 /* error? */
144 if (size != 1)
146 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "socks_handshake: TCP port read failed on recv()");
147 return false;
150 /* store char in buffer */
151 buf[len++] = c;
154 /* VER == 5 && METHOD == 0 */
155 if (buf[0] != '\x05' || buf[1] != '\x00')
157 msg (D_LINK_ERRORS, "socks_handshake: Socks proxy returned bad status");
158 return false;
161 return true;
164 static bool
165 recv_socks_reply (socket_descriptor_t sd,
166 struct openvpn_sockaddr *addr,
167 volatile int *signal_received)
169 char atyp = '\0';
170 int alen = 0;
171 int len = 0;
172 char buf[22];
173 const int timeout_sec = 5;
175 if (addr != NULL)
177 addr->sa.sin_family = AF_INET;
178 addr->sa.sin_addr.s_addr = htonl (INADDR_ANY);
179 addr->sa.sin_port = htons (0);
182 while (len < 4 + alen + 2)
184 int status;
185 ssize_t size;
186 fd_set reads;
187 struct timeval tv;
188 char c;
190 FD_ZERO (&reads);
191 FD_SET (sd, &reads);
192 tv.tv_sec = timeout_sec;
193 tv.tv_usec = 0;
195 status = select (sd + 1, &reads, NULL, NULL, &tv);
197 get_signal (signal_received);
198 if (*signal_received)
199 return false;
201 /* timeout? */
202 if (status == 0)
204 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_socks_reply: TCP port read timeout expired");
205 return false;
208 /* error */
209 if (status < 0)
211 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_socks_reply: TCP port read failed on select()");
212 return false;
215 /* read single char */
216 size = recv(sd, &c, 1, MSG_NOSIGNAL);
218 /* error? */
219 if (size != 1)
221 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_socks_reply: TCP port read failed on recv()");
222 return false;
225 if (len == 3)
226 atyp = c;
228 if (len == 4)
230 switch (atyp)
232 case '\x01': /* IP V4 */
233 alen = 4;
234 break;
236 case '\x03': /* DOMAINNAME */
237 alen = (unsigned char) c;
238 break;
240 case '\x04': /* IP V6 */
241 alen = 16;
242 break;
244 default:
245 msg (D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad address type");
246 return false;
250 /* store char in buffer */
251 if (len < (int)sizeof(buf))
252 buf[len] = c;
253 ++len;
256 /* VER == 5 && REP == 0 (succeeded) */
257 if (buf[0] != '\x05' || buf[1] != '\x00')
259 msg (D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad reply");
260 return false;
263 /* ATYP == 1 (IP V4 address) */
264 if (atyp == '\x01' && addr != NULL)
266 memcpy (&addr->sa.sin_addr, buf + 4, sizeof (addr->sa.sin_addr));
267 memcpy (&addr->sa.sin_port, buf + 8, sizeof (addr->sa.sin_port));
271 return true;
274 void
275 establish_socks_proxy_passthru (struct socks_proxy_info *p,
276 socket_descriptor_t sd, /* already open to proxy */
277 const char *host, /* openvpn server remote */
278 const int port, /* openvpn server port */
279 volatile int *signal_received)
281 char buf[128];
282 size_t len;
284 if (!socks_handshake (sd, signal_received))
285 goto error;
287 /* format Socks CONNECT message */
288 buf[0] = '\x05'; /* VER = 5 */
289 buf[1] = '\x01'; /* CMD = 1 (CONNECT) */
290 buf[2] = '\x00'; /* RSV */
291 buf[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
293 len = strlen(host);
294 len = (5 + len + 2 > sizeof(buf)) ? (sizeof(buf) - 5 - 2) : len;
296 buf[4] = (char) len;
297 memcpy(buf + 5, host, len);
299 buf[5 + len] = (char) (port >> 8);
300 buf[5 + len + 1] = (char) (port & 0xff);
303 const ssize_t size = send (sd, buf, 5 + len + 2, MSG_NOSIGNAL);
304 if ((int)size != 5 + (int)len + 2)
306 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "establish_socks_proxy_passthru: TCP port write failed on send()");
307 goto error;
311 /* receive reply from Socks proxy and discard */
312 if (!recv_socks_reply (sd, NULL, signal_received))
313 goto error;
315 return;
317 error:
318 /* on error, should we exit or restart? */
319 if (!*signal_received)
320 *signal_received = (p->retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- socks error */
321 return;
324 void
325 establish_socks_proxy_udpassoc (struct socks_proxy_info *p,
326 socket_descriptor_t ctrl_sd, /* already open to proxy */
327 socket_descriptor_t udp_sd,
328 struct openvpn_sockaddr *relay_addr,
329 volatile int *signal_received)
331 if (!socks_handshake (ctrl_sd, signal_received))
332 goto error;
335 /* send Socks UDP ASSOCIATE message */
336 /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
337 BND.ADDR = 0, BND.PORT = 0 */
338 const ssize_t size = send (ctrl_sd,
339 "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00",
340 10, MSG_NOSIGNAL);
341 if (size != 10)
343 msg (D_LINK_ERRORS | M_ERRNO_SOCK, "establish_socks_proxy_passthru: TCP port write failed on send()");
344 goto error;
348 /* receive reply from Socks proxy */
349 CLEAR (*relay_addr);
350 if (!recv_socks_reply (ctrl_sd, relay_addr, signal_received))
351 goto error;
353 return;
355 error:
356 /* on error, should we exit or restart? */
357 if (!*signal_received)
358 *signal_received = (p->retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- socks error */
359 return;
363 * Remove the 10 byte socks5 header from an incoming
364 * UDP packet, setting *from to the source address.
366 * Run after UDP read.
368 void
369 socks_process_incoming_udp (struct buffer *buf,
370 struct link_socket_actual *from)
372 int atyp;
374 if (BLEN (buf) < 10)
375 goto error;
377 buf_read_u16 (buf);
378 if (buf_read_u8 (buf) != 0)
379 goto error;
381 atyp = buf_read_u8 (buf);
382 if (atyp != 1) /* ATYP == 1 (IP V4) */
383 goto error;
385 buf_read (buf, &from->dest.sa.sin_addr, sizeof (from->dest.sa.sin_addr));
386 buf_read (buf, &from->dest.sa.sin_port, sizeof (from->dest.sa.sin_port));
388 return;
390 error:
391 buf->len = 0;
395 * Add a 10 byte socks header prior to UDP write.
396 * *to is the destination address.
398 * Run before UDP write.
399 * Returns the size of the header.
402 socks_process_outgoing_udp (struct buffer *buf,
403 const struct link_socket_actual *to)
406 * Get a 10 byte subset buffer prepended to buf --
407 * we expect these bytes will be here because
408 * we allocated frame space in socks_adjust_frame_parameters.
410 struct buffer head = buf_sub (buf, 10, true);
412 /* crash if not enough headroom in buf */
413 ASSERT (buf_defined (&head));
415 buf_write_u16 (&head, 0); /* RSV = 0 */
416 buf_write_u8 (&head, 0); /* FRAG = 0 */
417 buf_write_u8 (&head, '\x01'); /* ATYP = 1 (IP V4) */
418 buf_write (&head, &to->dest.sa.sin_addr, sizeof (to->dest.sa.sin_addr));
419 buf_write (&head, &to->dest.sa.sin_port, sizeof (to->dest.sa.sin_port));
421 return 10;
424 #else
425 static void dummy(void) {}
426 #endif /* ENABLE_SOCKS */