diff options
Diffstat (limited to 'src/openvpnserv/common.c')
-rw-r--r-- | src/openvpnserv/common.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c new file mode 100644 index 0000000..dba4724 --- /dev/null +++ b/src/openvpnserv/common.c @@ -0,0 +1,218 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2011 Heiko Hund <heiko.hund@sophos.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program (see the file COPYING included with this + * distribution); if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <service.h> +#include <validate.h> +/* + * These are necessary due to certain buggy implementations of (v)snprintf, + * that don't guarantee null termination for size > 0. + */ +int +openvpn_vsntprintf (LPTSTR str, size_t size, LPCTSTR format, va_list arglist) +{ + int len = -1; + if (size > 0) + { + len = _vsntprintf (str, size, format, arglist); + str[size - 1] = 0; + } + return (len >= 0 && len < size); +} +int +openvpn_sntprintf (LPTSTR str, size_t size, LPCTSTR format, ...) +{ + va_list arglist; + int len = -1; + if (size > 0) + { + va_start (arglist, format); + len = openvpn_vsntprintf (str, size, format, arglist); + va_end (arglist); + } + return len; +} + +#define REG_KEY TEXT("SOFTWARE\\" PACKAGE_NAME) + +static DWORD +GetRegString (HKEY key, LPCTSTR value, LPTSTR data, DWORD 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) + { + SetLastError (status); + return MsgToEventLog (M_SYSERR, TEXT("Error querying registry value: HKLM\\%s\\%s"), REG_KEY, value); + } + + return ERROR_SUCCESS; +} + + +DWORD +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; + } + +out: + RegCloseKey (key); + return error; +} + + +LPCTSTR +GetLastErrorText () +{ + 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); + + 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()); + } + + if (tmp) + LocalFree (tmp); + + return buf; +} + + +DWORD +MsgToEventLog (DWORD flags, LPCTSTR format, ...) +{ + HANDLE hEventSource; + TCHAR msg[2][256]; + DWORD error = 0; + LPCTSTR err_msg = TEXT(""); + va_list arglist; + + if (flags & MSG_FLAGS_SYS_CODE) + { + error = GetLastError (); + err_msg = GetLastErrorText (); + } + + 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); + } + + return error; +} |