Commit 519ced06 authored by Slava Monich's avatar Slava Monich

[connman] Make directories configurable via config file. Contributes to JB#36462

New entries are StorageRoot and FileSystemIdentity. In addition to those,
connman-vpnd supports StateDirectory entry. This allows to store connman
data under the user home firectory.
parent 626aa667
......@@ -116,7 +116,7 @@ src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) \
src/ippool.c src/bridge.c src/nat.c src/ipaddress.c \
src/inotify.c src/firewall.c src/ipv6pd.c src/peer.c \
src/peer_service.c src/machine.c src/util.c \
src/wakeup_timer.c src/jolla-stats.c
src/wakeup_timer.c src/jolla-stats.c src/fsid.c
src_connmand_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ @GNUTLS_LIBS@ \
......@@ -145,7 +145,7 @@ vpn_connman_vpnd_SOURCES = $(builtin_vpn_sources) \
vpn/vpn-ipconfig.c src/inet.c vpn/vpn-rtnl.c \
src/dbus.c src/storage.c src/ipaddress.c src/agent.c \
vpn/vpn-agent.c vpn/vpn-agent.h src/inotify.c \
vpn/vpn-config.c
vpn/vpn-config.c src/fsid.c
vpn_connman_vpnd_LDADD = gdbus/libgdbus-internal.la $(builtin_vpn_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
......@@ -174,8 +174,7 @@ plugindir = $(libdir)/connman/plugins
scriptdir = $(libdir)/connman/scripts
storagedir = $(localstatedir)/lib/connman
vpn_storagedir = $(localstatedir)/lib/connman-vpn
storageroot = $(localstatedir)/lib
configdir = ${sysconfdir}/connman
......@@ -196,12 +195,9 @@ endif
AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
@GNUTLS_CFLAGS@ $(builtin_cflags) \
-DCONNMAN_PLUGIN_BUILTIN \
-DSTATEDIR=\""$(statedir)"\" \
-DVPN_STATEDIR=\""$(vpn_statedir)"\" \
-DPLUGINDIR=\""$(build_plugindir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\" \
-DSTORAGEDIR=\""$(storagedir)\"" \
-DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
-DDEFAULT_STORAGE_ROOT=\""$(storageroot)\"" \
-DCONFIGDIR=\""$(configdir)\""
if VPN
......@@ -217,8 +213,7 @@ src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
-DSTATEDIR=\""$(statedir)"\" \
-DPLUGINDIR=\""$(build_plugindir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\" \
-DSTORAGEDIR=\""$(storagedir)\"" \
-DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
-DDEFAULT_STORAGE_ROOT=\""$(storageroot)\"" \
-DCONFIGDIR=\""$(configdir)\"" \
-I$(builddir)/src
......@@ -230,11 +225,10 @@ if VPN
vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
$(builtin_vpn_cflags) \
-DCONNMAN_PLUGIN_BUILTIN \
-DVPN_STATEDIR=\""$(vpn_statedir)"\" \
-DDEFAULT_VPN_STATEDIR=\""$(vpn_statedir)"\" \
-DPLUGINDIR=\""$(build_vpn_plugindir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\" \
-DSTORAGEDIR=\""$(storagedir)\"" \
-DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
-DDEFAULT_STORAGE_ROOT=\""$(storageroot)\"" \
-DCONFIGDIR=\""$(configdir)\"" \
-I$(builddir)/vpn
......
......@@ -30,6 +30,7 @@ extern "C" {
#define CONF_STATUS_URL_IPV6 "Ipv6StatusUrl"
#define CONF_STATUS_URL_IPV4 "Ipv4StatusUrl"
#define CONF_TETHERING_SUBNET_BLOCK "TetheringSubnetBlock"
bool connman_setting_get_bool(const char *key);
char **connman_setting_get_string_list(const char *key);
......
......@@ -250,7 +250,12 @@ int __connman_resolvfile_append(int index, const char *domain, const char *serve
int __connman_resolvfile_remove(int index, const char *domain, const char *server);
int __connman_resolver_redo_servers(int index);
int __connman_storage_init(void);
#define STORAGEDIR __connman_storage_dir()
#define VPN_STORAGEDIR __connman_vpn_storage_dir()
const char *__connman_storage_dir(void);
const char *__connman_vpn_storage_dir(void);
int __connman_storage_init(const char *storageroot);
void __connman_storage_cleanup(void);
GKeyFile *__connman_storage_open_global(void);
GKeyFile *__connman_storage_load_global(void);
......@@ -1053,3 +1058,5 @@ void __connman_machine_cleanup(void);
int __connman_util_get_random(uint64_t *val);
int __connman_util_init(void);
void __connman_util_cleanup(void);
void __connman_set_fsid(const char *fs_identity);
/*
* Connection Manager
*
* Copyright (C) 2016 Jolla Ltd. All rights reserved.
*
* 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 "connman.h"
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <sys/fsuid.h>
/* Parses "user[:group]" string and sets fs identity */
void __connman_set_fsid(const char *fs_identity)
{
char *sep = strchr(fs_identity, ':');
const char *user;
char *tmp_user;
const struct passwd *pw = NULL;
const struct group *gr = NULL;
if (sep) {
/* Group */
const char *group = sep + 1;
gr = getgrnam(group);
user = tmp_user = g_strndup(fs_identity, sep - fs_identity);
if (!gr) {
/* Try numeric */
char *end = NULL;
long n = strtol(group, &end, 0);
if (end && end != group &&
((n != LONG_MAX && n != LONG_MIN) ||
errno != ERANGE)) {
gr = getgrgid(n);
}
if (!gr) {
fprintf(stderr, "Invalid group '%s'", group);
}
}
} else {
user = fs_identity;
tmp_user = NULL;
}
/* User */
pw = getpwnam(user);
if (!pw) {
/* Try numeric */
char *end = NULL;
long n = strtol(user, &end, 0);
if (end && end != user && ((n != LONG_MAX && n != LONG_MIN) ||
errno != ERANGE)) {
pw = getpwuid(n);
if (!pw) {
fprintf(stderr, "Invalid user '%s'", user);
}
}
}
/* Set fs identity */
if (pw) {
errno = 0;
setfsuid(pw->pw_uid);
if (errno) {
fprintf(stderr, "Failed to set fsuid to %d: %s\n",
pw->pw_uid, strerror(errno));
}
}
if (gr) {
errno = 0;
setfsgid(gr->gr_gid);
if (errno) {
fprintf(stderr, "Failed to set fsgid to %d: %s\n",
gr->gr_gid, strerror(errno));
}
}
g_free(tmp_user);
}
......@@ -435,7 +435,7 @@ int __connman_ippool_init(void)
subnet_mask_24 = ntohl(inet_addr("255.255.255.0"));
starting_block = ntohl(inet_addr(connman_option_get_string(
"TetheringSubnetBlock")));
CONF_TETHERING_SUBNET_BLOCK)));
if (!is_private_address(starting_block))
starting_block = block_16_bits;
......
......@@ -84,6 +84,8 @@ static struct {
char *ipv4_status_url;
char *tethering_subnet_block;
char **dont_bring_down_at_startup;
char *storage_root;
char *fs_identity;
bool enable_6to4;
} connman_settings = {
.bg_scan = true,
......@@ -98,10 +100,6 @@ static struct {
.single_tech = false,
.tethering_technologies = NULL,
.persistent_tethering_mode = false,
.ipv4_status_url = NULL,
.ipv6_status_url = NULL,
.tethering_subnet_block = NULL,
.dont_bring_down_at_startup = NULL,
.enable_6to4 = false,
};
......@@ -118,11 +116,8 @@ static struct {
#define CONF_TETHERING_TECHNOLOGIES "TetheringTechnologies"
#define CONF_PERSISTENT_TETHERING_MODE "PersistentTetheringMode"
#define CONF_DONT_BRING_DOWN_AT_STARTUP "DontBringDownAtStartup"
#define CONF_STATUS_URL_IPV6 "Ipv6StatusUrl"
#define CONF_STATUS_URL_IPV4 "Ipv4StatusUrl"
#define CONF_TETHERING_SUBNET_BLOCK "TetheringSubnetBlock"
#define CONF_STORAGE_ROOT "StorageRoot"
#define CONF_FILE_SYSTEM_IDENTITY "FileSystemIdentity"
#define CONF_ENABLE_6TO4 "Enable6to4"
static const char *supported_options[] = {
......@@ -138,6 +133,8 @@ static const char *supported_options[] = {
CONF_SINGLE_TECH,
CONF_TETHERING_TECHNOLOGIES,
CONF_PERSISTENT_TETHERING_MODE,
CONF_STORAGE_ROOT,
CONF_FILE_SYSTEM_IDENTITY,
CONF_STATUS_URL_IPV4,
CONF_STATUS_URL_IPV6,
CONF_TETHERING_SUBNET_BLOCK,
......@@ -146,6 +143,11 @@ static const char *supported_options[] = {
NULL
};
/* Default values */
#define CONF_STATUS_URL_IPV4_DEF "http://ipv4.connman.net/online/status.html"
#define CONF_STATUS_URL_IPV6_DEF "http://ipv6.connman.net/online/status.html"
#define CONF_TETHERING_SUBNET_BLOCK_DEF "192.168.0.0"
static GKeyFile *load_config(const char *file)
{
GError *err = NULL;
......@@ -265,10 +267,8 @@ static void parse_config(GKeyFile *config)
char **interfaces;
char **str_list;
char **tethering;
char *ipv4url;
char *ipv6url;
char *tetheringsubnet;
char **dontbringdown;
char *str;
const char *group = "General";
struct in_addr ip;
gsize len;
int timeout;
......@@ -381,14 +381,6 @@ static void parse_config(GKeyFile *config)
g_clear_error(&error);
dontbringdown = __connman_config_get_string_list(config, "General",
CONF_DONT_BRING_DOWN_AT_STARTUP, &len, &error);
if (!error)
connman_settings.dont_bring_down_at_startup = dontbringdown;
g_clear_error(&error);
boolean = __connman_config_get_bool(config, "General",
CONF_PERSISTENT_TETHERING_MODE,
&error);
......@@ -397,31 +389,30 @@ static void parse_config(GKeyFile *config)
g_clear_error(&error);
ipv4url = __connman_config_get_string(config, "General", CONF_STATUS_URL_IPV4, &error);
if (!error)
connman_settings.ipv4_status_url = ipv4url;
else
connman_settings.ipv4_status_url = "http://ipv4.connman.net/online/status.html";
connman_settings.dont_bring_down_at_startup =
__connman_config_get_string_list(config, group,
CONF_DONT_BRING_DOWN_AT_STARTUP, &len, NULL);
g_clear_error(&error);
connman_settings.storage_root = __connman_config_get_string(config,
group, CONF_STORAGE_ROOT, NULL);
ipv6url = __connman_config_get_string(config, "General", CONF_STATUS_URL_IPV6, &error);
if (!error)
connman_settings.ipv6_status_url = ipv6url;
else
connman_settings.ipv6_status_url = "http://ipv6.connman.net/online/status.html";
connman_settings.fs_identity = __connman_config_get_string(config,
group, CONF_FILE_SYSTEM_IDENTITY, NULL);
g_clear_error(&error);
connman_settings.ipv4_status_url = __connman_config_get_string(config,
group, CONF_STATUS_URL_IPV4, &error);
tetheringsubnet = __connman_config_get_string(config, "General",
CONF_TETHERING_SUBNET_BLOCK, &error);
if (!error && inet_pton(AF_INET, tetheringsubnet, &ip) == 1 &&
(ntohl(ip.s_addr) & 0xff) == 0)
connman_settings.tethering_subnet_block = tetheringsubnet;
else
connman_settings.tethering_subnet_block = "192.168.0.0";
connman_settings.ipv6_status_url = __connman_config_get_string(config,
group, CONF_STATUS_URL_IPV6, NULL);
g_clear_error(&error);
str = __connman_config_get_string(config, group,
CONF_TETHERING_SUBNET_BLOCK, NULL);
if (str && inet_pton(AF_INET, str, &ip) == 1 &&
(ntohl(ip.s_addr) & 0xff) == 0) {
connman_settings.tethering_subnet_block = str;
} else {
g_free(str);
}
boolean = __connman_config_get_bool(config, "General",
CONF_ENABLE_6TO4, &error);
......@@ -593,14 +584,20 @@ const char *connman_option_get_string(const char *key)
return option_wifi;
}
if (g_str_equal(key, CONF_STATUS_URL_IPV4) == TRUE) {
return connman_settings.ipv4_status_url;
}
if (g_str_equal(key, CONF_STATUS_URL_IPV6) == TRUE)
return connman_settings.ipv6_status_url;
if (g_str_equal(key, CONF_STATUS_URL_IPV4))
return connman_settings.ipv4_status_url ?
connman_settings.ipv4_status_url :
CONF_STATUS_URL_IPV4_DEF;
if (g_str_equal(key, CONF_STATUS_URL_IPV6))
return connman_settings.ipv6_status_url ?
connman_settings.ipv6_status_url :
CONF_STATUS_URL_IPV6_DEF;
if (g_str_equal(key, CONF_TETHERING_SUBNET_BLOCK) == TRUE)
return connman_settings.tethering_subnet_block;
if (g_str_equal(key, CONF_TETHERING_SUBNET_BLOCK))
return connman_settings.tethering_subnet_block ?
connman_settings.tethering_subnet_block :
CONF_TETHERING_SUBNET_BLOCK_DEF;
return NULL;
}
......@@ -700,13 +697,10 @@ int main(int argc, char *argv[])
}
}
if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
if (errno != EEXIST)
perror("Failed to create storage directory");
}
umask(0077);
gweb_log_hook = __connman_dbg;
gresolv_log_hook = __connman_dbg;
gdhcp_client_log_hook = __connman_dbg;
gdhcp_server_log_hook = __connman_dbg;
main_loop = g_main_loop_new(NULL, FALSE);
......@@ -729,21 +723,27 @@ int main(int argc, char *argv[])
__connman_log_init(argv[0], option_debug, option_detach,
option_backtrace, "Connection Manager", VERSION);
gweb_log_hook = __connman_dbg;
gresolv_log_hook = __connman_dbg;
gdhcp_client_log_hook = __connman_dbg;
gdhcp_server_log_hook = __connman_dbg;
__connman_dbus_init(conn);
__connman_inotify_init();
__connman_storage_init();
if (!option_config)
config_init(CONFIGMAINFILE);
else
config_init(option_config);
if (connman_settings.fs_identity)
__connman_set_fsid(connman_settings.fs_identity);
__connman_inotify_init();
__connman_storage_init(connman_settings.storage_root);
if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
if (errno != EEXIST)
perror("Failed to create storage directory");
}
umask(0077);
__connman_util_init();
__connman_technology_init();
__connman_notifier_init();
......@@ -861,6 +861,11 @@ int main(int argc, char *argv[])
g_strfreev(connman_settings.blacklisted_interfaces);
g_strfreev(connman_settings.tethering_technologies);
g_strfreev(connman_settings.dont_bring_down_at_startup);
g_free(connman_settings.ipv6_status_url);
g_free(connman_settings.ipv4_status_url);
g_free(connman_settings.tethering_subnet_block);
g_free(connman_settings.storage_root);
g_free(connman_settings.fs_identity);
g_free(option_debug);
g_free(option_wifi);
......
......@@ -863,9 +863,26 @@ gchar **__connman_storage_get_providers(void)
return result;
}
int __connman_storage_init(void)
static char *storage_dir = NULL;
static char *vpn_storage_dir = NULL;
const char *__connman_storage_dir(void)
{
DBG("");
return storage_dir;
}
const char *__connman_vpn_storage_dir(void)
{
return vpn_storage_dir;
}
int __connman_storage_init(const char *dir)
{
const char *root = dir ? dir : DEFAULT_STORAGE_ROOT;
DBG("%s", root);
storage_dir = g_strconcat(root, "/connman", NULL);
vpn_storage_dir = g_strconcat(root, "/connman-vpn", NULL);
keyfile_init();
return 0;
}
......@@ -875,4 +892,6 @@ void __connman_storage_cleanup(void)
DBG("");
storage_dir_cleanup();
keyfile_cleanup();
g_free(storage_dir);
g_free(vpn_storage_dir);
}
......@@ -32,7 +32,7 @@
#include "session-test.h"
#define POLICYDIR STORAGEDIR "/session_policy_local"
#define POLICYDIR DEFAULT_STORAGE_ROOT "/connman/session_policy_local"
enum test_session_state {
TEST_SESSION_STATE_0 = 0,
......
......@@ -52,10 +52,19 @@ static unsigned int __terminated = 0;
static struct {
unsigned int timeout_inputreq;
char *fs_identity;
char *storage_root;
char *state_dir;
} connman_vpn_settings = {
.timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT,
};
static char *get_string(GKeyFile *file, const char *group, const char *key)
{
char *str = g_key_file_get_string(file, group, key, NULL);
return str ? g_strchomp(str) : NULL;
}
static GKeyFile *load_config(const char *file)
{
GError *err = NULL;
......@@ -81,6 +90,7 @@ static GKeyFile *load_config(const char *file)
static void parse_config(GKeyFile *config, const char *file)
{
const char *group = "General";
GError *error = NULL;
int timeout;
......@@ -95,6 +105,13 @@ static void parse_config(GKeyFile *config, const char *file)
connman_vpn_settings.timeout_inputreq = timeout * 1000;
g_clear_error(&error);
connman_vpn_settings.fs_identity = get_string(config, group,
"FileSystemIdentity");
connman_vpn_settings.storage_root = get_string(config, group,
"StorageRoot");
connman_vpn_settings.state_dir = get_string(config, group,
"StateDirectory");
}
static int config_init(const char *file)
......@@ -203,6 +220,13 @@ static bool parse_debug(const char *key, const char *value,
return true;
}
const char *__vpn_state_dir()
{
return connman_vpn_settings.state_dir ?
connman_vpn_settings.state_dir :
DEFAULT_VPN_STATEDIR;
}
static GOptionEntry options[] = {
{ "config", 'c', 0, G_OPTION_ARG_STRING, &option_config,
"Load the specified configuration file "
......@@ -267,22 +291,21 @@ int main(int argc, char *argv[])
}
}
__connman_log_init(argv[0], option_debug, option_detach, false,
"Connection Manager VPN daemon", VERSION);
if (connman_vpn_settings.fs_identity)
__connman_set_fsid(connman_vpn_settings.fs_identity);
__connman_inotify_init();
__connman_storage_init(connman_vpn_settings.storage_root);
if (mkdir(VPN_STATEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
if (errno != EEXIST)
perror("Failed to create state directory");
}
/*
* At some point the VPN stuff is migrated into VPN_STORAGEDIR
* and this mkdir() call can be removed.
*/
if (mkdir(STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
if (errno != EEXIST)
perror("Failed to create storage directory");
}
if (mkdir(VPN_STORAGEDIR, S_IRUSR | S_IWUSR | S_IXUSR |
S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) {
if (errno != EEXIST)
......@@ -309,13 +332,8 @@ int main(int argc, char *argv[])
g_dbus_set_disconnect_function(conn, disconnect_callback, NULL, NULL);
__connman_log_init(argv[0], option_debug, option_detach, false,
"Connection Manager VPN daemon", VERSION);
__connman_dbus_init(conn);
__connman_inotify_init();
__connman_storage_init();
if (!option_config)
config_init(CONFIGMAINFILE);
else
......@@ -356,6 +374,10 @@ int main(int argc, char *argv[])
g_main_loop_unref(main_loop);
g_free(connman_vpn_settings.fs_identity);
g_free(connman_vpn_settings.storage_root);
g_free(connman_vpn_settings.state_dir);
g_free(option_debug);
return 0;
......
......@@ -116,3 +116,7 @@ char *__vpn_config_get_string(GKeyFile *key_file,
const char *group_name, const char *key, GError **error);
char **__vpn_config_get_string_list(GKeyFile *key_file,
const char *group_name, const char *key, gsize *length, GError **error);
#define VPN_STATEDIR __vpn_state_dir()
const char *__vpn_state_dir(void);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment