diff options
Diffstat (limited to 'src/ipc-uapi-windows.h')
-rw-r--r-- | src/ipc-uapi-windows.h | 140 |
1 files changed, 55 insertions, 85 deletions
diff --git a/src/ipc-uapi-windows.h b/src/ipc-uapi-windows.h index 86fab07..8ea4f75 100644 --- a/src/ipc-uapi-windows.h +++ b/src/ipc-uapi-windows.h @@ -10,126 +10,96 @@ #include <stdio.h> #include <stdbool.h> #include <fcntl.h> +#include <hashtable.h> 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; } +static bool have_cached_interfaces; +static struct hashtable cached_interfaces; + +static bool userspace_has_wireguard_interface(const char *iface) +{ + char fname[MAX_PATH]; + WIN32_FIND_DATA find_data; + HANDLE find_handle; + bool ret = false; + + if (have_cached_interfaces) + return hashtable_find_entry(&cached_interfaces, iface) != NULL; + + snprintf(fname, sizeof(fname), "ProtectedPrefix\\Administrators\\WireGuard\\%s", iface); + find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data); + if (find_handle == INVALID_HANDLE_VALUE) + return -EIO; + do { + if (!strcmp(fname, find_data.cFileName)) { + ret = true; + break; + } + } while (FindNextFile(find_handle, &find_data)); + FindClose(find_handle); + return ret; +} + static int userspace_get_wireguard_interfaces(struct string_list *list) { static const char prefix[] = "ProtectedPrefix\\Administrators\\WireGuard\\"; WIN32_FIND_DATA find_data; HANDLE find_handle; + char *iface; int ret = 0; find_handle = FindFirstFile("\\\\.\\pipe\\*", &find_data); if (find_handle == INVALID_HANDLE_VALUE) - return -GetLastError(); + return -EIO; do { if (strncmp(prefix, find_data.cFileName, strlen(prefix))) continue; - ret = string_list_add(list, find_data.cFileName + strlen(prefix)); + iface = find_data.cFileName + strlen(prefix); + ret = string_list_add(list, iface); if (ret < 0) goto out; + if (!hashtable_find_or_insert_entry(&cached_interfaces, iface)) { + ret = -errno; + goto out; + } } while (FindNextFile(find_handle, &find_data)); + have_cached_interfaces = true; out: FindClose(find_handle); |