From 3a2bbdb05ca6a6996e424c9fb225cb0d53804125 Mon Sep 17 00:00:00 2001 From: Alberto Gonzalez Iniesta Date: Tue, 27 Dec 2016 18:25:47 +0100 Subject: New upstream version 2.4.0 --- src/openvpnserv/Makefile.am | 2 +- src/openvpnserv/Makefile.in | 8 +- src/openvpnserv/automatic.c | 520 ++++----- src/openvpnserv/common.c | 322 +++--- src/openvpnserv/interactive.c | 2352 ++++++++++++++++++++++------------------- src/openvpnserv/service.c | 340 +++--- src/openvpnserv/service.h | 55 +- src/openvpnserv/validate.c | 124 ++- src/openvpnserv/validate.h | 10 +- 9 files changed, 2000 insertions(+), 1733 deletions(-) (limited to 'src/openvpnserv') diff --git a/src/openvpnserv/Makefile.am b/src/openvpnserv/Makefile.am index 58ecd91..21efc7c 100644 --- a/src/openvpnserv/Makefile.am +++ b/src/openvpnserv/Makefile.am @@ -5,7 +5,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2010 OpenVPN Technologies, Inc. +# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. # Copyright (C) 2006-2012 Alon Bar-Lev # diff --git a/src/openvpnserv/Makefile.in b/src/openvpnserv/Makefile.in index b38a76a..e113fee 100644 --- a/src/openvpnserv/Makefile.in +++ b/src/openvpnserv/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.14.1 from Makefile.am. +# Makefile.in generated by automake 1.13.4 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. @@ -21,7 +21,7 @@ # packet encryption, packet authentication, and # packet compression. # -# Copyright (C) 2002-2010 OpenVPN Technologies, Inc. +# Copyright (C) 2002-2017 OpenVPN Technologies, Inc. # Copyright (C) 2006-2012 Alon Bar-Lev # @@ -504,14 +504,14 @@ distclean-compile: @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/openvpnserv/automatic.c b/src/openvpnserv/automatic.c index aa7618f..6be6c6d 100644 --- a/src/openvpnserv/automatic.c +++ b/src/openvpnserv/automatic.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -48,17 +48,17 @@ static SERVICE_STATUS_HANDLE service; static SERVICE_STATUS status; openvpn_service_t automatic_service = { - automatic, - TEXT(PACKAGE_NAME "ServiceLegacy"), - TEXT(PACKAGE_NAME " Legacy Service"), - TEXT(SERVICE_DEPENDENCIES), - SERVICE_DEMAND_START + automatic, + TEXT(PACKAGE_NAME "ServiceLegacy"), + TEXT(PACKAGE_NAME " Legacy Service"), + TEXT(SERVICE_DEPENDENCIES), + SERVICE_DEMAND_START }; struct security_attributes { - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; }; /* @@ -74,18 +74,22 @@ static HANDLE exit_event = NULL; bool -init_security_attributes_allow_all (struct security_attributes *obj) +init_security_attributes_allow_all(struct security_attributes *obj) { - CLEAR (*obj); + CLEAR(*obj); - obj->sa.nLength = sizeof (SECURITY_ATTRIBUTES); - obj->sa.lpSecurityDescriptor = &obj->sd; - obj->sa.bInheritHandle = TRUE; - if (!InitializeSecurityDescriptor (&obj->sd, SECURITY_DESCRIPTOR_REVISION)) - return false; - if (!SetSecurityDescriptorDacl (&obj->sd, TRUE, NULL, FALSE)) - return false; - return true; + obj->sa.nLength = sizeof(SECURITY_ATTRIBUTES); + obj->sa.lpSecurityDescriptor = &obj->sd; + obj->sa.bInheritHandle = TRUE; + if (!InitializeSecurityDescriptor(&obj->sd, SECURITY_DESCRIPTOR_REVISION)) + { + return false; + } + if (!SetSecurityDescriptorDacl(&obj->sd, TRUE, NULL, FALSE)) + { + return false; + } + return true; } /* @@ -98,318 +102,342 @@ init_security_attributes_allow_all (struct security_attributes *obj) #define EXIT_EVENT_NAME TEXT(PACKAGE "_exit_1") HANDLE -create_event (LPCTSTR name, bool allow_all, bool initial_state, bool manual_reset) +create_event(LPCTSTR name, bool allow_all, bool initial_state, bool manual_reset) { - if (allow_all) + if (allow_all) { - struct security_attributes sa; - if (!init_security_attributes_allow_all (&sa)) - return NULL; - return CreateEvent (&sa.sa, (BOOL)manual_reset, (BOOL)initial_state, name); + struct security_attributes sa; + if (!init_security_attributes_allow_all(&sa)) + { + return NULL; + } + return CreateEvent(&sa.sa, (BOOL)manual_reset, (BOOL)initial_state, name); + } + else + { + return CreateEvent(NULL, (BOOL)manual_reset, (BOOL)initial_state, name); } - else - return CreateEvent (NULL, (BOOL)manual_reset, (BOOL)initial_state, name); } void -close_if_open (HANDLE h) +close_if_open(HANDLE h) { - if (h != NULL) - CloseHandle (h); + if (h != NULL) + { + CloseHandle(h); + } } static bool -match (const WIN32_FIND_DATA *find, LPCTSTR ext) +match(const WIN32_FIND_DATA *find, LPCTSTR ext) { - int i; + int i; - if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - return false; + if (find->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + return false; + } - if (!_tcslen (ext)) - return true; + if (!_tcslen(ext)) + { + return true; + } - i = _tcslen (find->cFileName) - _tcslen (ext) - 1; - if (i < 1) - return false; + i = _tcslen(find->cFileName) - _tcslen(ext) - 1; + if (i < 1) + { + return false; + } - return find->cFileName[i] == '.' && !_tcsicmp (find->cFileName + i + 1, ext); + return find->cFileName[i] == '.' && !_tcsicmp(find->cFileName + i + 1, ext); } /* * Modify the extension on a filename. */ static bool -modext (LPTSTR dest, int size, LPCTSTR src, LPCTSTR newext) +modext(LPTSTR dest, int size, LPCTSTR src, LPCTSTR newext) { - int i; + int i; - if (size > 0 && (_tcslen (src) + 1) <= size) + if (size > 0 && (_tcslen(src) + 1) <= size) { - _tcscpy (dest, src); - dest [size - 1] = TEXT('\0'); - i = _tcslen (dest); - while (--i >= 0) + _tcscpy(dest, src); + dest [size - 1] = TEXT('\0'); + i = _tcslen(dest); + while (--i >= 0) { - if (dest[i] == TEXT('\\')) - break; - if (dest[i] == TEXT('.')) + if (dest[i] == TEXT('\\')) + { + break; + } + if (dest[i] == TEXT('.')) { - dest[i] = TEXT('\0'); - break; + dest[i] = TEXT('\0'); + break; } } - if (_tcslen (dest) + _tcslen(newext) + 2 <= size) + if (_tcslen(dest) + _tcslen(newext) + 2 <= size) { - _tcscat (dest, TEXT(".")); - _tcscat (dest, newext); - return true; + _tcscat(dest, TEXT(".")); + _tcscat(dest, newext); + return true; } - dest[0] = TEXT('\0'); + dest[0] = TEXT('\0'); } - return false; + return false; } static DWORD WINAPI -ServiceCtrlAutomatic (DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) +ServiceCtrlAutomatic(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) { - SERVICE_STATUS *status = ctx; - switch (ctrl_code) + SERVICE_STATUS *status = ctx; + switch (ctrl_code) { - case SERVICE_CONTROL_STOP: - status->dwCurrentState = SERVICE_STOP_PENDING; - ReportStatusToSCMgr (service, status); - if (exit_event) - SetEvent (exit_event); - return NO_ERROR; - - case SERVICE_CONTROL_INTERROGATE: - return NO_ERROR; - - default: - return ERROR_CALL_NOT_IMPLEMENTED; + case SERVICE_CONTROL_STOP: + status->dwCurrentState = SERVICE_STOP_PENDING; + ReportStatusToSCMgr(service, status); + if (exit_event) + { + SetEvent(exit_event); + } + return NO_ERROR; + + case SERVICE_CONTROL_INTERROGATE: + return NO_ERROR; + + default: + return ERROR_CALL_NOT_IMPLEMENTED; } } VOID WINAPI -ServiceStartAutomatic (DWORD dwArgc, LPTSTR *lpszArgv) +ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv) { - DWORD error = NO_ERROR; - settings_t settings; + DWORD error = NO_ERROR; + settings_t settings; - service = RegisterServiceCtrlHandlerEx (automatic_service.name, ServiceCtrlAutomatic, &status); - if (!service) - return; + service = RegisterServiceCtrlHandlerEx(automatic_service.name, ServiceCtrlAutomatic, &status); + if (!service) + { + return; + } - status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; - status.dwCurrentState = SERVICE_START_PENDING; - status.dwServiceSpecificExitCode = NO_ERROR; - status.dwWin32ExitCode = NO_ERROR; - status.dwWaitHint = 3000; + status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; + status.dwCurrentState = SERVICE_START_PENDING; + status.dwServiceSpecificExitCode = NO_ERROR; + status.dwWin32ExitCode = NO_ERROR; + status.dwWaitHint = 3000; - if (!ReportStatusToSCMgr(service, &status)) + if (!ReportStatusToSCMgr(service, &status)) { - MsgToEventLog (M_ERR, TEXT("ReportStatusToSCMgr #1 failed")); - goto finish; + MsgToEventLog(M_ERR, TEXT("ReportStatusToSCMgr #1 failed")); + goto finish; } - /* - * Create our exit event - */ - exit_event = create_event (EXIT_EVENT_NAME, false, false, true); - if (!exit_event) + /* + * Create our exit event + */ + exit_event = create_event(EXIT_EVENT_NAME, false, false, true); + if (!exit_event) { - MsgToEventLog (M_ERR, TEXT("CreateEvent failed")); - goto finish; + MsgToEventLog(M_ERR, TEXT("CreateEvent failed")); + goto finish; } - /* - * If exit event is already signaled, it means we were not - * shut down properly. - */ - if (WaitForSingleObject (exit_event, 0) != WAIT_TIMEOUT) + /* + * If exit event is already signaled, it means we were not + * shut down properly. + */ + if (WaitForSingleObject(exit_event, 0) != WAIT_TIMEOUT) { - MsgToEventLog (M_ERR, TEXT("Exit event is already signaled -- we were not shut down properly")); - goto finish; + MsgToEventLog(M_ERR, TEXT("Exit event is already signaled -- we were not shut down properly")); + goto finish; } - if (!ReportStatusToSCMgr(service, &status)) + if (!ReportStatusToSCMgr(service, &status)) { - MsgToEventLog (M_ERR, TEXT("ReportStatusToSCMgr #2 failed")); - goto finish; + MsgToEventLog(M_ERR, TEXT("ReportStatusToSCMgr #2 failed")); + goto finish; } - /* - * Read info from registry in key HKLM\SOFTWARE\OpenVPN - */ - error = GetOpenvpnSettings (&settings); - if (error != ERROR_SUCCESS) - goto finish; - - /* - * Instantiate an OpenVPN process for each configuration - * file found. - */ - { - WIN32_FIND_DATA find_obj; - HANDLE find_handle; - BOOL more_files; - TCHAR find_string[MAX_PATH]; - - openvpn_sntprintf (find_string, MAX_PATH, TEXT("%s\\*"), settings.config_dir); - - find_handle = FindFirstFile (find_string, &find_obj); - if (find_handle == INVALID_HANDLE_VALUE) - { - MsgToEventLog (M_ERR, TEXT("Cannot get configuration file list using: %s"), find_string); + /* + * Read info from registry in key HKLM\SOFTWARE\OpenVPN + */ + error = GetOpenvpnSettings(&settings); + if (error != ERROR_SUCCESS) + { goto finish; - } + } /* - * Loop over each config file + * Instantiate an OpenVPN process for each configuration + * file found. */ - do { - HANDLE log_handle = NULL; - STARTUPINFO start_info; - PROCESS_INFORMATION proc_info; - struct security_attributes sa; - TCHAR log_file[MAX_PATH]; - TCHAR log_path[MAX_PATH]; - TCHAR command_line[256]; - - CLEAR (start_info); - CLEAR (proc_info); - CLEAR (sa); - - if (!ReportStatusToSCMgr(service, &status)) + { + WIN32_FIND_DATA find_obj; + HANDLE find_handle; + BOOL more_files; + TCHAR find_string[MAX_PATH]; + + openvpn_sntprintf(find_string, MAX_PATH, TEXT("%s\\*"), settings.config_dir); + + find_handle = FindFirstFile(find_string, &find_obj); + if (find_handle == INVALID_HANDLE_VALUE) { - MsgToEventLog (M_ERR, TEXT("ReportStatusToSCMgr #3 failed")); - FindClose (find_handle); - goto finish; + MsgToEventLog(M_ERR, TEXT("Cannot get configuration file list using: %s"), find_string); + goto finish; } - /* does file have the correct type and extension? */ - if (match (&find_obj, settings.ext_string)) - { - /* get log file pathname */ - if (!modext (log_file, _countof (log_file), find_obj.cFileName, TEXT("log"))) + /* + * Loop over each config file + */ + do { + HANDLE log_handle = NULL; + STARTUPINFO start_info; + PROCESS_INFORMATION proc_info; + struct security_attributes sa; + TCHAR log_file[MAX_PATH]; + TCHAR log_path[MAX_PATH]; + TCHAR command_line[256]; + + CLEAR(start_info); + CLEAR(proc_info); + CLEAR(sa); + + if (!ReportStatusToSCMgr(service, &status)) { - MsgToEventLog (M_ERR, TEXT("Cannot construct logfile name based on: %s"), find_obj.cFileName); - FindClose (find_handle); - goto finish; + MsgToEventLog(M_ERR, TEXT("ReportStatusToSCMgr #3 failed")); + FindClose(find_handle); + goto finish; } - openvpn_sntprintf (log_path, _countof (log_path), - TEXT("%s\\%s"), settings.log_dir, log_file); - - /* construct command line */ - openvpn_sntprintf (command_line, _countof (command_line), TEXT(PACKAGE " --service %s 1 --config \"%s\""), - EXIT_EVENT_NAME, - find_obj.cFileName); - /* Make security attributes struct for logfile handle so it can - be inherited. */ - if (!init_security_attributes_allow_all (&sa)) + /* does file have the correct type and extension? */ + if (match(&find_obj, settings.ext_string)) { - error = MsgToEventLog (M_SYSERR, TEXT("InitializeSecurityDescriptor start_" PACKAGE " failed")); - goto finish; - } + /* get log file pathname */ + if (!modext(log_file, _countof(log_file), find_obj.cFileName, TEXT("log"))) + { + MsgToEventLog(M_ERR, TEXT("Cannot construct logfile name based on: %s"), find_obj.cFileName); + FindClose(find_handle); + goto finish; + } + openvpn_sntprintf(log_path, _countof(log_path), + TEXT("%s\\%s"), settings.log_dir, log_file); - /* open logfile as stdout/stderr for soon-to-be-spawned subprocess */ - log_handle = CreateFile (log_path, - GENERIC_WRITE, - FILE_SHARE_READ, - &sa.sa, - settings.append ? OPEN_ALWAYS : CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); + /* construct command line */ + openvpn_sntprintf(command_line, _countof(command_line), TEXT(PACKAGE " --service %s 1 --config \"%s\""), + EXIT_EVENT_NAME, + find_obj.cFileName); - if (log_handle == INVALID_HANDLE_VALUE) - { - error = MsgToEventLog (M_SYSERR, TEXT("Cannot open logfile: %s"), log_path); - FindClose (find_handle); - goto finish; - } + /* Make security attributes struct for logfile handle so it can + * be inherited. */ + if (!init_security_attributes_allow_all(&sa)) + { + error = MsgToEventLog(M_SYSERR, TEXT("InitializeSecurityDescriptor start_" PACKAGE " failed")); + goto finish; + } - /* append to logfile? */ - if (settings.append) - { - if (SetFilePointer (log_handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) + /* open logfile as stdout/stderr for soon-to-be-spawned subprocess */ + log_handle = CreateFile(log_path, + GENERIC_WRITE, + FILE_SHARE_READ, + &sa.sa, + settings.append ? OPEN_ALWAYS : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (log_handle == INVALID_HANDLE_VALUE) { - error = MsgToEventLog (M_SYSERR, TEXT("Cannot seek to end of logfile: %s"), log_path); - FindClose (find_handle); - goto finish; + error = MsgToEventLog(M_SYSERR, TEXT("Cannot open logfile: %s"), log_path); + FindClose(find_handle); + goto finish; } - } - /* fill in STARTUPINFO struct */ - GetStartupInfo(&start_info); - start_info.cb = sizeof(start_info); - start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - start_info.wShowWindow = SW_HIDE; - start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - start_info.hStdOutput = start_info.hStdError = log_handle; - - /* create an OpenVPN process for one config file */ - if (!CreateProcess(settings.exe_path, - command_line, - NULL, - NULL, - TRUE, - settings.priority | CREATE_NEW_CONSOLE, - NULL, - settings.config_dir, - &start_info, - &proc_info)) - { - error = MsgToEventLog (M_SYSERR, TEXT("CreateProcess failed, exe='%s' cmdline='%s' dir='%s'"), - settings.exe_path, - command_line, - settings.config_dir); - - FindClose (find_handle); - CloseHandle (log_handle); - goto finish; - } + /* append to logfile? */ + if (settings.append) + { + if (SetFilePointer(log_handle, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) + { + error = MsgToEventLog(M_SYSERR, TEXT("Cannot seek to end of logfile: %s"), log_path); + FindClose(find_handle); + goto finish; + } + } - /* close unneeded handles */ - Sleep (1000); /* try to prevent race if we close logfile - handle before child process DUPs it */ - if (!CloseHandle (proc_info.hProcess) - || !CloseHandle (proc_info.hThread) - || !CloseHandle (log_handle)) - { - error = MsgToEventLog (M_SYSERR, TEXT("CloseHandle failed")); - goto finish; + /* fill in STARTUPINFO struct */ + GetStartupInfo(&start_info); + start_info.cb = sizeof(start_info); + start_info.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + start_info.wShowWindow = SW_HIDE; + start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + start_info.hStdOutput = start_info.hStdError = log_handle; + + /* create an OpenVPN process for one config file */ + if (!CreateProcess(settings.exe_path, + command_line, + NULL, + NULL, + TRUE, + settings.priority | CREATE_NEW_CONSOLE, + NULL, + settings.config_dir, + &start_info, + &proc_info)) + { + error = MsgToEventLog(M_SYSERR, TEXT("CreateProcess failed, exe='%s' cmdline='%s' dir='%s'"), + settings.exe_path, + command_line, + settings.config_dir); + + FindClose(find_handle); + CloseHandle(log_handle); + goto finish; + } + + /* close unneeded handles */ + Sleep(1000); /* try to prevent race if we close logfile + * handle before child process DUPs it */ + if (!CloseHandle(proc_info.hProcess) + || !CloseHandle(proc_info.hThread) + || !CloseHandle(log_handle)) + { + error = MsgToEventLog(M_SYSERR, TEXT("CloseHandle failed")); + goto finish; + } } - } - /* more files to process? */ - more_files = FindNextFile (find_handle, &find_obj); + /* more files to process? */ + more_files = FindNextFile(find_handle, &find_obj); - } while (more_files); + } while (more_files); - FindClose (find_handle); - } + FindClose(find_handle); + } - /* we are now fully started */ - status.dwCurrentState = SERVICE_RUNNING; - status.dwWaitHint = 0; - if (!ReportStatusToSCMgr(service, &status)) + /* we are now fully started */ + status.dwCurrentState = SERVICE_RUNNING; + status.dwWaitHint = 0; + if (!ReportStatusToSCMgr(service, &status)) { - MsgToEventLog (M_ERR, TEXT("ReportStatusToSCMgr SERVICE_RUNNING failed")); - goto finish; + MsgToEventLog(M_ERR, TEXT("ReportStatusToSCMgr SERVICE_RUNNING failed")); + goto finish; } - /* wait for our shutdown signal */ - if (WaitForSingleObject (exit_event, INFINITE) != WAIT_OBJECT_0) - MsgToEventLog (M_ERR, TEXT("wait for shutdown signal failed")); + /* wait for our shutdown signal */ + if (WaitForSingleObject(exit_event, INFINITE) != WAIT_OBJECT_0) + { + MsgToEventLog(M_ERR, TEXT("wait for shutdown signal failed")); + } finish: - if (exit_event) - CloseHandle (exit_event); + if (exit_event) + { + CloseHandle(exit_event); + } - status.dwCurrentState = SERVICE_STOPPED; - status.dwWin32ExitCode = error; - ReportStatusToSCMgr (service, &status); + status.dwCurrentState = SERVICE_STOPPED; + status.dwWin32ExitCode = error; + ReportStatusToSCMgr(service, &status); } diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c index eafee20..3b9b396 100644 --- a/src/openvpnserv/common.c +++ b/src/openvpnserv/common.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2011 Heiko Hund + * Copyright (C) 2011-2017 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -29,202 +29,236 @@ * that don't guarantee null termination for size > 0. */ int -openvpn_vsntprintf (LPTSTR str, size_t size, LPCTSTR format, va_list arglist) +openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist) { - int len = -1; - if (size > 0) + int len = -1; + if (size > 0) { - len = _vsntprintf (str, size, format, arglist); - str[size - 1] = 0; + len = _vsntprintf(str, size, format, arglist); + str[size - 1] = 0; } - return (len >= 0 && len < size); + return (len >= 0 && len < size); } int -openvpn_sntprintf (LPTSTR str, size_t size, LPCTSTR format, ...) +openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...) { - va_list arglist; - int len = -1; - if (size > 0) + va_list arglist; + int len = -1; + if (size > 0) { - va_start (arglist, format); - len = openvpn_vsntprintf (str, size, format, arglist); - va_end (arglist); + va_start(arglist, format); + len = openvpn_vsntprintf(str, size, format, arglist); + va_end(arglist); } - return len; + return len; } #define REG_KEY TEXT("SOFTWARE\\" PACKAGE_NAME) static DWORD -GetRegString (HKEY key, LPCTSTR value, LPTSTR data, DWORD size) +GetRegString(HKEY key, LPCTSTR value, LPTSTR data, DWORD size) { - DWORD type; - LONG status = RegQueryValueEx (key, value, NULL, &type, (LPBYTE) data, &size); + DWORD type; + LONG status = RegQueryValueEx(key, value, NULL, &type, (LPBYTE) data, &size); - if (status == ERROR_SUCCESS && type != REG_SZ) - status = ERROR_DATATYPE_MISMATCH; + if (status == ERROR_SUCCESS && type != REG_SZ) + { + status = ERROR_DATATYPE_MISMATCH; + } - if (status != ERROR_SUCCESS) + if (status != ERROR_SUCCESS) { - SetLastError (status); - return MsgToEventLog (M_SYSERR, TEXT("Error querying registry value: HKLM\\%s\\%s"), REG_KEY, value); + SetLastError(status); + return MsgToEventLog(M_SYSERR, TEXT("Error querying registry value: HKLM\\%s\\%s"), REG_KEY, value); } - return ERROR_SUCCESS; + return ERROR_SUCCESS; } DWORD -GetOpenvpnSettings (settings_t *s) +GetOpenvpnSettings(settings_t *s) { - TCHAR priority[64]; - TCHAR append[2]; - DWORD error; - HKEY key; - - LONG status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, REG_KEY, 0, KEY_READ, &key); - if (status != ERROR_SUCCESS) - { - SetLastError (status); - return MsgToEventLog (M_SYSERR, TEXT("Could not open Registry key HKLM\\%s not found"), REG_KEY); - } - - error = GetRegString (key, TEXT("exe_path"), s->exe_path, sizeof (s->exe_path)); - if (error != ERROR_SUCCESS) - goto out; - - error = GetRegString (key, TEXT("config_dir"), s->config_dir, sizeof (s->config_dir)); - if (error != ERROR_SUCCESS) - goto out; - - error = GetRegString (key, TEXT("config_ext"), s->ext_string, sizeof (s->ext_string)); - if (error != ERROR_SUCCESS) - goto out; - - error = GetRegString (key, TEXT("log_dir"), s->log_dir, sizeof (s->log_dir)); - if (error != ERROR_SUCCESS) - goto out; - - error = GetRegString (key, TEXT("priority"), priority, sizeof (priority)); - if (error != ERROR_SUCCESS) - goto out; - - error = GetRegString (key, TEXT("log_append"), append, sizeof (append)); - if (error != ERROR_SUCCESS) - goto out; - - /* read if present, else use default */ - error = GetRegString (key, TEXT("ovpn_admin_group"), s->ovpn_admin_group, sizeof (s->ovpn_admin_group)); - if (error != ERROR_SUCCESS) - { - openvpn_sntprintf(s->ovpn_admin_group, _countof(s->ovpn_admin_group), OVPN_ADMIN_GROUP); - error = 0; /* this error is not fatal */ - } - /* set process priority */ - if (!_tcsicmp (priority, TEXT("IDLE_PRIORITY_CLASS"))) - s->priority = IDLE_PRIORITY_CLASS; - else if (!_tcsicmp (priority, TEXT("BELOW_NORMAL_PRIORITY_CLASS"))) - s->priority = BELOW_NORMAL_PRIORITY_CLASS; - else if (!_tcsicmp (priority, TEXT("NORMAL_PRIORITY_CLASS"))) - s->priority = NORMAL_PRIORITY_CLASS; - else if (!_tcsicmp (priority, TEXT("ABOVE_NORMAL_PRIORITY_CLASS"))) - s->priority = ABOVE_NORMAL_PRIORITY_CLASS; - else if (!_tcsicmp (priority, TEXT("HIGH_PRIORITY_CLASS"))) - s->priority = HIGH_PRIORITY_CLASS; - else - { - SetLastError (ERROR_INVALID_DATA); - error = MsgToEventLog (M_SYSERR, TEXT("Unknown priority name: %s"), priority); - goto out; - } - - /* set log file append/truncate flag */ - if (append[0] == TEXT('0')) - s->append = FALSE; - else if (append[0] == TEXT('1')) - s->append = TRUE; - else - { - SetLastError (ERROR_INVALID_DATA); - error = MsgToEventLog (M_ERR, TEXT("Log file append flag (given as '%s') must be '0' or '1'"), append); - goto out; + TCHAR priority[64]; + TCHAR append[2]; + DWORD error; + HKEY key; + + LONG status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY, 0, KEY_READ, &key); + if (status != ERROR_SUCCESS) + { + SetLastError(status); + return MsgToEventLog(M_SYSERR, TEXT("Could not open Registry key HKLM\\%s not found"), REG_KEY); + } + + error = GetRegString(key, TEXT("exe_path"), s->exe_path, sizeof(s->exe_path)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + error = GetRegString(key, TEXT("config_dir"), s->config_dir, sizeof(s->config_dir)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + error = GetRegString(key, TEXT("config_ext"), s->ext_string, sizeof(s->ext_string)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + error = GetRegString(key, TEXT("log_dir"), s->log_dir, sizeof(s->log_dir)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + error = GetRegString(key, TEXT("priority"), priority, sizeof(priority)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + error = GetRegString(key, TEXT("log_append"), append, sizeof(append)); + if (error != ERROR_SUCCESS) + { + goto out; + } + + /* read if present, else use default */ + error = GetRegString(key, TEXT("ovpn_admin_group"), s->ovpn_admin_group, sizeof(s->ovpn_admin_group)); + if (error != ERROR_SUCCESS) + { + openvpn_sntprintf(s->ovpn_admin_group, _countof(s->ovpn_admin_group), OVPN_ADMIN_GROUP); + error = 0; /* this error is not fatal */ + } + /* set process priority */ + if (!_tcsicmp(priority, TEXT("IDLE_PRIORITY_CLASS"))) + { + s->priority = IDLE_PRIORITY_CLASS; + } + else if (!_tcsicmp(priority, TEXT("BELOW_NORMAL_PRIORITY_CLASS"))) + { + s->priority = BELOW_NORMAL_PRIORITY_CLASS; + } + else if (!_tcsicmp(priority, TEXT("NORMAL_PRIORITY_CLASS"))) + { + s->priority = NORMAL_PRIORITY_CLASS; + } + else if (!_tcsicmp(priority, TEXT("ABOVE_NORMAL_PRIORITY_CLASS"))) + { + s->priority = ABOVE_NORMAL_PRIORITY_CLASS; + } + else if (!_tcsicmp(priority, TEXT("HIGH_PRIORITY_CLASS"))) + { + s->priority = HIGH_PRIORITY_CLASS; + } + else + { + SetLastError(ERROR_INVALID_DATA); + error = MsgToEventLog(M_SYSERR, TEXT("Unknown priority name: %s"), priority); + goto out; + } + + /* set log file append/truncate flag */ + if (append[0] == TEXT('0')) + { + s->append = FALSE; + } + else if (append[0] == TEXT('1')) + { + s->append = TRUE; + } + else + { + SetLastError(ERROR_INVALID_DATA); + error = MsgToEventLog(M_ERR, TEXT("Log file append flag (given as '%s') must be '0' or '1'"), append); + goto out; } out: - RegCloseKey (key); - return error; + RegCloseKey(key); + return error; } LPCTSTR -GetLastErrorText () +GetLastErrorText() { - static TCHAR buf[256]; - DWORD len; - LPTSTR tmp = NULL; + static TCHAR buf[256]; + DWORD len; + LPTSTR tmp = NULL; - len = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&tmp, 0, NULL); + len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, GetLastError(), LANG_NEUTRAL, (LPTSTR)&tmp, 0, NULL); - if (len == 0 || (long) _countof (buf) < (long) len + 14) - buf[0] = TEXT('\0'); - else + if (len == 0 || (long) _countof(buf) < (long) len + 14) + { + buf[0] = TEXT('\0'); + } + else { - tmp[_tcslen (tmp) - 2] = TEXT('\0'); /* remove CR/LF characters */ - openvpn_sntprintf (buf, _countof (buf), TEXT("%s (0x%x)"), tmp, GetLastError()); + tmp[_tcslen(tmp) - 2] = TEXT('\0'); /* remove CR/LF characters */ + openvpn_sntprintf(buf, _countof(buf), TEXT("%s (0x%x)"), tmp, GetLastError()); } - if (tmp) - LocalFree (tmp); + if (tmp) + { + LocalFree(tmp); + } - return buf; + return buf; } DWORD -MsgToEventLog (DWORD flags, LPCTSTR format, ...) +MsgToEventLog(DWORD flags, LPCTSTR format, ...) { - HANDLE hEventSource; - TCHAR msg[2][256]; - DWORD error = 0; - LPCTSTR err_msg = TEXT(""); - va_list arglist; + HANDLE hEventSource; + TCHAR msg[2][256]; + DWORD error = 0; + LPCTSTR err_msg = TEXT(""); + va_list arglist; - if (flags & MSG_FLAGS_SYS_CODE) + if (flags & MSG_FLAGS_SYS_CODE) { - error = GetLastError (); - err_msg = GetLastErrorText (); + error = GetLastError(); + err_msg = GetLastErrorText(); } - hEventSource = RegisterEventSource (NULL, APPNAME); - if (hEventSource != NULL) + hEventSource = RegisterEventSource(NULL, APPNAME); + if (hEventSource != NULL) { - openvpn_sntprintf (msg[0], _countof (msg[0]), - TEXT("%s%s: %s"), APPNAME, - (flags & MSG_FLAGS_ERROR) ? TEXT(" error") : TEXT(""), err_msg); - - va_start (arglist, format); - openvpn_vsntprintf (msg[1], _countof (msg[1]), format, arglist); - va_end (arglist); - - const TCHAR *mesg[] = { msg[0], msg[1] }; - ReportEvent (hEventSource, flags & MSG_FLAGS_ERROR ? - EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, - 0, 0, NULL, 2, 0, mesg, NULL); - DeregisterEventSource (hEventSource); + openvpn_sntprintf(msg[0], _countof(msg[0]), + TEXT("%s%s: %s"), APPNAME, + (flags & MSG_FLAGS_ERROR) ? TEXT(" error") : TEXT(""), err_msg); + + va_start(arglist, format); + openvpn_vsntprintf(msg[1], _countof(msg[1]), format, arglist); + va_end(arglist); + + const TCHAR *mesg[] = { msg[0], msg[1] }; + ReportEvent(hEventSource, flags & MSG_FLAGS_ERROR ? + EVENTLOG_ERROR_TYPE : EVENTLOG_INFORMATION_TYPE, + 0, 0, NULL, 2, 0, mesg, NULL); + DeregisterEventSource(hEventSource); } - return error; + return error; } /* Convert a utf8 string to utf16. Caller should free the result */ wchar_t * -utf8to16 (const char *utf8) +utf8to16(const char *utf8) { - int n = MultiByteToWideChar (CP_UTF8, 0, utf8, -1, NULL, 0); - wchar_t *utf16 = malloc (n * sizeof (wchar_t)); - if (!utf16) - return NULL; - MultiByteToWideChar (CP_UTF8, 0, utf8, -1, utf16, n); - return utf16; + int n = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0); + wchar_t *utf16 = malloc(n * sizeof(wchar_t)); + if (!utf16) + { + return NULL; + } + MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, n); + return utf16; } diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c index ec54216..dbe2b9b 100644 --- a/src/openvpnserv/interactive.c +++ b/src/openvpnserv/interactive.c @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2012 Heiko Hund + * Copyright (C) 2012-2017 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -61,265 +61,291 @@ static HANDLE rdns_semaphore = NULL; openvpn_service_t interactive_service = { - interactive, - TEXT(PACKAGE_NAME "ServiceInteractive"), - TEXT(PACKAGE_NAME " Interactive Service"), - TEXT(SERVICE_DEPENDENCIES), - SERVICE_AUTO_START + interactive, + TEXT(PACKAGE_NAME "ServiceInteractive"), + TEXT(PACKAGE_NAME " Interactive Service"), + TEXT(SERVICE_DEPENDENCIES), + SERVICE_AUTO_START }; typedef struct { - WCHAR *directory; - WCHAR *options; - WCHAR *std_input; + WCHAR *directory; + WCHAR *options; + WCHAR *std_input; } STARTUP_DATA; /* Datatype for linked lists */ typedef struct _list_item { - struct _list_item *next; - LPVOID data; + struct _list_item *next; + LPVOID data; } list_item_t; /* Datatypes for undo information */ typedef enum { - address, - route, - block_dns, - undo_dns4, - undo_dns6, - _undo_type_max + address, + route, + block_dns, + undo_dns4, + undo_dns6, + _undo_type_max } undo_type_t; -typedef list_item_t* undo_lists_t[_undo_type_max]; +typedef list_item_t *undo_lists_t[_undo_type_max]; static DWORD -AddListItem (list_item_t **pfirst, LPVOID data) +AddListItem(list_item_t **pfirst, LPVOID data) { - list_item_t *new_item = malloc (sizeof (list_item_t)); - if (new_item == NULL) - return ERROR_OUTOFMEMORY; + list_item_t *new_item = malloc(sizeof(list_item_t)); + if (new_item == NULL) + { + return ERROR_OUTOFMEMORY; + } - new_item->next = *pfirst; - new_item->data = data; + new_item->next = *pfirst; + new_item->data = data; - *pfirst = new_item; - return NO_ERROR; + *pfirst = new_item; + return NO_ERROR; } typedef BOOL (*match_fn_t) (LPVOID item, LPVOID ctx); static LPVOID -RemoveListItem (list_item_t **pfirst, match_fn_t match, LPVOID ctx) +RemoveListItem(list_item_t **pfirst, match_fn_t match, LPVOID ctx) { - LPVOID data = NULL; - list_item_t **pnext; + LPVOID data = NULL; + list_item_t **pnext; - for (pnext = pfirst; *pnext; pnext = &(*pnext)->next) + for (pnext = pfirst; *pnext; pnext = &(*pnext)->next) { - list_item_t *item = *pnext; - if (!match (item->data, ctx)) - continue; + list_item_t *item = *pnext; + if (!match(item->data, ctx)) + { + continue; + } - /* Found item, remove from the list and free memory */ - *pnext = item->next; - data = item->data; - free (item); - break; + /* Found item, remove from the list and free memory */ + *pnext = item->next; + data = item->data; + free(item); + break; } - return data; + return data; } static HANDLE -CloseHandleEx (LPHANDLE handle) +CloseHandleEx(LPHANDLE handle) { - if (handle && *handle && *handle != INVALID_HANDLE_VALUE) + if (handle && *handle && *handle != INVALID_HANDLE_VALUE) { - CloseHandle (*handle); - *handle = INVALID_HANDLE_VALUE; + CloseHandle(*handle); + *handle = INVALID_HANDLE_VALUE; } - return INVALID_HANDLE_VALUE; + return INVALID_HANDLE_VALUE; } static HANDLE -InitOverlapped (LPOVERLAPPED overlapped) +InitOverlapped(LPOVERLAPPED overlapped) { - ZeroMemory (overlapped, sizeof (OVERLAPPED)); - overlapped->hEvent = CreateEvent (NULL, TRUE, FALSE, NULL); - return overlapped->hEvent; + ZeroMemory(overlapped, sizeof(OVERLAPPED)); + overlapped->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + return overlapped->hEvent; } static BOOL -ResetOverlapped (LPOVERLAPPED overlapped) +ResetOverlapped(LPOVERLAPPED overlapped) { - HANDLE io_event = overlapped->hEvent; - if (!ResetEvent (io_event)) - return FALSE; - ZeroMemory (overlapped, sizeof (OVERLAPPED)); - overlapped->hEvent = io_event; - return TRUE; + HANDLE io_event = overlapped->hEvent; + if (!ResetEvent(io_event)) + { + return FALSE; + } + ZeroMemory(overlapped, sizeof(OVERLAPPED)); + overlapped->hEvent = io_event; + return TRUE; } typedef enum { - peek, - read, - write + peek, + read, + write } async_op_t; static DWORD -AsyncPipeOp (async_op_t op, HANDLE pipe, LPVOID buffer, DWORD size, DWORD count, LPHANDLE events) +AsyncPipeOp(async_op_t op, HANDLE pipe, LPVOID buffer, DWORD size, DWORD count, LPHANDLE events) { - int i; - BOOL success; - HANDLE io_event; - DWORD res, bytes = 0; - OVERLAPPED overlapped; - LPHANDLE handles = NULL; + int i; + BOOL success; + HANDLE io_event; + DWORD res, bytes = 0; + OVERLAPPED overlapped; + LPHANDLE handles = NULL; - io_event = InitOverlapped (&overlapped); - if (!io_event) - goto out; + io_event = InitOverlapped(&overlapped); + if (!io_event) + { + goto out; + } - handles = malloc ((count + 1) * sizeof (HANDLE)); - if (!handles) - goto out; + handles = malloc((count + 1) * sizeof(HANDLE)); + if (!handles) + { + goto out; + } - if (op == write) - success = WriteFile (pipe, buffer, size, NULL, &overlapped); - else - success = ReadFile (pipe, buffer, size, NULL, &overlapped); - if (!success && GetLastError () != ERROR_IO_PENDING && GetLastError () != ERROR_MORE_DATA) - goto out; + if (op == write) + { + success = WriteFile(pipe, buffer, size, NULL, &overlapped); + } + else + { + success = ReadFile(pipe, buffer, size, NULL, &overlapped); + } + if (!success && GetLastError() != ERROR_IO_PENDING && GetLastError() != ERROR_MORE_DATA) + { + goto out; + } - handles[0] = io_event; - for (i = 0; i < count; i++) - handles[i + 1] = events[i]; + handles[0] = io_event; + for (i = 0; i < count; i++) + handles[i + 1] = events[i]; - res = WaitForMultipleObjects (count + 1, handles, FALSE, - op == peek ? INFINITE : IO_TIMEOUT); - if (res != WAIT_OBJECT_0) + res = WaitForMultipleObjects(count + 1, handles, FALSE, + op == peek ? INFINITE : IO_TIMEOUT); + if (res != WAIT_OBJECT_0) { - CancelIo (pipe); - goto out; + CancelIo(pipe); + goto out; } - if (op == peek) - PeekNamedPipe (pipe, NULL, 0, NULL, &bytes, NULL); - else - GetOverlappedResult (pipe, &overlapped, &bytes, TRUE); + if (op == peek) + { + PeekNamedPipe(pipe, NULL, 0, NULL, &bytes, NULL); + } + else + { + GetOverlappedResult(pipe, &overlapped, &bytes, TRUE); + } out: - CloseHandleEx (&io_event); - free (handles); - return bytes; + CloseHandleEx(&io_event); + free(handles); + return bytes; } static DWORD -PeekNamedPipeAsync (HANDLE pipe, DWORD count, LPHANDLE events) +PeekNamedPipeAsync(HANDLE pipe, DWORD count, LPHANDLE events) { - return AsyncPipeOp (peek, pipe, NULL, 0, count, events); + return AsyncPipeOp(peek, pipe, NULL, 0, count, events); } static DWORD -ReadPipeAsync (HANDLE pipe, LPVOID buffer, DWORD size, DWORD count, LPHANDLE events) +ReadPipeAsync(HANDLE pipe, LPVOID buffer, DWORD size, DWORD count, LPHANDLE events) { - return AsyncPipeOp (read, pipe, buffer, size, count, events); + return AsyncPipeOp(read, pipe, buffer, size, count, events); } static DWORD -WritePipeAsync (HANDLE pipe, LPVOID data, DWORD size, DWORD count, LPHANDLE events) +WritePipeAsync(HANDLE pipe, LPVOID data, DWORD size, DWORD count, LPHANDLE events) { - return AsyncPipeOp (write, pipe, data, size, count, events); + return AsyncPipeOp(write, pipe, data, size, count, events); } static VOID -ReturnProcessId (HANDLE pipe, DWORD pid, DWORD count, LPHANDLE events) +ReturnProcessId(HANDLE pipe, DWORD pid, DWORD count, LPHANDLE events) { - const WCHAR msg[] = L"Process ID"; - WCHAR buf[22 + _countof(msg)]; /* 10 chars each for error and PID and 2 for line breaks */ + const WCHAR msg[] = L"Process ID"; + WCHAR buf[22 + _countof(msg)]; /* 10 chars each for error and PID and 2 for line breaks */ - /* - * Same format as error messages (3 line string) with error = 0 in - * 0x%08x format, PID on line 2 and a description "Process ID" on line 3 - */ - _snwprintf (buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); - buf[_countof(buf) - 1] = '\0'; + /* + * Same format as error messages (3 line string) with error = 0 in + * 0x%08x format, PID on line 2 and a description "Process ID" on line 3 + */ + _snwprintf(buf, _countof(buf), L"0x%08x\n0x%08x\n%s", 0, pid, msg); + buf[_countof(buf) - 1] = '\0'; - WritePipeAsync (pipe, buf, wcslen (buf) * 2, count, events); + WritePipeAsync(pipe, buf, wcslen(buf) * 2, count, events); } static VOID -ReturnError (HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events) +ReturnError(HANDLE pipe, DWORD error, LPCWSTR func, DWORD count, LPHANDLE events) { - DWORD result_len; - LPWSTR result = L"0xffffffff\nFormatMessage failed\nCould not return result"; - DWORD_PTR args[] = { - (DWORD_PTR) error, - (DWORD_PTR) func, - (DWORD_PTR) "" - }; + DWORD result_len; + LPWSTR result = L"0xffffffff\nFormatMessage failed\nCould not return result"; + DWORD_PTR args[] = { + (DWORD_PTR) error, + (DWORD_PTR) func, + (DWORD_PTR) "" + }; - if (error != ERROR_OPENVPN_STARTUP) + if (error != ERROR_OPENVPN_STARTUP) { - FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS, - 0, error, 0, (LPWSTR) &args[2], 0, NULL); + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM + |FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_IGNORE_INSERTS, + 0, error, 0, (LPWSTR) &args[2], 0, NULL); } - result_len = FormatMessageW (FORMAT_MESSAGE_FROM_STRING | - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_ARGUMENT_ARRAY, - L"0x%1!08x!\n%2!s!\n%3!s!", 0, 0, - (LPWSTR) &result, 0, (va_list*) args); + result_len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING + |FORMAT_MESSAGE_ALLOCATE_BUFFER + |FORMAT_MESSAGE_ARGUMENT_ARRAY, + L"0x%1!08x!\n%2!s!\n%3!s!", 0, 0, + (LPWSTR) &result, 0, (va_list *) args); - WritePipeAsync (pipe, result, wcslen (result) * 2, count, events); + WritePipeAsync(pipe, result, wcslen(result) * 2, count, events); #ifdef UNICODE - MsgToEventLog (MSG_FLAGS_ERROR, result); + MsgToEventLog(MSG_FLAGS_ERROR, result); #else - MsgToEventLog (MSG_FLAGS_ERROR, "%S", result); + MsgToEventLog(MSG_FLAGS_ERROR, "%S", result); #endif - if (error != ERROR_OPENVPN_STARTUP) - LocalFree ((LPVOID) args[2]); - if (result_len) - LocalFree (result); + if (error != ERROR_OPENVPN_STARTUP) + { + LocalFree((LPVOID) args[2]); + } + if (result_len) + { + LocalFree(result); + } } static VOID -ReturnLastError (HANDLE pipe, LPCWSTR func) +ReturnLastError(HANDLE pipe, LPCWSTR func) { - ReturnError (pipe, GetLastError (), func, 1, &exit_event); + ReturnError(pipe, GetLastError(), func, 1, &exit_event); } static VOID -ReturnOpenvpnOutput (HANDLE pipe, HANDLE ovpn_output, DWORD count, LPHANDLE events) +ReturnOpenvpnOutput(HANDLE pipe, HANDLE ovpn_output, DWORD count, LPHANDLE events) { - WCHAR *wide_output = NULL; - CHAR output[512]; - DWORD size; + WCHAR *wide_output = NULL; + CHAR output[512]; + DWORD size; - ReadFile (ovpn_output, output, sizeof (output), &size, NULL); - if (size == 0) - return; + ReadFile(ovpn_output, output, sizeof(output), &size, NULL); + if (size == 0) + { + return; + } - wide_output = malloc ((size) * sizeof (WCHAR)); - if (wide_output) + wide_output = malloc((size) * sizeof(WCHAR)); + if (wide_output) { - MultiByteToWideChar (CP_UTF8, 0, output, size, wide_output, size); - wide_output[size - 1] = 0; + MultiByteToWideChar(CP_UTF8, 0, output, size, wide_output, size); + wide_output[size - 1] = 0; } - ReturnError (pipe, ERROR_OPENVPN_STARTUP, wide_output, count, events); - free (wide_output); + ReturnError(pipe, ERROR_OPENVPN_STARTUP, wide_output, count, events); + free(wide_output); } /* @@ -328,7 +354,7 @@ ReturnOpenvpnOutput (HANDLE pipe, HANDLE ovpn_output, DWORD count, LPHANDLE even * Returns true on success */ static BOOL -ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) +ValidateOptions(HANDLE pipe, const WCHAR *workdir, const WCHAR *options) { WCHAR **argv; int argc; @@ -340,15 +366,15 @@ ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) " by adding your account to the \"%s\" group"; const WCHAR *msg2 = L"You have specified an option (%s) that may be used" - " only with admin approval. This error may be avoided" - " by adding your account to the \"%s\" group"; + " only with admin approval. This error may be avoided" + " by adding your account to the \"%s\" group"; - argv = CommandLineToArgvW (options, &argc); + argv = CommandLineToArgvW(options, &argc); if (!argv) { - ReturnLastError (pipe, L"CommandLineToArgvW"); - ReturnError (pipe, ERROR_STARTUP_DATA, L"Cannot validate options", 1, &exit_event); + ReturnLastError(pipe, L"CommandLineToArgvW"); + ReturnError(pipe, ERROR_STARTUP_DATA, L"Cannot validate options", 1, &exit_event); goto out; } @@ -366,12 +392,12 @@ ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) { WCHAR *argv_tmp[2] = { L"--config", argv[0] }; - if (!CheckOption (workdir, 2, argv_tmp, &settings)) + if (!CheckOption(workdir, 2, argv_tmp, &settings)) { - snwprintf (buf, _countof(buf), msg1, argv[0], workdir, - settings.ovpn_admin_group); + snwprintf(buf, _countof(buf), msg1, argv[0], workdir, + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; - ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); + ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } @@ -379,23 +405,25 @@ ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) for (i = 0; i < argc; ++i) { if (!IsOption(argv[i])) + { continue; + } - if (!CheckOption (workdir, argc-i, &argv[i], &settings)) + if (!CheckOption(workdir, argc-i, &argv[i], &settings)) { if (wcscmp(L"--config", argv[i]) == 0 && argc-i > 1) { - snwprintf (buf, _countof(buf), msg1, argv[i+1], workdir, - settings.ovpn_admin_group); + snwprintf(buf, _countof(buf), msg1, argv[i+1], workdir, + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; - ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); + ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } else { - snwprintf (buf, _countof(buf), msg2, argv[i], - settings.ovpn_admin_group); + snwprintf(buf, _countof(buf), msg2, argv[i], + settings.ovpn_admin_group); buf[_countof(buf) - 1] = L'\0'; - ReturnError (pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); + ReturnError(pipe, ERROR_STARTUP_DATA, buf, 1, &exit_event); } goto out; } @@ -406,427 +434,494 @@ ValidateOptions (HANDLE pipe, const WCHAR *workdir, const WCHAR *options) out: if (argv) - LocalFree (argv); + { + LocalFree(argv); + } return ret; } static BOOL -GetStartupData (HANDLE pipe, STARTUP_DATA *sud) +GetStartupData(HANDLE pipe, STARTUP_DATA *sud) { - size_t len; - BOOL ret = FALSE; - WCHAR *data = NULL; - DWORD size, bytes, read; + size_t len; + BOOL ret = FALSE; + WCHAR *data = NULL; + DWORD size, bytes, read; - bytes = PeekNamedPipeAsync (pipe, 1, &exit_event); - if (bytes == 0) + bytes = PeekNamedPipeAsync(pipe, 1, &exit_event); + if (bytes == 0) { - MsgToEventLog (M_SYSERR, TEXT("PeekNamedPipeAsync failed")); - ReturnLastError (pipe, L"PeekNamedPipeAsync"); - goto out; + MsgToEventLog(M_SYSERR, TEXT("PeekNamedPipeAsync failed")); + ReturnLastError(pipe, L"PeekNamedPipeAsync"); + goto out; } - size = bytes / sizeof (*data); - data = malloc (bytes); - if (data == NULL) + size = bytes / sizeof(*data); + data = malloc(bytes); + if (data == NULL) { - MsgToEventLog (M_SYSERR, TEXT("malloc failed")); - ReturnLastError (pipe, L"malloc"); - goto out; + MsgToEventLog(M_SYSERR, TEXT("malloc failed")); + ReturnLastError(pipe, L"malloc"); + goto out; } - read = ReadPipeAsync (pipe, data, bytes, 1, &exit_event); - if (bytes != read) - { - MsgToEventLog (M_SYSERR, TEXT("ReadPipeAsync failed")); - ReturnLastError (pipe, L"ReadPipeAsync"); - goto out; - } + read = ReadPipeAsync(pipe, data, bytes, 1, &exit_event); + if (bytes != read) + { + MsgToEventLog(M_SYSERR, TEXT("ReadPipeAsync failed")); + ReturnLastError(pipe, L"ReadPipeAsync"); + goto out; + } - if (data[size - 1] != 0) + if (data[size - 1] != 0) { - MsgToEventLog (M_ERR, TEXT("Startup data is not NULL terminated")); - ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); - goto out; + MsgToEventLog(M_ERR, TEXT("Startup data is not NULL terminated")); + ReturnError(pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); + goto out; } - sud->directory = data; - len = wcslen (sud->directory) + 1; - size -= len; - if (size <= 0) + sud->directory = data; + len = wcslen(sud->directory) + 1; + size -= len; + if (size <= 0) { - MsgToEventLog (M_ERR, TEXT("Startup data ends at working directory")); - ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); - goto out; + MsgToEventLog(M_ERR, TEXT("Startup data ends at working directory")); + ReturnError(pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); + goto out; } - sud->options = sud->directory + len; - len = wcslen (sud->options) + 1; - size -= len; - if (size <= 0) + sud->options = sud->directory + len; + len = wcslen(sud->options) + 1; + size -= len; + if (size <= 0) { - MsgToEventLog (M_ERR, TEXT("Startup data ends at command line options")); - ReturnError (pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); - goto out; + MsgToEventLog(M_ERR, TEXT("Startup data ends at command line options")); + ReturnError(pipe, ERROR_STARTUP_DATA, L"GetStartupData", 1, &exit_event); + goto out; } - sud->std_input = sud->options + len; - data = NULL; /* don't free data */ - ret = TRUE; + sud->std_input = sud->options + len; + data = NULL; /* don't free data */ + ret = TRUE; out: - free (data); - return ret; + free(data); + return ret; } static VOID -FreeStartupData (STARTUP_DATA *sud) +FreeStartupData(STARTUP_DATA *sud) { - free (sud->directory); + free(sud->directory); } static SOCKADDR_INET -sockaddr_inet (short family, inet_address_t *addr) +sockaddr_inet(short family, inet_address_t *addr) { - SOCKADDR_INET sa_inet; - ZeroMemory (&sa_inet, sizeof (sa_inet)); - sa_inet.si_family = family; - if (family == AF_INET) - sa_inet.Ipv4.sin_addr = addr->ipv4; - else if (family == AF_INET6) - sa_inet.Ipv6.sin6_addr = addr->ipv6; - return sa_inet; + SOCKADDR_INET sa_inet; + ZeroMemory(&sa_inet, sizeof(sa_inet)); + sa_inet.si_family = family; + if (family == AF_INET) + { + sa_inet.Ipv4.sin_addr = addr->ipv4; + } + else if (family == AF_INET6) + { + sa_inet.Ipv6.sin6_addr = addr->ipv6; + } + return sa_inet; } static DWORD -InterfaceLuid (const char *iface_name, PNET_LUID luid) +InterfaceLuid(const char *iface_name, PNET_LUID luid) { - NETIO_STATUS status; - LPWSTR wide_name; - int n; + NETIO_STATUS status; + LPWSTR wide_name; + int n; - typedef NETIO_STATUS WINAPI (*ConvertInterfaceAliasToLuidFn) (LPCWSTR, PNET_LUID); - static ConvertInterfaceAliasToLuidFn ConvertInterfaceAliasToLuid = NULL; - if (!ConvertInterfaceAliasToLuid) + typedef NETIO_STATUS WINAPI (*ConvertInterfaceAliasToLuidFn) (LPCWSTR, PNET_LUID); + static ConvertInterfaceAliasToLuidFn ConvertInterfaceAliasToLuid = NULL; + if (!ConvertInterfaceAliasToLuid) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - ConvertInterfaceAliasToLuid = (ConvertInterfaceAliasToLuidFn) GetProcAddress (iphlpapi, "ConvertInterfaceAliasToLuid"); - if (!ConvertInterfaceAliasToLuid) - return GetLastError (); + ConvertInterfaceAliasToLuid = (ConvertInterfaceAliasToLuidFn) GetProcAddress(iphlpapi, "ConvertInterfaceAliasToLuid"); + if (!ConvertInterfaceAliasToLuid) + { + return GetLastError(); + } } - n = MultiByteToWideChar (CP_UTF8, 0, iface_name, -1, NULL, 0); - wide_name = malloc (n * sizeof (WCHAR)); - MultiByteToWideChar (CP_UTF8, 0, iface_name, -1, wide_name, n); - status = ConvertInterfaceAliasToLuid (wide_name, luid); - free (wide_name); + n = MultiByteToWideChar(CP_UTF8, 0, iface_name, -1, NULL, 0); + wide_name = malloc(n * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, iface_name, -1, wide_name, n); + status = ConvertInterfaceAliasToLuid(wide_name, luid); + free(wide_name); - return status; + return status; } static BOOL -CmpAddress (LPVOID item, LPVOID address) +CmpAddress(LPVOID item, LPVOID address) { - return memcmp (item, address, sizeof (MIB_UNICASTIPADDRESS_ROW)) == 0 ? TRUE : FALSE; + return memcmp(item, address, sizeof(MIB_UNICASTIPADDRESS_ROW)) == 0 ? TRUE : FALSE; } static DWORD -DeleteAddress (PMIB_UNICASTIPADDRESS_ROW addr_row) +DeleteAddress(PMIB_UNICASTIPADDRESS_ROW addr_row) { - typedef NETIOAPI_API (*DeleteUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); - static DeleteUnicastIpAddressEntryFn DeleteUnicastIpAddressEntry = NULL; + typedef NETIOAPI_API (*DeleteUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); + static DeleteUnicastIpAddressEntryFn DeleteUnicastIpAddressEntry = NULL; - if (!DeleteUnicastIpAddressEntry) + if (!DeleteUnicastIpAddressEntry) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - DeleteUnicastIpAddressEntry = (DeleteUnicastIpAddressEntryFn) GetProcAddress (iphlpapi, "DeleteUnicastIpAddressEntry"); - if (!DeleteUnicastIpAddressEntry) - return GetLastError (); + DeleteUnicastIpAddressEntry = (DeleteUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "DeleteUnicastIpAddressEntry"); + if (!DeleteUnicastIpAddressEntry) + { + return GetLastError(); + } } - return DeleteUnicastIpAddressEntry (addr_row); + return DeleteUnicastIpAddressEntry(addr_row); } static DWORD -HandleAddressMessage (address_message_t *msg, undo_lists_t *lists) +HandleAddressMessage(address_message_t *msg, undo_lists_t *lists) { - DWORD err; - PMIB_UNICASTIPADDRESS_ROW addr_row; - BOOL add = msg->header.type == msg_add_address; + DWORD err; + PMIB_UNICASTIPADDRESS_ROW addr_row; + BOOL add = msg->header.type == msg_add_address; - typedef NETIOAPI_API (*CreateUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); - typedef NETIOAPI_API (*InitializeUnicastIpAddressEntryFn) (PMIB_UNICASTIPADDRESS_ROW); - static CreateUnicastIpAddressEntryFn CreateUnicastIpAddressEntry = NULL; - static InitializeUnicastIpAddressEntryFn InitializeUnicastIpAddressEntry = NULL; + typedef NETIOAPI_API (*CreateUnicastIpAddressEntryFn) (const PMIB_UNICASTIPADDRESS_ROW); + typedef NETIOAPI_API (*InitializeUnicastIpAddressEntryFn) (PMIB_UNICASTIPADDRESS_ROW); + static CreateUnicastIpAddressEntryFn CreateUnicastIpAddressEntry = NULL; + static InitializeUnicastIpAddressEntryFn InitializeUnicastIpAddressEntry = NULL; - if (!CreateUnicastIpAddressEntry || !InitializeUnicastIpAddressEntry) + if (!CreateUnicastIpAddressEntry || !InitializeUnicastIpAddressEntry) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - CreateUnicastIpAddressEntry = (CreateUnicastIpAddressEntryFn) GetProcAddress (iphlpapi, "CreateUnicastIpAddressEntry"); - if (!CreateUnicastIpAddressEntry) - return GetLastError (); + CreateUnicastIpAddressEntry = (CreateUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "CreateUnicastIpAddressEntry"); + if (!CreateUnicastIpAddressEntry) + { + return GetLastError(); + } - InitializeUnicastIpAddressEntry = (InitializeUnicastIpAddressEntryFn) GetProcAddress (iphlpapi, "InitializeUnicastIpAddressEntry"); - if (!InitializeUnicastIpAddressEntry) - return GetLastError (); + InitializeUnicastIpAddressEntry = (InitializeUnicastIpAddressEntryFn) GetProcAddress(iphlpapi, "InitializeUnicastIpAddressEntry"); + if (!InitializeUnicastIpAddressEntry) + { + return GetLastError(); + } } - addr_row = malloc (sizeof (*addr_row)); - if (addr_row == NULL) - return ERROR_OUTOFMEMORY; + addr_row = malloc(sizeof(*addr_row)); + if (addr_row == NULL) + { + return ERROR_OUTOFMEMORY; + } - InitializeUnicastIpAddressEntry (addr_row); - addr_row->Address = sockaddr_inet (msg->family, &msg->address); - addr_row->OnLinkPrefixLength = (UINT8) msg->prefix_len; + InitializeUnicastIpAddressEntry(addr_row); + addr_row->Address = sockaddr_inet(msg->family, &msg->address); + addr_row->OnLinkPrefixLength = (UINT8) msg->prefix_len; - if (msg->iface.index != -1) + if (msg->iface.index != -1) { - addr_row->InterfaceIndex = msg->iface.index; + addr_row->InterfaceIndex = msg->iface.index; } - else + else { - NET_LUID luid; - err = InterfaceLuid (msg->iface.name, &luid); - if (err) - goto out; - addr_row->InterfaceLuid = luid; + NET_LUID luid; + err = InterfaceLuid(msg->iface.name, &luid); + if (err) + { + goto out; + } + addr_row->InterfaceLuid = luid; } - if (add) + if (add) { - err = CreateUnicastIpAddressEntry (addr_row); - if (err) - goto out; + err = CreateUnicastIpAddressEntry(addr_row); + if (err) + { + goto out; + } - err = AddListItem (&(*lists)[address], addr_row); - if (err) - DeleteAddress (addr_row); + err = AddListItem(&(*lists)[address], addr_row); + if (err) + { + DeleteAddress(addr_row); + } } - else + else { - err = DeleteAddress (addr_row); - if (err) - goto out; + err = DeleteAddress(addr_row); + if (err) + { + goto out; + } - free (RemoveListItem (&(*lists)[address], CmpAddress, addr_row)); + free(RemoveListItem(&(*lists)[address], CmpAddress, addr_row)); } out: - if (!add || err) - free (addr_row); + if (!add || err) + { + free(addr_row); + } - return err; + return err; } static BOOL -CmpRoute (LPVOID item, LPVOID route) +CmpRoute(LPVOID item, LPVOID route) { - return memcmp (item, route, sizeof (MIB_IPFORWARD_ROW2)) == 0 ? TRUE : FALSE; + return memcmp(item, route, sizeof(MIB_IPFORWARD_ROW2)) == 0 ? TRUE : FALSE; } static DWORD -DeleteRoute (PMIB_IPFORWARD_ROW2 fwd_row) +DeleteRoute(PMIB_IPFORWARD_ROW2 fwd_row) { - typedef NETIOAPI_API (*DeleteIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); - static DeleteIpForwardEntry2Fn DeleteIpForwardEntry2 = NULL; + typedef NETIOAPI_API (*DeleteIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); + static DeleteIpForwardEntry2Fn DeleteIpForwardEntry2 = NULL; - if (!DeleteIpForwardEntry2) + if (!DeleteIpForwardEntry2) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - DeleteIpForwardEntry2 = (DeleteIpForwardEntry2Fn) GetProcAddress (iphlpapi, "DeleteIpForwardEntry2"); - if (!DeleteIpForwardEntry2) - return GetLastError (); + DeleteIpForwardEntry2 = (DeleteIpForwardEntry2Fn) GetProcAddress(iphlpapi, "DeleteIpForwardEntry2"); + if (!DeleteIpForwardEntry2) + { + return GetLastError(); + } } - return DeleteIpForwardEntry2 (fwd_row); + return DeleteIpForwardEntry2(fwd_row); } static DWORD -HandleRouteMessage (route_message_t *msg, undo_lists_t *lists) +HandleRouteMessage(route_message_t *msg, undo_lists_t *lists) { - DWORD err; - PMIB_IPFORWARD_ROW2 fwd_row; - BOOL add = msg->header.type == msg_add_route; + DWORD err; + PMIB_IPFORWARD_ROW2 fwd_row; + BOOL add = msg->header.type == msg_add_route; - typedef NETIOAPI_API (*CreateIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); - static CreateIpForwardEntry2Fn CreateIpForwardEntry2 = NULL; + typedef NETIOAPI_API (*CreateIpForwardEntry2Fn) (PMIB_IPFORWARD_ROW2); + static CreateIpForwardEntry2Fn CreateIpForwardEntry2 = NULL; - if (!CreateIpForwardEntry2) + if (!CreateIpForwardEntry2) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - CreateIpForwardEntry2 = (CreateIpForwardEntry2Fn) GetProcAddress (iphlpapi, "CreateIpForwardEntry2"); - if (!CreateIpForwardEntry2) - return GetLastError (); + CreateIpForwardEntry2 = (CreateIpForwardEntry2Fn) GetProcAddress(iphlpapi, "CreateIpForwardEntry2"); + if (!CreateIpForwardEntry2) + { + return GetLastError(); + } } - fwd_row = malloc (sizeof (*fwd_row)); - if (fwd_row == NULL) - return ERROR_OUTOFMEMORY; + fwd_row = malloc(sizeof(*fwd_row)); + if (fwd_row == NULL) + { + return ERROR_OUTOFMEMORY; + } - ZeroMemory (fwd_row, sizeof (*fwd_row)); - fwd_row->ValidLifetime = 0xffffffff; - fwd_row->PreferredLifetime = 0xffffffff; - fwd_row->Protocol = MIB_IPPROTO_NETMGMT; - fwd_row->Metric = msg->metric; - fwd_row->DestinationPrefix.Prefix = sockaddr_inet (msg->family, &msg->prefix); - fwd_row->DestinationPrefix.PrefixLength = (UINT8) msg->prefix_len; - fwd_row->NextHop = sockaddr_inet (msg->family, &msg->gateway); + ZeroMemory(fwd_row, sizeof(*fwd_row)); + fwd_row->ValidLifetime = 0xffffffff; + fwd_row->PreferredLifetime = 0xffffffff; + fwd_row->Protocol = MIB_IPPROTO_NETMGMT; + fwd_row->Metric = msg->metric; + fwd_row->DestinationPrefix.Prefix = sockaddr_inet(msg->family, &msg->prefix); + fwd_row->DestinationPrefix.PrefixLength = (UINT8) msg->prefix_len; + fwd_row->NextHop = sockaddr_inet(msg->family, &msg->gateway); - if (msg->iface.index != -1) + if (msg->iface.index != -1) { - fwd_row->InterfaceIndex = msg->iface.index; + fwd_row->InterfaceIndex = msg->iface.index; } - else if (strlen (msg->iface.name)) + else if (strlen(msg->iface.name)) { - NET_LUID luid; - err = InterfaceLuid (msg->iface.name, &luid); - if (err) - goto out; - fwd_row->InterfaceLuid = luid; + NET_LUID luid; + err = InterfaceLuid(msg->iface.name, &luid); + if (err) + { + goto out; + } + fwd_row->InterfaceLuid = luid; } - if (add) + if (add) { - err = CreateIpForwardEntry2 (fwd_row); - if (err) - goto out; + err = CreateIpForwardEntry2(fwd_row); + if (err) + { + goto out; + } - err = AddListItem (&(*lists)[route], fwd_row); - if (err) - DeleteRoute (fwd_row); + err = AddListItem(&(*lists)[route], fwd_row); + if (err) + { + DeleteRoute(fwd_row); + } } - else + else { - err = DeleteRoute (fwd_row); - if (err) - goto out; + err = DeleteRoute(fwd_row); + if (err) + { + goto out; + } - free (RemoveListItem (&(*lists)[route], CmpRoute, fwd_row)); + free(RemoveListItem(&(*lists)[route], CmpRoute, fwd_row)); } out: - if (!add || err) - free (fwd_row); + if (!add || err) + { + free(fwd_row); + } - return err; + return err; } static DWORD -HandleFlushNeighborsMessage (flush_neighbors_message_t *msg) +HandleFlushNeighborsMessage(flush_neighbors_message_t *msg) { - typedef NETIOAPI_API (*FlushIpNetTable2Fn) (ADDRESS_FAMILY, NET_IFINDEX); - static FlushIpNetTable2Fn flush_fn = NULL; + typedef NETIOAPI_API (*FlushIpNetTable2Fn) (ADDRESS_FAMILY, NET_IFINDEX); + static FlushIpNetTable2Fn flush_fn = NULL; - if (msg->family == AF_INET) - return FlushIpNetTable (msg->iface.index); + if (msg->family == AF_INET) + { + return FlushIpNetTable(msg->iface.index); + } - if (!flush_fn) + if (!flush_fn) { - HMODULE iphlpapi = GetModuleHandle (TEXT("iphlpapi.dll")); - if (iphlpapi == NULL) - return GetLastError (); + HMODULE iphlpapi = GetModuleHandle(TEXT("iphlpapi.dll")); + if (iphlpapi == NULL) + { + return GetLastError(); + } - flush_fn = (FlushIpNetTable2Fn) GetProcAddress (iphlpapi, "FlushIpNetTable2"); - if (!flush_fn) + flush_fn = (FlushIpNetTable2Fn) GetProcAddress(iphlpapi, "FlushIpNetTable2"); + if (!flush_fn) { - if (GetLastError () == ERROR_PROC_NOT_FOUND) - return WSAEPFNOSUPPORT; - else - return GetLastError (); + if (GetLastError() == ERROR_PROC_NOT_FOUND) + { + return WSAEPFNOSUPPORT; + } + else + { + return GetLastError(); + } } } - return flush_fn (msg->family, msg->iface.index); + return flush_fn(msg->family, msg->iface.index); } static void -BlockDNSErrHandler (DWORD err, const char *msg) +BlockDNSErrHandler(DWORD err, const char *msg) { - TCHAR buf[256]; - LPCTSTR err_str; + TCHAR buf[256]; + LPCTSTR err_str; - if (!err) return; + if (!err) + { + return; + } - err_str = TEXT("Unknown Win32 Error"); + err_str = TEXT("Unknown Win32 Error"); - if (FormatMessage (FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_ARGUMENT_ARRAY, - NULL, err, 0, buf, sizeof (buf), NULL)) + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ARGUMENT_ARRAY, + NULL, err, 0, buf, sizeof(buf), NULL)) { - err_str = buf; + err_str = buf; } #ifdef UNICODE - MsgToEventLog (M_ERR, L"%S (status = %lu): %s", msg, err, err_str); + MsgToEventLog(M_ERR, L"%S (status = %lu): %s", msg, err, err_str); #else - MsgToEventLog (M_ERR, "%s (status = %lu): %s", msg, err, err_str); + MsgToEventLog(M_ERR, "%s (status = %lu): %s", msg, err, err_str); #endif } /* Use an always-true match_fn to get the head of the list */ static BOOL -CmpEngine (LPVOID item, LPVOID any) +CmpEngine(LPVOID item, LPVOID any) { - return TRUE; + return TRUE; } static DWORD -HandleBlockDNSMessage (const block_dns_message_t *msg, undo_lists_t *lists) +HandleBlockDNSMessage(const block_dns_message_t *msg, undo_lists_t *lists) { - DWORD err = 0; - HANDLE engine = NULL; - LPCWSTR exe_path; + DWORD err = 0; + HANDLE engine = NULL; + LPCWSTR exe_path; #ifdef UNICODE - exe_path = settings.exe_path; + exe_path = settings.exe_path; #else - WCHAR wide_path[MAX_PATH]; - MultiByteToWideChar (CP_UTF8, 0, settings.exe_path, MAX_PATH, wide_path, MAX_PATH); - exe_path = wide_path; + WCHAR wide_path[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, settings.exe_path, MAX_PATH, wide_path, MAX_PATH); + exe_path = wide_path; #endif - if (msg->header.type == msg_add_block_dns) + if (msg->header.type == msg_add_block_dns) { - err = add_block_dns_filters (&engine, msg->iface.index, exe_path, BlockDNSErrHandler); - if (!err) - err = AddListItem (&(*lists)[block_dns], engine); + err = add_block_dns_filters(&engine, msg->iface.index, exe_path, BlockDNSErrHandler); + if (!err) + { + err = AddListItem(&(*lists)[block_dns], engine); + } } - else + else { - engine = RemoveListItem (&(*lists)[block_dns], CmpEngine, NULL); - if (engine) + engine = RemoveListItem(&(*lists)[block_dns], CmpEngine, NULL); + if (engine) + { + err = delete_block_dns_filters(engine); + engine = NULL; + } + else { - err = delete_block_dns_filters (engine); - engine = NULL; + MsgToEventLog(M_ERR, TEXT("No previous block DNS filters to delete")); } - else - MsgToEventLog (M_ERR, TEXT("No previous block DNS filters to delete")); } - if (err && engine) + if (err && engine) { - delete_block_dns_filters (engine); + delete_block_dns_filters(engine); } - return err; + return err; } /* @@ -835,133 +930,141 @@ HandleBlockDNSMessage (const block_dns_message_t *msg, undo_lists_t *lists) * the return value is the windows error code WAIT_TIMEOUT = 0x102 */ static DWORD -ExecCommand (const WCHAR *argv0, const WCHAR *cmdline, DWORD timeout) +ExecCommand(const WCHAR *argv0, const WCHAR *cmdline, DWORD timeout) { - DWORD exit_code; - STARTUPINFOW si; - PROCESS_INFORMATION pi; - DWORD proc_flags = CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT; - WCHAR *cmdline_dup = NULL; + DWORD exit_code; + STARTUPINFOW si; + PROCESS_INFORMATION pi; + DWORD proc_flags = CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT; + WCHAR *cmdline_dup = NULL; - ZeroMemory (&si, sizeof(si)); - ZeroMemory (&pi, sizeof(pi)); + ZeroMemory(&si, sizeof(si)); + ZeroMemory(&pi, sizeof(pi)); - si.cb = sizeof(si); + si.cb = sizeof(si); - /* CreateProcess needs a modifiable cmdline: make a copy */ - cmdline_dup = wcsdup (cmdline); - if ( cmdline_dup && CreateProcessW (argv0, cmdline_dup, NULL, NULL, FALSE, + /* CreateProcess needs a modifiable cmdline: make a copy */ + cmdline_dup = wcsdup(cmdline); + if (cmdline_dup && CreateProcessW(argv0, cmdline_dup, NULL, NULL, FALSE, proc_flags, NULL, NULL, &si, &pi) ) { - WaitForSingleObject (pi.hProcess, timeout ? timeout : INFINITE); - if (!GetExitCodeProcess (pi.hProcess, &exit_code)) + WaitForSingleObject(pi.hProcess, timeout ? timeout : INFINITE); + if (!GetExitCodeProcess(pi.hProcess, &exit_code)) { - MsgToEventLog (M_SYSERR, TEXT("ExecCommand: Error getting exit_code:")); - exit_code = GetLastError(); + MsgToEventLog(M_SYSERR, TEXT("ExecCommand: Error getting exit_code:")); + exit_code = GetLastError(); } - else if (exit_code == STILL_ACTIVE) + else if (exit_code == STILL_ACTIVE) { - exit_code = WAIT_TIMEOUT; /* Windows error code 0x102 */ + exit_code = WAIT_TIMEOUT; /* Windows error code 0x102 */ - /* kill without impunity */ - TerminateProcess (pi.hProcess, exit_code); - MsgToEventLog (M_ERR, TEXT("ExecCommand: \"%s %s\" killed after timeout"), - argv0, cmdline); + /* kill without impunity */ + TerminateProcess(pi.hProcess, exit_code); + MsgToEventLog(M_ERR, TEXT("ExecCommand: \"%s %s\" killed after timeout"), + argv0, cmdline); } - else if (exit_code) - MsgToEventLog (M_ERR, TEXT("ExecCommand: \"%s %s\" exited with status = %lu"), + else if (exit_code) + { + MsgToEventLog(M_ERR, TEXT("ExecCommand: \"%s %s\" exited with status = %lu"), argv0, cmdline, exit_code); - else - MsgToEventLog (M_INFO, TEXT("ExecCommand: \"%s %s\" completed"), argv0, cmdline); + } + else + { + MsgToEventLog(M_INFO, TEXT("ExecCommand: \"%s %s\" completed"), argv0, cmdline); + } - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); } - else + else { - exit_code = GetLastError(); - MsgToEventLog (M_SYSERR, TEXT("ExecCommand: could not run \"%s %s\" :"), - argv0, cmdline); + exit_code = GetLastError(); + MsgToEventLog(M_SYSERR, TEXT("ExecCommand: could not run \"%s %s\" :"), + argv0, cmdline); } - free (cmdline_dup); - return exit_code; + free(cmdline_dup); + return exit_code; } /* * Entry point for register-dns thread. */ static DWORD WINAPI -RegisterDNS (LPVOID unused) +RegisterDNS(LPVOID unused) { - DWORD err; - DWORD i; - WCHAR sys_path[MAX_PATH]; - DWORD timeout = RDNS_TIMEOUT * 1000; /* in milliseconds */ + DWORD err; + DWORD i; + WCHAR sys_path[MAX_PATH]; + DWORD timeout = RDNS_TIMEOUT * 1000; /* in milliseconds */ - /* default path of ipconfig command */ - WCHAR ipcfg[MAX_PATH] = L"C:\\Windows\\system32\\ipconfig.exe"; + /* default path of ipconfig command */ + WCHAR ipcfg[MAX_PATH] = L"C:\\Windows\\system32\\ipconfig.exe"; - struct + struct { - WCHAR *argv0; - WCHAR *cmdline; - DWORD timeout; + WCHAR *argv0; + WCHAR *cmdline; + DWORD timeout; } cmds [] = { - { ipcfg, L"ipconfig /flushdns", timeout }, - { ipcfg, L"ipconfig /registerdns", timeout }, - }; - int ncmds = sizeof (cmds) / sizeof (cmds[0]); + { ipcfg, L"ipconfig /flushdns", timeout }, + { ipcfg, L"ipconfig /registerdns", timeout }, + }; + int ncmds = sizeof(cmds) / sizeof(cmds[0]); - HANDLE wait_handles[2] = {rdns_semaphore, exit_event}; + HANDLE wait_handles[2] = {rdns_semaphore, exit_event}; - if(GetSystemDirectory(sys_path, MAX_PATH)) + if (GetSystemDirectory(sys_path, MAX_PATH)) { - _snwprintf (ipcfg, MAX_PATH, L"%s\\%s", sys_path, L"ipconfig.exe"); - ipcfg[MAX_PATH-1] = L'\0'; + _snwprintf(ipcfg, MAX_PATH, L"%s\\%s", sys_path, L"ipconfig.exe"); + ipcfg[MAX_PATH-1] = L'\0'; } - if (WaitForMultipleObjects (2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0) + if (WaitForMultipleObjects(2, wait_handles, FALSE, timeout) == WAIT_OBJECT_0) { - /* Semaphore locked */ - for (i = 0; i < ncmds; ++i) + /* Semaphore locked */ + for (i = 0; i < ncmds; ++i) + { + ExecCommand(cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout); + } + err = 0; + if (!ReleaseSemaphore(rdns_semaphore, 1, NULL) ) { - ExecCommand (cmds[i].argv0, cmds[i].cmdline, cmds[i].timeout); + err = MsgToEventLog(M_SYSERR, TEXT("RegisterDNS: Failed to release regsiter-dns semaphore:")); } - err = 0; - if ( !ReleaseSemaphore (rdns_semaphore, 1, NULL) ) - err = MsgToEventLog (M_SYSERR, TEXT("RegisterDNS: Failed to release regsiter-dns semaphore:")); } - else + else { - MsgToEventLog (M_ERR, TEXT("RegisterDNS: Failed to lock register-dns semaphore")); - err = ERROR_SEM_TIMEOUT; /* Windows error code 0x79 */ + MsgToEventLog(M_ERR, TEXT("RegisterDNS: Failed to lock register-dns semaphore")); + err = ERROR_SEM_TIMEOUT; /* Windows error code 0x79 */ } - return err; + return err; } static DWORD -HandleRegisterDNSMessage (void) +HandleRegisterDNSMessage(void) { - DWORD err; - HANDLE thread = NULL; + DWORD err; + HANDLE thread = NULL; - /* Delegate this job to a sub-thread */ - thread = CreateThread (NULL, 0, RegisterDNS, NULL, 0, NULL); + /* Delegate this job to a sub-thread */ + thread = CreateThread(NULL, 0, RegisterDNS, NULL, 0, NULL); - /* - * We don't add these thread handles to the undo list -- the thread and - * processes it spawns are all supposed to terminate or timeout by themselves. - */ - if (thread) + /* + * We don't add these thread handles to the undo list -- the thread and + * processes it spawns are all supposed to terminate or timeout by themselves. + */ + if (thread) + { + err = 0; + CloseHandle(thread); + } + else { - err = 0; - CloseHandle (thread); + err = GetLastError(); } - else - err = GetLastError(); - return err; + return err; } /** @@ -974,845 +1077,904 @@ HandleRegisterDNSMessage (void) * If addr is null and action = "delete" all addresses are deleted. */ static DWORD -netsh_dns_cmd (const wchar_t *action, const wchar_t *proto, const wchar_t *if_name, const wchar_t *addr) +netsh_dns_cmd(const wchar_t *action, const wchar_t *proto, const wchar_t *if_name, const wchar_t *addr) { - DWORD err = 0; - int timeout = 30000; /* in msec */ - wchar_t argv0[MAX_PATH]; + DWORD err = 0; + int timeout = 30000; /* in msec */ + wchar_t argv0[MAX_PATH]; - if (!addr) + if (!addr) { - if (wcscmp(action, L"delete") == 0) - addr = L"all"; - else /* nothing to do -- return success*/ - goto out; + if (wcscmp(action, L"delete") == 0) + { + addr = L"all"; + } + else /* nothing to do -- return success*/ + { + goto out; + } } - /* Path of netsh */ - int n = GetSystemDirectory (argv0, MAX_PATH); - if (n > 0 && n < MAX_PATH) /* got system directory */ - { - wcsncat(argv0, L"\\netsh.exe", MAX_PATH - n - 1); - } - else - { - wcsncpy(argv0, L"C:\\Windows\\system32\\netsh.exe", MAX_PATH); - } + /* Path of netsh */ + int n = GetSystemDirectory(argv0, MAX_PATH); + if (n > 0 && n < MAX_PATH) /* got system directory */ + { + wcsncat(argv0, L"\\netsh.exe", MAX_PATH - n - 1); + } + else + { + wcsncpy(argv0, L"C:\\Windows\\system32\\netsh.exe", MAX_PATH); + } - /* cmd template: - * netsh interface $proto $action dns $if_name $addr [validate=no] - */ - const wchar_t *fmt = L"netsh interface %s %s dns \"%s\" %s"; + /* cmd template: + * netsh interface $proto $action dns $if_name $addr [validate=no] + */ + const wchar_t *fmt = L"netsh interface %s %s dns \"%s\" %s"; - /* max cmdline length in wchars -- include room for worst case and some */ - int ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1; - wchar_t *cmdline = malloc(ncmdline*sizeof(wchar_t)); - if (!cmdline) - { - err = ERROR_OUTOFMEMORY; - goto out; - } + /* max cmdline length in wchars -- include room for worst case and some */ + int ncmdline = wcslen(fmt) + wcslen(if_name) + wcslen(addr) + 32 + 1; + wchar_t *cmdline = malloc(ncmdline*sizeof(wchar_t)); + if (!cmdline) + { + err = ERROR_OUTOFMEMORY; + goto out; + } - openvpn_sntprintf (cmdline, ncmdline, fmt, proto, action, if_name, addr); + openvpn_sntprintf(cmdline, ncmdline, fmt, proto, action, if_name, addr); - if (IsWindows7OrGreater()) + if (IsWindows7OrGreater()) { - wcsncat(cmdline, L" validate=no", ncmdline - wcslen(cmdline) - 1); + wcsncat(cmdline, L" validate=no", ncmdline - wcslen(cmdline) - 1); } - err = ExecCommand (argv0, cmdline, timeout); + err = ExecCommand(argv0, cmdline, timeout); out: - free (cmdline); - return err; + free(cmdline); + return err; } /* Delete all IPv4 or IPv6 dns servers for an interface */ static DWORD DeleteDNS(short family, wchar_t *if_name) { - wchar_t *proto = (family == AF_INET6) ? L"ipv6" : L"ip"; - return netsh_dns_cmd (L"delete", proto, if_name, NULL); + wchar_t *proto = (family == AF_INET6) ? L"ipv6" : L"ip"; + return netsh_dns_cmd(L"delete", proto, if_name, NULL); } /* Add an IPv4 or IPv6 dns server to an interface */ static DWORD AddDNS(short family, wchar_t *if_name, wchar_t *addr) { - wchar_t *proto = (family == AF_INET6) ? L"ipv6" : L"ip"; - return netsh_dns_cmd (L"add", proto, if_name, addr); + wchar_t *proto = (family == AF_INET6) ? L"ipv6" : L"ip"; + return netsh_dns_cmd(L"add", proto, if_name, addr); } static BOOL -CmpWString (LPVOID item, LPVOID str) +CmpWString(LPVOID item, LPVOID str) { - return (wcscmp (item, str) == 0) ? TRUE : FALSE; + return (wcscmp(item, str) == 0) ? TRUE : FALSE; } static DWORD -HandleDNSConfigMessage (const dns_cfg_message_t *msg, undo_lists_t *lists) +HandleDNSConfigMessage(const dns_cfg_message_t *msg, undo_lists_t *lists) { - DWORD err = 0; - wchar_t addr[46]; /* large enough to hold string representation of an ipv4 / ipv6 address */ - undo_type_t undo_type = (msg->family == AF_INET6) ? undo_dns4 : undo_dns6; - int addr_len = msg->addr_len; + DWORD err = 0; + wchar_t addr[46]; /* large enough to hold string representation of an ipv4 / ipv6 address */ + undo_type_t undo_type = (msg->family == AF_INET6) ? undo_dns4 : undo_dns6; + int addr_len = msg->addr_len; - /* sanity check */ - if (addr_len > _countof(msg->addr)) - addr_len = _countof(msg->addr); + /* sanity check */ + if (addr_len > _countof(msg->addr)) + { + addr_len = _countof(msg->addr); + } - if (!msg->iface.name[0]) /* interface name is required */ - return ERROR_MESSAGE_DATA; + if (!msg->iface.name[0]) /* interface name is required */ + { + return ERROR_MESSAGE_DATA; + } - wchar_t *wide_name = utf8to16(msg->iface.name); /* utf8 to wide-char */ - if (!wide_name) - return ERROR_OUTOFMEMORY; + wchar_t *wide_name = utf8to16(msg->iface.name); /* utf8 to wide-char */ + if (!wide_name) + { + return ERROR_OUTOFMEMORY; + } - /* We delete all current addresses before adding any - * OR if the message type is del_dns_cfg - */ - if (addr_len > 0 || msg->header.type == msg_del_dns_cfg) + /* We delete all current addresses before adding any + * OR if the message type is del_dns_cfg + */ + if (addr_len > 0 || msg->header.type == msg_del_dns_cfg) { - err = DeleteDNS(msg->family, wide_name); - if (err) - goto out; - free (RemoveListItem (&(*lists)[undo_type], CmpWString, wide_name)); + err = DeleteDNS(msg->family, wide_name); + if (err) + { + goto out; + } + free(RemoveListItem(&(*lists)[undo_type], CmpWString, wide_name)); } - if (msg->header.type == msg_del_dns_cfg) /* job done */ - goto out; + if (msg->header.type == msg_del_dns_cfg) /* job done */ + { + goto out; + } - for (int i = 0; i < addr_len; ++i) + for (int i = 0; i < addr_len; ++i) { - if (msg->family == AF_INET6) - RtlIpv6AddressToStringW (&msg->addr[i].ipv6, addr); - else - RtlIpv4AddressToStringW (&msg->addr[i].ipv4, addr); - err = AddDNS(msg->family, wide_name, addr); - if (i == 0 && err) - goto out; - /* We do not check for duplicate addresses, so any error in adding - * additional addresses is ignored. - */ + if (msg->family == AF_INET6) + { + RtlIpv6AddressToStringW(&msg->addr[i].ipv6, addr); + } + else + { + RtlIpv4AddressToStringW(&msg->addr[i].ipv4, addr); + } + err = AddDNS(msg->family, wide_name, addr); + if (i == 0 && err) + { + goto out; + } + /* We do not check for duplicate addresses, so any error in adding + * additional addresses is ignored. + */ } - if (msg->addr_len > 0) + if (msg->addr_len > 0) { - wchar_t *tmp_name = wcsdup(wide_name); - if (!tmp_name || AddListItem(&(*lists)[undo_type], tmp_name)) + wchar_t *tmp_name = wcsdup(wide_name); + if (!tmp_name || AddListItem(&(*lists)[undo_type], tmp_name)) { - free(tmp_name); - DeleteDNS(msg->family, wide_name); - err = ERROR_OUTOFMEMORY; - goto out; + free(tmp_name); + DeleteDNS(msg->family, wide_name); + err = ERROR_OUTOFMEMORY; + goto out; } } - err = 0; + err = 0; out: - free(wide_name); - return err; + free(wide_name); + return err; } static VOID -HandleMessage (HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) +HandleMessage(HANDLE pipe, DWORD bytes, DWORD count, LPHANDLE events, undo_lists_t *lists) { - DWORD read; - union { - message_header_t header; - address_message_t address; - route_message_t route; - flush_neighbors_message_t flush_neighbors; - block_dns_message_t block_dns; - dns_cfg_message_t dns; - } msg; - ack_message_t ack = { - .header = { - .type = msg_acknowledgement, - .size = sizeof (ack), - .message_id = -1 - }, - .error_number = ERROR_MESSAGE_DATA - }; - - read = ReadPipeAsync (pipe, &msg, bytes, count, events); - if (read != bytes || read < sizeof (msg.header) || read != msg.header.size) - goto out; - - ack.header.message_id = msg.header.message_id; - - switch (msg.header.type) - { - case msg_add_address: - case msg_del_address: - if (msg.header.size == sizeof (msg.address)) - ack.error_number = HandleAddressMessage (&msg.address, lists); - break; - - case msg_add_route: - case msg_del_route: - if (msg.header.size == sizeof (msg.route)) - ack.error_number = HandleRouteMessage (&msg.route, lists); - break; - - case msg_flush_neighbors: - if (msg.header.size == sizeof (msg.flush_neighbors)) - ack.error_number = HandleFlushNeighborsMessage (&msg.flush_neighbors); - break; - - case msg_add_block_dns: - case msg_del_block_dns: - if (msg.header.size == sizeof (msg.block_dns)) - ack.error_number = HandleBlockDNSMessage (&msg.block_dns, lists); - break; - - case msg_register_dns: - ack.error_number = HandleRegisterDNSMessage (); - break; + DWORD read; + union { + message_header_t header; + address_message_t address; + route_message_t route; + flush_neighbors_message_t flush_neighbors; + block_dns_message_t block_dns; + dns_cfg_message_t dns; + } msg; + ack_message_t ack = { + .header = { + .type = msg_acknowledgement, + .size = sizeof(ack), + .message_id = -1 + }, + .error_number = ERROR_MESSAGE_DATA + }; + + read = ReadPipeAsync(pipe, &msg, bytes, count, events); + if (read != bytes || read < sizeof(msg.header) || read != msg.header.size) + { + goto out; + } - case msg_add_dns_cfg: - case msg_del_dns_cfg: - ack.error_number = HandleDNSConfigMessage (&msg.dns, lists); - break; + ack.header.message_id = msg.header.message_id; + + switch (msg.header.type) + { + case msg_add_address: + case msg_del_address: + if (msg.header.size == sizeof(msg.address)) + { + ack.error_number = HandleAddressMessage(&msg.address, lists); + } + break; + + case msg_add_route: + case msg_del_route: + if (msg.header.size == sizeof(msg.route)) + { + ack.error_number = HandleRouteMessage(&msg.route, lists); + } + break; - default: - ack.error_number = ERROR_MESSAGE_TYPE; - MsgToEventLog (MSG_FLAGS_ERROR, TEXT("Unknown message type %d"), msg.header.type); - break; + case msg_flush_neighbors: + if (msg.header.size == sizeof(msg.flush_neighbors)) + { + ack.error_number = HandleFlushNeighborsMessage(&msg.flush_neighbors); + } + break; + + case msg_add_block_dns: + case msg_del_block_dns: + if (msg.header.size == sizeof(msg.block_dns)) + { + ack.error_number = HandleBlockDNSMessage(&msg.block_dns, lists); + } + break; + + case msg_register_dns: + ack.error_number = HandleRegisterDNSMessage(); + break; + + case msg_add_dns_cfg: + case msg_del_dns_cfg: + ack.error_number = HandleDNSConfigMessage(&msg.dns, lists); + break; + + default: + ack.error_number = ERROR_MESSAGE_TYPE; + MsgToEventLog(MSG_FLAGS_ERROR, TEXT("Unknown message type %d"), msg.header.type); + break; } out: - WritePipeAsync (pipe, &ack, sizeof (ack), count, events); + WritePipeAsync(pipe, &ack, sizeof(ack), count, events); } static VOID -Undo (undo_lists_t *lists) +Undo(undo_lists_t *lists) { - undo_type_t type; - for (type = 0; type < _undo_type_max; type++) + undo_type_t type; + for (type = 0; type < _undo_type_max; type++) { - list_item_t **pnext = &(*lists)[type]; - while (*pnext) + list_item_t **pnext = &(*lists)[type]; + while (*pnext) { - list_item_t *item = *pnext; - switch (type) + list_item_t *item = *pnext; + switch (type) { - case address: - DeleteAddress (item->data); - break; - - case route: - DeleteRoute (item->data); - break; - - case undo_dns4: - DeleteDNS(AF_INET, item->data); - break; - - case undo_dns6: - DeleteDNS(AF_INET6, item->data); - break; - - case block_dns: - delete_block_dns_filters (item->data); - item->data = NULL; - break; + case address: + DeleteAddress(item->data); + break; + + case route: + DeleteRoute(item->data); + break; + + case undo_dns4: + DeleteDNS(AF_INET, item->data); + break; + + case undo_dns6: + DeleteDNS(AF_INET6, item->data); + break; + + case block_dns: + delete_block_dns_filters(item->data); + item->data = NULL; + break; } - /* Remove from the list and free memory */ - *pnext = item->next; - free (item->data); - free (item); + /* Remove from the list and free memory */ + *pnext = item->next; + free(item->data); + free(item); } } } static DWORD WINAPI -RunOpenvpn (LPVOID p) +RunOpenvpn(LPVOID p) { - HANDLE pipe = p; - HANDLE ovpn_pipe, svc_pipe; - PTOKEN_USER svc_user, ovpn_user; - HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL; - HANDLE stdin_read = NULL, stdin_write = NULL; - HANDLE stdout_write = NULL; - DWORD pipe_mode, len, exit_code = 0; - STARTUP_DATA sud = { 0, 0, 0 }; - STARTUPINFOW startup_info; - PROCESS_INFORMATION proc_info; - LPVOID user_env = NULL; - TCHAR ovpn_pipe_name[36]; - LPCWSTR exe_path; - WCHAR *cmdline = NULL; - size_t cmdline_size; - undo_lists_t undo_lists; - - SECURITY_ATTRIBUTES inheritable = { - .nLength = sizeof (inheritable), - .lpSecurityDescriptor = NULL, - .bInheritHandle = TRUE - }; - - PACL ovpn_dacl; - EXPLICIT_ACCESS ea[2]; - SECURITY_DESCRIPTOR ovpn_sd; - SECURITY_ATTRIBUTES ovpn_sa = { - .nLength = sizeof (ovpn_sa), - .lpSecurityDescriptor = &ovpn_sd, - .bInheritHandle = FALSE - }; - - ZeroMemory (&ea, sizeof (ea)); - ZeroMemory (&startup_info, sizeof (startup_info)); - ZeroMemory (&undo_lists, sizeof (undo_lists)); - ZeroMemory (&proc_info, sizeof (proc_info)); - - if (!GetStartupData (pipe, &sud)) - goto out; - - if (!InitializeSecurityDescriptor (&ovpn_sd, SECURITY_DESCRIPTOR_REVISION)) - { - ReturnLastError (pipe, L"InitializeSecurityDescriptor"); - goto out; - } - - /* Get SID of user the service is running under */ - if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &svc_token)) - { - ReturnLastError (pipe, L"OpenProcessToken"); - goto out; - } - len = 0; - svc_user = NULL; - while (!GetTokenInformation (svc_token, TokenUser, svc_user, len, &len)) - { - if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) + HANDLE pipe = p; + HANDLE ovpn_pipe, svc_pipe; + PTOKEN_USER svc_user, ovpn_user; + HANDLE svc_token = NULL, imp_token = NULL, pri_token = NULL; + HANDLE stdin_read = NULL, stdin_write = NULL; + HANDLE stdout_write = NULL; + DWORD pipe_mode, len, exit_code = 0; + STARTUP_DATA sud = { 0, 0, 0 }; + STARTUPINFOW startup_info; + PROCESS_INFORMATION proc_info; + LPVOID user_env = NULL; + TCHAR ovpn_pipe_name[36]; + LPCWSTR exe_path; + WCHAR *cmdline = NULL; + size_t cmdline_size; + undo_lists_t undo_lists; + + SECURITY_ATTRIBUTES inheritable = { + .nLength = sizeof(inheritable), + .lpSecurityDescriptor = NULL, + .bInheritHandle = TRUE + }; + + PACL ovpn_dacl; + EXPLICIT_ACCESS ea[2]; + SECURITY_DESCRIPTOR ovpn_sd; + SECURITY_ATTRIBUTES ovpn_sa = { + .nLength = sizeof(ovpn_sa), + .lpSecurityDescriptor = &ovpn_sd, + .bInheritHandle = FALSE + }; + + ZeroMemory(&ea, sizeof(ea)); + ZeroMemory(&startup_info, sizeof(startup_info)); + ZeroMemory(&undo_lists, sizeof(undo_lists)); + ZeroMemory(&proc_info, sizeof(proc_info)); + + if (!GetStartupData(pipe, &sud)) + { + goto out; + } + + if (!InitializeSecurityDescriptor(&ovpn_sd, SECURITY_DESCRIPTOR_REVISION)) + { + ReturnLastError(pipe, L"InitializeSecurityDescriptor"); + goto out; + } + + /* Get SID of user the service is running under */ + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &svc_token)) + { + ReturnLastError(pipe, L"OpenProcessToken"); + goto out; + } + len = 0; + svc_user = NULL; + while (!GetTokenInformation(svc_token, TokenUser, svc_user, len, &len)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - ReturnLastError (pipe, L"GetTokenInformation (service token)"); - goto out; + ReturnLastError(pipe, L"GetTokenInformation (service token)"); + goto out; } - free (svc_user); - svc_user = malloc (len); - if (svc_user == NULL) + free(svc_user); + svc_user = malloc(len); + if (svc_user == NULL) { - ReturnLastError (pipe, L"malloc (service token user)"); - goto out; + ReturnLastError(pipe, L"malloc (service token user)"); + goto out; } } - if (!IsValidSid (svc_user->User.Sid)) + if (!IsValidSid(svc_user->User.Sid)) { - ReturnLastError (pipe, L"IsValidSid (service token user)"); - goto out; + ReturnLastError(pipe, L"IsValidSid (service token user)"); + goto out; } - if (!ImpersonateNamedPipeClient (pipe)) + if (!ImpersonateNamedPipeClient(pipe)) { - ReturnLastError (pipe, L"ImpersonateNamedPipeClient"); - goto out; + ReturnLastError(pipe, L"ImpersonateNamedPipeClient"); + goto out; } - if (!OpenThreadToken (GetCurrentThread (), TOKEN_ALL_ACCESS, FALSE, &imp_token)) + if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, FALSE, &imp_token)) { - ReturnLastError (pipe, L"OpenThreadToken"); - goto out; + ReturnLastError(pipe, L"OpenThreadToken"); + goto out; } - len = 0; - ovpn_user = NULL; - while (!GetTokenInformation (imp_token, TokenUser, ovpn_user, len, &len)) + len = 0; + ovpn_user = NULL; + while (!GetTokenInformation(imp_token, TokenUser, ovpn_user, len, &len)) { - if (GetLastError () != ERROR_INSUFFICIENT_BUFFER) + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { - ReturnLastError (pipe, L"GetTokenInformation (impersonation token)"); - goto out; + ReturnLastError(pipe, L"GetTokenInformation (impersonation token)"); + goto out; } - free (ovpn_user); - ovpn_user = malloc (len); - if (ovpn_user == NULL) + free(ovpn_user); + ovpn_user = malloc(len); + if (ovpn_user == NULL) { - ReturnLastError (pipe, L"malloc (impersonation token user)"); - goto out; + ReturnLastError(pipe, L"malloc (impersonation token user)"); + goto out; } } - if (!IsValidSid (ovpn_user->User.Sid)) + if (!IsValidSid(ovpn_user->User.Sid)) { - ReturnLastError (pipe, L"IsValidSid (impersonation token user)"); - goto out; + ReturnLastError(pipe, L"IsValidSid (impersonation token user)"); + goto out; } - /* Check user is authorized or options are white-listed */ - if (!IsAuthorizedUser (ovpn_user->User.Sid, &settings) && - !ValidateOptions (pipe, sud.directory, sud.options)) + /* Check user is authorized or options are white-listed */ + if (!IsAuthorizedUser(ovpn_user->User.Sid, &settings) + && !ValidateOptions(pipe, sud.directory, sud.options)) { - goto out; + goto out; } - /* OpenVPN process DACL entry for access by service and user */ - ea[0].grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL; - ea[0].grfAccessMode = SET_ACCESS; - ea[0].grfInheritance = NO_INHERITANCE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[0].Trustee.ptstrName = (LPTSTR) svc_user->User.Sid; - ea[1].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | PROCESS_VM_READ | - SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION; - ea[1].grfAccessMode = SET_ACCESS; - ea[1].grfInheritance = NO_INHERITANCE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[1].Trustee.ptstrName = (LPTSTR) ovpn_user->User.Sid; - - /* Set owner and DACL of OpenVPN security descriptor */ - if (!SetSecurityDescriptorOwner (&ovpn_sd, svc_user->User.Sid, FALSE)) - { - ReturnLastError (pipe, L"SetSecurityDescriptorOwner"); - goto out; + /* OpenVPN process DACL entry for access by service and user */ + ea[0].grfAccessPermissions = SPECIFIC_RIGHTS_ALL | STANDARD_RIGHTS_ALL; + ea[0].grfAccessMode = SET_ACCESS; + ea[0].grfInheritance = NO_INHERITANCE; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + ea[0].Trustee.ptstrName = (LPTSTR) svc_user->User.Sid; + ea[1].grfAccessPermissions = READ_CONTROL | SYNCHRONIZE | PROCESS_VM_READ + |SYNCHRONIZE | PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION; + ea[1].grfAccessMode = SET_ACCESS; + ea[1].grfInheritance = NO_INHERITANCE; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + ea[1].Trustee.ptstrName = (LPTSTR) ovpn_user->User.Sid; + + /* Set owner and DACL of OpenVPN security descriptor */ + if (!SetSecurityDescriptorOwner(&ovpn_sd, svc_user->User.Sid, FALSE)) + { + ReturnLastError(pipe, L"SetSecurityDescriptorOwner"); + goto out; } - if (SetEntriesInAcl (2, ea, NULL, &ovpn_dacl) != ERROR_SUCCESS) + if (SetEntriesInAcl(2, ea, NULL, &ovpn_dacl) != ERROR_SUCCESS) { - ReturnLastError (pipe, L"SetEntriesInAcl"); - goto out; + ReturnLastError(pipe, L"SetEntriesInAcl"); + goto out; } - if (!SetSecurityDescriptorDacl (&ovpn_sd, TRUE, ovpn_dacl, FALSE)) + if (!SetSecurityDescriptorDacl(&ovpn_sd, TRUE, ovpn_dacl, FALSE)) { - ReturnLastError (pipe, L"SetSecurityDescriptorDacl"); - goto out; + ReturnLastError(pipe, L"SetSecurityDescriptorDacl"); + goto out; } - /* Create primary token from impersonation token */ - if (!DuplicateTokenEx (imp_token, TOKEN_ALL_ACCESS, NULL, 0, TokenPrimary, &pri_token)) + /* Create primary token from impersonation token */ + if (!DuplicateTokenEx(imp_token, TOKEN_ALL_ACCESS, NULL, 0, TokenPrimary, &pri_token)) { - ReturnLastError (pipe, L"DuplicateTokenEx"); - goto out; + ReturnLastError(pipe, L"DuplicateTokenEx"); + goto out; } - /* use /dev/null for stdout of openvpn (client should use --log for output) */ - stdout_write = CreateFile(_T("NUL"), GENERIC_WRITE, FILE_SHARE_WRITE, - &inheritable, OPEN_EXISTING, 0, NULL); - if (stdout_write == INVALID_HANDLE_VALUE) + /* use /dev/null for stdout of openvpn (client should use --log for output) */ + stdout_write = CreateFile(_T("NUL"), GENERIC_WRITE, FILE_SHARE_WRITE, + &inheritable, OPEN_EXISTING, 0, NULL); + if (stdout_write == INVALID_HANDLE_VALUE) { - ReturnLastError (pipe, L"CreateFile for stdout"); - goto out; + ReturnLastError(pipe, L"CreateFile for stdout"); + goto out; } - if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0) || - !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0)) + if (!CreatePipe(&stdin_read, &stdin_write, &inheritable, 0) + || !SetHandleInformation(stdin_write, HANDLE_FLAG_INHERIT, 0)) { - ReturnLastError (pipe, L"CreatePipe"); - goto out; + ReturnLastError(pipe, L"CreatePipe"); + goto out; } - openvpn_sntprintf (ovpn_pipe_name, _countof (ovpn_pipe_name), - TEXT("\\\\.\\pipe\\openvpn\\service_%lu"), GetCurrentThreadId ()); - ovpn_pipe = CreateNamedPipe (ovpn_pipe_name, - PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL); - if (ovpn_pipe == INVALID_HANDLE_VALUE) + openvpn_sntprintf(ovpn_pipe_name, _countof(ovpn_pipe_name), + TEXT("\\\\.\\pipe\\openvpn\\service_%lu"), GetCurrentThreadId()); + ovpn_pipe = CreateNamedPipe(ovpn_pipe_name, + PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_OVERLAPPED, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 128, 128, 0, NULL); + if (ovpn_pipe == INVALID_HANDLE_VALUE) { - ReturnLastError (pipe, L"CreateNamedPipe"); - goto out; + ReturnLastError(pipe, L"CreateNamedPipe"); + goto out; } - svc_pipe = CreateFile (ovpn_pipe_name, GENERIC_READ | GENERIC_WRITE, 0, - &inheritable, OPEN_EXISTING, 0, NULL); - if (svc_pipe == INVALID_HANDLE_VALUE) + svc_pipe = CreateFile(ovpn_pipe_name, GENERIC_READ | GENERIC_WRITE, 0, + &inheritable, OPEN_EXISTING, 0, NULL); + if (svc_pipe == INVALID_HANDLE_VALUE) { - ReturnLastError (pipe, L"CreateFile"); - goto out; + ReturnLastError(pipe, L"CreateFile"); + goto out; } - pipe_mode = PIPE_READMODE_MESSAGE; - if (!SetNamedPipeHandleState (svc_pipe, &pipe_mode, NULL, NULL)) + pipe_mode = PIPE_READMODE_MESSAGE; + if (!SetNamedPipeHandleState(svc_pipe, &pipe_mode, NULL, NULL)) { - ReturnLastError (pipe, L"SetNamedPipeHandleState"); - goto out; + ReturnLastError(pipe, L"SetNamedPipeHandleState"); + goto out; } - cmdline_size = wcslen (sud.options) + 128; - cmdline = malloc (cmdline_size * sizeof (*cmdline)); - if (cmdline == NULL) + cmdline_size = wcslen(sud.options) + 128; + cmdline = malloc(cmdline_size * sizeof(*cmdline)); + if (cmdline == NULL) { - ReturnLastError (pipe, L"malloc"); - goto out; + ReturnLastError(pipe, L"malloc"); + goto out; } - openvpn_sntprintf (cmdline, cmdline_size, L"openvpn %s --msg-channel %lu", - sud.options, svc_pipe); + openvpn_sntprintf(cmdline, cmdline_size, L"openvpn %s --msg-channel %lu", + sud.options, svc_pipe); - if (!CreateEnvironmentBlock (&user_env, imp_token, FALSE)) + if (!CreateEnvironmentBlock(&user_env, imp_token, FALSE)) { - ReturnLastError (pipe, L"CreateEnvironmentBlock"); - goto out; + ReturnLastError(pipe, L"CreateEnvironmentBlock"); + goto out; } - startup_info.cb = sizeof (startup_info); - startup_info.lpDesktop = L"winsta0\\default"; - startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = stdin_read; - startup_info.hStdOutput = stdout_write; - startup_info.hStdError = stdout_write; + startup_info.cb = sizeof(startup_info); + startup_info.lpDesktop = L"winsta0\\default"; + startup_info.dwFlags = STARTF_USESTDHANDLES; + startup_info.hStdInput = stdin_read; + startup_info.hStdOutput = stdout_write; + startup_info.hStdError = stdout_write; #ifdef UNICODE - exe_path = settings.exe_path; + exe_path = settings.exe_path; #else - WCHAR wide_path[MAX_PATH]; - MultiByteToWideChar (CP_UTF8, 0, settings.exe_path, MAX_PATH, wide_path, MAX_PATH); - exe_path = wide_path; + WCHAR wide_path[MAX_PATH]; + MultiByteToWideChar(CP_UTF8, 0, settings.exe_path, MAX_PATH, wide_path, MAX_PATH); + exe_path = wide_path; #endif - // TODO: make sure HKCU is correct or call LoadUserProfile() - if (!CreateProcessAsUserW (pri_token, exe_path, cmdline, &ovpn_sa, NULL, TRUE, - settings.priority | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, - user_env, sud.directory, &startup_info, &proc_info)) + /* TODO: make sure HKCU is correct or call LoadUserProfile() */ + if (!CreateProcessAsUserW(pri_token, exe_path, cmdline, &ovpn_sa, NULL, TRUE, + settings.priority | CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, + user_env, sud.directory, &startup_info, &proc_info)) { - ReturnLastError (pipe, L"CreateProcessAsUser"); - goto out; + ReturnLastError(pipe, L"CreateProcessAsUser"); + goto out; } - if (!RevertToSelf ()) + if (!RevertToSelf()) { - TerminateProcess (proc_info.hProcess, 1); - ReturnLastError (pipe, L"RevertToSelf"); - goto out; + TerminateProcess(proc_info.hProcess, 1); + ReturnLastError(pipe, L"RevertToSelf"); + goto out; } - ReturnProcessId (pipe, proc_info.dwProcessId, 1, &exit_event); + ReturnProcessId(pipe, proc_info.dwProcessId, 1, &exit_event); - CloseHandleEx (&stdout_write); - CloseHandleEx (&stdin_read); - CloseHandleEx (&svc_pipe); + CloseHandleEx(&stdout_write); + CloseHandleEx(&stdin_read); + CloseHandleEx(&svc_pipe); - DWORD input_size = WideCharToMultiByte (CP_UTF8, 0, sud.std_input, -1, NULL, 0, NULL, NULL); - LPSTR input = NULL; - if (input_size && (input = malloc (input_size))) + DWORD input_size = WideCharToMultiByte(CP_UTF8, 0, sud.std_input, -1, NULL, 0, NULL, NULL); + LPSTR input = NULL; + if (input_size && (input = malloc(input_size))) { - DWORD written; - WideCharToMultiByte (CP_UTF8, 0, sud.std_input, -1, input, input_size, NULL, NULL); - WriteFile (stdin_write, input, strlen (input), &written, NULL); - free (input); + DWORD written; + WideCharToMultiByte(CP_UTF8, 0, sud.std_input, -1, input, input_size, NULL, NULL); + WriteFile(stdin_write, input, strlen(input), &written, NULL); + free(input); } - while (TRUE) + while (TRUE) { - DWORD bytes = PeekNamedPipeAsync (ovpn_pipe, 1, &exit_event); - if (bytes == 0) - break; + DWORD bytes = PeekNamedPipeAsync(ovpn_pipe, 1, &exit_event); + if (bytes == 0) + { + break; + } - HandleMessage (ovpn_pipe, bytes, 1, &exit_event, &undo_lists); + HandleMessage(ovpn_pipe, bytes, 1, &exit_event, &undo_lists); } - WaitForSingleObject (proc_info.hProcess, IO_TIMEOUT); - GetExitCodeProcess (proc_info.hProcess, &exit_code); - if (exit_code == STILL_ACTIVE) - TerminateProcess (proc_info.hProcess, 1); - else if (exit_code != 0) + WaitForSingleObject(proc_info.hProcess, IO_TIMEOUT); + GetExitCodeProcess(proc_info.hProcess, &exit_code); + if (exit_code == STILL_ACTIVE) { - WCHAR buf[256]; - int len = _snwprintf (buf, _countof (buf), - L"OpenVPN exited with error: exit code = %lu", exit_code); - buf[_countof (buf) - 1] = L'\0'; - ReturnError (pipe, ERROR_OPENVPN_STARTUP, buf, 1, &exit_event); + TerminateProcess(proc_info.hProcess, 1); } - Undo (&undo_lists); + else if (exit_code != 0) + { + WCHAR buf[256]; + int len = _snwprintf(buf, _countof(buf), + L"OpenVPN exited with error: exit code = %lu", exit_code); + buf[_countof(buf) - 1] = L'\0'; + ReturnError(pipe, ERROR_OPENVPN_STARTUP, buf, 1, &exit_event); + } + Undo(&undo_lists); out: - FlushFileBuffers (pipe); - DisconnectNamedPipe (pipe); - - free (ovpn_user); - free (svc_user); - free (cmdline); - DestroyEnvironmentBlock (user_env); - FreeStartupData (&sud); - CloseHandleEx (&proc_info.hProcess); - CloseHandleEx (&proc_info.hThread); - CloseHandleEx (&stdin_read); - CloseHandleEx (&stdin_write); - CloseHandleEx (&stdout_write); - CloseHandleEx (&svc_token); - CloseHandleEx (&imp_token); - CloseHandleEx (&pri_token); - CloseHandleEx (&ovpn_pipe); - CloseHandleEx (&svc_pipe); - CloseHandleEx (&pipe); - - return 0; + FlushFileBuffers(pipe); + DisconnectNamedPipe(pipe); + + free(ovpn_user); + free(svc_user); + free(cmdline); + DestroyEnvironmentBlock(user_env); + FreeStartupData(&sud); + CloseHandleEx(&proc_info.hProcess); + CloseHandleEx(&proc_info.hThread); + CloseHandleEx(&stdin_read); + CloseHandleEx(&stdin_write); + CloseHandleEx(&stdout_write); + CloseHandleEx(&svc_token); + CloseHandleEx(&imp_token); + CloseHandleEx(&pri_token); + CloseHandleEx(&ovpn_pipe); + CloseHandleEx(&svc_pipe); + CloseHandleEx(&pipe); + + return 0; } static DWORD WINAPI -ServiceCtrlInteractive (DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) +ServiceCtrlInteractive(DWORD ctrl_code, DWORD event, LPVOID data, LPVOID ctx) { - SERVICE_STATUS *status = ctx; - switch (ctrl_code) + SERVICE_STATUS *status = ctx; + switch (ctrl_code) { - case SERVICE_CONTROL_STOP: - status->dwCurrentState = SERVICE_STOP_PENDING; - ReportStatusToSCMgr (service, status); - if (exit_event) - SetEvent (exit_event); - return NO_ERROR; + case SERVICE_CONTROL_STOP: + status->dwCurrentState = SERVICE_STOP_PENDING; + ReportStatusToSCMgr(service, status); + if (exit_event) + { + SetEvent(exit_event); + } + return NO_ERROR; - case SERVICE_CONTROL_INTERROGATE: - return NO_ERROR; + case SERVICE_CONTROL_INTERROGATE: + return NO_ERROR; - default: - return ERROR_CALL_NOT_IMPLEMENTED; + default: + return ERROR_CALL_NOT_IMPLEMENTED; } } static HANDLE -CreateClientPipeInstance (VOID) +CreateClientPipeInstance(VOID) { - HANDLE pipe = NULL; - PACL old_dacl, new_dacl; - PSECURITY_DESCRIPTOR sd; - static EXPLICIT_ACCESS ea[2]; - static BOOL initialized = FALSE; - DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED; + HANDLE pipe = NULL; + PACL old_dacl, new_dacl; + PSECURITY_DESCRIPTOR sd; + static EXPLICIT_ACCESS ea[2]; + static BOOL initialized = FALSE; + DWORD flags = PIPE_ACCESS_DUPLEX | WRITE_DAC | FILE_FLAG_OVERLAPPED; - if (!initialized) + if (!initialized) { - PSID everyone, anonymous; + PSID everyone, anonymous; - ConvertStringSidToSid (TEXT("S-1-1-0"), &everyone); - ConvertStringSidToSid (TEXT("S-1-5-7"), &anonymous); + ConvertStringSidToSid(TEXT("S-1-1-0"), &everyone); + ConvertStringSidToSid(TEXT("S-1-5-7"), &anonymous); - ea[0].grfAccessPermissions = FILE_GENERIC_WRITE; - ea[0].grfAccessMode = GRANT_ACCESS; - ea[0].grfInheritance = NO_INHERITANCE; - ea[0].Trustee.pMultipleTrustee = NULL; - ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[0].Trustee.ptstrName = (LPTSTR) everyone; + ea[0].grfAccessPermissions = FILE_GENERIC_WRITE; + ea[0].grfAccessMode = GRANT_ACCESS; + ea[0].grfInheritance = NO_INHERITANCE; + ea[0].Trustee.pMultipleTrustee = NULL; + ea[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + ea[0].Trustee.ptstrName = (LPTSTR) everyone; - ea[1].grfAccessPermissions = 0; - ea[1].grfAccessMode = REVOKE_ACCESS; - ea[1].grfInheritance = NO_INHERITANCE; - ea[1].Trustee.pMultipleTrustee = NULL; - ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ea[1].Trustee.ptstrName = (LPTSTR) anonymous; + ea[1].grfAccessPermissions = 0; + ea[1].grfAccessMode = REVOKE_ACCESS; + ea[1].grfInheritance = NO_INHERITANCE; + ea[1].Trustee.pMultipleTrustee = NULL; + ea[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + ea[1].Trustee.ptstrName = (LPTSTR) anonymous; - flags |= FILE_FLAG_FIRST_PIPE_INSTANCE; - initialized = TRUE; + flags |= FILE_FLAG_FIRST_PIPE_INSTANCE; + initialized = TRUE; } - pipe = CreateNamedPipe (TEXT("\\\\.\\pipe\\openvpn\\service"), flags, - PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, - PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL); - if (pipe == INVALID_HANDLE_VALUE) + pipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\openvpn\\service"), flags, + PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, + PIPE_UNLIMITED_INSTANCES, 1024, 1024, 0, NULL); + if (pipe == INVALID_HANDLE_VALUE) { - MsgToEventLog (M_SYSERR, TEXT("Could not create named pipe")); - return INVALID_HANDLE_VALUE; + MsgToEventLog(M_SYSERR, TEXT("Could not create named pipe")); + return INVALID_HANDLE_VALUE; } - if (GetSecurityInfo (pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, + if (GetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &old_dacl, NULL, &sd) != ERROR_SUCCESS) { - MsgToEventLog (M_SYSERR, TEXT("Could not get pipe security info")); - return CloseHandleEx (&pipe); + MsgToEventLog(M_SYSERR, TEXT("Could not get pipe security info")); + return CloseHandleEx(&pipe); } - if (SetEntriesInAcl (2, ea, old_dacl, &new_dacl) != ERROR_SUCCESS) + if (SetEntriesInAcl(2, ea, old_dacl, &new_dacl) != ERROR_SUCCESS) { - MsgToEventLog (M_SYSERR, TEXT("Could not set entries in new acl")); - return CloseHandleEx (&pipe); + MsgToEventLog(M_SYSERR, TEXT("Could not set entries in new acl")); + return CloseHandleEx(&pipe); } - if (SetSecurityInfo (pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, + if (SetSecurityInfo(pipe, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, new_dacl, NULL) != ERROR_SUCCESS) { - MsgToEventLog (M_SYSERR, TEXT("Could not set pipe security info")); - return CloseHandleEx (&pipe); + MsgToEventLog(M_SYSERR, TEXT("Could not set pipe security info")); + return CloseHandleEx(&pipe); } - return pipe; + return pipe; } static DWORD -UpdateWaitHandles (LPHANDLE *handles_ptr, LPDWORD count, - HANDLE io_event, HANDLE exit_event, list_item_t *threads) +UpdateWaitHandles(LPHANDLE *handles_ptr, LPDWORD count, + HANDLE io_event, HANDLE exit_event, list_item_t *threads) { - static DWORD size = 10; - static LPHANDLE handles = NULL; - DWORD pos = 0; + static DWORD size = 10; + static LPHANDLE handles = NULL; + DWORD pos = 0; - if (handles == NULL) + if (handles == NULL) { - handles = malloc (size * sizeof (HANDLE)); - *handles_ptr = handles; - if (handles == NULL) - return ERROR_OUTOFMEMORY; + handles = malloc(size * sizeof(HANDLE)); + *handles_ptr = handles; + if (handles == NULL) + { + return ERROR_OUTOFMEMORY; + } } - handles[pos++] = io_event; + handles[pos++] = io_event; - if (!threads) - handles[pos++] = exit_event; + if (!threads) + { + handles[pos++] = exit_event; + } - while (threads) + while (threads) { - if (pos == size) + if (pos == size) { - LPHANDLE tmp; - size += 10; - tmp = realloc (handles, size * sizeof (HANDLE)); - if (tmp == NULL) + LPHANDLE tmp; + size += 10; + tmp = realloc(handles, size * sizeof(HANDLE)); + if (tmp == NULL) { - size -= 10; - *count = pos; - return ERROR_OUTOFMEMORY; + size -= 10; + *count = pos; + return ERROR_OUTOFMEMORY; } - handles = tmp; - *handles_ptr = handles; + handles = tmp; + *handles_ptr = handles; } - handles[pos++] = threads->data; - threads = threads->next; + handles[pos++] = threads->data; + threads = threads->next; } - *count = pos; - return NO_ERROR; + *count = pos; + return NO_ERROR; } static VOID -FreeWaitHandles (LPHANDLE h) +FreeWaitHandles(LPHANDLE h) { - free (h); + free(h); } VOID WINAPI -ServiceStartInteractive (DWORD dwArgc, LPTSTR *lpszArgv) +ServiceStartInteractive(DWORD dwArgc, LPTSTR *lpszArgv) { - HANDLE pipe, io_event = NULL; - OVERLAPPED overlapped; - DWORD error = NO_ERROR; - list_item_t *threads = NULL; - PHANDLE handles = NULL; - DWORD handle_count; - BOOL CmpHandle (LPVOID item, LPVOID hnd) { return item == hnd; } - - service = RegisterServiceCtrlHandlerEx (interactive_service.name, ServiceCtrlInteractive, &status); - if (!service) - return; - - status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; - status.dwCurrentState = SERVICE_START_PENDING; - status.dwServiceSpecificExitCode = NO_ERROR; - status.dwWin32ExitCode = NO_ERROR; - status.dwWaitHint = 3000; - ReportStatusToSCMgr (service, &status); - - /* Read info from registry in key HKLM\SOFTWARE\OpenVPN */ - error = GetOpenvpnSettings (&settings); - if (error != ERROR_SUCCESS) - goto out; - - io_event = InitOverlapped (&overlapped); - exit_event = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!exit_event || !io_event) - { - error = MsgToEventLog (M_SYSERR, TEXT("Could not create event")); - goto out; - } - - rdns_semaphore = CreateSemaphoreW (NULL, 1, 1, NULL); - if (!rdns_semaphore) - { - error = MsgToEventLog (M_SYSERR, TEXT("Could not create semaphore for register-dns")); - goto out; - } - - error = UpdateWaitHandles (&handles, &handle_count, io_event, exit_event, threads); - if (error != NO_ERROR) - goto out; - - pipe = CreateClientPipeInstance (); - if (pipe == INVALID_HANDLE_VALUE) - goto out; - - status.dwCurrentState = SERVICE_RUNNING; - status.dwWaitHint = 0; - ReportStatusToSCMgr (service, &status); - - while (TRUE) - { - if (ConnectNamedPipe (pipe, &overlapped) == FALSE && - GetLastError () != ERROR_PIPE_CONNECTED && - GetLastError () != ERROR_IO_PENDING) + HANDLE pipe, io_event = NULL; + OVERLAPPED overlapped; + DWORD error = NO_ERROR; + list_item_t *threads = NULL; + PHANDLE handles = NULL; + DWORD handle_count; + BOOL + CmpHandle(LPVOID item, LPVOID hnd) { + return item == hnd; + } + + service = RegisterServiceCtrlHandlerEx(interactive_service.name, ServiceCtrlInteractive, &status); + if (!service) + { + return; + } + + status.dwServiceType = SERVICE_WIN32_SHARE_PROCESS; + status.dwCurrentState = SERVICE_START_PENDING; + status.dwServiceSpecificExitCode = NO_ERROR; + status.dwWin32ExitCode = NO_ERROR; + status.dwWaitHint = 3000; + ReportStatusToSCMgr(service, &status); + + /* Read info from registry in key HKLM\SOFTWARE\OpenVPN */ + error = GetOpenvpnSettings(&settings); + if (error != ERROR_SUCCESS) + { + goto out; + } + + io_event = InitOverlapped(&overlapped); + exit_event = CreateEvent(NULL, TRUE, FALSE, NULL); + if (!exit_event || !io_event) + { + error = MsgToEventLog(M_SYSERR, TEXT("Could not create event")); + goto out; + } + + rdns_semaphore = CreateSemaphoreW(NULL, 1, 1, NULL); + if (!rdns_semaphore) + { + error = MsgToEventLog(M_SYSERR, TEXT("Could not create semaphore for register-dns")); + goto out; + } + + error = UpdateWaitHandles(&handles, &handle_count, io_event, exit_event, threads); + if (error != NO_ERROR) + { + goto out; + } + + pipe = CreateClientPipeInstance(); + if (pipe == INVALID_HANDLE_VALUE) + { + goto out; + } + + status.dwCurrentState = SERVICE_RUNNING; + status.dwWaitHint = 0; + ReportStatusToSCMgr(service, &status); + + while (TRUE) + { + if (ConnectNamedPipe(pipe, &overlapped) == FALSE + && GetLastError() != ERROR_PIPE_CONNECTED + && GetLastError() != ERROR_IO_PENDING) { - MsgToEventLog (M_SYSERR, TEXT("Could not connect pipe")); - break; + MsgToEventLog(M_SYSERR, TEXT("Could not connect pipe")); + break; } - error = WaitForMultipleObjects (handle_count, handles, FALSE, INFINITE); - if (error == WAIT_OBJECT_0) + error = WaitForMultipleObjects(handle_count, handles, FALSE, INFINITE); + if (error == WAIT_OBJECT_0) { - /* Client connected, spawn a worker thread for it */ - HANDLE next_pipe = CreateClientPipeInstance (); - HANDLE thread = CreateThread (NULL, 0, RunOpenvpn, pipe, CREATE_SUSPENDED, NULL); - if (thread) + /* Client connected, spawn a worker thread for it */ + HANDLE next_pipe = CreateClientPipeInstance(); + HANDLE thread = CreateThread(NULL, 0, RunOpenvpn, pipe, CREATE_SUSPENDED, NULL); + if (thread) { - error = AddListItem (&threads, thread); - if (!error) - error = UpdateWaitHandles (&handles, &handle_count, io_event, exit_event, threads); - if (error) + error = AddListItem(&threads, thread); + if (!error) + { + error = UpdateWaitHandles(&handles, &handle_count, io_event, exit_event, threads); + } + if (error) + { + ReturnError(pipe, error, L"Insufficient resources to service new clients", 1, &exit_event); + /* Update wait handles again after removing the last worker thread */ + RemoveListItem(&threads, CmpHandle, thread); + UpdateWaitHandles(&handles, &handle_count, io_event, exit_event, threads); + TerminateThread(thread, 1); + CloseHandleEx(&thread); + CloseHandleEx(&pipe); + } + else { - ReturnError (pipe, error, L"Insufficient resources to service new clients", 1, &exit_event); - /* Update wait handles again after removing the last worker thread */ - RemoveListItem (&threads, CmpHandle, thread); - UpdateWaitHandles (&handles, &handle_count, io_event, exit_event, threads); - TerminateThread (thread, 1); - CloseHandleEx (&thread); - CloseHandleEx (&pipe); + ResumeThread(thread); } - else - ResumeThread (thread); } - else - CloseHandleEx (&pipe); + else + { + CloseHandleEx(&pipe); + } - ResetOverlapped (&overlapped); - pipe = next_pipe; + ResetOverlapped(&overlapped); + pipe = next_pipe; } - else + else { - CancelIo (pipe); - if (error == WAIT_FAILED) + CancelIo(pipe); + if (error == WAIT_FAILED) { - MsgToEventLog (M_SYSERR, TEXT("WaitForMultipleObjects failed")); - SetEvent (exit_event); - /* Give some time for worker threads to exit and then terminate */ - Sleep (1000); - break; + MsgToEventLog(M_SYSERR, TEXT("WaitForMultipleObjects failed")); + SetEvent(exit_event); + /* Give some time for worker threads to exit and then terminate */ + Sleep(1000); + break; } - if (!threads) + if (!threads) { - /* exit event signaled */ - CloseHandleEx (&pipe); - ResetEvent (exit_event); - error = NO_ERROR; - break; + /* exit event signaled */ + CloseHandleEx(&pipe); + ResetEvent(exit_event); + error = NO_ERROR; + break; } - /* Worker thread ended */ - HANDLE thread = RemoveListItem (&threads, CmpHandle, handles[error]); - UpdateWaitHandles (&handles, &handle_count, io_event, exit_event, threads); - CloseHandleEx (&thread); + /* Worker thread ended */ + HANDLE thread = RemoveListItem(&threads, CmpHandle, handles[error]); + UpdateWaitHandles(&handles, &handle_count, io_event, exit_event, threads); + CloseHandleEx(&thread); } } out: - FreeWaitHandles (handles); - CloseHandleEx (&io_event); - CloseHandleEx (&exit_event); - CloseHandleEx (&rdns_semaphore); - - status.dwCurrentState = SERVICE_STOPPED; - status.dwWin32ExitCode = error; - ReportStatusToSCMgr (service, &status); + FreeWaitHandles(handles); + CloseHandleEx(&io_event); + CloseHandleEx(&exit_event); + CloseHandleEx(&rdns_semaphore); + + status.dwCurrentState = SERVICE_STOPPED; + status.dwWin32ExitCode = error; + ReportStatusToSCMgr(service, &status); } diff --git a/src/openvpnserv/service.c b/src/openvpnserv/service.c index 82f5551..b79e999 100644 --- a/src/openvpnserv/service.c +++ b/src/openvpnserv/service.c @@ -19,227 +19,257 @@ openvpn_service_t openvpn_service[_service_max]; BOOL -ReportStatusToSCMgr (SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status) +ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status) { - static DWORD dwCheckPoint = 1; - BOOL res = TRUE; - - if (status->dwCurrentState == SERVICE_START_PENDING) - status->dwControlsAccepted = 0; - else - status->dwControlsAccepted = SERVICE_ACCEPT_STOP; - - if (status->dwCurrentState == SERVICE_RUNNING || - status->dwCurrentState == SERVICE_STOPPED) - status->dwCheckPoint = 0; - else - status->dwCheckPoint = dwCheckPoint++; - - /* Report the status of the service to the service control manager. */ - res = SetServiceStatus (service, status); - if (!res) - MsgToEventLog(MSG_FLAGS_ERROR, TEXT("SetServiceStatus")); - - return res; + static DWORD dwCheckPoint = 1; + BOOL res = TRUE; + + if (status->dwCurrentState == SERVICE_START_PENDING) + { + status->dwControlsAccepted = 0; + } + else + { + status->dwControlsAccepted = SERVICE_ACCEPT_STOP; + } + + if (status->dwCurrentState == SERVICE_RUNNING + || status->dwCurrentState == SERVICE_STOPPED) + { + status->dwCheckPoint = 0; + } + else + { + status->dwCheckPoint = dwCheckPoint++; + } + + /* Report the status of the service to the service control manager. */ + res = SetServiceStatus(service, status); + if (!res) + { + MsgToEventLog(MSG_FLAGS_ERROR, TEXT("SetServiceStatus")); + } + + return res; } static int -CmdInstallServices () +CmdInstallServices() { - SC_HANDLE service; - SC_HANDLE svc_ctl_mgr; - TCHAR path[512]; - int i, ret = _service_max; - - if (GetModuleFileName (NULL, path + 1, 510) == 0) - { - _tprintf (TEXT("Unable to install service - %s\n"), GetLastErrorText ()); - return 1; - } - - path[0] = TEXT('\"'); - _tcscat (path, TEXT("\"")); - - svc_ctl_mgr = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); - if (svc_ctl_mgr == NULL) + SC_HANDLE service; + SC_HANDLE svc_ctl_mgr; + TCHAR path[512]; + int i, ret = _service_max; + + if (GetModuleFileName(NULL, path + 1, 510) == 0) { - _tprintf (TEXT("OpenSCManager failed - %s\n"), GetLastErrorText ()); - return 1; + _tprintf(TEXT("Unable to install service - %s\n"), GetLastErrorText()); + return 1; } - for (i = 0; i < _service_max; i++) + path[0] = TEXT('\"'); + _tcscat(path, TEXT("\"")); + + svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); + if (svc_ctl_mgr == NULL) { - service = CreateService (svc_ctl_mgr, - openvpn_service[i].name, - openvpn_service[i].display_name, - SERVICE_QUERY_STATUS, - SERVICE_WIN32_SHARE_PROCESS, - openvpn_service[i].start_type, - SERVICE_ERROR_NORMAL, - path, NULL, NULL, - openvpn_service[i].dependencies, - NULL, NULL); - if (service) + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText()); + return 1; + } + + for (i = 0; i < _service_max; i++) + { + service = CreateService(svc_ctl_mgr, + openvpn_service[i].name, + openvpn_service[i].display_name, + SERVICE_QUERY_STATUS, + SERVICE_WIN32_SHARE_PROCESS, + openvpn_service[i].start_type, + SERVICE_ERROR_NORMAL, + path, NULL, NULL, + openvpn_service[i].dependencies, + NULL, NULL); + if (service) + { + _tprintf(TEXT("%s installed.\n"), openvpn_service[i].display_name); + CloseServiceHandle(service); + --ret; + } + else { - _tprintf (TEXT("%s installed.\n"), openvpn_service[i].display_name); - CloseServiceHandle (service); - --ret; + _tprintf(TEXT("CreateService failed - %s\n"), GetLastErrorText()); } - else - _tprintf (TEXT("CreateService failed - %s\n"), GetLastErrorText ()); } - CloseServiceHandle (svc_ctl_mgr); - return ret; + CloseServiceHandle(svc_ctl_mgr); + return ret; } static int -CmdStartService (openvpn_service_type type) +CmdStartService(openvpn_service_type type) { - int ret = 1; - SC_HANDLE svc_ctl_mgr; - SC_HANDLE service; + int ret = 1; + SC_HANDLE svc_ctl_mgr; + SC_HANDLE service; - svc_ctl_mgr = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (svc_ctl_mgr == NULL) + svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (svc_ctl_mgr == NULL) { - _tprintf (TEXT("OpenSCManager failed - %s\n"), GetLastErrorText ()); - return 1; + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText()); + return 1; } - service = OpenService (svc_ctl_mgr, openvpn_service[type].name, SERVICE_ALL_ACCESS); - if (service) + service = OpenService(svc_ctl_mgr, openvpn_service[type].name, SERVICE_ALL_ACCESS); + if (service) { - if (StartService (service, 0, NULL)) + if (StartService(service, 0, NULL)) { - _tprintf (TEXT("Service Started\n")); - ret = 0; + _tprintf(TEXT("Service Started\n")); + ret = 0; + } + else + { + _tprintf(TEXT("StartService failed - %s\n"), GetLastErrorText()); } - else - _tprintf (TEXT("StartService failed - %s\n"), GetLastErrorText ()); - CloseServiceHandle(service); + CloseServiceHandle(service); } - else + else { - _tprintf (TEXT("OpenService failed - %s\n"), GetLastErrorText ()); + _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText()); } - CloseServiceHandle(svc_ctl_mgr); - return ret; + CloseServiceHandle(svc_ctl_mgr); + return ret; } static int -CmdRemoveServices () +CmdRemoveServices() { - SC_HANDLE service; - SC_HANDLE svc_ctl_mgr; - SERVICE_STATUS status; - int i, ret = _service_max; + SC_HANDLE service; + SC_HANDLE svc_ctl_mgr; + SERVICE_STATUS status; + int i, ret = _service_max; - svc_ctl_mgr = OpenSCManager (NULL, NULL, SC_MANAGER_CONNECT); - if (svc_ctl_mgr == NULL) + svc_ctl_mgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); + if (svc_ctl_mgr == NULL) { - _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText ()); - return 1; + _tprintf(TEXT("OpenSCManager failed - %s\n"), GetLastErrorText()); + return 1; } - for (i = 0; i < _service_max; i++) + for (i = 0; i < _service_max; i++) { - openvpn_service_t *ovpn_svc = &openvpn_service[i]; - service = OpenService (svc_ctl_mgr, ovpn_svc->name, - DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS); - if (service == NULL) + openvpn_service_t *ovpn_svc = &openvpn_service[i]; + service = OpenService(svc_ctl_mgr, ovpn_svc->name, + DELETE | SERVICE_STOP | SERVICE_QUERY_STATUS); + if (service == NULL) { - _tprintf (TEXT("OpenService failed - %s\n"), GetLastErrorText ()); - goto out; + _tprintf(TEXT("OpenService failed - %s\n"), GetLastErrorText()); + goto out; } - /* try to stop the service */ - if (ControlService (service, SERVICE_CONTROL_STOP, &status)) + /* try to stop the service */ + if (ControlService(service, SERVICE_CONTROL_STOP, &status)) { - _tprintf (TEXT("Stopping %s."), ovpn_svc->display_name); - Sleep (1000); + _tprintf(TEXT("Stopping %s."), ovpn_svc->display_name); + Sleep(1000); - while (QueryServiceStatus (service, &status)) + while (QueryServiceStatus(service, &status)) { - if (status.dwCurrentState == SERVICE_STOP_PENDING) + if (status.dwCurrentState == SERVICE_STOP_PENDING) { - _tprintf (TEXT(".")); - Sleep (1000); + _tprintf(TEXT(".")); + Sleep(1000); + } + else + { + break; } - else - break; } - if (status.dwCurrentState == SERVICE_STOPPED) - _tprintf (TEXT("\n%s stopped.\n"), ovpn_svc->display_name); - else - _tprintf (TEXT("\n%s failed to stop.\n"), ovpn_svc->display_name); + if (status.dwCurrentState == SERVICE_STOPPED) + { + _tprintf(TEXT("\n%s stopped.\n"), ovpn_svc->display_name); + } + else + { + _tprintf(TEXT("\n%s failed to stop.\n"), ovpn_svc->display_name); + } } - /* now remove the service */ - if (DeleteService (service)) + /* now remove the service */ + if (DeleteService(service)) { - _tprintf (TEXT("%s removed.\n"), ovpn_svc->display_name); - --ret; + _tprintf(TEXT("%s removed.\n"), ovpn_svc->display_name); + --ret; + } + else + { + _tprintf(TEXT("DeleteService failed - %s\n"), GetLastErrorText()); } - else - _tprintf (TEXT("DeleteService failed - %s\n"), GetLastErrorText ()); - CloseServiceHandle (service); + CloseServiceHandle(service); } out: - CloseServiceHandle (svc_ctl_mgr); - return ret; + CloseServiceHandle(svc_ctl_mgr); + return ret; } int -_tmain (int argc, TCHAR *argv[]) +_tmain(int argc, TCHAR *argv[]) { - SERVICE_TABLE_ENTRY dispatchTable[] = { - { automatic_service.name, ServiceStartAutomatic }, - { interactive_service.name, ServiceStartInteractive }, - { NULL, NULL } - }; - - openvpn_service[0] = automatic_service; - openvpn_service[1] = interactive_service; - - if (argc > 1 && (*argv[1] == TEXT('-') || *argv[1] == TEXT('/'))) - { - if (_tcsicmp (TEXT("install"), argv[1] + 1) == 0) - return CmdInstallServices (); - else if (_tcsicmp (TEXT("remove"), argv[1] + 1) == 0) - return CmdRemoveServices (); - else if (_tcsicmp (TEXT("start"), argv[1] + 1) == 0) - { - BOOL is_auto = argc < 3 || _tcsicmp (TEXT("interactive"), argv[2]) != 0; - return CmdStartService (is_auto ? automatic : interactive); - } - else - goto dispatch; + SERVICE_TABLE_ENTRY dispatchTable[] = { + { automatic_service.name, ServiceStartAutomatic }, + { interactive_service.name, ServiceStartInteractive }, + { NULL, NULL } + }; - return 0; - } + openvpn_service[0] = automatic_service; + openvpn_service[1] = interactive_service; - /* If it doesn't match any of the above parameters - * the service control manager may be starting the service - * so we must call StartServiceCtrlDispatcher - */ + if (argc > 1 && (*argv[1] == TEXT('-') || *argv[1] == TEXT('/'))) + { + if (_tcsicmp(TEXT("install"), argv[1] + 1) == 0) + { + return CmdInstallServices(); + } + else if (_tcsicmp(TEXT("remove"), argv[1] + 1) == 0) + { + return CmdRemoveServices(); + } + else if (_tcsicmp(TEXT("start"), argv[1] + 1) == 0) + { + BOOL is_auto = argc < 3 || _tcsicmp(TEXT("interactive"), argv[2]) != 0; + return CmdStartService(is_auto ? automatic : interactive); + } + else + { + goto dispatch; + } + + return 0; + } + + /* If it doesn't match any of the above parameters + * the service control manager may be starting the service + * so we must call StartServiceCtrlDispatcher + */ dispatch: - _tprintf (TEXT("%s -install to install the services\n"), APPNAME); - _tprintf (TEXT("%s -start to start a service (\"automatic\" or \"interactive\")\n"), APPNAME); - _tprintf (TEXT("%s -remove to remove the services\n"), APPNAME); - _tprintf (TEXT("\nStartServiceCtrlDispatcher being called.\n")); - _tprintf (TEXT("This may take several seconds. Please wait.\n")); + _tprintf(TEXT("%s -install to install the services\n"), APPNAME); + _tprintf(TEXT("%s -start to start a service (\"automatic\" or \"interactive\")\n"), APPNAME); + _tprintf(TEXT("%s -remove to remove the services\n"), APPNAME); + _tprintf(TEXT("\nStartServiceCtrlDispatcher being called.\n")); + _tprintf(TEXT("This may take several seconds. Please wait.\n")); - if (!StartServiceCtrlDispatcher (dispatchTable)) - MsgToEventLog (MSG_FLAGS_ERROR, TEXT("StartServiceCtrlDispatcher failed.")); + if (!StartServiceCtrlDispatcher(dispatchTable)) + { + MsgToEventLog(MSG_FLAGS_ERROR, TEXT("StartServiceCtrlDispatcher failed.")); + } - return 0; + return 0; } diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h index c5d745f..b1130c9 100644 --- a/src/openvpnserv/service.h +++ b/src/openvpnserv/service.h @@ -5,7 +5,7 @@ * packet encryption, packet authentication, and * packet compression. * - * Copyright (C) 2013 Heiko Hund + * Copyright (C) 2013-2017 Heiko Hund * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -48,48 +48,51 @@ #define M_ERR (MSG_FLAGS_ERROR) /* error */ typedef enum { - automatic, - interactive, - _service_max + automatic, + interactive, + _service_max } openvpn_service_type; typedef struct { - openvpn_service_type type; - TCHAR *name; - TCHAR *display_name; - TCHAR *dependencies; - DWORD start_type; + openvpn_service_type type; + TCHAR *name; + TCHAR *display_name; + TCHAR *dependencies; + DWORD start_type; } openvpn_service_t; #define MAX_NAME 256 typedef struct { - TCHAR exe_path[MAX_PATH]; - TCHAR config_dir[MAX_PATH]; - TCHAR ext_string[16]; - TCHAR log_dir[MAX_PATH]; - TCHAR ovpn_admin_group[MAX_NAME]; - DWORD priority; - BOOL append; + TCHAR exe_path[MAX_PATH]; + TCHAR config_dir[MAX_PATH]; + TCHAR ext_string[16]; + TCHAR log_dir[MAX_PATH]; + TCHAR ovpn_admin_group[MAX_NAME]; + DWORD priority; + BOOL append; } settings_t; extern openvpn_service_t automatic_service; extern openvpn_service_t interactive_service; -VOID WINAPI ServiceStartAutomatic (DWORD argc, LPTSTR *argv); -VOID WINAPI ServiceStartInteractive (DWORD argc, LPTSTR *argv); +VOID WINAPI ServiceStartAutomatic(DWORD argc, LPTSTR *argv); -int openvpn_vsntprintf (LPTSTR str, size_t size, LPCTSTR format, va_list arglist); -int openvpn_sntprintf (LPTSTR str, size_t size, LPCTSTR format, ...); +VOID WINAPI ServiceStartInteractive(DWORD argc, LPTSTR *argv); -DWORD GetOpenvpnSettings (settings_t *s); +int openvpn_vsntprintf(LPTSTR str, size_t size, LPCTSTR format, va_list arglist); -BOOL ReportStatusToSCMgr (SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status); +int openvpn_sntprintf(LPTSTR str, size_t size, LPCTSTR format, ...); -LPCTSTR GetLastErrorText (); -DWORD MsgToEventLog (DWORD flags, LPCTSTR lpszMsg, ...); +DWORD GetOpenvpnSettings(settings_t *s); + +BOOL ReportStatusToSCMgr(SERVICE_STATUS_HANDLE service, SERVICE_STATUS *status); + +LPCTSTR GetLastErrorText(); + +DWORD MsgToEventLog(DWORD flags, LPCTSTR lpszMsg, ...); /* Convert a utf8 string to utf16. Caller should free the result */ -wchar_t *utf8to16 (const char *utf8); +wchar_t *utf8to16(const char *utf8); -#endif +#endif /* ifndef _SERVICE_H */ diff --git a/src/openvpnserv/validate.c b/src/openvpnserv/validate.c index 7458d75..c9c3855 100644 --- a/src/openvpnserv/validate.c +++ b/src/openvpnserv/validate.c @@ -29,41 +29,41 @@ #include static const WCHAR *white_list[] = - { - L"auth-retry", - L"config", - L"log", - L"log-append", - L"management", - L"management-forget-disconnect", - L"management-hold", - L"management-query-passwords", - L"management-query-proxy", - L"management-signal", - L"management-up-down", - L"mute", - L"setenv", - L"service", - L"verb", - - NULL /* last value */ - }; +{ + L"auth-retry", + L"config", + L"log", + L"log-append", + L"management", + L"management-forget-disconnect", + L"management-hold", + L"management-query-passwords", + L"management-query-proxy", + L"management-signal", + L"management-up-down", + L"mute", + L"setenv", + L"service", + L"verb", + + NULL /* last value */ +}; /* * Check workdir\fname is inside config_dir * The logic here is simple: we may reject some valid paths if ..\ is in any of the strings */ static BOOL -CheckConfigPath (const WCHAR *workdir, const WCHAR *fname, const settings_t *s) +CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s) { WCHAR tmp[MAX_PATH]; const WCHAR *config_file = NULL; const WCHAR *config_dir = NULL; /* convert fname to full path */ - if (PathIsRelativeW (fname) ) + if (PathIsRelativeW(fname) ) { - snwprintf (tmp, _countof(tmp), L"%s\\%s", workdir, fname); + snwprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); tmp[_countof(tmp)-1] = L'\0'; config_file = tmp; } @@ -75,17 +75,19 @@ CheckConfigPath (const WCHAR *workdir, const WCHAR *fname, const settings_t *s) #ifdef UNICODE config_dir = s->config_dir; #else - if (MultiByteToWideChar (CP_UTF8, 0, s->config_dir, -1, widepath, MAX_PATH) == 0) + if (MultiByteToWideChar(CP_UTF8, 0, s->config_dir, -1, widepath, MAX_PATH) == 0) { - MsgToEventLog (M_SYSERR, TEXT("Failed to convert config_dir name to WideChar")); + MsgToEventLog(M_SYSERR, TEXT("Failed to convert config_dir name to WideChar")); return FALSE; } config_dir = widepath; #endif - if (wcsncmp (config_dir, config_file, wcslen(config_dir)) == 0 && - wcsstr (config_file + wcslen(config_dir), L"..") == NULL ) + if (wcsncmp(config_dir, config_file, wcslen(config_dir)) == 0 + && wcsstr(config_file + wcslen(config_dir), L"..") == NULL) + { return TRUE; + } return FALSE; } @@ -96,14 +98,16 @@ CheckConfigPath (const WCHAR *workdir, const WCHAR *fname, const settings_t *s) * Returns index to the item if found, -1 otherwise. */ static int -OptionLookup (const WCHAR *name, const WCHAR *white_list[]) +OptionLookup(const WCHAR *name, const WCHAR *white_list[]) { int i; - for (i = 0 ; white_list[i]; i++) + for (i = 0; white_list[i]; i++) { - if ( wcscmp(white_list[i], name) == 0 ) + if (wcscmp(white_list[i], name) == 0) + { return i; + } } return -1; @@ -114,7 +118,7 @@ OptionLookup (const WCHAR *name, const WCHAR *white_list[]) * Get the local name of the group using the SID. */ static BOOL -GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen) +GetBuiltinAdminGroupName(WCHAR *name, DWORD nlen) { BOOL b = FALSE; PSID admin_sid = NULL; @@ -126,15 +130,17 @@ GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen) admin_sid = malloc(sid_size); if (!admin_sid) + { return FALSE; + } b = CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, admin_sid, &sid_size); - if(b) + if (b) { b = LookupAccountSidW(NULL, admin_sid, name, &nlen, domain, &dlen, &snu); } - free (admin_sid); + free(admin_sid); return b; } @@ -144,7 +150,7 @@ GetBuiltinAdminGroupName (WCHAR *name, DWORD nlen) * the group specified in s->ovpn_admin_group */ BOOL -IsAuthorizedUser (SID *sid, settings_t *s) +IsAuthorizedUser(SID *sid, settings_t *s) { LOCALGROUP_USERS_INFO_0 *groups = NULL; DWORD nread; @@ -160,19 +166,19 @@ IsAuthorizedUser (SID *sid, settings_t *s) SID_NAME_USE sid_type; /* Get username */ - if (!LookupAccountSidW (NULL, sid, username, &len, domain, &len, &sid_type)) + if (!LookupAccountSidW(NULL, sid, username, &len, domain, &len, &sid_type)) { - MsgToEventLog (M_SYSERR, TEXT("LookupAccountSid")); + MsgToEventLog(M_SYSERR, TEXT("LookupAccountSid")); goto out; } /* Get an array of groups the user is member of */ - err = NetUserGetLocalGroups (NULL, username, 0, LG_INCLUDE_INDIRECT, (LPBYTE *) &groups, - MAX_PREFERRED_LENGTH, &nread, &nmax); + err = NetUserGetLocalGroups(NULL, username, 0, LG_INCLUDE_INDIRECT, (LPBYTE *) &groups, + MAX_PREFERRED_LENGTH, &nread, &nmax); if (err && err != ERROR_MORE_DATA) { - SetLastError (err); - MsgToEventLog (M_SYSERR, TEXT("NetUserGetLocalGroups")); + SetLastError(err); + MsgToEventLog(M_SYSERR, TEXT("NetUserGetLocalGroups")); goto out; } @@ -182,7 +188,7 @@ IsAuthorizedUser (SID *sid, settings_t *s) } else { - MsgToEventLog (M_SYSERR, TEXT("Failed to get the name of Administrators group. Using the default.")); + MsgToEventLog(M_SYSERR, TEXT("Failed to get the name of Administrators group. Using the default.")); /* use the default value */ admin_group[0] = SYSTEM_ADMIN_GROUP; } @@ -191,25 +197,25 @@ IsAuthorizedUser (SID *sid, settings_t *s) admin_group[1] = s->ovpn_admin_group; #else tmp = NULL; - len = MultiByteToWideChar (CP_UTF8, 0, s->ovpn_admin_group, -1, NULL, 0); - if (len == 0 || (tmp = malloc (len*sizeof(WCHAR))) == NULL) + len = MultiByteToWideChar(CP_UTF8, 0, s->ovpn_admin_group, -1, NULL, 0); + if (len == 0 || (tmp = malloc(len*sizeof(WCHAR))) == NULL) { - MsgToEventLog (M_SYSERR, TEXT("Failed to convert admin group name to WideChar")); + MsgToEventLog(M_SYSERR, TEXT("Failed to convert admin group name to WideChar")); goto out; } - MultiByteToWideChar (CP_UTF8, 0, s->ovpn_admin_group, -1, tmp, len); + MultiByteToWideChar(CP_UTF8, 0, s->ovpn_admin_group, -1, tmp, len); admin_group[1] = tmp; #endif /* Check if user's groups include any of the admin groups */ for (i = 0; i < nread; i++) { - if ( wcscmp (groups[i].lgrui0_name, admin_group[0]) == 0 || - wcscmp (groups[i].lgrui0_name, admin_group[1]) == 0 - ) + if (wcscmp(groups[i].lgrui0_name, admin_group[0]) == 0 + || wcscmp(groups[i].lgrui0_name, admin_group[1]) == 0 + ) { - MsgToEventLog (M_INFO, TEXT("Authorizing user %s by virtue of membership in group %s"), - username, groups[i].lgrui0_name); + MsgToEventLog(M_INFO, TEXT("Authorizing user %s by virtue of membership in group %s"), + username, groups[i].lgrui0_name); ret = TRUE; break; } @@ -217,8 +223,10 @@ IsAuthorizedUser (SID *sid, settings_t *s) out: if (groups) - NetApiBufferFree (groups); - free (tmp); + { + NetApiBufferFree(groups); + } + free(tmp); return ret; } @@ -229,21 +237,23 @@ out: * The caller should set argc to the number of valid elements in argv[] array. */ BOOL -CheckOption (const WCHAR *workdir, int argc, WCHAR *argv[], const settings_t *s) +CheckOption(const WCHAR *workdir, int argc, WCHAR *argv[], const settings_t *s) { /* Do not modify argv or *argv -- ideally it should be const WCHAR *const *, but alas...*/ - if ( wcscmp (argv[0], L"--config") == 0 && - argc > 1 && - !CheckConfigPath (workdir, argv[1], s) - ) + if (wcscmp(argv[0], L"--config") == 0 + && argc > 1 + && !CheckConfigPath(workdir, argv[1], s) + ) { return FALSE; } /* option name starts at 2 characters from argv[i] */ - if (OptionLookup (argv[0] + 2, white_list) == -1) /* not found */ + if (OptionLookup(argv[0] + 2, white_list) == -1) /* not found */ + { return FALSE; + } return TRUE; } diff --git a/src/openvpnserv/validate.h b/src/openvpnserv/validate.h index 0d0270a..ece8704 100644 --- a/src/openvpnserv/validate.h +++ b/src/openvpnserv/validate.h @@ -34,15 +34,15 @@ /* The last one may be reset in registry: HKLM\Software\OpenVPN\ovpn_admin_group */ BOOL -IsAuthorizedUser (SID *sid, settings_t *s); +IsAuthorizedUser(SID *sid, settings_t *s); BOOL -CheckOption (const WCHAR *workdir, int narg, WCHAR *argv[], const settings_t *s); +CheckOption(const WCHAR *workdir, int narg, WCHAR *argv[], const settings_t *s); static inline BOOL -IsOption (const WCHAR *o) +IsOption(const WCHAR *o) { - return (wcsncmp (o, L"--", 2) == 0); + return (wcsncmp(o, L"--", 2) == 0); } -#endif +#endif /* ifndef VALIDATE_H */ -- cgit v1.2.3