OpenVPN 3 Core Library
Loading...
Searching...
No Matches
winproxy.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11//
12
13// proxy settings for Windows
14
15#pragma once
16
17#include <wininet.h>
18
20#include <openvpn/tun/proxy.hpp>
21#include <openvpn/win/reg.hpp>
22
23using namespace openvpn::Win;
24
25namespace openvpn::TunWin {
27{
28 public:
30
32 : ProxySettings(config_arg)
33 {
34 }
35
36 void set_proxy(bool del) override
37 {
38 Impersonate imp{false};
39
40 LONG status;
41 Reg::Key hkcu;
42 Reg::Key key;
43
44 status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
45 check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
46
47 status = ::RegCreateKeyExA(hkcu(), key_name, 0, NULL, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, key.ref(), NULL);
48 check_reg_error<proxy_error>(status, key_name);
49
50 if (!del)
51 {
52 save_key(key, "AutoConfigURL", config.url, true);
53 save_key(key, "ProxyEnable", "0", false);
54 }
55 else
56 {
57 restore_key(key, "AutoConfigURL", true);
58 restore_key(key, "ProxyEnable", false);
59 }
60
61 // WinInet API cannot be called from service, even via impersonation
62 if (!imp.is_local_system())
63 {
64 OPENVPN_LOG("Refresh proxy settings");
65
66 InternetSetOptionA(NULL, INTERNET_OPTION_SETTINGS_CHANGED, NULL, 0);
67 InternetSetOptionA(NULL, INTERNET_OPTION_REFRESH, NULL, 0);
68 }
69 }
70
71 private:
72 void restore_key(Win::Reg::Key &regkey, const std::string &key, bool str)
73 {
74 LONG status;
75 char prev_val_str[1024] = {0}; // should be enough to fit proxy URL
76 DWORD prev_val_dword;
77 DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword);
78 bool del = false;
79 Win::Reg::Key hkcu;
80
81 status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
82 check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
83
84 // get previous value
85 std::string prev_key_name = sname + key;
86 status = ::RegGetValueA(hkcu(),
88 prev_key_name.c_str(),
89 str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD,
90 NULL,
91 str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword,
92 &prev_buf_size);
93 check_reg_error<proxy_error>(status, prev_key_name);
94
95 RegDeleteValueA(regkey(), prev_key_name.c_str());
96
97 // check if previous value needs to be deleted
98 if (str)
99 del = strcmp(delete_value_str, prev_val_str) == 0;
100 else
101 del = prev_val_dword == delete_value_dword;
102
103 if (del)
104 ::RegDeleteValueA(regkey(), key.c_str());
105 else
106 ::RegSetValueExA(regkey(),
107 key.c_str(),
108 0,
109 str ? REG_SZ : REG_DWORD,
110 str ? reinterpret_cast<const BYTE *>(prev_val_str) : reinterpret_cast<CONST BYTE *>(&prev_val_dword),
111 str ? static_cast<DWORD>(strlen(prev_val_str) + 1) : sizeof(prev_val_dword));
112 }
113
114 void save_key(Win::Reg::Key &regkey, const std::string &key, const std::string &value, bool str)
115 {
116 LONG status;
117 char prev_val_str[1024] = {0}; // should be enought to fit proxy URL
118 DWORD prev_val_dword;
119 DWORD prev_buf_size = str ? sizeof(prev_val_str) : sizeof(prev_val_dword);
120 Win::Reg::Key hkcu;
121
122 status = ::RegOpenCurrentUser(KEY_QUERY_VALUE | KEY_SET_VALUE, hkcu.ref());
123 check_reg_error<proxy_error>(status, "RegOpenCurrentUser");
124
125 // get original value
126 status = ::RegGetValueA(hkcu(),
127 key_name,
128 key.c_str(),
129 str ? RRF_RT_REG_SZ : RRF_RT_REG_DWORD,
130 NULL,
131 str ? (PVOID)prev_val_str : (PVOID)&prev_val_dword,
132 &prev_buf_size);
133 switch (status)
134 {
135 case ERROR_FILE_NOT_FOUND:
136 // mark that original value doesn't exist
137 strcpy(prev_val_str, delete_value_str);
138 prev_val_dword = delete_value_dword;
139 case ERROR_SUCCESS:
140 break;
141 default:
142 check_reg_error<proxy_error>(status, key);
143 break;
144 }
145
146 // save original value
147 std::string prev_key_name = sname + key;
148 status = ::RegSetValueExA(regkey(),
149 prev_key_name.c_str(),
150 0,
151 str ? REG_SZ : REG_DWORD,
152 str ? reinterpret_cast<const BYTE *>(prev_val_str) : reinterpret_cast<CONST BYTE *>(&prev_val_dword),
153 str ? static_cast<DWORD>(strlen(prev_val_str) + 1) : sizeof(prev_val_dword));
154 check_reg_error<proxy_error>(status, prev_key_name);
155
156 // save new value
157 DWORD val_dword = 0;
158 if (!str)
159 val_dword = std::atol(value.c_str());
160 status = ::RegSetValueExA(regkey(),
161 key.c_str(),
162 0,
163 str ? REG_SZ : REG_DWORD,
164 str ? reinterpret_cast<const BYTE *>(value.c_str()) : reinterpret_cast<CONST BYTE *>(&val_dword),
165 str ? static_cast<DWORD>(value.length() + 1) : sizeof(val_dword));
166 check_reg_error<proxy_error>(status, key);
167 }
168
169 const char *key_name = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
170 const char *delete_value_str = "DeleteValue";
171 const DWORD delete_value_dword = 0xCAFEBABE;
172};
173} // namespace openvpn::TunWin
const std::string sname
Definition proxy.hpp:74
TunBuilderCapture::ProxyAutoConfigURL config
Definition proxy.hpp:76
The smart pointer class.
Definition rc.hpp:119
RCPtr< WinProxySettings > Ptr
Definition winproxy.hpp:29
void save_key(Win::Reg::Key &regkey, const std::string &key, const std::string &value, bool str)
Definition winproxy.hpp:114
WinProxySettings(const TunBuilderCapture::ProxyAutoConfigURL &config_arg)
Definition winproxy.hpp:31
void set_proxy(bool del) override
Definition winproxy.hpp:36
void restore_key(Win::Reg::Key &regkey, const std::string &key, bool str)
Definition winproxy.hpp:72
Wrapper class for a Registry key handle.
Definition reg.hpp:45
PHKEY ref()
Retrun a pointer to the Registry key handle.
Definition reg.hpp:146
#define OPENVPN_LOG(args)
DNS utilities for Windows.