]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
ipc: remove windows elevation
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 23 Jun 2021 23:52:06 +0000 (01:52 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Tue, 20 Jul 2021 11:24:18 +0000 (13:24 +0200)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
src/ipc-uapi-windows.h
src/ipc-windows.h

index 4d362d007338650372bd339631bfe1907b03b3d3..8ea4f75fa9afe16184884ab9e067dafd78692d6f 100644 (file)
 
 static FILE *userspace_interface_file(const char *iface)
 {
-       char fname[MAX_PATH], error_message[1024 * 128] = { 0 };
-       HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token, pipe_handle = INVALID_HANDLE_VALUE;
-       PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
-       PSECURITY_DESCRIPTOR pipe_sd;
-       PSID pipe_sid;
+       char fname[MAX_PATH];
+       HANDLE pipe_handle;
        SID expected_sid;
-       BOOL ret;
+       DWORD bytes = sizeof(expected_sid);
+       PSID pipe_sid;
+       PSECURITY_DESCRIPTOR pipe_sd;
+       bool equal;
        int fd;
-       DWORD last_error = ERROR_SUCCESS, bytes = sizeof(expected_sid);
-       TOKEN_PRIVILEGES privileges = {
-               .PrivilegeCount = 1,
-               .Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
-       };
 
-       if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid))
-               goto err;
        if (!CreateWellKnownSid(WinLocalSystemSid, NULL, &expected_sid, &bytes))
                goto err;
 
-       process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-       if (process_snapshot == INVALID_HANDLE_VALUE)
-               goto err;
-       for (ret = Process32First(process_snapshot, &entry); ret; last_error = GetLastError(), ret = Process32Next(process_snapshot, &entry)) {
-               if (strcasecmp(entry.szExeFile, "winlogon.exe"))
-                       continue;
-
-               RevertToSelf();
-               if (!ImpersonateSelf(SecurityImpersonation))
-                       continue;
-               if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token))
-                       continue;
-               if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) {
-                       last_error = GetLastError();
-                       CloseHandle(thread_token);
-                       continue;
-               }
-               CloseHandle(thread_token);
-
-               winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
-               if (!winlogon_process)
-                       continue;
-               if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token))
-                       continue;
-               CloseHandle(winlogon_process);
-               if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) {
-                       last_error = GetLastError();
-                       RevertToSelf();
-                       continue;
-               }
-               CloseHandle(winlogon_token);
-               if (!SetThreadToken(NULL, duplicated_token)) {
-                       last_error = GetLastError();
-                       CloseHandle(duplicated_token);
-                       continue;
-               }
-               CloseHandle(duplicated_token);
-
-               snprintf(fname, sizeof(fname), "\\\\.\\pipe\\ProtectedPrefix\\Administrators\\WireGuard\\%s", iface);
-               pipe_handle = CreateFile(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
-               last_error = GetLastError();
-               if (pipe_handle == INVALID_HANDLE_VALUE)
-                       continue;
-               last_error = GetSecurityInfo(pipe_handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pipe_sid, NULL, NULL, NULL, &pipe_sd);
-               if (last_error != ERROR_SUCCESS) {
-                       CloseHandle(pipe_handle);
-                       continue;
-               }
-               last_error = EqualSid(&expected_sid, pipe_sid) ? ERROR_SUCCESS : ERROR_ACCESS_DENIED;
-               LocalFree(pipe_sd);
-               if (last_error != ERROR_SUCCESS) {
-                       CloseHandle(pipe_handle);
-                       continue;
-               }
-               last_error = ERROR_SUCCESS;
-               break;
-       }
-       RevertToSelf();
-       CloseHandle(process_snapshot);
-
-       if (last_error != ERROR_SUCCESS || pipe_handle == INVALID_HANDLE_VALUE)
+       snprintf(fname, sizeof(fname), "\\\\.\\pipe\\ProtectedPrefix\\Administrators\\WireGuard\\%s", iface);
+       pipe_handle = CreateFileA(fname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+       if (pipe_handle == INVALID_HANDLE_VALUE)
                goto err;
+       if (GetSecurityInfo(pipe_handle, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pipe_sid, NULL, NULL, NULL, &pipe_sd) != ERROR_SUCCESS)
+               goto err_close;
+       equal = EqualSid(&expected_sid, pipe_sid);
+       LocalFree(pipe_sd);
+       if (!equal)
+               goto err_close;
        fd = _open_osfhandle((intptr_t)pipe_handle, _O_RDWR);
        if (fd == -1) {
-               last_error = GetLastError();
                CloseHandle(pipe_handle);
-               goto err;
+               return NULL;
        }
        return _fdopen(fd, "r+");
-
+err_close:
+       CloseHandle(pipe_handle);
 err:
-       if (last_error == ERROR_SUCCESS)
-               last_error = GetLastError();
-       if (last_error == ERROR_SUCCESS)
-               last_error = ERROR_ACCESS_DENIED;
-       FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, last_error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), error_message, sizeof(error_message) - 1, NULL);
-       fprintf(stderr, "Error: Unable to open IPC handle via SYSTEM impersonation: %ld: %s\n", last_error, error_message);
        errno = EACCES;
        return NULL;
 }
