From b76f48320c5b5f6d44afab6e67b2da6c8f77c08b Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Fri, 29 May 2015 10:07:20 +0000 Subject: Remove dead declaration PR: 195928 MFC after: 2 days --- pw/pwupd.h | 1 - 1 file changed, 1 deletion(-) (limited to 'pw') diff --git a/pw/pwupd.h b/pw/pwupd.h index d6e39ce..1d13511 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -93,7 +93,6 @@ char * getpwpath(char const * file); int addgrent(struct group * grp); int delgrent(struct group * grp); int chggrent(char const * name, struct group * grp); -int editgroups(char *name, char **groups); int setgrdir(const char * dir); char * getgrpath(const char *file); -- cgit v1.2.3 From 3af58faa587f263481899bbe5a258c74be6038c0 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 10:02:01 +0000 Subject: Use asprintf instead of malloc + snprintf and test the memory allocation --- pw/pw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index ff48db7..0c41f03 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -221,8 +221,9 @@ main(int argc, char *argv[]) char * etcpath = getarg(&arglist, 'V')->val; if (*etcpath) { if (config == NULL) { /* Only override config location if -C not specified */ - config = malloc(MAXPATHLEN); - snprintf(config, MAXPATHLEN, "%s/pw.conf", etcpath); + asprintf(&config, "%s/pw.conf", etcpath); + if (config == NULL) + errx(EX_OSERR, "out of memory"); } memcpy(&PWF, &VPWF, sizeof PWF); setpwdir(etcpath); -- cgit v1.2.3 From 229f1c5662a4b35f0e78f947120ebd810d45ce20 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 10:14:13 +0000 Subject: Remove uneeded intermediate variable --- pw/grupd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'pw') diff --git a/pw/grupd.c b/pw/grupd.c index 74cc390..8735831 100644 --- a/pw/grupd.c +++ b/pw/grupd.c @@ -116,9 +116,6 @@ chggrent(char const * login, struct group * grp) int delgrent(struct group * grp) { - char group[MAXLOGNAME]; - strlcpy(group, grp->gr_name, MAXLOGNAME); - - return gr_update(NULL, group); + return (gr_update(NULL, grp->gr_name)); } -- cgit v1.2.3 From 08520f443624966a4c8aa144284e58effedea404 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 10:18:10 +0000 Subject: Remove uneeded intermediate variable --- pw/pwupd.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'pw') diff --git a/pw/pwupd.c b/pw/pwupd.c index 710e901..89d0856 100644 --- a/pw/pwupd.c +++ b/pw/pwupd.c @@ -162,9 +162,6 @@ chgpwent(char const * login, struct passwd * pwd) int delpwent(struct passwd * pwd) { - char login[MAXLOGNAME]; - - strlcpy(login, pwd->pw_name, MAXLOGNAME); - return (pw_update(NULL, login)); + return (pw_update(NULL, pwd->pw_name)); } -- cgit v1.2.3 From e2434c7f83a53c8fb2288cf5c58a73ac2f3e0130 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 11:23:19 +0000 Subject: Make pw_user()/pw_group() more consitent about errors Some of errors were returned to the main function, some others caused a direct exit via err(3). The main function is only interested in EXIT_SUCCESS, so in all other cases replace warn(3) + return err by err(3) --- pw/pw_group.c | 21 +++++++++------------ pw/pw_user.c | 40 +++++++++++++++------------------------- 2 files changed, 24 insertions(+), 37 deletions(-) (limited to 'pw') diff --git a/pw/pw_group.c b/pw/pw_group.c index b20ce88..78adbf1 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -135,8 +135,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) if (rc == -1) err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name); else if (rc != 0) { - warn("group update"); - return EX_IOERR; + err(EX_IOERR, "group update"); } pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid); return EXIT_SUCCESS; @@ -201,10 +200,8 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) fputc('\n', stdout); fflush(stdout); } - if (b < 0) { - warn("-h file descriptor"); - return EX_OSERR; - } + if (b < 0) + err(EX_OSERR, "-h file descriptor"); line[b] = '\0'; if ((p = strpbrk(line, " \t\r\n")) != NULL) *p = '\0'; @@ -265,16 +262,16 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) if (mode == M_ADD && (rc = addgrent(grp)) != 0) { if (rc == -1) - warnx("group '%s' already exists", grp->gr_name); + errx(EX_IOERR, "group '%s' already exists", + grp->gr_name); else - warn("group update"); - return EX_IOERR; + err(EX_IOERR, "group update"); } else if (mode == M_UPDATE && (rc = chggrent(a_name->val, grp)) != 0) { if (rc == -1) - warnx("group '%s' not available (NIS?)", grp->gr_name); + errx(EX_IOERR, "group '%s' not available (NIS?)", + grp->gr_name); else - warn("group update"); - return EX_IOERR; + err(EX_IOERR, "group update"); } arg = a_newname != NULL ? a_newname : a_name; diff --git a/pw/pw_user.c b/pw/pw_user.c index b058aab..95a4519 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -286,8 +286,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) arg = getarg(args, 'C'); if (write_userconfig(arg ? arg->val : NULL)) return EXIT_SUCCESS; - warn("config update"); - return EX_IOERR; + err(EX_IOERR, "config udpate"); } if (mode == M_PRINT && getarg(args, 'a')) { @@ -416,10 +415,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) 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; - } + else if (rc != 0) + err(EX_IOERR, "passwd update"); if (cnf->nispasswd && *cnf->nispasswd=='/') { rc = delnispwent(cnf->nispasswd, a_name->val); @@ -672,11 +669,9 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) fputc('\n', stdout); fflush(stdout); } - if (b < 0) { - warn("-%c file descriptor", precrypt ? 'H' : - 'h'); - return EX_IOERR; - } + if (b < 0) + err(EX_IOERR, "-%c file descriptor", + precrypt ? 'H' : 'h'); line[b] = '\0'; if ((p = strpbrk(line, "\r\n")) != NULL) *p = '\0'; @@ -709,13 +704,11 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (mode == M_ADD) { 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 (rc == -1) + errx(EX_IOERR, "user '%s' already exists", + pwd->pw_name); + else if (rc != 0) + err(EX_IOERR, "passwd file update"); if (cnf->nispasswd && *cnf->nispasswd=='/') { rc = addnispwent(cnf->nispasswd, pwd); if (rc == -1) @@ -727,13 +720,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) } 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 (rc == -1) + errx(EX_IOERR, "user '%s' does not exist (NIS?)", pwd->pw_name); + else if (rc != 0) + err(EX_IOERR, "passwd file update"); if ( cnf->nispasswd && *cnf->nispasswd=='/') { rc = chgnispwent(cnf->nispasswd, a_name->val, pwd); if (rc == -1) -- cgit v1.2.3 From 381b3dc707154395616b47ac6acd3e20ea174541 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 11:55:28 +0000 Subject: Return early in case we cannot read the configuration file This drops one level of indentation --- pw/pw_conf.c | 221 ++++++++++++++++++++++++++++++----------------------------- 1 file changed, 111 insertions(+), 110 deletions(-) (limited to 'pw') diff --git a/pw/pw_conf.c b/pw/pw_conf.c index 99d3e8f..f67d04b 100644 --- a/pw/pw_conf.c +++ b/pw/pw_conf.c @@ -241,126 +241,127 @@ read_userconfig(char const * file) if (file == NULL) file = _PATH_PW_CONF; - if ((fp = fopen(file, "r")) != NULL) { - while ((linelen = getline(&buf, &linecap, fp)) > 0) { - if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { - static char const toks[] = " \t\r\n,="; - char *q = strtok(NULL, toks); - int i = 0; - mode_t *modeset; - - while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) - ++i; + if ((fp = fopen(file, "r")) == NULL) + return (&config); + + while ((linelen = getline(&buf, &linecap, fp)) > 0) { + if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { + static char const toks[] = " \t\r\n,="; + char *q = strtok(NULL, toks); + int i = 0; + mode_t *modeset; + + while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) + ++i; #if debugging - if (i == _UC_FIELDS) - printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); - else - printf("Got kwd[%s]=%s\n", p, q); + if (i == _UC_FIELDS) + printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : ""); + else + printf("Got kwd[%s]=%s\n", p, q); #endif - switch (i) { - case _UC_DEFAULTPWD: - config.default_password = boolean_val(q, 1); - break; - case _UC_REUSEUID: - config.reuse_uids = boolean_val(q, 0); - break; - case _UC_REUSEGID: - config.reuse_gids = boolean_val(q, 0); - break; - case _UC_NISPASSWD: - config.nispasswd = (q == NULL || !boolean_val(q, 1)) - ? NULL : newstr(q); - break; - case _UC_DOTDIR: - config.dotdir = (q == NULL || !boolean_val(q, 1)) - ? NULL : newstr(q); - break; + switch (i) { + case _UC_DEFAULTPWD: + config.default_password = boolean_val(q, 1); + break; + case _UC_REUSEUID: + config.reuse_uids = boolean_val(q, 0); + break; + case _UC_REUSEGID: + config.reuse_gids = boolean_val(q, 0); + break; + case _UC_NISPASSWD: + config.nispasswd = (q == NULL || !boolean_val(q, 1)) + ? NULL : newstr(q); + break; + case _UC_DOTDIR: + config.dotdir = (q == NULL || !boolean_val(q, 1)) + ? NULL : newstr(q); + break; case _UC_NEWMAIL: - config.newmail = (q == NULL || !boolean_val(q, 1)) - ? NULL : newstr(q); - break; - case _UC_LOGFILE: - config.logfile = (q == NULL || !boolean_val(q, 1)) - ? NULL : newstr(q); - break; - case _UC_HOMEROOT: - config.home = (q == NULL || !boolean_val(q, 1)) - ? "/home" : newstr(q); - break; - case _UC_HOMEMODE: - modeset = setmode(q); - config.homemode = (q == NULL || !boolean_val(q, 1)) - ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE); - free(modeset); - break; - case _UC_SHELLPATH: - config.shelldir = (q == NULL || !boolean_val(q, 1)) - ? "/bin" : newstr(q); - break; - case _UC_SHELLS: - for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) - system_shells[i] = newstr(q); - if (i > 0) - while (i < _UC_MAXSHELLS) - system_shells[i++] = NULL; - break; - case _UC_DEFAULTSHELL: - config.shell_default = (q == NULL || !boolean_val(q, 1)) - ? (char *) bourne_shell : newstr(q); - break; - case _UC_DEFAULTGROUP: - q = unquote(q); - config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) - ? NULL : newstr(q); - break; - case _UC_EXTRAGROUPS: - for (i = 0; q != NULL; q = strtok(NULL, toks)) { - if (extendarray(&config.groups, &config.numgroups, i + 2) != -1) - config.groups[i++] = newstr(q); - } - if (i > 0) - while (i < config.numgroups) - config.groups[i++] = NULL; - break; - case _UC_DEFAULTCLASS: - config.default_class = (q == NULL || !boolean_val(q, 1)) - ? NULL : newstr(q); - break; - case _UC_MINUID: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.min_uid = (uid_t) atol(q); - break; - case _UC_MAXUID: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.max_uid = (uid_t) atol(q); - break; - case _UC_MINGID: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.min_gid = (gid_t) atol(q); - break; - case _UC_MAXGID: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.max_gid = (gid_t) atol(q); - break; - case _UC_EXPIRE: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.expire_days = atoi(q); - break; - case _UC_PASSWORD: - if ((q = unquote(q)) != NULL && isdigit(*q)) - config.password_days = atoi(q); - break; - case _UC_FIELDS: - case _UC_NONE: - break; + config.newmail = (q == NULL || !boolean_val(q, 1)) + ? NULL : newstr(q); + break; + case _UC_LOGFILE: + config.logfile = (q == NULL || !boolean_val(q, 1)) + ? NULL : newstr(q); + break; + case _UC_HOMEROOT: + config.home = (q == NULL || !boolean_val(q, 1)) + ? "/home" : newstr(q); + break; + case _UC_HOMEMODE: + modeset = setmode(q); + config.homemode = (q == NULL || !boolean_val(q, 1)) + ? _DEF_DIRMODE : getmode(modeset, _DEF_DIRMODE); + free(modeset); + break; + case _UC_SHELLPATH: + config.shelldir = (q == NULL || !boolean_val(q, 1)) + ? "/bin" : newstr(q); + break; + case _UC_SHELLS: + for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks)) + system_shells[i] = newstr(q); + if (i > 0) + while (i < _UC_MAXSHELLS) + system_shells[i++] = NULL; + break; + case _UC_DEFAULTSHELL: + config.shell_default = (q == NULL || !boolean_val(q, 1)) + ? (char *) bourne_shell : newstr(q); + break; + case _UC_DEFAULTGROUP: + q = unquote(q); + config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL) + ? NULL : newstr(q); + break; + case _UC_EXTRAGROUPS: + for (i = 0; q != NULL; q = strtok(NULL, toks)) { + if (extendarray(&config.groups, &config.numgroups, i + 2) != -1) + config.groups[i++] = newstr(q); } + if (i > 0) + while (i < config.numgroups) + config.groups[i++] = NULL; + break; + case _UC_DEFAULTCLASS: + config.default_class = (q == NULL || !boolean_val(q, 1)) + ? NULL : newstr(q); + break; + case _UC_MINUID: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.min_uid = (uid_t) atol(q); + break; + case _UC_MAXUID: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.max_uid = (uid_t) atol(q); + break; + case _UC_MINGID: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.min_gid = (gid_t) atol(q); + break; + case _UC_MAXGID: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.max_gid = (gid_t) atol(q); + break; + case _UC_EXPIRE: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.expire_days = atoi(q); + break; + case _UC_PASSWORD: + if ((q = unquote(q)) != NULL && isdigit(*q)) + config.password_days = atoi(q); + break; + case _UC_FIELDS: + case _UC_NONE: + break; } } if (linecap > 0) free(buf); fclose(fp); } - return &config; + return (&config); } -- cgit v1.2.3 From fcf1df7c5811847a0fff8bba94e21edfaeb98027 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 11:56:59 +0000 Subject: Remove useless test before free() --- pw/pw_conf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pw_conf.c b/pw/pw_conf.c index f67d04b..df0bda3 100644 --- a/pw/pw_conf.c +++ b/pw/pw_conf.c @@ -357,8 +357,7 @@ read_userconfig(char const * file) break; } } - if (linecap > 0) - free(buf); + free(buf); fclose(fp); } return (&config); -- cgit v1.2.3 From 861c9030d5b3c835e61181480716d6af26d463e4 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 12:04:06 +0000 Subject: Move cleanup functions to the right place --- pw/pw_conf.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pw_conf.c b/pw/pw_conf.c index df0bda3..06117e2 100644 --- a/pw/pw_conf.c +++ b/pw/pw_conf.c @@ -357,9 +357,10 @@ read_userconfig(char const * file) break; } } - free(buf); - fclose(fp); } + free(buf); + fclose(fp); + return (&config); } -- cgit v1.2.3 From 52819077bb4348529466a387988b6785585c3829 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 21:44:09 +0000 Subject: Cast -1 to uid_t and bump WARNING level to 3 --- pw/Makefile | 2 +- pw/pw_group.c | 2 +- pw/pw_user.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'pw') diff --git a/pw/Makefile b/pw/Makefile index 69953da..4bcf691 100644 --- a/pw/Makefile +++ b/pw/Makefile @@ -6,7 +6,7 @@ SRCS= pw.c pw_conf.c pw_user.c pw_group.c pw_log.c pw_nis.c pw_vpw.c \ grupd.c pwupd.c fileupd.c psdate.c \ bitmap.c cpdir.c rm_r.c -WARNS?= 2 +WARNS?= 3 LIBADD= crypt util sbuf diff --git a/pw/pw_group.c b/pw/pw_group.c index 78adbf1..53757f5 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -116,7 +116,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) char *fmems[1]; fmems[0] = NULL; fakegroup.gr_name = a_name ? a_name->val : "nogroup"; - fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : -1; + fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : (uid_t)-1; fakegroup.gr_mem = fmems; return print_group(&fakegroup, getarg(args, 'P') != NULL); } diff --git a/pw/pw_user.c b/pw/pw_user.c index 95a4519..112d018 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -335,7 +335,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (pwd == NULL) { if (mode == M_PRINT && getarg(args, 'F')) { fakeuser.pw_name = a_name ? a_name->val : "nouser"; - fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : -1; + fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : (uid_t) -1; return print_user(&fakeuser, getarg(args, 'P') != NULL, getarg(args, '7') != NULL); @@ -791,7 +791,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) grp = GETGRGID(pwd->pw_gid); pw_log(cnf, mode, W_USER, "%s(%ld):%s(%ld):%s:%s:%s", pwd->pw_name, (long) pwd->pw_uid, - grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : -1), + grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : (uid_t)-1), pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); /* -- cgit v1.2.3 From e0861fa9e8f60ad49848126462f99eded11a6c9d Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 22:07:03 +0000 Subject: Remove useless cast in printf and printf-like functions: use %u for uid_t and gid_t --- pw/pw_conf.c | 8 ++++---- pw/pw_group.c | 8 ++++---- pw/pw_user.c | 30 +++++++++++++++--------------- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'pw') diff --git a/pw/pw_conf.c b/pw/pw_conf.c index 06117e2..24c0650 100644 --- a/pw/pw_conf.c +++ b/pw/pw_conf.c @@ -453,19 +453,19 @@ write_userconfig(char const * file) config.default_class : ""); break; case _UC_MINUID: - sbuf_printf(buf, "%lu", (unsigned long) config.min_uid); + sbuf_printf(buf, "%u", config.min_uid); quote = 0; break; case _UC_MAXUID: - sbuf_printf(buf, "%lu", (unsigned long) config.max_uid); + sbuf_printf(buf, "%u", config.max_uid); quote = 0; break; case _UC_MINGID: - sbuf_printf(buf, "%lu", (unsigned long) config.min_gid); + sbuf_printf(buf, "%u", config.min_gid); quote = 0; break; case _UC_MAXGID: - sbuf_printf(buf, "%lu", (unsigned long) config.max_gid); + sbuf_printf(buf, "%u", config.max_gid); quote = 0; break; case _UC_EXPIRE: diff --git a/pw/pw_group.c b/pw/pw_group.c index 53757f5..37f2426 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -83,7 +83,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) gid_t next = gr_gidpolicy(cnf, args); if (getarg(args, 'q')) return next; - printf("%ld\n", (long)next); + printf("%u\n", next); return EXIT_SUCCESS; } @@ -137,7 +137,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) else if (rc != 0) { err(EX_IOERR, "group update"); } - pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", a_name->val, (long) gid); + pw_log(cnf, mode, W_GROUP, "%s(%u) removed", a_name->val, gid); return EXIT_SUCCESS; } else if (mode == M_PRINT) return print_group(grp, getarg(args, 'P') != NULL); @@ -279,7 +279,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) if ((grp = GETGRNAM(arg->val)) == NULL) errx(EX_SOFTWARE, "group disappeared during update"); - pw_log(cnf, mode, W_GROUP, "%s(%ld)", grp->gr_name, (long) grp->gr_gid); + pw_log(cnf, mode, W_GROUP, "%s(%u)", grp->gr_name, grp->gr_gid); free(members); @@ -361,7 +361,7 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args) gid = (gid_t) atol(a_gid->val); if ((grp = GETGRGID(gid)) != NULL && getarg(args, 'o') == NULL) - errx(EX_DATAERR, "gid `%ld' has already been allocated", (long) grp->gr_gid); + errx(EX_DATAERR, "gid `%u' has already been allocated", grp->gr_gid); } else { struct bitmap bm; diff --git a/pw/pw_user.c b/pw/pw_user.c index 112d018..48eb934 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -139,7 +139,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) uid_t next = pw_uidpolicy(cnf, args); if (getarg(args, 'q')) return next; - printf("%ld:", (long)next); + printf("%u:", next); pw_group(cnf, mode, args); return EXIT_SUCCESS; } @@ -449,7 +449,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) } ENDGRENT(); - pw_log(cnf, mode, W_USER, "%s(%ld) account removed", a_name->val, (long) uid); + pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); if (!PWALTDIR()) { /* @@ -469,8 +469,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (getarg(args, 'r') != NULL && *home == '/' && getpwuid(uid) == NULL) { if (stat(home, &st) != -1) { rm_r(home, uid); - pw_log(cnf, mode, W_USER, "%s(%ld) home '%s' %sremoved", - a_name->val, (long) uid, home, + pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", + a_name->val, uid, home, stat(home, &st) == -1 ? "" : "not completely "); } } @@ -789,9 +789,9 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) errx(EX_NOUSER, "user '%s' disappeared during update", a_name->val); grp = GETGRGID(pwd->pw_gid); - pw_log(cnf, mode, W_USER, "%s(%ld):%s(%ld):%s:%s:%s", - pwd->pw_name, (long) pwd->pw_uid, - grp ? grp->gr_name : "unknown", (long) (grp ? grp->gr_gid : (uid_t)-1), + pw_log(cnf, mode, W_USER, "%s(%u):%s(%u):%s:%s:%s", + pwd->pw_name, pwd->pw_uid, + grp ? grp->gr_name : "unknown", (grp ? grp->gr_gid : (uid_t)-1), pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); /* @@ -815,8 +815,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) */ if (!PWALTDIR() && getarg(args, 'm') != NULL && pwd->pw_dir && *pwd->pw_dir == '/' && pwd->pw_dir[1]) { copymkdir(pwd->pw_dir, cnf->dotdir, cnf->homemode, pwd->pw_uid, pwd->pw_gid); - pw_log(cnf, mode, W_USER, "%s(%ld) home %s made", - pwd->pw_name, (long) pwd->pw_uid, pwd->pw_dir); + pw_log(cnf, mode, W_USER, "%s(%u) home %s made", + pwd->pw_name, pwd->pw_uid, pwd->pw_dir); } @@ -835,8 +835,8 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) fputs(line, pfp); } pclose(pfp); - pw_log(cnf, mode, W_USER, "%s(%ld) new user mail sent", - pwd->pw_name, (long) pwd->pw_uid); + pw_log(cnf, mode, W_USER, "%s(%u) new user mail sent", + pwd->pw_name, pwd->pw_uid); } fclose(fp); } @@ -859,7 +859,7 @@ pw_uidpolicy(struct userconf * cnf, struct cargs * args) uid = (uid_t) atol(a_uid->val); if ((pwd = GETPWUID(uid)) != NULL && getarg(args, 'o') == NULL) - errx(EX_DATAERR, "uid `%ld' has already been allocated", (long) pwd->pw_uid); + errx(EX_DATAERR, "uid `%u' has already been allocated", pwd->pw_uid); } else { struct bitmap bm; @@ -1183,14 +1183,14 @@ print_user(struct passwd * pwd, int pretty, int v7) strftime(acexpire, sizeof acexpire, "%c", tptr); if (pwd->pw_change > (time_t)0 && (tptr = localtime(&pwd->pw_change)) != NULL) strftime(pwexpire, sizeof pwexpire, "%c", tptr); - printf("Login Name: %-15s #%-12ld Group: %-15s #%ld\n" + printf("Login Name: %-15s #%-12u Group: %-15s #%u\n" " Full Name: %s\n" " Home: %-26.26s Class: %s\n" " Shell: %-26.26s Office: %s\n" "Work Phone: %-26.26s Home Phone: %s\n" "Acc Expire: %-26.26s Pwd Expire: %s\n", - pwd->pw_name, (long) pwd->pw_uid, - grp ? grp->gr_name : "(invalid)", (long) pwd->pw_gid, + pwd->pw_name, pwd->pw_uid, + grp ? grp->gr_name : "(invalid)", pwd->pw_gid, uname, pwd->pw_dir, pwd->pw_class, pwd->pw_shell, office, wphone, hphone, acexpire, pwexpire); -- cgit v1.2.3 From 8f462098108bd06c25d0d54f3ff624a3f7103a82 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 31 May 2015 22:12:31 +0000 Subject: Cast to gid_t for groups not uid_t --- pw/pw_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pw') diff --git a/pw/pw_group.c b/pw/pw_group.c index 37f2426..c001160 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -116,7 +116,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) char *fmems[1]; fmems[0] = NULL; fakegroup.gr_name = a_name ? a_name->val : "nogroup"; - fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : (uid_t)-1; + fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : (gid_t)-1; fakegroup.gr_mem = fmems; return print_group(&fakegroup, getarg(args, 'P') != NULL); } -- cgit v1.2.3 From f1cacd691c6b62757f4a0168eded3d8672a06b13 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 3 Jun 2015 19:08:25 +0000 Subject: New pw -R rootdir option This allows to set an alternate root directory in which the users/groups will be manipulated Requested by: gjb, ian Tested by: gjb --- pw/pw.c | 79 +++++++++++++++++++++++++++++++++++++++--------------------- pw/pw_user.c | 44 ++++++++++++++++++++++++--------- pw/pwupd.h | 4 +++ 3 files changed, 89 insertions(+), 38 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 0c41f03..496ecd8 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -56,7 +56,7 @@ static const char *Combo2[] = { struct pwf PWF = { - 0, + PWF_REGULAR, setpwent, endpwent, getpwent, @@ -71,7 +71,7 @@ struct pwf PWF = }; struct pwf VPWF = { - 1, + PWF_ALT, vsetpwent, vendpwent, vgetpwent, @@ -99,24 +99,27 @@ main(int argc, char *argv[]) char *config = NULL; struct userconf *cnf; struct stat st; + char arg; + struct carg *carg; + char *etcpath = NULL; static const char *opts[W_NUM][M_NUM] = { { /* user */ - "V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y", - "V:C:qn:u:rY", - "V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY", - "V:C:qn:u:FPa7", - "V:C:q", - "V:C:q", - "V:C:q" + "R:V:C:qn:u:c:d:e:p:g:G:mM:k:s:oL:i:w:h:H:Db:NPy:Y", + "R:V:C:qn:u:rY", + "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY", + "R:V:C:qn:u:FPa7", + "R:V:C:q", + "R:V:C:q", + "R:V:C:q" }, { /* grp */ - "V:C:qn:g:h:H:M:opNPY", - "V:C:qn:g:Y", - "V:C:qn:d:g:l:h:H:FM:m:NPY", - "V:C:qn:g:FPa", - "V:C:q" + "R:V:C:qn:g:h:H:M:opNPY", + "R:V:C:qn:g:Y", + "R:V:C:qn:d:g:l:h:H:FM:m:NPY", + "R:V:C:qn:g:FPa", + "R:V:C:q" } }; @@ -141,7 +144,8 @@ main(int argc, char *argv[]) /* * Special case, allow pw -V [args] for scripts etc. */ - if (argv[1][1] == 'V') { + arg = argv[1][1]; + if (arg == 'V' || arg == 'R') { optarg = &argv[1][2]; if (*optarg == '\0') { if (stat(argv[2], &st) != 0) @@ -155,7 +159,7 @@ main(int argc, char *argv[]) ++argv; --argc; } - addarg(&arglist, 'V', optarg); + addarg(&arglist, arg, optarg); } else break; } @@ -217,19 +221,29 @@ main(int argc, char *argv[]) config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL; - if (getarg(&arglist, 'V') != NULL) { - char * etcpath = getarg(&arglist, 'V')->val; - if (*etcpath) { - if (config == NULL) { /* Only override config location if -C not specified */ - asprintf(&config, "%s/pw.conf", etcpath); - if (config == NULL) - errx(EX_OSERR, "out of memory"); - } - memcpy(&PWF, &VPWF, sizeof PWF); - setpwdir(etcpath); - setgrdir(etcpath); + if ((carg = getarg(&arglist, 'R')) != NULL) { + asprintf(&etcpath, "%s/etc", carg->val); + if (etcpath == NULL) + errx(EX_OSERR, "out of memory"); + } + if (etcpath == NULL && (carg = getarg(&arglist, 'V')) != NULL) { + etcpath = strdup(carg->val); + if (etcpath == NULL) + errx(EX_OSERR, "out of memory"); + } + if (etcpath && *etcpath) { + if (config == NULL) { /* Only override config location if -C not specified */ + asprintf(&config, "%s/pw.conf", etcpath); + if (config == NULL) + errx(EX_OSERR, "out of memory"); } + setpwdir(etcpath); + setgrdir(etcpath); + memcpy(&PWF, &VPWF, sizeof PWF); + if (getarg(&arglist, 'R')) + PWF._altdir = PWF_ROOTDIR; } + free(etcpath); /* * Now, let's do the common initialisation @@ -303,6 +317,7 @@ cmdhelp(int mode, int which) { "usage: pw useradd [name] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n" " Adding users:\n" @@ -325,6 +340,7 @@ cmdhelp(int mode, int which) "\t-N no update\n" " Setting defaults:\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-D set user defaults\n" "\t-b dir default home root dir\n" "\t-e period default expiry period\n" @@ -341,12 +357,14 @@ cmdhelp(int mode, int which) "\t-y path set NIS passwd file path\n", "usage: pw userdel [uid|name] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-n name login name\n" "\t-u uid user id\n" "\t-Y update NIS maps\n" "\t-r remove home & contents\n", "usage: pw usermod [uid|name] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n" "\t-F force add if no user\n" @@ -370,6 +388,7 @@ cmdhelp(int mode, int which) "\t-N no update\n", "usage: pw usershow [uid|name] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-n name login name\n" "\t-u uid user id\n" "\t-F force print\n" @@ -378,6 +397,7 @@ cmdhelp(int mode, int which) "\t-7 print in v7 format\n", "usage: pw usernext [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n", "usage pw: lock [switches]\n" @@ -392,6 +412,7 @@ cmdhelp(int mode, int which) { "usage: pw groupadd [group|gid] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n" "\t-n group group name\n" @@ -402,11 +423,13 @@ cmdhelp(int mode, int which) "\t-N no update\n", "usage: pw groupdel [group|gid] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-n name group name\n" "\t-g gid group id\n" "\t-Y update NIS maps\n", "usage: pw groupmod [group|gid] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n" "\t-F force add if not exists\n" @@ -420,6 +443,7 @@ cmdhelp(int mode, int which) "\t-N no update\n", "usage: pw groupshow [group|gid] [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-n name group name\n" "\t-g gid group id\n" "\t-F force print\n" @@ -427,6 +451,7 @@ cmdhelp(int mode, int which) "\t-a print all accounting groups\n", "usage: pw groupnext [switches]\n" "\t-V etcdir alternate /etc location\n" + "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" "\t-q quiet operation\n" } diff --git a/pw/pw_user.c b/pw/pw_user.c index 48eb934..cb4c3de 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -63,6 +63,28 @@ 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 +create_and_populate_homedir(int mode, struct cargs *args, struct passwd *pwd, + struct userconf *cnf) +{ + char *homedir, *dotdir; + struct carg *arg; + + homedir = dotdir = NULL; + + if ((arg = getarg(args, 'R'))) { + asprintf(&homedir, "%s/%s", arg->val, pwd->pw_dir); + if (homedir == NULL) + errx(EX_OSERR, "out of memory"); + asprintf(&dotdir, "%s/%s", arg->val, cnf->dotdir); + } + + copymkdir(homedir ? homedir : pwd->pw_dir, dotdir ? dotdir: cnf->dotdir, + cnf->homemode, pwd->pw_uid, pwd->pw_gid); + pw_log(cnf, mode, W_USER, "%s(%u) home %s made", pwd->pw_name, + pwd->pw_uid, pwd->pw_dir); +} + /*- * -C config configuration file * -q quiet operation @@ -108,6 +130,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) struct group *grp; struct stat st; char line[_PASSWORD_LEN+1]; + char path[MAXPATHLEN]; FILE *fp; char *dmode_c; void *set = NULL; @@ -451,7 +474,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); - if (!PWALTDIR()) { + if (PWALTDIR()) { /* * Remove mail file */ @@ -800,11 +823,13 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) * doesn't hurt anything to create the empty mailfile */ if (mode == M_ADD) { - if (!PWALTDIR()) { - snprintf(line, sizeof(line), "%s/%s", _PATH_MAILDIR, pwd->pw_name); - close(open(line, O_RDWR | O_CREAT, 0600)); /* Preserve contents & + if (PWALTDIR() != PWF_ALT) { + arg = getarg(args, 'R'); + snprintf(path, sizeof(path), "%s%s/%s", + arg ? arg->val : "", _PATH_MAILDIR, pwd->pw_name); + close(open(path, O_RDWR | O_CREAT, 0600)); /* Preserve contents & * mtime */ - chown(line, pwd->pw_uid, pwd->pw_gid); + chown(path, pwd->pw_uid, pwd->pw_gid); } } @@ -813,12 +838,9 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) * that this also `works' for editing users if -m is used, but * existing files will *not* be overwritten. */ - if (!PWALTDIR() && getarg(args, 'm') != NULL && pwd->pw_dir && *pwd->pw_dir == '/' && pwd->pw_dir[1]) { - copymkdir(pwd->pw_dir, cnf->dotdir, cnf->homemode, pwd->pw_uid, pwd->pw_gid); - pw_log(cnf, mode, W_USER, "%s(%u) home %s made", - pwd->pw_name, pwd->pw_uid, pwd->pw_dir); - } - + if (PWALTDIR() != PWF_ALT && getarg(args, 'm') != NULL && pwd->pw_dir && + *pwd->pw_dir == '/' && pwd->pw_dir[1]) + create_and_populate_homedir(mode, args, pwd, cnf); /* * Finally, send mail to the new user as well, if we are asked to diff --git a/pw/pwupd.h b/pw/pwupd.h index 1d13511..f936483 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -71,6 +71,10 @@ extern struct pwf VPWF; #define GETGRGID(gid) PWF._getgrgid(gid) #define GETGRNAM(nam) PWF._getgrnam(nam) +#define PWF_REGULAR 0 +#define PWF_ALT 1 +#define PWF_ROOTDIR 2 + #define PWALTDIR() PWF._altdir #ifndef _PATH_PWD #define _PATH_PWD "/etc" -- cgit v1.2.3 From 6596d2a2e94fa247ab005de4577ad07f9acb94d6 Mon Sep 17 00:00:00 2001 From: Glen Barber Date: Wed, 3 Jun 2015 19:17:45 +0000 Subject: Document pw(8) '-R' option, added in r283961. MFC after: 1 week X-MFC-after: r283961 Sponsored by: The FreeBSD Foundation --- pw/pw.8 | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'pw') diff --git a/pw/pw.8 b/pw/pw.8 index 076f2eb..9074313 100644 --- a/pw/pw.8 +++ b/pw/pw.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 29, 2012 +.Dd June 3, 2015 .Dt PW 8 .Os .Sh NAME @@ -32,6 +32,7 @@ .Nd create, remove, modify & display system users and groups .Sh SYNOPSIS .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar useradd .Op name|uid @@ -57,6 +58,7 @@ .Op Fl P .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar useradd .Op name|uid @@ -76,6 +78,7 @@ .Op Fl s Ar shell .Op Fl y Ar path .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar userdel .Op name|uid @@ -84,6 +87,7 @@ .Op Fl r .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar usermod .Op name|uid @@ -109,6 +113,7 @@ .Op Fl P .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar usershow .Op name|uid @@ -119,11 +124,13 @@ .Op Fl 7 .Op Fl a .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar usernext .Op Fl C Ar config .Op Fl q .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar groupadd .Op group|gid @@ -138,6 +145,7 @@ .Op Fl P .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar groupdel .Op group|gid @@ -145,6 +153,7 @@ .Op Fl g Ar gid .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar groupmod .Op group|gid @@ -161,6 +170,7 @@ .Op Fl P .Op Fl Y .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar groupshow .Op group|gid @@ -170,17 +180,20 @@ .Op Fl P .Op Fl a .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar groupnext .Op Fl C Ar config .Op Fl q .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar lock .Op name|uid .Op Fl C Ar config .Op Fl q .Nm +.Op Fl R Ar rootdir .Op Fl V Ar etcdir .Ar unlock .Op name|uid @@ -246,6 +259,12 @@ options. .Pp The following flags are common to most or all modes of operation: .Bl -tag -width "-G grouplist" +.It Fl R Ar rootdir +Specifies an alternate root directory within which +.Nm +will operate. +Any paths specified will be relative to +.Va rootdir . .It Fl V Ar etcdir This flag sets an alternate location for the password, group and configuration files, and may be used to maintain a user/group database in an alternate location. -- cgit v1.2.3 From 7184d24a07df16085b560f362e87bc9c9ec5004f Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 10:57:02 +0000 Subject: Instead of always casting the pw_checkname input to u_char * and casting it back to char *, change pw_checkname to directly take char * in input --- pw/pw.h | 2 +- pw/pw_group.c | 4 ++-- pw/pw_user.c | 17 +++++++++-------- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'pw') diff --git a/pw/pw.h b/pw/pw.h index a1ed0c4..5950681 100644 --- a/pw/pw.h +++ b/pw/pw.h @@ -108,7 +108,7 @@ struct carg *getarg(struct cargs * _args, int ch); int pw_user(struct userconf * cnf, int mode, struct cargs * _args); int pw_group(struct userconf * cnf, int mode, struct cargs * _args); -char *pw_checkname(u_char *name, int gecos); +char *pw_checkname(char *name, int gecos); int addnispwent(const char *path, struct passwd *pwd); int delnispwent(const char *path, const char *login); diff --git a/pw/pw_group.c b/pw/pw_group.c index c001160..bc559a5 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -146,7 +146,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) grp->gr_gid = (gid_t) atoi(a_gid->val); if (a_newname != NULL) - grp->gr_name = pw_checkname((u_char *)a_newname->val, 0); + grp->gr_name = pw_checkname(a_newname->val, 0); } else { if (a_name == NULL) /* Required */ errx(EX_DATAERR, "group name required"); @@ -156,7 +156,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) extendarray(&members, &grmembers, 200); members[0] = NULL; grp = &fakegroup; - grp->gr_name = pw_checkname((u_char *)a_name->val, 0); + grp->gr_name = pw_checkname(a_name->val, 0); grp->gr_passwd = "*"; grp->gr_gid = gr_gidpolicy(cnf, args); grp->gr_mem = members; diff --git a/pw/pw_user.c b/pw/pw_user.c index cb4c3de..3880c42 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -263,7 +263,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) } } if ((arg = getarg(args, 'L')) != NULL) - cnf->default_class = pw_checkname((u_char *)arg->val, 0); + cnf->default_class = pw_checkname(arg->val, 0); if ((arg = getarg(args, 'G')) != NULL && arg->val) { int i = 0; @@ -323,7 +323,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) } if ((a_name = getarg(args, 'n')) != NULL) - pwd = GETPWNAM(pw_checkname((u_char *)a_name->val, 0)); + pwd = GETPWNAM(pw_checkname(a_name->val, 0)); a_uid = getarg(args, 'u'); if (a_uid == NULL) { @@ -510,7 +510,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if ((arg = getarg(args, 'l')) != NULL) { 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); + pwd->pw_name = pw_checkname(arg->val, 0); edited = 1; } @@ -648,7 +648,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) * Shared add/edit code */ if ((arg = getarg(args, 'c')) != NULL) { - char *gecos = pw_checkname((u_char *)arg->val, 1); + char *gecos = pw_checkname(arg->val, 1); if (strcmp(pwd->pw_gecos, gecos) != 0) { pwd->pw_gecos = gecos; edited = 1; @@ -1239,11 +1239,11 @@ print_user(struct passwd * pwd, int pretty, int v7) return EXIT_SUCCESS; } -char * -pw_checkname(u_char *name, int gecos) +char * +pw_checkname(char *name, int gecos) { char showch[8]; - u_char const *badchars, *ch, *showtype; + const char *badchars, *ch, *showtype; int reject; ch = name; @@ -1294,7 +1294,8 @@ pw_checkname(u_char *name, int gecos) if (!gecos && (ch - name) > LOGNAMESIZE) errx(EX_DATAERR, "name too long `%s' (max is %d)", name, LOGNAMESIZE); - return (char *)name; + + return (name); } -- cgit v1.2.3 From e953873e6616177dddc24c5b707934a923984bfa Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 11:26:28 +0000 Subject: Move user deletion code into a separate function to improve readability --- pw/pw_user.c | 221 +++++++++++++++++++++++++++++++---------------------------- 1 file changed, 115 insertions(+), 106 deletions(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index 3880c42..ad02450 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -51,6 +51,8 @@ static const char rcsid[] = static char locked_str[] = "*LOCKED*"; +static int delete_user(struct userconf *cnf, struct passwd *pwd, + struct carg *a_name, int delete, int mode); static int print_user(struct passwd * pwd, int pretty, int v7); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); static uid_t pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer); @@ -394,112 +396,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) 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; - struct group *gr; - char grname[LOGNAMESIZE]; - - if (strcmp(pwd->pw_name, "root") == 0) - errx(EX_DATAERR, "cannot remove user 'root'"); - - if (!PWALTDIR()) { - /* - * Remove opie record from /etc/opiekeys - */ - - rmopie(pwd->pw_name); - - /* - * 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); - } - } - /* - * Save these for later, since contents of pwd may be - * invalidated by deletion - */ - snprintf(file, sizeof(file), "%s/%s", _PATH_MAILDIR, pwd->pw_name); - strlcpy(home, pwd->pw_dir, sizeof(home)); - gr = GETGRGID(pwd->pw_gid); - if (gr != NULL) - strlcpy(grname, gr->gr_name, LOGNAMESIZE); - else - grname[0] = '\0'; - - rc = delpwent(pwd); - if (rc == -1) - err(EX_IOERR, "user '%s' does not exist", pwd->pw_name); - else if (rc != 0) - err(EX_IOERR, "passwd update"); - - 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 */ - } - - grp = GETGRNAM(a_name->val); - if (grp != NULL && - (grp->gr_mem == NULL || *grp->gr_mem == NULL) && - strcmp(a_name->val, grname) == 0) - delgrent(GETGRNAM(a_name->val)); - SETGRENT(); - while ((grp = GETGRENT()) != NULL) { - int i, j; - char group[MAXLOGNAME]; - if (grp->gr_mem != NULL) { - for (i = 0; grp->gr_mem[i] != NULL; i++) { - if (!strcmp(grp->gr_mem[i], a_name->val)) { - for (j = i; grp->gr_mem[j] != NULL; j++) - grp->gr_mem[j] = grp->gr_mem[j+1]; - strlcpy(group, grp->gr_name, MAXLOGNAME); - chggrent(group, grp); - } - } - } - } - ENDGRENT(); - - pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); - - if (PWALTDIR()) { - /* - * Remove mail file - */ - remove(file); - - /* - * Remove at jobs - */ - if (getpwuid(uid) == NULL) - rmat(uid); - - /* - * Remove home directory and contents - */ - if (getarg(args, 'r') != NULL && *home == '/' && getpwuid(uid) == NULL) { - if (stat(home, &st) != -1) { - rm_r(home, uid); - pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", - a_name->val, uid, home, - stat(home, &st) == -1 ? "" : "not completely "); - } - } - } - return EXIT_SUCCESS; - } else if (mode == M_PRINT) + } else if (mode == M_DELETE) + return (delete_user(cnf, pwd, a_name, + getarg(args, 'r') != NULL, mode)); + else if (mode == M_PRINT) return print_user(pwd, getarg(args, 'P') != NULL, getarg(args, '7') != NULL); @@ -1155,6 +1055,115 @@ pw_password(struct userconf * cnf, struct cargs * args, char const * user) return pw_pwcrypt(pwbuf); } +static int +delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, + int delete, int mode) +{ + char file[MAXPATHLEN]; + char home[MAXPATHLEN]; + uid_t uid = pwd->pw_uid; + struct group *gr, *grp; + char grname[LOGNAMESIZE]; + int rc; + struct stat st; + + if (strcmp(pwd->pw_name, "root") == 0) + errx(EX_DATAERR, "cannot remove user 'root'"); + + if (!PWALTDIR()) { + /* + * Remove opie record from /etc/opiekeys + */ + + rmopie(pwd->pw_name); + + /* + * 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); + } + } + /* + * Save these for later, since contents of pwd may be + * invalidated by deletion + */ + snprintf(file, sizeof(file), "%s/%s", _PATH_MAILDIR, pwd->pw_name); + strlcpy(home, pwd->pw_dir, sizeof(home)); + gr = GETGRGID(pwd->pw_gid); + if (gr != NULL) + strlcpy(grname, gr->gr_name, LOGNAMESIZE); + else + grname[0] = '\0'; + + rc = delpwent(pwd); + if (rc == -1) + err(EX_IOERR, "user '%s' does not exist", pwd->pw_name); + else if (rc != 0) + err(EX_IOERR, "passwd update"); + + 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 */ + } + + grp = GETGRNAM(a_name->val); + if (grp != NULL && + (grp->gr_mem == NULL || *grp->gr_mem == NULL) && + strcmp(a_name->val, grname) == 0) + delgrent(GETGRNAM(a_name->val)); + SETGRENT(); + while ((grp = GETGRENT()) != NULL) { + int i, j; + char group[MAXLOGNAME]; + if (grp->gr_mem != NULL) { + for (i = 0; grp->gr_mem[i] != NULL; i++) { + if (!strcmp(grp->gr_mem[i], a_name->val)) { + for (j = i; grp->gr_mem[j] != NULL; j++) + grp->gr_mem[j] = grp->gr_mem[j+1]; + strlcpy(group, grp->gr_name, MAXLOGNAME); + chggrent(group, grp); + } + } + } + } + ENDGRENT(); + + pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); + + if (PWALTDIR()) { + /* + * Remove mail file + */ + remove(file); + + /* + * Remove at jobs + */ + if (getpwuid(uid) == NULL) + rmat(uid); + + /* + * Remove home directory and contents + */ + if (delete && *home == '/' && getpwuid(uid) == NULL) { + if (stat(home, &st) != -1) { + rm_r(home, uid); + pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", + a_name->val, uid, home, + stat(home, &st) == -1 ? "" : "not completely "); + } + } + } + + return (EXIT_SUCCESS); +} static int print_user(struct passwd * pwd, int pretty, int v7) -- cgit v1.2.3 From 913db9fa365fd7f1c73ab492d2decfb718d3dbba Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 11:30:33 +0000 Subject: Remove one level of indentation --- pw/pw_user.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index ad02450..8a07a0e 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -1152,13 +1152,12 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, /* * Remove home directory and contents */ - if (delete && *home == '/' && getpwuid(uid) == NULL) { - if (stat(home, &st) != -1) { - rm_r(home, uid); - pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", - a_name->val, uid, home, - stat(home, &st) == -1 ? "" : "not completely "); - } + if (delete && *home == '/' && getpwuid(uid) == NULL && + stat(home, &st) != -1) { + rm_r(home, uid); + pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", + a_name->val, uid, home, + stat(home, &st) == -1 ? "" : "not completely "); } } -- cgit v1.2.3 From 9a58ddd97ed3d0fc7096b8793c87f971f4ec0009 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 11:35:34 +0000 Subject: Improve readability by reducing indentations levels --- pw/pw_user.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index 8a07a0e..dc33272 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -1122,15 +1122,17 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, while ((grp = GETGRENT()) != NULL) { int i, j; char group[MAXLOGNAME]; - if (grp->gr_mem != NULL) { - for (i = 0; grp->gr_mem[i] != NULL; i++) { - if (!strcmp(grp->gr_mem[i], a_name->val)) { - for (j = i; grp->gr_mem[j] != NULL; j++) - grp->gr_mem[j] = grp->gr_mem[j+1]; - strlcpy(group, grp->gr_name, MAXLOGNAME); - chggrent(group, grp); - } - } + if (grp->gr_mem == NULL) + continue; + + for (i = 0; grp->gr_mem[i] != NULL; i++) { + if (strcmp(grp->gr_mem[i], a_name->val)) + continue; + + for (j = i; grp->gr_mem[j] != NULL; j++) + grp->gr_mem[j] = grp->gr_mem[j+1]; + strlcpy(group, grp->gr_name, MAXLOGNAME); + chggrent(group, grp); } } ENDGRENT(); -- cgit v1.2.3 From aa02e73442262bdff0eacbf64175e8c0c711a749 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 11:38:26 +0000 Subject: Test explicitly the result of strcmp to be consistent with the rest of the code --- pw/pw_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index dc33272..5f65129 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -1126,7 +1126,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, continue; for (i = 0; grp->gr_mem[i] != NULL; i++) { - if (strcmp(grp->gr_mem[i], a_name->val)) + if (strcmp(grp->gr_mem[i], a_name->val) != 0) continue; for (j = i; grp->gr_mem[j] != NULL; j++) -- cgit v1.2.3 From 9eca0d3b9875657b856d9f4b2c808164886ef1cd Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 14:32:52 +0000 Subject: Fix pw userdel -r not deleting homedir --- pw/pw_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index 5f65129..f5305f9 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -1139,7 +1139,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); - if (PWALTDIR()) { + if (!PWALTDIR()) { /* * Remove mail file */ -- cgit v1.2.3 From 39d77815028ba1a72509c07e0a8583493f6ec0a8 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 14:34:38 +0000 Subject: Add a new global struct pwconf to store etcpath, rootdir and struct userconf Do not add anymore -R and -V to arglist Add an error message if both -V and -R are set in arguments --- pw/grupd.c | 22 ++++------------------ pw/pw.c | 56 ++++++++++++++++++++++++++------------------------------ pw/pw.h | 28 ++-------------------------- pw/pw_group.c | 3 ++- pw/pw_user.c | 30 ++++++++++++++++-------------- pw/pwupd.c | 24 ++++-------------------- pw/pwupd.h | 36 ++++++++++++++++++++++++++++++++---- 7 files changed, 86 insertions(+), 113 deletions(-) (limited to 'pw') diff --git a/pw/grupd.c b/pw/grupd.c index 8735831..d52a345 100644 --- a/pw/grupd.c +++ b/pw/grupd.c @@ -39,28 +39,14 @@ static const char rcsid[] = #include "pwupd.h" -static char * grpath = _PATH_PWD; - -int -setgrdir(const char * dir) -{ - if (dir == NULL) - return -1; - else - grpath = strdup(dir); - if (grpath == NULL) - return -1; - - return 0; -} - char * getgrpath(const char * file) { static char pathbuf[MAXPATHLEN]; - snprintf(pathbuf, sizeof pathbuf, "%s/%s", grpath, file); - return pathbuf; + snprintf(pathbuf, sizeof pathbuf, "%s/%s", conf.etcpath, file); + + return (pathbuf); } static int @@ -76,7 +62,7 @@ gr_update(struct group * grp, char const * group) if (group != NULL) old_gr = GETGRNAM(group); - if (gr_init(grpath, NULL)) + if (gr_init(conf.etcpath, NULL)) err(1, "gr_init()"); if ((pfd = gr_lock()) == -1) { diff --git a/pw/pw.c b/pw/pw.c index 496ecd8..174a9dc 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -33,6 +33,7 @@ static const char rcsid[] = #include #include #include +#include #include #include "pw.h" @@ -84,6 +85,8 @@ struct pwf VPWF = vgetgrnam, }; +struct pwconf conf; + static struct cargs arglist; static int getindex(const char *words[], const char *word); @@ -97,11 +100,9 @@ main(int argc, char *argv[]) int mode = -1; int which = -1; char *config = NULL; - struct userconf *cnf; struct stat st; char arg; - struct carg *carg; - char *etcpath = NULL; + bool relocated = false; static const char *opts[W_NUM][M_NUM] = { @@ -123,12 +124,15 @@ main(int argc, char *argv[]) } }; - static int (*funcs[W_NUM]) (struct userconf * _cnf, int _mode, struct cargs * _args) = + static int (*funcs[W_NUM]) (int _mode, struct cargs * _args) = { /* Request handlers */ pw_user, pw_group }; + conf.rootdir[0] = '\0'; + strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); + LIST_INIT(&arglist); (void)setlocale(LC_ALL, ""); @@ -146,6 +150,10 @@ main(int argc, char *argv[]) */ arg = argv[1][1]; if (arg == 'V' || arg == 'R') { + if (relocated) + errx(EXIT_FAILURE, "Both '-R' and '-V' " + "specified, only one accepted"); + relocated = true; optarg = &argv[1][2]; if (*optarg == '\0') { if (stat(argv[2], &st) != 0) @@ -159,7 +167,14 @@ main(int argc, char *argv[]) ++argv; --argc; } - addarg(&arglist, arg, optarg); + memcpy(&PWF, &VPWF, sizeof PWF); + if (arg == 'R') { + strlcpy(conf.rootdir, optarg, + sizeof(conf.rootdir)); + PWF._altdir = PWF_ROOTDIR; + } + snprintf(conf.etcpath, sizeof(conf.etcpath), + "%s%s", optarg, arg == 'R' ? "/etc" : ""); } else break; } @@ -220,37 +235,18 @@ main(int argc, char *argv[]) */ config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL; - - if ((carg = getarg(&arglist, 'R')) != NULL) { - asprintf(&etcpath, "%s/etc", carg->val); - if (etcpath == NULL) + if (config == NULL) { /* Only override config location if -C not specified */ + asprintf(&config, "%s/pw.conf", conf.etcpath); + if (config == NULL) errx(EX_OSERR, "out of memory"); } - if (etcpath == NULL && (carg = getarg(&arglist, 'V')) != NULL) { - etcpath = strdup(carg->val); - if (etcpath == NULL) - errx(EX_OSERR, "out of memory"); - } - if (etcpath && *etcpath) { - if (config == NULL) { /* Only override config location if -C not specified */ - asprintf(&config, "%s/pw.conf", etcpath); - if (config == NULL) - errx(EX_OSERR, "out of memory"); - } - setpwdir(etcpath); - setgrdir(etcpath); - memcpy(&PWF, &VPWF, sizeof PWF); - if (getarg(&arglist, 'R')) - PWF._altdir = PWF_ROOTDIR; - } - free(etcpath); /* * Now, let's do the common initialisation */ - cnf = read_userconfig(config); + conf.userconf = read_userconfig(config); - ch = funcs[which] (cnf, mode, &arglist); + ch = funcs[which] (mode, &arglist); /* * If everything went ok, and we've been asked to update @@ -274,7 +270,7 @@ main(int argc, char *argv[]) if ((i = WEXITSTATUS(i)) != 0) errx(ch, "make exited with status %d", i); else - pw_log(cnf, mode, which, "NIS maps updated"); + pw_log(conf.userconf, mode, which, "NIS maps updated"); } } return ch; diff --git a/pw/pw.h b/pw/pw.h index 5950681..9c0aa32 100644 --- a/pw/pw.h +++ b/pw/pw.h @@ -72,30 +72,6 @@ struct carg LIST_HEAD(cargs, carg); -struct userconf -{ - int default_password; /* Default password for new users? */ - int reuse_uids; /* Reuse uids? */ - int reuse_gids; /* Reuse gids? */ - char *nispasswd; /* Path to NIS version of the passwd file */ - char *dotdir; /* Where to obtain skeleton files */ - char *newmail; /* Mail to send to new accounts */ - char *logfile; /* Where to log changes */ - char *home; /* Where to create home directory */ - mode_t homemode; /* Home directory permissions */ - char *shelldir; /* Where shells are located */ - char **shells; /* List of shells */ - char *shell_default; /* Default shell */ - char *default_group; /* Default group number */ - char **groups; /* Default (additional) groups */ - char *default_class; /* Default user class */ - uid_t min_uid, max_uid; /* Allowed range of uids */ - gid_t min_gid, max_gid; /* Allowed range of gids */ - int expire_days; /* Days to expiry */ - int password_days; /* Days to password expiry */ - int numgroups; /* (internal) size of default_group array */ -}; - #define _DEF_DIRMODE (S_IRWXU | S_IRWXG | S_IRWXO) #define _PATH_PW_CONF "/etc/pw.conf" #define _UC_MAXLINE 1024 @@ -106,8 +82,8 @@ int write_userconfig(char const * file); struct carg *addarg(struct cargs * _args, int ch, char *argstr); struct carg *getarg(struct cargs * _args, int ch); -int pw_user(struct userconf * cnf, int mode, struct cargs * _args); -int pw_group(struct userconf * cnf, int mode, struct cargs * _args); +int pw_user(int mode, struct cargs * _args); +int pw_group(int mode, struct cargs * _args); char *pw_checkname(char *name, int gecos); int addnispwent(const char *path, struct passwd *pwd); diff --git a/pw/pw_group.c b/pw/pw_group.c index bc559a5..b57eab3 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -48,7 +48,7 @@ static int print_group(struct group * grp, int pretty); static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); int -pw_group(struct userconf * cnf, int mode, struct cargs * args) +pw_group(int mode, struct cargs * args) { int rc; struct carg *a_newname = getarg(args, 'l'); @@ -58,6 +58,7 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) struct group *grp = NULL; int grmembers = 0; char **members = NULL; + struct userconf *cnf = conf.userconf; static struct group fakegroup = { diff --git a/pw/pw_user.c b/pw/pw_user.c index f5305f9..d69f56b 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -55,7 +55,7 @@ static int delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, int delete, int mode); static int print_user(struct passwd * pwd, int pretty, int v7); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); -static uid_t pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer); +static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer); static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args); static time_t pw_exppolicy(struct userconf * cnf, struct cargs * args); static char *pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user); @@ -66,19 +66,18 @@ static void rmat(uid_t uid); static void rmopie(char const * name); static void -create_and_populate_homedir(int mode, struct cargs *args, struct passwd *pwd, - struct userconf *cnf) +create_and_populate_homedir(int mode, struct passwd *pwd) { char *homedir, *dotdir; - struct carg *arg; + struct userconf *cnf = conf.userconf; homedir = dotdir = NULL; - if ((arg = getarg(args, 'R'))) { - asprintf(&homedir, "%s/%s", arg->val, pwd->pw_dir); + if (conf.rootdir[0] != '\0') { + asprintf(&homedir, "%s/%s", conf.rootdir, pwd->pw_dir); if (homedir == NULL) errx(EX_OSERR, "out of memory"); - asprintf(&dotdir, "%s/%s", arg->val, cnf->dotdir); + asprintf(&dotdir, "%s/%s", conf.rootdir, cnf->dotdir); } copymkdir(homedir ? homedir : pwd->pw_dir, dotdir ? dotdir: cnf->dotdir, @@ -120,7 +119,7 @@ create_and_populate_homedir(int mode, struct cargs *args, struct passwd *pwd, */ int -pw_user(struct userconf * cnf, int mode, struct cargs * args) +pw_user(int mode, struct cargs * args) { int rc, edited = 0; char *p = NULL; @@ -131,6 +130,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) struct passwd *pwd = NULL; struct group *grp; struct stat st; + struct userconf *cnf; char line[_PASSWORD_LEN+1]; char path[MAXPATHLEN]; FILE *fp; @@ -154,6 +154,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) #endif }; + cnf = conf.userconf; /* * With M_NEXT, we only need to return the @@ -165,7 +166,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (getarg(args, 'q')) return next; printf("%u:", next); - pw_group(cnf, mode, args); + pw_group(mode, args); return EXIT_SUCCESS; } @@ -528,7 +529,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) pwd->pw_name = a_name->val; pwd->pw_class = cnf->default_class ? cnf->default_class : ""; pwd->pw_uid = pw_uidpolicy(cnf, args); - pwd->pw_gid = pw_gidpolicy(cnf, args, pwd->pw_name, (gid_t) pwd->pw_uid); + pwd->pw_gid = pw_gidpolicy(args, pwd->pw_name, (gid_t) pwd->pw_uid); pwd->pw_change = pw_pwdpolicy(cnf, args); pwd->pw_expire = pw_exppolicy(cnf, args); pwd->pw_dir = pw_homepolicy(cnf, args, pwd->pw_name); @@ -740,7 +741,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) */ if (PWALTDIR() != PWF_ALT && getarg(args, 'm') != NULL && pwd->pw_dir && *pwd->pw_dir == '/' && pwd->pw_dir[1]) - create_and_populate_homedir(mode, args, pwd, cnf); + create_and_populate_homedir(mode, pwd); /* * Finally, send mail to the new user as well, if we are asked to @@ -824,11 +825,12 @@ pw_uidpolicy(struct userconf * cnf, struct cargs * args) static uid_t -pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer) +pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer) { struct group *grp; gid_t gid = (uid_t) - 1; struct carg *a_gid = getarg(args, 'g'); + struct userconf *cnf = conf.userconf; /* * If no arg given, see if default can help out @@ -874,11 +876,11 @@ pw_gidpolicy(struct userconf * cnf, struct cargs * args, char *nam, gid_t prefer { addarg(&grpargs, 'N', NULL); addarg(&grpargs, 'q', NULL); - gid = pw_group(cnf, M_NEXT, &grpargs); + gid = pw_group(M_NEXT, &grpargs); } else { - pw_group(cnf, M_ADD, &grpargs); + pw_group(M_ADD, &grpargs); if ((grp = GETGRNAM(nam)) != NULL) gid = grp->gr_gid; } diff --git a/pw/pwupd.c b/pw/pwupd.c index 89d0856..f9e1959 100644 --- a/pw/pwupd.c +++ b/pw/pwupd.c @@ -44,28 +44,12 @@ static const char rcsid[] = #include "pwupd.h" -static char pathpwd[] = _PATH_PWD; -static char * pwpath = pathpwd; - -int -setpwdir(const char * dir) -{ - if (dir == NULL) - return (-1); - else - pwpath = strdup(dir); - if (pwpath == NULL) - return (-1); - - return (0); -} - char * getpwpath(char const * file) { static char pathbuf[MAXPATHLEN]; - snprintf(pathbuf, sizeof pathbuf, "%s/%s", pwpath, file); + snprintf(pathbuf, sizeof pathbuf, "%s/%s", conf.etcpath, file); return (pathbuf); } @@ -80,9 +64,9 @@ pwdb_check(void) args[i++] = _PATH_PWD_MKDB; args[i++] = "-C"; - if (pwpath != pathpwd) { + if (strcmp(conf.etcpath, _PATH_PWD) != 0) { args[i++] = "-d"; - args[i++] = pwpath; + args[i++] = conf.etcpath; } args[i++] = getpwpath(_MASTERPASSWD); args[i] = NULL; @@ -117,7 +101,7 @@ pw_update(struct passwd * pwd, char const * user) if (user != NULL) old_pw = GETPWNAM(user); - if (pw_init(pwpath, NULL)) + if (pw_init(conf.etcpath, NULL)) err(1, "pw_init()"); if ((pfd = pw_lock()) == -1) { pw_fini(); diff --git a/pw/pwupd.h b/pw/pwupd.h index f936483..a17dacf 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -29,6 +29,7 @@ #ifndef _PWUPD_H_ #define _PWUPD_H_ +#include #include #include #include @@ -41,8 +42,7 @@ #define RET_SETGRENT void #endif -struct pwf -{ +struct pwf { int _altdir; void (*_setpwent)(void); void (*_endpwent)(void); @@ -56,8 +56,38 @@ struct pwf struct group * (*_getgrnam)(const char * nam); }; +struct userconf { + int default_password; /* Default password for new users? */ + int reuse_uids; /* Reuse uids? */ + int reuse_gids; /* Reuse gids? */ + char *nispasswd; /* Path to NIS version of the passwd file */ + char *dotdir; /* Where to obtain skeleton files */ + char *newmail; /* Mail to send to new accounts */ + char *logfile; /* Where to log changes */ + char *home; /* Where to create home directory */ + mode_t homemode; /* Home directory permissions */ + char *shelldir; /* Where shells are located */ + char **shells; /* List of shells */ + char *shell_default; /* Default shell */ + char *default_group; /* Default group number */ + char **groups; /* Default (additional) groups */ + char *default_class; /* Default user class */ + uid_t min_uid, max_uid; /* Allowed range of uids */ + gid_t min_gid, max_gid; /* Allowed range of gids */ + int expire_days; /* Days to expiry */ + int password_days; /* Days to password expiry */ + int numgroups; /* (internal) size of default_group array */ +}; + +struct pwconf { + char rootdir[MAXPATHLEN]; + char etcpath[MAXPATHLEN]; + struct userconf *userconf; +}; + extern struct pwf PWF; extern struct pwf VPWF; +extern struct pwconf conf; #define SETPWENT() PWF._setpwent() #define ENDPWENT() PWF._endpwent() @@ -91,14 +121,12 @@ int addpwent(struct passwd * pwd); int delpwent(struct passwd * pwd); int chgpwent(char const * login, struct passwd * pwd); -int setpwdir(const char * dir); char * getpwpath(char const * file); int addgrent(struct group * grp); int delgrent(struct group * grp); int chggrent(char const * name, struct group * grp); -int setgrdir(const char * dir); char * getgrpath(const char *file); void vsetpwent(void); -- cgit v1.2.3 From ed070f3fb430bf14b9fae10c25312f6dc4235aa6 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 14:54:07 +0000 Subject: Handle -C and -Y locally and stop adding them to arglist --- pw/pw.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 174a9dc..991019d 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -102,7 +102,7 @@ main(int argc, char *argv[]) char *config = NULL; struct stat st; char arg; - bool relocated = false; + bool relocated, nis; static const char *opts[W_NUM][M_NUM] = { @@ -130,6 +130,7 @@ main(int argc, char *argv[]) pw_group }; + relocated = nis = false; conf.rootdir[0] = '\0'; strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); @@ -210,10 +211,20 @@ main(int argc, char *argv[]) optarg = NULL; while ((ch = getopt(argc, argv, opts[which][mode])) != -1) { - if (ch == '?') + switch (ch) { + case '?': errx(EX_USAGE, "unknown switch"); - else + break; + case 'C': + config = optarg; + break; + case 'Y': + nis = true; + break; + default: addarg(&arglist, ch, optarg); + break; + } optarg = NULL; } @@ -234,7 +245,6 @@ main(int argc, char *argv[]) * Set our base working path if not overridden */ - config = getarg(&arglist, 'C') ? getarg(&arglist, 'C')->val : NULL; if (config == NULL) { /* Only override config location if -C not specified */ asprintf(&config, "%s/pw.conf", conf.etcpath); if (config == NULL) @@ -252,7 +262,7 @@ main(int argc, char *argv[]) * If everything went ok, and we've been asked to update * the NIS maps, then do it now */ - if (ch == EXIT_SUCCESS && getarg(&arglist, 'Y') != NULL) { + if (ch == EXIT_SUCCESS && nis) { pid_t pid; fflush(NULL); -- cgit v1.2.3 From e6c20d74e9c630e7116f84d3712c178369b10c96 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 14:57:16 +0000 Subject: Sort headers --- pw/pwupd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pwupd.h b/pw/pwupd.h index a17dacf..a5d6c27 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -29,13 +29,13 @@ #ifndef _PWUPD_H_ #define _PWUPD_H_ +#include #include #include + #include #include -#include - #if defined(__FreeBSD__) #define RET_SETGRENT int #else -- cgit v1.2.3 From 577824cadb88a52417c8a551d1aa6b70b2224b22 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 15:09:53 +0000 Subject: Handle dryrun (-N) via global pwconf --- pw/pw.c | 6 +++++- pw/pw_group.c | 2 +- pw/pw_user.c | 8 +++----- pw/pwupd.h | 2 ++ 4 files changed, 11 insertions(+), 7 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 991019d..7a86680 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -132,6 +132,7 @@ main(int argc, char *argv[]) relocated = nis = false; conf.rootdir[0] = '\0'; + conf.dryrun = false; strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); LIST_INIT(&arglist); @@ -218,6 +219,9 @@ main(int argc, char *argv[]) case 'C': config = optarg; break; + case 'N': + conf.dryrun = true; + break; case 'Y': nis = true; break; @@ -231,7 +235,7 @@ main(int argc, char *argv[]) /* * Must be root to attempt an update */ - if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && getarg(&arglist, 'N')==NULL) + if (geteuid() != 0 && mode != M_PRINT && mode != M_NEXT && !conf.dryrun) errx(EX_NOPERM, "you must be root to run this program"); /* diff --git a/pw/pw_group.c b/pw/pw_group.c index b57eab3..302d44e 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -258,7 +258,7 @@ pw_group(int mode, struct cargs * args) grp->gr_mem = members; } - if (getarg(args, 'N') != NULL) + if (conf.dryrun) return print_group(grp, getarg(args, 'P') != NULL); if (mode == M_ADD && (rc = addgrent(grp)) != 0) { diff --git a/pw/pw_user.c b/pw/pw_user.c index d69f56b..fac4d25 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -620,7 +620,7 @@ pw_user(int mode, struct cargs * args) /* * Special case: -N only displays & exits */ - if (getarg(args, 'N') != NULL) + if (conf.dryrun) return print_user(pwd, getarg(args, 'P') != NULL, getarg(args, '7') != NULL); @@ -872,9 +872,7 @@ pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer) snprintf(tmp, sizeof(tmp), "%u", prefer); addarg(&grpargs, 'g', tmp); } - if (getarg(args, 'N')) - { - addarg(&grpargs, 'N', NULL); + if (conf.dryrun) { addarg(&grpargs, 'q', NULL); gid = pw_group(M_NEXT, &grpargs); } @@ -1035,7 +1033,7 @@ pw_password(struct userconf * cnf, struct cargs * args, char const * user) * We give this information back to the user */ if (getarg(args, 'h') == NULL && getarg(args, 'H') == NULL && - getarg(args, 'N') == NULL) { + !conf.dryrun) { if (isatty(STDOUT_FILENO)) printf("Password for '%s' is: ", user); printf("%s\n", pwbuf); diff --git a/pw/pwupd.h b/pw/pwupd.h index a5d6c27..ec9ac30 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -35,6 +35,7 @@ #include #include +#include #if defined(__FreeBSD__) #define RET_SETGRENT int @@ -82,6 +83,7 @@ struct userconf { struct pwconf { char rootdir[MAXPATHLEN]; char etcpath[MAXPATHLEN]; + bool dryrun; struct userconf *userconf; }; -- cgit v1.2.3 From fec3dfc01be2e26eb5df5998a06066e2064e0a4b Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 15:27:17 +0000 Subject: Handle pretty print (-P) via global pwconf --- pw/pw.c | 4 ++++ pw/pw_group.c | 16 +++++++--------- pw/pw_user.c | 18 ++++++------------ pw/pwupd.h | 1 + 4 files changed, 18 insertions(+), 21 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 7a86680..22665e9 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -133,6 +133,7 @@ main(int argc, char *argv[]) relocated = nis = false; conf.rootdir[0] = '\0'; conf.dryrun = false; + conf.pretty = false; strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); LIST_INIT(&arglist); @@ -222,6 +223,9 @@ main(int argc, char *argv[]) case 'N': conf.dryrun = true; break; + case 'P': + conf.pretty = true; + break; case 'Y': nis = true; break; diff --git a/pw/pw_group.c b/pw/pw_group.c index 302d44e..d5d7d52 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -44,7 +44,7 @@ static const char rcsid[] = static struct passwd *lookup_pwent(const char *user); static void delete_members(char ***members, int *grmembers, int *i, struct carg *arg, struct group *grp); -static int print_group(struct group * grp, int pretty); +static int print_group(struct group * grp); static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); int @@ -89,11 +89,9 @@ pw_group(int mode, struct cargs * args) } if (mode == M_PRINT && getarg(args, 'a')) { - int pretty = getarg(args, 'P') != NULL; - SETGRENT(); while ((grp = GETGRENT()) != NULL) - print_group(grp, pretty); + print_group(grp); ENDGRENT(); return EXIT_SUCCESS; } @@ -119,7 +117,7 @@ pw_group(int mode, struct cargs * args) fakegroup.gr_name = a_name ? a_name->val : "nogroup"; fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : (gid_t)-1; fakegroup.gr_mem = fmems; - return print_group(&fakegroup, getarg(args, 'P') != NULL); + return print_group(&fakegroup); } errx(EX_DATAERR, "unknown group `%s'", a_name ? a_name->val : a_gid->val); } @@ -141,7 +139,7 @@ pw_group(int mode, struct cargs * args) pw_log(cnf, mode, W_GROUP, "%s(%u) removed", a_name->val, gid); return EXIT_SUCCESS; } else if (mode == M_PRINT) - return print_group(grp, getarg(args, 'P') != NULL); + return print_group(grp); if (a_gid) grp->gr_gid = (gid_t) atoi(a_gid->val); @@ -259,7 +257,7 @@ pw_group(int mode, struct cargs * args) } if (conf.dryrun) - return print_group(grp, getarg(args, 'P') != NULL); + return print_group(grp); if (mode == M_ADD && (rc = addgrent(grp)) != 0) { if (rc == -1) @@ -412,9 +410,9 @@ gr_gidpolicy(struct userconf * cnf, struct cargs * args) static int -print_group(struct group * grp, int pretty) +print_group(struct group * grp) { - if (!pretty) { + if (!conf.pretty) { char *buf = NULL; buf = gr_make(grp); diff --git a/pw/pw_user.c b/pw/pw_user.c index fac4d25..bfbde78 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -53,7 +53,7 @@ static char locked_str[] = "*LOCKED*"; static int delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, int delete, int mode); -static int print_user(struct passwd * pwd, int pretty, int v7); +static int print_user(struct passwd * pwd, int v7); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer); static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args); @@ -316,11 +316,10 @@ pw_user(int mode, struct cargs * args) } if (mode == M_PRINT && getarg(args, 'a')) { - int pretty = getarg(args, 'P') != NULL; int v7 = getarg(args, '7') != NULL; SETPWENT(); while ((pwd = GETPWENT()) != NULL) - print_user(pwd, pretty, v7); + print_user(pwd, v7); ENDPWENT(); return EXIT_SUCCESS; } @@ -363,7 +362,6 @@ pw_user(int mode, struct cargs * args) fakeuser.pw_name = a_name ? a_name->val : "nouser"; fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : (uid_t) -1; return print_user(&fakeuser, - getarg(args, 'P') != NULL, getarg(args, '7') != NULL); } if (a_name == NULL) @@ -401,9 +399,7 @@ pw_user(int mode, struct cargs * args) return (delete_user(cnf, pwd, a_name, getarg(args, 'r') != NULL, mode)); else if (mode == M_PRINT) - return print_user(pwd, - getarg(args, 'P') != NULL, - getarg(args, '7') != NULL); + return print_user(pwd, getarg(args, '7') != NULL); /* * The rest is edit code @@ -621,9 +617,7 @@ pw_user(int mode, struct cargs * args) * Special case: -N only displays & exits */ if (conf.dryrun) - return print_user(pwd, - getarg(args, 'P') != NULL, - getarg(args, '7') != NULL); + return print_user(pwd, getarg(args, '7') != NULL); if (mode == M_ADD) { edited = 1; /* Always */ @@ -1167,9 +1161,9 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, } static int -print_user(struct passwd * pwd, int pretty, int v7) +print_user(struct passwd * pwd, int v7) { - if (!pretty) { + if (!conf.pretty) { char *buf; if (!v7) diff --git a/pw/pwupd.h b/pw/pwupd.h index ec9ac30..63aaa64 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -84,6 +84,7 @@ struct pwconf { char rootdir[MAXPATHLEN]; char etcpath[MAXPATHLEN]; bool dryrun; + bool pretty; struct userconf *userconf; }; -- cgit v1.2.3 From 98e6bc31dc6985604ba6aa31a3c58fcb3f077127 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 15:29:58 +0000 Subject: Initialize conf using menset(3) --- pw/pw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 22665e9..6376133 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -131,9 +131,7 @@ main(int argc, char *argv[]) }; relocated = nis = false; - conf.rootdir[0] = '\0'; - conf.dryrun = false; - conf.pretty = false; + memset(&conf, 0, sizeof(conf)); strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); LIST_INIT(&arglist); -- cgit v1.2.3 From 8b4eba30cac45e27a97d4e86a8e8506b0e8dc318 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 15:33:08 +0000 Subject: Handle -7 via gloval pwconf --- pw/pw.c | 3 +++ pw/pw_user.c | 11 +++++------ pw/pwupd.h | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 6376133..c81b5c4 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -215,6 +215,9 @@ main(int argc, char *argv[]) case '?': errx(EX_USAGE, "unknown switch"); break; + case '7': + conf.v7 = true; + break; case 'C': config = optarg; break; diff --git a/pw/pw_user.c b/pw/pw_user.c index bfbde78..0fc7272 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -53,7 +53,7 @@ static char locked_str[] = "*LOCKED*"; static int delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, int delete, int mode); -static int print_user(struct passwd * pwd, int v7); +static int print_user(struct passwd * pwd); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer); static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args); @@ -316,10 +316,9 @@ pw_user(int mode, struct cargs * args) } if (mode == M_PRINT && getarg(args, 'a')) { - int v7 = getarg(args, '7') != NULL; SETPWENT(); while ((pwd = GETPWENT()) != NULL) - print_user(pwd, v7); + print_user(pwd); ENDPWENT(); return EXIT_SUCCESS; } @@ -1161,15 +1160,15 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, } static int -print_user(struct passwd * pwd, int v7) +print_user(struct passwd * pwd) { if (!conf.pretty) { char *buf; - if (!v7) + if (!conf.v7) pwd->pw_passwd = (pwd->pw_passwd == NULL) ? "" : "*"; - buf = v7 ? pw_make_v7(pwd) : pw_make(pwd); + buf = conf.v7 ? pw_make_v7(pwd) : pw_make(pwd); printf("%s\n", buf); free(buf); } else { diff --git a/pw/pwupd.h b/pw/pwupd.h index 63aaa64..573e063 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -85,6 +85,7 @@ struct pwconf { char etcpath[MAXPATHLEN]; bool dryrun; bool pretty; + bool v7; struct userconf *userconf; }; -- cgit v1.2.3 From 8af1e4400ed08ccdd415de9e187cc030f77412fd Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 15:54:57 +0000 Subject: Finish converting -7 to pwconf --- pw/pw_user.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index 0fc7272..0b15c77 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -360,8 +360,7 @@ pw_user(int mode, struct cargs * args) if (mode == M_PRINT && getarg(args, 'F')) { fakeuser.pw_name = a_name ? a_name->val : "nouser"; fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : (uid_t) -1; - return print_user(&fakeuser, - getarg(args, '7') != NULL); + return print_user(&fakeuser); } if (a_name == NULL) errx(EX_NOUSER, "no such uid `%s'", a_uid->val); @@ -398,7 +397,7 @@ pw_user(int mode, struct cargs * args) return (delete_user(cnf, pwd, a_name, getarg(args, 'r') != NULL, mode)); else if (mode == M_PRINT) - return print_user(pwd, getarg(args, '7') != NULL); + return print_user(pwd); /* * The rest is edit code @@ -616,7 +615,7 @@ pw_user(int mode, struct cargs * args) * Special case: -N only displays & exits */ if (conf.dryrun) - return print_user(pwd, getarg(args, '7') != NULL); + return print_user(pwd); if (mode == M_ADD) { edited = 1; /* Always */ -- cgit v1.2.3 From 7d8cc6729f3fcf5fb4c38936179b2c0b9b026130 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 19:03:41 +0000 Subject: Refactor input validation Mutualize code to validate inputs of both 'user' and 'group' command Test that the input name fits into MAXLOGNAME --- pw/pw.c | 49 ++++++++++++++++++++++++++---- pw/pw.h | 4 +-- pw/pw_group.c | 62 ++++++++++++++++---------------------- pw/pw_user.c | 95 +++++++++++++++++++++++------------------------------------ 4 files changed, 108 insertions(+), 102 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index c81b5c4..7274c32 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -99,9 +99,11 @@ main(int argc, char *argv[]) int ch; int mode = -1; int which = -1; + long id = -1; char *config = NULL; struct stat st; - char arg; + const char *errstr; + char arg, *name; bool relocated, nis; static const char *opts[W_NUM][M_NUM] = @@ -124,12 +126,14 @@ main(int argc, char *argv[]) } }; - static int (*funcs[W_NUM]) (int _mode, struct cargs * _args) = + static int (*funcs[W_NUM]) (int _mode, char *_name, long _id, + struct cargs * _args) = { /* Request handlers */ pw_user, pw_group }; + name = NULL; relocated = nis = false; memset(&conf, 0, sizeof(conf)); strlcpy(conf.etcpath, _PATH_PWD, sizeof(conf.etcpath)); @@ -190,9 +194,15 @@ main(int argc, char *argv[]) mode = tmp % M_NUM; } else if (strcmp(argv[1], "help") == 0 && argv[2] == NULL) cmdhelp(mode, which); - else if (which != -1 && mode != -1) - addarg(&arglist, 'n', argv[1]); - else + else if (which != -1 && mode != -1) { + if (strspn(argv[1], "0123456789") == strlen(argv[1])) { + id = strtonum(argv[1], 0, LONG_MAX, &errstr); + if (errstr != NULL) + errx(EX_USAGE, "Bad id '%s': %s", + argv[1], errstr); + } else + name = argv[1]; + } else errx(EX_USAGE, "unknown keyword `%s'", argv[1]); ++argv; --argc; @@ -230,6 +240,30 @@ main(int argc, char *argv[]) case 'Y': nis = true; break; + case 'g': + if (which == 0) { /* for user* */ + addarg(&arglist, 'g', optarg); + break; + } + /* FALLTHROUGH */ + case 'u': + if (strspn(optarg, "0123456789") != strlen(optarg)) + errx(EX_USAGE, "%s expects a number", + which == 1 ? "-g" : "-u" ); + id = strtonum(optarg, 0, LONG_MAX, &errstr); + if (errstr != NULL) + errx(EX_USAGE, "Bad id '%s': %s", optarg, + errstr); + break; + case 'n': + if (strspn(optarg, "0123456789") != strlen(optarg)) { + name = optarg; + break; + } + id = strtonum(optarg, 0, LONG_MAX, &errstr); + if (errstr != NULL) + errx(EX_USAGE, "Bad id '%s': %s", optarg, + errstr); default: addarg(&arglist, ch, optarg); break; @@ -237,6 +271,9 @@ main(int argc, char *argv[]) optarg = NULL; } + if (name != NULL && strlen(name) >= MAXLOGNAME) + errx(EX_USAGE, "name too long: %s", name); + /* * Must be root to attempt an update */ @@ -265,7 +302,7 @@ main(int argc, char *argv[]) */ conf.userconf = read_userconfig(config); - ch = funcs[which] (mode, &arglist); + ch = funcs[which] (mode, name, id, &arglist); /* * If everything went ok, and we've been asked to update diff --git a/pw/pw.h b/pw/pw.h index 9c0aa32..6239004 100644 --- a/pw/pw.h +++ b/pw/pw.h @@ -82,8 +82,8 @@ int write_userconfig(char const * file); struct carg *addarg(struct cargs * _args, int ch, char *argstr); struct carg *getarg(struct cargs * _args, int ch); -int pw_user(int mode, struct cargs * _args); -int pw_group(int mode, struct cargs * _args); +int pw_user(int mode, char *name, long id, struct cargs * _args); +int pw_group(int mode, char *name, long id, struct cargs * _args); char *pw_checkname(char *name, int gecos); int addnispwent(const char *path, struct passwd *pwd); diff --git a/pw/pw_group.c b/pw/pw_group.c index d5d7d52..b06b59e 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -48,12 +48,10 @@ static int print_group(struct group * grp); static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); int -pw_group(int mode, struct cargs * args) +pw_group(int mode, char *name, long id, struct cargs * args) { int rc; struct carg *a_newname = getarg(args, 'l'); - struct carg *a_name = getarg(args, 'n'); - struct carg *a_gid = getarg(args, 'g'); struct carg *arg; struct group *grp = NULL; int grmembers = 0; @@ -68,11 +66,6 @@ pw_group(int mode, struct cargs * args) NULL }; - if (a_gid != NULL) { - if (strspn(a_gid->val, "0123456789") != strlen(a_gid->val)) - errx(EX_USAGE, "-g expects a number"); - } - if (mode == M_LOCK || mode == M_UNLOCK) errx(EX_USAGE, "'lock' command is not available for groups"); @@ -95,67 +88,63 @@ pw_group(int mode, struct cargs * args) ENDGRENT(); return EXIT_SUCCESS; } - if (a_gid == NULL) { - if (a_name == NULL) - errx(EX_DATAERR, "group name or id required"); + if (id < 0 && name == NULL) + errx(EX_DATAERR, "group name or id required"); - if (mode != M_ADD && grp == NULL && isdigit((unsigned char)*a_name->val)) { - (a_gid = a_name)->ch = 'g'; - a_name = NULL; - } - } - grp = (a_name != NULL) ? GETGRNAM(a_name->val) : GETGRGID((gid_t) atoi(a_gid->val)); + grp = (name != NULL) ? GETGRNAM(name) : GETGRGID(id); if (mode == M_UPDATE || mode == M_DELETE || mode == M_PRINT) { - if (a_name == NULL && grp == NULL) /* Try harder */ - grp = GETGRGID(atoi(a_gid->val)); + if (name == NULL && grp == NULL) /* Try harder */ + grp = GETGRGID(id); if (grp == NULL) { if (mode == M_PRINT && getarg(args, 'F')) { char *fmems[1]; fmems[0] = NULL; - fakegroup.gr_name = a_name ? a_name->val : "nogroup"; - fakegroup.gr_gid = a_gid ? (gid_t) atol(a_gid->val) : (gid_t)-1; + fakegroup.gr_name = name ? name : "nogroup"; + fakegroup.gr_gid = (gid_t) id; fakegroup.gr_mem = fmems; return print_group(&fakegroup); } - errx(EX_DATAERR, "unknown group `%s'", a_name ? a_name->val : a_gid->val); + if (name == NULL) + errx(EX_DATAERR, "unknown group `%s'", name); + else + errx(EX_DATAERR, "unknown group `%ld'", id); } - if (a_name == NULL) /* Needed later */ - a_name = addarg(args, 'n', grp->gr_name); + if (name == NULL) /* Needed later */ + name = grp->gr_name; /* * Handle deletions now */ if (mode == M_DELETE) { - gid_t gid = grp->gr_gid; - rc = delgrent(grp); if (rc == -1) - err(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name); + err(EX_IOERR, "group '%s' not available (NIS?)", + name); else if (rc != 0) { err(EX_IOERR, "group update"); } - pw_log(cnf, mode, W_GROUP, "%s(%u) removed", a_name->val, gid); + pw_log(cnf, mode, W_GROUP, "%s(%ld) removed", name, id); return EXIT_SUCCESS; } else if (mode == M_PRINT) return print_group(grp); - if (a_gid) - grp->gr_gid = (gid_t) atoi(a_gid->val); + if (id > 0) + grp->gr_gid = (gid_t) id; if (a_newname != NULL) grp->gr_name = pw_checkname(a_newname->val, 0); } else { - if (a_name == NULL) /* Required */ + if (name == NULL) /* Required */ errx(EX_DATAERR, "group name required"); else if (grp != NULL) /* Exists */ - errx(EX_DATAERR, "group name `%s' already exists", a_name->val); + errx(EX_DATAERR, "group name `%s' already exists", name); extendarray(&members, &grmembers, 200); members[0] = NULL; grp = &fakegroup; - grp->gr_name = pw_checkname(a_name->val, 0); + grp->gr_name = pw_checkname(name, 0); grp->gr_passwd = "*"; grp->gr_gid = gr_gidpolicy(cnf, args); grp->gr_mem = members; @@ -265,7 +254,7 @@ pw_group(int mode, struct cargs * args) grp->gr_name); else err(EX_IOERR, "group update"); - } else if (mode == M_UPDATE && (rc = chggrent(a_name->val, grp)) != 0) { + } else if (mode == M_UPDATE && (rc = chggrent(name, grp)) != 0) { if (rc == -1) errx(EX_IOERR, "group '%s' not available (NIS?)", grp->gr_name); @@ -273,9 +262,10 @@ pw_group(int mode, struct cargs * args) err(EX_IOERR, "group update"); } - arg = a_newname != NULL ? a_newname : a_name; + if (a_newname != NULL) + name = a_newname->val; /* grp may have been invalidated */ - if ((grp = GETGRNAM(arg->val)) == NULL) + if ((grp = GETGRNAM(name)) == NULL) errx(EX_SOFTWARE, "group disappeared during update"); pw_log(cnf, mode, W_GROUP, "%s(%u)", grp->gr_name, grp->gr_gid); diff --git a/pw/pw_user.c b/pw/pw_user.c index 0b15c77..c9093bb 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -52,7 +52,7 @@ static const char rcsid[] = static char locked_str[] = "*LOCKED*"; static int delete_user(struct userconf *cnf, struct passwd *pwd, - struct carg *a_name, int delete, int mode); + char *name, int delete, int mode); static int print_user(struct passwd * pwd); static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer); @@ -119,13 +119,11 @@ create_and_populate_homedir(int mode, struct passwd *pwd) */ int -pw_user(int mode, struct cargs * args) +pw_user(int mode, char *name, long id, struct cargs * args) { int rc, edited = 0; char *p = NULL; char *passtmp; - struct carg *a_name; - struct carg *a_uid; struct carg *arg; struct passwd *pwd = NULL; struct group *grp; @@ -166,7 +164,7 @@ pw_user(int mode, struct cargs * args) if (getarg(args, 'q')) return next; printf("%u:", next); - pw_group(mode, args); + pw_group(mode, name, -1, args); return EXIT_SUCCESS; } @@ -323,29 +321,11 @@ pw_user(int mode, struct cargs * args) return EXIT_SUCCESS; } - if ((a_name = getarg(args, 'n')) != NULL) - pwd = GETPWNAM(pw_checkname(a_name->val, 0)); - a_uid = getarg(args, 'u'); + if (name != NULL) + pwd = GETPWNAM(pw_checkname(name, 0)); - if (a_uid == NULL) { - if (a_name == NULL) - errx(EX_DATAERR, "user name or id required"); - - /* - * Determine whether 'n' switch is name or uid - we don't - * really don't really care which we have, but we need to - * know. - */ - if (mode != M_ADD && pwd == NULL - && strspn(a_name->val, "0123456789") == strlen(a_name->val) - && *a_name->val) { - (a_uid = a_name)->ch = 'u'; - a_name = NULL; - } - } else { - if (strspn(a_uid->val, "0123456789") != strlen(a_uid->val)) - errx(EX_USAGE, "-u expects a number"); - } + if (id < 0 && name == NULL) + errx(EX_DATAERR, "user name or id required"); /* * Update, delete & print require that the user exists @@ -353,22 +333,22 @@ pw_user(int mode, struct cargs * args) 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)); + if (name == NULL && pwd == NULL) /* Try harder */ + pwd = GETPWUID(id); if (pwd == NULL) { if (mode == M_PRINT && getarg(args, 'F')) { - fakeuser.pw_name = a_name ? a_name->val : "nouser"; - fakeuser.pw_uid = a_uid ? (uid_t) atol(a_uid->val) : (uid_t) -1; + fakeuser.pw_name = name ? name : "nouser"; + fakeuser.pw_uid = (uid_t) id; return print_user(&fakeuser); } - if (a_name == NULL) - errx(EX_NOUSER, "no such uid `%s'", a_uid->val); - errx(EX_NOUSER, "no such user `%s'", a_name->val); + if (name == NULL) + errx(EX_NOUSER, "no such uid `%ld'", id); + errx(EX_NOUSER, "no such user `%s'", name); } - if (a_name == NULL) /* May be needed later */ - a_name = addarg(args, 'n', newstr(pwd->pw_name)); + if (name == NULL) + name = pwd->pw_name; /* * The M_LOCK and M_UNLOCK functions simply add or remove @@ -394,7 +374,7 @@ pw_user(int mode, struct cargs * args) pwd->pw_passwd += sizeof(locked_str)-1; edited = 1; } else if (mode == M_DELETE) - return (delete_user(cnf, pwd, a_name, + return (delete_user(cnf, pwd, name, getarg(args, 'r') != NULL, mode)); else if (mode == M_PRINT) return print_user(pwd); @@ -511,16 +491,16 @@ pw_user(int mode, struct cargs * args) * Add code */ - if (a_name == NULL) /* Required */ + if (name == NULL) /* Required */ errx(EX_DATAERR, "login name required"); - else if ((pwd = GETPWNAM(a_name->val)) != NULL) /* Exists */ - errx(EX_DATAERR, "login name `%s' already exists", a_name->val); + else if ((pwd = GETPWNAM(name)) != NULL) /* Exists */ + errx(EX_DATAERR, "login name `%s' already exists", name); /* * Now, set up defaults for a new user */ pwd = &fakeuser; - pwd->pw_name = a_name->val; + pwd->pw_name = name; pwd->pw_class = cnf->default_class ? cnf->default_class : ""; pwd->pw_uid = pw_uidpolicy(cnf, args); pwd->pw_gid = pw_gidpolicy(args, pwd->pw_name, (gid_t) pwd->pw_uid); @@ -635,13 +615,13 @@ pw_user(int mode, struct cargs * args) } } else if (mode == M_UPDATE || mode == M_LOCK || mode == M_UNLOCK) { if (edited) { /* Only updated this if required */ - rc = chgpwent(a_name->val, pwd); + rc = chgpwent(name, pwd); if (rc == -1) errx(EX_IOERR, "user '%s' does not exist (NIS?)", pwd->pw_name); else if (rc != 0) err(EX_IOERR, "passwd file update"); if ( cnf->nispasswd && *cnf->nispasswd=='/') { - rc = chgnispwent(cnf->nispasswd, a_name->val, pwd); + rc = chgnispwent(cnf->nispasswd, name, pwd); if (rc == -1) warn("User '%s' not found in NIS passwd", pwd->pw_name); else @@ -693,16 +673,16 @@ pw_user(int mode, struct cargs * args) /* go get a current version of pwd */ - pwd = GETPWNAM(a_name->val); + pwd = GETPWNAM(name); 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 */ + name = arg->val; /* update new name */ + pwd = GETPWNAM(name); /* refetch renamed rec */ } } if (pwd == NULL) /* can't go on without this */ - errx(EX_NOUSER, "user '%s' disappeared during update", a_name->val); + errx(EX_NOUSER, "user '%s' disappeared during update", name); grp = GETGRGID(pwd->pw_gid); pw_log(cnf, mode, W_USER, "%s(%u):%s(%u):%s:%s:%s", @@ -849,7 +829,6 @@ pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer) char tmp[32]; LIST_INIT(&grpargs); - addarg(&grpargs, 'n', nam); /* * We need to auto-create a group with the user's name. We @@ -866,11 +845,11 @@ pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer) } if (conf.dryrun) { addarg(&grpargs, 'q', NULL); - gid = pw_group(M_NEXT, &grpargs); + gid = pw_group(M_NEXT, nam, -1, &grpargs); } else { - pw_group(M_ADD, &grpargs); + pw_group(M_ADD, nam, -1, &grpargs); if ((grp = GETGRNAM(nam)) != NULL) gid = grp->gr_gid; } @@ -1048,7 +1027,7 @@ pw_password(struct userconf * cnf, struct cargs * args, char const * user) } static int -delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, +delete_user(struct userconf *cnf, struct passwd *pwd, char *name, int delete, int mode) { char file[MAXPATHLEN]; @@ -1097,7 +1076,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, err(EX_IOERR, "passwd update"); if (cnf->nispasswd && *cnf->nispasswd=='/') { - rc = delnispwent(cnf->nispasswd, a_name->val); + rc = delnispwent(cnf->nispasswd, name); if (rc == -1) warnx("WARNING: user '%s' does not exist in NIS passwd", pwd->pw_name); else if (rc != 0) @@ -1105,11 +1084,11 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, /* non-fatal */ } - grp = GETGRNAM(a_name->val); + grp = GETGRNAM(name); if (grp != NULL && (grp->gr_mem == NULL || *grp->gr_mem == NULL) && - strcmp(a_name->val, grname) == 0) - delgrent(GETGRNAM(a_name->val)); + strcmp(name, grname) == 0) + delgrent(GETGRNAM(name)); SETGRENT(); while ((grp = GETGRENT()) != NULL) { int i, j; @@ -1118,7 +1097,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, continue; for (i = 0; grp->gr_mem[i] != NULL; i++) { - if (strcmp(grp->gr_mem[i], a_name->val) != 0) + if (strcmp(grp->gr_mem[i], name) != 0) continue; for (j = i; grp->gr_mem[j] != NULL; j++) @@ -1129,7 +1108,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, } ENDGRENT(); - pw_log(cnf, mode, W_USER, "%s(%u) account removed", a_name->val, uid); + pw_log(cnf, mode, W_USER, "%s(%u) account removed", name, uid); if (!PWALTDIR()) { /* @@ -1150,7 +1129,7 @@ delete_user(struct userconf *cnf, struct passwd *pwd, struct carg *a_name, stat(home, &st) != -1) { rm_r(home, uid); pw_log(cnf, mode, W_USER, "%s(%u) home '%s' %sremoved", - a_name->val, uid, home, + name, uid, home, stat(home, &st) == -1 ? "" : "not completely "); } } -- cgit v1.2.3 From 34211cbde959d55fb8e6b818365341d0193e7253 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 19:33:25 +0000 Subject: In case of rename validate the length of the new name Check early that the new name fits MAXLOGNAME and store it in pwconf --- pw/pw.c | 5 +++++ pw/pw_group.c | 9 ++++----- pw/pw_user.c | 8 ++++---- pw/pwupd.h | 1 + 4 files changed, 14 insertions(+), 9 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index 7274c32..ae030ec 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -234,6 +234,11 @@ main(int argc, char *argv[]) case 'N': conf.dryrun = true; break; + case 'l': + if (strlen(optarg) >= MAXLOGNAME) + errx(EX_USAGE, "new name too long: %s", optarg); + conf.newname = optarg; + break; case 'P': conf.pretty = true; break; diff --git a/pw/pw_group.c b/pw/pw_group.c index b06b59e..f95d263 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -51,7 +51,6 @@ int pw_group(int mode, char *name, long id, struct cargs * args) { int rc; - struct carg *a_newname = getarg(args, 'l'); struct carg *arg; struct group *grp = NULL; int grmembers = 0; @@ -133,8 +132,8 @@ pw_group(int mode, char *name, long id, struct cargs * args) if (id > 0) grp->gr_gid = (gid_t) id; - if (a_newname != NULL) - grp->gr_name = pw_checkname(a_newname->val, 0); + if (conf.newname != NULL) + grp->gr_name = pw_checkname(conf.newname, 0); } else { if (name == NULL) /* Required */ errx(EX_DATAERR, "group name required"); @@ -262,8 +261,8 @@ pw_group(int mode, char *name, long id, struct cargs * args) err(EX_IOERR, "group update"); } - if (a_newname != NULL) - name = a_newname->val; + if (conf.newname != NULL) + name = conf.newname; /* grp may have been invalidated */ if ((grp = GETGRNAM(name)) == NULL) errx(EX_SOFTWARE, "group disappeared during update"); diff --git a/pw/pw_user.c b/pw/pw_user.c index c9093bb..6b3a266 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -382,10 +382,10 @@ pw_user(int mode, char *name, long id, struct cargs * args) /* * The rest is edit code */ - if ((arg = getarg(args, 'l')) != NULL) { + if (conf.newname != NULL) { if (strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "can't rename `root' account"); - pwd->pw_name = pw_checkname(arg->val, 0); + pwd->pw_name = pw_checkname(conf.newname, 0); edited = 1; } @@ -676,8 +676,8 @@ pw_user(int mode, char *name, long id, struct cargs * args) pwd = GETPWNAM(name); if (pwd == NULL) { /* This will fail when we rename, so special case that */ - if (mode == M_UPDATE && (arg = getarg(args, 'l')) != NULL) { - name = arg->val; /* update new name */ + if (mode == M_UPDATE && conf.newname != NULL) { + name = conf.newname; /* update new name */ pwd = GETPWNAM(name); /* refetch renamed rec */ } } diff --git a/pw/pwupd.h b/pw/pwupd.h index 573e063..ebf78dc 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -83,6 +83,7 @@ struct userconf { struct pwconf { char rootdir[MAXPATHLEN]; char etcpath[MAXPATHLEN]; + char *newname; bool dryrun; bool pretty; bool v7; -- cgit v1.2.3 From e3bd6749869f3f1649662b39609bbea8d2141354 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 19:39:06 +0000 Subject: Remove uneeded code (already done by pw_make_v7) --- pw/pw_user.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'pw') diff --git a/pw/pw_user.c b/pw/pw_user.c index 6b3a266..99d8129 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -1143,9 +1143,6 @@ print_user(struct passwd * pwd) if (!conf.pretty) { char *buf; - if (!conf.v7) - pwd->pw_passwd = (pwd->pw_passwd == NULL) ? "" : "*"; - buf = conf.v7 ? pw_make_v7(pwd) : pw_make(pwd); printf("%s\n", buf); free(buf); -- cgit v1.2.3 From 068c2f64c08c71d084c16d066a0fb3802e26b7a9 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 19:59:01 +0000 Subject: Fix duplicate checking --- pw/pw.c | 4 ++++ pw/pw_group.c | 15 +++++++-------- pw/pw_user.c | 19 +++++++++---------- pw/pwupd.h | 1 + 4 files changed, 21 insertions(+), 18 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index ae030ec..a311572 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -269,6 +269,10 @@ main(int argc, char *argv[]) if (errstr != NULL) errx(EX_USAGE, "Bad id '%s': %s", optarg, errstr); + break; + case 'o': + conf.checkduplicate = true; + break; default: addarg(&arglist, ch, optarg); break; diff --git a/pw/pw_group.c b/pw/pw_group.c index f95d263..b9cce0d 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -45,7 +45,7 @@ static struct passwd *lookup_pwent(const char *user); static void delete_members(char ***members, int *grmembers, int *i, struct carg *arg, struct group *grp); static int print_group(struct group * grp); -static gid_t gr_gidpolicy(struct userconf * cnf, struct cargs * args); +static gid_t gr_gidpolicy(struct userconf * cnf, long id); int pw_group(int mode, char *name, long id, struct cargs * args) @@ -73,7 +73,7 @@ pw_group(int mode, char *name, long id, struct cargs * args) * next gid to stdout */ if (mode == M_NEXT) { - gid_t next = gr_gidpolicy(cnf, args); + gid_t next = gr_gidpolicy(cnf, id); if (getarg(args, 'q')) return next; printf("%u\n", next); @@ -145,7 +145,7 @@ pw_group(int mode, char *name, long id, struct cargs * args) grp = &fakegroup; grp->gr_name = pw_checkname(name, 0); grp->gr_passwd = "*"; - grp->gr_gid = gr_gidpolicy(cnf, args); + grp->gr_gid = gr_gidpolicy(cnf, id); grp->gr_mem = members; } @@ -336,19 +336,18 @@ delete_members(char ***members, int *grmembers, int *i, struct carg *arg, static gid_t -gr_gidpolicy(struct userconf * cnf, struct cargs * args) +gr_gidpolicy(struct userconf * cnf, long id) { struct group *grp; gid_t gid = (gid_t) - 1; - struct carg *a_gid = getarg(args, 'g'); /* * Check the given gid, if any */ - if (a_gid != NULL) { - gid = (gid_t) atol(a_gid->val); + if (id > 0) { + gid = (gid_t) id; - if ((grp = GETGRGID(gid)) != NULL && getarg(args, 'o') == NULL) + if ((grp = GETGRGID(gid)) != NULL && conf.checkduplicate) errx(EX_DATAERR, "gid `%u' has already been allocated", grp->gr_gid); } else { struct bitmap bm; diff --git a/pw/pw_user.c b/pw/pw_user.c index 99d8129..c567e68 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -54,7 +54,7 @@ static char locked_str[] = "*LOCKED*"; static int delete_user(struct userconf *cnf, struct passwd *pwd, char *name, int delete, int mode); static int print_user(struct passwd * pwd); -static uid_t pw_uidpolicy(struct userconf * cnf, struct cargs * args); +static uid_t pw_uidpolicy(struct userconf * cnf, long id); static uid_t pw_gidpolicy(struct cargs * args, char *nam, gid_t prefer); static time_t pw_pwdpolicy(struct userconf * cnf, struct cargs * args); static time_t pw_exppolicy(struct userconf * cnf, struct cargs * args); @@ -160,7 +160,7 @@ pw_user(int mode, char *name, long id, struct cargs * args) */ if (mode == M_NEXT) { - uid_t next = pw_uidpolicy(cnf, args); + uid_t next = pw_uidpolicy(cnf, id); if (getarg(args, 'q')) return next; printf("%u:", next); @@ -389,8 +389,8 @@ pw_user(int mode, char *name, long id, struct cargs * args) edited = 1; } - if ((arg = getarg(args, 'u')) != NULL && isdigit((unsigned char)*arg->val)) { - pwd->pw_uid = (uid_t) atol(arg->val); + if (id > 0 && isdigit((unsigned char)*arg->val)) { + pwd->pw_uid = (uid_t)id; edited = 1; if (pwd->pw_uid != 0 && strcmp(pwd->pw_name, "root") == 0) errx(EX_DATAERR, "can't change uid of `root' account"); @@ -502,7 +502,7 @@ pw_user(int mode, char *name, long id, struct cargs * args) pwd = &fakeuser; pwd->pw_name = name; pwd->pw_class = cnf->default_class ? cnf->default_class : ""; - pwd->pw_uid = pw_uidpolicy(cnf, args); + pwd->pw_uid = pw_uidpolicy(cnf, id); pwd->pw_gid = pw_gidpolicy(args, pwd->pw_name, (gid_t) pwd->pw_uid); pwd->pw_change = pw_pwdpolicy(cnf, args); pwd->pw_expire = pw_exppolicy(cnf, args); @@ -741,19 +741,18 @@ pw_user(int mode, char *name, long id, struct cargs * args) static uid_t -pw_uidpolicy(struct userconf * cnf, struct cargs * args) +pw_uidpolicy(struct userconf * cnf, long id) { struct passwd *pwd; uid_t uid = (uid_t) - 1; - struct carg *a_uid = getarg(args, 'u'); /* * Check the given uid, if any */ - if (a_uid != NULL) { - uid = (uid_t) atol(a_uid->val); + if (id > 0) { + uid = (uid_t) id; - if ((pwd = GETPWUID(uid)) != NULL && getarg(args, 'o') == NULL) + if ((pwd = GETPWUID(uid)) != NULL && conf.checkduplicate) errx(EX_DATAERR, "uid `%u' has already been allocated", pwd->pw_uid); } else { struct bitmap bm; diff --git a/pw/pwupd.h b/pw/pwupd.h index ebf78dc..a67e6db 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -87,6 +87,7 @@ struct pwconf { bool dryrun; bool pretty; bool v7; + bool checkduplicate; struct userconf *userconf; }; -- cgit v1.2.3 From 5b291029a9ed6f6ac19b03b29501179559dc07c3 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 20:44:06 +0000 Subject: Fix generating configuration file --- pw/pw.c | 3 ++- pw/pw_user.c | 7 +++---- pw/pwupd.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index a311572..d8d8c03 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -229,7 +229,8 @@ main(int argc, char *argv[]) conf.v7 = true; break; case 'C': - config = optarg; + conf.config = optarg; + config = conf.config; break; case 'N': conf.dryrun = true; diff --git a/pw/pw_user.c b/pw/pw_user.c index c567e68..c3b2751 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -292,7 +292,7 @@ pw_user(int mode, char *name, long id, struct cargs * args) if ((arg = getarg(args, 'w')) != NULL) cnf->default_password = boolean_val(arg->val, cnf->default_password); if (mode == M_ADD && getarg(args, 'D')) { - if (getarg(args, 'n') != NULL) + if (name != NULL) errx(EX_DATAERR, "can't combine `-D' with `-n name'"); if ((arg = getarg(args, 'u')) != NULL && (p = strtok(arg->val, ", \t")) != NULL) { if ((cnf->min_uid = (uid_t) atoi(p)) == 0) @@ -307,9 +307,8 @@ pw_user(int mode, char *name, long id, struct cargs * args) cnf->max_gid = 32000; } - arg = getarg(args, 'C'); - if (write_userconfig(arg ? arg->val : NULL)) - return EXIT_SUCCESS; + if (write_userconfig(conf.config)) + return (EXIT_SUCCESS); err(EX_IOERR, "config udpate"); } diff --git a/pw/pwupd.h b/pw/pwupd.h index a67e6db..8f46e7d 100644 --- a/pw/pwupd.h +++ b/pw/pwupd.h @@ -84,6 +84,7 @@ struct pwconf { char rootdir[MAXPATHLEN]; char etcpath[MAXPATHLEN]; char *newname; + char *config; bool dryrun; bool pretty; bool v7; -- cgit v1.2.3 From 50b3230917e6e4c6538d6d0f01fed543b8be5efc Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 20:59:59 +0000 Subject: Fix setting uid/gid min/max via pw --- pw/pw.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index d8d8c03..30fb55b 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -251,11 +251,20 @@ main(int argc, char *argv[]) addarg(&arglist, 'g', optarg); break; } - /* FALLTHROUGH */ - case 'u': if (strspn(optarg, "0123456789") != strlen(optarg)) - errx(EX_USAGE, "%s expects a number", - which == 1 ? "-g" : "-u" ); + errx(EX_USAGE, "-g expects a number"); + id = strtonum(optarg, 0, LONG_MAX, &errstr); + if (errstr != NULL) + errx(EX_USAGE, "Bad id '%s': %s", optarg, + errstr); + break; + case 'u': + if (strspn(optarg, "0123456789,") != strlen(optarg)) + errx(EX_USAGE, "-u expects a number"); + if (strchr(optarg, ',') != NULL) { + addarg(&arglist, 'u', optarg); + break; + } id = strtonum(optarg, 0, LONG_MAX, &errstr); if (errstr != NULL) errx(EX_USAGE, "Bad id '%s': %s", optarg, -- cgit v1.2.3 From 44a564bd4185ea1e172a8f310d13f71f24abf73f Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 21:57:20 +0000 Subject: Remove '-q' support for pw [user|group] next the intent of -q in this command is to return as exit status the value of the next group/user id, which does not make sense given exit status are limited to values between 0 and 255. --- pw/pw.8 | 4 +--- pw/pw.c | 8 +++----- pw/pw_group.c | 7 ++----- pw/pw_user.c | 10 +++------- 4 files changed, 9 insertions(+), 20 deletions(-) (limited to 'pw') diff --git a/pw/pw.8 b/pw/pw.8 index 9074313..1c1f740 100644 --- a/pw/pw.8 +++ b/pw/pw.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 3, 2015 +.Dd June 7, 2015 .Dt PW 8 .Os .Sh NAME @@ -128,7 +128,6 @@ .Op Fl V Ar etcdir .Ar usernext .Op Fl C Ar config -.Op Fl q .Nm .Op Fl R Ar rootdir .Op Fl V Ar etcdir @@ -184,7 +183,6 @@ .Op Fl V Ar etcdir .Ar groupnext .Op Fl C Ar config -.Op Fl q .Nm .Op Fl R Ar rootdir .Op Fl V Ar etcdir diff --git a/pw/pw.c b/pw/pw.c index 30fb55b..d75557e 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -113,7 +113,7 @@ main(int argc, char *argv[]) "R:V:C:qn:u:rY", "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY", "R:V:C:qn:u:FPa7", - "R:V:C:q", + "R:V:C", "R:V:C:q", "R:V:C:q" }, @@ -122,7 +122,7 @@ main(int argc, char *argv[]) "R:V:C:qn:g:Y", "R:V:C:qn:d:g:l:h:H:FM:m:NPY", "R:V:C:qn:g:FPa", - "R:V:C:q" + "R:V:C" } }; @@ -469,8 +469,7 @@ cmdhelp(int mode, int which) "usage: pw usernext [switches]\n" "\t-V etcdir alternate /etc location\n" "\t-R rootir alternate root directory\n" - "\t-C config configuration file\n" - "\t-q quiet operation\n", + "\t-C config configuration file\n", "usage pw: lock [switches]\n" "\t-V etcdir alternate /etc locations\n" "\t-C config configuration file\n" @@ -524,7 +523,6 @@ cmdhelp(int mode, int which) "\t-V etcdir alternate /etc location\n" "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" - "\t-q quiet operation\n" } }; diff --git a/pw/pw_group.c b/pw/pw_group.c index b9cce0d..e504a12 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -73,11 +73,8 @@ pw_group(int mode, char *name, long id, struct cargs * args) * next gid to stdout */ if (mode == M_NEXT) { - gid_t next = gr_gidpolicy(cnf, id); - if (getarg(args, 'q')) - return next; - printf("%u\n", next); - return EXIT_SUCCESS; + printf("%u\n", gr_gidpolicy(cnd, id)); + return (EXIT_SUCCESS); } if (mode == M_PRINT && getarg(args, 'a')) { diff --git a/pw/pw_user.c b/pw/pw_user.c index c3b2751..ea3cb3d 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -158,14 +158,10 @@ pw_user(int mode, char *name, long id, struct cargs * args) * With M_NEXT, we only need to return the * next uid to stdout */ - if (mode == M_NEXT) - { - uid_t next = pw_uidpolicy(cnf, id); - if (getarg(args, 'q')) - return next; - printf("%u:", next); + if (mode == M_NEXT) { + printf("%u:", pw_uidpolicy(cnf, id)); pw_group(mode, name, -1, args); - return EXIT_SUCCESS; + return (EXIT_SUCCESS); } /* -- cgit v1.2.3 From 8cf9c51c20f43a1cafc48f42d29666c58cdfa781 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 7 Jun 2015 21:59:43 +0000 Subject: Fix mistakes than came along with r284139 --- pw/pw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pw.c b/pw/pw.c index d75557e..b21f6c0 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -113,7 +113,7 @@ main(int argc, char *argv[]) "R:V:C:qn:u:rY", "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY", "R:V:C:qn:u:FPa7", - "R:V:C", + "R:V:C:", "R:V:C:q", "R:V:C:q" }, @@ -122,7 +122,7 @@ main(int argc, char *argv[]) "R:V:C:qn:g:Y", "R:V:C:qn:d:g:l:h:H:FM:m:NPY", "R:V:C:qn:g:FPa", - "R:V:C" + "R:V:C:" } }; -- cgit v1.2.3 From 1384cb87b1c4c46b04a04d39617eb11537a371e5 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Mon, 8 Jun 2015 05:06:17 +0000 Subject: Fix typo --- pw/pw_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'pw') diff --git a/pw/pw_group.c b/pw/pw_group.c index e504a12..daa121d 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -73,7 +73,7 @@ pw_group(int mode, char *name, long id, struct cargs * args) * next gid to stdout */ if (mode == M_NEXT) { - printf("%u\n", gr_gidpolicy(cnd, id)); + printf("%u\n", gr_gidpolicy(cnf, id)); return (EXIT_SUCCESS); } -- cgit v1.2.3 From 07d47dbbf964e186685045cb504935dd9be45792 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Mon, 8 Jun 2015 05:27:34 +0000 Subject: backout remove of -q option for pw [user|group] next While the return code is broken, some corner case usage depends on the functionnality, so backout until we get better regression tests covering those corner case usage. --- pw/pw.8 | 4 +++- pw/pw.c | 8 +++++--- pw/pw_group.c | 7 +++++-- pw/pw_user.c | 10 +++++++--- 4 files changed, 20 insertions(+), 9 deletions(-) (limited to 'pw') diff --git a/pw/pw.8 b/pw/pw.8 index 1c1f740..9074313 100644 --- a/pw/pw.8 +++ b/pw/pw.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 7, 2015 +.Dd June 3, 2015 .Dt PW 8 .Os .Sh NAME @@ -128,6 +128,7 @@ .Op Fl V Ar etcdir .Ar usernext .Op Fl C Ar config +.Op Fl q .Nm .Op Fl R Ar rootdir .Op Fl V Ar etcdir @@ -183,6 +184,7 @@ .Op Fl V Ar etcdir .Ar groupnext .Op Fl C Ar config +.Op Fl q .Nm .Op Fl R Ar rootdir .Op Fl V Ar etcdir diff --git a/pw/pw.c b/pw/pw.c index b21f6c0..30fb55b 100644 --- a/pw/pw.c +++ b/pw/pw.c @@ -113,7 +113,7 @@ main(int argc, char *argv[]) "R:V:C:qn:u:rY", "R:V:C:qn:u:c:d:e:p:g:G:mM:l:k:s:w:L:h:H:FNPY", "R:V:C:qn:u:FPa7", - "R:V:C:", + "R:V:C:q", "R:V:C:q", "R:V:C:q" }, @@ -122,7 +122,7 @@ main(int argc, char *argv[]) "R:V:C:qn:g:Y", "R:V:C:qn:d:g:l:h:H:FM:m:NPY", "R:V:C:qn:g:FPa", - "R:V:C:" + "R:V:C:q" } }; @@ -469,7 +469,8 @@ cmdhelp(int mode, int which) "usage: pw usernext [switches]\n" "\t-V etcdir alternate /etc location\n" "\t-R rootir alternate root directory\n" - "\t-C config configuration file\n", + "\t-C config configuration file\n" + "\t-q quiet operation\n", "usage pw: lock [switches]\n" "\t-V etcdir alternate /etc locations\n" "\t-C config configuration file\n" @@ -523,6 +524,7 @@ cmdhelp(int mode, int which) "\t-V etcdir alternate /etc location\n" "\t-R rootir alternate root directory\n" "\t-C config configuration file\n" + "\t-q quiet operation\n" } }; diff --git a/pw/pw_group.c b/pw/pw_group.c index daa121d..b9cce0d 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -73,8 +73,11 @@ pw_group(int mode, char *name, long id, struct cargs * args) * next gid to stdout */ if (mode == M_NEXT) { - printf("%u\n", gr_gidpolicy(cnf, id)); - return (EXIT_SUCCESS); + gid_t next = gr_gidpolicy(cnf, id); + if (getarg(args, 'q')) + return next; + printf("%u\n", next); + return EXIT_SUCCESS; } if (mode == M_PRINT && getarg(args, 'a')) { diff --git a/pw/pw_user.c b/pw/pw_user.c index ea3cb3d..c3b2751 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -158,10 +158,14 @@ pw_user(int mode, char *name, long id, struct cargs * args) * With M_NEXT, we only need to return the * next uid to stdout */ - if (mode == M_NEXT) { - printf("%u:", pw_uidpolicy(cnf, id)); + if (mode == M_NEXT) + { + uid_t next = pw_uidpolicy(cnf, id); + if (getarg(args, 'q')) + return next; + printf("%u:", next); pw_group(mode, name, -1, args); - return (EXIT_SUCCESS); + return EXIT_SUCCESS; } /* -- cgit v1.2.3 From 899bd5d0a18bee6a94dc840d5a457da6484670ed Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Sun, 14 Jun 2015 21:50:38 +0000 Subject: Change the documentation to reflect where the -V option should be used Suggested by: kientzle --- pw/pw.8 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'pw') diff --git a/pw/pw.8 b/pw/pw.8 index 9074313..c29a8a9 100644 --- a/pw/pw.8 +++ b/pw/pw.8 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd June 3, 2015 +.Dd June 14, 2015 .Dt PW 8 .Os .Sh NAME @@ -278,7 +278,7 @@ flag may be used to override this behaviour. As an exception to the general rule where options must follow the operation type, the .Fl V -flag may be used on the command line before the operation keyword. +flag must be used on the command line before the operation keyword. .It Fl C Ar config By default, .Nm -- cgit v1.2.3