diff options
author | David Nugent <davidn@FreeBSD.org> | 2000-06-18 05:51:35 +0000 |
---|---|---|
committer | David Nugent <davidn@FreeBSD.org> | 2000-06-18 05:51:35 +0000 |
commit | d56e55b0a378cffb2c9b484b6957bedbc51ae7b6 (patch) | |
tree | 309fc0078f5028629261ba29a77a6e2ecc94e542 | |
parent | 2b0ec9b9d68c5288e19cc6dcf670661d45bf0065 (diff) | |
download | src-d56e55b0a378cffb2c9b484b6957bedbc51ae7b6.tar.gz src-d56e55b0a378cffb2c9b484b6957bedbc51ae7b6.zip |
MFC recent bug fixes and feature.
This commit unifies pw(8) code across all active branches.
Still-Todo: manpage updates
Notes
Notes:
svn path=/stable/3/; revision=61793
-rw-r--r-- | usr.sbin/pw/fileupd.c | 62 | ||||
-rw-r--r-- | usr.sbin/pw/grupd.c | 5 | ||||
-rw-r--r-- | usr.sbin/pw/pw.c | 29 | ||||
-rw-r--r-- | usr.sbin/pw/pw.h | 2 | ||||
-rw-r--r-- | usr.sbin/pw/pw_group.c | 34 | ||||
-rw-r--r-- | usr.sbin/pw/pw_user.c | 226 | ||||
-rw-r--r-- | usr.sbin/pw/pw_vpw.c | 4 | ||||
-rw-r--r-- | usr.sbin/pw/pwupd.c | 31 | ||||
-rw-r--r-- | usr.sbin/pw/pwupd.h | 14 |
9 files changed, 297 insertions, 110 deletions
diff --git a/usr.sbin/pw/fileupd.c b/usr.sbin/pw/fileupd.c index 376f589ac1f7..a846513dbea3 100644 --- a/usr.sbin/pw/fileupd.c +++ b/usr.sbin/pw/fileupd.c @@ -71,38 +71,44 @@ extendarray(char ***buf, int * buflen, int needed) int fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode) { - int rc = 0; + int rc = 0; if (pfxlen <= 1) - errno = EINVAL; + rc = EINVAL; else { - int infd = open(filename, O_RDWR | O_CREAT, fmode); + int infd = open(filename, O_RDWR | O_CREAT, fmode); - if (infd != -1) { - FILE *infp = fdopen(infd, "r+"); + if (infd == -1) + rc = errno; + else { + FILE *infp = fdopen(infd, "r+"); - if (infp == NULL) + if (infp == NULL) { + rc = errno; /* Assumes fopen(3) sets errno from open(2) */ close(infd); - else { - int outfd; - char file[MAXPATHLEN]; + } else { + int outfd; + char file[MAXPATHLEN]; strcpy(file, filename); strcat(file, ".new"); outfd = open(file, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, fmode); - if (outfd != -1) { - FILE *outfp = fdopen(outfd, "w+"); + if (outfd == -1) + rc = errno; + else { + FILE *outfp = fdopen(outfd, "w+"); - if (outfp == NULL) + if (outfp == NULL) { + rc = errno; close(outfd); - else { - int updated = UPD_CREATE; + } else { + int updated = UPD_CREATE; int linesize = PWBUFSZ; - char *line = malloc(linesize); + char *line = malloc(linesize); nextline: while (fgets(line, linesize, infp) != NULL) { - char *p = strchr(line, '\n'); + char *p = strchr(line, '\n'); while ((p = strchr(line, '\n')) == NULL) { int l; @@ -143,7 +149,11 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const * then error */ if (updmode != updated) - errno = (updmode == UPD_CREATE) ? EEXIST : ENOENT; + /* -1 return means: + * update,delete=no user entry + * create=entry exists + */ + rc = -1; else { /* @@ -155,9 +165,9 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const /* * Flush the file and check for the result */ - rc = fflush(outfp) != EOF; - if (rc) { - + if (fflush(outfp) == EOF) + rc = errno; /* Failed to update */ + else { /* * Copy data back into the * original file and truncate @@ -168,18 +178,16 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const fputs(line, infp); /* - * If there was a problem with copying - * we will just rename 'file.new' - * to 'file'. + * If there was a problem with copying + * we will just rename 'file.new' + * to 'file'. * This is a gross hack, but we may have * corrupted the original file * Unfortunately, it will lose the inode - * and hence the lock. + * and hence the lock. */ - if (fflush(infp) == EOF || ferror(infp)) { - rc = errno; /* Preserve errno for return */ + if (fflush(infp) == EOF || ferror(infp)) rename(file, filename); - } else ftruncate(infd, ftell(infp)); } diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c index 237fe950d5fc..edff76d1285c 100644 --- a/usr.sbin/pw/grupd.c +++ b/usr.sbin/pw/grupd.c @@ -142,8 +142,9 @@ gr_update(struct group * grp, char const * group, int mode) if (grp != NULL && fmtgrentry(&grbuf, &grbuflen, grp, PWF_PASSWD) == -1) l = -1; else { - if ((l = fileupdate(getgrpath(_GROUP), 0644, grbuf, pfx, l, mode)) != 0) - l = grdb(NULL) == 0; + l = fileupdate(getgrpath(_GROUP), 0644, grbuf, pfx, l, mode); + if (l == 0) + l = grdb(NULL); } if (grbuf != NULL) free(grbuf); diff --git a/usr.sbin/pw/pw.c b/usr.sbin/pw/pw.c index 1da063c0796b..6c070acb2665 100644 --- a/usr.sbin/pw/pw.c +++ b/usr.sbin/pw/pw.c @@ -35,16 +35,23 @@ static const char rcsid[] = #include <sys/wait.h> #include "pw.h" -const char *Modes[] = {"add", "del", "mod", "show", "next", NULL}; +#if !defined(_PATH_YP) +#define _PATH_YP "/var/yp/" +#endif +const char *Modes[] = { + "add", "del", "mod", "show", "next", + NULL}; const char *Which[] = {"user", "group", NULL}; static const char *Combo1[] = { "useradd", "userdel", "usermod", "usershow", "usernext", + "lock", "unlock", "groupadd", "groupdel", "groupmod", "groupshow", "groupnext", NULL}; static const char *Combo2[] = { "adduser", "deluser", "moduser", "showuser", "nextuser", + "lock", "unlock", "addgroup", "delgroup", "modgroup", "showgroup", "nextgroup", -NULL}; + NULL}; struct pwf PWF = { @@ -102,6 +109,8 @@ main(int argc, char *argv[]) "V:C:qn:u:rY", "V:C:qn:u:c:d:e:p:g:G:ml:k:s:w:L:h:FNPY", "V:C:qn:u:FPa7", + "V:C:q", + "V:C:q", "V:C:q" }, { /* grp */ @@ -144,14 +153,16 @@ main(int argc, char *argv[]) } else break; } - else if ((tmp = getindex(Modes, argv[1])) != -1) + else if (mode == -1 && (tmp = getindex(Modes, argv[1])) != -1) mode = tmp; - else if ((tmp = getindex(Which, argv[1])) != -1) + else if (which == -1 && (tmp = getindex(Which, argv[1])) != -1) which = tmp; - else if ((tmp = getindex(Combo1, argv[1])) != -1 || (tmp = getindex(Combo2, argv[1])) != -1) { + else if ((mode == -1 && which == -1) && + ((tmp = getindex(Combo1, argv[1])) != -1 || + (tmp = getindex(Combo2, argv[1])) != -1)) { which = tmp / M_NUM; mode = tmp % M_NUM; - } else if (strcmp(argv[1], "help") == 0) + } else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL) cmdhelp(mode, which); else if (which != -1 && mode != -1) addarg(&arglist, 'n', argv[1]); @@ -175,7 +186,7 @@ main(int argc, char *argv[]) while ((ch = getopt(argc, argv, opts[which][mode])) != -1) { if (ch == '?') - errx(EX_USAGE, NULL); + errx(EX_USAGE, "unknown switch"); else addarg(&arglist, ch, optarg); optarg = NULL; @@ -272,9 +283,9 @@ static void cmdhelp(int mode, int which) { if (which == -1) - fprintf(stderr, "usage: pw [user|group] [add|del|mod|show|next] [ help | switches/values ]\n"); + fprintf(stderr, "usage:\n pw [user|group|lock|unlock] [add|del|mod|show|next] [help|switches/values]\n"); else if (mode == -1) - fprintf(stderr, "usage: pw %s [add|del|mod|show|next] [ help | switches/values ]\n", Which[which]); + fprintf(stderr, "usage:\n pw %s [add|del|mod|show|next] [help|switches/values]\n", Which[which]); else { /* diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h index f85eac737db3..aa437ec3cd9a 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -50,6 +50,8 @@ enum _mode M_UPDATE, M_PRINT, M_NEXT, + M_LOCK, + M_UNLOCK, M_NUM }; diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c index 3385752feafc..6042a683713d 100644 --- a/usr.sbin/pw/pw_group.c +++ b/usr.sbin/pw/pw_group.c @@ -44,12 +44,13 @@ static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); int pw_group(struct userconf * cnf, int mode, struct cargs * args) { + int rc; struct carg *a_name = getarg(args, 'n'); struct carg *a_gid = getarg(args, 'g'); struct carg *arg; struct group *grp = NULL; int grmembers = 0; - char **members = NULL; + char **members = NULL; static struct group fakegroup = { @@ -59,12 +60,14 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) NULL }; + if (mode == M_LOCK || mode == M_UNLOCK) + errx(EX_USAGE, "'lock' command is not available for groups"); + /* * With M_NEXT, we only need to return the * next gid to stdout */ - if (mode == M_NEXT) - { + if (mode == M_NEXT) { gid_t next = gr_gidpolicy(cnf, args); if (getarg(args, 'q')) return next; @@ -116,8 +119,13 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) if (mode == M_DELETE) { gid_t gid = grp->gr_gid; - if (delgrent(grp) == -1) - err(EX_IOERR, "error updating group file"); + rc = delgrent(grp); + if (rc == -1) + err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name); + else if (rc != 0) { + warn("group update"); + return EX_IOERR; + } pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid); return EXIT_SUCCESS; } else if (mode == M_PRINT) @@ -231,8 +239,17 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) if (getarg(args, 'N') != NULL) return print_group(grp, getarg(args, 'P') != NULL); - if ((mode == M_ADD && !addgrent(grp)) || (mode == M_UPDATE && !chggrent(a_name->val, grp))) { - warn("group update"); + if (mode == M_ADD && (rc = addgrent(grp)) != 0) { + if (rc == -1) + warnx("group '%s' already exists", grp->gr_name); + else + warn("group update"); + return EX_IOERR; + } else if (mode == M_UPDATE && (rc = chggrent(a_name->val, grp)) != 0) { + if (rc == -1) + warnx("group '%s' not available (NIS?)", grp->gr_name); + else + warn("group update"); return EX_IOERR; } /* grp may have been invalidated */ @@ -282,7 +299,8 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args) */ SETGRENT(); while ((grp = GETGRENT()) != NULL) - if (grp->gr_gid >= (int) cnf->min_gid && grp->gr_gid <= (int) cnf->max_gid) + if ((gid_t)grp->gr_gid >= (gid_t)cnf->min_gid && + (gid_t)grp->gr_gid <= (gid_t)cnf->max_gid) bm_setbit(&bm, grp->gr_gid - cnf->min_gid); ENDGRENT(); diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index bba8a01e47bd..b70a4102a521 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -55,6 +55,7 @@ static const char rcsid[] = #endif static int randinit; +static char locked_str[] = "*LOCKED*"; static int print_user(struct passwd * pwd, int pretty, int v7); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); @@ -102,8 +103,9 @@ static void rmskey(char const * name); int pw_user(struct userconf * cnf, int mode, struct cargs * args) { - int r, r1; + int rc, edited = 0; char *p = NULL; + char *passtmp; struct carg *a_name; struct carg *a_uid; struct carg *arg; @@ -121,12 +123,15 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) 0, "", "User &", + "/nonexistent", "/bin/sh", - 0, - 0, 0 +#if defined(__FreeBSD__) + ,0 +#endif }; + /* * With M_NEXT, we only need to return the * next uid to stdout @@ -204,7 +209,6 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) errx(EX_OSFILE, "root home `%s' is not a directory", cnf->home); } - if ((arg = getarg(args, 'e')) != NULL) cnf->expire_days = atoi(arg->val); @@ -226,7 +230,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) cnf->default_class = pw_checkname((u_char *)arg->val, 0); if ((arg = getarg(args, 'G')) != NULL && arg->val) { - int i = 0; + int i = 0; for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) { if ((grp = GETGRNAM(p)) == NULL) { @@ -239,10 +243,12 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) while (i < cnf->numgroups) cnf->groups[i++] = NULL; } + if ((arg = getarg(args, 'k')) != NULL) { if (stat(cnf->dotdir = arg->val, &st) == -1 || !S_ISDIR(st.st_mode)) errx(EX_OSFILE, "skeleton `%s' is not a directory or does not exist", cnf->dotdir); } + if ((arg = getarg(args, 's')) != NULL) cnf->shell_default = arg->val; @@ -270,6 +276,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) warn("config update"); return EX_IOERR; } + if (mode == M_PRINT && getarg(args, 'a')) { int pretty = getarg(args, 'P') != NULL; int v7 = getarg(args, '7') != NULL; @@ -280,6 +287,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) ENDPWENT(); return EXIT_SUCCESS; } + if ((a_name = getarg(args, 'n')) != NULL) pwd = GETPWNAM(pw_checkname((u_char *)a_name->val, 0)); a_uid = getarg(args, 'u'); @@ -300,10 +308,13 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) a_name = NULL; } } + /* * Update, delete & print require that the user exists */ - if (mode == M_UPDATE || mode == M_DELETE || mode == M_PRINT) { + if (mode == M_UPDATE || mode == M_DELETE || + mode == M_PRINT || mode == M_LOCK || mode == M_UNLOCK) { + if (a_name == NULL && pwd == NULL) /* Try harder */ pwd = GETPWUID(atoi(a_uid->val)); @@ -319,13 +330,39 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) errx(EX_NOUSER, "no such uid `%s'", a_uid->val); errx(EX_NOUSER, "no such user `%s'", a_name->val); } + if (a_name == NULL) /* May be needed later */ a_name = addarg(args, 'n', newstr(pwd->pw_name)); /* - * Handle deletions now + * The M_LOCK and M_UNLOCK functions simply add or remove + * a "*LOCKED*" prefix from in front of the password to + * prevent it decoding correctly, and therefore prevents + * access. Of course, this only prevents access via + * password authentication (not ssh, kerberos or any + * other method that does not use the UNIX password) but + * that is a known limitation. */ - if (mode == M_DELETE) { + + if (mode == M_LOCK) { + if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) == 0) + errx(EX_DATAERR, "user '%s' is already locked", pwd->pw_name); + passtmp = malloc(strlen(pwd->pw_passwd) + sizeof(locked_str)); + if (passtmp == NULL) /* disaster */ + errx(EX_UNAVAILABLE, "out of memory"); + strcpy(passtmp, locked_str); + strcat(passtmp, pwd->pw_passwd); + pwd->pw_passwd = passtmp; + edited = 1; + } else if (mode == M_UNLOCK) { + if (strncmp(pwd->pw_passwd, locked_str, sizeof(locked_str)-1) != 0) + errx(EX_DATAERR, "user '%s' is not locked", pwd->pw_name); + pwd->pw_passwd += sizeof(locked_str)-1; + edited = 1; + } else if (mode == M_DELETE) { + /* + * Handle deletions now + */ char file[MAXPATHLEN]; char home[MAXPATHLEN]; uid_t uid = pwd->pw_uid; @@ -357,12 +394,23 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) strncpy(home, pwd->pw_dir, sizeof home); home[sizeof home - 1] = '\0'; - if (!delpwent(pwd)) - err(EX_IOERR, "error updating passwd file"); + rc = delpwent(pwd); + if (rc == -1) + err(EX_IOERR, "user '%s' does not exist", pwd->pw_name); + else if (rc != 0) { + warn("passwd update"); + return EX_IOERR; + } + + if (cnf->nispasswd && *cnf->nispasswd=='/') { + rc = delnispwent(cnf->nispasswd, a_name->val); + if (rc == -1) + warnx("WARNING: user '%s' does not exist in NIS passwd", pwd->pw_name); + else if (rc != 0) + warn("WARNING: NIS passwd update"); + /* non-fatal */ + } - if (cnf->nispasswd && *cnf->nispasswd=='/' && !delnispwent(cnf->nispasswd, a_name->val)) - warn("WARNING: NIS passwd update"); - editgroups(a_name->val, NULL); pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid); @@ -404,46 +452,84 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "can't rename `root' account"); pwd->pw_name = pw_checkname((u_char *)arg->val, 0); + edited = 1; } + if ((arg = getarg(args, 'u')) != NULL && isdigit(*arg->val)) { pwd->pw_uid = (uid_t) atol(arg->val); + edited = 1; if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "can't change uid of `root' account"); if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) warnx("WARNING: account `%s' will have a uid of 0 (superuser access!)", pwd->pw_name); } - if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) /* Already checked this */ - pwd->pw_gid = (gid_t) GETGRNAM(cnf->default_group)->gr_gid; + + if ((arg = getarg(args, 'g')) != NULL && pwd->pw_uid != 0) { /* Already checked this */ + gid_t newgid = (gid_t) GETGRNAM(cnf->default_group)->gr_gid; + if (newgid != pwd->pw_gid) { + edited = 1; + pwd->pw_gid = newgid; + } + } if ((arg = getarg(args, 'p')) != NULL) { - if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) - pwd->pw_change = 0; + if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) { + if (pwd->pw_change != 0) { + pwd->pw_change = 0; + edited = 1; + } + } else { time_t now = time(NULL); time_t expire = parse_date(now, arg->val); if (now == expire) errx(EX_DATAERR, "invalid password change date `%s'", arg->val); - pwd->pw_change = expire; + if (pwd->pw_change != expire) { + pwd->pw_change = expire; + edited = 1; + } } } + if ((arg = getarg(args, 'e')) != NULL) { - if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) - pwd->pw_expire = 0; + if (*arg->val == '\0' || strcmp(arg->val, "0") == 0) { + if (pwd->pw_expire != 0) { + pwd->pw_expire = 0; + edited = 1; + } + } else { time_t now = time(NULL); time_t expire = parse_date(now, arg->val); if (now == expire) errx(EX_DATAERR, "invalid account expiry date `%s'", arg->val); - pwd->pw_expire = expire; + if (pwd->pw_expire != expire) { + pwd->pw_expire = expire; + edited = 1; + } } } - if ((arg = getarg(args, 's')) != NULL) - pwd->pw_shell = shell_path(cnf->shelldir, cnf->shells, arg->val); - if (getarg(args, 'L')) - pwd->pw_class = cnf->default_class; + if ((arg = getarg(args, 's')) != NULL) { + char *shell = shell_path(cnf->shelldir, cnf->shells, arg->val); + if (shell == NULL) + shell = ""; + if (strcmp(shell, pwd->pw_shell) != 0) { + pwd->pw_shell = shell; + edited = 1; + } + } + + if (getarg(args, 'L')) { + if (cnf->default_class == NULL) + cnf->default_class = ""; + if (strcmp(pwd->pw_class, cnf->default_class) != 0) { + pwd->pw_class = cnf->default_class; + edited = 1; + } + } if ((arg = getarg(args, 'd')) != NULL) { if (stat(pwd->pw_dir = arg->val, &st) == -1) { @@ -453,10 +539,17 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) warnx("WARNING: home `%s' is not a directory", pwd->pw_dir); } - if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) + if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) { pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); + edited = 1; + } } else { + + /* + * Add code + */ + if (a_name == NULL) /* Required */ errx(EX_DATAERR, "login name required"); else if ((pwd = GETPWNAM(a_name->val)) != NULL) /* Exists */ @@ -475,6 +568,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) pwd->pw_expire = pw_exppolicy(cnf, args); pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name); pwd->pw_shell = pw_shellpolicy(cnf, args, NULL); + edited = 1; if (pwd->pw_uid == 0 && strcmp(pwd->pw_name, "root") != 0) warnx("WARNING: new account `%s' has a uid of 0 (superuser access!)", pwd->pw_name); @@ -483,8 +577,13 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) /* * Shared add/edit code */ - if ((arg = getarg(args, 'c')) != NULL) - pwd->pw_gecos = pw_checkname((u_char *)arg->val, 1); + if ((arg = getarg(args, 'c')) != NULL) { + char *gecos = pw_checkname((u_char *)arg->val, 1); + if (strcmp(pwd->pw_gecos, gecos) != 0) { + pwd->pw_gecos = gecos; + edited = 1; + } + } if ((arg = getarg(args, 'h')) != NULL) { if (strcmp(arg->val, "-") == 0) @@ -524,6 +623,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (!*line) errx(EX_DATAERR, "empty password read on file descriptor %d", fd); pwd->pw_passwd = pw_pwcrypt(line); + edited = 1; } } @@ -535,23 +635,43 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) getarg(args, 'P') != NULL, getarg(args, '7') != NULL); - r = r1 = 1; if (mode == M_ADD) { - r = addpwent(pwd); - if (r && cnf->nispasswd && *cnf->nispasswd=='/') - r1 = addnispwent(cnf->nispasswd, pwd); - } else if (mode == M_UPDATE) { - r = chgpwent(a_name->val, pwd); - if (r && cnf->nispasswd && *cnf->nispasswd=='/') - r1 = chgnispwent(cnf->nispasswd, a_name->val, pwd); - } - - if (!r) { - warn("password update"); - return EX_IOERR; - } else if (!r1) { - warn("WARNING: NIS password update"); - /* Keep on trucking */ + edited = 1; /* Always */ + rc = addpwent(pwd); + if (rc == -1) { + warnx("user '%s' already exists", pwd->pw_name); + return EX_IOERR; + } else if (rc != 0) { + warn("passwd file update"); + return EX_IOERR; + } + if (cnf->nispasswd && *cnf->nispasswd=='/') { + rc = addnispwent(cnf->nispasswd, pwd); + if (rc == -1) + warnx("User '%s' already exists in NIS passwd", pwd->pw_name); + else + warn("NIS passwd update"); + /* NOTE: we treat NIS-only update errors as non-fatal */ + } + } else if (mode == M_UPDATE || mode == M_LOCK || mode == M_UNLOCK) { + if (edited) { /* Only updated this if required */ + rc = chgpwent(a_name->val, pwd); + if (rc == -1) { + warnx("user '%s' does not exist (NIS?)", pwd->pw_name); + return EX_IOERR; + } else if (rc != 0) { + warn("passwd file update"); + return EX_IOERR; + } + if ( cnf->nispasswd && *cnf->nispasswd=='/') { + rc = chgnispwent(cnf->nispasswd, a_name->val, pwd); + if (rc == -1) + warn("User '%s' not found in NIS passwd", pwd->pw_name); + else + warn("NIS passwd update"); + /* NOTE: NIS-only update errors are not fatal */ + } + } } /* @@ -561,8 +681,16 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (mode == M_ADD || getarg(args, 'G') != NULL) editgroups(pwd->pw_name, cnf->groups); - /* pwd may have been invalidated */ - if ((pwd = GETPWNAM(a_name->val)) == NULL) + /* go get a current version of pwd */ + pwd = GETPWNAM(a_name->val); + if (pwd == NULL) { + /* This will fail when we rename, so special case that */ + if (mode == M_UPDATE && (arg = getarg(args, 'l')) != NULL) { + a_name->val = arg->val; /* update new name */ + pwd = GETPWNAM(a_name->val); /* refetch renamed rec */ + } + } + if (pwd == NULL) /* can't go on without this */ errx(EX_NOUSER, "user '%s' disappeared during update", a_name->val); grp = GETGRGID(pwd->pw_gid); @@ -607,6 +735,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) } } } + /* * Finally, let's create and populate the user's home directory. Note * that this also `works' for editing users if -m is used, but @@ -617,6 +746,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) pw_log(cnf, mode, W_USER, "%s(%ld) home %s made", pwd->pw_name, (long) pwd->pw_uid, pwd->pw_dir); } + return EXIT_SUCCESS; } @@ -1016,9 +1146,9 @@ print_user(struct passwd * pwd, int pretty, int v7) *p = (char) toupper(*p); } if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL) - strftime(acexpire, sizeof acexpire, "%c", tptr); + strftime(acexpire, sizeof acexpire, "%e-%b-%Y %T", tptr); if (pwd->pw_change > (time_t)9 && (tptr = localtime(&pwd->pw_change)) != NULL) - strftime(pwexpire, sizeof pwexpire, "%c", tptr); + strftime(pwexpire, sizeof pwexpire, "%e-%b-%Y %T", tptr); printf("Login Name: %-15s #%-12ld Group: %-15s #%ld\n" " Full Name: %s\n" " Home: %-26.26s Class: %s\n" diff --git a/usr.sbin/pw/pw_vpw.c b/usr.sbin/pw/pw_vpw.c index ef12437a15ef..bc5713e82d32 100644 --- a/usr.sbin/pw/pw_vpw.c +++ b/usr.sbin/pw/pw_vpw.c @@ -190,11 +190,13 @@ vendgrent(void) } } -int +RET_SETGRENT vsetgrent(void) { vendgrent(); +#if defined(__FreeBSD__) return 0; +#endif } static struct group * diff --git a/usr.sbin/pw/pwupd.c b/usr.sbin/pw/pwupd.c index 10a6066e198c..1f0d86fa7322 100644 --- a/usr.sbin/pw/pwupd.c +++ b/usr.sbin/pw/pwupd.c @@ -43,6 +43,7 @@ static const char rcsid[] = #include "pwupd.h" #define HAVE_PWDB_C 1 +#define HAVE_PWDB_U 1 static char pathpwd[] = _PATH_PWD; static char * pwpath = pathpwd; @@ -92,14 +93,14 @@ pwdb(char *arg,...) args[i] = NULL; if ((pid = fork()) == -1) /* Error (errno set) */ - i = -1; + i = errno; else if (pid == 0) { /* Child */ execv(args[0], args); _exit(1); } else { /* Parent */ waitpid(pid, &i, 0); - if ((i = WEXITSTATUS(i)) != 0) - errno = EIO; /* set SOMETHING */ + if (WEXITSTATUS(i)) + i = EIO; } return i; } @@ -150,9 +151,12 @@ pw_update(struct passwd * pwd, char const * user, int mode) #else { /* No -C */ #endif - char pfx[32]; + char pfx[PWBUFSZ]; char pwbuf[PWBUFSZ]; - int l = sprintf(pfx, "%s:", user); + int l = snprintf(pfx, PWBUFSZ, "%s:", user); +#ifdef HAVE_PWDB_U + int isrename = strcmp(user, pwd->pw_name); +#endif /* * Update the passwd file first @@ -161,18 +165,25 @@ pw_update(struct passwd * pwd, char const * user, int mode) *pwbuf = '\0'; else fmtpwentry(pwbuf, pwd, PWF_PASSWD); - if ((rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode)) != 0) { + + rc = fileupdate(getpwpath(_PASSWD), 0644, pwbuf, pfx, l, mode); + if (rc == 0) { /* * Then the master.passwd file */ if (pwd != NULL) fmtpwentry(pwbuf, pwd, PWF_MASTER); - if ((rc = fileupdate(getpwpath(_MASTERPASSWD), 0644, pwbuf, pfx, l, mode)) != 0) { - if (mode == UPD_DELETE) - rc = pwdb(NULL) == 0; + rc = fileupdate(getpwpath(_MASTERPASSWD), 0644, pwbuf, pfx, l, mode); + if (rc == 0) { +#ifdef HAVE_PWDB_U + if (mode == UPD_DELETE || isrename) +#endif + rc = pwdb(NULL); +#ifdef HAVE_PWDB_U else - rc = pwdb("-u", user, NULL) == 0; + rc = pwdb("-u", user, NULL); +#endif } } } diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index 046bd2e464c9..8da036dbdf92 100644 --- a/usr.sbin/pw/pwupd.h +++ b/usr.sbin/pw/pwupd.h @@ -35,6 +35,12 @@ #include <sys/cdefs.h> +#if defined(__FreeBSD__) +#define RET_SETGRENT int +#else +#define RET_SETGRENT void +#endif + enum updtype { UPD_DELETE = -1, @@ -63,7 +69,7 @@ struct pwf struct passwd * (*_getpwuid)(uid_t uid); struct passwd * (*_getpwnam)(const char * nam); int (*_pwdb)(char *arg, ...); - int (*_setgrent)(void); + RET_SETGRENT (*_setgrent)(void); void (*_endgrent)(void); struct group * (*_getgrent)(void); struct group * (*_getgrgid)(gid_t gid); @@ -135,15 +141,13 @@ struct passwd * vgetpwnam __P((const char * nam)); struct passwd * vgetpwent __P((void)); int vpwdb __P((char *arg, ...)); -int vsetgrent __P((void)); -void vendgrent __P((void)); struct group * vgetgrent __P((void)); struct group * vgetgrgid __P((gid_t gid)); struct group * vgetgrnam __P((const char * nam)); struct group * vgetgrent __P((void)); int vgrdb __P((char *arg, ...)); -int vsetgrent __P((void)); -void vendgrent __P((void)); +RET_SETGRENT vsetgrent __P((void)); +void vendgrent __P((void)); void copymkdir __P((char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)); void rm_r __P((char const * dir, uid_t uid)); |