From f143c5375336dc02525eb9d9509af756e3dd61e9 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 5 Dec 2012 13:56:43 +0000 Subject: Remove useless check for NULL prior to free. Approved by: cperciva MFC after: 2 weeks --- pw/bitmap.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ pw/pw_group.c | 3 +- 2 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 pw/bitmap.c diff --git a/pw/bitmap.c b/pw/bitmap.c new file mode 100644 index 0000000..8e96bff --- /dev/null +++ b/pw/bitmap.c @@ -0,0 +1,131 @@ +/*- + * Copyright (C) 1996 + * David L. Nugent. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include + +#include "bitmap.h" + +struct bitmap +bm_alloc(int size) +{ + struct bitmap bm; + int szmap = (size / 8) + !!(size % 8); + + bm.size = size; + bm.map = malloc(szmap); + if (bm.map) + memset(bm.map, 0, szmap); + return bm; +} + +void +bm_dealloc(struct bitmap * bm) +{ + free(bm->map); +} + +static void +bm_getmask(int *pos, unsigned char *bmask) +{ + *bmask = (unsigned char) (1 << (*pos % 8)); + *pos /= 8; +} + +void +bm_setbit(struct bitmap * bm, int pos) +{ + unsigned char bmask; + + bm_getmask(&pos, &bmask); + bm->map[pos] |= bmask; +} + +void +bm_clrbit(struct bitmap * bm, int pos) +{ + unsigned char bmask; + + bm_getmask(&pos, &bmask); + bm->map[pos] &= ~bmask; +} + +int +bm_isset(struct bitmap * bm, int pos) +{ + unsigned char bmask; + + bm_getmask(&pos, &bmask); + return !!(bm->map[pos] & bmask); +} + +int +bm_firstunset(struct bitmap * bm) +{ + int szmap = (bm->size / 8) + !!(bm->size % 8); + int at = 0; + int pos = 0; + + while (pos < szmap) { + unsigned char bmv = bm->map[pos++]; + unsigned char bmask = 1; + + while (bmask & 0xff) { + if ((bmv & bmask) == 0) + return at; + bmask <<= 1; + ++at; + } + } + return at; +} + +int +bm_lastset(struct bitmap * bm) +{ + int szmap = (bm->size / 8) + !!(bm->size % 8); + int at = 0; + int pos = 0; + int ofs = 0; + + while (pos < szmap) { + unsigned char bmv = bm->map[pos++]; + unsigned char bmask = 1; + + while (bmask & 0xff) { + if ((bmv & bmask) != 0) + ofs = at; + bmask <<= 1; + ++at; + } + } + return ofs; +} diff --git a/pw/pw_group.c b/pw/pw_group.c index f4f2116..fda62b2 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -274,8 +274,7 @@ 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); + free(members); return EXIT_SUCCESS; } -- cgit v1.2.3 From 85bd783a36b8090690f2fddfe2069fc0ea6b4159 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 5 Dec 2012 13:56:46 +0000 Subject: Avoid overflow of file buffer Submitted by: db Approved by: cperciva MFC after: 2 weeks --- pw/pw_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pw/pw_user.c b/pw/pw_user.c index abf1c35..23a7856 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -394,7 +394,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) /* * Remove crontabs */ - sprintf(file, "/var/cron/tabs/%s", pwd->pw_name); + snprintf(file, sizeof(file), "/var/cron/tabs/%s", pwd->pw_name); if (access(file, F_OK) == 0) { sprintf(file, "crontab -u %s -r", pwd->pw_name); system(file); -- cgit v1.2.3 From 47669a6b6b0e278467f264dba9428048aeb1f283 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 5 Dec 2012 13:56:49 +0000 Subject: Use strdup instead of malloc + strcpy Submitted by: db Approved by: cperciva MFC after: 2 weeks --- pw/pwupd.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pw/pwupd.c b/pw/pwupd.c index 4ab0f01..0f2df7a 100644 --- a/pw/pwupd.c +++ b/pw/pwupd.c @@ -56,12 +56,10 @@ setpwdir(const char * dir) { if (dir == NULL) return -1; - else { - char * d = malloc(strlen(dir)+1); - if (d == NULL) - return -1; - pwpath = strcpy(d, dir); - } + else + pwpath = strdup(dir); + if (pwpath == NULL) + return -1; return 0; } -- cgit v1.2.3 From 20929a4bb15d04607a63dc41ee257643f1c9181a Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 5 Dec 2012 13:56:52 +0000 Subject: Avoid overflowing the file buffer Submitted by: db Approved by: cperciva MFC after: 2 weeks --- pw/rm_r.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 pw/rm_r.c diff --git a/pw/rm_r.c b/pw/rm_r.c new file mode 100644 index 0000000..797ca9d --- /dev/null +++ b/pw/rm_r.c @@ -0,0 +1,75 @@ +/*- + * Copyright (C) 1996 + * David L. Nugent. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwupd.h" + +void +rm_r(char const * dir, uid_t uid) +{ + DIR *d = opendir(dir); + + if (d != NULL) { + struct dirent *e; + struct stat st; + char file[MAXPATHLEN]; + + while ((e = readdir(d)) != NULL) { + if (strcmp(e->d_name, ".") != 0 && strcmp(e->d_name, "..") != 0) { + snprintf(file, sizeof(file), "%s/%s", dir, e->d_name); + if (lstat(file, &st) == 0) { /* Need symlinks, not + * linked file */ + if (S_ISDIR(st.st_mode)) /* Directory - recurse */ + rm_r(file, uid); + else { + if (S_ISLNK(st.st_mode) || st.st_uid == uid) + remove(file); + } + } + } + } + closedir(d); + if (lstat(dir, &st) == 0) { + if (S_ISLNK(st.st_mode)) + remove(dir); + else if (st.st_uid == uid) + rmdir(dir); + } + } +} -- cgit v1.2.3 From 272e225a6ba49cf949fc263c3dcd7e74152ffdc2 Mon Sep 17 00:00:00 2001 From: Eitan Adler Date: Wed, 5 Dec 2012 13:56:56 +0000 Subject: Simplify string duplication: use strdup instead of malloc + strcpy Submitted by: db Approved by: cperciva MFC after: 2 weeks --- pw/grupd.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pw/grupd.c b/pw/grupd.c index e9f6b5e..3f78e95 100644 --- a/pw/grupd.c +++ b/pw/grupd.c @@ -50,12 +50,11 @@ setgrdir(const char * dir) { if (dir == NULL) return -1; - else { - char * d = malloc(strlen(dir)+1); - if (d == NULL) - return -1; - grpath = strcpy(d, dir); - } + else + grpath = strdup(dir); + if (grpath == NULL) + return -1; + return 0; } -- cgit v1.2.3 From e9c255fbe0172e9e9b0489054fed55d6142f8347 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 26 Dec 2012 18:14:45 +0000 Subject: Fix creating a user and adding it to a group Reported by: "Sam Fourman Jr." , dim --- pw/pw_user.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/pw/pw_user.c b/pw/pw_user.c index 23a7856..7df6b85 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -747,6 +747,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (mode == M_ADD || getarg(args, 'G') != NULL) { int i, j; for (i = 0; cnf->groups[i] != NULL; i++) { + char **members; grp = GETGRNAM(cnf->groups[i]); for (j = 0; grp->gr_mem[j] != NULL; j++) { if (!strcmp(grp->gr_mem[j], pwd->pw_name)) @@ -755,15 +756,15 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (grp->gr_mem[j] != NULL) /* user already member of group */ continue; - if (j == 0) - grp->gr_mem = NULL; + members = malloc(sizeof(char *) * (j + 1)); + for (j = 0; grp->gr_mem[j] != NULL; j++) + members[j] = grp->gr_mem[j]; - grp->gr_mem = reallocf(grp->gr_mem, sizeof(*grp->gr_mem) * - (j + 2)); - - grp->gr_mem[j] = pwd->pw_name; - grp->gr_mem[j+1] = NULL; + members[j] = pwd->pw_name; + members[j+1] = NULL; + grp->gr_mem = members; chggrent(cnf->groups[i], grp); + free(members); } } -- cgit v1.2.3 From e384eae800c0d663ba8b68103771103d8e78c0f6 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 26 Dec 2012 18:28:17 +0000 Subject: In case of the deletion of a user those whole database has to be regenerated, otherwise the user planned to be deleted remain in the pwd.db while removed from the plain text password file. --- pw/pwupd.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pw/pwupd.c b/pw/pwupd.c index 0f2df7a..22662db 100644 --- a/pw/pwupd.c +++ b/pw/pwupd.c @@ -146,7 +146,11 @@ pw_update(struct passwd * pwd, char const * user) pw_fini(); err(1, "pw_copy()"); } - if (pw_mkdb(user) == -1) { + /* + * in case of deletion of a user, the whole database + * needs to be regenerated + */ + if (pw_mkdb(pw != NULL ? user : NULL) == -1) { pw_fini(); err(1, "pw_mkdb()"); } -- cgit v1.2.3 From 9ee906bbd3ca844c465c6f1056ac025ccca948e3 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 26 Dec 2012 23:14:33 +0000 Subject: Fix off-by-one error in memory allocation: j entries, one new and a null terminator is j + 2. Submitted by: Christoph Mallon --- pw/pw_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pw/pw_user.c b/pw/pw_user.c index 7df6b85..43119ed 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -756,7 +756,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) if (grp->gr_mem[j] != NULL) /* user already member of group */ continue; - members = malloc(sizeof(char *) * (j + 1)); + members = malloc(sizeof(char *) * (j + 2)); for (j = 0; grp->gr_mem[j] != NULL; j++) members[j] = grp->gr_mem[j]; -- cgit v1.2.3 From 6f9e060eaafec4d7157f90f32e8d2d580fd73a71 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 26 Dec 2012 23:16:24 +0000 Subject: Simplify copying of group members by using memcpy Submitted by: Christoph Mallon --- pw/pw_user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pw/pw_user.c b/pw/pw_user.c index 43119ed..74c1ef9 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -757,8 +757,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) continue; members = malloc(sizeof(char *) * (j + 2)); - for (j = 0; grp->gr_mem[j] != NULL; j++) - members[j] = grp->gr_mem[j]; + memcpy(members, grp->gr_mem, j * sizeof(*members)); members[j] = pwd->pw_name; members[j+1] = NULL; -- cgit v1.2.3 From 758c4f17afd4a148f62b0b87647f242acf074aa9 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 14:09:50 +0000 Subject: Use flopen(3) instead of open(2) + flock(2) --- libutil/gr_util.c | 6 ++---- libutil/pw_util.c | 7 ++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index be34395..6bf102f 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -106,10 +106,8 @@ gr_lock(void) for (;;) { struct stat st; - lockfd = open(group_file, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) - err(1, "%s", group_file); - if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { + lockfd = flopen(group_file, O_RDONLY|O_NONBLOCK, 0); + if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the group file is busy"); } else { diff --git a/libutil/pw_util.c b/libutil/pw_util.c index 4bf3001..24c0263 100644 --- a/libutil/pw_util.c +++ b/libutil/pw_util.c @@ -179,11 +179,8 @@ pw_lock(void) for (;;) { struct stat st; - lockfd = open(masterpasswd, O_RDONLY, 0); - if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) - err(1, "%s", masterpasswd); - /* XXX vulnerable to race conditions */ - if (flock(lockfd, LOCK_EX|LOCK_NB) == -1) { + lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK, 0); + if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the password db file is busy"); } else { -- cgit v1.2.3 From ac1681ea5c7980246ca789137e852441e10207d5 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 14:30:19 +0000 Subject: New gr_add function to provide a clean and safe method to append a new member into an existing group. Submitted by: db --- libutil/gr_util.c | 40 ++++++++++++++++++++++++++++++++++++++++ libutil/libutil.h | 2 ++ 2 files changed, 42 insertions(+) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 6bf102f..90062eb 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -478,6 +478,46 @@ gr_dup(const struct group *gr) return (&gs->gr); } +/* + * Add a new member name to a struct group. + */ +struct group * +gr_add(struct group *gr, const char *newmember) +{ + size_t mlen; + int num_mem=0; + char **members; + struct group *newgr; + + if (newmember == NULL) + return(gr_dup(gr)); + + if (gr->gr_mem != NULL) { + for (num_mem = 0; gr->gr_mem[num_mem] != NULL; num_mem++) { + if (strcmp(gr->gr_mem[num_mem], newmember) == 0) { + errno = EEXIST; + return (NULL); + } + } + } + /* Allocate enough for current pointers + 1 more and NULL marker */ + mlen = (num_mem + 2) * sizeof(*gr->gr_mem); + if ((members = calloc(1, mlen )) == NULL) { + errno = ENOMEM; + return (NULL); + } + memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem)); + members[num_mem++] = (char *)newmember; + members[num_mem] = NULL; + gr->gr_mem = members; + newgr = gr_dup(gr); + if (newgr == NULL) + errno = ENOMEM; + + free(members); + return (newgr); +} + /* * Scan a line and place it into a group structure. */ diff --git a/libutil/libutil.h b/libutil/libutil.h index bf42766..fcd74e1 100644 --- a/libutil/libutil.h +++ b/libutil/libutil.h @@ -166,6 +166,8 @@ int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group *_old_gr); struct group * gr_dup(const struct group *_gr); +struct group * + gr_add(struct group *_gr, const char *_newmember); int gr_equal(const struct group *_gr1, const struct group *_gr2); void gr_fini(void); int gr_init(const char *_dir, const char *_master); -- cgit v1.2.3 From a76b46580eef36f7765bae26ec8a9a9f0fea4408 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 14:35:06 +0000 Subject: Simplify the code by using the new gr_add function --- pw/pw_user.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/pw/pw_user.c b/pw/pw_user.c index 74c1ef9..5577511 100644 --- a/pw/pw_user.c +++ b/pw/pw_user.c @@ -745,25 +745,19 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args) */ if (mode == M_ADD || getarg(args, 'G') != NULL) { - int i, j; + int i; for (i = 0; cnf->groups[i] != NULL; i++) { - char **members; grp = GETGRNAM(cnf->groups[i]); - for (j = 0; grp->gr_mem[j] != NULL; j++) { - if (!strcmp(grp->gr_mem[j], pwd->pw_name)) - break; - } - if (grp->gr_mem[j] != NULL) /* user already member of group */ + grp = gr_add(grp, pwd->pw_name); + /* + * grp can only be NULL in 2 cases: + * - the new member is already a member + * - a problem with memory occurs + * in both cases we want to skip now. + */ + if (grp == NULL) continue; - - members = malloc(sizeof(char *) * (j + 2)); - memcpy(members, grp->gr_mem, j * sizeof(*members)); - - members[j] = pwd->pw_name; - members[j+1] = NULL; - grp->gr_mem = members; chggrent(cnf->groups[i], grp); - free(members); } } -- cgit v1.2.3 From dcb35c061edb54776541bad319d4da3448dcb09b Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 14:44:13 +0000 Subject: Fix a regression in "pw group show" introduced r242349: print a newline after printing each group line. PR: bin/174731 Submitted by: Jan Beich --- pw/pw_group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pw/pw_group.c b/pw/pw_group.c index fda62b2..3259412 100644 --- a/pw/pw_group.c +++ b/pw/pw_group.c @@ -407,7 +407,7 @@ print_group(struct group * grp, int pretty) char *buf = NULL; buf = gr_make(grp); - fputs(buf, stdout); + printf("%s\n", buf); free(buf); } else { int i; -- cgit v1.2.3 From dca2732b7d9f3eb818b44fe0038b3d3cf3c07fc2 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 16:51:29 +0000 Subject: - Clean up previous gr_add use malloc instead of calloc - Fix tinderbox error Submitted by: db --- libutil/gr_util.c | 7 +++---- libutil/libutil.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 90062eb..0cd8055 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -482,7 +482,7 @@ gr_dup(const struct group *gr) * Add a new member name to a struct group. */ struct group * -gr_add(struct group *gr, const char *newmember) +gr_add(struct group *gr, char *newmember) { size_t mlen; int num_mem=0; @@ -502,18 +502,17 @@ gr_add(struct group *gr, const char *newmember) } /* Allocate enough for current pointers + 1 more and NULL marker */ mlen = (num_mem + 2) * sizeof(*gr->gr_mem); - if ((members = calloc(1, mlen )) == NULL) { + if ((members = malloc(mlen)) == NULL) { errno = ENOMEM; return (NULL); } memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem)); - members[num_mem++] = (char *)newmember; + members[num_mem++] = newmember; members[num_mem] = NULL; gr->gr_mem = members; newgr = gr_dup(gr); if (newgr == NULL) errno = ENOMEM; - free(members); return (newgr); } diff --git a/libutil/libutil.h b/libutil/libutil.h index fcd74e1..b1b2405 100644 --- a/libutil/libutil.h +++ b/libutil/libutil.h @@ -167,7 +167,7 @@ int gr_copy(int __ffd, int _tfd, const struct group *_gr, struct group * gr_dup(const struct group *_gr); struct group * - gr_add(struct group *_gr, const char *_newmember); + gr_add(struct group *_gr, char *_newmember); int gr_equal(const struct group *_gr1, const struct group *_gr2); void gr_fini(void); int gr_init(const char *_dir, const char *_master); -- cgit v1.2.3 From b8861f725f2d4f68c95cf844d66b85651935951b Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 19:33:43 +0000 Subject: gr_dup: simplify duplication of group Submitted by: db --- libutil/gr_util.c | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 0cd8055..2f87bd1 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -44,11 +44,6 @@ __FBSDID("$FreeBSD$"); #include #include -struct group_storage { - struct group gr; - char *members[]; -}; - static int lockfd = -1; static char group_dir[PATH_MAX]; static char group_file[PATH_MAX]; @@ -434,14 +429,14 @@ gr_make(const struct group *gr) struct group * gr_dup(const struct group *gr) { + struct group *newgr; char *dst; size_t len; - struct group_storage *gs; int ndx; int num_mem; /* Calculate size of the group. */ - len = sizeof(*gs); + len = sizeof(*newgr); if (gr->gr_name != NULL) len += strlen(gr->gr_name) + 1; if (gr->gr_passwd != NULL) @@ -452,30 +447,34 @@ gr_dup(const struct group *gr) len += (num_mem + 1) * sizeof(*gr->gr_mem); } else num_mem = -1; - /* Create new group and copy old group into it. */ - if ((gs = calloc(1, len)) == NULL) + if ((newgr = malloc(len)) == NULL) return (NULL); - dst = (char *)&gs->members[num_mem + 1]; + /* point new gr_mem to end of struct + 1 */ + if (gr->gr_mem != NULL) + newgr->gr_mem = (char **)newgr + sizeof(struct group); + else + newgr->gr_mem = NULL; + /* point dst after the end of all the gr_mem pointers in newgr */ + dst = (char *)newgr + sizeof(struct group) + + (num_mem + 1) * sizeof(*gr->gr_mem); if (gr->gr_name != NULL) { - gs->gr.gr_name = dst; - dst = stpcpy(gs->gr.gr_name, gr->gr_name) + 1; + newgr->gr_name = dst; + dst = stpcpy(dst, gr->gr_name) + 1; } if (gr->gr_passwd != NULL) { - gs->gr.gr_passwd = dst; - dst = stpcpy(gs->gr.gr_passwd, gr->gr_passwd) + 1; + newgr->gr_passwd = dst; + dst = stpcpy(dst, gr->gr_passwd) + 1; } - gs->gr.gr_gid = gr->gr_gid; + newgr->gr_gid = gr->gr_gid; if (gr->gr_mem != NULL) { - gs->gr.gr_mem = gs->members; for (ndx = 0; ndx < num_mem; ndx++) { - gs->gr.gr_mem[ndx] = dst; - dst = stpcpy(gs->gr.gr_mem[ndx], gr->gr_mem[ndx]) + 1; + newgr->gr_mem[ndx] = dst; + dst = stpcpy(dst, gr->gr_mem[ndx]) + 1; } - gs->gr.gr_mem[ndx] = NULL; + newgr->gr_mem[ndx] = NULL; } - - return (&gs->gr); + return (newgr); } /* -- cgit v1.2.3 From db8e9b62df85e4ed7de7938e68c221930a9a30c6 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 19:43:29 +0000 Subject: Simplify vnextgrent and vnextpwent reusing pw_scan and gr_scan from libutil. --- pw/pw_vpw.c | 236 +++++++++++++++++------------------------------------------- 1 file changed, 67 insertions(+), 169 deletions(-) diff --git a/pw/pw_vpw.c b/pw/pw_vpw.c index 674b64f..99663be 100644 --- a/pw/pw_vpw.c +++ b/pw/pw_vpw.c @@ -30,6 +30,10 @@ static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ +#include +#include +#include +#define _WITH_GETLINE #include #include #include @@ -55,101 +59,44 @@ vsetpwent(void) } static struct passwd * -vnextpwent(char const * nam, uid_t uid, int doclose) +vnextpwent(char const *nam, uid_t uid, int doclose) { - struct passwd * pw = NULL; - static char pwtmp[1024]; - - strlcpy(pwtmp, getpwpath(_MASTERPASSWD), sizeof(pwtmp)); - - if (pwd_fp != NULL || (pwd_fp = fopen(pwtmp, "r")) != NULL) { - int done = 0; - - static struct passwd pwd; - - while (!done && fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL) - { - int i, quickout = 0; - char * q; - char * p = strchr(pwtmp, '\n'); - - if (p == NULL) { - while (fgets(pwtmp, sizeof pwtmp, pwd_fp) != NULL && strchr(pwtmp, '\n')==NULL) - ; /* Skip long lines */ - continue; - } - - /* skip comments & empty lines */ - if (*pwtmp =='\n' || *pwtmp == '#') + struct passwd *pw; + char *line; + size_t linecap; + ssize_t linelen; + + pw = NULL; + line = NULL; + linecap = 0; + linelen = 0; + + if (pwd_fp != NULL || (pwd_fp = fopen(getpwpath(_MASTERPASSWD), "r")) != NULL) { + while ((linelen = getline(&line, &linecap, pwd_fp)) > 0) { + /* Skip comments and empty lines */ + if (*line == '\n' || *line == '#') continue; - - i = 0; - q = p = pwtmp; - bzero(&pwd, sizeof pwd); - while (!quickout && (p = strsep(&q, ":\n")) != NULL) { - switch (i++) - { - case 0: /* username */ - pwd.pw_name = p; - if (nam) { - if (strcmp(nam, p) == 0) - done = 1; - else - quickout = 1; - } - break; - case 1: /* password */ - pwd.pw_passwd = p; - break; - case 2: /* uid */ - pwd.pw_uid = atoi(p); - if (uid != (uid_t)-1) { - if (uid == pwd.pw_uid) - done = 1; - else - quickout = 1; - } - break; - case 3: /* gid */ - pwd.pw_gid = atoi(p); - break; - case 4: /* class */ - if (nam == NULL && uid == (uid_t)-1) - done = 1; - pwd.pw_class = p; - break; - case 5: /* change */ - pwd.pw_change = (time_t)atol(p); - break; - case 6: /* expire */ - pwd.pw_expire = (time_t)atol(p); - break; - case 7: /* gecos */ - pwd.pw_gecos = p; - break; - case 8: /* directory */ - pwd.pw_dir = p; - break; - case 9: /* shell */ - pwd.pw_shell = p; - break; - } - } - } + /* trim latest \n */ + if (line[linelen - 1 ] == '\n') + line[linelen - 1] = '\0'; + pw = pw_scan(line, PWSCAN_MASTER); + if (uid != (uid_t)-1) { + if (uid == pw->pw_uid) + break; + } else if (nam != NULL) { + if (strcmp(nam, pw->pw_name) == 0) + break; + } else + break; + free(pw); + pw = NULL; + } if (doclose) vendpwent(); - if (done && pwd.pw_name) { - pw = &pwd; + } + free(line); - #define CKNULL(s) s = s ? s : "" - CKNULL(pwd.pw_passwd); - CKNULL(pwd.pw_class); - CKNULL(pwd.pw_gecos); - CKNULL(pwd.pw_dir); - CKNULL(pwd.pw_shell); - } - } - return pw; + return (pw); } struct passwd * @@ -192,93 +139,44 @@ vsetgrent(void) } static struct group * -vnextgrent(char const * nam, gid_t gid, int doclose) +vnextgrent(char const *nam, gid_t gid, int doclose) { - struct group * gr = NULL; - - static char * grtmp = NULL; - static int grlen = 0; - static char ** mems = NULL; - static int memlen = 0; - - extendline(&grtmp, &grlen, MAXPATHLEN); - strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN); - - if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) { - int done = 0; - - static struct group grp; - - while (!done && fgets(grtmp, grlen, grp_fp) != NULL) - { - int i, quickout = 0; - int mno = 0; - char * q, * p; - const char * sep = ":\n"; - - if ((p = strchr(grtmp, '\n')) == NULL) { - int l; - extendline(&grtmp, &grlen, grlen + PWBUFSZ); - l = strlen(grtmp); - if (fgets(grtmp + l, grlen - l, grp_fp) == NULL) - break; /* No newline terminator on last line */ - } + struct group *gr; + char *line; + size_t linecap; + ssize_t linelen; + + gr = NULL; + line = NULL; + linecap = 0; + linelen = 0; + + if (grp_fp != NULL || (grp_fp = fopen(getgrpath(_GROUP), "r")) != NULL) { + while ((linelen = getline(&line, &linecap, grp_fp)) > 0) { /* Skip comments and empty lines */ - if (*grtmp == '\n' || *grtmp == '#') + if (*line == '\n' || *line == '#') continue; - i = 0; - q = p = grtmp; - bzero(&grp, sizeof grp); - extendarray(&mems, &memlen, 200); - while (!quickout && (p = strsep(&q, sep)) != NULL) { - switch (i++) - { - case 0: /* groupname */ - grp.gr_name = p; - if (nam) { - if (strcmp(nam, p) == 0) - done = 1; - else - quickout = 1; - } - break; - case 1: /* password */ - grp.gr_passwd = p; + /* trim latest \n */ + if (line[linelen - 1 ] == '\n') + line[linelen - 1] = '\0'; + gr = gr_scan(line); + if (gid != (gid_t)-1) { + if (gid == gr->gr_gid) break; - case 2: /* gid */ - grp.gr_gid = atoi(p); - if (gid != (gid_t)-1) { - if (gid == (gid_t)grp.gr_gid) - done = 1; - else - quickout = 1; - } else if (nam == NULL) - done = 1; + } else if (nam != NULL) { + if (strcmp(nam, gr->gr_name) == 0) break; - case 3: - q = p; - sep = ",\n"; - break; - default: - if (*p) { - extendarray(&mems, &memlen, mno + 2); - mems[mno++] = p; - } - break; - } - } - grp.gr_mem = mems; - mems[mno] = NULL; - } + } else + break; + free(gr); + gr = NULL; + } if (doclose) vendgrent(); - if (done && grp.gr_name) { - gr = &grp; - - CKNULL(grp.gr_passwd); - } } - return gr; + free(line); + + return (gr); } struct group * -- cgit v1.2.3 From ac2faf4bbf898c2f46cb06a82893638622806ac7 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 20:24:44 +0000 Subject: Add O_CLOEXEC to flopen Requested by: jilles --- libutil/gr_util.c | 2 +- libutil/pw_util.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 2f87bd1..4583257 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -101,7 +101,7 @@ gr_lock(void) for (;;) { struct stat st; - lockfd = flopen(group_file, O_RDONLY|O_NONBLOCK, 0); + lockfd = flopen(group_file, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0); if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the group file is busy"); diff --git a/libutil/pw_util.c b/libutil/pw_util.c index 24c0263..befd1fb 100644 --- a/libutil/pw_util.c +++ b/libutil/pw_util.c @@ -179,7 +179,7 @@ pw_lock(void) for (;;) { struct stat st; - lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK, 0); + lockfd = flopen(masterpasswd, O_RDONLY|O_NONBLOCK|O_CLOEXEC, 0); if (lockfd == -1) { if (errno == EWOULDBLOCK) { errx(1, "the password db file is busy"); -- cgit v1.2.3 From 51b9aa2af727f3e728cf8676626c60a2b08747b5 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 20:31:12 +0000 Subject: cast to uintptr_t to properly calculate offset Reported by: mdf Submitted by: db --- libutil/gr_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 4583257..f4a08c4 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -452,7 +452,7 @@ gr_dup(const struct group *gr) return (NULL); /* point new gr_mem to end of struct + 1 */ if (gr->gr_mem != NULL) - newgr->gr_mem = (char **)newgr + sizeof(struct group); + newgr->gr_mem = (char **)((uintptr_t)newgr + sizeof(struct group)); else newgr->gr_mem = NULL; /* point dst after the end of all the gr_mem pointers in newgr */ -- cgit v1.2.3 From aa220b5f62d62ea62dc8ac4e3a26696ee05faba7 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Thu, 27 Dec 2012 20:47:34 +0000 Subject: avoid arithmetic on uintptr_t Submitted by: pjd Reviewed by: jilles --- libutil/gr_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index f4a08c4..437fd78 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -452,7 +452,7 @@ gr_dup(const struct group *gr) return (NULL); /* point new gr_mem to end of struct + 1 */ if (gr->gr_mem != NULL) - newgr->gr_mem = (char **)((uintptr_t)newgr + sizeof(struct group)); + newgr->gr_mem = (char **)(newgr + 1); else newgr->gr_mem = NULL; /* point dst after the end of all the gr_mem pointers in newgr */ -- cgit v1.2.3 From 3a3bcd13e99f20e0db107edca2d675ffb65cadc4 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Fri, 28 Dec 2012 20:19:54 +0000 Subject: Do not leave parts of the new group uninitialized in gr_dup(). Submitted by: Christoph Mallon Reported by: pjd --- libutil/gr_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 437fd78..759e6e8 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -461,10 +461,14 @@ gr_dup(const struct group *gr) if (gr->gr_name != NULL) { newgr->gr_name = dst; dst = stpcpy(dst, gr->gr_name) + 1; + } else { + newgr->gr_name = NULL; } if (gr->gr_passwd != NULL) { newgr->gr_passwd = dst; dst = stpcpy(dst, gr->gr_passwd) + 1; + } else { + newgr->gr_passwd = NULL; } newgr->gr_gid = gr->gr_gid; if (gr->gr_mem != NULL) { -- cgit v1.2.3 From a4ba8cb5d1a040d3dea01a404d49e2bee012a6b5 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Fri, 28 Dec 2012 20:21:14 +0000 Subject: malloc() sets errno to ENOMEM already. Submitted by: Christoph Mallon --- libutil/gr_util.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 759e6e8..6676720 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -505,17 +505,13 @@ gr_add(struct group *gr, char *newmember) } /* Allocate enough for current pointers + 1 more and NULL marker */ mlen = (num_mem + 2) * sizeof(*gr->gr_mem); - if ((members = malloc(mlen)) == NULL) { + if ((members = malloc(mlen)) == NULL) errno = ENOMEM; - return (NULL); - } memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem)); members[num_mem++] = newmember; members[num_mem] = NULL; gr->gr_mem = members; newgr = gr_dup(gr); - if (newgr == NULL) - errno = ENOMEM; free(members); return (newgr); } -- cgit v1.2.3 From e7ae79563ae6e4b961c2343f08df0900b302c822 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Fri, 28 Dec 2012 20:30:04 +0000 Subject: errno = ENOMEM was supposed to be removed not return (NULL); Submitted by: gcooper --- libutil/gr_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 6676720..5f803af 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -506,7 +506,7 @@ gr_add(struct group *gr, char *newmember) /* Allocate enough for current pointers + 1 more and NULL marker */ mlen = (num_mem + 2) * sizeof(*gr->gr_mem); if ((members = malloc(mlen)) == NULL) - errno = ENOMEM; + return (NULL); memcpy(members, gr->gr_mem, num_mem * sizeof(*gr->gr_mem)); members[num_mem++] = newmember; members[num_mem] = NULL; -- cgit v1.2.3 From 8f1370df706a16668cc3a3f9be05d8af396c365c Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Fri, 28 Dec 2012 20:44:10 +0000 Subject: Simplify pointing dst after the end of all the gr_mem pointers in newgr Submitted by: pjd Reviewed by: db --- libutil/gr_util.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libutil/gr_util.c b/libutil/gr_util.c index 5f803af..acb9767 100644 --- a/libutil/gr_util.c +++ b/libutil/gr_util.c @@ -456,8 +456,7 @@ gr_dup(const struct group *gr) else newgr->gr_mem = NULL; /* point dst after the end of all the gr_mem pointers in newgr */ - dst = (char *)newgr + sizeof(struct group) + - (num_mem + 1) * sizeof(*gr->gr_mem); + dst = (char *)&newgr->gr_mem[num_mem + 1]; if (gr->gr_name != NULL) { newgr->gr_name = dst; dst = stpcpy(dst, gr->gr_name) + 1; -- cgit v1.2.3