From ae5c4633974707111deaccca4fce48ed57a8709a Mon Sep 17 00:00:00 2001 From: davidn Date: Sat, 21 Dec 1996 15:35:45 +0000 Subject: 1) 200 users per group limitation removed and pw will handle lines of any length in /etc/group. 2) Fixed bug with usermod -d not updating user's home directory. 3) Minor formatting display changes/fixes with *show -P. --- usr.sbin/pw/edgroup.c | 234 ++++++++++++++++++++++++-------------------- usr.sbin/pw/fileupd.c | 61 +++++++++--- usr.sbin/pw/grupd.c | 66 +++++++++---- usr.sbin/pw/pw.h | 5 +- usr.sbin/pw/pw_conf.c | 256 +++++++++++++++++++++++++++---------------------- usr.sbin/pw/pw_group.c | 45 ++++++--- usr.sbin/pw/pw_user.c | 79 ++++++++++++--- usr.sbin/pw/pwupd.c | 4 +- usr.sbin/pw/pwupd.h | 12 ++- 9 files changed, 472 insertions(+), 290 deletions(-) (limited to 'usr.sbin/pw') diff --git a/usr.sbin/pw/edgroup.c b/usr.sbin/pw/edgroup.c index 34a22d1..c7b379c 100644 --- a/usr.sbin/pw/edgroup.c +++ b/usr.sbin/pw/edgroup.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: edgroup.c,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ + * $Id: edgroup.c,v 1.1.1.2 1996/12/10 23:58:54 joerg Exp $ */ #include @@ -47,7 +47,7 @@ isingroup(char const * name, char **mem) { int i; - for (i = 0; i < MAXGROUPS && mem[i] != NULL; i++) + for (i = 0; mem[i] != NULL; i++) if (strcmp(name, mem[i]) == 0) return i; return -1; @@ -76,119 +76,143 @@ editgroups(char *name, char **groups) if ((outfp = fdopen(outfd, "w+")) == NULL) close(outfd); else { - char line[MAXPWLINE]; - char outl[MAXPWLINE]; - - while (fgets(line, sizeof(line), infp) != NULL) { - char *p = strchr(line, '\n'); - - if (p == NULL) { /* Line too long */ - int ch; - - fputs(line, outfp); - while ((ch = fgetc(infp)) != EOF) { - fputc(ch, outfp); - if (ch == '\n') - break; - } - continue; - } - if (*line == '#') - strcpy(outl, line); - else if (*line == '\n') - *outl = '\0'; - else { - int i, - mno = 0; - char *cp = line; - char const *sep = ":\n"; - struct group grp; - char *mems[MAXGROUPS]; - - memset(&grp, 0, sizeof grp); - grp.gr_mem = mems; - for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) { - switch (i) { - case 0: /* Group name */ - grp.gr_name = p; - break; - case 1: /* Group password */ - grp.gr_passwd = p; - break; - case 2: /* Group id */ - grp.gr_gid = atoi(p); - break; - case 3: /* Member list */ - cp = p; - sep = ",\n"; - break; - default: /* Individual members */ - if (mno < MAXGROUPS && *p) - mems[mno++] = p; - break; + int linelen = PWBUFSZ; + int outlen = PWBUFSZ; + int memlen = 200; /* Arbitrary */ + char *line = malloc(linelen); + char *outl = malloc(outlen); + char **mems = malloc(memlen * sizeof(char *)); + int namlen = strlen(name); + + if (line == NULL || outl == NULL || mems == NULL) { + mem_abort: + rc = 0; + } else { + while (fgets(line, linelen, infp) != NULL) { + char *p; + int l; + + while ((p = strchr(line, '\n')) == NULL) + { + if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) { + goto mem_abort; } + l = strlen(line); + if (fgets(line + l, linelen - l, infp) == NULL) + break; /* No newline terminator on last line */ } - if (i < 2) /* Bail out - - * insufficient fields */ - continue; - - for (i = mno; i < MAXGROUPS; i++) - mems[i] = NULL; - - /* - * Delete from group, or add to group? - */ - if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */ - int idx; + l = strlen(line) + namlen + 1; + if (extendline(&outl, &outlen, l) == -1) { + goto mem_abort; + } + if (*line == '#') + strcpy(outl, line); + else if (*line == '\n') + *outl = '\0'; + else { + int i, + mno = 0; + char *cp = line; + char const *sep = ":\n"; + struct group grp; + + memset(&grp, 0, sizeof grp); + for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) { + switch (i) { + case 0: /* Group name */ + grp.gr_name = p; + break; + case 1: /* Group password */ + grp.gr_passwd = p; + break; + case 2: /* Group id */ + grp.gr_gid = atoi(p); + break; + case 3: /* Member list */ + cp = p; + sep = ",\n"; + break; + default: /* Individual members */ + if (*p) { + if (extendarray(&mems, &memlen, mno + 2) == -1) { + goto mem_abort; + } + mems[mno++] = p; + } + break; + } + } + if (i < 2) /* Bail out - insufficient fields */ + continue; - while ((idx = isingroup(name, mems)) != -1) { - for (i = idx; i < (MAXGROUPS - 1); i++) - mems[i] = mems[i + 1]; + grp.gr_mem = mems; + for (i = mno; i < memlen; i++) mems[i] = NULL; - --mno; - } /* - * Special case - deleting user and group may be user's own + * Delete from group, or add to group? */ - if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) { /* First, make _sure_ we - * don't have other - * members */ - struct passwd *pwd; - - setpwent(); - while ((pwd = getpwent()) != NULL && pwd->pw_gid != grp.gr_gid); - endpwent(); - if (pwd == NULL) /* No members at all */ - continue; /* Drop the group */ + if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */ + int idx; + + while ((idx = isingroup(name, mems)) != -1) { + for (i = idx; i < (memlen - 1); i++) + mems[i] = mems[i + 1]; + mems[i] = NULL; + --mno; + } + /* + * Special case - deleting user and group may be user's own + */ + if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) { + /* + * First, make _sure_ we don't have other members + */ + struct passwd *pwd; + + setpwent(); + while ((pwd = getpwent()) != NULL && pwd->pw_gid != grp.gr_gid); + endpwent(); + if (pwd == NULL) /* No members at all */ + continue; /* Drop the group */ + } + } else if (isingroup(name, mems) == -1) { + if (extendarray(&mems, &memlen, mno + 2) == -1) { + goto mem_abort; + } + grp.gr_mem = mems; /* May have realloced() */ + mems[mno++] = name; + mems[mno ] = NULL; } - } else if (isingroup(name, mems) == -1) - mems[mno++] = name; - fmtgrentry(outl, &grp, PWF_GROUP); + fmtgrentry(&outl, &outlen, &grp, PWF_GROUP); + } + fputs(outl, outfp); + } + if (fflush(outfp) != EOF) { + rc = 1; + + /* + * Copy data back into the original file and truncate + */ + rewind(infp); + rewind(outfp); + while (fgets(outl, outlen, outfp) != NULL) + fputs(outl, infp); + + /* + * This is a gross hack, but we may have corrupted the + * original file. Unfortunately, it will lose preservation + * of the inode. + */ + if (fflush(infp) == EOF || ferror(infp)) + rc = rename(grouptmp, groupfile) == 0; + else + ftruncate(infd, ftell(infp)); } - fputs(outl, outfp); - } - if (fflush(outfp) != EOF) { - rc = 1; - - /* - * Copy data back into the original file and truncate - */ - rewind(infp); - rewind(outfp); - while (fgets(line, sizeof(line), outfp) != NULL) - fputs(line, infp); - - /* - * This is a gross hack, but we may have corrupted the - * original file. Unfortunately, it will lose preservation - * of the inode. - */ - if (fflush(infp) == EOF || ferror(infp)) - rc = rename(grouptmp, groupfile) == 0; - else - ftruncate(infd, ftell(infp)); } + free(mems); + free(outl); + free(line); fclose(outfp); } remove(grouptmp); diff --git a/usr.sbin/pw/fileupd.c b/usr.sbin/pw/fileupd.c index 0abaac6..e49e407 100644 --- a/usr.sbin/pw/fileupd.c +++ b/usr.sbin/pw/fileupd.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: fileupd.c,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ + * $Id: fileupd.c,v 1.1.1.2 1996/12/10 23:58:55 joerg Exp $ */ #include @@ -39,6 +39,33 @@ #include "pwupd.h" int +extendline(char **buf, int * buflen, int needed) +{ + if (needed > *buflen) { + char *tmp = realloc(*buf, needed); + if (tmp == NULL) + return -1; + *buf = tmp; + *buflen = needed; + } + return *buflen; +} + +int +extendarray(char ***buf, int * buflen, int needed) +{ + if (needed > *buflen) { + char **tmp = realloc(*buf, needed * sizeof(char *)); + if (tmp == NULL) + return -1; + *buf = tmp; + *buflen = needed; + } + return *buflen; +} + + +int fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode) { int rc = 0; @@ -67,21 +94,28 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const close(outfd); else { int updated = UPD_CREATE; - char line[2048]; + int linesize = PWBUFSZ; + char *line = malloc(linesize); - while (fgets(line, sizeof(line), infp) != NULL) { + nextline: + while (fgets(line, linesize, infp) != NULL) { char *p = strchr(line, '\n'); - if (p == NULL) { /* Line too long */ - int ch; - - fputs(line, outfp); - while ((ch = fgetc(infp)) != EOF) { - fputc(ch, outfp); - if (ch == '\n') - break; + while ((p = strchr(line, '\n')) == NULL) { + int l; + if (extendline(&line, &linesize, linesize + PWBUFSZ) == -1) { + int ch; + fputs(line, outfp); + while ((ch = fgetc(infp)) != EOF) { + fputc(ch, outfp); + if (ch == '\n') + break; + } + goto nextline; } - continue; + l = strlen(line); + if (fgets(line + l, linesize - l, infp) == NULL) + break; } if (*line != '#' && *line != '\n') { if (!updated && strncmp(line, prefix, pfxlen) == 0) { @@ -127,7 +161,7 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const */ rewind(infp); rewind(outfp); - while (fgets(line, sizeof(line), outfp) != NULL) + while (fgets(line, linesize, outfp) != NULL) fputs(line, infp); /* @@ -141,6 +175,7 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const ftruncate(infd, ftell(infp)); } } + free(line); fclose(outfp); } remove(file); diff --git a/usr.sbin/pw/grupd.c b/usr.sbin/pw/grupd.c index 784dbe5..725cf09 100644 --- a/usr.sbin/pw/grupd.c +++ b/usr.sbin/pw/grupd.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: grupd.c,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ + * $Id: grupd.c,v 1.1.1.2 1996/12/10 23:58:56 joerg Exp $ */ #include @@ -38,30 +38,51 @@ #include "pwupd.h" int -fmtgrentry(char *buf, struct group * grp, int type) +fmtgrentry(char **buf, int * buflen, struct group * grp, int type) { int i, l; - if (type == PWF_STANDARD) - l = sprintf(buf, "%s:*:%ld:", grp->gr_name, (long) grp->gr_gid); - else - l = sprintf(buf, "%s:%s:%ld:", grp->gr_name, grp->gr_passwd, (long) grp->gr_gid); - /* - * Now, list members + * Since a group line is of arbitrary length, + * we need to calculate up-front just how long + * it will need to be... */ - for (i = 0; i < 200 && grp->gr_mem[i]; i++) - l += sprintf(buf + l, "%s%s", i ? "," : "", grp->gr_mem[i]); - buf[l++] = '\n'; - buf[l] = '\0'; + /* groupname : password : gid : */ + l = strlen(grp->gr_name) + 1 + strlen(grp->gr_passwd) + 1 + 5 + 1; + /* group members + comma separator */ + for (i = 0; grp->gr_mem[i] != NULL; i++) { + l += strlen(grp->gr_mem[i]) + 1; + } + l += 2; /* For newline & NUL */ + if (extendline(buf, buflen, l) == -1) + l = -1; + else{ + /* + * Now we can safely format + */ + if (type == PWF_STANDARD) + l = sprintf(*buf, "%s:*:%ld:", grp->gr_name, (long) grp->gr_gid); + else + l = sprintf(*buf, "%s:%s:%ld:", grp->gr_name, grp->gr_passwd, (long) grp->gr_gid); + + /* + * List members + */ + for (i = 0; grp->gr_mem[i] != NULL; i++) { + l += sprintf(*buf + l, "%s%s", i ? "," : "", grp->gr_mem[i]); + } + + (*buf)[l++] = '\n'; + (*buf)[l] = '\0'; + } return l; } int -fmtgrent(char *buf, struct group * grp) +fmtgrent(char **buf, int * buflen, struct group * grp) { - return fmtgrentry(buf, grp, PWF_STANDARD); + return fmtgrentry(buf, buflen, grp, PWF_STANDARD); } @@ -69,20 +90,23 @@ static int gr_update(struct group * grp, char const * group, int mode) { int l; - char pfx[32]; - char grbuf[MAXPWLINE]; + char pfx[64]; + int grbuflen = 0; + char *grbuf = NULL; endgrent(); - l = sprintf(pfx, "%s:", group); + l = snprintf(pfx, sizeof pfx, "%s:", group); /* * Update the group file */ - if (grp == NULL) - *grbuf = '\0'; + if (grp != NULL && fmtgrentry(&grbuf, &grbuflen, grp, PWF_PASSWD) == -1) + l = -1; else - fmtgrentry(grbuf, grp, PWF_PASSWD); - return fileupdate(_PATH_GROUP, 0644, grbuf, pfx, l, mode); + l = fileupdate(_PATH_GROUP, 0644, grbuf, pfx, l, mode); + if (grbuf != NULL) + free(grbuf); + return l; } diff --git a/usr.sbin/pw/pw.h b/usr.sbin/pw/pw.h index 57c9bce..7c8cff5 100644 --- a/usr.sbin/pw/pw.h +++ b/usr.sbin/pw/pw.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pw.h,v 1.1.1.3 1996/12/10 23:58:59 joerg Exp $ + * $Id: pw.h,v 1.2 1996/12/19 15:22:42 davidn Exp $ */ #include @@ -86,12 +86,12 @@ struct userconf 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 _PATH_PW_CONF "/etc/pw.conf" #define _UC_MAXLINE 1024 #define _UC_MAXSHELLS 32 -#define _UC_MAXGROUPS 200 struct userconf *read_userconfig(char const * file); int write_userconfig(char const * file); @@ -111,7 +111,6 @@ int fmtpwent(char *buf, struct passwd * pwd); int addgrent(struct group * grp); int delgrent(struct group * grp); int chggrent(char const * login, struct group * grp); -int fmtgrent(char *buf, struct group * grp); int boolean_val(char const * str, int dflt); char const *boolean_str(int val); diff --git a/usr.sbin/pw/pw_conf.c b/usr.sbin/pw/pw_conf.c index 77778f3..8a0e644 100644 --- a/usr.sbin/pw/pw_conf.c +++ b/usr.sbin/pw/pw_conf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pw_conf.c,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ + * $Id: pw_conf.c,v 1.1.1.2 1996/12/10 23:59:00 joerg Exp $ */ #include @@ -31,6 +31,7 @@ #include #include "pw.h" +#include "pwupd.h" #define debugging 0 @@ -66,11 +67,6 @@ static char *system_shells[_UC_MAXSHELLS] = "csh" }; -static char *default_groups[_UC_MAXGROUPS] = -{ - NULL -}; - static char const *booltrue[] = { "yes", "true", "1", "on", NULL @@ -93,7 +89,7 @@ static struct userconf config = system_shells, /* List of shells (first is default) */ bourne_shell, /* Default shell */ NULL, /* Default group name */ - default_groups, /* Default (additional) groups */ + NULL, /* Default (additional) groups */ NULL, /* Default login class */ 1000, 32000, /* Allowed range of uids */ 1000, 32000, /* Allowed range of gids */ @@ -212,126 +208,143 @@ newstr(char const * p) return q; } +#define LNBUFSZ 1024 + struct userconf * read_userconfig(char const * file) { FILE *fp; + extendarray(&config.groups, &config.numgroups, 200); + memset(config.groups, 0, config.numgroups * sizeof(char *)); if (file == NULL) file = _PATH_PW_CONF; if ((fp = fopen(file, "r")) != NULL) { - char buf[_UC_MAXLINE]; - - while (fgets(buf, sizeof buf, fp) != NULL) { - char *p = strchr(buf, '\n'); - - if (p == NULL) { /* Line too long */ - int ch; + int buflen = LNBUFSZ; + char *buf = malloc(buflen); + + nextline: + while (fgets(buf, buflen, fp) != NULL) { + char *p; + + while ((p = strchr(buf, '\n')) == NULL) { + int l; + if (extendline(&buf, &buflen, buflen + LNBUFSZ) == -1) { + int ch; + while ((ch = fgetc(fp)) != '\n' && ch != EOF); + goto nextline; /* Ignore it */ + } + l = strlen(buf); + if (fgets(buf + l, buflen - l, fp) == NULL) + break; /* Unterminated last line */ + } - while ((ch = fgetc(fp)) != '\n' && ch != EOF); - } else { + if (p != NULL) *p = '\0'; - if (*buf && *buf != '\n' && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') { - static char const toks[] = " \t\r\n,="; - char *q = strtok(NULL, toks); - int i = 0; - while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0) - ++i; + 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; + + 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_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_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: - config.default_group = (q == NULL || !boolean_val(q, 1) || getgrnam(q) == NULL) - ? NULL : newstr(q); - break; - case _UC_EXTRAGROUPS: - for (i = 0; i < _UC_MAXGROUPS && q != NULL; i++, q = strtok(NULL, toks)) - default_groups[i] = newstr(q); - if (i > 0) - while (i < _UC_MAXGROUPS) - default_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; + 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_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_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: + 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; } } } + free(buf); fclose(fp); } return &config; @@ -353,7 +366,8 @@ write_userconfig(char const * file) close(fd); else { int i, j, k; - char buf[_UC_MAXLINE]; + int len = LNBUFSZ; + char *buf = malloc(len); for (i = _UC_NONE; i < _UC_FIELDS; i++) { int quote = 1; @@ -386,8 +400,14 @@ write_userconfig(char const * file) val = config.shelldir; break; case _UC_SHELLS: - for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) - k += sprintf(buf + k, "%s\"%s\"", k ? "," : "", system_shells[j]); + for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) { + char lbuf[64]; + int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", system_shells[j]); + if (l + k + 1 < len || extendline(&buf, &len, len + LNBUFSZ) != -1) { + strcpy(buf + k, lbuf); + k += l; + } + } quote = 0; break; case _UC_DEFAULTSHELL: @@ -397,8 +417,15 @@ write_userconfig(char const * file) val = config.default_group ? config.default_group : ""; break; case _UC_EXTRAGROUPS: - for (j = k = 0; j < _UC_MAXGROUPS && default_groups[j] != NULL; j++) - k += sprintf(buf + k, "%s\"%s\"", k ? "," : "", default_groups[j]); + extendarray(&config.groups, &config.numgroups, 200); + for (j = k = 0; j < config.numgroups && config.groups[j] != NULL; j++) { + char lbuf[64]; + int l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", config.groups[j]); + if (l + k + 1 < len || extendline(&buf, &len, len + 1024) != -1) { + strcpy(buf + k, lbuf); + k += l; + } + } quote = 0; break; case _UC_DEFAULTCLASS: @@ -445,6 +472,7 @@ write_userconfig(char const * file) #endif } } + free(buf); return fclose(fp) != EOF; } } diff --git a/usr.sbin/pw/pw_group.c b/usr.sbin/pw/pw_group.c index 8097297..a8b3c41 100644 --- a/usr.sbin/pw/pw_group.c +++ b/usr.sbin/pw/pw_group.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pw_group.c,v 1.1.1.3 1996/12/10 23:59:01 joerg Exp $ + * $Id: pw_group.c,v 1.2 1996/12/19 15:22:44 davidn Exp $ */ #include @@ -32,6 +32,7 @@ #include "pw.h" #include "bitmap.h" +#include "pwupd.h" static int print_group(struct group * grp, int pretty); @@ -44,7 +45,8 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) struct carg *a_gid = getarg(args, 'g'); struct carg *arg; struct group *grp = NULL; - char *members[_UC_MAXGROUPS]; + int grmembers = 0; + char **members = NULL; static struct group fakegroup = { @@ -93,8 +95,11 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) 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) : -1; + fakegroup.gr_mem = fmems; return print_group(&fakegroup, getarg(args, 'P') != NULL); } cmderr(EX_DATAERR, "unknown group `%s'\n", a_name ? a_name->val : a_gid->val); @@ -126,7 +131,8 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) else if (grp != NULL) /* Exists */ cmderr(EX_DATAERR, "group name `%s' already exists\n", a_name->val); - memset(members, 0, sizeof members); + extendarray(&members, &grmembers, 200); + members[0] = NULL; grp = &fakegroup; grp->gr_name = pw_checkname((u_char *)a_name->val, 0); grp->gr_passwd = "*"; @@ -188,13 +194,19 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) char *p; struct passwd *pwd; + /* Make sure this is not stay NULL with -M "" */ + extendarray(&members, &grmembers, 200); if (arg->ch == 'm') { - while (i < _UC_MAXGROUPS && grp->gr_mem[i] != NULL) { - members[i] = grp->gr_mem[i]; - i++; + int k = 0; + + while (grp->gr_mem[k] != NULL) { + if (extendarray(&members, &grmembers, i + 2) != -1) { + members[i++] = grp->gr_mem[k]; + } + k++; } } - for (p = strtok(arg->val, ", \t"); i < _UC_MAXGROUPS && p != NULL; p = strtok(NULL, ", \t")) { + for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) { int j; if ((pwd = getpwnam(p)) == NULL) { if (!isdigit(*p) || (pwd = getpwuid((uid_t) atoi(p))) == NULL) @@ -205,10 +217,10 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) */ for (j = 0; j < i && strcmp(members[j], pwd->pw_name)!=0; j++) ; - if (j == i) + if (j == i && extendarray(&members, &grmembers, i + 2) != -1) members[i++] = newstr(pwd->pw_name); } - while (i < _UC_MAXGROUPS) + while (i < grmembers) members[i++] = NULL; grp->gr_mem = members; } @@ -226,6 +238,9 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args) pw_log(cnf, mode, W_GROUP, "%s(%ld)", grp->gr_name, (long) grp->gr_gid); + if (members) + free(members); + return EXIT_SUCCESS; } @@ -296,17 +311,19 @@ static int print_group(struct group * grp, int pretty) { if (!pretty) { - char buf[_UC_MAXLINE]; + int buflen = 0; + char *buf = NULL; - fmtgrent(buf, grp); + fmtgrent(&buf, &buflen, grp); fputs(buf, stdout); + free(buf); } else { int i; - printf("Group Name : %-10s #%lu\n" - " Members : ", + printf("Group Name: %-10s #%lu\n" + " Members: ", grp->gr_name, (long) grp->gr_gid); - for (i = 0; i < _UC_MAXGROUPS && grp->gr_mem[i]; i++) + for (i = 0; grp->gr_mem[i]; i++) printf("%s%s", i ? "," : "", grp->gr_mem[i]); fputs("\n\n", stdout); } diff --git a/usr.sbin/pw/pw_user.c b/usr.sbin/pw/pw_user.c index 4d6131f..81d4d9f 100644 --- a/usr.sbin/pw/pw_user.c +++ b/usr.sbin/pw/pw_user.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pw_user.c,v 1.6 1996/12/19 15:22:45 davidn Exp $ + * $Id: pw_user.c,v 1.7 1996/12/20 10:45:39 davidn Exp $ */ #include @@ -51,6 +51,7 @@ static char *pw_shellpolicy(struct userconf * cnf, struct cargs * args, char static char *pw_password(struct userconf * cnf, struct cargs * args, char const * user); static char *shell_path(char const * path, char *shells[], char *sh); static void rmat(uid_t uid); +static void rmskey(char const * name); /*- * -C config configuration file @@ -93,7 +94,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) struct passwd *pwd = NULL; struct group *grp; struct stat st; - char line[MAXPWLINE]; + char line[_PASSWORD_LEN+1]; static struct passwd fakeuser = { @@ -152,14 +153,15 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if ((arg = getarg(args, 'G')) != NULL && arg->val) { int i = 0; - for (p = strtok(arg->val, ", \t"); i < _UC_MAXGROUPS && p != NULL; p = strtok(NULL, ", \t")) { + for (p = strtok(arg->val, ", \t"); p != NULL; p = strtok(NULL, ", \t")) { if ((grp = getgrnam(p)) == NULL) { if (!isdigit(*p) || (grp = getgrgid((gid_t) atoi(p))) == NULL) cmderr(EX_NOUSER, "group `%s' does not exist\n", p); } - cnf->groups[i++] = newstr(grp->gr_name); + if (extendarray(&cnf->groups, &cnf->numgroups, i + 2) != -1) + cnf->groups[i++] = newstr(grp->gr_name); } - while (i < _UC_MAXGROUPS) + while (i < cnf->numgroups) cnf->groups[i++] = NULL; } if ((arg = getarg(args, 'k')) != NULL) { @@ -252,6 +254,12 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) cmderr(EX_DATAERR, "cannot remove user 'root'\n"); /* + * Remove skey record from /etc/skeykeys + */ + + rmskey(pwd->pw_name); + + /* * Remove crontabs */ sprintf(file, "/var/cron/tabs/%s", pwd->pw_name); @@ -347,6 +355,14 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (getarg(args, 'L')) pwd->pw_class = cnf->default_class; + if ((arg = getarg(args, 'd')) != NULL) { + if (stat(pwd->pw_dir = arg->val, &st) == -1) { + if (getarg(args, 'm') == NULL && strcmp(pwd->pw_dir, "/nonexistent") != 0) + fprintf(stderr, "WARNING: home `%s' does not exist\n", pwd->pw_dir); + } else if (!S_ISDIR(st.st_mode)) + fprintf(stderr, "WARNING: home `%s' is not a directory\n", pwd->pw_dir); + } + if ((arg = getarg(args, 'w')) != NULL && getarg(args, 'h') == NULL) pwd->pw_passwd = pw_password(cnf, args, pwd->pw_name); @@ -900,12 +916,12 @@ print_user(struct passwd * pwd, int pretty) strftime(acexpire, sizeof acexpire, "%c", tptr); if (pwd->pw_change > (time_t)9 && (tptr = localtime(&pwd->pw_change)) != NULL) strftime(pwexpire, sizeof pwexpire, "%c", tptr); - printf("Login Name : %-10s #%-22ld Group : %-10s #%ld\n" - " Full Name : %s\n" - " Home : %-32.32s Class : %s\n" - " Shell : %-32.32s Office : %s\n" - "Work Phone : %-32.32s Home Phone : %s\n" - "Acc Expire : %-32.32s Pwd Expire : %s\n", + printf("Login Name: %-10s #%-16ld Group: %-10s #%ld\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, uname, pwd->pw_dir, pwd->pw_class, @@ -916,11 +932,11 @@ print_user(struct passwd * pwd, int pretty) while ((grp=getgrent()) != NULL) { int i = 0; - while (i < _UC_MAXGROUPS && grp->gr_mem[i] != NULL) + while (grp->gr_mem[i] != NULL) { if (strcmp(grp->gr_mem[i], pwd->pw_name)==0) { - printf(j++ == 0 ? " Groups : %s" : ",%s", grp->gr_name); + printf(j++ == 0 ? " Groups: %s" : ",%s", grp->gr_name); break; } ++i; @@ -977,3 +993,40 @@ rmat(uid_t uid) closedir(d); } } + +static void +rmskey(char const * name) +{ + static const char etcskey[] = "/etc/skeykeys"; + static const char newskey[] = "/etc/skeykeys.new"; + int done = 0; + FILE *infp = fopen(etcskey, "r"); + + if (infp != NULL) { + int fd = open(newskey, O_RDWR|O_CREAT|O_TRUNC, 0644); + + if (fd != -1) { + FILE * outfp = fdopen(fd, "w"); + int length = strlen(name); + char tmp[1024]; + + while (fgets(tmp, sizeof tmp, infp) != NULL) { + if (strncmp(name, tmp, length) == 0 && isspace(tmp[length])) + ++done; /* Found a key */ + else + fputs(tmp, outfp); + } + /* + * If we got an error of any sort, don't update! + */ + if (fclose(outfp) == EOF || ferror(infp)) + done = 0; + } + fclose(infp); + if (!done) + remove(newskey); + else + rename(newskey, etcskey); + } +} + diff --git a/usr.sbin/pw/pwupd.c b/usr.sbin/pw/pwupd.c index 149d239..fb56dac 100644 --- a/usr.sbin/pw/pwupd.c +++ b/usr.sbin/pw/pwupd.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pwupd.c,v 1.1.1.2 1996/12/09 23:55:27 joerg Exp $ + * $Id: pwupd.c,v 1.1.1.3 1996/12/10 23:59:02 joerg Exp $ */ #include @@ -118,7 +118,7 @@ pw_update(struct passwd * pwd, char const * user, int mode) { /* No -c */ #endif char pfx[32]; - char pwbuf[MAXPWLINE]; + char pwbuf[PWBUFSZ]; int l = sprintf(pfx, "%s:", user); /* diff --git a/usr.sbin/pw/pwupd.h b/usr.sbin/pw/pwupd.h index 54324f8..457a91b 100644 --- a/usr.sbin/pw/pwupd.h +++ b/usr.sbin/pw/pwupd.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: pwupd.h,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ + * $Id: pwupd.h,v 1.1.1.2 1996/12/10 23:59:03 joerg Exp $ */ #ifndef _PWUPD_H_ @@ -60,20 +60,22 @@ int delpwent __P((struct passwd * pwd)); int chgpwent __P((char const * login, struct passwd * pwd)); int fmtpwent __P((char *buf, struct passwd * pwd)); int fmtpwentry __P((char *buf, struct passwd * pwd, int type)); + int addgrent __P((struct group * grp)); int delgrent __P((struct group * grp)); int chggrent __P((char const * name, struct group * grp)); -int fmtgrent __P((char *buf, struct group * grp)); -int fmtgrentry __P((char *buf, struct group * grp, int type)); +int fmtgrent __P((char **buf, int * buflen, struct group * grp)); +int fmtgrentry __P((char **buf, int * buflen, struct group * grp, int type)); int editgroups __P((char *name, char **groups)); __END_DECLS -#define MAXGROUPS 200 -#define MAXPWLINE 1024 +#define PWBUFSZ 1024 __BEGIN_DECLS void copymkdir __P((char const * dir, char const * skel, mode_t mode, uid_t uid, gid_t gid)); void rm_r __P((char const * dir, uid_t uid)); +int extendline __P((char **buf, int *buflen, int needed)); +int extendarray __P((char ***buf, int *buflen, int needed)); __END_DECLS #endif /* !_PWUPD_H */ -- cgit v1.1