Skip to content

Commit 01dcad9

Browse files
committed
ipc: remove windows elevation
Signed-off-by: Jason A. Donenfeld <[email protected]>
1 parent 9e78059 commit 01dcad9

File tree

2 files changed

+36
-150
lines changed

2 files changed

+36
-150
lines changed

src/ipc-uapi-windows.h

Lines changed: 18 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -14,102 +14,37 @@
1414

1515
static FILE *userspace_interface_file(const char *iface)
1616
{
17-
char fname[MAX_PATH], error_message[1024 * 128] = { 0 };
18-
HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token, pipe_handle = INVALID_HANDLE_VALUE;
19-
PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
20-
PSECURITY_DESCRIPTOR pipe_sd;
21-
PSID pipe_sid;
17+
char fname[MAX_PATH];
18+
HANDLE pipe_handle;
2219
SID expected_sid;
23-
BOOL ret;
20+
DWORD bytes = sizeof(expected_sid);
21+
PSID pipe_sid;
22+
PSECURITY_DESCRIPTOR pipe_sd;
23+
bool equal;
2424
int fd;
25-
DWORD last_error = ERROR_SUCCESS, bytes = sizeof(expected_sid);
26-
TOKEN_PRIVILEGES privileges = {
27-
.PrivilegeCount = 1,
28-
.Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
29-
};
3025

31-
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid))
32-
goto err;
3326
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, &expected_sid, &bytes))
3427
goto err;
3528

36-
process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
37-
if (process_snapshot == INVALID_HANDLE_VALUE)
38-
goto err;
39-
for (ret = Process32First(process_snapshot, &entry); ret; last_error = GetLastError(), ret = Process32Next(process_snapshot, &entry)) {
40-
if (strcasecmp(entry.szExeFile, "winlogon.exe"))
41-
continue;
42-
43-
RevertToSelf();
44-
if (!ImpersonateSelf(SecurityImpersonation))
45-
continue;
46-
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token))
47-
continue;
48-
if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) {
49-
last_error = GetLastError();
50-
CloseHandle(thread_token);
51-
continue;
52-
}
53-
CloseHandle(thread_token);
54-
55-
winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
56-
if (!winlogon_process)
57-
continue;
58-
if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token))
59-
continue;
60-
CloseHandle(winlogon_process);
61-
if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) {
62-
last_error = GetLastError();
63-
RevertToSelf();
64-
continue;
65-
}
66-
CloseHandle(winlogon_token);
67-
if (!SetThreadToken(NULL, duplicated_token)) {
68-
last_error = GetLastError();
69-
CloseHandle(duplicated_token);
70-
continue;
71-
}
72-
CloseHandle(duplicated_token);
73-
74-
snprintf(fname, sizeof(fname), "\\\\.\\pipe\\ProtectedPrefix\\Administrators\\WireGuard\\%s", iface);
75-
pipe_handle = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
76-
last_error = GetLastError();
77-
if (pipe_handle == INVALID_HANDLE_VALUE)
78-
continue;
79-
last_error = GetSecurityInfo(pipe_handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pipe_sid, NULL, NULL, NULL, &pipe_sd);
80-
if (last_error != ERROR_SUCCESS) {
81-
CloseHandle(pipe_handle);
82-
continue;
83-
}
84-
last_error = EqualSid(&expected_sid, pipe_sid) ? ERROR_SUCCESS : ERROR_ACCESS_DENIED;
85-
LocalFree(pipe_sd);
86-
if (last_error != ERROR_SUCCESS) {
87-
CloseHandle(pipe_handle);
88-
continue;
89-
}
90-
last_error = ERROR_SUCCESS;
91-
break;
92-
}
93-
RevertToSelf();
94-
CloseHandle(process_snapshot);
95-
96-
if (last_error != ERROR_SUCCESS || pipe_handle == INVALID_HANDLE_VALUE)
29+
snprintf(fname, sizeof(fname), "\\\\.\\pipe\\ProtectedPrefix\\Administrators\\WireGuard\\%s", iface);
30+
pipe_handle = CreateFileA(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
31+
if (pipe_handle == INVALID_HANDLE_VALUE)
9732
goto err;
33+
if (GetSecurityInfo(pipe_handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pipe_sid, NULL, NULL, NULL, &pipe_sd) != ERROR_SUCCESS)
34+
goto err_close;
35+
equal = EqualSid(&expected_sid, pipe_sid);
36+
LocalFree(pipe_sd);
37+
if (!equal)
38+
goto err_close;
9839
fd = _open_osfhandle((intptr_t)pipe_handle, _O_RDWR);
9940
if (fd == -1) {
100-
last_error = GetLastError();
10141
CloseHandle(pipe_handle);
102-
goto err;
42+
return NULL;
10343
}
10444
return _fdopen(fd, "r+");
105-
45+
err_close:
46+
CloseHandle(pipe_handle);
10647
err:
107-
if (last_error == ERROR_SUCCESS)
108-
last_error = GetLastError();
109-
if (last_error == ERROR_SUCCESS)
110-
last_error = ERROR_ACCESS_DENIED;
111-
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error_message, sizeof(error_message) - 1, NULL);
112-
fprintf(stderr, "Error: Unable to open IPC handle via SYSTEM impersonation: %ld: %s\n", last_error, error_message);
11348
errno = EACCES;
11449
return NULL;
11550
}

