summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2004-04-20 23:20:08 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2004-04-20 23:20:08 +0000
commita4ccbe5bc7e8df106f798254306616fb80e6922f (patch)
tree36e883584f5995d21c4c37300e1a7dbfc63b492b /lib
parent5d3813f3f73ea1f5cd7b4684048b1db3b5cb6adc (diff)
Change pw_copy(3) to take a 3rd arguement, the existing passwd entry.
This allows an application to only update a password entry if it is in the state it expects. Additionally, if the old passwd struct is specified the new one may have a different pw_name field since matching is done on the original. Adapted from FreeBSD.
Diffstat (limited to 'lib')
-rw-r--r--lib/libutil/passwd.c37
-rw-r--r--lib/libutil/pw_init.319
-rw-r--r--lib/libutil/shlib_version2
-rw-r--r--lib/libutil/util.h4
4 files changed, 49 insertions, 13 deletions
diff --git a/lib/libutil/passwd.c b/lib/libutil/passwd.c
index 33b900db5c0..69d6cdc1dcd 100644
--- a/lib/libutil/passwd.c
+++ b/lib/libutil/passwd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: passwd.c,v 1.42 2003/06/26 16:34:42 deraadt Exp $ */
+/* $OpenBSD: passwd.c,v 1.43 2004/04/20 23:20:07 millert Exp $ */
/*
* Copyright (c) 1987, 1993, 1994, 1995
@@ -30,7 +30,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$OpenBSD: passwd.c,v 1.42 2003/06/26 16:34:42 deraadt Exp $";
+static const char rcsid[] = "$OpenBSD: passwd.c,v 1.43 2004/04/20 23:20:07 millert Exp $";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
@@ -422,12 +422,27 @@ pw_prompt(void)
pw_error(NULL, 0, 0);
}
+static int
+pw_equal(const struct passwd *pw1, const struct passwd *pw2)
+{
+ return (strcmp(pw1->pw_name, pw2->pw_name) == 0 &&
+ pw1->pw_uid == pw2->pw_uid &&
+ pw1->pw_gid == pw2->pw_gid &&
+ strcmp(pw1->pw_class, pw2->pw_class) == 0 &&
+ pw1->pw_change == pw2->pw_change &&
+ pw1->pw_expire == pw2->pw_expire &&
+ strcmp(pw1->pw_gecos, pw2->pw_gecos) == 0 &&
+ strcmp(pw1->pw_dir, pw2->pw_dir) == 0 &&
+ strcmp(pw1->pw_shell, pw2->pw_shell) == 0);
+}
+
void
-pw_copy(int ffd, int tfd, struct passwd *pw)
+pw_copy(int ffd, int tfd, const struct passwd *pw, const struct passwd *opw)
{
+ struct passwd tpw;
FILE *from, *to;
int done;
- char *p, buf[8192];
+ char *p, *ep, buf[8192];
char *master = pw_file(_PATH_MASTERPASSWD);
if (!master)
@@ -438,7 +453,7 @@ pw_copy(int ffd, int tfd, struct passwd *pw)
pw_error(pw_lck ? pw_lck : NULL, pw_lck ? 1 : 0, 1);
for (done = 0; fgets(buf, sizeof(buf), from);) {
- if (!strchr(buf, '\n')) {
+ if ((ep = strchr(buf, '\n')) == NULL) {
warnx("%s: line too long", master);
pw_error(NULL, 0, 1);
}
@@ -453,13 +468,23 @@ pw_copy(int ffd, int tfd, struct passwd *pw)
pw_error(NULL, 0, 1);
}
*p = '\0';
- if (strcmp(buf, pw->pw_name)) {
+ if (strcmp(buf, opw ? opw->pw_name : pw->pw_name)) {
*p = ':';
(void)fprintf(to, "%s", buf);
if (ferror(to))
goto err;
continue;
}
+ if (opw != NULL) {
+ *p = ':';
+ *ep = '\0';
+ if (!pw_scan(buf, &tpw, NULL))
+ pw_error(NULL, 0, 1);
+ if (!pw_equal(&tpw, opw)) {
+ warnx("%s: inconsistent entry", master);
+ pw_error(NULL, 0, 1);
+ }
+ }
(void)fprintf(to, "%s:%s:%u:%u:%s:%d:%d:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd, (u_int)pw->pw_uid,
(u_int)pw->pw_gid, pw->pw_class, pw->pw_change,
diff --git a/lib/libutil/pw_init.3 b/lib/libutil/pw_init.3
index 2cff0f3a33f..49daeb04724 100644
--- a/lib/libutil/pw_init.3
+++ b/lib/libutil/pw_init.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pw_init.3,v 1.7 2003/06/02 20:18:42 millert Exp $
+.\" $OpenBSD: pw_init.3,v 1.8 2004/04/20 23:20:07 millert Exp $
.\"
.\" Copyright (c) 1995
.\" The Regents of the University of California. All rights reserved.
@@ -58,7 +58,7 @@
.Ft void
.Fn pw_prompt
.Ft void
-.Fn pw_copy "int ffd" "int tfd" "struct passwd *pw"
+.Fn pw_copy "int ffd" "int tfd" "const struct passwd *pw" "const struct passwd *opw"
.Ft int
.Fn pw_scan "char *bp" "struct passwd *pw" "int *flags"
.Ft void
@@ -125,9 +125,20 @@ function reads a passwd file from
.Fa ffd
and writes it to
.Fa tfd ,
-updating the entry corresponding to pw->pw_name with the information
-in
+updating the entry corresponding to pw-\*(Gtpw_name
+with the information in
.Fa pw .
+If
+.Fa opw
+is not NULL, opw-\*(Gtpw_name will be used for matching instead.
+Additionally, if the existing entry does not match
+.Fa opw ,
+the operation is aborted.
+The use of
+.Fa opw
+allows the caller to change the user name in an entry as well as
+guarantee that the entry being replaced has not changed in the
+meantime.
.Pp
The
.Fn pw_scan
diff --git a/lib/libutil/shlib_version b/lib/libutil/shlib_version
index 1c5d96eb2aa..c10074d52ae 100644
--- a/lib/libutil/shlib_version
+++ b/lib/libutil/shlib_version
@@ -1,2 +1,2 @@
-major=9
+major=10
minor=0
diff --git a/lib/libutil/util.h b/lib/libutil/util.h
index 6f8b9b4095b..d3fc11fc35a 100644
--- a/lib/libutil/util.h
+++ b/lib/libutil/util.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.h,v 1.24 2003/06/02 20:18:42 millert Exp $ */
+/* $OpenBSD: util.h,v 1.25 2004/04/20 23:20:07 millert Exp $ */
/* $NetBSD: util.h,v 1.2 1996/05/16 07:00:22 thorpej Exp $ */
/*-
@@ -97,7 +97,7 @@ int pw_abort(void);
void pw_init(void);
void pw_edit(int, const char *);
void pw_prompt(void);
-void pw_copy(int, int, struct passwd *);
+void pw_copy(int, int, const struct passwd *, const struct passwd *);
void pw_getconf(char *, size_t, const char *, const char *);
int pw_scan(char *, struct passwd *, int *);
void pw_error(const char *, int, int);