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 \
|
openvpn-gui-res.o \
|
||||||
$(OPENSSL_CRYPTO_LIBS) \
|
$(OPENSSL_CRYPTO_LIBS) \
|
||||||
-lws2_32 \
|
-lws2_32 \
|
||||||
-lcomctl32
|
-lcomctl32 \
|
||||||
|
-lwinhttp
|
||||||
|
|
||||||
openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h
|
openvpn-gui-res.o: $(openvpn_gui_RESOURCES) $(srcdir)/openvpn-gui-res.h
|
||||||
$(RCCOMPILE) -i $< -o $@
|
$(RCCOMPILE) -i $< -o $@
|
||||||
|
|
1
main.c
1
main.c
|
@ -105,6 +105,7 @@ int WINAPI _tWinMain (HINSTANCE hThisInstance,
|
||||||
{ log, OnLogLine },
|
{ log, OnLogLine },
|
||||||
{ state, OnStateChange },
|
{ state, OnStateChange },
|
||||||
{ password, OnPassword },
|
{ password, OnPassword },
|
||||||
|
{ proxy, OnProxy },
|
||||||
{ stop, OnStop },
|
{ stop, OnStop },
|
||||||
{ 0, NULL }
|
{ 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
5
manage.c
5
manage.c
|
@ -256,6 +256,11 @@ OnManagement(SOCKET sk, LPARAM lParam)
|
||||||
if (rtmsg_handler[password])
|
if (rtmsg_handler[password])
|
||||||
rtmsg_handler[password](c, pos + 9);
|
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)
|
else if (strncmp(pos, "INFO:", 5) == 0)
|
||||||
{
|
{
|
||||||
/* delay until management interface accepts input */
|
/* delay until management interface accepts input */
|
||||||
|
|
1
manage.h
1
manage.h
|
@ -34,6 +34,7 @@ typedef enum {
|
||||||
hold,
|
hold,
|
||||||
log,
|
log,
|
||||||
password,
|
password,
|
||||||
|
proxy,
|
||||||
state,
|
state,
|
||||||
needok,
|
needok,
|
||||||
needstr,
|
needstr,
|
||||||
|
|
21
misc.c
21
misc.c
|
@ -102,3 +102,24 @@ ManagementCommandFromInput(connection_t *c, LPSTR fmt, HWND hDlg, int id)
|
||||||
return retval;
|
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 ManagementCommandFromInput(connection_t *, LPSTR, HWND, int);
|
||||||
|
|
||||||
|
BOOL streq(LPCSTR, LPCSTR);
|
||||||
|
BOOL wcsbegins(LPCWSTR, LPCWSTR);
|
||||||
|
BOOL wcseq(LPCWSTR, LPCWSTR);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
17
openvpn.c
17
openvpn.c
|
@ -621,7 +621,6 @@ StartOpenVPN(connection_t *c)
|
||||||
{
|
{
|
||||||
TCHAR cmdline[1024];
|
TCHAR cmdline[1024];
|
||||||
TCHAR *options = cmdline + 8;
|
TCHAR *options = cmdline + 8;
|
||||||
TCHAR proxy_string[100];
|
|
||||||
TCHAR exit_event_name[17];
|
TCHAR exit_event_name[17];
|
||||||
HANDLE hStdInRead = NULL, hStdInWrite = NULL;
|
HANDLE hStdInRead = NULL, hStdInWrite = NULL;
|
||||||
HANDLE hNul = NULL, hThread = NULL, service = NULL;
|
HANDLE hNul = NULL, hThread = NULL, service = NULL;
|
||||||
|
@ -659,18 +658,14 @@ StartOpenVPN(connection_t *c)
|
||||||
/* Create a management interface password */
|
/* Create a management interface password */
|
||||||
GetRandomPassword(c->manage.password, sizeof(c->manage.password) - 1);
|
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 */
|
/* Construct command line */
|
||||||
_sntprintf_0(cmdline, _T("openvpn "
|
_sntprintf_0(cmdline, _T("openvpn "
|
||||||
"--config \"%s\" %s --service %s 0 --log%s \"%s\" "
|
"--config \"%s\" --service %s 0 --log%s \"%s\" --auth-retry interact "
|
||||||
"--management %S %hd stdin --auth-retry interact "
|
"--management %S %hd stdin --management-query-passwords %s"
|
||||||
"--management-hold --management-query-passwords --tls-exit"),
|
"--management-hold --tls-exit"), c->config_file, exit_event_name,
|
||||||
c->config_file, proxy_string, exit_event_name,
|
(o.append_string[0] == '1' ? _T("-append") : _T("")), c->log_path,
|
||||||
(o.append_string[0] == '1' ? _T("-append") : _T("")),
|
inet_ntoa(c->manage.skaddr.sin_addr), ntohs(c->manage.skaddr.sin_port),
|
||||||
c->log_path, inet_ntoa(c->manage.skaddr.sin_addr),
|
(o.proxy_source != config ? _T("--management-query-proxy ") : _T("")));
|
||||||
ntohs(c->manage.skaddr.sin_port));
|
|
||||||
|
|
||||||
/* Try to open the service pipe */
|
/* Try to open the service pipe */
|
||||||
service = CreateFile(_T("\\\\.\\pipe\\openvpn\\service"),
|
service = CreateFile(_T("\\\\.\\pipe\\openvpn\\service"),
|
||||||
|
|
207
proxy.c
207
proxy.c
|
@ -28,7 +28,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <prsht.h>
|
#include <prsht.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <wininet.h>
|
#include <winhttp.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
@ -361,28 +361,211 @@ ProxyAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
typedef enum { HTTPS_URL, SOCKS_URL } url_scheme;
|
||||||
* Construct the proxy options to append to the cmd-line.
|
static LPCWSTR
|
||||||
*/
|
UrlSchemeStr(const url_scheme scheme)
|
||||||
void ConstructProxyCmdLine(TCHAR *proxy_string, unsigned int size)
|
|
||||||
{
|
{
|
||||||
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_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"),
|
type = "HTTP";
|
||||||
o.proxy_http_address, o.proxy_http_port);
|
addr = o.proxy_http_address;
|
||||||
|
port = o.proxy_http_port;
|
||||||
}
|
}
|
||||||
else if (o.proxy_type == socks)
|
else if (o.proxy_type == socks)
|
||||||
{
|
{
|
||||||
__sntprintf_0(proxy_string, size, _T(" --socks-proxy %s %s"),
|
type = "SOCKS";
|
||||||
o.proxy_socks_address, o.proxy_socks_port);
|
addr = o.proxy_socks_address;
|
||||||
|
port = o.proxy_socks_port;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (o.proxy_source == windows)
|
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
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
INT_PTR CALLBACK ProxySettingsDialogFunc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
|
#ifndef PROXY_H
|
||||||
int CheckProxySettings(HWND hwndDlg);
|
#define PROXY_H
|
||||||
void LoadProxySettings(HWND hwndDlg);
|
|
||||||
void SaveProxySettings(HWND hwndDlg);
|
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();
|
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