Imported Upstream version 1.40
[platform/upstream/connman.git] / vpn / vpn-settings.c
index 0eca2bc..e78e501 100644 (file)
@@ -2,7 +2,7 @@
  *  ConnMan VPN daemon settings
  *
  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
- *  Copyright (C) 2018-2019 Jolla Ltd. All rights reserved.
+ *  Copyright (C) 2018-2020 Jolla Ltd. All rights reserved.
  *  Contact: jussi.laakkonen@jolla.com
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,9 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <sys/types.h>
 
 #include <connman/log.h>
 
@@ -37,11 +40,13 @@ static struct {
        char *binary_user;
        char *binary_group;
        char **binary_supplementary_groups;
+       char **system_binary_users;
 } connman_vpn_settings  = {
        .timeout_inputreq               = DEFAULT_INPUT_REQUEST_TIMEOUT,
        .binary_user                    = NULL,
        .binary_group                   = NULL,
        .binary_supplementary_groups    = NULL,
+       .system_binary_users            = NULL,
 };
 
 struct vpn_plugin_data {
@@ -52,6 +57,58 @@ struct vpn_plugin_data {
 
 GHashTable *plugin_hash = NULL;
 
+bool vpn_settings_is_system_user(const char *user)
+{
+       struct passwd *pwd;
+       struct passwd *system_pwd;
+       int i;
+
+       /*
+        * The username is not set = override should not be used. This is the
+        * case after the override is reset.
+        */
+       if (!user)
+               return true;
+
+       DBG("check user \"%s\"", user);
+
+       /*
+        * Ignore errors if no entry was found. Treat as system user to
+        * prevent using an invalid override.
+        */
+       pwd = vpn_util_get_passwd(user);
+       if (!pwd)
+               return true;
+
+       if (!connman_vpn_settings.system_binary_users) {
+               DBG("no binary users set");
+
+               /*
+                * Check if the user is root, or the uid equals to process
+                * effective uid.
+                */
+               return !pwd->pw_uid || pwd->pw_uid == geteuid();
+       }
+
+       /* Root set as user or the effective user id */
+       if (!pwd->pw_uid || pwd->pw_uid == geteuid())
+               return true;
+
+       for (i = 0; connman_vpn_settings.system_binary_users[i]; i++) {
+               const char *system_user =
+                               connman_vpn_settings.system_binary_users[i];
+
+               system_pwd = vpn_util_get_passwd(system_user);
+               if (!system_pwd)
+                       continue;
+
+               if (pwd->pw_uid == system_pwd->pw_uid)
+                       return true;
+       }
+
+       return false;
+}
+
 const char *vpn_settings_get_binary_user(struct vpn_plugin_data *data)
 {
        if (data && data->binary_user)
@@ -129,6 +186,9 @@ static void parse_config(GKeyFile *config, const char *file)
        connman_vpn_settings.binary_supplementary_groups = get_string_list(
                                                config, VPN_GROUP,
                                                "SupplementaryGroups");
+       connman_vpn_settings.system_binary_users = get_string_list(
+                                               config, VPN_GROUP,
+                                               "SystemBinaryUsers");
 }
 
 struct vpn_plugin_data *vpn_settings_get_vpn_plugin_config(const char *name)
@@ -245,6 +305,7 @@ void __vpn_settings_cleanup()
        g_free(connman_vpn_settings.binary_user);
        g_free(connman_vpn_settings.binary_group);
        g_strfreev(connman_vpn_settings.binary_supplementary_groups);
+       g_strfreev(connman_vpn_settings.system_binary_users);
 
        if (plugin_hash) {
                g_hash_table_destroy(plugin_hash);