1ff636
From 169e74d772eac561a24f461ac65118d3d83a5980 Mon Sep 17 00:00:00 2001
1ff636
From: Ivan Shapovalov <intelfx100@gmail.com>
1ff636
Date: Sat, 7 Mar 2015 18:11:32 +0300
1ff636
Subject: [PATCH] sysusers: do not reject users with already present
1ff636
 /etc/shadow entries
1ff636
1ff636
This is needed to interoperate firstboot and sysusers. The former one is started
1ff636
first, and it writes only /etc/shadow when it is told to set the root password.
1ff636
It's better to relax checks here than to duplicate functionality in firstboot.
1ff636
1ff636
(cherry picked from commit c5abf22514b3925aa6f0d4a3f36f76799bf1911b)
1ff636
---
1ff636
 src/sysusers/sysusers.c | 23 +++++++++--------------
1ff636
 1 file changed, 9 insertions(+), 14 deletions(-)
1ff636
1ff636
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c
c62b8e
index e47bcb4dca..76b5962c51 100644
1ff636
--- a/src/sysusers/sysusers.c
1ff636
+++ b/src/sysusers/sysusers.c
1ff636
@@ -605,6 +605,8 @@ static int write_files(void) {
1ff636
                 if (r < 0)
1ff636
                         goto finish;
1ff636
 
1ff636
+                lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
1ff636
+
1ff636
                 original = fopen(shadow_path, "re");
1ff636
                 if (original) {
1ff636
                         struct spwd *sp;
1ff636
@@ -618,8 +620,13 @@ static int write_files(void) {
1ff636
 
1ff636
                                 i = hashmap_get(users, sp->sp_namp);
1ff636
                                 if (i && i->todo_user) {
1ff636
-                                        r = -EEXIST;
1ff636
-                                        goto finish;
1ff636
+                                        /* we will update the existing entry */
1ff636
+                                        sp->sp_lstchg = lstchg;
1ff636
+
1ff636
+                                        /* only the /etc/shadow stage is left, so we can
1ff636
+                                         * safely remove the item from the todo set */
1ff636
+                                        i->todo_user = false;
1ff636
+                                        hashmap_remove(todo_uids, UID_TO_PTR(i->uid));
1ff636
                                 }
1ff636
 
1ff636
                                 errno = 0;
1ff636
@@ -642,7 +649,6 @@ static int write_files(void) {
1ff636
                         goto finish;
1ff636
                 }
1ff636
 
1ff636
-                lstchg = (long) (now(CLOCK_REALTIME) / USEC_PER_DAY);
1ff636
                 HASHMAP_FOREACH(i, todo_uids, iterator) {
1ff636
                         struct spwd n = {
1ff636
                                 .sp_namp = i->name,
1ff636
@@ -879,7 +885,6 @@ static int add_user(Item *i) {
1ff636
 
1ff636
         if (!arg_root) {
1ff636
                 struct passwd *p;
1ff636
-                struct spwd *sp;
1ff636
 
1ff636
                 /* Also check NSS */
1ff636
                 errno = 0;
1ff636
@@ -895,16 +900,6 @@ static int add_user(Item *i) {
1ff636
                 }
1ff636
                 if (!IN_SET(errno, 0, ENOENT))
1ff636
                         return log_error_errno(errno, "Failed to check if user %s already exists: %m", i->name);
1ff636
-
1ff636
-                /* And shadow too, just to be sure */
1ff636
-                errno = 0;
1ff636
-                sp = getspnam(i->name);
1ff636
-                if (sp) {
1ff636
-                        log_error("User %s already exists in shadow database, but not in user database.", i->name);
1ff636
-                        return -EBADMSG;
1ff636
-                }
1ff636
-                if (!IN_SET(errno, 0, ENOENT))
1ff636
-                        return log_error_errno(errno, "Failed to check if user %s already exists in shadow database: %m", i->name);
1ff636
         }
1ff636
 
1ff636
         /* Try to use the suggested numeric uid */