mirror of https://github.com/OpenVPN/openvpn-gui
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
640 lines
20 KiB
640 lines
20 KiB
/* |
|
* OpenVPN-GUI -- A Windows GUI for OpenVPN. |
|
* |
|
* Copyright (C) 2004 Mathias Sundman <mathias@nilings.se> |
|
* 2011 Heiko Hund <heikoh@users.sf.net> |
|
* |
|
* This program is free software; you can redistribute it and/or modify |
|
* it under the terms of the GNU General Public License as published by |
|
* the Free Software Foundation; either version 2 of the License, or |
|
* (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program (see the file COPYING included with this |
|
* distribution); if not, write to the Free Software Foundation, Inc., |
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
*/ |
|
|
|
|
|
#ifdef HAVE_CONFIG_H |
|
#include <config.h> |
|
#endif |
|
|
|
#include <windows.h> |
|
#include <windowsx.h> |
|
#include <prsht.h> |
|
#include <tchar.h> |
|
#include <winhttp.h> |
|
#include <stdlib.h> |
|
|
|
#include "main.h" |
|
#include "options.h" |
|
#include "registry.h" |
|
#include "proxy.h" |
|
#include "openvpn-gui-res.h" |
|
#include "localization.h" |
|
#include "manage.h" |
|
#include "openvpn.h" |
|
#include "misc.h" |
|
|
|
extern options_t o; |
|
|
|
INT_PTR CALLBACK |
|
ProxySettingsDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, UNUSED LPARAM lParam) |
|
{ |
|
HICON hIcon; |
|
LPPSHNOTIFY psn; |
|
|
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
hIcon = LoadLocalizedIcon(ID_ICO_APP); |
|
if (hIcon) |
|
{ |
|
SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_SMALL), (LPARAM) (hIcon)); |
|
SendMessage(hwndDlg, WM_SETICON, (WPARAM) (ICON_BIG), (LPARAM) (hIcon)); |
|
} |
|
|
|
/* Limit Port editbox to 5 chars. */ |
|
SendMessage(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), EM_SETLIMITTEXT, 5, 0); |
|
|
|
LoadProxySettings(hwndDlg); |
|
break; |
|
|
|
case WM_COMMAND: |
|
switch (LOWORD(wParam)) |
|
{ |
|
case ID_RB_PROXY_OPENVPN: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE); |
|
} |
|
break; |
|
|
|
case ID_RB_PROXY_MSIE: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), FALSE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), FALSE); |
|
} |
|
break; |
|
|
|
case ID_RB_PROXY_MANUAL: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_HTTP), TRUE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_RB_PROXY_SOCKS), TRUE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_ADDRESS), TRUE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_EDT_PROXY_PORT), TRUE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_ADDRESS), TRUE); |
|
EnableWindow(GetDlgItem(hwndDlg, ID_TXT_PROXY_PORT), TRUE); |
|
} |
|
break; |
|
|
|
case ID_RB_PROXY_HTTP: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port); |
|
} |
|
break; |
|
|
|
case ID_RB_PROXY_SOCKS: |
|
if (HIWORD(wParam) == BN_CLICKED) |
|
{ |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port); |
|
} |
|
break; |
|
} |
|
break; |
|
|
|
case WM_NOTIFY: |
|
psn = (LPPSHNOTIFY) lParam; |
|
if (psn->hdr.code == (UINT) PSN_KILLACTIVE) |
|
{ |
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (CheckProxySettings(hwndDlg) ? FALSE : TRUE)); |
|
return TRUE; |
|
} |
|
else if (psn->hdr.code == (UINT) PSN_APPLY) |
|
{ |
|
SaveProxySettings(hwndDlg); |
|
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case WM_CLOSE: |
|
EndDialog(hwndDlg, LOWORD(wParam)); |
|
return TRUE; |
|
} |
|
return FALSE; |
|
} |
|
|
|
|
|
/* Check that proxy settings are valid */ |
|
int |
|
CheckProxySettings(HWND hwndDlg) |
|
{ |
|
if (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_MANUAL) == BST_CHECKED) |
|
{ |
|
TCHAR text[100]; |
|
BOOL http = (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_HTTP) == BST_CHECKED); |
|
|
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, text, _countof(text)); |
|
if (_tcslen(text) == 0) |
|
{ |
|
/* proxy address not specified */ |
|
ShowLocalizedMsg((http ? IDS_ERR_HTTP_PROXY_ADDRESS : IDS_ERR_SOCKS_PROXY_ADDRESS)); |
|
return 0; |
|
} |
|
|
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, text, _countof(text)); |
|
if (_tcslen(text) == 0) |
|
{ |
|
/* proxy port not specified */ |
|
ShowLocalizedMsg((http ? IDS_ERR_HTTP_PROXY_PORT : IDS_ERR_SOCKS_PROXY_PORT)); |
|
return 0; |
|
} |
|
|
|
long port = _tcstol(text, NULL, 10); |
|
if ((port < 1) || (port > 65535)) |
|
{ |
|
/* proxy port range error */ |
|
ShowLocalizedMsg((http ? IDS_ERR_HTTP_PROXY_PORT_RANGE : IDS_ERR_SOCKS_PROXY_PORT_RANGE)); |
|
return 0; |
|
} |
|
} |
|
|
|
return 1; |
|
} |
|
|
|
|
|
void |
|
LoadProxySettings(HWND hwndDlg) |
|
{ |
|
/* Set Proxy type, address and port */ |
|
if (o.proxy_type == http) |
|
{ |
|
CheckRadioButton(hwndDlg, ID_RB_PROXY_HTTP, ID_RB_PROXY_SOCKS, ID_RB_PROXY_HTTP); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port); |
|
} |
|
else if (o.proxy_type == socks) |
|
{ |
|
CheckRadioButton(hwndDlg, ID_RB_PROXY_HTTP, ID_RB_PROXY_SOCKS, ID_RB_PROXY_SOCKS); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address); |
|
SetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port); |
|
} |
|
|
|
/* Set Proxy Settings Source */ |
|
if (o.proxy_source == config) |
|
{ |
|
SendMessage(GetDlgItem(hwndDlg, ID_RB_PROXY_OPENVPN), BM_CLICK, 0, 0); |
|
} |
|
else if (o.proxy_source == windows) |
|
{ |
|
SendMessage(GetDlgItem(hwndDlg, ID_RB_PROXY_MSIE), BM_CLICK, 0, 0); |
|
} |
|
else if (o.proxy_source == manual) |
|
{ |
|
SendMessage(GetDlgItem(hwndDlg, ID_RB_PROXY_MANUAL), BM_CLICK, 0, 0); |
|
} |
|
} |
|
|
|
|
|
void |
|
SaveProxySettings(HWND hwndDlg) |
|
{ |
|
HKEY regkey; |
|
DWORD dwDispos; |
|
TCHAR proxy_source_string[2] = _T("0"); |
|
TCHAR proxy_type_string[2] = _T("0"); |
|
TCHAR proxy_subkey[MAX_PATH]; |
|
|
|
/* Save Proxy Settings Source */ |
|
if (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_OPENVPN) == BST_CHECKED) |
|
{ |
|
o.proxy_source = config; |
|
proxy_source_string[0] = _T('0'); |
|
} |
|
else if (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_MSIE) == BST_CHECKED) |
|
{ |
|
o.proxy_source = windows; |
|
proxy_source_string[0] = _T('1'); |
|
} |
|
else if (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_MANUAL) == BST_CHECKED) |
|
{ |
|
o.proxy_source = manual; |
|
proxy_source_string[0] = _T('2'); |
|
} |
|
|
|
/* Save Proxy type, address and port */ |
|
if (IsDlgButtonChecked(hwndDlg, ID_RB_PROXY_HTTP) == BST_CHECKED) |
|
{ |
|
o.proxy_type = http; |
|
proxy_type_string[0] = _T('0'); |
|
|
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_http_address, |
|
_countof(o.proxy_http_address)); |
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_http_port, |
|
_countof(o.proxy_http_port)); |
|
} |
|
else |
|
{ |
|
o.proxy_type = socks; |
|
proxy_type_string[0] = _T('1'); |
|
|
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_ADDRESS, o.proxy_socks_address, |
|
_countof(o.proxy_socks_address)); |
|
GetDlgItemText(hwndDlg, ID_EDT_PROXY_PORT, o.proxy_socks_port, |
|
_countof(o.proxy_socks_port)); |
|
} |
|
|
|
/* Open Registry for writing */ |
|
_sntprintf_0(proxy_subkey, _T("%ls\\proxy"), GUI_REGKEY_HKCU); |
|
if (RegCreateKeyEx(HKEY_CURRENT_USER, proxy_subkey, 0, _T(""), REG_OPTION_NON_VOLATILE, |
|
KEY_WRITE, NULL, ®key, &dwDispos) != ERROR_SUCCESS) |
|
{ |
|
/* error creating Registry-Key */ |
|
ShowLocalizedMsg(IDS_ERR_CREATE_REG_HKCU_KEY, proxy_subkey); |
|
return; |
|
} |
|
|
|
/* Save Settings to registry */ |
|
SetRegistryValue(regkey, _T("proxy_source"), proxy_source_string); |
|
SetRegistryValue(regkey, _T("proxy_type"), proxy_type_string); |
|
SetRegistryValue(regkey, _T("proxy_http_address"), o.proxy_http_address); |
|
SetRegistryValue(regkey, _T("proxy_http_port"), o.proxy_http_port); |
|
SetRegistryValue(regkey, _T("proxy_socks_address"), o.proxy_socks_address); |
|
SetRegistryValue(regkey, _T("proxy_socks_port"), o.proxy_socks_port); |
|
|
|
RegCloseKey(regkey); |
|
} |
|
|
|
|
|
void |
|
GetProxyRegistrySettings() |
|
{ |
|
LONG status; |
|
HKEY regkey; |
|
TCHAR proxy_source_string[2] = _T("0"); |
|
TCHAR proxy_type_string[2] = _T("0"); |
|
TCHAR proxy_subkey[MAX_PATH]; |
|
|
|
/* Open Registry for reading */ |
|
_sntprintf_0(proxy_subkey, _T("%ls\\proxy"), GUI_REGKEY_HKCU); |
|
status = RegOpenKeyEx(HKEY_CURRENT_USER, proxy_subkey, 0, KEY_READ, ®key); |
|
if (status != ERROR_SUCCESS) |
|
{ |
|
return; |
|
} |
|
|
|
/* get registry settings */ |
|
GetRegistryValue(regkey, _T("proxy_http_address"), o.proxy_http_address, _countof(o.proxy_http_address)); |
|
GetRegistryValue(regkey, _T("proxy_http_port"), o.proxy_http_port, _countof(o.proxy_http_port)); |
|
GetRegistryValue(regkey, _T("proxy_socks_address"), o.proxy_socks_address, _countof(o.proxy_socks_address)); |
|
GetRegistryValue(regkey, _T("proxy_socks_port"), o.proxy_socks_port, _countof(o.proxy_socks_port)); |
|
GetRegistryValue(regkey, _T("proxy_source"), proxy_source_string, _countof(proxy_source_string)); |
|
GetRegistryValue(regkey, _T("proxy_type"), proxy_type_string, _countof(proxy_type_string)); |
|
|
|
if (proxy_source_string[0] == _T('0')) |
|
{ |
|
o.proxy_source = config; |
|
} |
|
else if (proxy_source_string[0] == _T('1')) |
|
{ |
|
o.proxy_source = windows; |
|
} |
|
else if (proxy_source_string[0] == _T('2')) |
|
{ |
|
o.proxy_source = manual; |
|
} |
|
|
|
o.proxy_type = (proxy_type_string[0] == _T('0') ? http : socks); |
|
|
|
RegCloseKey(regkey); |
|
} |
|
|
|
|
|
INT_PTR CALLBACK |
|
ProxyAuthDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) |
|
{ |
|
LPCSTR proxy_type; |
|
connection_t *c; |
|
char fmt[32]; |
|
|
|
switch (msg) |
|
{ |
|
case WM_INITDIALOG: |
|
/* Set connection for this dialog and show it */ |
|
c = (connection_t *) lParam; |
|
TRY_SETPROP(hwndDlg, cfgProp, (HANDLE) c); |
|
if (c->state == resuming) |
|
{ |
|
ForceForegroundWindow(hwndDlg); |
|
} |
|
else |
|
{ |
|
SetForegroundWindow(hwndDlg); |
|
} |
|
break; |
|
|
|
case WM_COMMAND: |
|
switch (LOWORD(wParam)) |
|
{ |
|
case ID_EDT_PROXY_USER: |
|
if (HIWORD(wParam) == EN_UPDATE) |
|
{ |
|
int len = Edit_GetTextLength((HWND) lParam); |
|
EnableWindow(GetDlgItem(hwndDlg, IDOK), (len ? TRUE : FALSE)); |
|
} |
|
break; |
|
|
|
case IDOK: |
|
c = (connection_t *) GetProp(hwndDlg, cfgProp); |
|
proxy_type = (c->proxy_type == http ? "HTTP" : "SOCKS"); |
|
|
|
snprintf(fmt, sizeof(fmt), "username \"%s Proxy\" \"%%s\"", proxy_type); |
|
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_USER); |
|
|
|
snprintf(fmt, sizeof(fmt), "password \"%s Proxy\" \"%%s\"", proxy_type); |
|
ManagementCommandFromInput(c, fmt, hwndDlg, ID_EDT_PROXY_PASS); |
|
|
|
EndDialog(hwndDlg, LOWORD(wParam)); |
|
return TRUE; |
|
} |
|
break; |
|
|
|
case WM_OVPN_STATE: /* state changed -- destroy the dialog */ |
|
EndDialog(hwndDlg, LOWORD(wParam)); |
|
return TRUE; |
|
|
|
case WM_CLOSE: |
|
EndDialog(hwndDlg, LOWORD(wParam)); |
|
return TRUE; |
|
|
|
case WM_NCDESTROY: |
|
RemoveProp(hwndDlg, cfgProp); |
|
break; |
|
} |
|
return FALSE; |
|
} |
|
|
|
|
|
void |
|
QueryProxyAuth(connection_t *c, proxy_t type) |
|
{ |
|
c->proxy_type = type; |
|
LocalizedDialogBoxParamEx(ID_DLG_PROXY_AUTH, c->hwndStatus, ProxyAuthDialogFunc, (LPARAM) c); |
|
} |
|
|
|
|
|
typedef enum { HTTPS_URL, SOCKS_URL } url_scheme; |
|
static LPCWSTR |
|
UrlSchemeStr(const url_scheme scheme) |
|
{ |
|
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"%ls://%hs", UrlSchemeStr(scheme), host) + 1; |
|
LPWSTR url = malloc(size * sizeof(WCHAR)); |
|
if (url) |
|
{ |
|
_snwprintf(url, size, L"%ls://%hs", 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) |
|
{ |
|
if (proxy_str == NULL) |
|
{ |
|
return; |
|
} |
|
|
|
LPCWSTR delim = L"; "; |
|
LPWSTR ctx = NULL; |
|
LPWSTR token = wcstok_s(proxy_str, delim, &ctx); |
|
|
|
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_s(NULL, delim, &ctx); |
|
} |
|
} |
|
|
|
|
|
/* |
|
* 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 && streq(proto, "TCP")) |
|
{ |
|
type = "HTTP"; |
|
addr = o.proxy_http_address; |
|
port = o.proxy_http_port; |
|
} |
|
else if (o.proxy_type == socks) |
|
{ |
|
type = "SOCKS"; |
|
addr = o.proxy_socks_address; |
|
port = o.proxy_socks_port; |
|
} |
|
} |
|
else if (o.proxy_source == windows) |
|
{ |
|
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 %ls %ls", type, addr, port); |
|
cmd[sizeof(cmd) - 1] = '\0'; |
|
ManagementCommand(c, cmd, NULL, regular); |
|
|
|
GlobalFree(proxy_str); |
|
}
|
|
|