1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
|
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef _WIN32
#ifndef OPENVPN_WIN32_H
#define OPENVPN_WIN32_H
#include <winioctl.h>
#include "mtu.h"
#include "openvpn-msg.h"
#include "argv.h"
/* location of executables */
#define SYS_PATH_ENV_VAR_NAME "SystemRoot" /* environmental variable name that normally contains the system path */
#define NETSH_PATH_SUFFIX "\\system32\\netsh.exe"
#define WIN_ROUTE_PATH_SUFFIX "\\system32\\route.exe"
#define WIN_IPCONFIG_PATH_SUFFIX "\\system32\\ipconfig.exe"
#define WIN_NET_PATH_SUFFIX "\\system32\\net.exe"
/*
* Win32-specific OpenVPN code, targeted at the mingw
* development environment.
*/
/* MSVC headers do not define this macro, so do it here */
#ifndef IN6_ARE_ADDR_EQUAL
#define IN6_ARE_ADDR_EQUAL(a,b) \
(memcmp((const void *)(a), (const void *)(b), sizeof(struct in6_addr)) == 0)
#endif
void init_win32(void);
void uninit_win32(void);
void set_pause_exit_win32(void);
struct security_attributes
{
SECURITY_ATTRIBUTES sa;
SECURITY_DESCRIPTOR sd;
};
#define HANDLE_DEFINED(h) ((h) != NULL && (h) != INVALID_HANDLE_VALUE)
/*
* Save old window title.
*/
struct window_title
{
bool saved;
char old_window_title[256];
};
struct rw_handle {
HANDLE read;
HANDLE write;
};
/*
* Event-based notification of incoming TCP connections
*/
#define NE32_PERSIST_EVENT (1<<0)
#define NE32_WRITE_EVENT (1<<1)
static inline bool
defined_net_event_win32(const struct rw_handle *event)
{
return event->read != NULL;
}
void init_net_event_win32(struct rw_handle *event, long network_events, socket_descriptor_t sd, unsigned int flags);
long reset_net_event_win32(struct rw_handle *event, socket_descriptor_t sd);
void close_net_event_win32(struct rw_handle *event, socket_descriptor_t sd, unsigned int flags);
/*
* A stateful variant of the net_event_win32 functions above
*/
struct net_event_win32
{
struct rw_handle handle;
socket_descriptor_t sd;
long event_mask;
};
void net_event_win32_init(struct net_event_win32 *ne);
void net_event_win32_start(struct net_event_win32 *ne, long network_events, socket_descriptor_t sd);
void net_event_win32_reset(struct net_event_win32 *ne);
void net_event_win32_reset_write(struct net_event_win32 *ne);
void net_event_win32_stop(struct net_event_win32 *ne);
void net_event_win32_close(struct net_event_win32 *ne);
static inline bool
net_event_win32_defined(const struct net_event_win32 *ne)
{
return defined_net_event_win32(&ne->handle);
}
static inline struct rw_handle *
net_event_win32_get_event(struct net_event_win32 *ne)
{
return &ne->handle;
}
static inline long
net_event_win32_get_event_mask(const struct net_event_win32 *ne)
{
return ne->event_mask;
}
static inline void
net_event_win32_clear_selected_events(struct net_event_win32 *ne, long selected_events)
{
ne->event_mask &= ~selected_events;
}
/*
* Signal handling
*/
struct win32_signal {
#define WSO_MODE_UNDEF 0
#define WSO_MODE_SERVICE 1
#define WSO_MODE_CONSOLE 2
int mode;
struct rw_handle in;
DWORD console_mode_save;
bool console_mode_save_defined;
};
extern struct win32_signal win32_signal; /* static/global */
extern struct window_title window_title; /* static/global */
void win32_signal_clear(struct win32_signal *ws);
/* win32_signal_open startup type */
#define WSO_NOFORCE 0
#define WSO_FORCE_SERVICE 1
#define WSO_FORCE_CONSOLE 2
void win32_signal_open(struct win32_signal *ws,
int force, /* set to WSO force parm */
const char *exit_event_name,
bool exit_event_initial_state);
void win32_signal_close(struct win32_signal *ws);
int win32_signal_get(struct win32_signal *ws);
void win32_pause(struct win32_signal *ws);
bool win32_service_interrupt(struct win32_signal *ws);
/*
* Set the text on the window title bar
*/
void window_title_clear(struct window_title *wt);
void window_title_save(struct window_title *wt);
void window_title_restore(const struct window_title *wt);
void window_title_generate(const char *title);
/*
* We try to do all Win32 I/O using overlapped
* (i.e. asynchronous) I/O for a performance win.
*/
struct overlapped_io {
#define IOSTATE_INITIAL 0
#define IOSTATE_QUEUED 1 /* overlapped I/O has been queued */
#define IOSTATE_IMMEDIATE_RETURN 2 /* I/O function returned immediately without queueing */
int iostate;
OVERLAPPED overlapped;
DWORD size;
DWORD flags;
int status;
bool addr_defined;
union {
struct sockaddr_in addr;
struct sockaddr_in6 addr6;
};
int addrlen;
struct buffer buf_init;
struct buffer buf;
};
void overlapped_io_init(struct overlapped_io *o,
const struct frame *frame,
BOOL event_state,
bool tuntap_buffer);
void overlapped_io_close(struct overlapped_io *o);
static inline bool
overlapped_io_active(struct overlapped_io *o)
{
return o->iostate == IOSTATE_QUEUED || o->iostate == IOSTATE_IMMEDIATE_RETURN;
}
char *overlapped_io_state_ascii(const struct overlapped_io *o);
/*
* Use to control access to resources that only one
* OpenVPN process on a given machine can access at
* a given time.
*/
struct semaphore
{
const char *name;
bool locked;
HANDLE hand;
};
void semaphore_clear(struct semaphore *s);
void semaphore_open(struct semaphore *s, const char *name);
bool semaphore_lock(struct semaphore *s, int timeout_milliseconds);
void semaphore_release(struct semaphore *s);
void semaphore_close(struct semaphore *s);
/*
* Special global semaphore used to protect network
* shell commands from simultaneous instantiation.
*
* It seems you can't run more than one instance
* of netsh on the same machine at the same time.
*/
extern struct semaphore netcmd_semaphore;
void netcmd_semaphore_init(void);
void netcmd_semaphore_close(void);
void netcmd_semaphore_lock(void);
void netcmd_semaphore_release(void);
/* Set Win32 security attributes structure to allow all access */
bool init_security_attributes_allow_all(struct security_attributes *obj);
/* return true if filename is safe to be used on Windows */
bool win_safe_filename(const char *fn);
/* add constant environmental variables needed by Windows */
struct env_set;
/* get and set the current windows system path */
void set_win_sys_path(const char *newpath, struct env_set *es);
void set_win_sys_path_via_env(struct env_set *es);
char *get_win_sys_path(void);
/* call self in a subprocess */
void fork_to_self(const char *cmdline);
/* Find temporary directory */
const char *win_get_tempdir(void);
/* Convert a string from UTF-8 to UCS-2 */
WCHAR *wide_string(const char *utf8, struct gc_arena *gc);
bool win_wfp_block_dns(const NET_IFINDEX index, const HANDLE msg_channel);
bool win_wfp_uninit(const NET_IFINDEX index, const HANDLE msg_channel);
#define WIN_XP 0
#define WIN_VISTA 1
#define WIN_7 2
#define WIN_8 3
#define WIN_8_1 4
#define WIN_10 5
int win32_version_info(void);
/*
* String representation of Windows version number and name, see
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx
*/
const char *win32_version_string(struct gc_arena *gc, bool add_name);
/*
* Send the |size| bytes in buffer |data| to the interactive service |pipe|
* and read the result in |ack|. Returns false on communication error.
* The string in |context| is used to prefix error messages.
*/
bool send_msg_iservice(HANDLE pipe, const void *data, size_t size,
ack_message_t *ack, const char *context);
/*
* Attempt to simulate fork/execve on Windows
*/
int
openvpn_execve(const struct argv *a, const struct env_set *es, const unsigned int flags);
bool impersonate_as_system();
#endif /* ifndef OPENVPN_WIN32_H */
#endif /* ifdef _WIN32 */
|