summaryrefslogtreecommitdiff
path: root/src/openvpnserv/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpnserv/common.c')
-rw-r--r--src/openvpnserv/common.c218
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;
+}