]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
wg: windows: enforce named pipe ownership and use protected prefix
authorJason A. Donenfeld <Jason@zx2c4.com>
Fri, 30 Aug 2019 19:51:27 +0000 (13:51 -0600)
committerJason A. Donenfeld <Jason@zx2c4.com>
Sat, 31 Aug 2019 14:48:39 +0000 (08:48 -0600)
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
src/ipc.c
src/wincompat/ipc.c

index e0be413c88cc77b79a2ef7f230b3d8d765daedf4..89484b1fdf75147a650cac8b30a2bab29015c29f 100644 (file)
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -96,7 +96,7 @@ static int add_next_to_inflatable_buffer(struct inflatable_buffer *buffer)
 }
 
 #ifndef WINCOMPAT
-static FILE *userspace_interface_file(const char *interface)
+static FILE *userspace_interface_file(const char *iface)
 {
        struct stat sbuf;
        struct sockaddr_un addr = { .sun_family = AF_UNIX };
@@ -104,9 +104,9 @@ static FILE *userspace_interface_file(const char *interface)
        FILE *f = NULL;
 
        errno = EINVAL;
-       if (strchr(interface, '/'))
+       if (strchr(iface, '/'))
                goto out;
-       ret = snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, interface);
+       ret = snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, iface);
        if (ret < 0)
                goto out;
        ret = stat(addr.sun_path, &sbuf);
@@ -140,15 +140,15 @@ out:
        return f;
 }
 
-static bool userspace_has_wireguard_interface(const char *interface)
+static bool userspace_has_wireguard_interface(const char *iface)
 {
        struct stat sbuf;
        struct sockaddr_un addr = { .sun_family = AF_UNIX };
        int fd, ret;
 
-       if (strchr(interface, '/'))
+       if (strchr(iface, '/'))
                return false;
-       if (snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, interface) < 0)
+       if (snprintf(addr.sun_path, sizeof(addr.sun_path), SOCK_PATH "%s" SOCK_SUFFIX, iface) < 0)
                return false;
        if (stat(addr.sun_path, &sbuf) < 0)
                return false;
@@ -288,7 +288,7 @@ static int userspace_set_device(struct wgdevice *dev)
        num; \
 })
 
-static int userspace_get_device(struct wgdevice **out, const char *interface)
+static int userspace_get_device(struct wgdevice **out, const char *iface)
 {
        struct wgdevice *dev;
        struct wgpeer *peer = NULL;
@@ -302,14 +302,14 @@ static int userspace_get_device(struct wgdevice **out, const char *interface)
        if (!dev)
                return -errno;
 
-       f = userspace_interface_file(interface);
+       f = userspace_interface_file(iface);
        if (!f)
                return -errno;
 
        fprintf(f, "get=1\n\n");
        fflush(f);
 
-       strncpy(dev->name, interface, IFNAMSIZ - 1);
+       strncpy(dev->name, iface, IFNAMSIZ - 1);
        dev->name[IFNAMSIZ - 1] = '\0';
 
        while (getline(&key, &line_buffer_len, f) > 0) {
@@ -889,7 +889,7 @@ static void coalesce_peers(struct wgdevice *device)
        }
 }
 
-static int kernel_get_device(struct wgdevice **device, const char *interface)
+static int kernel_get_device(struct wgdevice **device, const char *iface)
 {
        int ret = 0;
        struct nlmsghdr *nlh;
@@ -908,7 +908,7 @@ try_again:
        }
 
        nlh = mnlg_msg_prepare(nlg, WG_CMD_GET_DEVICE, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
-       mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, interface);
+       mnl_attr_put_strz(nlh, WGDEVICE_A_IFNAME, iface);
        if (mnlg_socket_send(nlg, nlh) < 0) {
                ret = -errno;
                goto out;
@@ -963,14 +963,14 @@ cleanup:
        return buffer.buffer;
 }
 
-int ipc_get_device(struct wgdevice **dev, const char *interface)
+int ipc_get_device(struct wgdevice **dev, const char *iface)
 {
 #ifdef __linux__
-       if (userspace_has_wireguard_interface(interface))
-               return userspace_get_device(dev, interface);
-       return kernel_get_device(dev, interface);
+       if (userspace_has_wireguard_interface(iface))
+               return userspace_get_device(dev, iface);
+       return kernel_get_device(dev, iface);
 #else
-       return userspace_get_device(dev, interface);
+       return userspace_get_device(dev, iface);
 #endif
 }
 
index a7a59f84e2b02f5ec93af3a6cef9fa2ea8e65df1..25471b04e485d3955337a95a6d48f90ce78621ac 100644 (file)
@@ -5,18 +5,23 @@
 
 #include <windows.h>
 #include <tlhelp32.h>
+#include <accctrl.h>
+#include <aclapi.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <fcntl.h>
 
-static FILE *userspace_interface_file(const char *interface)
+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;
+       SID expected_sid;
        BOOL ret;
        int fd;
-       DWORD last_error = ERROR_SUCCESS;
+       DWORD last_error = ERROR_SUCCESS, bytes = sizeof(expected_sid);
        TOKEN_PRIVILEGES privileges = {
                .PrivilegeCount = 1,
                .Privileges = {{ .Attributes = SE_PRIVILEGE_ENABLED }}
@@ -24,6 +29,8 @@ static FILE *userspace_interface_file(const char *interface)
 
        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)
@@ -63,13 +70,24 @@ static FILE *userspace_interface_file(const char *interface)
                }
                CloseHandle(duplicated_token);
 
-               snprintf(fname, sizeof(fname), "\\\\.\\pipe\\WireGuard\\%s", interface);
+               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) {
-                       last_error = ERROR_SUCCESS;
-                       break;
+               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);