diff options
Diffstat (limited to 'src/openvpnserv/automatic.c')
-rw-r--r-- | src/openvpnserv/automatic.c | 520 |
1 files changed, 274 insertions, 246 deletions
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. <sales@openvpn.net> + * Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <sales@openvpn.net> * * 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); } |