[PATCH 12/17] vipw: use xmkstemp() and lckpwdf()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Get rid private locking schema and use libc instead.

Signed-off-by: Sami Kerola <kerolasa@xxxxxx>
---
 login-utils/Makefile.am |    3 +-
 login-utils/setpwnam.h  |   39 ++++--------------
 login-utils/vipw.8      |    1 +
 login-utils/vipw.c      |  100 ++++++++++++++++++-----------------------------
 4 files changed, 49 insertions(+), 94 deletions(-)

diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am
index 7bd2ddb..7b3b739 100644
--- a/login-utils/Makefile.am
+++ b/login-utils/Makefile.am
@@ -51,7 +51,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)
diff --git a/login-utils/setpwnam.h b/login-utils/setpwnam.h
index e7f44a9..6a4dbb7 100644
--- a/login-utils/setpwnam.h
+++ b/login-utils/setpwnam.h
@@ -15,38 +15,15 @@
 #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);
diff --git a/login-utils/vipw.8 b/login-utils/vipw.8
index 66c99d1..62dcc85 100644
--- a/login-utils/vipw.8
+++ b/login-utils/vipw.8
@@ -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
diff --git a/login-utils/vipw.c b/login-utils/vipw.c
index 992a3a3..765d111 100644
--- a/login-utils/vipw.c
+++ b/login-utils/vipw.c
@@ -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) {
-- 
1.7.9.2

--
To unsubscribe from this list: send the line "unsubscribe util-linux" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux