OpenVPN: Update to version 2.3.2. Solves TLS security bug.
[tomato.git] / release / src / router / openvpn / src / openvpn / proxy.c
blob95d71531bc2ffbbfd096da669e8ff931b6d333eb
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-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
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #elif defined(_MSC_VER)
28 #include "config-msvc.h"
29 #endif
31 #include "syshead.h"
33 #include "common.h"
34 #include "misc.h"
35 #include "crypto.h"
36 #include "win32.h"
37 #include "socket.h"
38 #include "fdmisc.h"
39 #include "proxy.h"
40 #include "base64.h"
41 #include "httpdigest.h"
42 #include "ntlm.h"
43 #include "memdbg.h"
45 #ifdef ENABLE_HTTP_PROXY
47 #define UP_TYPE_PROXY "HTTP Proxy"
49 struct http_proxy_options *
50 init_http_proxy_options_once (struct http_proxy_options **hpo,
51 struct gc_arena *gc)
53 if (!*hpo)
55 ALLOC_OBJ_CLEAR_GC (*hpo, struct http_proxy_options, gc);
56 /* http proxy defaults */
57 (*hpo)->timeout = 5;
58 (*hpo)->http_version = "1.0";
60 return *hpo;
64 /* cached proxy username/password */
65 static struct user_pass static_proxy_user_pass;
67 static bool
68 recv_line (socket_descriptor_t sd,
69 char *buf,
70 int len,
71 const int timeout_sec,
72 const bool verbose,
73 struct buffer *lookahead,
74 volatile int *signal_received)
76 struct buffer la;
77 int lastc = 0;
79 CLEAR (la);
80 if (lookahead)
81 la = *lookahead;
83 while (true)
85 int status;
86 ssize_t size;
87 fd_set reads;
88 struct timeval tv;
89 uint8_t c;
91 if (buf_defined (&la))
93 ASSERT (buf_init (&la, 0));
96 FD_ZERO (&reads);
97 FD_SET (sd, &reads);
98 tv.tv_sec = timeout_sec;
99 tv.tv_usec = 0;
101 status = select (sd + 1, &reads, NULL, NULL, &tv);
103 get_signal (signal_received);
104 if (*signal_received)
105 goto error;
107 /* timeout? */
108 if (status == 0)
110 if (verbose)
111 msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read timeout expired");
112 goto error;
115 /* error */
116 if (status < 0)
118 if (verbose)
119 msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on select()");
120 goto error;
123 /* read single char */
124 size = recv (sd, &c, 1, MSG_NOSIGNAL);
126 /* error? */
127 if (size != 1)
129 if (verbose)
130 msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on recv()");
131 goto error;
134 #if 0
135 if (isprint(c))
136 msg (M_INFO, "PROXY: read '%c' (%d)", c, (int)c);
137 else
138 msg (M_INFO, "PROXY: read (%d)", (int)c);
139 #endif
141 /* store char in buffer */
142 if (len > 1)
144 *buf++ = c;
145 --len;
148 /* also store char in lookahead buffer */
149 if (buf_defined (&la))
151 buf_write_u8 (&la, c);
152 if (!isprint(c) && !isspace(c)) /* not ascii? */
154 if (verbose)
155 msg (D_LINK_ERRORS | M_ERRNO, "recv_line: Non-ASCII character (%d) read on recv()", (int)c);
156 *lookahead = la;
157 return false;
161 /* end of line? */
162 if (lastc == '\r' && c == '\n')
163 break;
165 lastc = c;
168 /* append trailing null */
169 if (len > 0)
170 *buf++ = '\0';
172 return true;
174 error:
175 return false;
178 static bool
179 send_line (socket_descriptor_t sd,
180 const char *buf)
182 const ssize_t size = send (sd, buf, strlen (buf), MSG_NOSIGNAL);
183 if (size != (ssize_t) strlen (buf))
185 msg (D_LINK_ERRORS | M_ERRNO, "send_line: TCP port write failed on send()");
186 return false;
188 return true;
191 static bool
192 send_line_crlf (socket_descriptor_t sd,
193 const char *src)
195 bool ret;
197 struct buffer buf = alloc_buf (strlen (src) + 3);
198 ASSERT (buf_write (&buf, src, strlen (src)));
199 ASSERT (buf_write (&buf, "\r\n", 3));
200 ret = send_line (sd, BSTR (&buf));
201 free_buf (&buf);
202 return ret;
205 static bool
206 send_crlf (socket_descriptor_t sd)
208 return send_line_crlf (sd, "");
211 uint8_t *
212 make_base64_string2 (const uint8_t *str, int src_len, struct gc_arena *gc)
214 uint8_t *ret = NULL;
215 char *b64out = NULL;
216 ASSERT (openvpn_base64_encode ((const void *)str, src_len, &b64out) >= 0);
217 ret = (uint8_t *) string_alloc (b64out, gc);
218 free (b64out);
219 return ret;
222 uint8_t *
223 make_base64_string (const uint8_t *str, struct gc_arena *gc)
225 return make_base64_string2 (str, strlen ((const char *)str), gc);
228 static const char *
229 username_password_as_base64 (const struct http_proxy_info *p,
230 struct gc_arena *gc)
232 struct buffer out = alloc_buf_gc (strlen (p->up.username) + strlen (p->up.password) + 2, gc);
233 ASSERT (strlen (p->up.username) > 0);
234 buf_printf (&out, "%s:%s", p->up.username, p->up.password);
235 return (const char *)make_base64_string ((const uint8_t*)BSTR (&out), gc);
238 static void
239 get_user_pass_http (struct http_proxy_info *p, const bool force)
241 if (!static_proxy_user_pass.defined || force)
243 unsigned int flags = GET_USER_PASS_MANAGEMENT;
244 if (p->queried_creds)
245 flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED;
246 get_user_pass (&static_proxy_user_pass,
247 p->options.auth_file,
248 UP_TYPE_PROXY,
249 flags);
250 p->queried_creds = true;
251 p->up = static_proxy_user_pass;
254 static void
255 clear_user_pass_http (void)
257 purge_user_pass (&static_proxy_user_pass, true);
260 static void
261 dump_residual (socket_descriptor_t sd,
262 int timeout,
263 volatile int *signal_received)
265 char buf[256];
266 while (true)
268 if (!recv_line (sd, buf, sizeof (buf), timeout, true, NULL, signal_received))
269 return;
270 chomp (buf);
271 msg (D_PROXY, "PROXY HEADER: '%s'", buf);
276 * Extract the Proxy-Authenticate header from the stream.
277 * Consumes all headers.
279 static int
280 get_proxy_authenticate (socket_descriptor_t sd,
281 int timeout,
282 char **data,
283 struct gc_arena *gc,
284 volatile int *signal_received)
286 char buf[256];
287 int ret = HTTP_AUTH_NONE;
288 while (true)
290 if (!recv_line (sd, buf, sizeof (buf), timeout, true, NULL, signal_received))
292 *data = NULL;
293 return HTTP_AUTH_NONE;
295 chomp (buf);
296 if (!strlen(buf))
297 return ret;
298 if (ret == HTTP_AUTH_NONE && !strncmp(buf, "Proxy-Authenticate: ", 20))
300 if (!strncmp(buf+20, "Basic ", 6))
302 msg (D_PROXY, "PROXY AUTH BASIC: '%s'", buf);
303 *data = string_alloc(buf+26, gc);
304 ret = HTTP_AUTH_BASIC;
306 #if PROXY_DIGEST_AUTH
307 else if (!strncmp(buf+20, "Digest ", 7))
309 msg (D_PROXY, "PROXY AUTH DIGEST: '%s'", buf);
310 *data = string_alloc(buf+27, gc);
311 ret = HTTP_AUTH_DIGEST;
313 #endif
314 #if NTLM
315 else if (!strncmp(buf+20, "NTLM", 4))
317 msg (D_PROXY, "PROXY AUTH HTLM: '%s'", buf);
318 *data = NULL;
319 ret = HTTP_AUTH_NTLM;
321 #endif
326 static void
327 store_proxy_authenticate (struct http_proxy_info *p, char *data)
329 if (p->proxy_authenticate)
330 free (p->proxy_authenticate);
331 p->proxy_authenticate = data;
335 * Parse out key/value pairs from Proxy-Authenticate string.
336 * Return true on success, or false on parse failure.
338 static bool
339 get_key_value(const char *str, /* source string */
340 char *key, /* key stored here */
341 char *value, /* value stored here */
342 int max_key_len,
343 int max_value_len,
344 const char **endptr) /* next search position */
346 int c;
347 bool starts_with_quote = false;
348 bool escape = false;
350 for (c = max_key_len-1; (*str && (*str != '=') && c--); )
351 *key++ = *str++;
352 *key = '\0';
354 if('=' != *str++)
355 /* no key/value found */
356 return false;
358 if('\"' == *str)
360 /* quoted string */
361 str++;
362 starts_with_quote = true;
365 for (c = max_value_len-1; *str && c--; str++)
367 switch (*str)
369 case '\\':
370 if (!escape)
372 /* possibly the start of an escaped quote */
373 escape = true;
374 *value++ = '\\'; /* even though this is an escape character, we still
375 store it as-is in the target buffer */
376 continue;
378 break;
379 case ',':
380 if (!starts_with_quote)
382 /* this signals the end of the value if we didn't get a starting quote
383 and then we do "sloppy" parsing */
384 c=0; /* the end */
385 continue;
387 break;
388 case '\r':
389 case '\n':
390 /* end of string */
391 c=0;
392 continue;
393 case '\"':
394 if (!escape && starts_with_quote)
396 /* end of string */
397 c=0;
398 continue;
400 break;
402 escape = false;
403 *value++ = *str;
405 *value = '\0';
407 *endptr = str;
409 return true; /* success */
412 static char *
413 get_pa_var (const char *key, const char *pa, struct gc_arena *gc)
415 char k[64];
416 char v[256];
417 const char *content = pa;
419 while (true)
421 const int status = get_key_value(content, k, v, sizeof(k), sizeof(v), &content);
422 if (status)
424 if (!strcmp(key, k))
425 return string_alloc(v, gc);
427 else
428 return NULL;
430 /* advance to start of next key */
431 if (*content == ',')
432 ++content;
433 while (*content && isspace(*content))
434 ++content;
438 struct http_proxy_info *
439 http_proxy_new (const struct http_proxy_options *o)
441 struct http_proxy_info *p;
442 struct http_proxy_options opt;
444 if (!o || !o->server)
445 msg (M_FATAL, "HTTP_PROXY: server not specified");
447 ASSERT (legal_ipv4_port (o->port));
449 ALLOC_OBJ_CLEAR (p, struct http_proxy_info);
450 p->options = *o;
452 /* parse authentication method */
453 p->auth_method = HTTP_AUTH_NONE;
454 if (o->auth_method_string)
456 if (!strcmp (o->auth_method_string, "none"))
457 p->auth_method = HTTP_AUTH_NONE;
458 else if (!strcmp (o->auth_method_string, "basic"))
459 p->auth_method = HTTP_AUTH_BASIC;
460 #if NTLM
461 else if (!strcmp (o->auth_method_string, "ntlm"))
462 p->auth_method = HTTP_AUTH_NTLM;
463 else if (!strcmp (o->auth_method_string, "ntlm2"))
464 p->auth_method = HTTP_AUTH_NTLM2;
465 #endif
466 else
467 msg (M_FATAL, "ERROR: unknown HTTP authentication method: '%s'",
468 o->auth_method_string);
471 /* only basic and NTLM/NTLMv2 authentication supported so far */
472 if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
474 get_user_pass_http (p, true);
477 #if !NTLM
478 if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
479 msg (M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");
480 #endif
482 p->defined = true;
483 return p;
486 void
487 http_proxy_close (struct http_proxy_info *hp)
489 free (hp);
492 bool
493 establish_http_proxy_passthru (struct http_proxy_info *p,
494 socket_descriptor_t sd, /* already open to proxy */
495 const char *host, /* openvpn server remote */
496 const int port, /* openvpn server port */
497 struct buffer *lookahead,
498 volatile int *signal_received)
500 struct gc_arena gc = gc_new ();
501 char buf[512];
502 char buf2[129];
503 char get[80];
504 int status;
505 int nparms;
506 bool ret = false;
507 bool processed = false;
509 /* get user/pass if not previously given */
510 if (p->auth_method == HTTP_AUTH_BASIC
511 || p->auth_method == HTTP_AUTH_DIGEST
512 || p->auth_method == HTTP_AUTH_NTLM)
513 get_user_pass_http (p, false);
515 /* are we being called again after getting the digest server nonce in the previous transaction? */
516 if (p->auth_method == HTTP_AUTH_DIGEST && p->proxy_authenticate)
518 nparms = 1;
519 status = 407;
521 else
523 /* format HTTP CONNECT message */
524 openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
525 host,
526 port,
527 p->options.http_version);
529 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
531 /* send HTTP CONNECT message to proxy */
532 if (!send_line_crlf (sd, buf))
533 goto error;
535 openvpn_snprintf(buf, sizeof(buf), "Host: %s", host);
536 if (!send_line_crlf(sd, buf))
537 goto error;
539 /* send User-Agent string if provided */
540 if (p->options.user_agent)
542 openvpn_snprintf (buf, sizeof(buf), "User-Agent: %s",
543 p->options.user_agent);
544 if (!send_line_crlf (sd, buf))
545 goto error;
548 /* auth specified? */
549 switch (p->auth_method)
551 case HTTP_AUTH_NONE:
552 break;
554 case HTTP_AUTH_BASIC:
555 openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Basic %s",
556 username_password_as_base64 (p, &gc));
557 msg (D_PROXY, "Attempting Basic Proxy-Authorization");
558 dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
559 if (!send_line_crlf (sd, buf))
560 goto error;
561 break;
563 #if NTLM
564 case HTTP_AUTH_NTLM:
565 case HTTP_AUTH_NTLM2:
566 /* keep-alive connection */
567 openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
568 if (!send_line_crlf (sd, buf))
569 goto error;
571 openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s",
572 ntlm_phase_1 (p, &gc));
573 msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1");
574 dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
575 if (!send_line_crlf (sd, buf))
576 goto error;
577 break;
578 #endif
580 default:
581 ASSERT (0);
584 /* send empty CR, LF */
585 if (!send_crlf (sd))
586 goto error;
588 /* receive reply from proxy */
589 if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
590 goto error;
592 /* remove trailing CR, LF */
593 chomp (buf);
595 msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
597 /* parse return string */
598 nparms = sscanf (buf, "%*s %d", &status);
602 /* check for a "407 Proxy Authentication Required" response */
603 while (nparms >= 1 && status == 407)
605 msg (D_PROXY, "Proxy requires authentication");
607 if (p->auth_method == HTTP_AUTH_BASIC && !processed)
609 processed = true;
611 else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */
613 #if NTLM
614 /* look for the phase 2 response */
616 while (true)
618 if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
619 goto error;
620 chomp (buf);
621 msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
623 openvpn_snprintf (get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof (buf2) - 1);
624 nparms = sscanf (buf, get, buf2);
625 buf2[128] = 0; /* we only need the beginning - ensure it's null terminated. */
627 /* check for "Proxy-Authenticate: NTLM TlRM..." */
628 if (nparms == 1)
630 /* parse buf2 */
631 msg (D_PROXY, "auth string: '%s'", buf2);
632 break;
635 /* if we are here then auth string was got */
636 msg (D_PROXY, "Received NTLM Proxy-Authorization phase 2 response");
638 /* receive and discard everything else */
639 while (recv_line (sd, NULL, 0, 2, true, NULL, signal_received))
642 /* now send the phase 3 reply */
644 /* format HTTP CONNECT message */
645 openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
646 host,
647 port,
648 p->options.http_version);
650 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
652 /* send HTTP CONNECT message to proxy */
653 if (!send_line_crlf (sd, buf))
654 goto error;
656 /* keep-alive connection */
657 openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
658 if (!send_line_crlf (sd, buf))
659 goto error;
662 /* send HOST etc, */
663 openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
664 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
665 if (!send_line_crlf (sd, buf))
666 goto error;
668 msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3");
670 const char *np3 = ntlm_phase_3 (p, buf2, &gc);
671 if (!np3)
673 msg (D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
674 goto error;
676 openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3);
679 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
680 if (!send_line_crlf (sd, buf))
681 goto error;
682 /* ok so far... */
683 /* send empty CR, LF */
684 if (!send_crlf (sd))
685 goto error;
687 /* receive reply from proxy */
688 if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
689 goto error;
691 /* remove trailing CR, LF */
692 chomp (buf);
694 msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
696 /* parse return string */
697 nparms = sscanf (buf, "%*s %d", &status);
698 processed = true;
699 #endif
701 #if PROXY_DIGEST_AUTH
702 else if (p->auth_method == HTTP_AUTH_DIGEST && !processed)
704 char *pa = p->proxy_authenticate;
705 const int method = p->auth_method;
706 ASSERT(pa);
708 if (method == HTTP_AUTH_DIGEST)
710 const char *http_method = "CONNECT";
711 const char *nonce_count = "00000001";
712 const char *qop = "auth";
713 const char *username = p->up.username;
714 const char *password = p->up.password;
715 char *opaque_kv = "";
716 char uri[128];
717 uint8_t cnonce_raw[8];
718 uint8_t *cnonce;
719 HASHHEX session_key;
720 HASHHEX response;
722 const char *realm = get_pa_var("realm", pa, &gc);
723 const char *nonce = get_pa_var("nonce", pa, &gc);
724 const char *algor = get_pa_var("algorithm", pa, &gc);
725 const char *opaque = get_pa_var("opaque", pa, &gc);
727 /* generate a client nonce */
728 ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw)));
729 cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc);
732 /* build the digest response */
733 openvpn_snprintf (uri, sizeof(uri), "%s:%d",
734 host,
735 port);
737 if (opaque)
739 const int len = strlen(opaque)+16;
740 opaque_kv = gc_malloc(len, false, &gc);
741 openvpn_snprintf (opaque_kv, len, ", opaque=\"%s\"", opaque);
744 DigestCalcHA1(algor,
745 username,
746 realm,
747 password,
748 nonce,
749 (char *)cnonce,
750 session_key);
751 DigestCalcResponse(session_key,
752 nonce,
753 nonce_count,
754 (char *)cnonce,
755 qop,
756 http_method,
757 uri,
758 NULL,
759 response);
761 /* format HTTP CONNECT message */
762 openvpn_snprintf (buf, sizeof(buf), "%s %s HTTP/%s",
763 http_method,
764 uri,
765 p->options.http_version);
767 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
769 /* send HTTP CONNECT message to proxy */
770 if (!send_line_crlf (sd, buf))
771 goto error;
773 /* send HOST etc, */
774 openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
775 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
776 if (!send_line_crlf (sd, buf))
777 goto error;
779 /* send digest response */
780 openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", qop=%s, nc=%s, cnonce=\"%s\", response=\"%s\"%s",
781 username,
782 realm,
783 nonce,
784 uri,
785 qop,
786 nonce_count,
787 cnonce,
788 response,
789 opaque_kv
791 msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
792 if (!send_line_crlf (sd, buf))
793 goto error;
794 if (!send_crlf (sd))
795 goto error;
797 /* receive reply from proxy */
798 if (!recv_line (sd, buf, sizeof(buf), p->options.timeout, true, NULL, signal_received))
799 goto error;
801 /* remove trailing CR, LF */
802 chomp (buf);
804 msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
806 /* parse return string */
807 nparms = sscanf (buf, "%*s %d", &status);
808 processed = true;
810 else
812 msg (D_PROXY, "HTTP proxy: digest method not supported");
813 goto error;
816 #endif
817 else if (p->options.auth_retry)
819 /* figure out what kind of authentication the proxy needs */
820 char *pa = NULL;
821 const int method = get_proxy_authenticate(sd,
822 p->options.timeout,
823 &pa,
824 NULL,
825 signal_received);
826 if (method != HTTP_AUTH_NONE)
828 if (pa)
829 msg (D_PROXY, "HTTP proxy authenticate '%s'", pa);
830 if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC)
832 msg (D_PROXY, "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
833 goto error;
835 p->auth_method = method;
836 store_proxy_authenticate(p, pa);
837 ret = true;
838 goto done;
840 else
842 msg (D_PROXY, "HTTP proxy: do not recognize the authentication method required by proxy");
843 free (pa);
844 goto error;
847 else
849 if (!processed)
850 msg (D_PROXY, "HTTP proxy: no support for proxy authentication method");
851 goto error;
854 /* clear state */
855 if (p->options.auth_retry)
856 clear_user_pass_http();
857 store_proxy_authenticate(p, NULL);
860 /* check return code, success = 200 */
861 if (nparms < 1 || status != 200)
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, p->options.timeout, signal_received);
867 #endif
868 goto error;
871 /* SUCCESS */
873 /* receive line from proxy and discard */
874 if (!recv_line (sd, NULL, 0, p->options.timeout, true, NULL, signal_received))
875 goto error;
878 * Toss out any extraneous chars, but don't throw away the
879 * start of the OpenVPN data stream (put it in lookahead).
881 while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received))
884 /* reset queried_creds so that we don't think that the next creds request is due to an auth error */
885 p->queried_creds = false;
887 #if 0
888 if (lookahead && BLEN (lookahead))
889 msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0));
890 #endif
892 done:
893 gc_free (&gc);
894 return ret;
896 error:
897 /* on error, should we exit or restart? */
898 if (!*signal_received)
899 *signal_received = (p->options.retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- HTTP proxy error */
900 gc_free (&gc);
901 return ret;
904 #else
905 static void dummy(void) {}
906 #endif /* ENABLE_HTTP_PROXY */