summaryrefslogtreecommitdiff
path: root/src/openvpn/proxy.c
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2016-12-27 18:25:47 +0100
committerAlberto Gonzalez Iniesta <agi@inittab.org>2016-12-27 18:25:47 +0100
commit79f3537f69e125f19f59c36aa090120a63186a54 (patch)
tree2089a3b7dac990841dbc2e4d9b2f535b82dbb0af /src/openvpn/proxy.c
parentf2137fedb30cb87448eb03b2f288920df6187571 (diff)
parent3a2bbdb05ca6a6996e424c9fb225cb0d53804125 (diff)
Merge tag 'upstream/2.4.0'
Upstream version 2.4.0
Diffstat (limited to 'src/openvpn/proxy.c')
-rw-r--r--src/openvpn/proxy.c1513
1 files changed, 815 insertions, 698 deletions
diff --git a/src/openvpn/proxy.c b/src/openvpn/proxy.c
index 0f78020..dd327a2 100644
--- a/src/openvpn/proxy.c
+++ b/src/openvpn/proxy.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -46,16 +46,16 @@
#define UP_TYPE_PROXY "HTTP Proxy"
struct http_proxy_options *
-init_http_proxy_options_once (struct http_proxy_options **hpo,
- struct gc_arena *gc)
+init_http_proxy_options_once(struct http_proxy_options **hpo,
+ struct gc_arena *gc)
{
- if (!*hpo)
+ if (!*hpo)
{
- ALLOC_OBJ_CLEAR_GC (*hpo, struct http_proxy_options, gc);
- /* http proxy defaults */
- (*hpo)->http_version = "1.0";
+ ALLOC_OBJ_CLEAR_GC(*hpo, struct http_proxy_options, gc);
+ /* http proxy defaults */
+ (*hpo)->http_version = "1.0";
}
- return *hpo;
+ return *hpo;
}
@@ -63,214 +63,240 @@ init_http_proxy_options_once (struct http_proxy_options **hpo,
static struct user_pass static_proxy_user_pass;
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)
+recv_line(socket_descriptor_t sd,
+ char *buf,
+ int len,
+ const int timeout_sec,
+ const bool verbose,
+ struct buffer *lookahead,
+ volatile int *signal_received)
{
- struct buffer la;
- int lastc = 0;
+ struct buffer la;
+ int lastc = 0;
- CLEAR (la);
- if (lookahead)
- la = *lookahead;
+ CLEAR(la);
+ if (lookahead)
+ {
+ la = *lookahead;
+ }
- while (true)
+ while (true)
{
- int status;
- ssize_t size;
- fd_set reads;
- struct timeval tv;
- uint8_t c;
-
- if (buf_defined (&la))
- {
- ASSERT (buf_init (&la, 0));
- }
-
- FD_ZERO (&reads);
- openvpn_fd_set (sd, &reads);
- tv.tv_sec = timeout_sec;
- tv.tv_usec = 0;
-
- status = select (sd + 1, &reads, NULL, NULL, &tv);
-
- get_signal (signal_received);
- if (*signal_received)
- goto error;
-
- /* timeout? */
- if (status == 0)
- {
- if (verbose)
- msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read timeout expired");
- goto error;
- }
-
- /* error */
- if (status < 0)
- {
- if (verbose)
- msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on select()");
- goto error;
- }
-
- /* read single char */
- size = recv (sd, &c, 1, MSG_NOSIGNAL);
-
- /* error? */
- if (size != 1)
- {
- if (verbose)
- msg (D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on recv()");
- goto error;
- }
+ int status;
+ ssize_t size;
+ fd_set reads;
+ struct timeval tv;
+ uint8_t c;
+
+ if (buf_defined(&la))
+ {
+ ASSERT(buf_init(&la, 0));
+ }
+
+ FD_ZERO(&reads);
+ openvpn_fd_set(sd, &reads);
+ tv.tv_sec = timeout_sec;
+ tv.tv_usec = 0;
+
+ status = select(sd + 1, &reads, NULL, NULL, &tv);
+
+ get_signal(signal_received);
+ if (*signal_received)
+ {
+ goto error;
+ }
+
+ /* timeout? */
+ if (status == 0)
+ {
+ if (verbose)
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read timeout expired");
+ }
+ goto error;
+ }
+
+ /* error */
+ if (status < 0)
+ {
+ if (verbose)
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on select()");
+ }
+ goto error;
+ }
+
+ /* read single char */
+ size = recv(sd, &c, 1, MSG_NOSIGNAL);
+
+ /* error? */
+ if (size != 1)
+ {
+ if (verbose)
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "recv_line: TCP port read failed on recv()");
+ }
+ goto error;
+ }
#if 0
- if (isprint(c))
- msg (M_INFO, "PROXY: read '%c' (%d)", c, (int)c);
- else
- msg (M_INFO, "PROXY: read (%d)", (int)c);
+ if (isprint(c))
+ {
+ msg(M_INFO, "PROXY: read '%c' (%d)", c, (int)c);
+ }
+ else
+ {
+ msg(M_INFO, "PROXY: read (%d)", (int)c);
+ }
#endif
- /* store char in buffer */
- if (len > 1)
- {
- *buf++ = c;
- --len;
- }
-
- /* also store char in lookahead buffer */
- if (buf_defined (&la))
- {
- buf_write_u8 (&la, c);
- if (!isprint(c) && !isspace(c)) /* not ascii? */
- {
- if (verbose)
- msg (D_LINK_ERRORS | M_ERRNO, "recv_line: Non-ASCII character (%d) read on recv()", (int)c);
- *lookahead = la;
- return false;
- }
- }
-
- /* end of line? */
- if (lastc == '\r' && c == '\n')
- break;
-
- lastc = c;
+ /* store char in buffer */
+ if (len > 1)
+ {
+ *buf++ = c;
+ --len;
+ }
+
+ /* also store char in lookahead buffer */
+ if (buf_defined(&la))
+ {
+ buf_write_u8(&la, c);
+ if (!isprint(c) && !isspace(c)) /* not ascii? */
+ {
+ if (verbose)
+ {
+ msg(D_LINK_ERRORS | M_ERRNO, "recv_line: Non-ASCII character (%d) read on recv()", (int)c);
+ }
+ *lookahead = la;
+ return false;
+ }
+ }
+
+ /* end of line? */
+ if (lastc == '\r' && c == '\n')
+ {
+ break;
+ }
+
+ lastc = c;
}
- /* append trailing null */
- if (len > 0)
- *buf++ = '\0';
+ /* append trailing null */
+ if (len > 0)
+ {
+ *buf++ = '\0';
+ }
- return true;
+ return true;
- error:
- return false;
+error:
+ return false;
}
static bool
-send_line (socket_descriptor_t sd,
- const char *buf)
+send_line(socket_descriptor_t sd,
+ const char *buf)
{
- const ssize_t size = send (sd, buf, strlen (buf), MSG_NOSIGNAL);
- if (size != (ssize_t) strlen (buf))
+ const ssize_t size = send(sd, buf, strlen(buf), MSG_NOSIGNAL);
+ if (size != (ssize_t) strlen(buf))
{
- msg (D_LINK_ERRORS | M_ERRNO, "send_line: TCP port write failed on send()");
- return false;
+ msg(D_LINK_ERRORS | M_ERRNO, "send_line: TCP port write failed on send()");
+ return false;
}
- return true;
+ return true;
}
static bool
-send_line_crlf (socket_descriptor_t sd,
- const char *src)
+send_line_crlf(socket_descriptor_t sd,
+ const char *src)
{
- bool ret;
-
- struct buffer buf = alloc_buf (strlen (src) + 3);
- ASSERT (buf_write (&buf, src, strlen (src)));
- ASSERT (buf_write (&buf, "\r\n", 3));
- ret = send_line (sd, BSTR (&buf));
- free_buf (&buf);
- return ret;
+ bool ret;
+
+ struct buffer buf = alloc_buf(strlen(src) + 3);
+ ASSERT(buf_write(&buf, src, strlen(src)));
+ ASSERT(buf_write(&buf, "\r\n", 3));
+ ret = send_line(sd, BSTR(&buf));
+ free_buf(&buf);
+ return ret;
}
static bool
-send_crlf (socket_descriptor_t sd)
+send_crlf(socket_descriptor_t sd)
{
- return send_line_crlf (sd, "");
+ return send_line_crlf(sd, "");
}
uint8_t *
-make_base64_string2 (const uint8_t *str, int src_len, struct gc_arena *gc)
+make_base64_string2(const uint8_t *str, int src_len, struct gc_arena *gc)
{
- uint8_t *ret = NULL;
- char *b64out = NULL;
- ASSERT (openvpn_base64_encode ((const void *)str, src_len, &b64out) >= 0);
- ret = (uint8_t *) string_alloc (b64out, gc);
- free (b64out);
- return ret;
+ uint8_t *ret = NULL;
+ char *b64out = NULL;
+ ASSERT(openvpn_base64_encode((const void *)str, src_len, &b64out) >= 0);
+ ret = (uint8_t *) string_alloc(b64out, gc);
+ free(b64out);
+ return ret;
}
uint8_t *
-make_base64_string (const uint8_t *str, struct gc_arena *gc)
+make_base64_string(const uint8_t *str, struct gc_arena *gc)
{
- return make_base64_string2 (str, strlen ((const char *)str), gc);
+ return make_base64_string2(str, strlen((const char *)str), gc);
}
static const char *
-username_password_as_base64 (const struct http_proxy_info *p,
- struct gc_arena *gc)
+username_password_as_base64(const struct http_proxy_info *p,
+ struct gc_arena *gc)
{
- struct buffer out = alloc_buf_gc (strlen (p->up.username) + strlen (p->up.password) + 2, gc);
- ASSERT (strlen (p->up.username) > 0);
- buf_printf (&out, "%s:%s", p->up.username, p->up.password);
- return (const char *)make_base64_string ((const uint8_t*)BSTR (&out), gc);
+ struct buffer out = alloc_buf_gc(strlen(p->up.username) + strlen(p->up.password) + 2, gc);
+ ASSERT(strlen(p->up.username) > 0);
+ buf_printf(&out, "%s:%s", p->up.username, p->up.password);
+ return (const char *)make_base64_string((const uint8_t *)BSTR(&out), gc);
}
static void
-get_user_pass_http (struct http_proxy_info *p, const bool force)
+get_user_pass_http(struct http_proxy_info *p, const bool force)
{
- if (!static_proxy_user_pass.defined || force)
+ if (!static_proxy_user_pass.defined || force)
{
- unsigned int flags = GET_USER_PASS_MANAGEMENT;
- if (p->queried_creds)
- flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED;
- if (p->options.inline_creds)
- flags |= GET_USER_PASS_INLINE_CREDS;
- get_user_pass (&static_proxy_user_pass,
- p->options.auth_file,
- UP_TYPE_PROXY,
- flags);
- p->queried_creds = true;
- p->up = static_proxy_user_pass;
+ unsigned int flags = GET_USER_PASS_MANAGEMENT;
+ if (p->queried_creds)
+ {
+ flags |= GET_USER_PASS_PREVIOUS_CREDS_FAILED;
+ }
+ if (p->options.inline_creds)
+ {
+ flags |= GET_USER_PASS_INLINE_CREDS;
+ }
+ get_user_pass(&static_proxy_user_pass,
+ p->options.auth_file,
+ UP_TYPE_PROXY,
+ flags);
+ p->queried_creds = true;
+ p->up = static_proxy_user_pass;
}
}
static void
-clear_user_pass_http (void)
+clear_user_pass_http(void)
{
- purge_user_pass (&static_proxy_user_pass, true);
+ purge_user_pass(&static_proxy_user_pass, true);
}
#if 0
/* function only used in #if 0 debug statement */
static void
-dump_residual (socket_descriptor_t sd,
- int timeout,
- volatile int *signal_received)
+dump_residual(socket_descriptor_t sd,
+ int timeout,
+ volatile int *signal_received)
{
- char buf[256];
- while (true)
+ char buf[256];
+ while (true)
{
- if (!recv_line (sd, buf, sizeof (buf), timeout, true, NULL, signal_received))
- return;
- chomp (buf);
- msg (D_PROXY, "PROXY HEADER: '%s'", buf);
+ if (!recv_line(sd, buf, sizeof(buf), timeout, true, NULL, signal_received))
+ {
+ return;
+ }
+ chomp(buf);
+ msg(D_PROXY, "PROXY HEADER: '%s'", buf);
}
}
#endif
@@ -280,58 +306,62 @@ dump_residual (socket_descriptor_t sd,
* Consumes all headers.
*/
static int
-get_proxy_authenticate (socket_descriptor_t sd,
- int timeout,
- char **data,
- struct gc_arena *gc,
- volatile int *signal_received)
+get_proxy_authenticate(socket_descriptor_t sd,
+ int timeout,
+ char **data,
+ struct gc_arena *gc,
+ volatile int *signal_received)
{
- char buf[256];
- int ret = HTTP_AUTH_NONE;
- while (true)
+ char buf[256];
+ int ret = HTTP_AUTH_NONE;
+ while (true)
{
- if (!recv_line (sd, buf, sizeof (buf), timeout, true, NULL, signal_received))
- {
- *data = NULL;
- return HTTP_AUTH_NONE;
- }
- chomp (buf);
- if (!strlen(buf))
- return ret;
- if (ret == HTTP_AUTH_NONE && !strncmp(buf, "Proxy-Authenticate: ", 20))
- {
- if (!strncmp(buf+20, "Basic ", 6))
- {
- msg (D_PROXY, "PROXY AUTH BASIC: '%s'", buf);
- *data = string_alloc(buf+26, gc);
- ret = HTTP_AUTH_BASIC;
- }
+ if (!recv_line(sd, buf, sizeof(buf), timeout, true, NULL, signal_received))
+ {
+ *data = NULL;
+ return HTTP_AUTH_NONE;
+ }
+ chomp(buf);
+ if (!strlen(buf))
+ {
+ return ret;
+ }
+ if (ret == HTTP_AUTH_NONE && !strncmp(buf, "Proxy-Authenticate: ", 20))
+ {
+ if (!strncmp(buf+20, "Basic ", 6))
+ {
+ msg(D_PROXY, "PROXY AUTH BASIC: '%s'", buf);
+ *data = string_alloc(buf+26, gc);
+ ret = HTTP_AUTH_BASIC;
+ }
#if PROXY_DIGEST_AUTH
- else if (!strncmp(buf+20, "Digest ", 7))
- {
- msg (D_PROXY, "PROXY AUTH DIGEST: '%s'", buf);
- *data = string_alloc(buf+27, gc);
- ret = HTTP_AUTH_DIGEST;
- }
+ else if (!strncmp(buf+20, "Digest ", 7))
+ {
+ msg(D_PROXY, "PROXY AUTH DIGEST: '%s'", buf);
+ *data = string_alloc(buf+27, gc);
+ ret = HTTP_AUTH_DIGEST;
+ }
#endif
#if NTLM
- else if (!strncmp(buf+20, "NTLM", 4))
- {
- msg (D_PROXY, "PROXY AUTH HTLM: '%s'", buf);
- *data = NULL;
- ret = HTTP_AUTH_NTLM;
- }
+ else if (!strncmp(buf+20, "NTLM", 4))
+ {
+ msg(D_PROXY, "PROXY AUTH HTLM: '%s'", buf);
+ *data = NULL;
+ ret = HTTP_AUTH_NTLM;
+ }
#endif
- }
+ }
}
}
static void
-store_proxy_authenticate (struct http_proxy_info *p, char *data)
+store_proxy_authenticate(struct http_proxy_info *p, char *data)
{
- if (p->proxy_authenticate)
- free (p->proxy_authenticate);
- p->proxy_authenticate = data;
+ if (p->proxy_authenticate)
+ {
+ free(p->proxy_authenticate);
+ }
+ p->proxy_authenticate = data;
}
/*
@@ -340,611 +370,698 @@ store_proxy_authenticate (struct http_proxy_info *p, char *data)
*/
static bool
get_key_value(const char *str, /* source string */
- char *key, /* key stored here */
- char *value, /* value stored here */
- int max_key_len,
- int max_value_len,
- const char **endptr) /* next search position */
+ char *key, /* key stored here */
+ char *value, /* value stored here */
+ int max_key_len,
+ int max_value_len,
+ const char **endptr) /* next search position */
{
- int c;
- bool starts_with_quote = false;
- bool escape = false;
+ int c;
+ bool starts_with_quote = false;
+ bool escape = false;
- for (c = max_key_len-1; (*str && (*str != '=') && c--); )
- *key++ = *str++;
- *key = '\0';
+ for (c = max_key_len-1; (*str && (*str != '=') && c--); )
+ *key++ = *str++;
+ *key = '\0';
- if('=' != *str++)
- /* no key/value found */
- return false;
+ if ('=' != *str++)
+ {
+ /* no key/value found */
+ return false;
+ }
- if('\"' == *str)
+ if ('\"' == *str)
{
- /* quoted string */
- str++;
- starts_with_quote = true;
+ /* quoted string */
+ str++;
+ starts_with_quote = true;
}
- for (c = max_value_len-1; *str && c--; str++)
+ for (c = max_value_len-1; *str && c--; str++)
{
- switch (*str)
- {
- case '\\':
- if (!escape)
- {
- /* possibly the start of an escaped quote */
- escape = true;
- *value++ = '\\'; /* even though this is an escape character, we still
- store it as-is in the target buffer */
- continue;
- }
- break;
- case ',':
- if (!starts_with_quote)
- {
- /* this signals the end of the value if we didn't get a starting quote
- and then we do "sloppy" parsing */
- c=0; /* the end */
- continue;
- }
- break;
- case '\r':
- case '\n':
- /* end of string */
- c=0;
- continue;
- case '\"':
- if (!escape && starts_with_quote)
- {
- /* end of string */
- c=0;
- continue;
- }
- break;
- }
- escape = false;
- *value++ = *str;
+ switch (*str)
+ {
+ case '\\':
+ if (!escape)
+ {
+ /* possibly the start of an escaped quote */
+ escape = true;
+ *value++ = '\\'; /* even though this is an escape character, we still
+ * store it as-is in the target buffer */
+ continue;
+ }
+ break;
+
+ case ',':
+ if (!starts_with_quote)
+ {
+ /* this signals the end of the value if we didn't get a starting quote
+ * and then we do "sloppy" parsing */
+ c = 0; /* the end */
+ continue;
+ }
+ break;
+
+ case '\r':
+ case '\n':
+ /* end of string */
+ c = 0;
+ continue;
+
+ case '\"':
+ if (!escape && starts_with_quote)
+ {
+ /* end of string */
+ c = 0;
+ continue;
+ }
+ break;
+ }
+ escape = false;
+ *value++ = *str;
}
- *value = '\0';
+ *value = '\0';
- *endptr = str;
+ *endptr = str;
- return true; /* success */
+ return true; /* success */
}
static char *
-get_pa_var (const char *key, const char *pa, struct gc_arena *gc)
+get_pa_var(const char *key, const char *pa, struct gc_arena *gc)
{
- char k[64];
- char v[256];
- const char *content = pa;
+ char k[64];
+ char v[256];
+ const char *content = pa;
- while (true)
+ while (true)
{
- const int status = get_key_value(content, k, v, sizeof(k), sizeof(v), &content);
- if (status)
- {
- if (!strcmp(key, k))
- return string_alloc(v, gc);
- }
- else
- return NULL;
-
- /* advance to start of next key */
- if (*content == ',')
- ++content;
- while (*content && isspace(*content))
- ++content;
+ const int status = get_key_value(content, k, v, sizeof(k), sizeof(v), &content);
+ if (status)
+ {
+ if (!strcmp(key, k))
+ {
+ return string_alloc(v, gc);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ /* advance to start of next key */
+ if (*content == ',')
+ {
+ ++content;
+ }
+ while (*content && isspace(*content))
+ ++content;
}
}
struct http_proxy_info *
-http_proxy_new (const struct http_proxy_options *o)
+http_proxy_new(const struct http_proxy_options *o)
{
- struct http_proxy_info *p;
+ struct http_proxy_info *p;
- if (!o || !o->server)
- msg (M_FATAL, "HTTP_PROXY: server not specified");
+ if (!o || !o->server)
+ {
+ msg(M_FATAL, "HTTP_PROXY: server not specified");
+ }
- ASSERT ( o->port);
+ ASSERT( o->port);
- ALLOC_OBJ_CLEAR (p, struct http_proxy_info);
- p->options = *o;
+ ALLOC_OBJ_CLEAR(p, struct http_proxy_info);
+ p->options = *o;
- /* parse authentication method */
- p->auth_method = HTTP_AUTH_NONE;
- if (o->auth_method_string)
+ /* parse authentication method */
+ p->auth_method = HTTP_AUTH_NONE;
+ if (o->auth_method_string)
{
- if (!strcmp (o->auth_method_string, "none"))
- p->auth_method = HTTP_AUTH_NONE;
- else if (!strcmp (o->auth_method_string, "basic"))
- p->auth_method = HTTP_AUTH_BASIC;
+ if (!strcmp(o->auth_method_string, "none"))
+ {
+ p->auth_method = HTTP_AUTH_NONE;
+ }
+ else if (!strcmp(o->auth_method_string, "basic"))
+ {
+ p->auth_method = HTTP_AUTH_BASIC;
+ }
#if NTLM
- else if (!strcmp (o->auth_method_string, "ntlm"))
- p->auth_method = HTTP_AUTH_NTLM;
- else if (!strcmp (o->auth_method_string, "ntlm2"))
- p->auth_method = HTTP_AUTH_NTLM2;
+ else if (!strcmp(o->auth_method_string, "ntlm"))
+ {
+ p->auth_method = HTTP_AUTH_NTLM;
+ }
+ else if (!strcmp(o->auth_method_string, "ntlm2"))
+ {
+ p->auth_method = HTTP_AUTH_NTLM2;
+ }
#endif
- else
- msg (M_FATAL, "ERROR: unknown HTTP authentication method: '%s'",
- o->auth_method_string);
+ else
+ {
+ msg(M_FATAL, "ERROR: unknown HTTP authentication method: '%s'",
+ o->auth_method_string);
+ }
}
- /* only basic and NTLM/NTLMv2 authentication supported so far */
- if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
+ /* only basic and NTLM/NTLMv2 authentication supported so far */
+ if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
{
- get_user_pass_http (p, true);
+ get_user_pass_http(p, true);
}
#if !NTLM
- if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
- msg (M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");
+ if (p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2)
+ {
+ msg(M_FATAL, "Sorry, this version of " PACKAGE_NAME " was built without NTLM Proxy support.");
+ }
#endif
- p->defined = true;
- return p;
+ p->defined = true;
+ return p;
}
void
-http_proxy_close (struct http_proxy_info *hp)
+http_proxy_close(struct http_proxy_info *hp)
{
- free (hp);
+ free(hp);
}
bool
-add_proxy_headers (struct http_proxy_info *p,
- socket_descriptor_t sd, /* already open to proxy */
- const char *host, /* openvpn server remote */
- const char* port /* openvpn server port */
- )
+add_proxy_headers(struct http_proxy_info *p,
+ socket_descriptor_t sd, /* already open to proxy */
+ const char *host, /* openvpn server remote */
+ const char *port /* openvpn server port */
+ )
{
- char buf[512];
- int i;
- bool host_header_sent=false;
-
- /*
- * Send custom headers if provided
- * If content is NULL the whole header is in name
- * Also remember if we already sent a Host: header
- */
- for (i=0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name;i++)
+ char buf[512];
+ int i;
+ bool host_header_sent = false;
+
+ /*
+ * Send custom headers if provided
+ * If content is NULL the whole header is in name
+ * Also remember if we already sent a Host: header
+ */
+ for (i = 0; i < MAX_CUSTOM_HTTP_HEADER && p->options.custom_headers[i].name; i++)
{
- if (p->options.custom_headers[i].content)
- {
- openvpn_snprintf (buf, sizeof(buf), "%s: %s",
- p->options.custom_headers[i].name,
- p->options.custom_headers[i].content);
- if (!strcasecmp(p->options.custom_headers[i].name, "Host"))
- host_header_sent=true;
- }
- else
- {
- openvpn_snprintf (buf, sizeof(buf), "%s",
- p->options.custom_headers[i].name);
- if (!strncasecmp(p->options.custom_headers[i].name, "Host:", 5))
- host_header_sent=true;
- }
-
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- return false;
+ if (p->options.custom_headers[i].content)
+ {
+ openvpn_snprintf(buf, sizeof(buf), "%s: %s",
+ p->options.custom_headers[i].name,
+ p->options.custom_headers[i].content);
+ if (!strcasecmp(p->options.custom_headers[i].name, "Host"))
+ {
+ host_header_sent = true;
+ }
+ }
+ else
+ {
+ openvpn_snprintf(buf, sizeof(buf), "%s",
+ p->options.custom_headers[i].name);
+ if (!strncasecmp(p->options.custom_headers[i].name, "Host:", 5))
+ {
+ host_header_sent = true;
+ }
+ }
+
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ return false;
+ }
}
- if (!host_header_sent)
+ if (!host_header_sent)
{
- openvpn_snprintf (buf, sizeof(buf), "Host: %s", host);
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf(sd, buf))
- return false;
+ openvpn_snprintf(buf, sizeof(buf), "Host: %s", host);
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ return false;
+ }
}
- /* send User-Agent string if provided */
- if (p->options.user_agent)
+ /* send User-Agent string if provided */
+ if (p->options.user_agent)
{
- openvpn_snprintf (buf, sizeof(buf), "User-Agent: %s",
- p->options.user_agent);
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- return false;
+ openvpn_snprintf(buf, sizeof(buf), "User-Agent: %s",
+ p->options.user_agent);
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ return false;
+ }
}
- return true;
+ return true;
}
bool
-establish_http_proxy_passthru (struct http_proxy_info *p,
- socket_descriptor_t sd, /* already open to proxy */
- const char *host, /* openvpn server remote */
- const char *port, /* openvpn server port */
- struct event_timeout* server_poll_timeout,
- struct buffer *lookahead,
- volatile int *signal_received)
+establish_http_proxy_passthru(struct http_proxy_info *p,
+ socket_descriptor_t sd, /* already open to proxy */
+ const char *host, /* openvpn server remote */
+ const char *port, /* openvpn server port */
+ struct event_timeout *server_poll_timeout,
+ struct buffer *lookahead,
+ volatile int *signal_received)
{
- struct gc_arena gc = gc_new ();
- char buf[512];
- char buf2[129];
- char get[80];
- int status;
- int nparms;
- bool ret = false;
- bool processed = false;
-
- /* get user/pass if not previously given */
- if (p->auth_method == HTTP_AUTH_BASIC
- || p->auth_method == HTTP_AUTH_DIGEST
- || p->auth_method == HTTP_AUTH_NTLM)
- get_user_pass_http (p, false);
-
- /* are we being called again after getting the digest server nonce in the previous transaction? */
- if (p->auth_method == HTTP_AUTH_DIGEST && p->proxy_authenticate)
+ struct gc_arena gc = gc_new();
+ char buf[512];
+ char buf2[129];
+ char get[80];
+ int status;
+ int nparms;
+ bool ret = false;
+ bool processed = false;
+
+ /* get user/pass if not previously given */
+ if (p->auth_method == HTTP_AUTH_BASIC
+ || p->auth_method == HTTP_AUTH_DIGEST
+ || p->auth_method == HTTP_AUTH_NTLM)
+ {
+ get_user_pass_http(p, false);
+ }
+
+ /* are we being called again after getting the digest server nonce in the previous transaction? */
+ if (p->auth_method == HTTP_AUTH_DIGEST && p->proxy_authenticate)
{
- nparms = 1;
- status = 407;
+ nparms = 1;
+ status = 407;
}
- else
+ else
{
- /* format HTTP CONNECT message */
- openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
- host,
- port,
- p->options.http_version);
-
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
-
- /* send HTTP CONNECT message to proxy */
- if (!send_line_crlf (sd, buf))
- goto error;
-
- if (!add_proxy_headers (p, sd, host, port))
- goto error;
-
- /* auth specified? */
- switch (p->auth_method)
- {
- case HTTP_AUTH_NONE:
- break;
-
- case HTTP_AUTH_BASIC:
- openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: Basic %s",
- username_password_as_base64 (p, &gc));
- msg (D_PROXY, "Attempting Basic Proxy-Authorization");
- dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- goto error;
- break;
+ /* format HTTP CONNECT message */
+ openvpn_snprintf(buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
+ host,
+ port,
+ p->options.http_version);
+
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+
+ /* send HTTP CONNECT message to proxy */
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+
+ if (!add_proxy_headers(p, sd, host, port))
+ {
+ goto error;
+ }
+
+ /* auth specified? */
+ switch (p->auth_method)
+ {
+ case HTTP_AUTH_NONE:
+ break;
+
+ case HTTP_AUTH_BASIC:
+ openvpn_snprintf(buf, sizeof(buf), "Proxy-Authorization: Basic %s",
+ username_password_as_base64(p, &gc));
+ msg(D_PROXY, "Attempting Basic Proxy-Authorization");
+ dmsg(D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+ break;
#if NTLM
- case HTTP_AUTH_NTLM:
- case HTTP_AUTH_NTLM2:
- /* keep-alive connection */
- openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
- if (!send_line_crlf (sd, buf))
- goto error;
-
- openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s",
- ntlm_phase_1 (p, &gc));
- msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 1");
- dmsg (D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- goto error;
- break;
+ case HTTP_AUTH_NTLM:
+ case HTTP_AUTH_NTLM2:
+ /* keep-alive connection */
+ openvpn_snprintf(buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+
+ openvpn_snprintf(buf, sizeof(buf), "Proxy-Authorization: NTLM %s",
+ ntlm_phase_1(p, &gc));
+ msg(D_PROXY, "Attempting NTLM Proxy-Authorization phase 1");
+ dmsg(D_SHOW_KEYS, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+ break;
#endif
- default:
- ASSERT (0);
- }
+ default:
+ ASSERT(0);
+ }
- /* send empty CR, LF */
- if (!send_crlf (sd))
- goto error;
+ /* send empty CR, LF */
+ if (!send_crlf(sd))
+ {
+ goto error;
+ }
- /* receive reply from proxy */
- if (!recv_line (sd, buf, sizeof(buf), get_server_poll_remaining_time (server_poll_timeout), true, NULL, signal_received))
- goto error;
+ /* receive reply from proxy */
+ if (!recv_line(sd, buf, sizeof(buf), get_server_poll_remaining_time(server_poll_timeout), true, NULL, signal_received))
+ {
+ goto error;
+ }
- /* remove trailing CR, LF */
- chomp (buf);
+ /* remove trailing CR, LF */
+ chomp(buf);
- msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
+ msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
- /* parse return string */
- nparms = sscanf (buf, "%*s %d", &status);
+ /* parse return string */
+ nparms = sscanf(buf, "%*s %d", &status);
}
- /* check for a "407 Proxy Authentication Required" response */
- while (nparms >= 1 && status == 407)
+ /* check for a "407 Proxy Authentication Required" response */
+ while (nparms >= 1 && status == 407)
{
- msg (D_PROXY, "Proxy requires authentication");
+ msg(D_PROXY, "Proxy requires authentication");
- if (p->auth_method == HTTP_AUTH_BASIC && !processed)
- {
- processed = true;
- }
- else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */
+ if (p->auth_method == HTTP_AUTH_BASIC && !processed)
+ {
+ processed = true;
+ }
+ else if ((p->auth_method == HTTP_AUTH_NTLM || p->auth_method == HTTP_AUTH_NTLM2) && !processed) /* check for NTLM */
{
#if NTLM
- /* look for the phase 2 response */
+ /* look for the phase 2 response */
- while (true)
+ while (true)
{
- if (!recv_line (sd, buf, sizeof(buf), get_server_poll_remaining_time (server_poll_timeout), true, NULL, signal_received))
- goto error;
- chomp (buf);
- msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
+ if (!recv_line(sd, buf, sizeof(buf), get_server_poll_remaining_time(server_poll_timeout), true, NULL, signal_received))
+ {
+ goto error;
+ }
+ chomp(buf);
+ msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
- openvpn_snprintf (get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof (buf2) - 1);
- nparms = sscanf (buf, get, buf2);
- buf2[128] = 0; /* we only need the beginning - ensure it's null terminated. */
+ openvpn_snprintf(get, sizeof get, "%%*s NTLM %%%ds", (int) sizeof(buf2) - 1);
+ nparms = sscanf(buf, get, buf2);
+ buf2[128] = 0; /* we only need the beginning - ensure it's null terminated. */
- /* check for "Proxy-Authenticate: NTLM TlRM..." */
- if (nparms == 1)
+ /* check for "Proxy-Authenticate: NTLM TlRM..." */
+ if (nparms == 1)
{
- /* parse buf2 */
- msg (D_PROXY, "auth string: '%s'", buf2);
- break;
+ /* parse buf2 */
+ msg(D_PROXY, "auth string: '%s'", buf2);
+ break;
}
}
- /* if we are here then auth string was got */
- msg (D_PROXY, "Received NTLM Proxy-Authorization phase 2 response");
+ /* if we are here then auth string was got */
+ msg(D_PROXY, "Received NTLM Proxy-Authorization phase 2 response");
- /* receive and discard everything else */
- while (recv_line (sd, NULL, 0, 2, true, NULL, signal_received))
- ;
+ /* receive and discard everything else */
+ while (recv_line(sd, NULL, 0, 2, true, NULL, signal_received))
+ ;
- /* now send the phase 3 reply */
+ /* now send the phase 3 reply */
- /* format HTTP CONNECT message */
- openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
- host,
- port,
- p->options.http_version);
+ /* format HTTP CONNECT message */
+ openvpn_snprintf(buf, sizeof(buf), "CONNECT %s:%s HTTP/%s",
+ host,
+ port,
+ p->options.http_version);
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
- /* send HTTP CONNECT message to proxy */
- if (!send_line_crlf (sd, buf))
- goto error;
+ /* send HTTP CONNECT message to proxy */
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
- /* keep-alive connection */
- openvpn_snprintf (buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
- if (!send_line_crlf (sd, buf))
- goto error;
+ /* keep-alive connection */
+ openvpn_snprintf(buf, sizeof(buf), "Proxy-Connection: Keep-Alive");
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
- /* send HOST etc, */
- if (!add_proxy_headers (p, sd, host, port))
- goto error;
-
- msg (D_PROXY, "Attempting NTLM Proxy-Authorization phase 3");
- {
- const char *np3 = ntlm_phase_3 (p, buf2, &gc);
- if (!np3)
- {
- msg (D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
- goto error;
- }
- openvpn_snprintf (buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3);
- }
-
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- goto error;
- /* ok so far... */
- /* send empty CR, LF */
- if (!send_crlf (sd))
- goto error;
+ /* send HOST etc, */
+ if (!add_proxy_headers(p, sd, host, port))
+ {
+ goto error;
+ }
- /* receive reply from proxy */
- if (!recv_line (sd, buf, sizeof(buf), get_server_poll_remaining_time (server_poll_timeout), true, NULL, signal_received))
- goto error;
+ msg(D_PROXY, "Attempting NTLM Proxy-Authorization phase 3");
+ {
+ const char *np3 = ntlm_phase_3(p, buf2, &gc);
+ if (!np3)
+ {
+ msg(D_PROXY, "NTLM Proxy-Authorization phase 3 failed: received corrupted data from proxy server");
+ goto error;
+ }
+ openvpn_snprintf(buf, sizeof(buf), "Proxy-Authorization: NTLM %s", np3);
+ }
+
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+ /* ok so far... */
+ /* send empty CR, LF */
+ if (!send_crlf(sd))
+ {
+ goto error;
+ }
- /* remove trailing CR, LF */
- chomp (buf);
+ /* receive reply from proxy */
+ if (!recv_line(sd, buf, sizeof(buf), get_server_poll_remaining_time(server_poll_timeout), true, NULL, signal_received))
+ {
+ goto error;
+ }
- msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
+ /* remove trailing CR, LF */
+ chomp(buf);
- /* parse return string */
- nparms = sscanf (buf, "%*s %d", &status);
- processed = true;
-#endif
- }
+ msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
+
+ /* parse return string */
+ nparms = sscanf(buf, "%*s %d", &status);
+ processed = true;
+#endif /* if NTLM */
+ }
#if PROXY_DIGEST_AUTH
- else if (p->auth_method == HTTP_AUTH_DIGEST && !processed)
- {
- char *pa = p->proxy_authenticate;
- const int method = p->auth_method;
- ASSERT(pa);
-
- if (method == HTTP_AUTH_DIGEST)
- {
- const char *http_method = "CONNECT";
- const char *nonce_count = "00000001";
- const char *qop = "auth";
- const char *username = p->up.username;
- const char *password = p->up.password;
- char *opaque_kv = "";
- char uri[128];
- uint8_t cnonce_raw[8];
- uint8_t *cnonce;
- HASHHEX session_key;
- HASHHEX response;
-
- const char *realm = get_pa_var("realm", pa, &gc);
- const char *nonce = get_pa_var("nonce", pa, &gc);
- const char *algor = get_pa_var("algorithm", pa, &gc);
- const char *opaque = get_pa_var("opaque", pa, &gc);
-
- /* generate a client nonce */
- ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw)));
- cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc);
-
-
- /* build the digest response */
- openvpn_snprintf (uri, sizeof(uri), "%s:%s",
- host,
- port);
-
- if (opaque)
- {
- const int len = strlen(opaque)+16;
- opaque_kv = gc_malloc(len, false, &gc);
- openvpn_snprintf (opaque_kv, len, ", opaque=\"%s\"", opaque);
- }
-
- DigestCalcHA1(algor,
- username,
- realm,
- password,
- nonce,
- (char *)cnonce,
- session_key);
- DigestCalcResponse(session_key,
- nonce,
- nonce_count,
- (char *)cnonce,
- qop,
- http_method,
- uri,
- NULL,
- response);
-
- /* format HTTP CONNECT message */
- openvpn_snprintf (buf, sizeof(buf), "%s %s HTTP/%s",
- http_method,
- uri,
- p->options.http_version);
-
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
-
- /* send HTTP CONNECT message to proxy */
- if (!send_line_crlf (sd, buf))
- goto error;
-
- /* send HOST etc, */
- if (!add_proxy_headers (p, sd, host, port))
- goto error;
-
- /* send digest response */
- 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",
- username,
- realm,
- nonce,
- uri,
- qop,
- nonce_count,
- cnonce,
- response,
- opaque_kv
- );
- msg (D_PROXY, "Send to HTTP proxy: '%s'", buf);
- if (!send_line_crlf (sd, buf))
- goto error;
- if (!send_crlf (sd))
- goto error;
-
- /* receive reply from proxy */
- if (!recv_line (sd, buf, sizeof(buf), get_server_poll_remaining_time (server_poll_timeout), true, NULL, signal_received))
- goto error;
-
- /* remove trailing CR, LF */
- chomp (buf);
-
- msg (D_PROXY, "HTTP proxy returned: '%s'", buf);
-
- /* parse return string */
- nparms = sscanf (buf, "%*s %d", &status);
- processed = true;
- }
- else
- {
- msg (D_PROXY, "HTTP proxy: digest method not supported");
- goto error;
- }
- }
-#endif
- else if (p->options.auth_retry)
- {
- /* figure out what kind of authentication the proxy needs */
- char *pa = NULL;
- const int method = get_proxy_authenticate(sd,
- get_server_poll_remaining_time (server_poll_timeout),
- &pa,
- NULL,
- signal_received);
- if (method != HTTP_AUTH_NONE)
- {
- if (pa)
- msg (D_PROXY, "HTTP proxy authenticate '%s'", pa);
- if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC)
- {
- msg (D_PROXY, "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
- goto error;
- }
- p->auth_method = method;
- store_proxy_authenticate(p, pa);
- ret = true;
- goto done;
- }
- else
- {
- msg (D_PROXY, "HTTP proxy: do not recognize the authentication method required by proxy");
- free (pa);
- goto error;
- }
- }
- else
- {
- if (!processed)
- msg (D_PROXY, "HTTP proxy: no support for proxy authentication method");
- goto error;
- }
-
- /* clear state */
- if (p->options.auth_retry)
- clear_user_pass_http();
- store_proxy_authenticate(p, NULL);
+ else if (p->auth_method == HTTP_AUTH_DIGEST && !processed)
+ {
+ char *pa = p->proxy_authenticate;
+ const int method = p->auth_method;
+ ASSERT(pa);
+
+ if (method == HTTP_AUTH_DIGEST)
+ {
+ const char *http_method = "CONNECT";
+ const char *nonce_count = "00000001";
+ const char *qop = "auth";
+ const char *username = p->up.username;
+ const char *password = p->up.password;
+ char *opaque_kv = "";
+ char uri[128];
+ uint8_t cnonce_raw[8];
+ uint8_t *cnonce;
+ HASHHEX session_key;
+ HASHHEX response;
+
+ const char *realm = get_pa_var("realm", pa, &gc);
+ const char *nonce = get_pa_var("nonce", pa, &gc);
+ const char *algor = get_pa_var("algorithm", pa, &gc);
+ const char *opaque = get_pa_var("opaque", pa, &gc);
+
+ /* generate a client nonce */
+ ASSERT(rand_bytes(cnonce_raw, sizeof(cnonce_raw)));
+ cnonce = make_base64_string2(cnonce_raw, sizeof(cnonce_raw), &gc);
+
+
+ /* build the digest response */
+ openvpn_snprintf(uri, sizeof(uri), "%s:%s",
+ host,
+ port);
+
+ if (opaque)
+ {
+ const int len = strlen(opaque)+16;
+ opaque_kv = gc_malloc(len, false, &gc);
+ openvpn_snprintf(opaque_kv, len, ", opaque=\"%s\"", opaque);
+ }
+
+ DigestCalcHA1(algor,
+ username,
+ realm,
+ password,
+ nonce,
+ (char *)cnonce,
+ session_key);
+ DigestCalcResponse(session_key,
+ nonce,
+ nonce_count,
+ (char *)cnonce,
+ qop,
+ http_method,
+ uri,
+ NULL,
+ response);
+
+ /* format HTTP CONNECT message */
+ openvpn_snprintf(buf, sizeof(buf), "%s %s HTTP/%s",
+ http_method,
+ uri,
+ p->options.http_version);
+
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+
+ /* send HTTP CONNECT message to proxy */
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+
+ /* send HOST etc, */
+ if (!add_proxy_headers(p, sd, host, port))
+ {
+ goto error;
+ }
+
+ /* send digest response */
+ 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",
+ username,
+ realm,
+ nonce,
+ uri,
+ qop,
+ nonce_count,
+ cnonce,
+ response,
+ opaque_kv
+ );
+ msg(D_PROXY, "Send to HTTP proxy: '%s'", buf);
+ if (!send_line_crlf(sd, buf))
+ {
+ goto error;
+ }
+ if (!send_crlf(sd))
+ {
+ goto error;
+ }
+
+ /* receive reply from proxy */
+ if (!recv_line(sd, buf, sizeof(buf), get_server_poll_remaining_time(server_poll_timeout), true, NULL, signal_received))
+ {
+ goto error;
+ }
+
+ /* remove trailing CR, LF */
+ chomp(buf);
+
+ msg(D_PROXY, "HTTP proxy returned: '%s'", buf);
+
+ /* parse return string */
+ nparms = sscanf(buf, "%*s %d", &status);
+ processed = true;
+ }
+ else
+ {
+ msg(D_PROXY, "HTTP proxy: digest method not supported");
+ goto error;
+ }
+ }
+#endif /* if PROXY_DIGEST_AUTH */
+ else if (p->options.auth_retry)
+ {
+ /* figure out what kind of authentication the proxy needs */
+ char *pa = NULL;
+ const int method = get_proxy_authenticate(sd,
+ get_server_poll_remaining_time(server_poll_timeout),
+ &pa,
+ NULL,
+ signal_received);
+ if (method != HTTP_AUTH_NONE)
+ {
+ if (pa)
+ {
+ msg(D_PROXY, "HTTP proxy authenticate '%s'", pa);
+ }
+ if (p->options.auth_retry == PAR_NCT && method == HTTP_AUTH_BASIC)
+ {
+ msg(D_PROXY, "HTTP proxy: support for basic auth and other cleartext proxy auth methods is disabled");
+ goto error;
+ }
+ p->auth_method = method;
+ store_proxy_authenticate(p, pa);
+ ret = true;
+ goto done;
+ }
+ else
+ {
+ msg(D_PROXY, "HTTP proxy: do not recognize the authentication method required by proxy");
+ free(pa);
+ goto error;
+ }
+ }
+ else
+ {
+ if (!processed)
+ {
+ msg(D_PROXY, "HTTP proxy: no support for proxy authentication method");
+ }
+ goto error;
+ }
+
+ /* clear state */
+ if (p->options.auth_retry)
+ {
+ clear_user_pass_http();
+ }
+ store_proxy_authenticate(p, NULL);
}
- /* check return code, success = 200 */
- if (nparms < 1 || status != 200)
+ /* check return code, success = 200 */
+ if (nparms < 1 || status != 200)
{
- msg (D_LINK_ERRORS, "HTTP proxy returned bad status");
+ msg(D_LINK_ERRORS, "HTTP proxy returned bad status");
#if 0
- /* DEBUGGING -- show a multi-line HTTP error response */
- dump_residual(sd, get_server_poll_remaining_time (server_poll_timeout), signal_received);
+ /* DEBUGGING -- show a multi-line HTTP error response */
+ dump_residual(sd, get_server_poll_remaining_time(server_poll_timeout), signal_received);
#endif
- goto error;
+ goto error;
}
- /* SUCCESS */
+ /* SUCCESS */
- /* receive line from proxy and discard */
- if (!recv_line (sd, NULL, 0, get_server_poll_remaining_time (server_poll_timeout), true, NULL, signal_received))
- goto error;
+ /* receive line from proxy and discard */
+ if (!recv_line(sd, NULL, 0, get_server_poll_remaining_time(server_poll_timeout), true, NULL, signal_received))
+ {
+ goto error;
+ }
- /*
- * Toss out any extraneous chars, but don't throw away the
- * start of the OpenVPN data stream (put it in lookahead).
- */
- while (recv_line (sd, NULL, 0, 2, false, lookahead, signal_received))
- ;
+ /*
+ * Toss out any extraneous chars, but don't throw away the
+ * start of the OpenVPN data stream (put it in lookahead).
+ */
+ while (recv_line(sd, NULL, 0, 2, false, lookahead, signal_received))
+ ;
- /* reset queried_creds so that we don't think that the next creds request is due to an auth error */
- p->queried_creds = false;
+ /* reset queried_creds so that we don't think that the next creds request is due to an auth error */
+ p->queried_creds = false;
#if 0
- if (lookahead && BLEN (lookahead))
- msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0));
+ if (lookahead && BLEN(lookahead))
+ {
+ msg(M_INFO, "HTTP PROXY: lookahead: %s", format_hex(BPTR(lookahead), BLEN(lookahead), 0));
+ }
#endif
- done:
- gc_free (&gc);
- return ret;
+done:
+ gc_free(&gc);
+ return ret;
- error:
- if (!*signal_received)
- *signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- HTTP proxy error */
- gc_free (&gc);
- return ret;
+error:
+ if (!*signal_received)
+ {
+ *signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- HTTP proxy error */
+ }
+ gc_free(&gc);
+ return ret;
}