2 * ConnMan VPN daemon settings
4 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
5 * Copyright (C) 2018-2020 Jolla Ltd. All rights reserved.
6 * Contact: jussi.laakkonen@jolla.com
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
28 #include <sys/types.h>
30 #include <connman/log.h>
34 #define DEFAULT_INPUT_REQUEST_TIMEOUT 300 * 1000
35 #define PLUGIN_CONFIGDIR CONFIGDIR "/vpn-plugin"
36 #define VPN_GROUP "DACPrivileges"
39 unsigned int timeout_inputreq;
42 char **binary_supplementary_groups;
43 char **system_binary_users;
44 } connman_vpn_settings = {
45 .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT,
48 .binary_supplementary_groups = NULL,
49 .system_binary_users = NULL,
52 struct vpn_plugin_data {
55 char **binary_supplementary_groups;
58 GHashTable *plugin_hash = NULL;
60 bool vpn_settings_is_system_user(const char *user)
63 struct passwd *system_pwd;
67 * The username is not set = override should not be used. This is the
68 * case after the override is reset.
73 DBG("check user \"%s\"", user);
76 * Ignore errors if no entry was found. Treat as system user to
77 * prevent using an invalid override.
79 pwd = vpn_util_get_passwd(user);
83 if (!connman_vpn_settings.system_binary_users) {
84 DBG("no binary users set");
87 * Check if the user is root, or the uid equals to process
90 return !pwd->pw_uid || pwd->pw_uid == geteuid();
93 /* Root set as user or the effective user id */
94 if (!pwd->pw_uid || pwd->pw_uid == geteuid())
97 for (i = 0; connman_vpn_settings.system_binary_users[i]; i++) {
98 const char *system_user =
99 connman_vpn_settings.system_binary_users[i];
101 system_pwd = vpn_util_get_passwd(system_user);
105 if (pwd->pw_uid == system_pwd->pw_uid)
112 const char *vpn_settings_get_binary_user(struct vpn_plugin_data *data)
114 if (data && data->binary_user)
115 return data->binary_user;
117 return connman_vpn_settings.binary_user;
120 const char *vpn_settings_get_binary_group(struct vpn_plugin_data *data)
122 if (data && data->binary_group)
123 return data->binary_group;
125 return connman_vpn_settings.binary_group;
128 char **vpn_settings_get_binary_supplementary_groups(struct vpn_plugin_data *data)
130 if (data && data->binary_supplementary_groups)
131 return data->binary_supplementary_groups;
133 return connman_vpn_settings.binary_supplementary_groups;
136 unsigned int __vpn_settings_get_timeout_inputreq()
138 return connman_vpn_settings.timeout_inputreq;
141 static char *get_string(GKeyFile *config, const char *group, const char *key)
143 char *str = g_key_file_get_string(config, group, key, NULL);
144 return str ? g_strstrip(str) : NULL;
147 static char **get_string_list(GKeyFile *config, const char *group,
151 char **str = g_key_file_get_string_list(config, group, key, &len, NULL);
156 for (i = 0; i < len ; i++) {
157 str[i] = g_strstrip(str[i]);
164 static void parse_config(GKeyFile *config, const char *file)
166 const char *group = "General";
167 GError *error = NULL;
173 DBG("parsing %s", file);
175 timeout = g_key_file_get_integer(config, group,
176 "InputRequestTimeout", &error);
177 if (!error && timeout >= 0)
178 connman_vpn_settings.timeout_inputreq = timeout * 1000;
180 g_clear_error(&error);
182 connman_vpn_settings.binary_user = get_string(config, VPN_GROUP,
184 connman_vpn_settings.binary_group = get_string(config, VPN_GROUP,
186 connman_vpn_settings.binary_supplementary_groups = get_string_list(
188 "SupplementaryGroups");
189 connman_vpn_settings.system_binary_users = get_string_list(
191 "SystemBinaryUsers");
194 struct vpn_plugin_data *vpn_settings_get_vpn_plugin_config(const char *name)
196 struct vpn_plugin_data *data = NULL;
199 data = g_hash_table_lookup(plugin_hash, name);
204 static void vpn_plugin_data_free(gpointer data)
206 struct vpn_plugin_data *plugin_data = (struct vpn_plugin_data*)data;
208 g_free(plugin_data->binary_user);
209 g_free(plugin_data->binary_group);
210 g_strfreev(plugin_data->binary_supplementary_groups);
215 int vpn_settings_parse_vpn_plugin_config(const char *name)
217 struct vpn_plugin_data *data;
219 gchar *ext = ".conf";
226 if (vpn_settings_get_vpn_plugin_config(name))
229 file = g_strconcat(PLUGIN_CONFIGDIR, "/", name, ext, NULL);
231 config = __vpn_settings_load_config(file);
235 DBG("Cannot load config %s for %s", file, name);
239 data = g_try_new0(struct vpn_plugin_data, 1);
241 data->binary_user = get_string(config, VPN_GROUP, "User");
242 data->binary_group = get_string(config, VPN_GROUP, "Group");
243 data->binary_supplementary_groups = get_string_list(config, VPN_GROUP,
244 "SupplementaryGroups");
246 DBG("Loaded settings for %s: %s - %s",
247 name, data->binary_user, data->binary_group);
250 plugin_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
251 g_free, vpn_plugin_data_free);
253 g_hash_table_replace(plugin_hash, g_strdup(name), data);
255 g_key_file_unref(config);
262 void vpn_settings_delete_vpn_plugin_config(const char *name)
264 if (plugin_hash && name)
265 g_hash_table_remove(plugin_hash, name);
268 GKeyFile *__vpn_settings_load_config(const char *file)
273 keyfile = g_key_file_new();
275 g_key_file_set_list_separator(keyfile, ',');
277 if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
278 if (err->code != G_FILE_ERROR_NOENT) {
279 connman_error("Parsing %s failed: %s", file,
284 g_key_file_unref(keyfile);
291 int __vpn_settings_init(const char *file)
295 config = __vpn_settings_load_config(file);
296 parse_config(config, file);
298 g_key_file_unref(config);
303 void __vpn_settings_cleanup()
305 g_free(connman_vpn_settings.binary_user);
306 g_free(connman_vpn_settings.binary_group);
307 g_strfreev(connman_vpn_settings.binary_supplementary_groups);
308 g_strfreev(connman_vpn_settings.system_binary_users);
311 g_hash_table_destroy(plugin_hash);