From 7f808dfb43f0a5ced7253a6dc8faf9f189ca8f2a Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 30 Aug 2019 13:51:27 -0600 Subject: tools: windows: enforce named pipe ownership and use protected prefix --- src/tools/ipc.c | 32 ++++++++++++++++---------------- src/tools/wincompat/ipc.c | 30 ++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/tools/ipc.c b/src/tools/ipc.c index e0be413..89484b1 100644 --- a/src/tools/ipc.c +++ b/src/tools/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 } diff --git a/src/tools/wincompat/ipc.c b/src/tools/wincompat/ipc.c index a7a59f8..25471b0 100644 --- a/src/tools/wincompat/ipc.c +++ b/src/tools/wincompat/ipc.c @@ -5,18 +5,23 @@ #include #include +#include +#include #include #include #include -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); -- cgit v1.2.3-59-g8ed1b