Allow get/add user evenif /opt/etc/passwd does not exist. 12/247412/3 accepted/tizen/unified/20201112.124133 submit/tizen/20201111.083035
authorYunmi Ha <yunmi.ha@samsung.com>
Tue, 10 Nov 2020 11:23:06 +0000 (20:23 +0900)
committerYunmi Ha <yunmi.ha@samsung.com>
Wed, 11 Nov 2020 06:46:14 +0000 (15:46 +0900)
- If /opt/etc/passwd file does not exist
    allow add_user
    allow get_user_list
    deny update_user
    deny delete_user

Change-Id: I901c47e6d73efd64133b04874c6b7727d975215b
Signed-off-by: Yunmi Ha <yunmi.ha@samsung.com>
include/gum/common/gum-file.h
src/common/gum-file.c
src/daemon/core/gumd-daemon-user.c

index 3ab8aca..fe45b1b 100644 (file)
@@ -51,6 +51,11 @@ typedef gboolean (*GumFileUpdateCB) (
         GError **error);
 
 gboolean
+gum_file_create_db_files (
+        const gchar *file_path,
+        GError **error);
+
+gboolean
 gum_file_update (
         GObject *object,
         GumOpType op,
index 6b3f71e..9d30014 100755 (executable)
@@ -371,6 +371,46 @@ _fail:
 }
 
 /**
+ * gum_file_create_db_files:
+ * @file_path: (transfer none): the path to db file
+ * @error: (transfer none): the #GError which is set in case of an error
+ *
+ * Create @file_path. If file already exists, flushing all the data.
+ *
+ * Returns: TRUE if successful, FALSE otherwise and @error is set.
+ */
+gboolean
+gum_file_create_db_files (const gchar *file_path, GError **error)
+{
+    FILE *file = NULL;
+
+    if (!file_path)
+        return FALSE;
+
+   if (!(file = _open_file (file_path, "w"))) {
+        GUM_RETURN_WITH_ERROR(GUM_ERROR_FILE_OPEN, "Unable to open new file",
+            error, FALSE);
+    }
+
+    fclose(file);
+
+    if (!_set_smack64_attr (file_path,
+            GUM_CONFIG_GENERAL_SMACK64_NEW_FILES, FALSE)) {
+        g_remove(file_path);
+        GUM_RETURN_WITH_ERROR(GUM_ERROR_FILE_ATTRIBUTE,
+            "Unable to set smack file attributes", error, FALSE);
+    }
+
+    if (lchown(file_path, 0, 0) < 0) {
+        g_remove(file_path);
+        GUM_RETURN_WITH_ERROR(GUM_ERROR_FILE_WRITE,
+            "Unable to change file owner and group", error, FALSE);
+    }
+
+    return TRUE;
+}
+
+/**
  * gum_file_update:
  * @object: (transfer none): the instance of #GObject; can be NULL
  * @op: (transfer none): the #GumOpType operation to be done on file entry
index 29d31cc..da58920 100755 (executable)
@@ -1697,6 +1697,11 @@ gumd_daemon_user_add (
         uid_t *uid,
         GError **error)
 {
+    const char *passwd_file = gum_config_get_string(self->priv->config,
+                                        GUM_CONFIG_GENERAL_PASSWD_FILE);
+    const char *shadow_file = gum_config_get_string (self->priv->config,
+                                        GUM_CONFIG_GENERAL_SHADOW_FILE);
+
     DBG ("");
 
     /* reset uid if set
@@ -1725,6 +1730,16 @@ gumd_daemon_user_add (
                 GUM_CONFIG_GENERAL_SHELL));
     }
 
+    if (!g_file_test(passwd_file, G_FILE_TEST_EXISTS)) {
+        if (!gum_file_create_db_files(passwd_file, error))
+            return FALSE;
+    }
+
+    if (!g_file_test(shadow_file, G_FILE_TEST_EXISTS)) {
+        if (!gum_file_create_db_files(shadow_file, error))
+            return FALSE;
+    }
+
     if (!gum_lock_pwdf_lock ()) {
         GUM_RETURN_WITH_ERROR (GUM_ERROR_DB_ALREADY_LOCKED,
                 "Database already locked", error, FALSE);
@@ -1743,12 +1758,10 @@ gumd_daemon_user_add (
 
     if (!gum_file_update (G_OBJECT (self), GUM_OPTYPE_ADD,
             (GumFileUpdateCB)_update_passwd_entry,
-            gum_config_get_string (self->priv->config,
-            GUM_CONFIG_GENERAL_PASSWD_FILE), NULL, error) ||
+            passwd_file, NULL, error) ||
         !gum_file_update (G_OBJECT (self), GUM_OPTYPE_ADD,
             (GumFileUpdateCB)_update_shadow_entry,
-            gum_config_get_string (self->priv->config,
-            GUM_CONFIG_GENERAL_SHADOW_FILE), NULL, error)) {
+            shadow_file, NULL, error)) {
         gum_lock_pwdf_unlock ();
         return FALSE;
     }
@@ -2148,14 +2161,16 @@ gumd_daemon_user_get_user_list (
     FILE *fpasswd = fopen("/etc/passwd", "r");
 
     fn = gum_config_get_string (config, GUM_CONFIG_GENERAL_PASSWD_FILE);
-    if (!fn || !fpasswd || !(fp = fopen (fn, "r"))) {
+    if (!fn || !fpasswd) {
         gum_lock_pwdf_unlock ();
-       if (fpasswd)
-            fclose (fpasswd);
+        if (fpasswd)
+            fclose (fpasswd);
         GUM_RETURN_WITH_ERROR (GUM_ERROR_FILE_OPEN,
                 "Opening passwd file failed", error, NULL);
     }
 
+    fp = fopen(fn, "r");
+
     sys_uid_min = (uid_t) gum_config_get_uint (config,
             GUM_CONFIG_GENERAL_SYS_UID_MIN, GUM_USER_INVALID_UID);
 
@@ -2166,7 +2181,7 @@ gumd_daemon_user_get_user_list (
 
     FILE *fparr[] = {fpasswd, fp};
     for (int i = 0; i < G_N_ELEMENTS(fparr); i++) {
-        while ((pent = fgetpwent (fparr[i])) != NULL) {
+        while (fparr[i] && ((pent = fgetpwent (fparr[i])) != NULL)) {
              /* If type is an empty string, all users are fetched. User type is
               * first compared with usertype in gecos field. If gecos field for
               * usertype does not exist, then all the users are considered as
@@ -2186,7 +2201,8 @@ gumd_daemon_user_get_user_list (
     }
 
     users = g_variant_builder_end (&builder);
-    fclose (fp);
+    if (fp)
+        fclose (fp);
     fclose (fpasswd);
 
     gum_lock_pwdf_unlock ();