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
8 * Copyright (C) 2002-2010 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, see RFC 1928
27 * (Christof Meerwald, http://cmeerw.org)
29 * 2010-10-10: Added Socks5 plain text authentication support (RFC 1929)
30 * (Pierre Bourdon <delroth@gmail.com>)
47 #define UP_TYPE_SOCKS "SOCKS Proxy"
50 socks_adjust_frame_parameters (struct frame
*frame
, int proto
)
52 if (proto
== PROTO_UDPv4
)
53 frame_add_to_extra_link (frame
, 10);
56 struct socks_proxy_info
*
57 socks_proxy_new (const char *server
,
61 struct auto_proxy_info
*auto_proxy_info
)
63 struct socks_proxy_info
*p
;
69 if (!auto_proxy_info
->socks
.server
)
72 server
= auto_proxy_info
->socks
.server
;
73 port
= auto_proxy_info
->socks
.port
;
77 ALLOC_OBJ_CLEAR (p
, struct socks_proxy_info
);
80 ASSERT (legal_ipv4_port (port
));
82 strncpynt (p
->server
, server
, sizeof (p
->server
));
86 strncpynt (p
->authfile
, authfile
, sizeof (p
->authfile
));
97 socks_proxy_close (struct socks_proxy_info
*sp
)
103 socks_username_password_auth (struct socks_proxy_info
*p
,
104 socket_descriptor_t sd
,
105 volatile int *signal_received
)
110 const int timeout_sec
= 5;
111 struct user_pass creds
;
115 get_user_pass (&creds
, p
->authfile
, UP_TYPE_SOCKS
, GET_USER_PASS_MANAGEMENT
);
117 if( !creds
.username
|| (strlen(creds
.username
) > 255)
118 || !creds
.password
|| (strlen(creds
.password
) > 255) ) {
120 "SOCKS username and/or password exceeds 255 characters. "
121 "Authentication not possible.");
124 openvpn_snprintf (to_send
, sizeof (to_send
), "\x01%c%s%c%s", (int) strlen(creds
.username
),
125 creds
.username
, (int) strlen(creds
.password
), creds
.password
);
126 size
= send (sd
, to_send
, strlen(to_send
), MSG_NOSIGNAL
);
128 if (size
!= strlen (to_send
))
130 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_username_password_auth: TCP port write failed on send()");
144 tv
.tv_sec
= timeout_sec
;
147 status
= select (sd
+ 1, &reads
, NULL
, NULL
, &tv
);
149 get_signal (signal_received
);
150 if (*signal_received
)
156 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_username_password_auth: TCP port read timeout expired");
163 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_username_password_auth: TCP port read failed on select()");
167 /* read single char */
168 size
= recv(sd
, &c
, 1, MSG_NOSIGNAL
);
173 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_username_password_auth: TCP port read failed on recv()");
177 /* store char in buffer */
181 /* VER = 5, SUCCESS = 0 --> auth success */
182 if (buf
[0] != 5 && buf
[1] != 0)
184 msg (D_LINK_ERRORS
, "socks_username_password_auth: server refused the authentication");
192 socks_handshake (struct socks_proxy_info
*p
,
193 socket_descriptor_t sd
,
194 volatile int *signal_received
)
198 const int timeout_sec
= 5;
200 /* VER = 5, NMETHODS = 2, METHODS = [0 (no auth), 2 (plain login)] */
201 const ssize_t size
= send (sd
, "\x05\x02\x00\x02", 4, MSG_NOSIGNAL
);
204 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port write failed on send()");
218 tv
.tv_sec
= timeout_sec
;
221 status
= select (sd
+ 1, &reads
, NULL
, NULL
, &tv
);
223 get_signal (signal_received
);
224 if (*signal_received
)
230 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read timeout expired");
237 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read failed on select()");
241 /* read single char */
242 size
= recv(sd
, &c
, 1, MSG_NOSIGNAL
);
247 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read failed on recv()");
251 /* store char in buffer */
256 if (buf
[0] != '\x05')
258 msg (D_LINK_ERRORS
, "socks_handshake: Socks proxy returned bad status");
262 /* select the appropriate authentication method */
265 case 0: /* no authentication */
268 case 2: /* login/password */
271 msg(D_LINK_ERRORS
, "socks_handshake: server asked for username/login auth but we were "
272 "not provided any credentials");
276 if (!socks_username_password_auth(p
, sd
, signal_received
))
281 default: /* unknown auth method */
282 msg(D_LINK_ERRORS
, "socks_handshake: unknown SOCKS auth method");
290 recv_socks_reply (socket_descriptor_t sd
,
291 struct openvpn_sockaddr
*addr
,
292 volatile int *signal_received
)
298 const int timeout_sec
= 5;
302 addr
->sa
.sin_family
= AF_INET
;
303 addr
->sa
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
304 addr
->sa
.sin_port
= htons (0);
307 while (len
< 4 + alen
+ 2)
317 tv
.tv_sec
= timeout_sec
;
320 status
= select (sd
+ 1, &reads
, NULL
, NULL
, &tv
);
322 get_signal (signal_received
);
323 if (*signal_received
)
329 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read timeout expired");
336 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read failed on select()");
340 /* read single char */
341 size
= recv(sd
, &c
, 1, MSG_NOSIGNAL
);
346 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read failed on recv()");
357 case '\x01': /* IP V4 */
361 case '\x03': /* DOMAINNAME */
362 alen
= (unsigned char) c
;
365 case '\x04': /* IP V6 */
370 msg (D_LINK_ERRORS
, "recv_socks_reply: Socks proxy returned bad address type");
375 /* store char in buffer */
376 if (len
< (int)sizeof(buf
))
381 /* VER == 5 && REP == 0 (succeeded) */
382 if (buf
[0] != '\x05' || buf
[1] != '\x00')
384 msg (D_LINK_ERRORS
, "recv_socks_reply: Socks proxy returned bad reply");
388 /* ATYP == 1 (IP V4 address) */
389 if (atyp
== '\x01' && addr
!= NULL
)
391 memcpy (&addr
->sa
.sin_addr
, buf
+ 4, sizeof (addr
->sa
.sin_addr
));
392 memcpy (&addr
->sa
.sin_port
, buf
+ 8, sizeof (addr
->sa
.sin_port
));
400 establish_socks_proxy_passthru (struct socks_proxy_info
*p
,
401 socket_descriptor_t sd
, /* already open to proxy */
402 const char *host
, /* openvpn server remote */
403 const int port
, /* openvpn server port */
404 volatile int *signal_received
)
409 if (!socks_handshake (p
, sd
, signal_received
))
412 /* format Socks CONNECT message */
413 buf
[0] = '\x05'; /* VER = 5 */
414 buf
[1] = '\x01'; /* CMD = 1 (CONNECT) */
415 buf
[2] = '\x00'; /* RSV */
416 buf
[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
419 len
= (5 + len
+ 2 > sizeof(buf
)) ? (sizeof(buf
) - 5 - 2) : len
;
422 memcpy(buf
+ 5, host
, len
);
424 buf
[5 + len
] = (char) (port
>> 8);
425 buf
[5 + len
+ 1] = (char) (port
& 0xff);
428 const ssize_t size
= send (sd
, buf
, 5 + len
+ 2, MSG_NOSIGNAL
);
429 if ((int)size
!= 5 + (int)len
+ 2)
431 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "establish_socks_proxy_passthru: TCP port write failed on send()");
436 /* receive reply from Socks proxy and discard */
437 if (!recv_socks_reply (sd
, NULL
, signal_received
))
443 /* on error, should we exit or restart? */
444 if (!*signal_received
)
445 *signal_received
= (p
->retry
? SIGUSR1
: SIGTERM
); /* SOFT-SIGUSR1 -- socks error */
450 establish_socks_proxy_udpassoc (struct socks_proxy_info
*p
,
451 socket_descriptor_t ctrl_sd
, /* already open to proxy */
452 socket_descriptor_t udp_sd
,
453 struct openvpn_sockaddr
*relay_addr
,
454 volatile int *signal_received
)
456 if (!socks_handshake (p
, ctrl_sd
, signal_received
))
460 /* send Socks UDP ASSOCIATE message */
461 /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
462 BND.ADDR = 0, BND.PORT = 0 */
463 const ssize_t size
= send (ctrl_sd
,
464 "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00",
468 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "establish_socks_proxy_passthru: TCP port write failed on send()");
473 /* receive reply from Socks proxy */
475 if (!recv_socks_reply (ctrl_sd
, relay_addr
, signal_received
))
481 /* on error, should we exit or restart? */
482 if (!*signal_received
)
483 *signal_received
= (p
->retry
? SIGUSR1
: SIGTERM
); /* SOFT-SIGUSR1 -- socks error */
488 * Remove the 10 byte socks5 header from an incoming
489 * UDP packet, setting *from to the source address.
491 * Run after UDP read.
494 socks_process_incoming_udp (struct buffer
*buf
,
495 struct link_socket_actual
*from
)
503 if (buf_read_u8 (buf
) != 0)
506 atyp
= buf_read_u8 (buf
);
507 if (atyp
!= 1) /* ATYP == 1 (IP V4) */
510 buf_read (buf
, &from
->dest
.sa
.sin_addr
, sizeof (from
->dest
.sa
.sin_addr
));
511 buf_read (buf
, &from
->dest
.sa
.sin_port
, sizeof (from
->dest
.sa
.sin_port
));
520 * Add a 10 byte socks header prior to UDP write.
521 * *to is the destination address.
523 * Run before UDP write.
524 * Returns the size of the header.
527 socks_process_outgoing_udp (struct buffer
*buf
,
528 const struct link_socket_actual
*to
)
531 * Get a 10 byte subset buffer prepended to buf --
532 * we expect these bytes will be here because
533 * we allocated frame space in socks_adjust_frame_parameters.
535 struct buffer head
= buf_sub (buf
, 10, true);
537 /* crash if not enough headroom in buf */
538 ASSERT (buf_defined (&head
));
540 buf_write_u16 (&head
, 0); /* RSV = 0 */
541 buf_write_u8 (&head
, 0); /* FRAG = 0 */
542 buf_write_u8 (&head
, '\x01'); /* ATYP = 1 (IP V4) */
543 buf_write (&head
, &to
->dest
.sa
.sin_addr
, sizeof (to
->dest
.sa
.sin_addr
));
544 buf_write (&head
, &to
->dest
.sa
.sin_port
, sizeof (to
->dest
.sa
.sin_port
));
550 static void dummy(void) {}
551 #endif /* ENABLE_SOCKS */