OpenVPN
proxy.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-2026 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#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include "common.h"
30#include "misc.h"
31#include "crypto.h"
32#include "win32.h"
33#include "socket.h"
34#include "fdmisc.h"
35#include "proxy.h"
36#include "base64.h"
37#include "httpdigest.h"
38#include "memdbg.h"
39#include "forward.h"
40
41#define UP_TYPE_PROXY "HTTP Proxy"
42
43struct http_proxy_options *
45{
46 if (!*hpo)
47 {
49 /* http proxy defaults */
50 (*hpo)->http_version = "1.0";
51 }
52 return *hpo;
53}
54
55
56/* cached proxy username/password */
58
59bool
60proxy_recv_char(uint8_t *c, const char *name, socket_descriptor_t sd,
61 struct timeval *timeout, volatile int *signal_received)
62{
63 fd_set reads;
64 FD_ZERO(&reads);
65 openvpn_fd_set(sd, &reads);
66
67 const int status = openvpn_select(sd + 1, &reads, NULL, NULL, timeout);
68
69 get_signal(signal_received);
70 if (*signal_received)
71 {
72 return false;
73 }
74
75 /* timeout? */
76 if (status == 0)
77 {
78 msg(D_LINK_ERRORS | M_ERRNO, "%s: TCP port read timeout expired", name);
79 return false;
80 }
81
82 /* error */
83 if (status < 0)
84 {
85 msg(D_LINK_ERRORS | M_ERRNO, "%s: TCP port read failed on select()", name);
86 return false;
87 }
88
89 /* read single char */
90 const ssize_t size = recv(sd, (void *)c, 1, MSG_NOSIGNAL);
91
92 /* error? */
93 if (size != 1)
94 {
95 msg(D_LINK_ERRORS | M_ERRNO, "%s: TCP port read failed on recv()", name);
96 return false;
97 }
98
99 return true;
100}
101
102
103static bool
104recv_line(socket_descriptor_t sd, char *buf, int len, const int timeout_sec, const bool verbose,
105 struct buffer *lookahead, volatile int *signal_received)
106{
107 struct buffer la;
108 int lastc = 0;
109
110 CLEAR(la);
111 if (lookahead)
112 {
113 la = *lookahead;
114 }
115
116 while (true)
117 {
118 struct timeval tv;
119 uint8_t c;
120
121 if (buf_defined(&la))
122 {
123 ASSERT(buf_init(&la, 0));
124 }
125
126 tv.tv_sec = timeout_sec;
127 tv.tv_usec = 0;
128
129 if (!proxy_recv_char(&c, "recv_line", sd, &tv, signal_received))
130 {
131 return false;
132 }
133
134#if 0
135 if (isprint(c))
136 {
137 msg(M_INFO, "PROXY: read '%c' (%d)", c, (int)c);
138 }
139 else
140 {
141 msg(M_INFO, "PROXY: read (%d)", (int)c);
142 }
143#endif
144
145 /* store char in buffer */
146 if (len > 1)
147 {
148 *buf++ = c;
149 --len;
150 }
151
152 /* also store char in lookahead buffer */
153 if (buf_defined(&la))
154 {
155 buf_write_u8(&la, c);
156 if (!isprint(c) && !isspace(c)) /* not ascii? */
157 {
158 if (verbose)
159 {
161 "recv_line: Non-ASCII character (%d) read on recv()", (int)c);
162 }
163 *lookahead = la;
164 return false;
165 }
166 }
167
168 /* end of line? */
169 if (lastc == '\r' && c == '\n')
170 {
171 break;
172 }
173
174 lastc = c;
175 }
176
177 /* append trailing null */
178 if (len > 0)
179 {
180 *buf++ = '\0';
181 }
182
183 return true;
184}
185
186bool
187proxy_send(socket_descriptor_t sd, const void *buf, size_t buf_len)
188{
189 const ssize_t size = openvpn_send(sd, buf, buf_len, MSG_NOSIGNAL);
190 if (size != (ssize_t)buf_len)
191 {
192 msg(D_LINK_ERRORS | M_ERRNO, "proxy_send: TCP port write failed on send()");
193 return false;
194 }
195 return true;
196}
197
198static bool
200{
201 bool ret;
202
203 struct buffer buf = alloc_buf(strlen(src) + 2);
204 ASSERT(buf_write(&buf, src, strlen(src)));
205 ASSERT(buf_write(&buf, "\r\n", 2));
206 ret = proxy_send(sd, BSTR(&buf), BLEN(&buf));
207 free_buf(&buf);
208 return ret;
209}
210
211static bool
213{
214 return send_line_crlf(sd, "");
215}
216
217uint8_t *
219{
220 uint8_t *ret = NULL;
221 char *b64out = NULL;
222 ASSERT(openvpn_base64_encode((const void *)str, src_len, &b64out) >= 0);
223 ret = (uint8_t *)string_alloc(b64out, gc);
224 free(b64out);
225 return ret;
226}
227
228uint8_t *
230{
231 return make_base64_string2(str, (int)strlen((const char *)str), gc);
232}
233
234static const char *
236{
237 struct buffer out = alloc_buf_gc(strlen(p->up.username) + strlen(p->up.password) + 2, gc);
238 ASSERT(strlen(p->up.username) > 0);
239 buf_printf(&out, "%s:%s", p->up.username, p->up.password);
240 char *ret = (char *)make_base64_string((const uint8_t *)BSTR(&out), gc);
241 secure_memzero(BSTR(&out), out.len);
242 return ret;
243}
244
245static void
250
251static void
253{
254 /*
255 * in case of forced (re)load, make sure the static storage is set as
256 * undefined, otherwise get_user_pass() won't try to load any credential
257 */
258 if (force)
259 {
261 }
262
264 {
265 unsigned int flags = GET_USER_PASS_MANAGEMENT;
266 const char *auth_file = p->options.auth_file;
267 if (p->options.auth_file_up)
268 {
269 auth_file = p->options.auth_file_up;
270 }
271 if (p->queried_creds && !static_proxy_user_pass.nocache)
272 {
274 }
275 if (p->options.inline_creds)
276 {
278 }
280 static_proxy_user_pass.nocache = p->options.nocache;
282 }
283
284 /*
285 * Using cached credentials
286 */
287 p->queried_creds = true;
288 p->up = static_proxy_user_pass; /* this is a copy of protected memory */
289}
290
291#if 0
292/* function only used in #if 0 debug statement */
293static void
295 int timeout,
296 volatile int *signal_received)
297{
298 char buf[256];
299 while (true)
300 {
301 if (!recv_line(sd, buf, sizeof(buf), timeout, true, NULL, signal_received))
302 {
303 return;
304 }
305 chomp(buf);
306 msg(D_PROXY, "PROXY HEADER: '%s'", buf);
307 }
308}
309#endif
310
311/*
312 * Extract the Proxy-Authenticate header from the stream.
313 * Consumes all headers.
314 */
315static int
317 volatile int *signal_received)
318{
319 char buf[256];
320 int ret = HTTP_AUTH_NONE;
321 while (true)
322 {
323 if (!recv_line(sd, buf, sizeof(buf), timeout, true, NULL, signal_received))
324 {
325 free(*data);
326 *data = NULL;
327 return HTTP_AUTH_NONE;
328 }
329 chomp(buf);
330 if (!strlen(buf))
331 {
332 return ret;
333 }
334 if (ret == HTTP_AUTH_NONE && !strncmp(buf, "Proxy-Authenticate: ", 20))
335 {
336 if (!strncmp(buf + 20, "Basic ", 6))
337 {
338 msg(D_PROXY, "PROXY AUTH BASIC: '%s'", buf);
339 *data = string_alloc(buf + 26, NULL);
340 ret = HTTP_AUTH_BASIC;
341 }
342#if PROXY_DIGEST_AUTH
343 else if (!strncmp(buf + 20, "Digest ", 7))
344 {
345 msg(D_PROXY, "PROXY AUTH DIGEST: '%s'", buf);
346 *data = string_alloc(buf + 27, NULL);
347 ret = HTTP_AUTH_DIGEST;
348 }
349#endif
350 }
351 }
352}
353
354static void
356{
357 free(p->proxy_authenticate);
358 p->proxy_authenticate = data;
359}
360
361/*
362 * Parse out key/value pairs from Proxy-Authenticate string.
363 * Return true on success, or false on parse failure.
364 */
365static bool
366get_key_value(const char *str, /* source string */
367 char *key, /* key stored here */
368 char *value, /* value stored here */
369 int max_key_len, int max_value_len, const char **endptr) /* next search position */
370{
371 int c;
372 bool starts_with_quote = false;
373 bool escape = false;
374
375 for (c = max_key_len - 1; (*str && (*str != '=') && c--);)
376 {
377 *key++ = *str++;
378 }
379 *key = '\0';
380
381 if ('=' != *str++)
382 {
383 /* no key/value found */
384 return false;
385 }
386
387 if ('\"' == *str)
388 {
389 /* quoted string */
390 str++;
391 starts_with_quote = true;
392 }
393
394 for (c = max_value_len - 1; *str && c--; str++)
395 {
396 switch (*str)
397 {
398 case '\\':
399 if (!escape)
400 {
401 /* possibly the start of an escaped quote */
402 escape = true;
403 *value++ = '\\'; /* even though this is an escape character, we still
404 * store it as-is in the target buffer */
405 continue;
406 }
407 break;
408
409 case ',':
411 {
412 /* this signals the end of the value if we didn't get a starting quote
413 * and then we do "sloppy" parsing */
414 c = 0; /* the end */
415 continue;
416 }
417 break;
418
419 case '\r':
420 case '\n':
421 /* end of string */
422 c = 0;
423 continue;
424
425 case '\"':
427 {
428 /* end of string */
429 c = 0;
430 continue;
431 }
432 break;
433 }
434 escape = false;
435 *value++ = *str;
436 }
437 *value = '\0';
438
439 *endptr = str;
440
441 return true; /* success */
442}
443
444static char *
445get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
446{
447 char k[64];
448 char v[256];
449 const char *content = pa;
450
451 while (true)
452 {
453 const int status = get_key_value(content, k, v, sizeof(k), sizeof(v), &content);
454 if (status)
455 {
456 if (!strcmp(key, k))
457 {
458 return string_alloc(v, gc);
459 }
460 }
461 else
462 {
463 return NULL;
464 }
465
466 /* advance to start of next key */
467 if (*content == ',')
468 {
469 ++content;
470 }
471 while (*content && isspace(*content))
472 {
473 ++content;
474 }
475 }
476}
477
478struct http_proxy_info *
480{
481 struct http_proxy_info *p;
482
483 if (!o || !o->server)
484 {
485 msg(M_FATAL, "HTTP_PROXY: server not specified");
486 }
487
488 ASSERT(o->port);
489
491 p->options = *o;
492
493 /* parse authentication method */
495 if (o->auth_method_string)
496 {
497 if (!strcmp(o->auth_method_string, "none"))
498 {
500 }
501 else if (!strcmp(o->auth_method_string, "basic"))
502 {
504 }
505 else
506 {
507 msg(M_FATAL, "ERROR: unknown HTTP authentication method: '%s'", o->auth_method_string);
508 }
509 }
510
511 /* When basic authentication is requested, get credentials now.
512 * In case of "auto" negotiation credentials will be retrieved later once
513 * we know whether we need any. */
515 {
517 }
518
519 p->defined = true;
520 return p;
521}
522
523void
525{
526 free(hp);
527}
528
529static bool
530add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, /* already open to proxy */
531 const char *host /* openvpn server remote */
532)
533{
534 char buf[512];
535 int i;
536 bool host_header_sent = false;
537
538 /*
539 * Send custom headers if provided
540 * If content is NULL the whole header is in name
541 * Also remember if we already sent a Host: header
542 */
543 for (i = 0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name; i++)
544 {
546 {
547 snprintf(buf, sizeof(buf), "%s: %s", p->options.custom_headers[i].name,
549 if (!strcasecmp(p->options.custom_headers[i].name, "Host"))
550 {
551 host_header_sent = true;
552 }
553 }
554 else
555 {
556 snprintf(buf, sizeof(buf), "%s", p->options.custom_headers[i].name);
557 if (!strncasecmp(p->options.custom_headers[i].name, "Host:", 5))
558 {
559 host_header_sent = true;
560 }
561 }
562
563 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
564 if (!send_line_crlf(sd, buf))
565 {
566 return false;
567 }
568 }
569
570 if (!host_header_sent)
571 {
572 snprintf(buf, sizeof(buf), "Host: %s", host);
573 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
574 if (!send_line_crlf(sd, buf))
575 {
576 return false;
577 }
578 }
579
580 /* send User-Agent string if provided */
581 if (p->options.user_agent)
582 {
583 snprintf(buf, sizeof(buf), "User-Agent: %s", p->options.user_agent);
584 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
585 if (!send_line_crlf(sd, buf))
586 {
587 return false;
588 }
589 }
590
591 return true;
592}
593
594
595bool
597 socket_descriptor_t sd, /* already open to proxy */
598 const char *host, /* openvpn server remote */
599 const char *port, /* openvpn server port */
600 struct event_timeout *server_poll_timeout, struct buffer *lookahead,
601 struct signal_info *sig_info)
602{
603 struct gc_arena gc = gc_new();
604 char buf[512];
605 int status;
606 int nparms;
607 bool ret = false;
608 bool processed = false;
609 volatile int *signal_received = &sig_info->signal_received;
610
611 /* get user/pass if not previously given */
613 {
614 get_user_pass_http(p, false);
615
616 if (p->up.nocache)
617 {
619 }
621 }
622
623 /* are we being called again after getting the digest server nonce in the previous transaction?
624 */
626 {
627 nparms = 1;
628 status = 407;
629 }
630 else
631 {
632 /* format HTTP CONNECT message */
633 snprintf(buf, sizeof(buf), "CONNECT %s:%s HTTP/%s", host, port, p->options.http_version);
634
635 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
636
637 /* send HTTP CONNECT message to proxy */
638 if (!send_line_crlf(sd, buf))
639 {
640 goto error;
641 }
642
643 if (!add_proxy_headers(p, sd, host))
644 {
645 goto error;
646 }
647
648 /* auth specified? */
649 switch (p->auth_method)
650 {
651 case HTTP_AUTH_NONE:
652 break;
653
654 case HTTP_AUTH_BASIC:
655 snprintf(buf, sizeof(buf), "Proxy-Authorization: Basic %s",
657 msg(D_PROXY, "Attempting Basic Proxy-Authorization");
658 dmsg(D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
659 if (!send_line_crlf(sd, buf))
660 {
661 goto error;
662 }
663 break;
664
665 default:
666 ASSERT(0);
667 }
668
669 /* clear any sensitive content in buf */
670 secure_memzero(buf, sizeof(buf));
671
672 /* send empty CR, LF */
673 if (!send_crlf(sd))
674 {
675 goto error;
676 }
677
678 /* receive reply from proxy */
679 if (!recv_line(sd, buf, sizeof(buf), get_server_poll_remaining_time(server_poll_timeout),
680 true, NULL, signal_received))
681 {
682 goto error;
683 }
684
685 /* remove trailing CR, LF */
686 chomp(buf);
687
688 msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
689
690 /* parse return string */
691 nparms = sscanf(buf, "%*s %d", &status);
692 }
693
694 /* check for a "407 Proxy Authentication Required" response */
695 while (nparms >= 1 && status == 407)
696 {
697 msg(D_PROXY, "Proxy requires authentication");
698
699 if (p->auth_method == HTTP_AUTH_BASIC && !processed)
700 {
701 processed = true;
702 }
703#if PROXY_DIGEST_AUTH
704 else if (p->auth_method == HTTP_AUTH_DIGEST && !processed)
705 {
706 char *pa = p->proxy_authenticate;
707 const int method = p->auth_method;
708 ASSERT(pa);
709
710 if (method == HTTP_AUTH_DIGEST)
711 {
712 const char *http_method = "CONNECT";
713 const char *nonce_count = "00000001";
714 const char *qop = "auth";
715 const char *username = p->up.username;
716 const char *password = p->up.password;
717 char *opaque_kv = "";
718 char uri[128];
719 uint8_t cnonce_raw[8];
720 uint8_t *cnonce;
721 HASHHEX session_key;
722 HASHHEX response;
723
724 const char *realm = get_pa_var("realm", pa, &gc);
725 const char *nonce = get_pa_var("nonce", pa, &gc);
726 const char *algor = get_pa_var("algorithm", pa, &gc);
727 const char *opaque = get_pa_var("opaque", pa, &gc);
728
729 if (!realm || !nonce)
730 {
731 msg(D_LINK_ERRORS, "HTTP proxy: digest auth failed, malformed response "
732 "from server: realm= or nonce= missing");
733 goto error;
734 }
735
736 /* generate a client nonce */
737 ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw)));
738 cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc);
739
740
741 /* build the digest response */
742 snprintf(uri, sizeof(uri), "%s:%s", host, port);
743
744 if (opaque)
745 {
746 const size_t len = strlen(opaque) + 16;
747 opaque_kv = gc_malloc(len, false, &gc);
748 snprintf(opaque_kv, len, ", opaque=\"%s\"", opaque);
749 }
750
751 DigestCalcHA1(algor, username, realm, password, nonce, (char *)cnonce, session_key);
752 DigestCalcResponse(session_key, nonce, nonce_count, (char *)cnonce, qop,
753 http_method, uri, NULL, response);
754
755 /* format HTTP CONNECT message */
756 snprintf(buf, sizeof(buf), "%s %s HTTP/%s", http_method, uri,
758
759 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
760
761 /* send HTTP CONNECT message to proxy */
762 if (!send_line_crlf(sd, buf))
763 {
764 goto error;
765 }
766
767 /* send HOST etc, */
768 if (!add_proxy_headers(p, sd, host))
769 {
770 goto error;
771 }
772
773 /* send digest response */
774 if (!checked_snprintf(
775 buf, sizeof(buf),
776 "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
777 username, realm, nonce, uri, qop, nonce_count, cnonce, response, opaque_kv))
778 {
779 goto error;
780 }
781
782 msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
783 if (!send_line_crlf(sd, buf))
784 {
785 goto error;
786 }
787 if (!send_crlf(sd))
788 {
789 goto error;
790 }
791 /* clear any sensitive content in buf */
792 secure_memzero(buf, sizeof(buf));
793
794 /* receive reply from proxy */
795 if (!recv_line(sd, buf, sizeof(buf),
796 get_server_poll_remaining_time(server_poll_timeout), true, NULL,
797 signal_received))
798 {
799 goto error;
800 }
801
802 /* remove trailing CR, LF */
803 chomp(buf);
804
805 msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
806
807 /* parse return string */
808 nparms = sscanf(buf, "%*s %d", &status);
809 processed = true;
810 }
811 else
812 {
813 msg(D_PROXY, "HTTP proxy: digest method not supported");
814 goto error;
815 }
816 }
817#endif /* if PROXY_DIGEST_AUTH */
818 else if (p->options.auth_retry)
819 {
820 /* figure out what kind of authentication the proxy needs */
821 char *pa = NULL;
822 const int method = get_proxy_authenticate(
823 sd, get_server_poll_remaining_time(server_poll_timeout), &pa, signal_received);
824 if (method != HTTP_AUTH_NONE)
825 {
826 if (pa)
827 {
828 msg(D_PROXY, "HTTP proxy authenticate '%s'", pa);
829 }
830 if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC)
831 {
832 msg(D_PROXY,
833 "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
834 free(pa);
835 goto error;
836 }
837 p->auth_method = method;
839 ret = true;
840 goto done;
841 }
842 else
843 {
844 msg(D_PROXY,
845 "HTTP proxy: do not recognize the authentication method required by proxy");
846 free(pa);
847 goto error;
848 }
849 }
850 else
851 {
852 if (!processed)
853 {
854 msg(D_PROXY, "HTTP proxy: no support for proxy authentication method");
855 }
856 goto error;
857 }
858 }
859
860 /* check return code, success = 200 */
861 if (nparms < 1 || status != 200)
862 {
863 msg(D_LINK_ERRORS, "HTTP proxy returned bad status");
864#if 0
865 /* DEBUGGING -- show a multi-line HTTP error response */
866 dump_residual(sd, get_server_poll_remaining_time(server_poll_timeout), signal_received);
867#endif
868 goto error;
869 }
870
871 /* SUCCESS */
872
873 /* receive line from proxy and discard */
874 if (!recv_line(sd, NULL, 0, get_server_poll_remaining_time(server_poll_timeout), true, NULL,
875 signal_received))
876 {
877 goto error;
878 }
879
880 /*
881 * Toss out any extraneous chars, but don't throw away the
882 * start of the OpenVPN data stream (put it in lookahead).
883 */
884 while (recv_line(sd, NULL, 0, 2, false, lookahead, signal_received))
885 {
886 }
887
888 /* reset queried_creds so that we don't think that the next creds request is due to an auth
889 * error */
890 p->queried_creds = false;
891
892#if 0
893 if (lookahead && BLEN(lookahead))
894 {
895 msg(M_INFO, "HTTP PROXY: lookahead: %s", format_hex(BPTR(lookahead), BLEN(lookahead), 0));
896 }
897#endif
898
899done:
900 purge_user_pass(&p->up, true);
901 gc_free(&gc);
902 return ret;
903
904error:
905 purge_user_pass(&p->up, true);
906 register_signal(sig_info, SIGUSR1, "HTTP proxy error"); /* SOFT-SIGUSR1 -- HTTP proxy error */
907 gc_free(&gc);
908 return ret;
909}
void free_buf(struct buffer *buf)
Definition buffer.c:184
bool buf_printf(struct buffer *buf, const char *format,...)
Definition buffer.c:241
void chomp(char *str)
Definition buffer.c:618
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:341
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
struct buffer alloc_buf(size_t size)
Definition buffer.c:63
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1143
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:653
#define BSTR(buf)
Definition buffer.h:129
#define BPTR(buf)
Definition buffer.h:123
static int buf_len(const struct buffer *buf)
Definition buffer.h:254
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition buffer.h:415
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition buffer.h:661
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition buffer.h:685
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1125
#define BLEN(buf)
Definition buffer.h:126
static char * format_hex(const uint8_t *data, size_t size, size_t maxoutput, struct gc_arena *gc)
Definition buffer.h:504
static void gc_free(struct gc_arena *a)
Definition buffer.h:1049
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1088
static bool buf_defined(const struct buffer *buf)
Definition buffer.h:229
#define buf_init(buf, offset)
Definition buffer.h:210
static struct gc_arena gc_new(void)
Definition buffer.h:1041
Data Channel Cryptography Module.
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
#define D_PROXY
Definition errlevel.h:73
#define D_SHOW_KEYS
Definition errlevel.h:120
#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:504
Interface functions to the internal and external multiplexers.
void DigestCalcHA1(IN char *pszAlg, IN char *pszUserName, IN char *pszRealm, IN char *pszPassword, IN char *pszNonce, IN char *pszCNonce, OUT HASHHEX SessionKey)
Definition httpdigest.c:66
void DigestCalcResponse(IN HASHHEX HA1, IN char *pszNonce, IN char *pszNonceCount, IN char *pszCNonce, IN char *pszQop, IN char *pszMethod, IN char *pszDigestUri, IN HASHHEX HEntity, OUT HASHHEX Response)
Definition httpdigest.c:96
static SERVICE_STATUS status
Definition interactive.c:51
void unprotect_user_pass(struct user_pass *up)
Decrypt username and password buffers in user_pass.
Definition misc.c:808
void purge_user_pass(struct user_pass *up, const bool force)
Definition misc.c:470
void protect_user_pass(struct user_pass *up)
Encrypt username and password buffers in user_pass.
Definition misc.c:788
#define GET_USER_PASS_MANAGEMENT
Definition misc.h:110
#define GET_USER_PASS_INLINE_CREDS
indicates that auth_file is actually inline creds
Definition misc.h:123
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 GET_USER_PASS_PREVIOUS_CREDS_FAILED
Definition misc.h:116
#define CLEAR(x)
Definition basic.h:32
#define M_FATAL
Definition error.h:90
#define dmsg(flags,...)
Definition error.h:172
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
#define M_ERRNO
Definition error.h:95
bool proxy_send(socket_descriptor_t sd, const void *buf, size_t buf_len)
Definition proxy.c:187
static bool send_crlf(socket_descriptor_t sd)
Definition proxy.c:212
static struct user_pass static_proxy_user_pass
Definition proxy.c:57
bool proxy_recv_char(uint8_t *c, const char *name, socket_descriptor_t sd, struct timeval *timeout, volatile int *signal_received)
Definition proxy.c:60
static bool recv_line(socket_descriptor_t sd, char *buf, int len, const int timeout_sec, const bool verbose, struct buffer *lookahead, volatile int *signal_received)
Definition proxy.c:104
void http_proxy_close(struct http_proxy_info *hp)
Definition proxy.c:524
static void clear_user_pass_http(void)
Definition proxy.c:246
static char * get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
Definition proxy.c:445
static const char * username_password_as_base64(const struct http_proxy_info *p, struct gc_arena *gc)
Definition proxy.c:235
struct http_proxy_info * http_proxy_new(const struct http_proxy_options *o)
Definition proxy.c:479
struct http_proxy_options * init_http_proxy_options_once(struct http_proxy_options **hpo, struct gc_arena *gc)
Definition proxy.c:44
static void store_proxy_authenticate(struct http_proxy_info *p, char *data)
Definition proxy.c:355
static bool get_key_value(const char *str, char *key, char *value, int max_key_len, int max_value_len, const char **endptr)
Definition proxy.c:366
bool establish_http_proxy_passthru(struct http_proxy_info *p, socket_descriptor_t sd, const char *host, const char *port, struct event_timeout *server_poll_timeout, struct buffer *lookahead, struct signal_info *sig_info)
Definition proxy.c:596
static bool send_line_crlf(socket_descriptor_t sd, const char *src)
Definition proxy.c:199
static void get_user_pass_http(struct http_proxy_info *p, const bool force)
Definition proxy.c:252
uint8_t * make_base64_string2(const uint8_t *str, int src_len, struct gc_arena *gc)
Definition proxy.c:218
uint8_t * make_base64_string(const uint8_t *str, struct gc_arena *gc)
Definition proxy.c:229
static bool add_proxy_headers(struct http_proxy_info *p, socket_descriptor_t sd, const char *host)
Definition proxy.c:530
static int get_proxy_authenticate(socket_descriptor_t sd, int timeout, char **data, volatile int *signal_received)
Definition proxy.c:316
#define UP_TYPE_PROXY
Definition proxy.c:41
#define PAR_NCT
Definition proxy.h:51
#define MAX_CUSTOM_HTTP_HEADER
Definition proxy.h:43
#define HTTP_AUTH_BASIC
Definition proxy.h:31
#define HTTP_AUTH_NONE
Definition proxy.h:30
#define HTTP_AUTH_DIGEST
Definition proxy.h:32
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:261
static int openvpn_select(socket_descriptor_t nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
Definition socket.h:317
static ssize_t openvpn_send(socket_descriptor_t sockfd, const void *buf, size_t len, int flags)
Definition socket.h:325
int openvpn_base64_encode(const void *data, int size, char **str)
Definition base64.c:51
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
uint8_t * data
Pointer to the allocated memory.
Definition buffer.h:67
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
const char * name
Definition proxy.h:39
const char * content
Definition proxy.h:40
struct user_pass up
Definition proxy.h:71
bool defined
Definition proxy.h:68
int auth_method
Definition proxy.h:69
bool queried_creds
Definition proxy.h:73
char * proxy_authenticate
Definition proxy.h:72
struct http_proxy_options options
Definition proxy.h:70
const char * http_version
Definition proxy.h:57
const char * port
Definition proxy.h:47
const char * user_agent
Definition proxy.h:58
const char * auth_method_string
Definition proxy.h:54
struct http_custom_header custom_headers[MAX_CUSTOM_HTTP_HEADER]
Definition proxy.h:59
const char * server
Definition proxy.h:46
Container for unidirectional cipher and HMAC key material.
Definition crypto.h:152
volatile int signal_received
Definition sig.h:42
bool defined
Definition misc.h:53
char password[USER_PASS_LEN]
Definition misc.h:68
bool nocache
Definition misc.h:57
char username[USER_PASS_LEN]
Definition misc.h:67
SOCKET socket_descriptor_t
Definition syshead.h:445
#define SIGUSR1
Definition syshead.h:57
struct gc_arena gc
Definition test_ssl.c:131