traceroute: fix help text to not show -6 when traceroute6 is off
[oweals/busybox.git] / libbb / update_passwd.c
index 32943482c6287e3bdbb9d9c61c880595fb75b677..301893be1d08079f411af19a8317fec45f1c58ba 100644 (file)
@@ -87,6 +87,12 @@ int FAST_FUNC update_passwd(const char *filename,
        int i;
        int changed_lines;
        int ret = -1; /* failure */
+       /* used as a bool: "are we modifying /etc/shadow?" */
+#if ENABLE_FEATURE_SHADOWPASSWDS
+       const char *shadow = strstr(filename, "shadow");
+#else
+# define shadow NULL
+#endif
 
        filename = xmalloc_follow_symlinks(filename);
        if (filename == NULL)
@@ -100,12 +106,15 @@ int FAST_FUNC update_passwd(const char *filename,
        name = xasprintf("%s:", name);
        user_len = strlen(name);
 
-       if (strstr(filename, "shadow"))
+       if (shadow)
                old_fp = fopen(filename, "r+");
        else
                old_fp = fopen_or_warn(filename, "r+");
-       if (!old_fp)
+       if (!old_fp) {
+               if (shadow)
+                       ret = 0; /* missing shadow is not an error */
                goto free_mem;
+       }
        old_fd = fileno(old_fp);
 
        selinux_preserve_fcontext(old_fd);
@@ -128,12 +137,7 @@ int FAST_FUNC update_passwd(const char *filename,
                fchown(new_fd, sb.st_uid, sb.st_gid);
        }
        errno = 0;
-       new_fp = fdopen(new_fd, "w");
-       if (!new_fp) {
-               bb_perror_nomsg();
-               close(new_fd);
-               goto unlink_new;
-       }
+       new_fp = xfdopen_for_write(new_fd);
 
        /* Backup file is "/etc/passwd-" */
        *sfx_char = '-';
@@ -215,8 +219,18 @@ int FAST_FUNC update_passwd(const char *filename,
                ) {
                        /* Change passwd */
                        cp = strchrnul(cp, ':'); /* move past old passwd */
-                       /* name: + new_passwd + :rest of line */
-                       fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
+
+                       if (shadow && *cp == ':') {
+                               /* /etc/shadow's field 3 (passwd change date) needs updating */
+                               /* move past old change date */
+                               cp = strchrnul(cp + 1, ':');
+                               /* "name:" + "new_passwd" + ":" + "change date" + ":rest of line" */
+                               fprintf(new_fp, "%s%s:%u%s\n", name, new_passwd,
+                                       (unsigned)(time(NULL)) / (24*60*60), cp);
+                       } else {
+                               /* "name:" + "new_passwd" + ":rest of line" */
+                               fprintf(new_fp, "%s%s%s\n", name, new_passwd, cp);
+                       }
                        changed_lines++;
                } /* else delete user or group: skip the line */
  next:
@@ -224,8 +238,10 @@ int FAST_FUNC update_passwd(const char *filename,
        }
 
        if (changed_lines == 0) {
-               if (ENABLE_FEATURE_DEL_USER_FROM_GROUP && member)
+#if ENABLE_FEATURE_DEL_USER_FROM_GROUP
+               if (member)
                        bb_error_msg("can't find %s in %s", member, filename);
+#endif
                if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
                 && applet_name[0] == 'a' && !member
                ) {