summaryrefslogtreecommitdiff
path: root/src/openvpnserv
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2017-06-22 13:16:46 +0200
committerAlberto Gonzalez Iniesta <agi@inittab.org>2017-06-22 13:16:46 +0200
commit9683f890944ffb114f5f8214f694e0b339cf5a5a (patch)
treefa391f5f343554b2861b1f8722d0a2a627e1c1fc /src/openvpnserv
parent3a2bbdb05ca6a6996e424c9fb225cb0d53804125 (diff)
New upstream version 2.4.3upstream/2.4.3
Diffstat (limited to 'src/openvpnserv')
-rw-r--r--src/openvpnserv/Makefile.in36
-rw-r--r--src/openvpnserv/automatic.c10
-rw-r--r--src/openvpnserv/common.c7
-rw-r--r--src/openvpnserv/interactive.c84
-rw-r--r--src/openvpnserv/service.h7
-rw-r--r--src/openvpnserv/validate.c178
-rw-r--r--src/openvpnserv/validate.h9
7 files changed, 246 insertions, 85 deletions
diff --git a/src/openvpnserv/Makefile.in b/src/openvpnserv/Makefile.in
index e113fee..234a927 100644
--- a/src/openvpnserv/Makefile.in
+++ b/src/openvpnserv/Makefile.in
@@ -1,7 +1,7 @@
-# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# Makefile.in generated by automake 1.15 from Makefile.am.
# @configure_input@
-# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+# Copyright (C) 1994-2014 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -37,7 +37,17 @@
# Required to build Windows resource file
VPATH = @srcdir@
-am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
@@ -100,8 +110,6 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-DIST_COMMON = $(top_srcdir)/build/ltrc.inc $(srcdir)/Makefile.in \
- $(srcdir)/Makefile.am $(top_srcdir)/depcomp
@WIN32_TRUE@sbin_PROGRAMS = openvpnserv$(EXEEXT)
subdir = src/openvpnserv
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -114,6 +122,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/ax_emptyarray.m4 \
$(top_srcdir)/compat.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h \
$(top_builddir)/include/openvpn-plugin.h
@@ -196,6 +205,8 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/ltrc.inc \
+ $(top_srcdir)/depcomp
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
@@ -244,6 +255,7 @@ LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
LZ4_CFLAGS = @LZ4_CFLAGS@
LZ4_LIBS = @LZ4_LIBS@
LZO_CFLAGS = @LZO_CFLAGS@
@@ -292,6 +304,7 @@ PKCS11_HELPER_LIBS = @PKCS11_HELPER_LIBS@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGINDIR = @PLUGINDIR@
PLUGIN_AUTH_PAM_CFLAGS = @PLUGIN_AUTH_PAM_CFLAGS@
PLUGIN_AUTH_PAM_LIBS = @PLUGIN_AUTH_PAM_LIBS@
RANLIB = @RANLIB@
@@ -304,12 +317,14 @@ SHELL = @SHELL@
SOCKETS_LIBS = @SOCKETS_LIBS@
STRIP = @STRIP@
SYSTEMD_ASK_PASSWORD = @SYSTEMD_ASK_PASSWORD@
+SYSTEMD_UNIT_DIR = @SYSTEMD_UNIT_DIR@
TAP_CFLAGS = @TAP_CFLAGS@
TAP_WIN_COMPONENT_ID = @TAP_WIN_COMPONENT_ID@
TAP_WIN_MIN_MAJOR = @TAP_WIN_MIN_MAJOR@
TAP_WIN_MIN_MINOR = @TAP_WIN_MIN_MINOR@
TEST_CFLAGS = @TEST_CFLAGS@
TEST_LDFLAGS = @TEST_LDFLAGS@
+TMPFILES_DIR = @TMPFILES_DIR@
VENDOR_BUILD_ROOT = @VENDOR_BUILD_ROOT@
VENDOR_DIST_ROOT = @VENDOR_DIST_ROOT@
VENDOR_SRC_ROOT = @VENDOR_SRC_ROOT@
@@ -366,7 +381,9 @@ sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
+systemdunitdir = @systemdunitdir@
target_alias = @target_alias@
+tmpfilesdir = @tmpfilesdir@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
@@ -413,7 +430,6 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/build/ltrc.inc $(am_
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/openvpnserv/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/openvpnserv/Makefile
-.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
@@ -422,7 +438,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
-$(top_srcdir)/build/ltrc.inc:
+$(top_srcdir)/build/ltrc.inc $(am__empty):
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
@@ -504,14 +520,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 $<
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.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 `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -817,6 +833,8 @@ uninstall-am: uninstall-sbinPROGRAMS
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am uninstall-sbinPROGRAMS
+.PRECIOUS: Makefile
+
.rc.lo:
$(LTRCCOMPILE) -i "$<" -o "$@"
diff --git a/src/openvpnserv/automatic.c b/src/openvpnserv/automatic.c
index 6be6c6d..4123d0f 100644
--- a/src/openvpnserv/automatic.c
+++ b/src/openvpnserv/automatic.c
@@ -16,10 +16,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
@@ -293,7 +292,8 @@ ServiceStartAutomatic(DWORD dwArgc, LPTSTR *lpszArgv)
/*
* Loop over each config file
*/
- do {
+ do
+ {
HANDLE log_handle = NULL;
STARTUPINFO start_info;
PROCESS_INFORMATION proc_info;
diff --git a/src/openvpnserv/common.c b/src/openvpnserv/common.c
index 3b9b396..0c9098f 100644
--- a/src/openvpnserv/common.c
+++ b/src/openvpnserv/common.c
@@ -16,10 +16,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <service.h>
diff --git a/src/openvpnserv/interactive.c b/src/openvpnserv/interactive.c
index dbe2b9b..607c8a9 100644
--- a/src/openvpnserv/interactive.c
+++ b/src/openvpnserv/interactive.c
@@ -16,10 +16,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
@@ -94,6 +93,13 @@ typedef enum {
} undo_type_t;
typedef list_item_t *undo_lists_t[_undo_type_max];
+typedef struct {
+ HANDLE engine;
+ int index;
+ int metric_v4;
+ int metric_v6;
+} block_dns_data_t;
+
static DWORD
AddListItem(list_item_t **pfirst, LPVOID data)
@@ -215,7 +221,9 @@ AsyncPipeOp(async_op_t op, HANDLE pipe, LPVOID buffer, DWORD size, DWORD count,
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);
@@ -883,6 +891,7 @@ static DWORD
HandleBlockDNSMessage(const block_dns_message_t *msg, undo_lists_t *lists)
{
DWORD err = 0;
+ block_dns_data_t *interface_data;
HANDLE engine = NULL;
LPCWSTR exe_path;
@@ -899,16 +908,57 @@ HandleBlockDNSMessage(const block_dns_message_t *msg, undo_lists_t *lists)
err = add_block_dns_filters(&engine, msg->iface.index, exe_path, BlockDNSErrHandler);
if (!err)
{
- err = AddListItem(&(*lists)[block_dns], engine);
+ interface_data = malloc(sizeof(block_dns_data_t));
+ if (!interface_data)
+ {
+ return ERROR_OUTOFMEMORY;
+ }
+ interface_data->engine = engine;
+ interface_data->index = msg->iface.index;
+ interface_data->metric_v4 = get_interface_metric(msg->iface.index,
+ AF_INET);
+ if (interface_data->metric_v4 < 0)
+ {
+ interface_data->metric_v4 = -1;
+ }
+ interface_data->metric_v6 = get_interface_metric(msg->iface.index,
+ AF_INET6);
+ if (interface_data->metric_v6 < 0)
+ {
+ interface_data->metric_v6 = -1;
+ }
+ err = AddListItem(&(*lists)[block_dns], interface_data);
+ if (!err)
+ {
+ err = set_interface_metric(msg->iface.index, AF_INET,
+ BLOCK_DNS_IFACE_METRIC);
+ if (!err)
+ {
+ set_interface_metric(msg->iface.index, AF_INET6,
+ BLOCK_DNS_IFACE_METRIC);
+ }
+ }
}
}
else
{
- engine = RemoveListItem(&(*lists)[block_dns], CmpEngine, NULL);
- if (engine)
+ interface_data = RemoveListItem(&(*lists)[block_dns], CmpEngine, NULL);
+ if (interface_data)
{
+ engine = interface_data->engine;
err = delete_block_dns_filters(engine);
engine = NULL;
+ if (interface_data->metric_v4 >= 0)
+ {
+ set_interface_metric(msg->iface.index, AF_INET,
+ interface_data->metric_v4);
+ }
+ if (interface_data->metric_v6 >= 0)
+ {
+ set_interface_metric(msg->iface.index, AF_INET6,
+ interface_data->metric_v6);
+ }
+ free(interface_data);
}
else
{
@@ -1323,6 +1373,7 @@ static VOID
Undo(undo_lists_t *lists)
{
undo_type_t type;
+ block_dns_data_t *interface_data;
for (type = 0; type < _undo_type_max; type++)
{
list_item_t **pnext = &(*lists)[type];
@@ -1348,8 +1399,18 @@ Undo(undo_lists_t *lists)
break;
case block_dns:
- delete_block_dns_filters(item->data);
- item->data = NULL;
+ interface_data = (block_dns_data_t*)(item->data);
+ delete_block_dns_filters(interface_data->engine);
+ if (interface_data->metric_v4 >= 0)
+ {
+ set_interface_metric(interface_data->index, AF_INET,
+ interface_data->metric_v4);
+ }
+ if (interface_data->metric_v6 >= 0)
+ {
+ set_interface_metric(interface_data->index, AF_INET6,
+ interface_data->metric_v6);
+ }
break;
}
@@ -1475,7 +1536,7 @@ RunOpenvpn(LPVOID p)
}
/* Check user is authorized or options are white-listed */
- if (!IsAuthorizedUser(ovpn_user->User.Sid, &settings)
+ if (!IsAuthorizedUser(ovpn_user->User.Sid, imp_token, settings.ovpn_admin_group)
&& !ValidateOptions(pipe, sud.directory, sud.options))
{
goto out;
@@ -1840,7 +1901,8 @@ ServiceStartInteractive(DWORD dwArgc, LPTSTR *lpszArgv)
PHANDLE handles = NULL;
DWORD handle_count;
BOOL
- CmpHandle(LPVOID item, LPVOID hnd) {
+ CmpHandle(LPVOID item, LPVOID hnd)
+ {
return item == hnd;
}
diff --git a/src/openvpnserv/service.h b/src/openvpnserv/service.h
index b1130c9..9fe573e 100644
--- a/src/openvpnserv/service.h
+++ b/src/openvpnserv/service.h
@@ -16,10 +16,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef _SERVICE_H
diff --git a/src/openvpnserv/validate.c b/src/openvpnserv/validate.c
index c9c3855..f6a97e9 100644
--- a/src/openvpnserv/validate.c
+++ b/src/openvpnserv/validate.c
@@ -16,10 +16,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "validate.h"
@@ -49,6 +48,9 @@ static const WCHAR *white_list[] =
NULL /* last value */
};
+static BOOL IsUserInGroup(PSID sid, const PTOKEN_GROUPS groups, const WCHAR *group_name);
+static PTOKEN_GROUPS GetTokenGroups(const HANDLE token);
+
/*
* 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
@@ -147,21 +149,16 @@ GetBuiltinAdminGroupName(WCHAR *name, DWORD nlen)
/*
* Check whether user is a member of Administrators group or
- * the group specified in s->ovpn_admin_group
+ * the group specified in ovpn_admin_group
*/
BOOL
-IsAuthorizedUser(SID *sid, settings_t *s)
+IsAuthorizedUser(PSID sid, const HANDLE token, const WCHAR *ovpn_admin_group)
{
- LOCALGROUP_USERS_INFO_0 *groups = NULL;
- DWORD nread;
- DWORD nmax;
- WCHAR *tmp = NULL;
const WCHAR *admin_group[2];
WCHAR username[MAX_NAME];
WCHAR domain[MAX_NAME];
WCHAR sysadmin_group[MAX_NAME];
- DWORD err, len = MAX_NAME;
- int i;
+ DWORD len = MAX_NAME;
BOOL ret = FALSE;
SID_NAME_USE sid_type;
@@ -169,17 +166,9 @@ IsAuthorizedUser(SID *sid, settings_t *s)
if (!LookupAccountSidW(NULL, sid, username, &len, domain, &len, &sid_type))
{
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);
- if (err && err != ERROR_MORE_DATA)
- {
- SetLastError(err);
- MsgToEventLog(M_SYSERR, TEXT("NetUserGetLocalGroups"));
- goto out;
+ /* not fatal as this is now used only for logging */
+ username[0] = '\0';
+ domain[0] = '\0';
}
if (GetBuiltinAdminGroupName(sysadmin_group, _countof(sysadmin_group)))
@@ -192,41 +181,136 @@ IsAuthorizedUser(SID *sid, settings_t *s)
/* use the default value */
admin_group[0] = SYSTEM_ADMIN_GROUP;
}
+ admin_group[1] = ovpn_admin_group;
-#ifdef UNICODE
- 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)
+ PTOKEN_GROUPS token_groups = GetTokenGroups(token);
+ for (int i = 0; i < 2; ++i)
{
- MsgToEventLog(M_SYSERR, TEXT("Failed to convert admin group name to WideChar"));
- goto out;
+ ret = IsUserInGroup(sid, token_groups, admin_group[i]);
+ if (ret)
+ {
+ MsgToEventLog(M_INFO, TEXT("Authorizing user '%s@%s' by virtue of membership in group '%s'"),
+ username, domain, admin_group[i]);
+ goto out;
+ }
}
- 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++)
+out:
+ free(token_groups);
+ return ret;
+}
+
+/**
+ * Get a list of groups in token.
+ * Returns a pointer to TOKEN_GROUPS struct or NULL on error.
+ * The caller should free the returned pointer.
+ */
+static PTOKEN_GROUPS
+GetTokenGroups(const HANDLE token)
+{
+ PTOKEN_GROUPS groups = NULL;
+ DWORD buf_size = 0;
+
+ if (!GetTokenInformation(token, TokenGroups, groups, buf_size, &buf_size)
+ && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ groups = malloc(buf_size);
+ }
+ if (!groups)
+ {
+ MsgToEventLog(M_SYSERR, L"GetTokenGroups");
+ }
+ else if (!GetTokenInformation(token, TokenGroups, groups, buf_size, &buf_size))
{
- if (wcscmp(groups[i].lgrui0_name, admin_group[0]) == 0
- || wcscmp(groups[i].lgrui0_name, admin_group[1]) == 0
- )
+ MsgToEventLog(M_SYSERR, L"GetTokenInformation");
+ free(groups);
+ }
+ return groups;
+}
+
+/*
+ * Find SID from name
+ *
+ * On input sid buffer should have space for at least sid_size bytes.
+ * Returns true on success, false on failure.
+ * Suggest: in caller allocate sid to hold SECURITY_MAX_SID_SIZE bytes
+ */
+static BOOL
+LookupSID(const WCHAR *name, PSID sid, DWORD sid_size)
+{
+ SID_NAME_USE su;
+ WCHAR domain[MAX_NAME];
+ DWORD dlen = _countof(domain);
+
+ if (!LookupAccountName(NULL, name, sid, &sid_size, domain, &dlen, &su))
+ {
+ return FALSE; /* not fatal as the group may not exist */
+ }
+ return TRUE;
+}
+
+/**
+ * User is in group if the token groups contain the SID of the group
+ * of if the user is a direct member of the group. The latter check
+ * catches dynamic changes in group membership in the local user
+ * database not reflected in the token.
+ * If token_groups or sid is NULL the corresponding check is skipped.
+ *
+ * Using sid and list of groups in token avoids reference to domains so that
+ * this could be completed without access to a Domain Controller.
+ *
+ * Returns true if the user is in the group, false otherwise.
+ */
+static BOOL
+IsUserInGroup(PSID sid, const PTOKEN_GROUPS token_groups, const WCHAR *group_name)
+{
+ BOOL ret = FALSE;
+ DWORD_PTR resume = 0;
+ DWORD err;
+ BYTE grp_sid[SECURITY_MAX_SID_SIZE];
+ int nloop = 0; /* a counter used to not get stuck in the do .. while() */
+
+ /* first check in the token groups */
+ if (token_groups && LookupSID(group_name, (PSID) grp_sid, _countof(grp_sid)))
+ {
+ for (DWORD i = 0; i < token_groups->GroupCount; ++i)
{
- MsgToEventLog(M_INFO, TEXT("Authorizing user %s by virtue of membership in group %s"),
- username, groups[i].lgrui0_name);
- ret = TRUE;
- break;
+ if (EqualSid((PSID) grp_sid, token_groups->Groups[i].Sid))
+ {
+ return TRUE;
+ }
}
}
-out:
- if (groups)
+ /* check user's SID is a member of the group */
+ if (!sid)
+ {
+ return FALSE;
+ }
+ do
+ {
+ DWORD nread, nmax;
+ LOCALGROUP_MEMBERS_INFO_0 *members = NULL;
+ err = NetLocalGroupGetMembers(NULL, group_name, 0, (LPBYTE *) &members,
+ MAX_PREFERRED_LENGTH, &nread, &nmax, &resume);
+ if ((err != NERR_Success && err != ERROR_MORE_DATA))
+ {
+ break;
+ }
+ /* If a match is already found, ret == TRUE and the loop is skipped */
+ for (int i = 0; i < nread && !ret; ++i)
+ {
+ ret = EqualSid(members[i].lgrmi0_sid, sid);
+ }
+ NetApiBufferFree(members);
+ /* MSDN says the lookup should always iterate until err != ERROR_MORE_DATA */
+ } while (err == ERROR_MORE_DATA && nloop++ < 100);
+
+ if (err != NERR_Success && err != NERR_GroupNotFound)
{
- NetApiBufferFree(groups);
+ SetLastError(err);
+ MsgToEventLog(M_SYSERR, TEXT("In NetLocalGroupGetMembers for group '%s'"), group_name);
}
- free(tmp);
return ret;
}
diff --git a/src/openvpnserv/validate.h b/src/openvpnserv/validate.h
index ece8704..cc443e6 100644
--- a/src/openvpnserv/validate.h
+++ b/src/openvpnserv/validate.h
@@ -17,10 +17,9 @@
* 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
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef VALIDATE_H
@@ -34,7 +33,7 @@
/* The last one may be reset in registry: HKLM\Software\OpenVPN\ovpn_admin_group */
BOOL
-IsAuthorizedUser(SID *sid, settings_t *s);
+IsAuthorizedUser(PSID sid, const HANDLE token, const WCHAR *ovpn_admin_group);
BOOL
CheckOption(const WCHAR *workdir, int narg, WCHAR *argv[], const settings_t *s);