mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// 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 Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
// proxy settings for Windows
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WinInet.h>
|
||||
|
||||
#include <openvpn\win\impersonate.hpp>
|
||||
#include <openvpn\tun\proxy.hpp>
|
||||
#include <openvpn\win\reg.hpp>
|
||||
|
||||
using namespace openvpn::Win;
|
||||
|
||||
namespace openvpn {
|
||||
namespace TunWin {
|
||||
class WinProxySettings : public ProxySettings {
|
||||
public:
|
||||
typedef RCPtr<WinProxySettings> Ptr;
|
||||
|
||||
WinProxySettings(const TunBuilderCapture::ProxyAutoConfigURL& config_arg)
|
||||
: ProxySettings(config_arg) { }
|
||||
|
||||
void set_proxy(bool del) override
|
||||
{
|
||||
Impersonate imp{false};
|
||||
|
||||
LONG status;
|
||||
RegKey hkcu;
|
||||
RegKey key;
|
||||
|
||||
status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
|
||||
check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
|
||||
|
||||
status = ::RegCreateKeyExA(hkcu(), key_name, 0, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, key.ref(), NULL);
|
||||
check_reg_error<proxy_error>(status, key_name);
|
||||
|
||||
if (!del)
|
||||
{
|
||||
save_key(key, "AutoConfigURL", config.url, true);
|
||||
save_key(key, "ProxyEnable", "0", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
restore_key(key, "AutoConfigURL", true);
|
||||
restore_key(key, "ProxyEnable", false);
|
||||
}
|
||||
|
||||
// WinInet API cannot be called from service, even via impersonation
|
||||
if (!imp.is_local_system())
|
||||
{
|
||||
OPENVPN_LOG("Refresh proxy settings");
|
||||
|
||||
InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
|
||||
InternetSetOptionA(NULL, INTERNET_OPTION_REFRESH, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void restore_key(Win::RegKey& regkey, const std::string& key, bool str)
|
||||
{
|
||||
LONG status;
|
||||
char prev_val_str[1024] = { 0 }; // should be enough to fit proxy URL
|
||||
DWORD prev_val_dword;
|
||||
DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword);
|
||||
bool del = false;
|
||||
Win::RegKey hkcu;
|
||||
|
||||
status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
|
||||
check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
|
||||
|
||||
// get previous value
|
||||
std::string prev_key_name = sname + key;
|
||||
status = ::RegGetValueA(hkcu(),
|
||||
key_name,
|
||||
prev_key_name.c_str(),
|
||||
str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword,
|
||||
&prev_buf_size);
|
||||
check_reg_error<proxy_error>(status, prev_key_name);
|
||||
|
||||
RegDeleteValueA(regkey(), prev_key_name.c_str());
|
||||
|
||||
// check if previous value needs to be deleted
|
||||
if (str)
|
||||
del = strcmp(delete_value_str, prev_val_str) == 0;
|
||||
else
|
||||
del = prev_val_dword == delete_value_dword;
|
||||
|
||||
if (del)
|
||||
::RegDeleteValueA(regkey(), key.c_str());
|
||||
else
|
||||
::RegSetValueExA(regkey(),
|
||||
key.c_str(),
|
||||
0,
|
||||
str ? REG_SZ : REG_DWORD,
|
||||
str ? (const BYTE *)prev_val_str : (CONST BYTE *)&prev_val_dword,
|
||||
str ? strlen(prev_val_str) + 1 : sizeof(prev_val_dword));
|
||||
}
|
||||
|
||||
void save_key(Win::RegKey& regkey, const std::string& key, const std::string& value, bool str)
|
||||
{
|
||||
LONG status;
|
||||
char prev_val_str[1024] = { 0 }; // should be enought to fit proxy URL
|
||||
DWORD prev_val_dword;
|
||||
DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword);
|
||||
Win::RegKey hkcu;
|
||||
|
||||
status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
|
||||
check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
|
||||
|
||||
// get original value
|
||||
status = ::RegGetValueA(hkcu(),
|
||||
key_name,
|
||||
key.c_str(),
|
||||
str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD,
|
||||
NULL,
|
||||
str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword,
|
||||
&prev_buf_size);
|
||||
switch (status)
|
||||
{
|
||||
case ERROR_FILE_NOT_FOUND:
|
||||
// mark that original value doesn't exist
|
||||
strcpy(prev_val_str, delete_value_str);
|
||||
prev_val_dword = delete_value_dword;
|
||||
case ERROR_SUCCESS:
|
||||
break;
|
||||
default:
|
||||
check_reg_error<proxy_error>(status, key);
|
||||
break;
|
||||
}
|
||||
|
||||
// save original value
|
||||
std::string prev_key_name = sname + key;
|
||||
status = ::RegSetValueExA(regkey(),
|
||||
prev_key_name.c_str(),
|
||||
0,
|
||||
str ? REG_SZ : REG_DWORD,
|
||||
str ? (const BYTE *)prev_val_str : (CONST BYTE *)&prev_val_dword,
|
||||
str ? strlen(prev_val_str) + 1 : sizeof(DWORD));
|
||||
check_reg_error<proxy_error>(status, prev_key_name);
|
||||
|
||||
// save new value
|
||||
DWORD val_dword = 0;
|
||||
if (!str)
|
||||
val_dword = std::atol(value.c_str());
|
||||
status = ::RegSetValueExA(regkey(),
|
||||
key.c_str(),
|
||||
0,
|
||||
str ? REG_SZ : REG_DWORD,
|
||||
str ? (const BYTE *)value.c_str() : (CONST BYTE *)&val_dword,
|
||||
str ? value.length() + 1 : sizeof(val_dword));
|
||||
check_reg_error<proxy_error>(status, key);
|
||||
}
|
||||
|
||||
const char* key_name = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
|
||||
const char* delete_value_str = "DeleteValue";
|
||||
const DWORD delete_value_dword = 0xCAFEBABE;
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user