src/ipc-windows.h

Lines changed: 18 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -311,66 +311,6 @@ skip:;
311311
return handle;
312312
}
313313

314-
static BOOL elevated_ioctl(HANDLE handle, DWORD code, void *in_buf, DWORD in_buf_len, void *out_buf, DWORD out_buf_len, DWORD *bytes_returned)
315-
{
316-
HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token;
317-
PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
318-
TOKEN_PRIVILEGES privileges = {
319-
.PrivilegeCount = 1,
320-
.Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
321-
};
322-
SID expected_sid;
323-
DWORD bytes = sizeof(expected_sid);
324-
BOOL ret;
325-
326-
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid))
327-
return FALSE;
328-
if (!CreateWellKnownSid(WinLocalSystemSid, NULL, &expected_sid, &bytes))
329-
return FALSE;
330-
331-
process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
332-
if (process_snapshot == INVALID_HANDLE_VALUE)
333-
return FALSE;
334-
for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) {
335-
if (strcasecmp(entry.szExeFile, "winlogon.exe"))
336-
continue;
337-
338-
RevertToSelf();
339-
if (!ImpersonateSelf(SecurityImpersonation))
340-
continue;
341-
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token))
342-
continue;
343-
if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) {
344-
CloseHandle(thread_token);
345-
continue;
346-
}
347-
CloseHandle(thread_token);
348-
349-
winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
350-
if (!winlogon_process)
351-
continue;
352-
if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token))
353-
continue;
354-
CloseHandle(winlogon_process);
355-
if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) {
356-
RevertToSelf();
357-
continue;
358-
}
359-
CloseHandle(winlogon_token);
360-
if (!SetThreadToken(NULL, duplicated_token)) {
361-
CloseHandle(duplicated_token);
362-
continue;
363-
}
364-
CloseHandle(duplicated_token);
365-
ret = DeviceIoControl(handle, code, in_buf, in_buf_len, out_buf, out_buf_len, bytes_returned, NULL);
366-
break;
367-
}
368-
369-
RevertToSelf();
370-
CloseHandle(process_snapshot);
371-
return ret;
372-
}
373-
374314
static int kernel_get_device(struct wgdevice **device, const char *iface)
375315
{
376316
WG_IOCTL_INTERFACE *wg_iface;
@@ -389,10 +329,10 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
389329
if (!handle)
390330
return -errno;
391331

392-
while (!elevated_ioctl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len)) {
332+
while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) {
393333
free(buf);
394334
if (GetLastError() != ERROR_MORE_DATA) {
395-
errno = EIO;
335+
errno = EACCES;
396336
return -errno;
397337
}
398338
buf = malloc(buf_len);
@@ -500,10 +440,10 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
500440

501441
static int kernel_set_device(struct wgdevice *dev)
502442
{
503-
WG_IOCTL_INTERFACE *wg_iface;
443+
WG_IOCTL_INTERFACE *wg_iface = NULL;
504444
WG_IOCTL_PEER *wg_peer;
505445
WG_IOCTL_ALLOWED_IP *wg_aip;
506-
size_t buf_len = sizeof(WG_IOCTL_INTERFACE);
446+
DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
507447
HANDLE handle = kernel_interface_handle(dev->name);
508448
struct wgpeer *peer;
509449
struct wgallowedip *aip;
@@ -514,13 +454,22 @@ static int kernel_set_device(struct wgdevice *dev)
514454
return -errno;
515455

516456
for_each_wgpeer(dev, peer) {
457+
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) {
458+
errno = EOVERFLOW;
459+
goto out;
460+
}
517461
buf_len += sizeof(WG_IOCTL_PEER);
518-
for_each_wgallowedip(peer, aip)
462+
for_each_wgallowedip(peer, aip) {
463+
if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) {
464+
errno = EOVERFLOW;
465+
goto out;
466+
}
519467
buf_len += sizeof(WG_IOCTL_ALLOWED_IP);
468+
}
520469
}
521470
wg_iface = calloc(1, buf_len);
522471
if (!wg_iface)
523-
return -errno;
472+
goto out;
524473

525474
if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
526475
memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
@@ -586,8 +535,10 @@ static int kernel_set_device(struct wgdevice *dev)
586535
}
587536
wg_iface->PeersCount = peer_count;
588537

589-
if (!elevated_ioctl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len))
538+
if (!DeviceIoControl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) {
539+
errno = EACCES;
590540
goto out;
541+
}
591542
errno = 0;
592543

593544
out:

0 commit comments

Comments
 (0)