mirror of https://github.com/OpenVPN/openvpn-gui
supply system proxy settings to management itf
Proxy settings are fetched from the users Internet Options for the active connection. If WPAD or a PAC script is configured they are preferred and used for automatic proxy detection. Proxy bypass configuration is completely ignored.pull/1/head
parent
2156479232
commit
e84834a08a
|
@ -91,7 +91,8 @@ openvpn_gui_LDADD = \
|
|||
openvpn-gui-res.o \
|
||||
$(OPENSSL_CRYPTO_LIBS) \
|
||||
-lws2_32 \
|
||||
-lcomctl32
|
||||
-lcomctl32 \
|
||||
-lwinhttp
|
||||
|
||||
openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h
|
||||
$(RCCOMPILE) -i $< -o $@
|
||||
|
|
1
main.c
1
main.c
|
@ -105,6 +105,7 @@ int WINAPI _tWinMain (HINSTANCE hThisInstance,
|
|||
{ log, OnLogLine },
|
||||
{ state, OnStateChange },
|
||||
{ password, OnPassword },
|
||||
{ proxy, OnProxy },
|
||||
{ stop, OnStop },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
|
5
manage.c
5
manage.c
|
@ -256,6 +256,11 @@ OnManagement(SOCKET sk, LPARAM lParam)
|
|||
if (rtmsg_handler[password])
|
||||
rtmsg_handler[password](c, pos + 9);
|
||||
}
|
||||
else if (strncmp(pos, "PROXY:", 6) == 0)
|
||||
{
|
||||
if (rtmsg_handler[proxy])
|
||||
rtmsg_handler[proxy](c, pos + 6);
|
||||
}
|
||||
else if (strncmp(pos, "INFO:", 5) == 0)
|
||||
{
|
||||
/* delay until management interface accepts input */
|
||||
|
|
1
manage.h
1
manage.h
|
@ -34,6 +34,7 @@ typedef enum {
|
|||
hold,
|
||||
log,
|
||||
password,
|
||||
proxy,
|
||||
state,
|
||||
needok,
|
||||
needstr,
|
||||
|
|
21
misc.c
21
misc.c
|
@ -102,3 +102,24 @@ ManagementCommandFromInput(connection_t *c, LPSTR fmt, HWND hDlg, int id)
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Various string helper functions
|
||||
*/
|
||||
BOOL
|
||||
streq(LPCSTR str1, LPCSTR str2)
|
||||
{
|
||||
return (strcmp(str1, str2) == 0);
|
||||
}
|
||||
|
||||
BOOL
|
||||
wcsbegins(LPCWSTR str, LPCWSTR begin)
|
||||
{
|
||||
return (wcsncmp(str, begin, wcslen(begin)) == 0);
|
||||
}
|
||||
|
||||
BOOL
|
||||
wcseq(LPCWSTR str1, LPCWSTR str2)
|
||||
{
|
||||
return (wcscmp(str1, str2) == 0);
|
||||
}
|
||||
|
|
4
misc.h
4
misc.h
|
@ -24,4 +24,8 @@
|
|||
|
||||
BOOL ManagementCommandFromInput(connection_t *, LPSTR, HWND, int);
|
||||
|
||||
BOOL streq(LPCSTR, LPCSTR);
|
||||
BOOL wcsbegins(LPCWSTR, LPCWSTR);
|
||||
BOOL wcseq(LPCWSTR, LPCWSTR);
|
||||
|
||||
#endif
|
||||
|
|
17
openvpn.c
17
openvpn.c
|
@ -621,7 +621,6 @@ StartOpenVPN(connection_t *c)
|
|||
{
|
||||
TCHAR cmdline[1024];
|
||||
TCHAR *options = cmdline + 8;
|
||||
TCHAR proxy_string[100];
|
||||
TCHAR exit_event_name[17];
|
||||
HANDLE hStdInRead = NULL, hStdInWrite = NULL;
|
||||
HANDLE hNul = NULL, hThread = NULL, service = NULL;
|
||||
|
@ -659,18 +658,14 @@ StartOpenVPN(connection_t *c)
|
|||
/* Create a management interface password */
|
||||
GetRandomPassword(c->manage.password, sizeof(c->manage.password) - 1);
|
||||
|
||||
/* Construct proxy string to append to command line */
|
||||
ConstructProxyCmdLine(proxy_string, _countof(proxy_string));
|
||||
|
||||
/* Construct command line */
|
||||
_sntprintf_0(cmdline, _T("openvpn "
|
||||
"--config \"%s\" %s --service %s 0 --log%s \"%s\" "
|
||||
"--management %S %hd stdin --auth-retry interact "
|
||||
"--management-hold --management-query-passwords --tls-exit"),
|
||||
c->config_file, proxy_string, exit_event_name,
|
||||
(o.append_string[0] == '1' ? _T("-append") : _T("")),
|
||||
c->log_path, inet_ntoa(c->manage.skaddr.sin_addr),
|
||||
ntohs(c->manage.skaddr.sin_port));
|
||||
"--config \"%s\" --service %s 0 --log%s \"%s\" --auth-retry interact "
|
||||
"--management %S %hd stdin --management-query-passwords %s"
|
||||
"--management-hold --tls-exit"), c->config_file, exit_event_name,
|
||||
(o.append_string[0] == '1' ? _T("-append") : _T("")), c->log_path,
|
||||
inet_ntoa(c->manage.skaddr.sin_addr), ntohs(c->manage.skaddr.sin_port),
|
||||
(o.proxy_source != config ? _T("--management-query-proxy ") : _T("")));
|
||||
|
||||
/* Try to open the service pipe */
|
||||
service = CreateFile(_T("\\\\.\\pipe\\openvpn\\service"),
|
||||
|
|
207
proxy.c
207
proxy.c
|
@ -28,7 +28,7 @@
|
|||
#include <windows.h>
|
||||
#include <prsht.h>
|
||||
#include <tchar.h>
|
||||
#include <wininet.h>
|
||||
#include <winhttp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "main.h"
|
||||
|
@ -361,28 +361,211 @@ ProxyAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Construct the proxy options to append to the cmd-line.
|
||||
*/
|
||||
void ConstructProxyCmdLine(TCHAR *proxy_string, unsigned int size)
|
||||
typedef enum { HTTPS_URL, SOCKS_URL } url_scheme;
|
||||
static LPCWSTR
|
||||
UrlSchemeStr(const url_scheme scheme)
|
||||
{
|
||||
proxy_string[0] = _T('\0');
|
||||
static LPCWSTR scheme_strings[] = { L"https", L"socks" };
|
||||
return scheme_strings[scheme];
|
||||
}
|
||||
|
||||
|
||||
static LPWSTR
|
||||
QueryWindowsProxySettings(const url_scheme scheme, LPCSTR host)
|
||||
{
|
||||
LPWSTR proxy = NULL;
|
||||
BOOL auto_detect = TRUE;
|
||||
LPWSTR auto_config_url = NULL;
|
||||
WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxy_config;
|
||||
|
||||
if (WinHttpGetIEProxyConfigForCurrentUser(&proxy_config))
|
||||
{
|
||||
proxy = proxy_config.lpszProxy;
|
||||
auto_detect = proxy_config.fAutoDetect;
|
||||
auto_config_url = proxy_config.lpszAutoConfigUrl;
|
||||
GlobalFree(proxy_config.lpszProxyBypass);
|
||||
}
|
||||
|
||||
if (auto_detect)
|
||||
{
|
||||
LPWSTR old_url = auto_config_url;
|
||||
DWORD flags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
|
||||
if (WinHttpDetectAutoProxyConfigUrl(flags, &auto_config_url))
|
||||
GlobalFree(old_url);
|
||||
}
|
||||
|
||||
if (auto_config_url)
|
||||
{
|
||||
HINTERNET session = WinHttpOpen(NULL, WINHTTP_ACCESS_TYPE_NO_PROXY,
|
||||
WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||
if (session)
|
||||
{
|
||||
int size = _snwprintf(NULL, 0, L"%s://%S", UrlSchemeStr(scheme), host) + 1;
|
||||
LPWSTR url = malloc(size * sizeof(WCHAR));
|
||||
if (url)
|
||||
{
|
||||
_snwprintf(url, size, L"%s://%S", UrlSchemeStr(scheme), host);
|
||||
|
||||
LPWSTR old_proxy = proxy;
|
||||
WINHTTP_PROXY_INFO proxy_info;
|
||||
WINHTTP_AUTOPROXY_OPTIONS options = {
|
||||
.fAutoLogonIfChallenged = TRUE,
|
||||
.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL,
|
||||
.lpszAutoConfigUrl = auto_config_url,
|
||||
.dwAutoDetectFlags = 0,
|
||||
.lpvReserved = NULL,
|
||||
.dwReserved = 0
|
||||
};
|
||||
|
||||
if (WinHttpGetProxyForUrl(session, url, &options, &proxy_info))
|
||||
{
|
||||
GlobalFree(old_proxy);
|
||||
GlobalFree(proxy_info.lpszProxyBypass);
|
||||
proxy = proxy_info.lpszProxy;
|
||||
}
|
||||
free(url);
|
||||
}
|
||||
WinHttpCloseHandle(session);
|
||||
}
|
||||
GlobalFree(auto_config_url);
|
||||
}
|
||||
|
||||
return proxy;
|
||||
}
|
||||
|
||||
|
||||
static VOID
|
||||
ParseProxyString(LPWSTR proxy_str, url_scheme scheme,
|
||||
LPCSTR *type, LPCWSTR *host, LPCWSTR *port)
|
||||
{
|
||||
LPCWSTR delim = L"; ";
|
||||
LPWSTR token = wcstok(proxy_str, delim);
|
||||
|
||||
LPCWSTR scheme_str = UrlSchemeStr(scheme);
|
||||
LPCWSTR socks_str = UrlSchemeStr(SOCKS_URL);
|
||||
|
||||
/* Token format: [<scheme>=][<scheme>"://"]<server>[":"<port>] */
|
||||
while (token)
|
||||
{
|
||||
BOOL match = FALSE;
|
||||
LPWSTR eq = wcschr(token, '=');
|
||||
LPWSTR css = wcsstr(token, L"://");
|
||||
|
||||
/*
|
||||
* If the token has a <scheme>, test for the one we're looking for.
|
||||
* If we're looking for a https proxy, socks will also do.
|
||||
* If it's a proxy without a <scheme> it's only good for https.
|
||||
*/
|
||||
if (eq || css)
|
||||
{
|
||||
if (wcsbegins(token, scheme_str))
|
||||
{
|
||||
match = TRUE;
|
||||
}
|
||||
else if (scheme == HTTPS_URL && wcsbegins(token, socks_str))
|
||||
{
|
||||
match = TRUE;
|
||||
scheme = SOCKS_URL;
|
||||
}
|
||||
}
|
||||
else if (scheme == HTTPS_URL)
|
||||
{
|
||||
match = TRUE;
|
||||
}
|
||||
|
||||
if (match)
|
||||
{
|
||||
LPWSTR server = token;
|
||||
if (css)
|
||||
server = css + 3;
|
||||
else if (eq)
|
||||
server = eq + 1;
|
||||
|
||||
/* IPv6 addresses are surrounded by brackets */
|
||||
LPWSTR port_delim;
|
||||
if (server[0] == '[')
|
||||
{
|
||||
server += 1;
|
||||
LPWSTR end = wcschr(server, ']');
|
||||
if (end == NULL)
|
||||
continue;
|
||||
*end++ = '\0';
|
||||
|
||||
port_delim = (*end == ':' ? end : NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
port_delim = wcsrchr(server, ':');
|
||||
if (port_delim)
|
||||
*port_delim = '\0';
|
||||
}
|
||||
|
||||
*type = (scheme == HTTPS_URL ? "HTTP" : "SOCKS");
|
||||
*host = server;
|
||||
if (port_delim)
|
||||
*port = port_delim + 1;
|
||||
else
|
||||
*port = (scheme == HTTPS_URL ? L"80": L"1080");
|
||||
|
||||
break;
|
||||
}
|
||||
token = wcstok(NULL, delim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Respond to management interface PROXY notifications
|
||||
* Input format: REMOTE_NO,PROTOCOL,HOST
|
||||
*/
|
||||
void
|
||||
OnProxy(connection_t *c, char *line)
|
||||
{
|
||||
LPSTR proto, host;
|
||||
char *pos = strchr(line, ',');
|
||||
if (pos == NULL)
|
||||
return;
|
||||
|
||||
proto = ++pos;
|
||||
pos = strchr(pos, ',');
|
||||
if (pos == NULL)
|
||||
return;
|
||||
|
||||
*pos = '\0';
|
||||
host = ++pos;
|
||||
if (host[0] == '\0')
|
||||
return;
|
||||
|
||||
LPCSTR type = "NONE";
|
||||
LPCWSTR addr = L"", port = L"";
|
||||
LPWSTR proxy_str = NULL;
|
||||
|
||||
if (o.proxy_source == manual)
|
||||
{
|
||||
if (o.proxy_type == http)
|
||||
if (o.proxy_type == http && streq(proto, "TCP"))
|
||||
{
|
||||
__sntprintf_0(proxy_string, size, _T(" --http-proxy %s %s auto"),
|
||||
o.proxy_http_address, o.proxy_http_port);
|
||||
type = "HTTP";
|
||||
addr = o.proxy_http_address;
|
||||
port = o.proxy_http_port;
|
||||
}
|
||||
else if (o.proxy_type == socks)
|
||||
{
|
||||
__sntprintf_0(proxy_string, size, _T(" --socks-proxy %s %s"),
|
||||
o.proxy_socks_address, o.proxy_socks_port);
|
||||
type = "SOCKS";
|
||||
addr = o.proxy_socks_address;
|
||||
port = o.proxy_socks_port;
|
||||
}
|
||||
}
|
||||
else if (o.proxy_source == windows)
|
||||
{
|
||||
__sntprintf_0(proxy_string, size, _T(" --auto-proxy"));
|
||||
url_scheme scheme = (streq(proto, "TCP") ? HTTPS_URL : SOCKS_URL);
|
||||
proxy_str = QueryWindowsProxySettings(scheme, host);
|
||||
ParseProxyString(proxy_str, scheme, &type, &addr, &port);
|
||||
}
|
||||
|
||||
char cmd[128];
|
||||
snprintf(cmd, sizeof(cmd), "proxy %s %S %S", type, addr, port);
|
||||
cmd[sizeof(cmd) - 1] = '\0';
|
||||
ManagementCommand(c, cmd, NULL, regular);
|
||||
|
||||
GlobalFree(proxy_str);
|
||||
}
|
||||
|
|
19
proxy.h
19
proxy.h
|
@ -19,10 +19,17 @@
|
|||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
INT_PTR CALLBACK ProxySettingsDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
int CheckProxySettings(HWND hwndDlg);
|
||||
void LoadProxySettings(HWND hwndDlg);
|
||||
void SaveProxySettings(HWND hwndDlg);
|
||||
#ifndef PROXY_H
|
||||
#define PROXY_H
|
||||
|
||||
INT_PTR CALLBACK ProxySettingsDialogFunc(HWND, UINT, WPARAM, LPARAM);
|
||||
INT_PTR CALLBACK ProxyAuthDialogFunc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
void OnProxy(connection_t *, char *);
|
||||
|
||||
int CheckProxySettings(HWND);
|
||||
void LoadProxySettings(HWND);
|
||||
void SaveProxySettings(HWND);
|
||||
void GetProxyRegistrySettings();
|
||||
INT_PTR CALLBACK ProxyAuthDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
void ConstructProxyCmdLine(TCHAR *proxy_string_ptr, unsigned int size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue