diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2004-02-26 21:18:19 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2004-02-26 21:18:19 +0000 |
commit | e12d139abecf78f73486a522823de23dfa38022a (patch) | |
tree | 0fab793c41c61e26c5a031fb451cf9f3deeac2c6 /usr.sbin | |
parent | e895248babca3545346064ebd563740c78101c94 (diff) |
Avoid using regexp when removing a user from /etc/group entries in
userdel since a username may contain regexp special chars.
Fix a memory leak on error and chmod before moving the new group
file is moved into place instead of after.
Saner error messages in rm_user_from_groups() (cut & pastos)
OK deraadt@, tdeval@ and otto@; error message fixes courtesy of otto@
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/user/user.c | 73 |
1 files changed, 41 insertions, 32 deletions
diff --git a/usr.sbin/user/user.c b/usr.sbin/user/user.c index c8496d8e4b6..98aeaa7807f 100644 --- a/usr.sbin/user/user.c +++ b/usr.sbin/user/user.c @@ -1,4 +1,4 @@ -/* $OpenBSD: user.c,v 1.55 2004/01/03 18:30:39 millert Exp $ */ +/* $OpenBSD: user.c,v 1.56 2004/02/26 21:18:18 millert Exp $ */ /* $NetBSD: user.c,v 1.69 2003/04/14 17:40:07 agc Exp $ */ /* @@ -1111,24 +1111,19 @@ static int rm_user_from_groups(char *login_name) { struct stat st; - regmatch_t matchv[10]; - regex_t r; + size_t login_len; FILE *from; FILE *to; - char line[LINE_MAX]; char buf[LINE_MAX]; char f[MaxFileNameLen]; + char *cp, *ep; int fd; int cc; - int sc; - (void) snprintf(line, sizeof(line), "(:|,)(%s)(,|$)", login_name); - if (regcomp(&r, line, REG_EXTENDED|REG_NEWLINE) != 0) { - warn("can't compile regular expression `%s'", line); - return 0; - } + login_len = strlen(login_name); if ((from = fopen(_PATH_GROUP, "r")) == NULL) { - warn("can't remove gid for `%s': can't open `%s'", login_name, _PATH_GROUP); + warn("can't remove gid for `%s': can't open `%s'", + login_name, _PATH_GROUP); return 0; } if (flock(fileno(from), LOCK_EX | LOCK_NB) < 0) { @@ -1138,14 +1133,15 @@ rm_user_from_groups(char *login_name) (void) snprintf(f, sizeof(f), "%s.XXXXXXXX", _PATH_GROUP); if ((fd = mkstemp(f)) < 0) { (void) fclose(from); - warn("can't create gid: mkstemp failed"); + warn("can't remove gid for `%s': mkstemp failed", login_name); return 0; } if ((to = fdopen(fd, "w")) == NULL) { (void) fclose(from); (void) close(fd); (void) unlink(f); - warn("can't create gid: fdopen `%s' failed", f); + warn("can't remove gid for `%s': fdopen `%s' failed", + login_name, f); return 0; } while (fgets(buf, sizeof(buf), from) > 0) { @@ -1157,37 +1153,50 @@ rm_user_from_groups(char *login_name) _PATH_GROUP, buf, cc); continue; } - if (regexec(&r, buf, 10, matchv, 0) == 0) { - if (buf[(int)matchv[1].rm_so] == ',') - matchv[2].rm_so = matchv[1].rm_so; - else if (matchv[2].rm_eo != matchv[3].rm_eo) - matchv[2].rm_eo = matchv[3].rm_eo; - cc -= (int) matchv[2].rm_eo; - sc = (int) matchv[2].rm_so; - if (fwrite(buf, sc, 1, to) != 1 || - fwrite(&buf[(int)matchv[2].rm_eo], cc, 1, to) != 1) { - (void) fclose(from); - (void) close(fd); - (void) unlink(f); - warn("can't create gid: short write to `%s'", f); - return 0; + + /* Break out the group list. */ + for (cp = buf, cc = 0; *cp != '\0' && cc < 3; cp++) { + if (*cp == ':') + cc++; + } + if (cc != 3) { + warnx("Malformed entry `%.*s'. Skipping", + (int)strlen(buf) - 1, buf); + continue; + } + while ((cp = strstr(cp, login_name)) != NULL) { + if ((cp[-1] == ':' || cp[-1] == ',') && + (cp[login_len] == ',' || cp[login_len] == '\n')) { + ep = cp + login_len; + if (cp[login_len] == ',') + ep++; + else if (cp[-1] == ',') + cp--; + memmove(cp, ep, strlen(ep) + 1); + } else { + if ((cp = strchr(cp, ',')) == NULL) + break; + cp++; } - } else if (fwrite(buf, cc, 1, to) != 1) { + } + if (fwrite(buf, strlen(buf), 1, to) != 1) { (void) fclose(from); - (void) close(fd); + (void) fclose(to); (void) unlink(f); - warn("can't create gid: short write to `%s'", f); + warn("can't remove gid for `%s': short write to `%s'", + login_name, f); return 0; } } + (void) fchmod(fileno(to), st.st_mode & 07777); (void) fclose(from); (void) fclose(to); if (rename(f, _PATH_GROUP) < 0) { (void) unlink(f); - warn("can't create gid: can't rename `%s' to `%s'", f, _PATH_GROUP); + warn("can't remove gid for `%s': can't rename `%s' to `%s'", + login_name, f, _PATH_GROUP); return 0; } - (void) chmod(_PATH_GROUP, st.st_mode & 07777); return 1; } |