]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
vipw: use xmkstemp() and lckpwdf()
authorSami Kerola <kerolasa@iki.fi>
Wed, 29 Feb 2012 13:09:56 +0000 (14:09 +0100)
committerSami Kerola <kerolasa@iki.fi>
Sun, 18 Mar 2012 13:28:04 +0000 (14:28 +0100)
Get rid private locking schema and use libc instead.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
login-utils/Makefile.am
login-utils/setpwnam.h
login-utils/vipw.8
login-utils/vipw.c

index 8328c66ab685ab7677f8f6881bcde8cc17185797..59cc5015619dffc04249370929dc688fa4ac7980 100644 (file)
@@ -64,7 +64,8 @@ login_SOURCES = \
        $(top_srcdir)/lib/setproctitle.c
 vipw_SOURCES = \
        vipw.c \
-       setpwnam.h
+       setpwnam.h \
+       $(top_srcdir)/lib/fileutils.c
 
 chfn_LDADD = $(login_ldadd_common)
 chsh_LDADD = $(login_ldadd_common)
index e7f44a94ce18e9d963a21e68ebd2bcceea55b0ef..6a4dbb7b4388e9f2c2230893fe5fa4ca25ad8ca9 100644 (file)
 #include "pathnames.h"
 
 #ifndef DEBUG
-#define PASSWD_FILE    _PATH_PASSWD
-#define PTMP_FILE      _PATH_PTMP
-#define PTMPTMP_FILE   _PATH_PTMPTMP
-
-#define GROUP_FILE     _PATH_GROUP
-#define GTMP_FILE      _PATH_GTMP
-#define GTMPTMP_FILE   _PATH_GTMPTMP
-
-#define SHADOW_FILE    _PATH_SHADOW_PASSWD
-#define SPTMP_FILE     _PATH_SHADOW_PTMP
-#define SPTMPTMP_FILE  _PATH_SHADOW_PTMPTMP
-
-#define SGROUP_FILE    _PATH_SHADOW_GROUP
-#define SGTMP_FILE     _PATH_SHADOW_GTMP
-#define SGTMPTMP_FILE  _PATH_SHADOW_GTMPTMP
-
+# define PASSWD_FILE   _PATH_PASSWD
+# define GROUP_FILE    _PATH_GROUP
+# define SHADOW_FILE   _PATH_SHADOW_PASSWD
+# define SGROUP_FILE   _PATH_SHADOW_GROUP
 #else
-#define PASSWD_FILE    "/tmp/passwd"
-#define PTMP_FILE      "/tmp/ptmp"
-#define PTMPTMP_FILE   "/tmp/ptmptmp"
-
-#define GROUP_FILE     "/tmp/group"
-#define GTMP_FILE      "/tmp/gtmp"
-#define GTMPTMP_FILE   "/tmp/gtmptmp"
-
-#define SHADOW_FILE    "/tmp/shadow"
-#define SPTMP_FILE     "/tmp/sptmp"
-#define SPTMPTMP_FILE  "/tmp/sptmptmp"
-
-#define SGROUP_FILE    "/tmp/gshadow"
-#define SGTMP_FILE     "/tmp/sgtmp"
-#define SGTMPTMP_FILE  "/tmp/sgtmptmp"
+# define PASSWD_FILE   "/tmp/passwd"
+# define GROUP_FILE    "/tmp/group"
+# define SHADOW_FILE   "/tmp/shadow"
+# define SGROUP_FILE   "/tmp/gshadow"
 #endif
 
 extern int setpwnam (struct passwd *pwd);
index 66c99d1fdd78105d4b0a2039949fd7f7817fa2f8..62dcc85deac0129f1fefdc83530ca6fd99fbb744 100644 (file)
@@ -72,6 +72,7 @@ will be invoked instead of the default editor
 .El
 .SH SEE ALSO
 .BR passwd (1),
+.BR flock (2),
 .BR vi (1),
 .BR passwd (5)
 .SH HISTORY
index 992a3a3063643d7070e3c484049b9ff20da91d92..765d11120602c916a5bc7a18bae41de5f919df50 100644 (file)
@@ -57,6 +57,7 @@
 #include <fcntl.h>
 #include <paths.h>
 #include <pwd.h>
+#include <shadow.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -71,6 +72,7 @@
 #include <unistd.h>
 
 #include "c.h"
+#include "fileutils.h"
 #include "nls.h"
 #include "setpwnam.h"
 #include "strutils.h"
@@ -88,8 +90,7 @@ enum {
 };
 int program;
 char orig_file[FILENAMELEN];   /* original file /etc/passwd or /etc/group */
-char tmp_file[FILENAMELEN];    /* tmp file */
-char tmptmp_file[FILENAMELEN]; /* very tmp file */
+char *tmp_file;                        /* tmp file */
 
 void pw_error __P((char *, int, int));
 
@@ -137,55 +138,22 @@ static void pw_init(void)
        (void)umask(0);
 }
 
