mirror of
https://github.com/OpenVPN/openvpn.git
synced 2025-05-09 05:31:05 +08:00
Added --auto-proxy directive to auto-detect HTTP or SOCKS
proxy settings (currently Windows only). git-svn-id: http://svn.openvpn.net/projects/openvpn/branches/BETA21/openvpn@850 e7ae566f-a301-0410-adde-c780ea21d3b5
This commit is contained in:
parent
df5722cc68
commit
f214bb2115
@ -3,7 +3,7 @@ Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
|
||||
|
||||
$Id$
|
||||
|
||||
2005.11.xx -- Version 2.1-beta8
|
||||
2005.12.xx -- Version 2.1-beta8
|
||||
|
||||
* --remap-usr1 will now also remap signals thrown during
|
||||
initialization.
|
||||
@ -17,6 +17,8 @@ $Id$
|
||||
* Fixed typo in manage.c where inline function declaration
|
||||
was declared without the "static" keyword (David Stipp).
|
||||
* Patch to support --topology subnet on Mac OS X (Mathias Sundman).
|
||||
* Added --auto-proxy directive to auto-detect HTTP or SOCKS
|
||||
proxy settings (currently Windows only).
|
||||
|
||||
2005.11.12 -- Version 2.1-beta7
|
||||
|
||||
@ -29,7 +31,8 @@ $Id$
|
||||
but actually would only accept /29 or less.
|
||||
* Extend byte counters to 64 bits (M. van Cuijk).
|
||||
* PKCS#11 fixes (Alon Bar-Lev).
|
||||
|
||||
* Removed redundant base64 code.
|
||||
|
||||
2005.11.02 -- Version 2.0.5
|
||||
|
||||
* Fixed bug in Linux get_default_gateway function
|
||||
|
@ -127,8 +127,7 @@ EXTRA_DIST = \
|
||||
plugin \
|
||||
management \
|
||||
pkcs11-headers \
|
||||
cryptoki-win32.h \
|
||||
ieproxy.c ieproxy.h
|
||||
cryptoki-win32.h
|
||||
|
||||
dist-hook:
|
||||
cd $(distdir) && for i in $(EXTRA_DIST) ; do find $$i -name .svn -type d -prune -exec rm -rf '{}' ';' ; rm -f `find $$i -type f | grep -E '(^|\/)\.?\#|\~$$|\.s?o$$'` ; done
|
||||
|
26
base64.c
26
base64.c
@ -39,7 +39,7 @@
|
||||
|
||||
#include "syshead.h"
|
||||
|
||||
#if NTLM
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
@ -48,16 +48,6 @@
|
||||
static char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
static int
|
||||
pos(char c)
|
||||
{
|
||||
char *p;
|
||||
for (p = base64_chars; *p; p++)
|
||||
if (*p == c)
|
||||
return p - base64_chars;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
base64_encode(const void *data, int size, char **str)
|
||||
{
|
||||
@ -96,6 +86,18 @@ base64_encode(const void *data, int size, char **str)
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
#if NTLM
|
||||
|
||||
static int
|
||||
pos(char c)
|
||||
{
|
||||
char *p;
|
||||
for (p = base64_chars; *p; p++)
|
||||
if (*p == c)
|
||||
return p - base64_chars;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define DECODE_ERROR 0xffffffff
|
||||
|
||||
static unsigned int
|
||||
@ -141,6 +143,8 @@ base64_decode(const char *str, void *data)
|
||||
return q - (unsigned char *) data;
|
||||
}
|
||||
|
||||
#endif /* NTLM */
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#endif
|
||||
|
4
base64.h
4
base64.h
@ -31,12 +31,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* $KTH: base64.h,v 1.2 1999/12/02 16:58:45 joda Exp $ */
|
||||
|
||||
#ifndef _BASE64_H_
|
||||
#define _BASE64_H_
|
||||
|
||||
#if NTLM
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
int base64_encode(const void *data, int size, char **str);
|
||||
int base64_decode(const char *str, void *data);
|
||||
|
12
buffer.c
12
buffer.c
@ -620,6 +620,18 @@ buf_parse (struct buffer *buf, const int delim, char *line, const int size)
|
||||
return !(eol && !strlen (line));
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a string which might be NULL
|
||||
*/
|
||||
const char *
|
||||
np (const char *str)
|
||||
{
|
||||
if (str)
|
||||
return str;
|
||||
else
|
||||
return "[NULL]";
|
||||
}
|
||||
|
||||
/*
|
||||
* Classify and mutate strings based on character types.
|
||||
*/
|
||||
|
3
buffer.h
3
buffer.h
@ -553,8 +553,9 @@ xor (uint8_t *dest, const uint8_t *src, int len)
|
||||
}
|
||||
|
||||
/*
|
||||
* Classify and mutate strings based on character types.
|
||||
* Print a string which might be NULL
|
||||
*/
|
||||
const char *np (const char *str);
|
||||
|
||||
/*#define CHARACTER_CLASS_DEBUG*/
|
||||
|
||||
|
14
init.c
14
init.c
@ -102,6 +102,12 @@ init_remote_list (struct context *c)
|
||||
void
|
||||
context_init_1 (struct context *c)
|
||||
{
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
bool did_http = false;
|
||||
#else
|
||||
const bool did_http = false;
|
||||
#endif
|
||||
|
||||
context_clear_1 (c);
|
||||
|
||||
packet_id_persist_init (&c->c1.pid_persist);
|
||||
@ -145,20 +151,24 @@ context_init_1 (struct context *c)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
if (c->options.http_proxy_options)
|
||||
if (c->options.http_proxy_options || c->options.auto_proxy_info)
|
||||
{
|
||||
/* Possible HTTP proxy user/pass input */
|
||||
c->c1.http_proxy = new_http_proxy (c->options.http_proxy_options,
|
||||
c->options.auto_proxy_info,
|
||||
&c->gc);
|
||||
if (c->c1.http_proxy)
|
||||
did_http = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SOCKS
|
||||
if (c->options.socks_proxy_server)
|
||||
if (!did_http && (c->options.socks_proxy_server || c->options.auto_proxy_info))
|
||||
{
|
||||
c->c1.socks_proxy = new_socks_proxy (c->options.socks_proxy_server,
|
||||
c->options.socks_proxy_port,
|
||||
c->options.socks_proxy_retry,
|
||||
c->options.auto_proxy_info,
|
||||
&c->gc);
|
||||
}
|
||||
#endif
|
||||
|
@ -78,7 +78,6 @@ HEADERS = \
|
||||
fragment.h \
|
||||
gremlin.h \
|
||||
helper.h \
|
||||
ieproxy.h \
|
||||
init.h \
|
||||
integer.h \
|
||||
interval.h \
|
||||
@ -137,7 +136,6 @@ OBJS = base64.o \
|
||||
fragment.o \
|
||||
gremlin.o \
|
||||
helper.o \
|
||||
ieproxy.o \
|
||||
init.o \
|
||||
interval.o \
|
||||
list.o \
|
||||
|
30
openvpn.8
30
openvpn.8
@ -101,6 +101,7 @@ openvpn \- secure IP tunnel daemon.
|
||||
[\ \fB\-\-auth\-user\-pass\-verify\fR\ \fIscript\fR\ ]
|
||||
[\ \fB\-\-auth\-user\-pass\fR\ \fIup\fR\ ]
|
||||
[\ \fB\-\-auth\fR\ \fIalg\fR\ ]
|
||||
[\ \fB\-\-auto\-proxy\fR\ ]
|
||||
[\ \fB\-\-bcast\-buffers\fR\ \fIn\fR\ ]
|
||||
[\ \fB\-\-ca\fR\ \fIfile\fR\ ]
|
||||
[\ \fB\-\-ccd\-exclusive\fR\ ]
|
||||
@ -597,7 +598,19 @@ as the
|
||||
number of retries of connection attempt (default=infinite).
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --http-proxy server port [authfile] [auth-method]
|
||||
.B --auto-proxy
|
||||
Try to sense HTTP or SOCKS proxy settings automatically.
|
||||
If no settings are present, a direct connection will be attempted.
|
||||
If both HTTP and SOCKS settings are present, HTTP will be preferred.
|
||||
If the HTTP proxy server requires a password, it will be queried from
|
||||
stdin or the management interface. If the underlying OS doesn't support an API for
|
||||
returning proxy settings, a direct connection will be attempted.
|
||||
Currently, only Windows clients support this option via the
|
||||
InternetQueryOption API.
|
||||
This option exists in OpenVPN 2.1 or higher.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --http-proxy server port [authfile|'auto'] [auth-method]
|
||||
Connect to remote host through an HTTP proxy at address
|
||||
.B server
|
||||
and port
|
||||
@ -608,7 +621,15 @@ is a file containing a username and password on 2 lines, or
|
||||
"stdin" to prompt from console.
|
||||
|
||||
.B auth-method
|
||||
should be one of "none", "basic", or "ntlm".
|
||||
should be one of "none", "basic", or "ntlm".
|
||||
|
||||
The
|
||||
.B auto
|
||||
flag causes OpenVPN to automatically determine the
|
||||
.B auth-method
|
||||
and query stdin or the management interface for
|
||||
username/password credentials, if required. This flag
|
||||
exists on OpenVPN 2.1 or higher.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --http-proxy-retry
|
||||
@ -857,6 +878,8 @@ of the TAP-Win32 driver. When used on *nix, requires that the tun
|
||||
driver supports an
|
||||
.BR ifconfig (8)
|
||||
command which sets a subnet instead of a remote endpoint IP address.
|
||||
|
||||
This option exists in OpenVPN 2.1 or higher.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --tun-ipv6
|
||||
@ -1175,8 +1198,7 @@ bypasses the tunnel
|
||||
(Available on Windows clients, may not be available
|
||||
on non-Windows clients).
|
||||
|
||||
Using the def1 flag is highly recommended, and is currently
|
||||
planned to become the default by OpenVPN 2.1.
|
||||
Using the def1 flag is highly recommended.
|
||||
.\"*********************************************************
|
||||
.TP
|
||||
.B --link-mtu n
|
||||
|
148
options.c
148
options.c
@ -97,12 +97,18 @@ static const char usage_message[] =
|
||||
" between connection retries (default=%d).\n"
|
||||
"--connect-timeout n : For --proto tcp-client, connection timeout (in seconds).\n"
|
||||
"--connect-retry-max n : Maximum connection attempt retries, default infinite.\n"
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
"--auto-proxy : Try to sense proxy settings (or lack thereof) automatically.\n"
|
||||
#endif
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
"--http-proxy s p [up] [auth] : Connect to remote host through an HTTP proxy at\n"
|
||||
" address s and port p. If proxy authentication is required,\n"
|
||||
"--http-proxy s p [up] [auth] : Connect to remote host\n"
|
||||
" through an HTTP proxy at address s and port p.\n"
|
||||
" If proxy authentication is required,\n"
|
||||
" up is a file containing username/password on 2 lines, or\n"
|
||||
" 'stdin' to prompt from console. Add auth='ntlm' if\n"
|
||||
" the proxy requires NTLM authentication.\n"
|
||||
"--http-proxy s p 'auto': Like the above directive, but automatically determine\n"
|
||||
" auth method and query for username/password if needed.\n"
|
||||
"--http-proxy-retry : Retry indefinitely on HTTP proxy errors.\n"
|
||||
"--http-proxy-timeout n : Proxy timeout in seconds, default=5.\n"
|
||||
"--http-proxy-option type [parm] : Set extended HTTP proxy options.\n"
|
||||
@ -1537,8 +1543,8 @@ options_postprocess (struct options *options, bool first_time)
|
||||
msg (M_USAGE, "--remote MUST be used in TCP Client mode");
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
if (options->http_proxy_options && options->proto != PROTO_TCPv4_CLIENT)
|
||||
msg (M_USAGE, "--http-proxy MUST be used in TCP Client mode (i.e. --proto tcp-client)");
|
||||
if ((options->http_proxy_options || options->auto_proxy_info) && options->proto != PROTO_TCPv4_CLIENT)
|
||||
msg (M_USAGE, "--http-proxy or --auto-proxy MUST be used in TCP Client mode (i.e. --proto tcp-client)");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_HTTP_PROXY) && defined(ENABLE_SOCKS)
|
||||
@ -3675,6 +3681,38 @@ add_option (struct options *options,
|
||||
}
|
||||
options->proto = proto;
|
||||
}
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
else if (streq (p[0], "auto-proxy"))
|
||||
{
|
||||
char *error = NULL;
|
||||
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
options->auto_proxy_info = get_proxy_settings (&error, &options->gc);
|
||||
if (error)
|
||||
msg (M_WARN, "PROXY: %s", error);
|
||||
}
|
||||
else if (streq (p[0], "show-proxy-settings"))
|
||||
{
|
||||
struct auto_proxy_info *pi;
|
||||
char *error = NULL;
|
||||
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
pi = get_proxy_settings (&error, &options->gc);
|
||||
if (pi)
|
||||
{
|
||||
msg (M_INFO|M_NOPREFIX, "HTTP Server: %s", np(pi->http.server));
|
||||
msg (M_INFO|M_NOPREFIX, "HTTP Port: %d", pi->http.port);
|
||||
msg (M_INFO|M_NOPREFIX, "SOCKS Server: %s", np(pi->socks.server));
|
||||
msg (M_INFO|M_NOPREFIX, "SOCKS Port: %d", pi->socks.port);
|
||||
}
|
||||
if (error)
|
||||
msg (msglevel, "Proxy error: %s", error);
|
||||
#ifdef WIN32
|
||||
show_win_proxy_settings (M_INFO|M_NOPREFIX);
|
||||
#endif
|
||||
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
|
||||
}
|
||||
#endif /* GENERAL_PROXY_SUPPORT */
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
else if (streq (p[0], "http-proxy") && p[1])
|
||||
{
|
||||
@ -3682,60 +3720,39 @@ add_option (struct options *options,
|
||||
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
|
||||
if (streq (p[1], "auto"))
|
||||
{
|
||||
struct http_proxy_options hpo;
|
||||
bool status;
|
||||
char *error = NULL;
|
||||
|
||||
p[4] = p[3];
|
||||
p[3] = p[2];
|
||||
p[1] = p[2] = NULL;
|
||||
CLEAR (hpo);
|
||||
|
||||
status = get_http_proxy_settings (&hpo, &error, &options->gc);
|
||||
if (status)
|
||||
{
|
||||
ho = init_http_options_if_undefined (options);
|
||||
ho->server = hpo.server;
|
||||
ho->port = hpo.port;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
msg (M_WARN, "http-proxy auto error: %s", error);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int port;
|
||||
if (!p[2])
|
||||
{
|
||||
msg (msglevel, "http-proxy port number not defined");
|
||||
goto err;
|
||||
}
|
||||
port = atoi (p[2]);
|
||||
if (!legal_ipv4_port (port))
|
||||
{
|
||||
msg (msglevel, "Bad http-proxy port number: %s", p[2]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ho = init_http_options_if_undefined (options);
|
||||
|
||||
ho->server = p[1];
|
||||
ho->port = port;
|
||||
}
|
||||
{
|
||||
int port;
|
||||
if (!p[2])
|
||||
{
|
||||
msg (msglevel, "http-proxy port number not defined");
|
||||
goto err;
|
||||
}
|
||||
port = atoi (p[2]);
|
||||
if (!legal_ipv4_port (port))
|
||||
{
|
||||
msg (msglevel, "Bad http-proxy port number: %s", p[2]);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ho = init_http_options_if_undefined (options);
|
||||
|
||||
ho->server = p[1];
|
||||
ho->port = port;
|
||||
}
|
||||
|
||||
if (p[3])
|
||||
{
|
||||
ho->auth_method_string = "basic";
|
||||
ho->auth_file = p[3];
|
||||
|
||||
if (p[4])
|
||||
if (streq (p[3], "auto"))
|
||||
ho->auth_retry = true;
|
||||
else
|
||||
{
|
||||
ho->auth_method_string = p[4];
|
||||
ho->auth_method_string = "basic";
|
||||
ho->auth_file = p[3];
|
||||
|
||||
if (p[4])
|
||||
{
|
||||
ho->auth_method_string = p[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -3778,29 +3795,6 @@ add_option (struct options *options,
|
||||
msg (msglevel, "Bad http-proxy-option or missing parameter: '%s'", p[1]);
|
||||
}
|
||||
}
|
||||
else if (streq (p[0], "show-http-proxy-settings"))
|
||||
{
|
||||
struct http_proxy_options po;
|
||||
bool status;
|
||||
char *error = NULL;
|
||||
|
||||
VERIFY_PERMISSION (OPT_P_GENERAL);
|
||||
CLEAR (po);
|
||||
status = get_http_proxy_settings (&po, &error, &options->gc);
|
||||
if (status)
|
||||
{
|
||||
msg (M_INFO|M_NOPREFIX, "Server: %s", po.server);
|
||||
msg (M_INFO|M_NOPREFIX, "Port: %d", po.port);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
msg (msglevel, "Proxy error: %s", error);
|
||||
else
|
||||
msg (msglevel, "Proxy settings are undefined");
|
||||
}
|
||||
openvpn_exit (OPENVPN_EXIT_STATUS_GOOD); /* exit point */
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKS
|
||||
else if (streq (p[0], "socks-proxy") && p[1])
|
||||
|
@ -250,6 +250,10 @@ struct options
|
||||
struct route_option_list *routes;
|
||||
bool route_nopull;
|
||||
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
struct auto_proxy_info *auto_proxy_info;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
struct http_proxy_options *http_proxy_options;
|
||||
#endif
|
||||
|
388
proxy.c
388
proxy.c
@ -28,8 +28,6 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
#include "syshead.h"
|
||||
|
||||
#include "common.h"
|
||||
@ -38,6 +36,7 @@
|
||||
#include "socket.h"
|
||||
#include "fdmisc.h"
|
||||
#include "proxy.h"
|
||||
#include "base64.h"
|
||||
#include "ntlm.h"
|
||||
|
||||
#ifdef WIN32
|
||||
@ -46,55 +45,7 @@
|
||||
|
||||
#include "memdbg.h"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
bool
|
||||
get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc)
|
||||
{
|
||||
bool ret = false;
|
||||
const char *result;
|
||||
|
||||
p->server = NULL;
|
||||
p->port = 0;
|
||||
getIeHttpProxyError = NULL;
|
||||
if (err)
|
||||
*err = NULL;
|
||||
|
||||
result = getIeHttpProxy ();
|
||||
if (result)
|
||||
{
|
||||
char addr_str[128];
|
||||
char port_str[16];
|
||||
struct buffer in;
|
||||
buf_set_read (&in, (const uint8_t *)result, strlen (result));
|
||||
if (buf_parse (&in, ':', addr_str, sizeof (addr_str))
|
||||
&& buf_parse (&in, ':', port_str, sizeof (port_str)))
|
||||
{
|
||||
p->server = string_alloc (addr_str, gc);
|
||||
p->port = atoi (port_str);
|
||||
ret = true;
|
||||
}
|
||||
free ((void *)result);
|
||||
}
|
||||
else if (getIeHttpProxyError)
|
||||
{
|
||||
if (err)
|
||||
*err = string_alloc (getIeHttpProxyError, gc);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool
|
||||
get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc)
|
||||
{
|
||||
if (err)
|
||||
*err = string_alloc ("HTTP proxy detection not supported on this OS", gc);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
/* cached proxy username/password */
|
||||
static struct user_pass static_proxy_user_pass;
|
||||
@ -246,42 +197,12 @@ send_crlf (socket_descriptor_t sd)
|
||||
uint8_t *
|
||||
make_base64_string2 (const uint8_t *str, int src_len, struct gc_arena *gc)
|
||||
{
|
||||
static const char base64_table[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
uint8_t *buf;
|
||||
const uint8_t *src;
|
||||
uint8_t *dst;
|
||||
int bits, data, dst_len;
|
||||
|
||||
/* make base64 string */
|
||||
dst_len = (src_len + 2) / 3 * 4;
|
||||
buf = gc_malloc (dst_len + 1, false, gc);
|
||||
bits = data = 0;
|
||||
src = str;
|
||||
dst = buf;
|
||||
while (dst_len--)
|
||||
{
|
||||
if (bits < 6)
|
||||
{
|
||||
data = (data << 8) | *src;
|
||||
bits += 8;
|
||||
src++;
|
||||
}
|
||||
*dst++ = base64_table[0x3F & (data >> (bits - 6))];
|
||||
bits -= 6;
|
||||
}
|
||||
*dst = '\0';
|
||||
|
||||
/* fix-up tail padding */
|
||||
switch (src_len % 3)
|
||||
{
|
||||
case 1:
|
||||
*--dst = '=';
|
||||
case 2:
|
||||
*--dst = '=';
|
||||
}
|
||||
return buf;
|
||||
uint8_t *ret = NULL;
|
||||
char *b64out = NULL;
|
||||
ASSERT (base64_encode ((const void *)str, src_len, &b64out) >= 0);
|
||||
ret = (uint8_t *) string_alloc (b64out, gc);
|
||||
free (b64out);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
@ -300,18 +221,67 @@ username_password_as_base64 (const struct http_proxy_info *p,
|
||||
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)
|
||||
{
|
||||
if (!static_proxy_user_pass.defined || force)
|
||||
{
|
||||
get_user_pass (&static_proxy_user_pass,
|
||||
p->options.auth_file,
|
||||
"HTTP Proxy",
|
||||
GET_USER_PASS_MANAGEMENT);
|
||||
p->up = static_proxy_user_pass;
|
||||
}
|
||||
}
|
||||
|
||||
struct http_proxy_info *
|
||||
new_http_proxy (const struct http_proxy_options *o,
|
||||
struct auto_proxy_info *auto_proxy_info,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
struct http_proxy_info *p;
|
||||
ALLOC_OBJ_CLEAR_GC (p, struct http_proxy_info, gc);
|
||||
struct http_proxy_options opt;
|
||||
|
||||
if (!o->server)
|
||||
if (auto_proxy_info)
|
||||
{
|
||||
if (o && o->server)
|
||||
{
|
||||
/* if --http-proxy explicitly given, disable auto-proxy */
|
||||
auto_proxy_info = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if no --http-proxy explicitly given and no auto settings, fail */
|
||||
if (!auto_proxy_info->http.server)
|
||||
return NULL;
|
||||
|
||||
if (o)
|
||||
{
|
||||
opt = *o;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR (opt);
|
||||
|
||||
/* These settings are only used for --auto-proxy */
|
||||
opt.timeout = 5;
|
||||
opt.http_version = "1.0";
|
||||
}
|
||||
|
||||
opt.server = auto_proxy_info->http.server;
|
||||
opt.port = auto_proxy_info->http.port;
|
||||
opt.auth_retry = true;
|
||||
|
||||
o = &opt;
|
||||
}
|
||||
}
|
||||
|
||||
if (!o || !o->server)
|
||||
msg (M_FATAL, "HTTP_PROXY: server not specified");
|
||||
|
||||
ASSERT (legal_ipv4_port (o->port));
|
||||
|
||||
ALLOC_OBJ_CLEAR_GC (p, struct http_proxy_info, gc);
|
||||
p->options = *o;
|
||||
|
||||
/* parse authentication method */
|
||||
@ -332,11 +302,7 @@ new_http_proxy (const struct http_proxy_options *o,
|
||||
/* only basic and NTLM authentication supported so far */
|
||||
if (p->auth_method == HTTP_AUTH_BASIC || p->auth_method == HTTP_AUTH_NTLM)
|
||||
{
|
||||
get_user_pass (&static_proxy_user_pass,
|
||||
o->auth_file,
|
||||
"HTTP Proxy",
|
||||
GET_USER_PASS_MANAGEMENT);
|
||||
p->up = static_proxy_user_pass;
|
||||
get_user_pass_http (p, true);
|
||||
}
|
||||
|
||||
#if !NTLM
|
||||
@ -348,7 +314,7 @@ new_http_proxy (const struct http_proxy_options *o,
|
||||
return p;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
socket_descriptor_t sd, /* already open to proxy */
|
||||
const char *host, /* openvpn server remote */
|
||||
@ -362,6 +328,12 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
char get[80];
|
||||
int status;
|
||||
int nparms;
|
||||
bool ret = false;
|
||||
|
||||
/* get user/pass if not previously given or if --auto-proxy is being used */
|
||||
if (p->auth_method == HTTP_AUTH_BASIC
|
||||
|| p->auth_method == HTTP_AUTH_NTLM)
|
||||
get_user_pass_http (p, false);
|
||||
|
||||
/* format HTTP CONNECT message */
|
||||
openvpn_snprintf (buf, sizeof(buf), "CONNECT %s:%d HTTP/%s",
|
||||
@ -519,7 +491,21 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
ASSERT (0); /* No NTLM support */
|
||||
#endif
|
||||
}
|
||||
else goto error;
|
||||
else if (p->auth_method == HTTP_AUTH_NONE && p->options.auth_retry)
|
||||
{
|
||||
/*
|
||||
* Proxy needs authentication, but we don't have a user/pass.
|
||||
* Now we will change p->auth_method and return true so that
|
||||
* our caller knows to call us again on a newly opened socket.
|
||||
* JYFIXME: This code needs to check proxy error output and set
|
||||
* JYFIXME: p->auth_method = HTTP_AUTH_NTLM if necessary.
|
||||
*/
|
||||
p->auth_method = HTTP_AUTH_BASIC;
|
||||
ret = true;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
@ -527,7 +513,7 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
if (nparms < 1 || status != 200)
|
||||
{
|
||||
msg (D_LINK_ERRORS, "HTTP proxy returned bad status");
|
||||
#if 0
|
||||
#if 0
|
||||
/* DEBUGGING -- show a multi-line HTTP error response */
|
||||
while (true)
|
||||
{
|
||||
@ -556,17 +542,221 @@ establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
msg (M_INFO, "HTTP PROXY: lookahead: %s", format_hex (BPTR (lookahead), BLEN (lookahead), 0));
|
||||
#endif
|
||||
|
||||
done:
|
||||
gc_free (&gc);
|
||||
return;
|
||||
return ret;
|
||||
|
||||
error:
|
||||
/* on error, should we exit or restart? */
|
||||
if (!*signal_received)
|
||||
*signal_received = (p->options.retry ? SIGUSR1 : SIGTERM); /* SOFT-SIGUSR1 -- HTTP proxy error */
|
||||
gc_free (&gc);
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
static void dummy(void) {}
|
||||
#endif /* ENABLE_HTTP_PROXY */
|
||||
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#if 0
|
||||
char *
|
||||
get_windows_internet_string (const DWORD dwOption, struct gc_arena *gc)
|
||||
{
|
||||
DWORD size = 0;
|
||||
char *ret = NULL;
|
||||
|
||||
/* Initially, get size of return buffer */
|
||||
InternetQueryOption (NULL, dwOption, NULL, &size);
|
||||
if (size)
|
||||
{
|
||||
/* Now get actual info */
|
||||
ret = (INTERNET_PROXY_INFO *) gc_malloc (size, false, gc);
|
||||
if (!InternetQueryOption (NULL, dwOption, (LPVOID) ret, &size))
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static INTERNET_PROXY_INFO *
|
||||
get_windows_proxy_settings (struct gc_arena *gc)
|
||||
{
|
||||
DWORD size = 0;
|
||||
INTERNET_PROXY_INFO *ret = NULL;
|
||||
|
||||
/* Initially, get size of return buffer */
|
||||
InternetQueryOption (NULL, INTERNET_OPTION_PROXY, NULL, &size);
|
||||
if (size)
|
||||
{
|
||||
/* Now get actual info */
|
||||
ret = (INTERNET_PROXY_INFO *) gc_malloc (size, false, gc);
|
||||
if (!InternetQueryOption (NULL, INTERNET_OPTION_PROXY, (LPVOID) ret, &size))
|
||||
ret = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *
|
||||
parse_windows_proxy_setting (const char *str, struct auto_proxy_info_entry *e, struct gc_arena *gc)
|
||||
{
|
||||
char buf[128];
|
||||
const char *ret = NULL;
|
||||
struct buffer in;
|
||||
|
||||
CLEAR (*e);
|
||||
|
||||
buf_set_read (&in, (const uint8_t *)str, strlen (str));
|
||||
|
||||
if (strchr (str, '=') != NULL)
|
||||
{
|
||||
if (buf_parse (&in, '=', buf, sizeof (buf)))
|
||||
ret = string_alloc (buf, gc);
|
||||
}
|
||||
|
||||
if (buf_parse (&in, ':', buf, sizeof (buf)))
|
||||
e->server = string_alloc (buf, gc);
|
||||
|
||||
if (e->server && buf_parse (&in, '\0', buf, sizeof (buf)))
|
||||
e->port = atoi (buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_windows_proxy_setting_list (const char *str, const char *type, struct auto_proxy_info_entry *e, struct gc_arena *gc)
|
||||
{
|
||||
struct gc_arena gc_local = gc_new ();
|
||||
struct auto_proxy_info_entry el;
|
||||
|
||||
CLEAR (*e);
|
||||
if (type)
|
||||
{
|
||||
char buf[128];
|
||||
struct buffer in;
|
||||
|
||||
buf_set_read (&in, (const uint8_t *)str, strlen (str));
|
||||
if (strchr (str, '=') != NULL)
|
||||
{
|
||||
while (buf_parse (&in, ' ', buf, sizeof (buf)))
|
||||
{
|
||||
const char *t = parse_windows_proxy_setting (buf, &el, &gc_local);
|
||||
if (t && !strcmp (t, type))
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!parse_windows_proxy_setting (str, &el, &gc_local))
|
||||
goto found;
|
||||
}
|
||||
goto done;
|
||||
|
||||
found:
|
||||
if (el.server && el.port > 0)
|
||||
{
|
||||
e->server = string_alloc (el.server, gc);
|
||||
e->port = el.port;
|
||||
}
|
||||
|
||||
done:
|
||||
gc_free (&gc_local);
|
||||
}
|
||||
|
||||
static const char *
|
||||
win_proxy_access_type (const DWORD dwAccessType)
|
||||
{
|
||||
switch (dwAccessType)
|
||||
{
|
||||
case INTERNET_OPEN_TYPE_DIRECT:
|
||||
return "INTERNET_OPEN_TYPE_DIRECT";
|
||||
case INTERNET_OPEN_TYPE_PROXY:
|
||||
return "INTERNET_OPEN_TYPE_PROXY";
|
||||
default:
|
||||
return "[UNKNOWN]";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
show_win_proxy_settings (const int msglevel)
|
||||
{
|
||||
INTERNET_PROXY_INFO *info;
|
||||
struct gc_arena gc = gc_new ();
|
||||
|
||||
info = get_windows_proxy_settings (&gc);
|
||||
msg (msglevel, "PROXY INFO: %s %s",
|
||||
win_proxy_access_type (info->dwAccessType),
|
||||
info->lpszProxy ? info->lpszProxy : "[NULL]");
|
||||
|
||||
gc_free (&gc);
|
||||
}
|
||||
|
||||
struct auto_proxy_info *
|
||||
get_proxy_settings (char **err, struct gc_arena *gc)
|
||||
{
|
||||
struct gc_arena gc_local = gc_new ();
|
||||
INTERNET_PROXY_INFO *info;
|
||||
struct auto_proxy_info *pi;
|
||||
|
||||
ALLOC_OBJ_CLEAR_GC (pi, struct auto_proxy_info, gc);
|
||||
|
||||
if (err)
|
||||
*err = NULL;
|
||||
|
||||
info = get_windows_proxy_settings (&gc_local);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
if (err)
|
||||
*err = "PROXY: failed to obtain windows proxy info";
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (info->dwAccessType)
|
||||
{
|
||||
case INTERNET_OPEN_TYPE_DIRECT:
|
||||
break;
|
||||
case INTERNET_OPEN_TYPE_PROXY:
|
||||
if (!info->lpszProxy)
|
||||
break;
|
||||
parse_windows_proxy_setting_list (info->lpszProxy, NULL, &pi->http, gc);
|
||||
if (!pi->http.server)
|
||||
parse_windows_proxy_setting_list (info->lpszProxy, "http", &pi->http, gc);
|
||||
parse_windows_proxy_setting_list (info->lpszProxy, "socks", &pi->socks, gc);
|
||||
break;
|
||||
default:
|
||||
if (err)
|
||||
*err = "PROXY: unknown proxy type";
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
gc_free (&gc_local);
|
||||
return pi;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct auto_proxy_info *
|
||||
get_proxy_settings (char **err, struct gc_arena *gc)
|
||||
{
|
||||
#if 1
|
||||
if (err)
|
||||
*err = string_alloc ("PROXY: automatic detection not supported on this OS", gc);
|
||||
return NULL;
|
||||
#else /* JYFIXME, test --auto-proxy feature */
|
||||
struct auto_proxy_info *pi;
|
||||
ALLOC_OBJ_CLEAR_GC (pi, struct auto_proxy_info, gc);
|
||||
pi->http.server = "10.10.0.2";
|
||||
pi->http.port = 4000;
|
||||
return pi;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* GENERAL_PROXY_SUPPORT */
|
||||
|
37
proxy.h
37
proxy.h
@ -25,11 +25,35 @@
|
||||
#ifndef PROXY_H
|
||||
#define PROXY_H
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
#include "buffer.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
|
||||
/*
|
||||
* Return value for get_proxy_settings to automatically
|
||||
* determine proxy information.
|
||||
*/
|
||||
struct auto_proxy_info_entry {
|
||||
char *server;
|
||||
int port;
|
||||
};
|
||||
|
||||
struct auto_proxy_info {
|
||||
struct auto_proxy_info_entry http;
|
||||
struct auto_proxy_info_entry socks;
|
||||
};
|
||||
|
||||
struct auto_proxy_info *get_proxy_settings (char **err, struct gc_arena *gc);
|
||||
|
||||
#ifdef WIN32
|
||||
void show_win_proxy_settings (const int msglevel);
|
||||
#endif /* WIN32 */
|
||||
|
||||
#endif /* GENERAL_PROXY_SUPPORT */
|
||||
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
|
||||
/* HTTP CONNECT authentication methods */
|
||||
#define HTTP_AUTH_NONE 0
|
||||
#define HTTP_AUTH_BASIC 1
|
||||
@ -41,6 +65,7 @@ struct http_proxy_options {
|
||||
int port;
|
||||
bool retry;
|
||||
int timeout;
|
||||
bool auth_retry;
|
||||
const char *auth_method_string;
|
||||
const char *auth_file;
|
||||
const char *http_version;
|
||||
@ -55,9 +80,10 @@ struct http_proxy_info {
|
||||
};
|
||||
|
||||
struct http_proxy_info *new_http_proxy (const struct http_proxy_options *o,
|
||||
struct auto_proxy_info *auto_proxy_info,
|
||||
struct gc_arena *gc);
|
||||
|
||||
void establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
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 int port, /* openvpn server port */
|
||||
@ -67,7 +93,6 @@ void establish_http_proxy_passthru (struct http_proxy_info *p,
|
||||
uint8_t *make_base64_string2 (const uint8_t *str, int str_len, struct gc_arena *gc);
|
||||
uint8_t *make_base64_string (const uint8_t *str, struct gc_arena *gc);
|
||||
|
||||
bool get_http_proxy_settings (struct http_proxy_options *p, char **err, struct gc_arena *gc);
|
||||
#endif /* ENABLE_HTTP_PROXY */
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif /* PROXY_H */
|
||||
|
79
socket.c
79
socket.c
@ -1307,44 +1307,57 @@ link_socket_init_phase2 (struct link_socket *sock,
|
||||
}
|
||||
else if (sock->info.proto == PROTO_TCPv4_CLIENT)
|
||||
{
|
||||
socket_connect (&sock->sd,
|
||||
&sock->info.lsa->local,
|
||||
sock->bind_local,
|
||||
&sock->info.lsa->actual.dest,
|
||||
sock->remote_list,
|
||||
remote_dynamic,
|
||||
&remote_changed,
|
||||
sock->connect_retry_seconds,
|
||||
sock->connect_timeout,
|
||||
sock->connect_retry_max,
|
||||
signal_received);
|
||||
|
||||
if (*signal_received)
|
||||
goto done;
|
||||
#ifdef GENERAL_PROXY_SUPPORT
|
||||
bool proxy_retry = false;
|
||||
#else
|
||||
const bool proxy_retry = false;
|
||||
#endif
|
||||
do {
|
||||
socket_connect (&sock->sd,
|
||||
&sock->info.lsa->local,
|
||||
sock->bind_local,
|
||||
&sock->info.lsa->actual.dest,
|
||||
sock->remote_list,
|
||||
remote_dynamic,
|
||||
&remote_changed,
|
||||
sock->connect_retry_seconds,
|
||||
sock->connect_timeout,
|
||||
sock->connect_retry_max,
|
||||
signal_received);
|
||||
|
||||
if (false)
|
||||
;
|
||||
if (*signal_received)
|
||||
goto done;
|
||||
|
||||
if (false)
|
||||
;
|
||||
#ifdef ENABLE_HTTP_PROXY
|
||||
else if (sock->http_proxy)
|
||||
{
|
||||
establish_http_proxy_passthru (sock->http_proxy,
|
||||
sock->sd,
|
||||
sock->proxy_dest_host,
|
||||
sock->proxy_dest_port,
|
||||
&sock->stream_buf.residual,
|
||||
signal_received);
|
||||
}
|
||||
else if (sock->http_proxy)
|
||||
{
|
||||
proxy_retry = establish_http_proxy_passthru (sock->http_proxy,
|
||||
sock->sd,
|
||||
sock->proxy_dest_host,
|
||||
sock->proxy_dest_port,
|
||||
&sock->stream_buf.residual,
|
||||
signal_received);
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKS
|
||||
else if (sock->socks_proxy)
|
||||
{
|
||||
establish_socks_proxy_passthru (sock->socks_proxy,
|
||||
sock->sd,
|
||||
sock->proxy_dest_host,
|
||||
sock->proxy_dest_port,
|
||||
signal_received);
|
||||
}
|
||||
else if (sock->socks_proxy)
|
||||
{
|
||||
establish_socks_proxy_passthru (sock->socks_proxy,
|
||||
sock->sd,
|
||||
sock->proxy_dest_host,
|
||||
sock->proxy_dest_port,
|
||||
signal_received);
|
||||
}
|
||||
#endif
|
||||
if (proxy_retry)
|
||||
{
|
||||
openvpn_close_socket (sock->sd);
|
||||
sock->sd = create_socket_tcp ();
|
||||
}
|
||||
} while (proxy_retry);
|
||||
}
|
||||
#ifdef ENABLE_SOCKS
|
||||
else if (sock->info.proto == PROTO_UDPv4 && sock->socks_proxy)
|
||||
@ -1386,7 +1399,7 @@ link_socket_init_phase2 (struct link_socket *sock,
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (*signal_received)
|
||||
goto done;
|
||||
|
||||
|
15
socks.c
15
socks.c
@ -60,10 +60,25 @@ struct socks_proxy_info *
|
||||
new_socks_proxy (const char *server,
|
||||
int port,
|
||||
bool retry,
|
||||
struct auto_proxy_info *auto_proxy_info,
|
||||
struct gc_arena *gc)
|
||||
{
|
||||
struct socks_proxy_info *p;
|
||||
|
||||
if (auto_proxy_info)
|
||||
{
|
||||
if (!server)
|
||||
{
|
||||
if (!auto_proxy_info->socks.server)
|
||||
return NULL;
|
||||
|
||||
server = auto_proxy_info->socks.server;
|
||||
port = auto_proxy_info->socks.port;
|
||||
}
|
||||
}
|
||||
|
||||
ALLOC_OBJ_CLEAR_GC (p, struct socks_proxy_info, gc);
|
||||
|
||||
ASSERT (server);
|
||||
ASSERT (legal_ipv4_port (port));
|
||||
|
||||
|
1
socks.h
1
socks.h
@ -50,6 +50,7 @@ void socks_adjust_frame_parameters (struct frame *frame, int proto);
|
||||
struct socks_proxy_info *new_socks_proxy (const char *server,
|
||||
int port,
|
||||
bool retry,
|
||||
struct auto_proxy_info *auto_proxy_info,
|
||||
struct gc_arena *gc);
|
||||
|
||||
void establish_socks_proxy_passthru (struct socks_proxy_info *p,
|
||||
|
@ -266,6 +266,7 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include <iphlpapi.h>
|
||||
#include <WinInet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
@ -435,6 +436,13 @@ socket_defined (const socket_descriptor_t sd)
|
||||
#define NTLM 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Should we include code common to all proxy methods?
|
||||
*/
|
||||
#if defined(ENABLE_HTTP_PROXY) || defined(ENABLE_SOCKS)
|
||||
#define GENERAL_PROXY_SUPPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do we have PKCS11 capability?
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user