diff options
Diffstat (limited to 'usr.sbin/pw')
42 files changed, 384 insertions, 249 deletions
diff --git a/usr.sbin/pw/Makefile b/usr.sbin/pw/Makefile index 353eac132c7d..cd93a227fa6f 100644 --- a/usr.sbin/pw/Makefile +++ b/usr.sbin/pw/Makefile @@ -1,5 +1,4 @@ -# $FreeBSD$ - +PACKAGE= runtime PROG= pw MAN= pw.conf.5 pw.8 SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \ diff --git a/usr.sbin/pw/Makefile.depend b/usr.sbin/pw/Makefile.depend index f746d7af1b21..1a673c53cbc6 100644 --- a/usr.sbin/pw/Makefile.depend +++ b/usr.sbin/pw/Makefile.depend @@ -1,15 +1,12 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ - gnu/lib/csu \ include \ include/xlocale \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ lib/libcrypt \ - lib/libsbuf \ lib/libutil \ diff --git a/usr.sbin/pw/README b/usr.sbin/pw/README index bbb153988366..b437df6b510f 100644 --- a/usr.sbin/pw/README +++ b/usr.sbin/pw/README @@ -16,7 +16,5 @@ is fully supported. This program may be FreeBSD specific, but should be trivial to port to other bsd4.4 variants. -Author and maintainer: David L. Nugent, <davidn@blaze.net.au> - -$FreeBSD$ +Author: David L. Nugent, <davidn@blaze.net.au> diff --git a/usr.sbin/pw/bitmap.c b/usr.sbin/pw/bitmap.c index be82b2c792dd..f176fe571a36 100644 --- a/usr.sbin/pw/bitmap.c +++ b/usr.sbin/pw/bitmap.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <stdlib.h> #include <string.h> diff --git a/usr.sbin/pw/bitmap.h b/usr.sbin/pw/bitmap.h index 570c678237d5..5bb436630055 100644 --- a/usr.sbin/pw/bitmap.h +++ b/usr.sbin/pw/bitmap.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _BITMAP_H_ diff --git a/usr.sbin/pw/cpdir.c b/usr.sbin/pw/cpdir.c index 4e6ca8828b91..3dee8f7c43ac 100644 --- a/usr.sbin/pw/cpdir.c +++ b/usr.sbin/pw/cpdir.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <dirent.h> #include <err.h> #include <errno.h> @@ -54,13 +49,28 @@ copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, if (*dir == '/') dir++; - if (mkdirat(rootfd, dir, mode) != 0 && errno != EEXIST) { - warn("mkdir(%s)", dir); - return; + if (mkdirat(rootfd, dir, mode) != 0) { + mode_t pumask; + + if (errno != EEXIST) { + warn("mkdir(%s)", dir); + return; + } + + pumask = umask(0); + umask(pumask); + + if (fchmodat(rootfd, dir, mode & ~pumask, + AT_SYMLINK_NOFOLLOW) == -1) + warn("chmod(%s)", dir); } - fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW); - if (flags > 0) - chflagsat(rootfd, dir, flags, AT_SYMLINK_NOFOLLOW); + + if (fchownat(rootfd, dir, uid, gid, AT_SYMLINK_NOFOLLOW) == -1) + warn("chown(%s)", dir); + + if (flags > 0 && chflagsat(rootfd, dir, flags, + AT_SYMLINK_NOFOLLOW) == -1) + warn("chflags(%s)", dir); if (skelfd == -1) return; diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c index e98dd295183f..392e32b3ee7a 100644 --- a/usr.sbin/pw/grupd.c +++ b/usr.sbin/pw/grupd.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <err.h> #include <grp.h> #include <libutil.h> diff --git a/usr.sbin/pw/psdate.c b/usr.sbin/pw/psdate.c index 8c833b5c69c7..7d37e6b4aa1b 100644 --- a/usr.sbin/pw/psdate.c +++ b/usr.sbin/pw/psdate.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <ctype.h> #include <err.h> #include <stdlib.h> @@ -128,8 +123,8 @@ parse_datesub(char const * str, struct tm *t) l = newlocale(LC_ALL_MASK, "C", NULL); - memset(&tm, 0, sizeof(tm)); for (i=0; valid_formats[i] != NULL; i++) { + memset(&tm, 0, sizeof(tm)); ret = strptime_l(str, valid_formats[i], &tm, l); if (ret && *ret == '\0') { t->tm_mday = tm.tm_mday; diff --git a/usr.sbin/pw/psdate.h b/usr.sbin/pw/psdate.h index 29bfb3397f37..00744baafb43 100644 --- a/usr.sbin/pw/psdate.h +++ b/usr.sbin/pw/psdate.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _PSDATE_H_ diff --git a/usr.sbin/pw/pw.8 b/usr.sbin/pw/pw.8 index d9072872bc2b..c72623ee05b3 100644 --- a/usr.sbin/pw/pw.8 +++ b/usr.sbin/pw/pw.8 @@ -22,9 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD$ -.\" -.Dd April 3, 2022 +.Dd July 29, 2024 .Dt PW 8 .Os .Sh NAME @@ -541,6 +539,11 @@ This is like .Fl h , but the password should be supplied already encrypted in a form suitable for writing directly to the password database. +See +.Xr openssl-passwd 1 +and +.Xr crypt 3 +for more details about generating an encrypted password hash. .El .Pp It is possible to use @@ -738,6 +741,9 @@ Secondly, it will only remove files and directories that are actually owned by the user, or symbolic links owned by anyone under the user's home directory. Finally, after deleting all contents owned by the user only empty directories will be removed. +If the home directory is a ZFS dataset and has been emptied, +the dataset will be destroyed. +ZFS datasets within the home directory and snapshots are not handled. If any additional cleanup work is required, this is left to the administrator. .El .Pp @@ -831,7 +837,8 @@ new group or replace an existing membership list .Pq in Cm groupmod . .Ar memberlist -is a comma separated list of valid and existing user names or uids. +is a comma, space, or tab-separated list of valid and existing user names or +uids. .It Fl m Ar newmembers Similar to .Fl M , @@ -988,6 +995,12 @@ in addition to the other groups jsmith is already a member of. .Bd -literal -offset indent pw groupmod wheel -m jsmith .Ed +.Pp +Generate random password and show it in both plain text and +encrypted form not modifying any database. +.Bd -literal -offset indent +pw usermod nobody -Nw random +.Ed .Sh EXIT STATUS The .Nm @@ -1068,7 +1081,8 @@ No base home directory configured. .Xr passwd 5 , .Xr pw.conf 5 , .Xr pwd_mkdb 8 , -.Xr vipw 8 +.Xr vipw 8 , +.Xr zfs 8 .Sh HISTORY The .Nm diff --git a/usr.sbin/pw/pw.c b/usr.sbin/pw/pw.c index 4f92034a5d20..fc17f6dba022 100644 --- a/usr.sbin/pw/pw.c +++ b/usr.sbin/pw/pw.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <err.h> #include <fcntl.h> #include <locale.h> @@ -106,13 +101,16 @@ static int (*cmdfunc[W_NUM][M_NUM])(int argc, char **argv, char *_name) = { struct pwconf conf; +static int mode = -1; +static int which = -1; + static int getindex(const char *words[], const char *word); static void cmdhelp(int mode, int which); int main(int argc, char *argv[]) { - int mode = -1, which = -1, tmp; + int tmp; struct stat st; char arg, *arg1; bool relocated, nis; @@ -380,5 +378,11 @@ cmdhelp(int mode, int which) fprintf(stderr, "%s", help[which][mode]); } - exit(EXIT_FAILURE); + exit(EX_USAGE); +} + +void +usage(void) +{ + cmdhelp(mode, which); } diff --git a/usr.sbin/pw/pw.conf.5 b/usr.sbin/pw/pw.conf.5 index 61c40e87c11a..2a4aab25c328 100644 --- a/usr.sbin/pw/pw.conf.5 +++ b/usr.sbin/pw/pw.conf.5 @@ -22,8 +22,6 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD$ -.\" .Dd March 30, 2007 .Dt PW.CONF 5 .Os diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h index 1e09722a907c..c3725693f91d 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -24,8 +24,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <sys/stat.h> @@ -38,14 +36,14 @@ enum _mode { - M_ADD, - M_DELETE, - M_UPDATE, - M_PRINT, + M_ADD, + M_DELETE, + M_MODIFY, + M_SHOW, M_NEXT, M_LOCK, M_UNLOCK, - M_NUM + M_NUM }; enum _passmode @@ -58,13 +56,13 @@ enum _passmode enum _which { - W_USER, - W_GROUP, - W_NUM + W_USER, + W_GROUP, + W_NUM }; -#define _DEF_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO) -#define _PW_CONF "pw.conf" +#define _DEF_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO) +#define _PW_CONF "pw.conf" #define _UC_MAXLINE 1024 #define _UC_MAXSHELLS 32 @@ -114,3 +112,7 @@ extern const char *Which[]; uintmax_t strtounum(const char * __restrict, uintmax_t, uintmax_t, const char ** __restrict); + +bool grp_has_member(struct group *grp, const char *name); + +void usage(void); diff --git a/usr.sbin/pw/pw_conf.c b/usr.sbin/pw/pw_conf.c index b9b80f85cd48..e9042b15b321 100644 --- a/usr.sbin/pw/pw_conf.c +++ b/usr.sbin/pw/pw_conf.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <err.h> #include <fcntl.h> #include <string.h> diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c index a294d4ecbb5c..1941c03aa2c5 100644 --- a/usr.sbin/pw/pw_group.c +++ b/usr.sbin/pw/pw_group.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <ctype.h> #include <err.h> #include <grp.h> @@ -55,7 +50,8 @@ grp_set_passwd(struct group *grp, bool update, int fd, bool precrypted) int b; int istty; struct termios t, n; - char *p, line[256]; + static char line[256]; + char *p; if (fd == -1) return; @@ -276,8 +272,14 @@ pw_group_next(int argc, char **argv, char *arg1 __unused) case 'q': quiet = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -333,8 +335,14 @@ pw_group_show(int argc, char **argv, char *arg1) case 'a': all = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -390,8 +398,14 @@ pw_group_del(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -411,7 +425,7 @@ pw_group_del(int argc, char **argv, char *arg1) return (EXIT_SUCCESS); } -static bool +bool grp_has_member(struct group *grp, const char *name) { int j; @@ -548,8 +562,14 @@ pw_group_add(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -640,8 +660,15 @@ pw_group_mod(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); + if (quiet) freopen(_PATH_DEVNULL, "w", stderr); cnf = get_userconfig(cfg); @@ -691,11 +718,11 @@ pw_group_mod(int argc, char **argv, char *arg1) if ((grp = GETGRNAM(name)) == NULL) errx(EX_SOFTWARE, "group disappeared during update"); - pw_log(cnf, M_UPDATE, W_GROUP, "%s(%ju)", grp->gr_name, + pw_log(cnf, M_MODIFY, W_GROUP, "%s(%ju)", grp->gr_name, (uintmax_t)grp->gr_gid); if (nis && nis_update() == 0) - pw_log(cnf, M_UPDATE, W_GROUP, "NIS maps updated"); + pw_log(cnf, M_MODIFY, W_GROUP, "NIS maps updated"); return (EXIT_SUCCESS); } diff --git a/usr.sbin/pw/pw_log.c b/usr.sbin/pw/pw_log.c index 17e14d1e44ed..43dd4207ba29 100644 --- a/usr.sbin/pw/pw_log.c +++ b/usr.sbin/pw/pw_log.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <ctype.h> #include <err.h> #include <fcntl.h> diff --git a/usr.sbin/pw/pw_nis.c b/usr.sbin/pw/pw_nis.c index 4b70bc1de1f6..23e82239379f 100644 --- a/usr.sbin/pw/pw_nis.c +++ b/usr.sbin/pw/pw_nis.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/types.h> #include <err.h> diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index 2eec317b5e5b..d9fd8c77c13e 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -27,13 +27,8 @@ * */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/param.h> -#include <sys/types.h> +#include <sys/wait.h> #include <assert.h> #include <ctype.h> @@ -50,6 +45,7 @@ static const char rcsid[] = #include <sysexits.h> #include <termios.h> #include <unistd.h> +#include <spawn.h> #include "pw.h" #include "bitmap.h" @@ -57,6 +53,7 @@ static const char rcsid[] = #define LOGNAMESIZE (MAXLOGNAME-1) +extern char **environ; static char locked_str[] = "*LOCKED*"; static struct passwd fakeuser = { @@ -80,11 +77,9 @@ static uid_t pw_gidpolicy(struct userconf *cnf, char *grname, char *nam, static char *pw_homepolicy(struct userconf * cnf, char *homedir, const char *user); static char *pw_shellpolicy(struct userconf * cnf); -static char *pw_password(struct userconf * cnf, char const * user, - bool dryrun); +static char *pw_password(struct userconf * cnf, char const * user); static char *shell_path(char const * path, char *shells[], char *sh); static void rmat(uid_t uid); -static void rmopie(char const * name); static void mkdir_home_parents(int dfd, const char *dir) @@ -114,36 +109,20 @@ mkdir_home_parents(int dfd, const char *dir) } tmp[0] = '\0'; - /* - * This is a kludge especially for Joerg :) - * If the home directory would be created in the root partition, then - * we really create it under /usr which is likely to have more space. - * But we create a symlink from cnf->home -> "/usr" -> cnf->home - */ - if (strchr(dirs, '/') == NULL) { - asprintf(&tmp, "usr/%s", dirs); - if (tmp == NULL) - errx(EX_UNAVAILABLE, "out of memory"); - if (mkdirat(dfd, tmp, _DEF_DIRMODE) != -1 || errno == EEXIST) { - fchownat(dfd, tmp, 0, 0, 0); - symlinkat(tmp, dfd, dirs); - } - free(tmp); - } tmp = dirs; if (fstatat(dfd, dirs, &st, 0) == -1) { while ((tmp = strchr(tmp + 1, '/')) != NULL) { *tmp = '\0'; if (fstatat(dfd, dirs, &st, 0) == -1) { if (mkdirat(dfd, dirs, _DEF_DIRMODE) == -1) - err(EX_OSFILE, "'%s' (root home parent) is not a directory", dirs); + err(EX_OSFILE, "'%s' (home parent) is not a directory", dirs); } *tmp = '/'; } } if (fstatat(dfd, dirs, &st, 0) == -1) { if (mkdirat(dfd, dirs, _DEF_DIRMODE) == -1) - err(EX_OSFILE, "'%s' (root home parent) is not a directory", dirs); + err(EX_OSFILE, "'%s' (home parent) is not a directory", dirs); fchownat(dfd, dirs, 0, 0, 0); } @@ -167,7 +146,7 @@ create_and_populate_homedir(struct userconf *cnf, struct passwd *pwd, copymkdir(conf.rootfd, pwd->pw_dir, skelfd, homemode, pwd->pw_uid, pwd->pw_gid, 0); - pw_log(cnf, update ? M_UPDATE : M_ADD, W_USER, "%s(%ju) home %s made", + pw_log(cnf, update ? M_MODIFY : M_ADD, W_USER, "%s(%ju) home %s made", pwd->pw_name, (uintmax_t)pwd->pw_uid, pwd->pw_dir); } @@ -394,8 +373,7 @@ pw_gidpolicy(struct userconf *cnf, char *grname, char *nam, gid_t prefer, bool d grp = GETGRGID(gid); } gid = grp->gr_gid; - } else if ((grp = GETGRNAM(nam)) != NULL && - (grp->gr_mem == NULL || grp->gr_mem[0] == NULL)) { + } else if ((grp = GETGRNAM(nam)) != NULL) { gid = grp->gr_gid; /* Already created? Use it anyway... */ } else { intmax_t grid = -1; @@ -511,7 +489,7 @@ pw_pwcrypt(char *password) } static char * -pw_password(struct userconf * cnf, char const * user, bool dryrun) +pw_password(struct userconf * cnf, char const * user) { int i, l; char pwbuf[32]; @@ -528,7 +506,7 @@ pw_password(struct userconf * cnf, char const * user, bool dryrun) /* * We give this information back to the user */ - if (conf.fd == -1 && !dryrun) { + if (conf.fd == -1) { if (isatty(STDOUT_FILENO)) printf("Password for '%s' is: ", user); printf("%s\n", pwbuf); @@ -636,7 +614,7 @@ pw_checkname(char *name, int gecos) showtype = "gecos field"; } else { /* See if the name is valid as a userid or group. */ - badchars = " ,\t:+&#%$^()!@~*?<>=|\\/\""; + badchars = " ,\t:+&#%$^()!@~*?<>=|\\/\";"; showtype = "userid/group name"; /* Userids and groups can not have a leading '-'. */ if (*ch == '-') @@ -691,52 +669,29 @@ rmat(uid_t uid) while ((e = readdir(d)) != NULL) { struct stat st; + pid_t pid; if (strncmp(e->d_name, ".lock", 5) != 0 && stat(e->d_name, &st) == 0 && !S_ISDIR(st.st_mode) && st.st_uid == uid) { - char tmp[MAXPATHLEN]; - - snprintf(tmp, sizeof(tmp), "/usr/bin/atrm %s", - e->d_name); - system(tmp); + const char *argv[] = { + "/usr/sbin/atrm", + e->d_name, + NULL + }; + if (posix_spawn(&pid, argv[0], NULL, NULL, + (char *const *) argv, environ)) { + warn("Failed to execute '%s %s'", + argv[0], argv[1]); + } else + (void) waitpid(pid, NULL, 0); } } closedir(d); } } -static void -rmopie(char const * name) -{ - char tmp[1014]; - FILE *fp; - size_t len; - long atofs; - int fd; - - if ((fd = openat(conf.rootfd, "etc/opiekeys", O_RDWR)) == -1) - return; - - fp = fdopen(fd, "r+"); - len = strlen(name); - - for (atofs = 0; fgets(tmp, sizeof(tmp), fp) != NULL && atofs >= 0; - atofs = ftell(fp)) { - if (strncmp(name, tmp, len) == 0 && tmp[len]==' ') { - /* Comment username out */ - if (fseek(fp, atofs, SEEK_SET) == 0) - fwrite("#", 1, 1, fp); - break; - } - } - /* - * If we got an error of any sort, don't update! - */ - fclose(fp); -} - int pw_user_next(int argc, char **argv, char *name __unused) { @@ -754,8 +709,14 @@ pw_user_next(int argc, char **argv, char *name __unused) case 'q': quiet = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -816,8 +777,14 @@ pw_user_show(int argc, char **argv, char *arg1) case '7': v7 = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -897,8 +864,14 @@ pw_user_del(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (quiet) freopen(_PATH_DEVNULL, "w", stderr); @@ -937,17 +910,25 @@ pw_user_del(int argc, char **argv, char *arg1) if (strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "cannot remove user 'root'"); - /* Remove opie record from /etc/opiekeys */ - if (PWALTDIR() != PWF_ALT) - rmopie(pwd->pw_name); - if (!PWALTDIR()) { /* Remove crontabs */ snprintf(file, sizeof(file), "/var/cron/tabs/%s", pwd->pw_name); if (access(file, F_OK) == 0) { - snprintf(file, sizeof(file), "crontab -u %s -r", - pwd->pw_name); - system(file); + const char *argv[] = { + "crontab", + "-u", + pwd->pw_name, + "-r", + NULL + }; + pid_t pid; + + if (posix_spawnp(&pid, argv[0], NULL, NULL, + (char *const *) argv, environ)) { + warn("Failed to execute '%s %s'", + argv[0], argv[1]); + } else + (void) waitpid(pid, NULL, 0); } } @@ -1038,8 +1019,14 @@ pw_user_lock(int argc, char **argv, char *arg1) case 'q': /* compatibility */ break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); return (pw_userlock(arg1, M_LOCK)); } @@ -1055,8 +1042,14 @@ pw_user_unlock(int argc, char **argv, char *arg1) case 'q': /* compatibility */ break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); return (pw_userlock(arg1, M_UNLOCK)); } @@ -1322,8 +1315,14 @@ pw_user_add(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (geteuid() != 0 && ! dryrun) errx(EX_NOPERM, "you must be root"); @@ -1398,7 +1397,7 @@ pw_user_add(int argc, char **argv, char *arg1) if (lc == NULL || login_setcryptfmt(lc, "sha512", NULL) == NULL) warn("setting crypt(3) format"); login_close(lc); - pwd->pw_passwd = pw_password(cmdcnf, pwd->pw_name, dryrun); + pwd->pw_passwd = pw_password(cmdcnf, pwd->pw_name); 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); @@ -1432,6 +1431,9 @@ pw_user_add(int argc, char **argv, char *arg1) if (cmdcnf->groups != NULL) { for (i = 0; i < cmdcnf->groups->sl_cur; i++) { grp = GETGRNAM(cmdcnf->groups->sl_str[i]); + /* gr_add doesn't check if new member is already in group */ + if (grp_has_member(grp, pwd->pw_name)) + continue; grp = gr_add(grp, pwd->pw_name); /* * grp can only be NULL in 2 cases: @@ -1630,8 +1632,14 @@ pw_user_mod(int argc, char **argv, char *arg1) case 'Y': nis = true; break; + default: + usage(); } } + argc -= optind; + argv += optind; + if (argc > 0) + usage(); if (geteuid() != 0 && ! dryrun) errx(EX_NOPERM, "you must be root"); @@ -1745,7 +1753,7 @@ pw_user_mod(int argc, char **argv, char *arg1) login_close(lc); cnf->default_password = passwd_val(passwd, cnf->default_password); - pwd->pw_passwd = pw_password(cnf, pwd->pw_name, dryrun); + pwd->pw_passwd = pw_password(cnf, pwd->pw_name); edited = true; } @@ -1812,7 +1820,7 @@ pw_user_mod(int argc, char **argv, char *arg1) if (pwd == NULL) errx(EX_NOUSER, "user '%s' disappeared during update", name); grp = GETGRGID(pwd->pw_gid); - pw_log(cnf, M_UPDATE, W_USER, "%s(%ju):%s(%ju):%s:%s:%s", + pw_log(cnf, M_MODIFY, W_USER, "%s(%ju):%s(%ju):%s:%s:%s", pwd->pw_name, (uintmax_t)pwd->pw_uid, grp ? grp->gr_name : "unknown", (uintmax_t)(grp ? grp->gr_gid : (uid_t)-1), @@ -1833,7 +1841,7 @@ pw_user_mod(int argc, char **argv, char *arg1) } if (nis && nis_update() == 0) - pw_log(cnf, M_UPDATE, W_USER, "NIS maps updated"); + pw_log(cnf, M_MODIFY, W_USER, "NIS maps updated"); return (EXIT_SUCCESS); } diff --git a/usr.sbin/pw/pw_utils.c b/usr.sbin/pw/pw_utils.c index fbf4a3f5f560..9be1656bcfe1 100644 --- a/usr.sbin/pw/pw_utils.c +++ b/usr.sbin/pw/pw_utils.c @@ -25,8 +25,6 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/wait.h> #include <err.h> diff --git a/usr.sbin/pw/pw_vpw.c b/usr.sbin/pw/pw_vpw.c index 192d588ab0cf..4814ec2076d6 100644 --- a/usr.sbin/pw/pw_vpw.c +++ b/usr.sbin/pw/pw_vpw.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -27,11 +27,6 @@ * */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <pwd.h> #include <grp.h> #include <libutil.h> diff --git a/usr.sbin/pw/pwupd.c b/usr.sbin/pw/pwupd.c index ac91c9e4c1bb..89c1553c8c92 100644 --- a/usr.sbin/pw/pwupd.c +++ b/usr.sbin/pw/pwupd.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,11 +26,6 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - #include <sys/wait.h> #include <err.h> diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index b6f268baae5c..262b044e07fc 100644 --- a/usr.sbin/pw/pwupd.h +++ b/usr.sbin/pw/pwupd.h @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -24,14 +24,11 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _PWUPD_H_ #define _PWUPD_H_ -#include <sys/cdefs.h> #include <sys/param.h> #include <sys/types.h> @@ -142,7 +139,7 @@ void vendgrent(void); void copymkdir(int rootfd, char const * dir, int skelfd, mode_t mode, uid_t uid, gid_t gid, int flags); -void rm_r(int rootfd, char const * dir, uid_t uid); +bool rm_r(int rootfd, char const * dir, uid_t uid); __END_DECLS #endif /* !_PWUPD_H */ diff --git a/usr.sbin/pw/rm_r.c b/usr.sbin/pw/rm_r.c index 66ec3f21423f..f25da8ce6ad3 100644 --- a/usr.sbin/pw/rm_r.c +++ b/usr.sbin/pw/rm_r.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (C) 1996 * David L. Nugent. All rights reserved. @@ -26,40 +26,58 @@ * SUCH DAMAGE. */ -#ifndef lint -static const char rcsid[] = - "$FreeBSD$"; -#endif /* not lint */ - +#include <sys/param.h> +#include <sys/mount.h> #include <sys/stat.h> +#include <sys/wait.h> #include <dirent.h> +#include <err.h> +#include <errno.h> #include <fcntl.h> +#include <libgen.h> +#include <libutil.h> +#include <spawn.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> #include "pwupd.h" -void +static bool try_dataset_remove(const char *home); +extern char **environ; + +/* + * "rm -r" a directory tree. If the top-level directory cannot be removed + * due to EBUSY, indicating that it is a ZFS dataset, and we have emptied + * it, destroy the dataset. Return true if any files or directories + * remain. + */ +bool rm_r(int rootfd, const char *path, uid_t uid) { int dirfd; DIR *d; struct dirent *e; struct stat st; + const char *fullpath; + bool skipped = false; + fullpath = path; if (*path == '/') path++; dirfd = openat(rootfd, path, O_DIRECTORY); if (dirfd == -1) { - return; + return (true); } d = fdopendir(dirfd); if (d == NULL) { (void)close(dirfd); - return; + return (true); } while ((e = readdir(d)) != NULL) { if (strcmp(e->d_name, ".") == 0 || strcmp(e->d_name, "..") == 0) @@ -67,16 +85,84 @@ rm_r(int rootfd, const char *path, uid_t uid) if (fstatat(dirfd, e->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) continue; - if (S_ISDIR(st.st_mode)) - rm_r(dirfd, e->d_name, uid); - else if (S_ISLNK(st.st_mode) || st.st_uid == uid) + if (S_ISDIR(st.st_mode)) { + if (rm_r(dirfd, e->d_name, uid) == true) + skipped = true; + } else if (S_ISLNK(st.st_mode) || st.st_uid == uid) unlinkat(dirfd, e->d_name, 0); + else + skipped = true; } closedir(d); if (fstatat(rootfd, path, &st, AT_SYMLINK_NOFOLLOW) != 0) - return; - if (S_ISLNK(st.st_mode)) - unlinkat(rootfd, path, 0); - else if (st.st_uid == uid) - unlinkat(rootfd, path, AT_REMOVEDIR); + return (skipped); + if (S_ISLNK(st.st_mode)) { + if (unlinkat(rootfd, path, 0) == -1) + skipped = true; + } else if (st.st_uid == uid) { + if (unlinkat(rootfd, path, AT_REMOVEDIR) == -1) { + if (errno == EBUSY && skipped == false) + skipped = try_dataset_remove(fullpath); + else + skipped = true; + } + } else + skipped = true; + + return (skipped); +} + +/* + * If the home directory is a ZFS dataset, attempt to destroy it. + * Return true if the dataset is not destroyed. + * This would be more straightforward as a shell script. + */ +static bool +try_dataset_remove(const char *path) +{ + bool skipped = true; + struct statfs stat; + const char *argv[] = { + "/sbin/zfs", + "destroy", + NULL, + NULL + }; + int status; + pid_t pid; + + /* see if this is an absolute path (top-level directory) */ + if (*path != '/') + return (skipped); + /* see if ZFS is loaded */ + if (kld_isloaded("zfs") == 0) + return (skipped); + /* This won't work if root dir is not / (-R option) */ + if (strcmp(conf.rootdir, "/") != 0) { + warnx("cannot destroy home dataset when -R was used"); + return (skipped); + } + /* if so, find dataset name */ + if (statfs(path, &stat) != 0) { + warn("statfs %s", path); + return (skipped); + } + /* + * Check that the path refers to the dataset itself, + * not a subdirectory. + */ + if (strcmp(stat.f_mntonname, path) != 0) + return (skipped); + argv[2] = stat.f_mntfromname; + if ((skipped = posix_spawn(&pid, argv[0], NULL, NULL, + (char *const *) argv, environ)) != 0) { + warn("Failed to execute '%s %s %s'", + argv[0], argv[1], argv[2]); + } else { + if (waitpid(pid, &status, 0) != -1 && status != 0) { + warnx("'%s %s %s' exit status %d\n", + argv[0], argv[1], argv[2], status); + } + } + return (skipped); } diff --git a/usr.sbin/pw/strtounum.c b/usr.sbin/pw/strtounum.c index ae578bdeaeba..b138e7f130b7 100644 --- a/usr.sbin/pw/strtounum.c +++ b/usr.sbin/pw/strtounum.c @@ -25,8 +25,6 @@ */ #include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <errno.h> #include <inttypes.h> #include <limits.h> diff --git a/usr.sbin/pw/tests/Makefile b/usr.sbin/pw/tests/Makefile index ecdb0fe1665d..910a563d680d 100644 --- a/usr.sbin/pw/tests/Makefile +++ b/usr.sbin/pw/tests/Makefile @@ -1,5 +1,3 @@ -# $FreeBSD$ - PACKAGE= tests BINDIR= ${TESTSDIR} diff --git a/usr.sbin/pw/tests/Makefile.depend b/usr.sbin/pw/tests/Makefile.depend index 9124664318e7..aed10d8908bf 100644 --- a/usr.sbin/pw/tests/Makefile.depend +++ b/usr.sbin/pw/tests/Makefile.depend @@ -1,9 +1,6 @@ -# $FreeBSD$ # Autogenerated - do NOT edit! DIRDEPS = \ - gnu/lib/csu \ - include \ lib/${CSU_DIR} \ lib/libc \ lib/libcompiler_rt \ diff --git a/usr.sbin/pw/tests/crypt.c b/usr.sbin/pw/tests/crypt.c index 586fccdfec78..2a2023e47393 100644 --- a/usr.sbin/pw/tests/crypt.c +++ b/usr.sbin/pw/tests/crypt.c @@ -22,8 +22,6 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ #include <err.h> diff --git a/usr.sbin/pw/tests/group b/usr.sbin/pw/tests/group index 620c588faa38..2812f56cfa98 100644 --- a/usr.sbin/pw/tests/group +++ b/usr.sbin/pw/tests/group @@ -1,3 +1,2 @@ -# $FreeBSD$ # wheel:*:0:root diff --git a/usr.sbin/pw/tests/helper_functions.shin b/usr.sbin/pw/tests/helper_functions.shin index 1ee731a786ef..c03ca98d8709 100755 --- a/usr.sbin/pw/tests/helper_functions.shin +++ b/usr.sbin/pw/tests/helper_functions.shin @@ -1,4 +1,3 @@ -# $FreeBSD$ # The pw command PW="pw -V ${HOME}" diff --git a/usr.sbin/pw/tests/master.passwd b/usr.sbin/pw/tests/master.passwd index f7dc837dabca..46728369eb17 100644 --- a/usr.sbin/pw/tests/master.passwd +++ b/usr.sbin/pw/tests/master.passwd @@ -1,4 +1,3 @@ -# $FreeBSD$ # root:*:0:0::0:0:Charlie &:/root:/bin/csh toor:*:0:0::0:0:Bourne-again Superuser:/root: diff --git a/usr.sbin/pw/tests/pw_config_test.sh b/usr.sbin/pw/tests/pw_config_test.sh index fb6489a0b31c..e9209190dc5e 100755 --- a/usr.sbin/pw/tests/pw_config_test.sh +++ b/usr.sbin/pw/tests/pw_config_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_etcdir_test.sh b/usr.sbin/pw/tests/pw_etcdir_test.sh index b237789ed457..db6f0f30eaf3 100755 --- a/usr.sbin/pw/tests/pw_etcdir_test.sh +++ b/usr.sbin/pw/tests/pw_etcdir_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # When the '-V directory' option is provided, the directory must exist atf_test_case etcdir_must_exist diff --git a/usr.sbin/pw/tests/pw_groupadd_test.sh b/usr.sbin/pw/tests/pw_groupadd_test.sh index 5fa7bef0fdf1..cf3c401a361c 100755 --- a/usr.sbin/pw/tests/pw_groupadd_test.sh +++ b/usr.sbin/pw/tests/pw_groupadd_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_groupdel_test.sh b/usr.sbin/pw/tests/pw_groupdel_test.sh index 88cc0e08b8bf..fa51b3814205 100755 --- a/usr.sbin/pw/tests/pw_groupdel_test.sh +++ b/usr.sbin/pw/tests/pw_groupdel_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_groupmod_test.sh b/usr.sbin/pw/tests/pw_groupmod_test.sh index 580692553847..ce7106d885d2 100755 --- a/usr.sbin/pw/tests/pw_groupmod_test.sh +++ b/usr.sbin/pw/tests/pw_groupmod_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_groupshow_test.sh b/usr.sbin/pw/tests/pw_groupshow_test.sh index f348d0ab1f70..06631e912c0f 100755 --- a/usr.sbin/pw/tests/pw_groupshow_test.sh +++ b/usr.sbin/pw/tests/pw_groupshow_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_lock_test.sh b/usr.sbin/pw/tests/pw_lock_test.sh index 5ec1b09a6956..f8fe03a4d147 100755 --- a/usr.sbin/pw/tests/pw_lock_test.sh +++ b/usr.sbin/pw/tests/pw_lock_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_useradd_test.sh b/usr.sbin/pw/tests/pw_useradd_test.sh index a50f018ab99d..6413c063d482 100755 --- a/usr.sbin/pw/tests/pw_useradd_test.sh +++ b/usr.sbin/pw/tests/pw_useradd_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin @@ -295,15 +294,54 @@ user_add_R_body() { [ ! -d ${HOME}/home/bar ] || atf_fail "Directory not removed" } -atf_test_case user_add_R_symlink -user_add_R_symlink_body() { +atf_test_case user_add_R_no_symlink +user_add_R_no_symlink_body() { populate_root_etc_skel mkdir ${HOME}/usr atf_check -s exit:0 ${RPW} useradd foo -m - test -d ${HOME}/usr/home || atf_fail "Home parent directory not created" - test -h ${HOME}/home || atf_fail "/home directory is not a symlink" - atf_check -s exit:0 -o inline:"usr/home\n" readlink ${HOME}/home + [ ! -d ${HOME}/usr/home ] || atf_fail "/usr/home created" + test -d ${HOME}/home || atf_fail "/home directory not created" +} + +atf_test_case user_add_R_intermed +user_add_R_intermed_body() { + populate_root_etc_skel + + atf_check -s exit:0 ${RPW} useradd foo -m -d /a/b/c/foo + test -d ${HOME}/a/b/c || atf_fail "intermediate directories not created" + test -d ${HOME}/a/b/c/foo || atf_fail "user directory not created" +} + +atf_test_case user_add_dir +user_add_dir_body() { + populate_root_etc_skel + + atf_check -s exit:0 ${RPW} useradd foo -M 0705 -m + atf_check grep -q '^foo:' $HOME/etc/master.passwd + atf_check test -d ${HOME}/home/foo + atf_check -o save:ugid \ + awk -F: '$1 == "foo" { print $3, $4 }' \ + $HOME/etc/master.passwd + atf_check -o file:ugid \ + stat -f '%u %g' ${HOME}/home/foo + atf_check -o inline:"40705\n" \ + stat -f '%p' ${HOME}/home/foo +} + +atf_test_case user_add_existing_dir +user_add_existing_dir_body() { + populate_root_etc_skel + + mkdir -p -m 0777 ${HOME}/home/foo + atf_check -o inline:"40777\n" \ + stat -f '%p' ${HOME}/home/foo + + atf_check -s exit:0 ${RPW} useradd foo -M 0705 -m + atf_check grep -q '^foo:' $HOME/etc/master.passwd + atf_check test -d ${HOME}/home/foo + atf_check -o inline:"40705\n" \ + stat -f '%p' ${HOME}/home/foo } atf_test_case user_add_skel @@ -455,6 +493,29 @@ user_add_conf_defaultpasswd_body() grep defaultpasswd ${HOME}/pw.conf } +atf_test_case user_add_existing_login_group +user_add_existing_login_group_body() +{ + populate_etc_skel + + atf_check -s exit:0 ${PW} groupadd testuser + atf_check -s exit:0 ${PW} useradd user1 -G testuser + atf_check -s exit:0 ${PW} useradd testuser + atf_check -o match:"1" \ + sh -c "grep testuser ${HOME}/group | wc -l" +} + +atf_test_case user_add_already_in_group +user_add_already_in_group_body() +{ + populate_etc_skel + + echo "testgroup:*:4242:testuser" >> ${HOME}/group + atf_check -s exit:0 ${PW} useradd testuser -G testgroup + atf_check -o not-match:"testuser,testuser" \ + grep testuser ${HOME}/group +} + atf_init_test_cases() { atf_add_test_case user_add atf_add_test_case user_add_noupdate @@ -479,7 +540,10 @@ atf_init_test_cases() { atf_add_test_case user_add_invalid_group_entry atf_add_test_case user_add_password_from_h atf_add_test_case user_add_R - atf_add_test_case user_add_R_symlink + atf_add_test_case user_add_R_no_symlink + atf_add_test_case user_add_R_intermed + atf_add_test_case user_add_dir + atf_add_test_case user_add_existing_dir atf_add_test_case user_add_skel atf_add_test_case user_add_uid0 atf_add_test_case user_add_uid_too_large @@ -494,4 +558,6 @@ atf_init_test_cases() { atf_add_test_case user_add_defaultgroup atf_add_test_case user_add_conf_defaultpasswd + atf_add_test_case user_add_existing_login_group + atf_add_test_case user_add_already_in_group } diff --git a/usr.sbin/pw/tests/pw_userdel_test.sh b/usr.sbin/pw/tests/pw_userdel_test.sh index 694d7bbae6cc..2e11c3534d58 100755 --- a/usr.sbin/pw/tests/pw_userdel_test.sh +++ b/usr.sbin/pw/tests/pw_userdel_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin @@ -39,12 +38,10 @@ delete_files_body() { touch ${HOME}/skel/a mkdir -p ${HOME}/home mkdir -p ${HOME}/var/mail - echo "foo wedontcare" > ${HOME}/etc/opiekeys atf_check -s exit:0 ${RPW} useradd foo -k /skel -m test -d ${HOME}/home || atf_fail "Fail to create home directory" test -f ${HOME}/var/mail/foo || atf_fail "Mail file not created" atf_check -s exit:0 ${RPW} userdel foo -r - atf_check -s exit:0 -o inline:"#oo wedontcare\n" cat ${HOME}/etc/opiekeys if test -f ${HOME}/var/mail/foo; then atf_fail "Mail file not removed" fi diff --git a/usr.sbin/pw/tests/pw_usermod_test.sh b/usr.sbin/pw/tests/pw_usermod_test.sh index cf3622f3b222..f8cb66a45b70 100755 --- a/usr.sbin/pw/tests/pw_usermod_test.sh +++ b/usr.sbin/pw/tests/pw_usermod_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_usernext_test.sh b/usr.sbin/pw/tests/pw_usernext_test.sh index 89f938ec8c33..63a688f573d8 100755 --- a/usr.sbin/pw/tests/pw_usernext_test.sh +++ b/usr.sbin/pw/tests/pw_usernext_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin diff --git a/usr.sbin/pw/tests/pw_usershow_test.sh b/usr.sbin/pw/tests/pw_usershow_test.sh index 530597948e4a..06f7f610936a 100755 --- a/usr.sbin/pw/tests/pw_usershow_test.sh +++ b/usr.sbin/pw/tests/pw_usershow_test.sh @@ -1,4 +1,3 @@ -# $FreeBSD$ # Import helper functions . $(atf_get_srcdir)/helper_functions.shin |