aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/ipc-uapi-windows.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc-uapi-windows.h')
-rw-r--r--src/ipc-uapi-windows.h140
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);