OpenVPN
socks.c
Go to the documentation of this file.
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.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 *
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.
13 *
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.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23/*
24 * 2004-01-30: Added Socks5 proxy support, see RFC 1928
25 * (Christof Meerwald, http://cmeerw.org)
26 *
27 * 2010-10-10: Added Socks5 plain text authentication support (RFC 1929)
28 * (Pierre Bourdon <delroth@gmail.com>)
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "syshead.h"
36
37#include "common.h"
38#include "misc.h"
39#include "win32.h"
40#include "socket.h"
41#include "fdmisc.h"
42#include "misc.h"
43#include "proxy.h"
44#include "forward.h"
45
46#include "memdbg.h"
47
48#define UP_TYPE_SOCKS "SOCKS Proxy"
49
50struct socks_proxy_info *
51socks_proxy_new(const char *server, const char *port, const char *authfile)
52{
53 struct socks_proxy_info *p;
54
56
58 ASSERT(port);
59
60 strncpynt(p->server, server, sizeof(p->server));
61 p->port = port;
62
63 if (authfile)
64 {
65 strncpynt(p->authfile, authfile, sizeof(p->authfile));
66 }
67 else
68 {
69 p->authfile[0] = 0;
70 }
71
72 p->defined = true;
73
74 return p;
75}
76
77void
79{
80 free(sp);
81}
82
83static bool
85 struct event_timeout *server_poll_timeout,
86 volatile int *signal_received)
87{
88 char to_send[516];
89 char buf[2];
90 int len = 0;
91 struct user_pass creds;
92 ssize_t size;
93 bool ret = false;
94
95 CLEAR(creds);
97 {
98 msg(M_NONFATAL, "SOCKS failed to get username/password.");
99 goto cleanup;
100 }
101
102 if ((strlen(creds.username) > 255) || (strlen(creds.password) > 255))
103 {
104 msg(M_NONFATAL, "SOCKS username and/or password exceeds 255 characters. "
105 "Authentication not possible.");
106 goto cleanup;
107 }
108
109 int sret = snprintf(to_send, sizeof(to_send), "\x01%c%s%c%s", (int)strlen(creds.username),
110 creds.username, (int)strlen(creds.password), creds.password);
111 ASSERT(sret <= sizeof(to_send));
112
113 size = send(sd, to_send, strlen(to_send), MSG_NOSIGNAL);
114
115 if (size != strlen(to_send))
116 {
118 "socks_username_password_auth: TCP port write failed on send()");
119 goto cleanup;
120 }
121
122 while (len < 2)
123 {
124 int status;
125 ssize_t size;
126 fd_set reads;
127 struct timeval tv;
128 char c;
129
130 FD_ZERO(&reads);
131 openvpn_fd_set(sd, &reads);
132 tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
133 tv.tv_usec = 0;
134
135 status = select(sd + 1, &reads, NULL, NULL, &tv);
136
137 get_signal(signal_received);
138 if (*signal_received)
139 {
140 goto cleanup;
141 }
142
143 /* timeout? */
144 if (status == 0)
145 {
147 "socks_username_password_auth: TCP port read timeout expired");
148 goto cleanup;
149 }
150
151 /* error */
152 if (status < 0)
153 {
155 "socks_username_password_auth: TCP port read failed on select()");
156 goto cleanup;
157 }
158
159 /* read single char */
160 size = recv(sd, &c, 1, MSG_NOSIGNAL);
161
162 /* error? */
163 if (size != 1)
164 {
166 "socks_username_password_auth: TCP port read failed on recv()");
167 goto cleanup;
168 }
169
170 /* store char in buffer */
171 buf[len++] = c;
172 }
173
174 /* VER = 5, SUCCESS = 0 --> auth success */
175 if (buf[0] != 5 && buf[1] != 0)
176 {
177 msg(D_LINK_ERRORS, "socks_username_password_auth: server refused the authentication");
178 goto cleanup;
179 }
180
181 ret = true;
182cleanup:
183 secure_memzero(&creds, sizeof(creds));
184 secure_memzero(to_send, sizeof(to_send));
185 return ret;
186}
187
188static bool
190 struct event_timeout *server_poll_timeout, volatile int *signal_received)
191{
192 char buf[2];
193 int len = 0;
194 ssize_t size;
195
196 /* VER = 5, NMETHODS = 1, METHODS = [0 (no auth)] */
197 char method_sel[3] = { 0x05, 0x01, 0x00 };
198 if (p->authfile[0])
199 {
200 method_sel[2] = 0x02; /* METHODS = [2 (plain login)] */
201 }
202 size = send(sd, method_sel, sizeof(method_sel), MSG_NOSIGNAL);
203 if (size != sizeof(method_sel))
204 {
205 msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port write failed on send()");
206 return false;
207 }
208
209 while (len < 2)
210 {
211 int status;
212 ssize_t size;
213 fd_set reads;
214 struct timeval tv;
215 char c;
216
217 FD_ZERO(&reads);
218 openvpn_fd_set(sd, &reads);
219 tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
220 tv.tv_usec = 0;
221
222 status = select(sd + 1, &reads, NULL, NULL, &tv);
223
224 get_signal(signal_received);
225 if (*signal_received)
226 {
227 return false;
228 }
229
230 /* timeout? */
231 if (status == 0)
232 {
233 msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read timeout expired");
234 return false;
235 }
236
237 /* error */
238 if (status < 0)
239 {
240 msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read failed on select()");
241 return false;
242 }
243
244 /* read single char */
245 size = recv(sd, &c, 1, MSG_NOSIGNAL);
246
247 /* error? */
248 if (size != 1)
249 {
250 msg(D_LINK_ERRORS | M_ERRNO, "socks_handshake: TCP port read failed on recv()");
251 return false;
252 }
253
254 /* store char in buffer */
255 buf[len++] = c;
256 }
257
258 /* VER == 5 */
259 if (buf[0] != '\x05')
260 {
261 msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned bad status");
262 return false;
263 }
264
265 /* validate that the auth method returned is the one sent */
266 if (buf[1] != method_sel[2])
267 {
268 msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned unexpected auth");
269 return false;
270 }
271
272 /* select the appropriate authentication method */
273 switch (buf[1])
274 {
275 case 0: /* no authentication */
276 break;
277
278 case 2: /* login/password */
279 if (!p->authfile[0])
280 {
282 "socks_handshake: server asked for username/login auth but we were "
283 "not provided any credentials");
284 return false;
285 }
286
287 if (!socks_username_password_auth(p, sd, server_poll_timeout, signal_received))
288 {
289 return false;
290 }
291
292 break;
293
294 default: /* unknown auth method */
295 msg(D_LINK_ERRORS, "socks_handshake: unknown SOCKS auth method");
296 return false;
297 }
298
299 return true;
300}
301
302static bool
304 struct event_timeout *server_poll_timeout, volatile int *signal_received)
305{
306 char atyp = '\0';
307 int alen = 0;
308 int len = 0;
309 char buf[270]; /* 4 + alen(max 256) + 2 */
310
311 if (addr != NULL)
312 {
313 addr->addr.in4.sin_family = AF_INET;
314 addr->addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
315 addr->addr.in4.sin_port = htons(0);
316 }
317
318 while (len < 4 + alen + 2)
319 {
320 int status;
321 ssize_t size;
322 fd_set reads;
323 struct timeval tv;
324 char c;
325
326 FD_ZERO(&reads);
327 openvpn_fd_set(sd, &reads);
328 tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
329 tv.tv_usec = 0;
330
331 status = select(sd + 1, &reads, NULL, NULL, &tv);
332
333 get_signal(signal_received);
334 if (*signal_received)
335 {
336 return false;
337 }
338
339 /* timeout? */
340 if (status == 0)
341 {
342 msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read timeout expired");
343 return false;
344 }
345
346 /* error */
347 if (status < 0)
348 {
349 msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read failed on select()");
350 return false;
351 }
352
353 /* read single char */
354 size = recv(sd, &c, 1, MSG_NOSIGNAL);
355
356 /* error? */
357 if (size < 0)
358 {
359 msg(D_LINK_ERRORS | M_ERRNO, "recv_socks_reply: TCP port read failed on recv()");
360 return false;
361 }
362 else if (size == 0)
363 {
364 msg(D_LINK_ERRORS, "ERROR: recv_socks_reply: empty response from socks server");
365 return false;
366 }
367
368 if (len == 3)
369 {
370 atyp = c;
371 }
372
373 if (len == 4)
374 {
375 switch (atyp)
376 {
377 case '\x01': /* IP V4 */
378 alen = 4;
379 break;
380
381 case '\x03': /* DOMAINNAME */
382 /* RFC 1928, section 5: 1 byte length, <n> bytes name,
383 * so the total "address length" is (length+1)
384 */
385 alen = (unsigned char)c + 1;
386 break;
387
388 case '\x04': /* IP V6 */
389 alen = 16;
390 break;
391
392 default:
393 msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad address type");
394 return false;
395 }
396 }
397
398 /* store char in buffer */
399 if (len < (int)sizeof(buf))
400 {
401 buf[len] = c;
402 }
403 ++len;
404 }
405
406 /* VER == 5 && REP == 0 (succeeded) */
407 if (buf[0] != '\x05' || buf[1] != '\x00')
408 {
409 msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad reply");
410 return false;
411 }
412
413 /* ATYP == 1 (IP V4 address) */
414 if (atyp == '\x01' && addr != NULL)
415 {
416 memcpy(&addr->addr.in4.sin_addr, buf + 4, sizeof(addr->addr.in4.sin_addr));
417 memcpy(&addr->addr.in4.sin_port, buf + 8, sizeof(addr->addr.in4.sin_port));
418 struct gc_arena gc = gc_new();
419 msg(M_INFO, "SOCKS proxy wants us to send UDP to %s", print_openvpn_sockaddr(addr, &gc));
420 gc_free(&gc);
421 }
422
423
424 return true;
425}
426
427static int
428port_from_servname(const char *servname)
429{
430 int port = 0;
431 port = atoi(servname);
432 if (port > 0 && port < 65536)
433 {
434 return port;
435 }
436
437 struct servent *service;
438 service = getservbyname(servname, NULL);
439 if (service)
440 {
441 return service->s_port;
442 }
443
444 return 0;
445}
446
447void
449 socket_descriptor_t sd, /* already open to proxy */
450 const char *host, /* openvpn server remote */
451 const char *servname, /* openvpn server port */
452 struct event_timeout *server_poll_timeout,
453 struct signal_info *sig_info)
454{
455 char buf[270];
456 size_t len;
457
458 if (!socks_handshake(p, sd, server_poll_timeout, &sig_info->signal_received))
459 {
460 goto error;
461 }
462
463 /* format Socks CONNECT message */
464 buf[0] = '\x05'; /* VER = 5 */
465 buf[1] = '\x01'; /* CMD = 1 (CONNECT) */
466 buf[2] = '\x00'; /* RSV */
467 buf[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
468
469 len = strlen(host);
470 len = (5 + len + 2 > sizeof(buf)) ? (sizeof(buf) - 5 - 2) : len;
471
472 buf[4] = (char)len;
473 memcpy(buf + 5, host, len);
474
475 int port = port_from_servname(servname);
476 if (port == 0)
477 {
478 msg(D_LINK_ERRORS, "establish_socks_proxy_passthrough: Cannot convert %s to port number",
479 servname);
480 goto error;
481 }
482
483 buf[5 + len] = (char)(port >> 8);
484 buf[5 + len + 1] = (char)(port & 0xff);
485
486 {
487 const ssize_t size = send(sd, buf, 5 + len + 2, MSG_NOSIGNAL);
488 if ((int)size != 5 + (int)len + 2)
489 {
491 "establish_socks_proxy_passthru: TCP port write failed on send()");
492 goto error;
493 }
494 }
495
496
497 /* receive reply from Socks proxy and discard */
498 if (!recv_socks_reply(sd, NULL, server_poll_timeout, &sig_info->signal_received))
499 {
500 goto error;
501 }
502
503 return;
504
505error:
506 /* SOFT-SIGUSR1 -- socks error */
507 register_signal(sig_info, SIGUSR1, "socks-error");
508 return;
509}
510
511void
513 socket_descriptor_t ctrl_sd, /* already open to proxy */
514 struct openvpn_sockaddr *relay_addr,
515 struct event_timeout *server_poll_timeout,
516 struct signal_info *sig_info)
517{
518 if (!socks_handshake(p, ctrl_sd, server_poll_timeout, &sig_info->signal_received))
519 {
520 goto error;
521 }
522
523 {
524 /* send Socks UDP ASSOCIATE message */
525 /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
526 * BND.ADDR = 0, BND.PORT = 0 */
527 const ssize_t size =
528 send(ctrl_sd, "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00", 10, MSG_NOSIGNAL);
529 if (size != 10)
530 {
532 "establish_socks_proxy_passthru: TCP port write failed on send()");
533 goto error;
534 }
535 }
536
537 /* receive reply from Socks proxy */
538 CLEAR(*relay_addr);
539 if (!recv_socks_reply(ctrl_sd, relay_addr, server_poll_timeout, &sig_info->signal_received))
540 {
541 goto error;
542 }
543
544 return;
545
546error:
547 /* SOFT-SIGUSR1 -- socks error */
548 register_signal(sig_info, SIGUSR1, "socks-error");
549 return;
550}
551
552/*
553 * Remove the 10 byte socks5 header from an incoming
554 * UDP packet, setting *from to the source address.
555 *
556 * Run after UDP read.
557 */
558void
560{
561 int atyp;
562
563 if (BLEN(buf) < 10)
564 {
565 goto error;
566 }
567
568 buf_read_u16(buf);
569 if (buf_read_u8(buf) != 0)
570 {
571 goto error;
572 }
573
574 atyp = buf_read_u8(buf);
575 if (atyp != 1) /* ATYP == 1 (IP V4) */
576 {
577 goto error;
578 }
579
580 buf_read(buf, &from->dest.addr.in4.sin_addr, sizeof(from->dest.addr.in4.sin_addr));
581 buf_read(buf, &from->dest.addr.in4.sin_port, sizeof(from->dest.addr.in4.sin_port));
582
583 return;
584
585error:
586 buf->len = 0;
587}
588
589/*
590 * Add a 10 byte socks header prior to UDP write.
591 * *to is the destination address.
592 *
593 * Run before UDP write.
594 * Returns the size of the header.
595 */
596int
598{
599 /*
600 * Get a 10 byte subset buffer prepended to buf --
601 * we expect these bytes will be here because
602 * we always allocate space for these bytes
603 */
604 struct buffer head = buf_sub(buf, 10, true);
605
606 /* crash if not enough headroom in buf */
607 ASSERT(buf_defined(&head));
608
609 buf_write_u16(&head, 0); /* RSV = 0 */
610 buf_write_u8(&head, 0); /* FRAG = 0 */
611 buf_write_u8(&head, '\x01'); /* ATYP = 1 (IP V4) */
612 buf_write(&head, &to->dest.addr.in4.sin_addr, sizeof(to->dest.addr.in4.sin_addr));
613 buf_write(&head, &to->dest.addr.in4.sin_port, sizeof(to->dest.addr.in4.sin_port));
614
615 return 10;
616}
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition buffer.c:222
static bool buf_write_u16(struct buffer *dest, uint16_t data)
Definition buffer.h:690
static int buf_read_u16(struct buffer *buf)
Definition buffer.h:787
static bool buf_read(struct buffer *src, void *dest, int size)
Definition buffer.h:762
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition buffer.h:414
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition buffer.h:660
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition buffer.h:684
static int buf_read_u8(struct buffer *buf)
Definition buffer.h:774
#define BLEN(buf)
Definition buffer.h:126
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:361
static void gc_free(struct gc_arena *a)
Definition buffer.h:1015
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1042
static bool buf_defined(const struct buffer *buf)
Definition buffer.h:228
static struct gc_arena gc_new(void)
Definition buffer.h:1007
#define M_INFO
Definition errlevel.h:54
#define D_LINK_ERRORS
Definition errlevel.h:56
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
Definition fdmisc.h:39
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
Definition forward.c:497
Interface functions to the internal and external multiplexers.
static SERVICE_STATUS status
Definition interactive.c:51
static SERVICE_STATUS_HANDLE service
Definition interactive.c:50
#define GET_USER_PASS_MANAGEMENT
Definition misc.h:110
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
Retrieves the user credentials from various sources depending on the flags.
Definition misc.h:150
#define CLEAR(x)
Definition basic.h:32
#define M_NONFATAL
Definition error.h:89
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
#define M_ERRNO
Definition error.h:93
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
Definition sig.c:228
static void get_signal(volatile int *sig)
Copy the global signal_received (if non-zero) to the passed-in argument sig.
Definition sig.h:109
#define MSG_NOSIGNAL
Definition socket.h:242
static const char * print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc)
Definition socket_util.h:71
static int port_from_servname(const char *servname)
Definition socks.c:428
void establish_socks_proxy_passthru(struct socks_proxy_info *p, socket_descriptor_t sd, const char *host, const char *servname, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition socks.c:448
static bool socks_handshake(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:189
int socks_process_outgoing_udp(struct buffer *buf, const struct link_socket_actual *to)
Definition socks.c:597
static bool socks_username_password_auth(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:84
#define UP_TYPE_SOCKS
Definition socks.c:48
void socks_process_incoming_udp(struct buffer *buf, struct link_socket_actual *from)
Definition socks.c:559
static bool recv_socks_reply(socket_descriptor_t sd, struct openvpn_sockaddr *addr, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:303
struct socks_proxy_info * socks_proxy_new(const char *server, const char *port, const char *authfile)
Definition socks.c:51
void establish_socks_proxy_udpassoc(struct socks_proxy_info *p, socket_descriptor_t ctrl_sd, struct openvpn_sockaddr *relay_addr, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition socks.c:512
void socks_proxy_close(struct socks_proxy_info *sp)
Definition socks.c:78
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
union openvpn_sockaddr::@27 addr
struct sockaddr_in in4
Definition socket_util.h:43
volatile int signal_received
Definition sig.h:42
char authfile[256]
Definition socks.h:42
char server[128]
Definition socks.h:40
const char * port
Definition socks.h:41
char password[USER_PASS_LEN]
Definition misc.h:68
char username[USER_PASS_LEN]
Definition misc.h:67
SOCKET socket_descriptor_t
Definition syshead.h:440
static int cleanup(void **state)
struct gc_arena gc
Definition test_ssl.c:154