-static int pw_lock(void)
+static FILE * pw_tmpfile(int lockfd)
 {
-       int lockfd, fd, ret;
-
-       /*
-        * If the password file doesn't exist, the system is hosed.  Might as
-        * well try to build one.  Set the close-on-exec bit so that users
-        * can't get at the encrypted passwords while editing.  Open should
-        * allow flock'ing the file; see 4.4BSD.  XXX
-        */
-#if 0
-       /* flock()ing is superfluous here, with the ptmp/ptmptmp system. */
-       if (flock(lockfd, LOCK_EX | LOCK_NB)) {
-               if (program == VIPW)
-                       err(EXIT_FAILURE, _("cannot lock password file"));
-               else
-                       err(EXIT_FAILURE, _("cannot lock group file"));
-       }
-#endif
-
-       if ((fd = open(tmptmp_file, O_WRONLY | O_CREAT, 0600)) == -1)
-               err(EXIT_FAILURE, _("%s: open failed"), tmptmp_file);
-
-       ret = link(tmptmp_file, tmp_file);
-       (void)unlink(tmptmp_file);
-       if (ret == -1) {
-               if (errno == EEXIST)
-                       errx(EXIT_FAILURE,
-                            _("the %s file is busy (%s present)"),
-                            program == VIPW ? "password" : "group", tmp_file);
-               else
-                       err(EXIT_FAILURE, _("can't link %s"), tmp_file);
-       }
-
-       lockfd = open(orig_file, O_RDONLY, 0);
+       FILE *fd;
+       char *tmpname = NULL;
 
-       if (lockfd < 0) {
-               warn("%s", orig_file);
-               unlink(tmp_file);
-               exit(EXIT_FAILURE);
+       if ((fd = xmkstemp(&tmpname)) == NULL) {
+               ulckpwdf();
+               err(EXIT_FAILURE, _("can't open temporary file"));
        }
 
-       copyfile(lockfd, fd);
-       (void)close(lockfd);
-       (void)close(fd);
-       return 1;
+       copyfile(lockfd, fileno(fd));
+       tmp_file = tmpname;
+       return fd;
 }
 
-static void pw_unlock(void)
+static void pw_write(void)
 {
        char tmp[FILENAMELEN + 4];
 
@@ -215,10 +183,11 @@ static void pw_unlock(void)
        if (rename(tmp_file, orig_file) == -1) {
                int errsv = errno;
                errx(EXIT_FAILURE,
-                    ("can't unlock %s: %s (your changes are still in %s)"),
+                    ("cannot write %s: %s (your changes are still in %s)"),
                     orig_file, strerror(errsv), tmp_file);
        }
        unlink(tmp_file);
+       free(tmp_file);
 }
 
 static void pw_edit(int notsetuid)
@@ -275,33 +244,49 @@ void pw_error(char *name, int err, int eval)
        }
        warnx(_("%s unchanged"), orig_file);
        unlink(tmp_file);
+       ulckpwdf();
        exit(eval);
 }
 
 static void edit_file(int is_shadow)
 {
        struct stat begin, end;
+       int passwd_file, ch_ret;
+       FILE *tmp_fd;
 
        pw_init();
-       pw_lock();
 
-       if (stat(tmp_file, &begin))
+       /* acquire exclusive lock */
+       if (lckpwdf() < 0)
+               err(EXIT_FAILURE, _("cannot get lock"));
+
+       passwd_file = open(orig_file, O_RDONLY, 0);
+       if (passwd_file < 0)
+               err(EXIT_FAILURE, "%s: %s", _("cannot open file"), orig_file);
+       tmp_fd = pw_tmpfile(passwd_file);
+
+       if (fstat(fileno(tmp_fd), &begin))
                pw_error(tmp_file, 1, 1);
 
        pw_edit(0);
 
-       if (stat(tmp_file, &end))
+       if (fstat(fileno(tmp_fd), &end))
                pw_error(tmp_file, 1, 1);
        if (begin.st_mtime == end.st_mtime) {
                warnx(_("no changes made"));
                pw_error((char *)NULL, 0, 0);
        }
-       /* see pw_lock() where we create the file with mode 600 */
+       /* pw_tmpfile() will create the file with mode 600 */
        if (!is_shadow)
-               chmod(tmp_file, 0644);
+               ch_ret = fchmod(fileno(tmp_fd), 0644);
        else
-               chmod(tmp_file, 0400);
-       pw_unlock();
+               ch_ret = fchmod(fileno(tmp_fd), 0400);
+       if (ch_ret < 0)
+               err(EXIT_FAILURE, "%s: %s", _("cannot chmod file"), orig_file);
+       fclose(tmp_fd);
+       pw_write();
+       close(passwd_file);
+       ulckpwdf();
 }
 
 int main(int argc, char *argv[])
@@ -310,17 +295,12 @@ int main(int argc, char *argv[])
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-       memset(tmp_file, '\0', FILENAMELEN);
        if (!strcmp(program_invocation_short_name, "vigr")) {
                program = VIGR;
                xstrncpy(orig_file, GROUP_FILE, sizeof(orig_file));
-               xstrncpy(tmp_file, GTMP_FILE, sizeof(tmp_file));
-               xstrncpy(tmptmp_file, GTMPTMP_FILE, sizeof(tmptmp_file));
        } else {
                program = VIPW;
                xstrncpy(orig_file, PASSWD_FILE, sizeof(orig_file));
-               xstrncpy(tmp_file, PTMP_FILE, sizeof(tmp_file));
-               xstrncpy(tmptmp_file, PTMPTMP_FILE, sizeof(tmptmp_file));
        }
 
        if ((argc > 1) &&
@@ -333,12 +313,8 @@ int main(int argc, char *argv[])
 
        if (program == VIGR) {
                strncpy(orig_file, SGROUP_FILE, FILENAMELEN - 1);
-               strncpy(tmp_file, SGTMP_FILE, FILENAMELEN - 1);
-               strncpy(tmptmp_file, SGTMPTMP_FILE, FILENAMELEN - 1);
        } else {
                strncpy(orig_file, SHADOW_FILE, FILENAMELEN - 1);
-               strncpy(tmp_file, SPTMP_FILE, FILENAMELEN - 1);
-               strncpy(tmptmp_file, SPTMPTMP_FILE, FILENAMELEN - 1);
        }
 
        if (access(orig_file, F_OK) == 0) {