index 2382847d2d34be094d07f0e3fe325f0480c9170f..9c72a62279c13c2316957ae3e9a3bfe044b5df92 100644 (file)
@@ -311,66 +311,6 @@ skip:;
        return handle;
 }
 
-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)
-{
-       HANDLE thread_token, process_snapshot, winlogon_process, winlogon_token, duplicated_token;
-       PROCESSENTRY32 entry = { .dwSize = sizeof(PROCESSENTRY32) };
-       TOKEN_PRIVILEGES privileges = {
-               .PrivilegeCount = 1,
-               .Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
-       };
-       SID expected_sid;
-       DWORD bytes = sizeof(expected_sid);
-       BOOL ret;
-
-       if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid))
-               return FALSE;
-       if (!CreateWellKnownSid(WinLocalSystemSid, NULL, &expected_sid, &bytes))
-               return FALSE;
-
-       process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
-       if (process_snapshot == INVALID_HANDLE_VALUE)
-               return FALSE;
-       for (ret = Process32First(process_snapshot, &entry); ret; ret = Process32Next(process_snapshot, &entry)) {
-               if (strcasecmp(entry.szExeFile, "winlogon.exe"))
-                       continue;
-
-               RevertToSelf();
-               if (!ImpersonateSelf(SecurityImpersonation))
-                       continue;
-               if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &thread_token))
-                       continue;
-               if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL)) {
-                       CloseHandle(thread_token);
-                       continue;
-               }
-               CloseHandle(thread_token);
-
-               winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
-               if (!winlogon_process)
-                       continue;
-               if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &winlogon_token))
-                       continue;
-               CloseHandle(winlogon_process);
-               if (!DuplicateToken(winlogon_token, SecurityImpersonation, &duplicated_token)) {
-                       RevertToSelf();
-                       continue;
-               }
-               CloseHandle(winlogon_token);
-               if (!SetThreadToken(NULL, duplicated_token)) {
-                       CloseHandle(duplicated_token);
-                       continue;
-               }
-               CloseHandle(duplicated_token);
-               ret = DeviceIoControl(handle, code, in_buf, in_buf_len, out_buf, out_buf_len, bytes_returned, NULL);
-               break;
-       }
-
-       RevertToSelf();
-       CloseHandle(process_snapshot);
-       return ret;
-}
-
 static int kernel_get_device(struct wgdevice **device, const char *iface)
 {
        WG_IOCTL_INTERFACE *wg_iface;
@@ -389,10 +329,10 @@ static int kernel_get_device(struct wgdevice **device, const char *iface)
        if (!handle)
                return -errno;
 
-       while (!elevated_ioctl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len)) {
+       while (!DeviceIoControl(handle, WG_IOCTL_GET, NULL, 0, buf, buf_len, &buf_len, NULL)) {
                free(buf);
                if (GetLastError() != ERROR_MORE_DATA) {
-                       errno = EIO;
+                       errno = EACCES;
                        return -errno;
                }
                buf = malloc(buf_len);
@@ -500,10 +440,10 @@ out:
 
 static int kernel_set_device(struct wgdevice *dev)
 {
-       WG_IOCTL_INTERFACE *wg_iface;
+       WG_IOCTL_INTERFACE *wg_iface = NULL;
        WG_IOCTL_PEER *wg_peer;
        WG_IOCTL_ALLOWED_IP *wg_aip;
-       size_t buf_len = sizeof(WG_IOCTL_INTERFACE);
+       DWORD buf_len = sizeof(WG_IOCTL_INTERFACE);
        HANDLE handle = kernel_interface_handle(dev->name);
        struct wgpeer *peer;
        struct wgallowedip *aip;
@@ -514,13 +454,22 @@ static int kernel_set_device(struct wgdevice *dev)
                return -errno;
 
        for_each_wgpeer(dev, peer) {
+               if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_PEER)) {
+                       errno = EOVERFLOW;
+                       goto out;
+               }
                buf_len += sizeof(WG_IOCTL_PEER);
-               for_each_wgallowedip(peer, aip)
+               for_each_wgallowedip(peer, aip) {
+                       if (DWORD_MAX - buf_len < sizeof(WG_IOCTL_ALLOWED_IP)) {
+                               errno = EOVERFLOW;
+                               goto out;
+                       }
                        buf_len += sizeof(WG_IOCTL_ALLOWED_IP);
+               }
        }
        wg_iface = calloc(1, buf_len);
        if (!wg_iface)
-               return -errno;
+               goto out;
 
        if (dev->flags & WGDEVICE_HAS_PRIVATE_KEY) {
                memcpy(wg_iface->PrivateKey, dev->private_key, sizeof(wg_iface->PrivateKey));
@@ -586,8 +535,10 @@ static int kernel_set_device(struct wgdevice *dev)
        }
        wg_iface->PeersCount = peer_count;
 
-       if (!elevated_ioctl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len))
+       if (!DeviceIoControl(handle, WG_IOCTL_SET, NULL, 0, wg_iface, buf_len, &buf_len, NULL)) {
+               errno = EACCES;
                goto out;
+       }
        errno = 0;
 
 out: