38 #include <versionhelpers.h>
45 #define IO_TIMEOUT 2000
47 #define ERROR_OPENVPN_STARTUP 0x20000000
48 #define ERROR_STARTUP_DATA 0x20000001
49 #define ERROR_MESSAGE_DATA 0x20000002
50 #define ERROR_MESSAGE_TYPE 0x20000003
53 static SERVICE_STATUS
status = { .dwServiceType = SERVICE_WIN32_SHARE_PROCESS };
57 #define RDNS_TIMEOUT 600
59 #define TUN_IOCTL_REGISTER_RINGS CTL_CODE(51820U, 0x970U, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
127 if (new_item == NULL)
129 return ERROR_OUTOFMEMORY;
132 new_item->
next = *pfirst;
133 new_item->
data = data;
147 for (pnext = pfirst; *pnext; pnext = &(*pnext)->
next)
150 if (!match(item->
data, ctx))
168 if (handle && *handle && *handle != INVALID_HANDLE_VALUE)
170 CloseHandle(*handle);
171 *handle = INVALID_HANDLE_VALUE;
173 return INVALID_HANDLE_VALUE;
181 UnmapViewOfFile(*ring);
196 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
197 overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
198 return overlapped->hEvent;
205 HANDLE io_event = overlapped->hEvent;
206 if (!ResetEvent(io_event))
210 ZeroMemory(overlapped,
sizeof(OVERLAPPED));
211 overlapped->hEvent = io_event;
228 DWORD res, bytes = 0;
229 OVERLAPPED overlapped;
230 LPHANDLE handles = NULL;
238 handles = malloc((count + 1) *
sizeof(HANDLE));
246 success = WriteFile(pipe,
buffer, size, NULL, &overlapped);
250 success = ReadFile(pipe,
buffer, size, NULL, &overlapped);
252 if (!success && GetLastError() != ERROR_IO_PENDING && GetLastError() != ERROR_MORE_DATA)
257 handles[0] = io_event;
258 for (i = 0; i < count; i++)
260 handles[i + 1] = events[i];
263 res = WaitForMultipleObjects(count + 1, handles, FALSE,
265 if (res != WAIT_OBJECT_0)
273 PeekNamedPipe(pipe, NULL, 0, NULL, &bytes, NULL);
277 GetOverlappedResult(pipe, &overlapped, &bytes, TRUE);
299 WritePipeAsync(HANDLE pipe, LPVOID data, DWORD size, DWORD count, LPHANDLE events)
307 const WCHAR
msg[] = L
"Process ID";
308 WCHAR buf[22 + _countof(
msg)];
314 swprintf(buf, _countof(buf), L
"0x%08x\n0x%08x\n%ls", 0, pid,
msg);
316 WritePipeAsync(pipe, buf, (DWORD)(wcslen(buf) * 2), count, events);
320 ReturnError(HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events)
323 LPWSTR result = L
"0xffffffff\nFormatMessage failed\nCould not return result";
332 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
333 |FORMAT_MESSAGE_ALLOCATE_BUFFER
334 |FORMAT_MESSAGE_IGNORE_INSERTS,
335 0, error, 0, (LPWSTR) &args[2], 0, NULL);
338 result_len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING
339 |FORMAT_MESSAGE_ALLOCATE_BUFFER
340 |FORMAT_MESSAGE_ARGUMENT_ARRAY,
341 L
"0x%1!08x!\n%2!s!\n%3!s!", 0, 0,
342 (LPWSTR) &result, 0, (va_list *) args);
344 WritePipeAsync(pipe, result, (DWORD)(wcslen(result) * 2), count, events);
349 LocalFree((LPVOID) args[2]);
376 const WCHAR *msg1 = L
"You have specified a config file location (%ls relative to %ls)"
377 L
" that requires admin approval. This error may be avoided"
378 L
" by adding your account to the \"%ls\" group";
380 const WCHAR *msg2 = L
"You have specified an option (%ls) that may be used"
381 L
" only with admin approval. This error may be avoided"
382 L
" by adding your account to the \"%ls\" group";
388 swprintf(errmsg, capacity,
389 L
"Cannot validate options: CommandLineToArgvW failed with error = 0x%08x",
406 WCHAR *argv_tmp[2] = { L
"--config",
argv[0] };
410 swprintf(errmsg, capacity, msg1,
argv[0], workdir,
416 for (i = 0; i < argc; ++i)
425 if (wcscmp(L
"--config",
argv[i]) == 0 && argc-i > 1)
427 swprintf(errmsg, capacity, msg1,
argv[i+1], workdir,
432 swprintf(errmsg, capacity, msg2,
argv[i],
465 size = bytes /
sizeof(*data);
473 data = malloc(bytes);
489 if (data[size - 1] != 0)
507 len = wcslen(sud->
options) + 1;
536 SOCKADDR_INET sa_inet;
537 ZeroMemory(&sa_inet,
sizeof(sa_inet));
538 sa_inet.si_family = family;
539 if (family == AF_INET)
541 sa_inet.Ipv4.sin_addr = addr->
ipv4;
543 else if (family == AF_INET6)
545 sa_inet.Ipv6.sin6_addr = addr->
ipv6;
554 LPWSTR wide_name =
utf8to16(iface_name);
558 status = ConvertInterfaceAliasToLuid(wide_name, luid);
563 status = ERROR_OUTOFMEMORY;
574 err = ConvertInterfaceAliasToLuid(ifname, &luid);
575 if (err == ERROR_SUCCESS)
577 err = ConvertInterfaceLuidToIndex(&luid, index);
579 if (err != ERROR_SUCCESS)
589 return memcmp(item,
address,
sizeof(MIB_UNICASTIPADDRESS_ROW)) == 0 ? TRUE : FALSE;
595 return DeleteUnicastIpAddressEntry(addr_row);
602 PMIB_UNICASTIPADDRESS_ROW addr_row;
605 addr_row = malloc(
sizeof(*addr_row));
606 if (addr_row == NULL)
608 return ERROR_OUTOFMEMORY;
611 InitializeUnicastIpAddressEntry(addr_row);
613 addr_row->OnLinkPrefixLength = (UINT8)
msg->prefix_len;
615 if (
msg->iface.index != -1)
617 addr_row->InterfaceIndex =
msg->iface.index;
627 addr_row->InterfaceLuid = luid;
632 err = CreateUnicastIpAddressEntry(addr_row);
667 return memcmp(item,
route,
sizeof(MIB_IPFORWARD_ROW2)) == 0 ? TRUE : FALSE;
673 return DeleteIpForwardEntry2(fwd_row);
680 PMIB_IPFORWARD_ROW2 fwd_row;
683 fwd_row = malloc(
sizeof(*fwd_row));
686 return ERROR_OUTOFMEMORY;
689 ZeroMemory(fwd_row,
sizeof(*fwd_row));
690 fwd_row->ValidLifetime = 0xffffffff;
691 fwd_row->PreferredLifetime = 0xffffffff;
692 fwd_row->Protocol = MIB_IPPROTO_NETMGMT;
693 fwd_row->Metric =
msg->metric;
695 fwd_row->DestinationPrefix.PrefixLength = (UINT8)
msg->prefix_len;
698 if (
msg->iface.index != -1)
700 fwd_row->InterfaceIndex =
msg->iface.index;
702 else if (strlen(
msg->iface.name))
710 fwd_row->InterfaceLuid = luid;
715 err = CreateIpForwardEntry2(fwd_row);
751 if (
msg->family == AF_INET)
753 return FlushIpNetTable(
msg->iface.index);
756 return FlushIpNetTable2(
msg->family,
msg->iface.index);
770 err_str = TEXT(
"Unknown Win32 Error");
772 if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM
773 | FORMAT_MESSAGE_ARGUMENT_ARRAY,
774 NULL, err, 0, buf,
sizeof(buf), NULL))
823 HANDLE engine = NULL;
836 err = ERROR_OUTOFMEMORY;
839 block_data->
engine = engine;
840 block_data->
index =
msg->iface.index;
908 ExecCommand(
const WCHAR *argv0,
const WCHAR *cmdline, DWORD timeout)
912 PROCESS_INFORMATION pi;
913 DWORD proc_flags = CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT;
914 WCHAR *cmdline_dup = NULL;
916 ZeroMemory(&si,
sizeof(si));
917 ZeroMemory(&pi,
sizeof(pi));
922 cmdline_dup = _wcsdup(cmdline);
923 if (cmdline_dup && CreateProcessW(argv0, cmdline_dup, NULL, NULL, FALSE,
924 proc_flags, NULL, NULL, &si, &pi) )
926 WaitForSingleObject(pi.hProcess, timeout ? timeout : INFINITE);
927 if (!GetExitCodeProcess(pi.hProcess, &exit_code))
930 exit_code = GetLastError();
932 else if (exit_code == STILL_ACTIVE)
934 exit_code = WAIT_TIMEOUT;
937 TerminateProcess(pi.hProcess, exit_code);
944 argv0, cmdline, exit_code);
951 CloseHandle(pi.hProcess);
952 CloseHandle(pi.hThread);
956 exit_code = GetLastError();
976 WCHAR ipcfg[MAX_PATH];
984 { ipcfg, L
"ipconfig /flushdns", timeout },
985 { ipcfg, L
"ipconfig /registerdns", timeout },
990 swprintf(ipcfg, MAX_PATH, L
"%ls\\%ls",
get_win_sys_path(), L
"ipconfig.exe");
992 if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0)
995 for (i = 0; i < _countof(cmds); ++i)
997 ExecCommand(cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout);
1008 err = ERROR_SEM_TIMEOUT;
1017 HANDLE thread = NULL;
1020 thread = CreateThread(NULL, 0,
RegisterDNS, NULL, 0, NULL);
1029 CloseHandle(thread);
1033 err = GetLastError();
1049 netsh_dns_cmd(
const wchar_t *action,
const wchar_t *proto,
const wchar_t *if_name,
const wchar_t *addr)
1052 int timeout = 30000;
1053 wchar_t argv0[MAX_PATH];
1054 wchar_t *cmdline = NULL;
1058 if (wcscmp(action, L
"delete") == 0)
1069 swprintf(argv0, _countof(argv0), L
"%ls\\%ls",
get_win_sys_path(), L
"netsh.exe");
1074 const wchar_t *fmt = L
"netsh interface %ls %ls dns \"%ls\" %ls";
1077 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1;
1078 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1081 err = ERROR_OUTOFMEMORY;
1085 swprintf(cmdline, ncmdline, fmt, proto, action, if_name, addr);
1087 if (IsWindows7OrGreater())
1089 wcscat_s(cmdline, ncmdline, L
" validate=no");
1111 int timeout = 30000;
1112 wchar_t argv0[MAX_PATH];
1113 wchar_t *cmdline = NULL;
1114 const wchar_t *addr_static = (wcscmp(action, L
"set") == 0) ? L
"static" : L
"";
1118 if (wcscmp(action, L
"delete") == 0)
1129 swprintf(argv0, _countof(argv0), L
"%ls\\%ls",
get_win_sys_path(), L
"netsh.exe");
1134 const wchar_t *fmt = L
"netsh interface ip %ls wins \"%ls\" %ls %ls";
1137 size_t ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(action) + wcslen(addr)
1138 +wcslen(addr_static) + 32 + 1;
1139 cmdline = malloc(ncmdline *
sizeof(
wchar_t));
1142 err = ERROR_OUTOFMEMORY;
1146 swprintf(cmdline, ncmdline, fmt, action, if_name, addr_static, addr);
1165 const wchar_t *data)
1168 wchar_t argv0[MAX_PATH];
1169 wchar_t *cmdline = NULL;
1170 int timeout = 10000;
1172 swprintf(argv0, _countof(argv0), L
"%ls\\%ls",
get_win_sys_path(), L
"wbem\\wmic.exe");
1176 if (data && wcschr(data, L
','))
1178 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls (%ls)";
1182 fmt = L
"wmic nicconfig where (InterfaceIndex=%ld) call %ls \"%ls\"";
1185 size_t ncmdline = wcslen(fmt) + 20 + wcslen(action)
1186 + (data ? wcslen(data) + 1 : 1);
1187 cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1190 return ERROR_OUTOFMEMORY;
1193 swprintf(cmdline, ncmdline, fmt, if_index, action,
1205 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1211 AddDNS(
short family,
wchar_t *if_name,
wchar_t *addr)
1213 wchar_t *proto = (family == AF_INET6) ? L
"ipv6" : L
"ip";
1220 return (wcscmp(item, str) == 0) ? TRUE : FALSE;
1234 NET_IFINDEX if_index;
1237 if (err != ERROR_SUCCESS)
1242 wchar_t *wdomain =
utf8to16(domain);
1245 return ERROR_OUTOFMEMORY;
1257 if (err == 0 && wdomain[0] && lists)
1259 wchar_t *tmp_name = _wcsdup(if_name);
1263 err = ERROR_OUTOFMEMORY;
1277 int addr_len =
msg->addr_len;
1280 if (addr_len > _countof(
msg->addr))
1282 addr_len = _countof(
msg->addr);
1285 if (!
msg->iface.name[0])
1293 msgptr->
iface.
name[_countof(
msg->iface.name)-1] =
'\0';
1294 msgptr->
domains[_countof(
msg->domains)-1] =
'\0';
1300 return ERROR_OUTOFMEMORY;
1318 if (
msg->domains[0])
1326 for (
int i = 0; i < addr_len; ++i)
1328 if (
msg->family == AF_INET6)
1330 RtlIpv6AddressToStringW(&
msg->addr[i].ipv6, addr);
1334 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1336 err =
AddDNS(
msg->family, wide_name, addr);
1348 if (
msg->addr_len > 0)
1350 wchar_t *tmp_name = _wcsdup(wide_name);
1351 if (!tmp_name ||
AddListItem(&(*lists)[undo_type], tmp_name))
1355 err = ERROR_OUTOFMEMORY;
1360 if (
msg->domains[0])
1375 int addr_len =
msg->addr_len;
1378 if (addr_len > _countof(
msg->addr))
1380 addr_len = _countof(
msg->addr);
1383 if (!
msg->iface.name[0])
1391 msgptr->
iface.
name[_countof(
msg->iface.name) - 1] =
'\0';
1397 return ERROR_OUTOFMEMORY;
1418 for (
int i = 0; i < addr_len; ++i)
1420 RtlIpv4AddressToStringW(&
msg->addr[i].ipv4, addr);
1435 wchar_t *tmp_name = _wcsdup(wide_name);
1440 err = ERROR_OUTOFMEMORY;
1454 DWORD timeout = 5000;
1455 wchar_t argv0[MAX_PATH];
1458 swprintf(argv0, _countof(argv0), L
"%ls\\%ls",
get_win_sys_path(), L
"netsh.exe");
1463 const wchar_t *fmt = L
"netsh interface ipv4 set address name=\"%d\" source=dhcp";
1468 size_t ncmdline = wcslen(fmt) + 10 + 1;
1469 wchar_t *cmdline = malloc(ncmdline*
sizeof(
wchar_t));
1472 err = ERROR_OUTOFMEMORY;
1476 swprintf(cmdline, ncmdline, fmt,
dhcp->iface.index);
1491 DWORD err = ERROR_SUCCESS;
1493 if (!DuplicateHandle(ovpn_proc, orig_handle, GetCurrentProcess(), new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS))
1495 err = GetLastError();
1506 DWORD err = ERROR_SUCCESS;
1508 HANDLE dup_handle = NULL;
1511 if (err != ERROR_SUCCESS)
1515 *ring = (
struct tun_ring *)MapViewOfFile(dup_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(
struct tun_ring));
1519 err = GetLastError();
1535 if (ring_buffer_maps)
1539 else if ((ring_buffer_maps = calloc(1,
sizeof(*ring_buffer_maps))) == NULL)
1541 return ERROR_OUTOFMEMORY;
1544 HANDLE device = NULL;
1545 HANDLE send_tail_moved = NULL;
1546 HANDLE receive_tail_moved = NULL;
1549 if (err != ERROR_SUCCESS)
1555 if (err != ERROR_SUCCESS)
1561 if (err != ERROR_SUCCESS)
1567 if (err != ERROR_SUCCESS)
1573 if (err != ERROR_SUCCESS)
1580 send_tail_moved, receive_tail_moved))
1582 err = GetLastError();
1590 if (err != ERROR_SUCCESS && ring_buffer_maps)
1593 free(ring_buffer_maps);
1605 MIB_IPINTERFACE_ROW ipiface;
1606 InitializeIpInterfaceEntry(&ipiface);
1607 ipiface.Family = mtu->
family;
1609 err = GetIpInterfaceEntry(&ipiface);
1610 if (err != NO_ERROR)
1614 if (mtu->
family == AF_INET)
1616 ipiface.SitePrefixLength = 0;
1618 ipiface.NlMtu = mtu->
mtu;
1620 err = SetIpInterfaceEntry(&ipiface);
1626 DWORD bytes, DWORD count, LPHANDLE events,
undo_lists_t *lists)
1632 .size =
sizeof(ack),
1646 switch (
msg.header.type)
1650 if (
msg.header.size ==
sizeof(
msg.address))
1658 if (
msg.header.size ==
sizeof(
msg.route))
1665 if (
msg.header.size ==
sizeof(
msg.flush_neighbors))
1673 if (
msg.header.size ==
sizeof(
msg.wfp_block))
1694 if (
msg.header.size ==
sizeof(
msg.dhcp))
1701 if (
msg.header.size ==
sizeof(
msg.rrb))
1708 if (
msg.header.size ==
sizeof(
msg.mtu))
1787 *pnext = item->
next;
1798 HANDLE ovpn_pipe = NULL, svc_pipe = NULL;
1799 PTOKEN_USER svc_user = NULL, ovpn_user = NULL;
1800 HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL;
1801 HANDLE stdin_read = NULL, stdin_write = NULL;
1802 HANDLE stdout_write = NULL;
1803 DWORD pipe_mode, len, exit_code = 0;
1805 STARTUPINFOW startup_info;
1806 PROCESS_INFORMATION proc_info;
1807 LPVOID user_env = NULL;
1808 TCHAR ovpn_pipe_name[256];
1810 WCHAR *cmdline = NULL;
1811 size_t cmdline_size;
1813 WCHAR errmsg[512] = L
"";
1815 SECURITY_ATTRIBUTES inheritable = {
1816 .nLength =
sizeof(inheritable),
1817 .lpSecurityDescriptor = NULL,
1818 .bInheritHandle = TRUE
1822 EXPLICIT_ACCESS ea[2];
1823 SECURITY_DESCRIPTOR ovpn_sd;
1824 SECURITY_ATTRIBUTES ovpn_sa = {
1825 .nLength =
sizeof(ovpn_sa),
1826 .lpSecurityDescriptor = &ovpn_sd,
1827 .bInheritHandle = FALSE
1830 ZeroMemory(&ea,
sizeof(ea));
1831 ZeroMemory(&startup_info,
sizeof(startup_info));
1832 ZeroMemory(&undo_lists,
sizeof(undo_lists));
1833 ZeroMemory(&proc_info,
sizeof(proc_info));
1840 if (!InitializeSecurityDescriptor(&ovpn_sd, SECURITY_DESCRIPTOR_REVISION))
1847 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &svc_token))
1853 while (!GetTokenInformation(svc_token, TokenUser, svc_user, len, &len))
1855 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1861 svc_user = malloc(len);
1862 if (svc_user == NULL)
1868 if (!IsValidSid(svc_user->User.Sid))
1874 if (!ImpersonateNamedPipeClient(pipe))
1879 if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &imp_token))
1885 while (!GetTokenInformation(imp_token, TokenUser, ovpn_user, len, &len))
1887 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1893 ovpn_user = malloc(len);
1894 if (ovpn_user == NULL)
1900 if (!IsValidSid(ovpn_user->User.Sid))
1921 ea[0].grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL;
1922 ea[0].grfAccessMode = SET_ACCESS;
1923 ea[0].grfInheritance = NO_INHERITANCE;
1924 ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1925 ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1926 ea[0].Trustee.ptstrName = (LPTSTR) svc_user->User.Sid;
1927 ea[1].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | PROCESS_VM_READ
1928 |SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION;
1929 ea[1].grfAccessMode = SET_ACCESS;
1930 ea[1].grfInheritance = NO_INHERITANCE;
1931 ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
1932 ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
1933 ea[1].Trustee.ptstrName = (LPTSTR) ovpn_user->User.Sid;
1936 if (!SetSecurityDescriptorOwner(&ovpn_sd, svc_user->User.Sid, FALSE))
1941 if (SetEntriesInAcl(2, ea, NULL, &ovpn_dacl) != ERROR_SUCCESS)
1946 if (!SetSecurityDescriptorDacl(&ovpn_sd, TRUE, ovpn_dacl, FALSE))
1953 if (!DuplicateTokenEx(imp_token, TOKEN_ALL_ACCESS, NULL, 0, TokenPrimary, &pri_token))
1960 stdout_write = CreateFile(_T(
"NUL"), GENERIC_WRITE, FILE_SHARE_WRITE,
1961 &inheritable, OPEN_EXISTING, 0, NULL);
1962 if (stdout_write == INVALID_HANDLE_VALUE)
1968 if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0)
1969 || !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0))
1975 swprintf(ovpn_pipe_name, _countof(ovpn_pipe_name),
1977 ovpn_pipe = CreateNamedPipe(ovpn_pipe_name,
1978 PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED,
1979 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL);
1980 if (ovpn_pipe == INVALID_HANDLE_VALUE)
1986 svc_pipe = CreateFile(ovpn_pipe_name, GENERIC_READ | GENERIC_WRITE, 0,
1987 &inheritable, OPEN_EXISTING, 0, NULL);
1988 if (svc_pipe == INVALID_HANDLE_VALUE)
1994 pipe_mode = PIPE_READMODE_MESSAGE;
1995 if (!SetNamedPipeHandleState(svc_pipe, &pipe_mode, NULL, NULL))
2001 cmdline_size = wcslen(sud.
options) + 128;
2002 cmdline = malloc(cmdline_size *
sizeof(*cmdline));
2003 if (cmdline == NULL)
2011 swprintf(cmdline, cmdline_size, L
"openvpn %ls --msg-channel %" PRIuPTR,
2012 sud.
options, (uintptr_t)svc_pipe);
2014 if (!CreateEnvironmentBlock(&user_env, imp_token, FALSE))
2020 startup_info.cb =
sizeof(startup_info);
2021 startup_info.dwFlags = STARTF_USESTDHANDLES;
2022 startup_info.hStdInput = stdin_read;
2023 startup_info.hStdOutput = stdout_write;
2024 startup_info.hStdError = stdout_write;
2029 if (!CreateProcessAsUserW(pri_token, exe_path, cmdline, &ovpn_sa, NULL, TRUE,
2031 user_env, sud.
directory, &startup_info, &proc_info))
2037 if (!RevertToSelf())
2039 TerminateProcess(proc_info.hProcess, 1);
2050 DWORD input_size = WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, NULL, 0, NULL, NULL);
2052 if (input_size && (input = malloc(input_size)))
2055 WideCharToMultiByte(CP_UTF8, 0, sud.
std_input, -1, input, input_size, NULL, NULL);
2056 WriteFile(stdin_write, input, (DWORD)strlen(input), &written, NULL);
2071 MsgToEventLog(
MSG_FLAGS_ERROR, TEXT(
"OpenVPN process sent too large payload length to the pipe (%lu bytes), it will be terminated"), bytes);
2078 WaitForSingleObject(proc_info.hProcess,
IO_TIMEOUT);
2079 GetExitCodeProcess(proc_info.hProcess, &exit_code);
2080 if (exit_code == STILL_ACTIVE)
2082 TerminateProcess(proc_info.hProcess, 1);
2084 else if (exit_code != 0)
2087 swprintf(buf, _countof(buf),
2088 L
"OpenVPN exited with error: exit code = %lu", exit_code);
2094 FlushFileBuffers(pipe);
2095 DisconnectNamedPipe(pipe);
2100 DestroyEnvironmentBlock(user_env);
2121 SERVICE_STATUS *
status = ctx;
2124 case SERVICE_CONTROL_STOP:
2125 status->dwCurrentState = SERVICE_STOP_PENDING;
2133 case SERVICE_CONTROL_INTERROGATE:
2137 return ERROR_CALL_NOT_IMPLEMENTED;
2151 const TCHAR *sddlString = TEXT(
"D:(A;OICI;GA;;;S-1-5-18)(D;OICI;0x4;;;S-1-1-0)(A;OICI;GRGW;;;S-1-5-11)(D;;GA;;;S-1-5-7)");
2153 PSECURITY_DESCRIPTOR sd = NULL;
2154 if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddlString, SDDL_REVISION_1, &sd, NULL))
2157 return INVALID_HANDLE_VALUE;
2161 SECURITY_ATTRIBUTES sa = {0};
2162 sa.nLength =
sizeof(SECURITY_ATTRIBUTES);
2163 sa.lpSecurityDescriptor = sd;
2164 sa.bInheritHandle = FALSE;
2166 DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED;
2168 static BOOL first = TRUE;
2171 flags |= FILE_FLAG_FIRST_PIPE_INSTANCE;
2175 TCHAR pipe_name[256];
2177 HANDLE pipe = CreateNamedPipe(pipe_name, flags,
2178 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS,
2179 PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, &sa);
2183 if (pipe == INVALID_HANDLE_VALUE)
2186 return INVALID_HANDLE_VALUE;
2197 static DWORD size = 10;
2198 static LPHANDLE handles = NULL;
2201 if (handles == NULL)
2203 handles = malloc(size *
sizeof(HANDLE));
2204 *handles_ptr = handles;
2205 if (handles == NULL)
2207 return ERROR_OUTOFMEMORY;
2211 handles[
pos++] = io_event;
2224 tmp = realloc(handles, size *
sizeof(HANDLE));
2229 return ERROR_OUTOFMEMORY;
2232 *handles_ptr = handles;
2234 handles[
pos++] = threads->
data;
2235 threads = threads->
next;
2259 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2267 HANDLE pipe, io_event = NULL;
2268 OVERLAPPED overlapped;
2269 DWORD error = NO_ERROR;
2271 PHANDLE handles = NULL;
2280 status.dwCurrentState = SERVICE_START_PENDING;
2281 status.dwServiceSpecificExitCode = NO_ERROR;
2282 status.dwWin32ExitCode = NO_ERROR;
2283 status.dwWaitHint = 3000;
2288 if (error != ERROR_SUCCESS)
2294 exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
2309 if (error != NO_ERROR)
2315 if (pipe == INVALID_HANDLE_VALUE)
2320 status.dwCurrentState = SERVICE_RUNNING;
2326 if (ConnectNamedPipe(pipe, &overlapped) == FALSE
2327 && GetLastError() != ERROR_PIPE_CONNECTED
2328 && GetLastError() != ERROR_IO_PENDING)
2334 error = WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE);
2335 if (error == WAIT_OBJECT_0)
2339 HANDLE thread = CreateThread(NULL, 0,
RunOpenvpn, pipe, CREATE_SUSPENDED, NULL);
2353 TerminateThread(thread, 1);
2359 ResumeThread(thread);
2373 if (error == WAIT_FAILED)
2403 status.dwCurrentState = SERVICE_STOPPED;
2404 status.dwWin32ExitCode = error;