Commit 9c30b7d1 authored by flypig's avatar flypig

[connman] Add access control to connman-vpn dbus interface. Contributes to JB#45379

Currently access to the connman-vpn dbus interfaces (connection and
manager) are controlled only by the policy config, which sets `<policy
at_console="true">`, allowing access to all users.

This change adds internal access control to the connection dbus
interface, which is configurable using a similar plugin approach as the
existing access method implemented for connman. It also adds a
Sailfish-specific plugin that blocks access for non-privileged users
base on a policy file installed at /etc/connman/vpn-dbus-access.conf.

The exceptions are the GetProperties and GetConnections dbus methods
which are available to all users (including nemo).

This Sailfish configuration is needed for MDM, to prevent users from
being able to connect to and disconnect from VPNs when this capability
is being restricted by the MDM policy.
parent 697a8980
......@@ -188,7 +188,7 @@ vpn_connman_vpnd_SOURCES = $(builtin_vpn_sources) $(backtrace_sources) \
vpn/vpn-manager.c vpn/vpn-provider.c \
vpn/vpn-provider.h vpn/vpn-rtnl.h \
vpn/vpn-ipconfig.c src/inet.c vpn/vpn-rtnl.c \
src/dbus.c src/storage.c src/ipaddress.c src/agent.c \
src/dbus.c src/storage.c src/ipaddress.c src/agent.c vpn/access.c \
vpn/vpn-agent.c vpn/vpn-agent.h src/inotify.c \
vpn/vpn-config.c src/fsid.c vpn/vpn-settings.c
......@@ -312,7 +312,7 @@ noinst_PROGRAMS += unit/test-access unit/test-ippool \
unit/test-sailfish_access unit/test-vpn-settings \
unit/test-sailfish_iptables_ext unit/test-service \
unit/test-globalproxy unit/test-firewall unit/test-iptables \
unit/test-device
unit/test-device unit/test-vpn_access unit/test-sailfish_vpn_access
if TEST_COVERAGE
COVERAGE_OPT = --coverage
......@@ -329,6 +329,11 @@ unit_test_access_SOURCES = unit/test-access.c src/access.c src/log.c \
$(backtrace_sources)
unit_test_access_LDADD = @GLIB_LIBS@ -ldl
unit_test_vpn_access_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
unit_test_vpn_access_SOURCES = unit/test-vpn_access.c vpn/access.c src/log.c \
$(backtrace_sources)
unit_test_vpn_access_LDADD = @GLIB_LIBS@ -ldl
unit_test_sailfish_access_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
@DBUSACCESS_CFLAGS@
unit_test_sailfish_access_SOURCES = unit/test-sailfish_access.c \
......@@ -403,11 +408,18 @@ unit_test_iptables_SOURCES = $(backtrace_sources) src/connman.h src/log.c \
unit/test-iptables.c src/iptables.c
unit_test_iptables_LDADD = @GLIB_LIBS@ -ldl
TESTS = unit/test-access unit/test-ippool \
unit_test_sailfish_vpn_access_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS) \
@DBUSACCESS_CFLAGS@
unit_test_sailfish_vpn_access_SOURCES = unit/test-sailfish_vpn_access.c \
src/log.c vpn/access.c vpn/plugins/sailfish_access.c \
$(backtrace_sources)
unit_test_sailfish_vpn_access_LDADD = @GLIB_LIBS@ @DBUSACCESS_LIBS@ -ldl
TESTS = unit/test-access unit/test-vpn_access unit/test-ippool \
unit/test-sailfish_access unit/test-vpn-settings \
unit/test-sailfish_iptables_ext unit/test-service \
unit/test-globalproxy unit/test-firewall unit/test-iptables \
unit/test-device
unit/test-device unit/test-sailfish_vpn_access
if SAILFISH_WAKEUP_TIMER
unit_test_sailfish_wakeup_timer_CFLAGS = $(COVERAGE_OPT) $(AM_CFLAGS)
......
......@@ -180,6 +180,29 @@ vpn_plugins_pptp_la_LDFLAGS = $(plugin_ldflags)
endif
endif
if SAILFISH_VPN_ACCESS
builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h
if SAILFISH_VPN_ACCESS_BUILTIN
builtin_vpn_modules += sailfish_access
builtin_vpn_sources += vpn/plugins/sailfish_access.c
builtin_vpn_cflags += -DSAILFISH_VPN_ACCESS=\"@SAILFISH_VPN_ACCESS@\"
else
vpn_plugin_LTLIBRARIES += vpn/plugins/sailfish_access.la
vpn_plugin_objects += $(plugins_sailfish_access_la_OBJECTS)
vpn_plugins_sailfish_access_la_SOURCES = vpn/plugins/sailfish_access.c
vpn_plugins_sailfish_access_la_CFLAGS = $(plugin_cflags) \
-DSAILFISH_VPN_ACCESS=\"@SAILFISH_VPN_ACCESS@\" \
-DVPN_STATEDIR=\""$(vpn_statedir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\"
vpn_plugins_sailfish_access_la_LDFLAGS = $(plugin_ldflags)
endif
vpnconfigdir = $(configdir)
vpnconfig_DATA = vpn/plugins/vpn-dbus-access.conf
EXTRA_DIST += vpnconfig_DATA
endif
if PPTP
script_LTLIBRARIES += scripts/libppp-plugin.la
scripts_libppp_plugin_la_LDFLAGS = $(plugin_ldflags)
......
......@@ -234,6 +234,17 @@ fi
AM_CONDITIONAL(PPTP, test "${enable_pptp}" != "no")
AM_CONDITIONAL(PPTP_BUILTIN, test "${enable_pptp}" = "builtin")
AC_ARG_ENABLE(sailfish-vpn-access,
AC_HELP_STRING([--enable-sailfish-vpn-access], [enable Sailfish vpn access control plugin]),
[enable_sailfish_vpn_access=${enableval}], [enable_sailfish_vpn_access="no"])
AM_CONDITIONAL(SAILFISH_VPN_ACCESS, test "${enable_sailfish_vpn_access}" != "no")
AM_CONDITIONAL(SAILFISH_VPN_ACCESS_BUILTIN, test "${enable_sailfish_vpn_access}" = "builtin")
if (test "${enable_sailfish_vpn_access}" != "no"); then
PKG_CHECK_MODULES(DBUSACCESS, libdbusaccess >= 1.0.3, dummy=yes,
AC_MSG_ERROR(libdbusaccess >= 1.0.3 is required))
need_glibutil=yes
fi
AC_CHECK_HEADERS(resolv.h, dummy=yes,
AC_MSG_ERROR(resolver header files are required))
AC_CHECK_LIB(resolv, ns_initparse, dummy=yes, [
......
......@@ -1154,6 +1154,7 @@ enum connman_access __connman_access_service_policy_check
const char *arg, const char *sender,
enum connman_access default_access);
/* Manager */
struct connman_access_manager_policy *__connman_access_manager_policy_create
(const char *spec);
void __connman_access_manager_policy_free
......@@ -1164,6 +1165,7 @@ enum connman_access __connman_access_manager_policy_check
const char *arg, const char *sender,
enum connman_access default_access);
/* Technology */
struct connman_access_tech_policy *__connman_access_tech_policy_create
(const char *spec);
void __connman_access_tech_policy_free
......@@ -1173,6 +1175,7 @@ enum connman_access __connman_access_tech_set_property
const char *name, const char *sender,
enum connman_access default_access);
/* Firewall */
struct connman_access_firewall_policy *__connman_access_firewall_policy_create
(const char *spec);
void __connman_access_firewall_policy_free
......
......@@ -19,7 +19,9 @@ test-sailfish_datacounter \
test-sailfish_datacounters \
test-sailfish_datahistory \
test-sailfish_developer_mode \
test-vpn-settings"
test-vpn-settings \
test-vpn_access \
test-sailfish_vpn_access"
pushd `dirname $0` > /dev/null
TEST_DIR="$PWD"
......
......@@ -238,6 +238,7 @@ static void test_sailfish_access_deny()
g_assert(sp);
g_assert(mp);
g_assert(tp);
g_assert(fp);
g_assert(__connman_access_service_policy_check(sp,
CONNMAN_ACCESS_SERVICE_GET_PROPERTY, "foo", "x",
CONNMAN_ACCESS_ALLOW) == CONNMAN_ACCESS_DENY);
......
/*
* Connection Manager
*
* Copyright (C) 2019 Jolla Ltd. All rights reserved.
* Contact: David Llewellyn-Jones <david.llewellyn-jones@jolla.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.
*/
#include "src/connman.h"
#include "vpn/vpn.h"
#include <errno.h>
#include <dbusaccess_peer.h>
#include <dbusaccess_policy.h>
#include <dbusaccess_system.h>
#include <gutil_idlepool.h>
#include <gutil_log.h>
static GUtilIdlePool* peer_pool;
extern struct connman_plugin_desc __connman_builtin_sailfish_access;
extern const char *sailfish_access_config_file;
#define TMP_DIR_TEMPLATE "test-sailfish_access-XXXXXX"
#define ROOT_SENDER ":1.100"
#define PRIVILEGED_SENDER ":1.200"
#define NON_PRIVILEGED_SENDER ":1.300"
#define INVALID_SENDER ":1.400"
#define NEMO_UID (100000)
#define NEMO_GID (100000)
#define PRIVILEGED_GID (996)
/*==========================================================================*
* Stubs
*==========================================================================*/
DAPeer *da_peer_get(DA_BUS bus, const char *name)
{
if (name && g_strcmp0(name, INVALID_SENDER)) {
gsize len = strlen(name);
DAPeer *peer = g_malloc0(sizeof(DAPeer) + len + 1);
char *buf = (char*)(peer + 1);
strcpy(buf, name);
peer->name = buf;
gutil_idle_pool_add(peer_pool, peer, g_free);
if (!strcmp(name, PRIVILEGED_SENDER)) {
peer->cred.euid = NEMO_UID;
peer->cred.egid = PRIVILEGED_GID;
} else if (strcmp(name, ROOT_SENDER)) {
peer->cred.euid = NEMO_UID;
peer->cred.egid = NEMO_GID;
}
return peer;
} else {
return NULL;
}
}
void da_peer_flush(DA_BUS bus, const char *name)
{
gutil_idle_pool_drain(peer_pool);
}
/*
* The build environment doesn't necessarily have these users and groups.
* And yet, sailfish access plugin depends on those.
*/
int da_system_uid(const char *user)
{
if (!g_strcmp0(user, "nemo"))
return NEMO_UID;
else
return -1;
}
int da_system_gid(const char *group)
{
if (!g_strcmp0(group, "privileged"))
return PRIVILEGED_GID;
else
return -1;
}
/*==========================================================================*
* Tests
*==========================================================================*/
static void test_sailfish_access_register()
{
g_assert(__connman_builtin_sailfish_access.init() == 0);
g_assert(__connman_builtin_sailfish_access.init() == -EALREADY);
__connman_builtin_sailfish_access.exit();
__connman_builtin_sailfish_access.exit();
}
static void test_sailfish_access_default()
{
const char *default_config_file = sailfish_access_config_file;
sailfish_access_config_file = "/no such file";
g_assert(__connman_builtin_sailfish_access.init() == 0);
/* root and privileged are allowed to access properties */
g_assert(__vpn_access_policy_check(ROOT_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", TRUE));
g_assert(__vpn_access_policy_check(PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", TRUE));
/* Non-privileged and unknown users are not */
g_assert(!__vpn_access_policy_check(NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", TRUE));
g_assert(!__vpn_access_policy_check(INVALID_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", TRUE));
/* Unknown methods are allowed */
g_assert(__vpn_access_policy_check(NON_PRIVILEGED_SENDER,
VPN_ACCESS_METHOD_COUNT,
"", TRUE));
__connman_builtin_sailfish_access.exit();
/* Restore the defaults */
sailfish_access_config_file = default_config_file;
}
struct test_config_data {
gboolean allowed;
const char *sender;
enum vpn_access_method method;
const char * arg;
gboolean default_access;
const char *config;
};
static const struct test_config_data config_tests [] = {
{
TRUE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", FALSE,
"[net.connman.vpn.Connection]\n"
"GetProperties = " DA_POLICY_VERSION "; * = allow \n"
},{
FALSE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"", FALSE,
"[net.connman.vpn.Connection]\n"
"GetProperties = " DA_POLICY_VERSION "; * = allow \n"
"=========" /* Invalid key file */
},{
FALSE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_SET_PROPERTY,
"", FALSE,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[net.connman.vpn.Connection]\n"
"SetProperty = " DA_POLICY_VERSION "; * = deny; "
"group(privileged) = allow\n"
},{
TRUE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_CLEAR_PROPERTY,
"", TRUE,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[net.connman.vpn.Connection]\n"
"SetProperty = " DA_POLICY_VERSION "; * = deny; "
"group(privileged) = allow \n"
},{
TRUE, PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_CONNECT,
"", TRUE,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = deny \n"
"[net.connman.vpn.Connection]\n"
"Connect = " DA_POLICY_VERSION "; * = deny; "
"group(privileged) = allow \n"
},{
TRUE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_CONNECTION_DISCONNECT,
"", TRUE,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[net.connman.vpn.Connection]\n"
"* = invalid"
},{
FALSE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_MANAGER_CREATE,
"", TRUE,
"[Common]\n"
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[net.connman.vpn.Manager]\n"
"* = " DA_POLICY_VERSION "; * = deny \n" /* <= Applied */
},{
TRUE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_MANAGER_REMOVE,
"", TRUE,
"[Common]\n" /* DefaultAccess gets applied */
"DefaultAccess = " DA_POLICY_VERSION "; * = allow \n"
"[net.connman.vpn.Connection]\n"
"* = " DA_POLICY_VERSION "; * = deny \n"
},{
TRUE, NON_PRIVILEGED_SENDER,
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"", TRUE,
"[net.connman.vpn.Manager]\n"
"* = " DA_POLICY_VERSION "; * = allow \n" /* <= Applied */
"GetConnections = invalid \n"
},{
FALSE, PRIVILEGED_SENDER,
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"", TRUE,
"[net.connman.vpn.Manager]\n"
"* = " DA_POLICY_VERSION "; * = allow \n"
"GetConnections = " DA_POLICY_VERSION "; "
"* = deny \n" /* <= Applied */
}
};
static void test_config(gconstpointer test_data)
{
const struct test_config_data *test = test_data;
const char *default_config_file = sailfish_access_config_file;
char *dir = g_dir_make_tmp(TMP_DIR_TEMPLATE, NULL);
char *file = g_strconcat(dir, "/test.conf", NULL);
/* Write temporary config file */
sailfish_access_config_file = file;
g_assert(g_file_set_contents(file, test->config, -1, NULL));
g_assert(__connman_builtin_sailfish_access.init() == 0);
g_assert(__vpn_access_policy_check(test->sender, test->method,
test->arg, test->default_access)
== test->allowed);
__connman_builtin_sailfish_access.exit();
/* Restore the defaults */
sailfish_access_config_file = default_config_file;
remove(file);
remove(dir);
g_free(file);
g_free(dir);
}
#define PREFIX "/sailfish_vpn_access/"
int main(int argc, char *argv[])
{
int i, ret;
peer_pool = gutil_idle_pool_new();
g_test_init(&argc, &argv, NULL);
gutil_log_timestamp = FALSE;
gutil_log_default.level = g_test_verbose() ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
__connman_log_init(argv[0], g_test_verbose() ? "*" : NULL,
FALSE, FALSE, "connman", CONNMAN_VERSION);
g_test_add_func(PREFIX "register", test_sailfish_access_register);
g_test_add_func(PREFIX "default", test_sailfish_access_default);
for (i = 0; i < G_N_ELEMENTS(config_tests); i++) {
char* name = g_strdup_printf("%s/config/%d", PREFIX, i + 1);
const struct test_config_data *test = config_tests + i;
g_test_add_data_func(name, test, test_config);
g_free(name);
}
ret = g_test_run();
gutil_idle_pool_unref(peer_pool);
return ret;
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/
/*
* Connection Manager
*
* Copyright (C) 2019 Jolla Ltd. All rights reserved.
* Contact: David Llewellyn-Jones <david.llewellyn-jones@jolla.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.
*/
#include "src/connman.h"
#include "vpn/vpn.h"
#include <errno.h>
#include <gutil_log.h>
/*==========================================================================*
* Test driver 1
*==========================================================================*/
static enum vpn_access test1_policy_check (const char *sender,
enum vpn_access_method method,
const char *arg)
{
return VPN_ACCESS_ALLOW;
}
static const struct vpn_access_plugin test1_driver = {
.name = "test1",
.priority = VPN_ACCESS_PRIORITY_LOW,
.vpn_policy_check = test1_policy_check
};
/*==========================================================================*
* Test driver 2
*==========================================================================*/
static enum vpn_access test2_policy_check (const char *sender,
enum vpn_access_method method,
const char *arg)
{
return VPN_ACCESS_DENY;
}
static const struct vpn_access_plugin test2_driver = {
.name = "test2",
.priority = VPN_ACCESS_PRIORITY_DEFAULT,
.vpn_policy_check = test2_policy_check
};
/*==========================================================================*
* Test driver 3
*==========================================================================*/
static enum vpn_access test3_policy_check (const char *sender,
enum vpn_access_method method,
const char *arg)
{
return VPN_ACCESS_DONT_CARE;
}
static const struct vpn_access_plugin test3_driver = {
.name = "test3",
.priority = VPN_ACCESS_PRIORITY_HIGH,
.vpn_policy_check = test3_policy_check
};
/*==========================================================================*
* Tests
*==========================================================================*/
static void test_access_policy_allow()
{
g_assert(vpn_access_plugin_register(&test1_driver) == 0);
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_GET_PROPERTIES,
"arg", TRUE));
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_CREATE,
"arg", TRUE));
vpn_access_plugin_unregister(&test1_driver);
}
static void test_access_policy_deny()
{
g_assert(vpn_access_plugin_register(&test2_driver) == 0);
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_SET_PROPERTY,
"arg", TRUE));
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"arg", TRUE));
vpn_access_plugin_unregister(&test2_driver);
}
static void test_access_policy_default()
{
g_assert(vpn_access_plugin_register(&test3_driver) == 0);
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_DISCONNECT,
"arg", TRUE));
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_REGISTER_AGENT,
"arg", FALSE));
vpn_access_plugin_unregister(&test3_driver);
}
static void test_access_policy_priority()
{
g_assert(vpn_access_plugin_register(&test1_driver) == 0);
g_assert(vpn_access_plugin_register(&test2_driver) == 0);
g_assert(vpn_access_plugin_register(&test3_driver) == 0);
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_SET_PROPERTY,
"arg", TRUE));
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"arg", TRUE));
vpn_access_plugin_unregister(&test2_driver);
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_SET_PROPERTY,
"arg", TRUE));
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"arg", TRUE));
vpn_access_plugin_unregister(&test1_driver);
g_assert(__vpn_access_policy_check("sender",
VPN_ACCESS_CONNECTION_SET_PROPERTY,
"arg", TRUE));
g_assert(!__vpn_access_policy_check("sender",
VPN_ACCESS_MANAGER_GET_CONNECTIONS,
"arg", FALSE));
vpn_access_plugin_unregister(&test3_driver);
}
#define PREFIX "/vpn_access/"
int main(int argc, char *argv[])
{
g_test_init(&argc, &argv, NULL);
gutil_log_timestamp = FALSE;
gutil_log_default.level = g_test_verbose() ?
GLOG_LEVEL_VERBOSE : GLOG_LEVEL_NONE;
__connman_log_init(argv[0], g_test_verbose() ? "*" : NULL,
FALSE, FALSE, "connman", CONNMAN_VERSION);
g_test_add_func(PREFIX "access_policy_allow",
test_access_policy_allow);
g_test_add_func(PREFIX "access_policy_deny",
test_access_policy_deny);
g_test_add_func(PREFIX "access_policy_default",
test_access_policy_default);
g_test_add_func(PREFIX "access_policy_priority",
test_access_policy_priority);
return g_test_run();
}
/*
* Local Variables:
* mode: C
* c-basic-offset: 8
* indent-tabs-mode: t
* End:
*/
/*
* Connection Manager
*
* Copyright (C) 2019 Jolla Ltd. All rights reserved.
* Contact: David Llewellyn-Jones <david.llewellyn-jones@jolla.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.
*/
#include "vpn.h"
#include <connman/log.h>
#include <connman/vpn-dbus.h>
#include <errno.h>
#include <string.h>
static GSList *access_plugins;
static const char * vpn_access_method_names[VPN_ACCESS_METHOD_COUNT] = {
/* Connection */
"GetProperties",
"SetProperty",
"ClearProperty",
"Connect",
"Disconnect",
/* Manager */
"Create",
"Remove",
"GetConnections",
"RegisterAgent",
"UnregisterAgent"
};
const char *vpn_access_intf_name(enum vpn_access_intf intf)
{
switch (intf) {
case VPN_ACCESS_INTF_CONNECTION:
return VPN_CONNECTION_INTERFACE;
case VPN_ACCESS_INTF_MANAGER:
return VPN_MANAGER_INTERFACE;
default:
return NULL;
}
}
const char *vpn_access_method_name(enum vpn_access_method method)
{
if ((method >= 0) && (method < VPN_ACCESS_METHOD_COUNT))
return vpn_access_method_names[method];
return NULL;
}
enum vpn_access_intf vpn_access_intf_from_method(enum vpn_access_method method)
{
enum vpn_access_intf intf = VPN_ACCESS_INTF_MANAGER;
if (method < VPN_ACCESS_CONNECTION_COUNT)
intf = VPN_ACCESS_INTF_CONNECTION;
return intf;
}
/**
* Returns 0 if both are equal;
* <0 if a comes before b;
* >0 if a comes after b.
*/
static gint vpn_access_plugin_compare(gconstpointer a, gconstpointer b)
{
const struct vpn_access_plugin *a_plugin = a;
const struct vpn_access_plugin *b_plugin = b;
int difference = b_plugin->priority - a_plugin->priority;
/* return < 0 if a has higher priority,
> 0 if b has higher priority,
alphabetical if they're the same priority */
if (difference != 0)
return difference;
return strcmp(a_plugin->name, b_plugin->name);
}
int vpn_access_plugin_register(const struct vpn_access_plugin *plugin)
{
if (!plugin || !plugin->name)
return -EINVAL;
if (g_slist_find(access_plugins, plugin))
return -EALREADY;
DBG("\"%s\"", plugin->name);
access_plugins = g_slist_insert_sorted(access_plugins, (void*)plugin,
vpn_access_plugin_compare);
return 0;
}
void vpn_access_plugin_unregister(const struct vpn_access_plugin *plugin)
{
if (g_slist_find(access_plugins, plugin)) {
DBG("\"%s\"", plugin->name);
access_plugins = g_slist_remove(access_plugins, plugin);
}
}
bool __vpn_access_policy_check(const char *sender,
enum vpn_access_method method,