diff --git a/lib/Makefile.am b/lib/Makefile.am index 6db86cd62..1a4a884a3 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,10 +1,11 @@ AUTOMAKE_OPTIONS = 1.0 foreign -DEFS = +DEFS = noinst_LTLIBRARIES = libshadow.la +libshadow_la_LIBADD = ../libmisc/libmisc.la libshadow_la_LDFLAGS = -version-info 0:0:0 libshadow_la_SOURCES = \ diff --git a/lib/prototypes.h b/lib/prototypes.h index 4808d5d98..e35a77699 100644 --- a/lib/prototypes.h +++ b/lib/prototypes.h @@ -229,8 +229,10 @@ extern void setup_limits (const struct passwd *); extern /*@only@*/ /*@out@*/char **add_list (/*@returned@*/ /*@only@*/char **, const char *); extern /*@only@*/ /*@out@*/char **del_list (/*@returned@*/ /*@only@*/char **, const char *); extern /*@only@*/ /*@out@*/char **dup_list (char *const *); +extern /*@only@*/ /*@out@*/void free_list (char *const *); extern bool is_on_list (char *const *list, const char *member); extern /*@only@*/char **comma_to_list (const char *); +extern /*@only@*/char *comma_from_list (char *const *); /* log.c */ extern void dolastlog ( diff --git a/lib/subordinateio.c b/lib/subordinateio.c index 0d64a9148..1cf03b66a 100644 --- a/lib/subordinateio.c +++ b/lib/subordinateio.c @@ -18,9 +18,11 @@ struct subordinate_range { const char *owner; unsigned long start; unsigned long count; + char **options; }; -#define NFIELDS 3 +#define NFIELDS_MIN 3 +#define NFIELDS_MAX 4 /* * subordinate_dup: create a duplicate range @@ -46,6 +48,7 @@ static /*@null@*/ /*@only@*/void *subordinate_dup (const void *ent) } range->start = rangeent->start; range->count = rangeent->count; + range->options = dup_list(rangeent->options); return range; } @@ -58,8 +61,9 @@ static /*@null@*/ /*@only@*/void *subordinate_dup (const void *ent) static void subordinate_free (/*@out@*/ /*@only@*/void *ent) { struct subordinate_range *rangeent = ent; - + free ((void *)(rangeent->owner)); + free_list(rangeent->options); free (rangeent); } @@ -76,9 +80,9 @@ static void *subordinate_parse (const char *line) { static struct subordinate_range range; static char rangebuf[1024]; - int i; + int i, j; char *cp; - char *fields[NFIELDS]; + char *fields[NFIELDS_MAX]; /* * Copy the string to a temporary buffer so the substrings can @@ -93,7 +97,7 @@ static void *subordinate_parse (const char *line) * field. The fields are converted into NUL terminated strings. */ - for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) { + for (cp = rangebuf, i = 0; (i < NFIELDS_MAX) && (NULL != cp); i++) { fields[i] = cp; while (('\0' != *cp) && (':' != *cp)) { cp++; @@ -108,16 +112,23 @@ static void *subordinate_parse (const char *line) } /* - * There must be exactly NFIELDS colon separated fields or - * the entry is invalid. Also, fields must be non-blank. + * There must be at least NFIELDS_MIN and at most NFIELDS_MAX colon + * separated fields or the entry is invalid. The first NFIELDS_MIN fields + * must be non-blank. */ - if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0') + if (i < NFIELDS_MIN || i > NFIELDS_MAX) return NULL; + for (j = 0; j < NFIELDS_MIN; j++) + if (*fields[j] == '\0') + return NULL; + range.owner = fields[0]; if (getulong (fields[1], &range.start) == 0) return NULL; if (getulong (fields[2], &range.count) == 0) return NULL; + if (i >= 4) + range.options = comma_to_list(fields[3]); return ⦥ } @@ -133,11 +144,15 @@ static void *subordinate_parse (const char *line) static int subordinate_put (const void *ent, FILE * file) { const struct subordinate_range *range = ent; + char *options = comma_from_list(range->options); - return fprintf(file, "%s:%lu:%lu\n", - range->owner, - range->start, - range->count) < 0 ? -1 : 0; + int n = fprintf(file, "%s:%lu:%lu:%s\n", + range->owner, + range->start, + range->count, + options ?: ""); + free(options); + return n < 0 ? -1 : 0; } static struct commonio_ops subordinate_ops = { @@ -285,38 +300,41 @@ static const struct subordinate_range *find_range(struct commonio_db *db, } /* - * have_range: check whether @owner is authorized to use the range - * (@start .. @start+@count-1). + * get_range: check whether @owner is authorized to use the range + * (@start .. @start+@count-1) and return the first matching range. * @db: database to check * @owner: owning uid being queried * @start: start of range * @count: number of uids in range * - * Returns true if @owner is authorized to use the range, false otherwise. + * Returns the corresponding subordinate_range if @owner is authorized to use + * the range, NULL otherwise. */ -static bool have_range(struct commonio_db *db, - const char *owner, unsigned long start, unsigned long count) +static const struct subordinate_range *get_range(struct commonio_db *db, + const char *owner, + unsigned long start, + unsigned long count) { const struct subordinate_range *range; unsigned long end; if (count == 0) - return false; + return NULL; end = start + count - 1; range = find_range (db, owner, start); while (range) { - unsigned long last; + unsigned long last; last = range->start + range->count - 1; if (last >= (start + count - 1)) - return true; + return range; count = end - last; start = last + 1; range = find_range(db, owner, start); } - return false; + return NULL; } /* @@ -430,7 +448,7 @@ static int add_range(struct commonio_db *db, range.count = count; /* See if the range is already present */ - if (have_range(db, owner, start, count)) + if (get_range(db, owner, start, count)) return 1; /* Otherwise append the range */ @@ -585,7 +603,12 @@ bool sub_uid_assigned(const char *owner) bool have_sub_uids(const char *owner, uid_t start, unsigned long count) { - return have_range (&subordinate_uid_db, owner, start, count); + return NULL != get_range (&subordinate_uid_db, owner, start, count); +} + +char **sub_uid_options(const char *owner, uid_t start, unsigned long count) +{ + return dup_list(get_range(&subordinate_uid_db, owner, start, count)->options); } int sub_uid_add (const char *owner, uid_t start, unsigned long count) @@ -661,7 +684,12 @@ int sub_gid_open (int mode) bool have_sub_gids(const char *owner, gid_t start, unsigned long count) { - return have_range(&subordinate_gid_db, owner, start, count); + return NULL != get_range (&subordinate_gid_db, owner, start, count); +} + +char **sub_gid_options(const char *owner, gid_t start, unsigned long count) +{ + return dup_list(get_range(&subordinate_gid_db, owner, start, count)->options); } bool sub_gid_assigned(const char *owner) diff --git a/lib/subordinateio.h b/lib/subordinateio.h index a21d72b8e..d5a054e6b 100644 --- a/lib/subordinateio.h +++ b/lib/subordinateio.h @@ -13,6 +13,7 @@ extern int sub_uid_close(void); extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count); +extern char **sub_uid_options(const char *owner, uid_t start, unsigned long count); extern bool sub_uid_file_present (void); extern bool sub_uid_assigned(const char *owner); extern int sub_uid_lock (void); @@ -26,6 +27,7 @@ extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count); extern int sub_gid_close(void); extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count); +extern char **sub_gid_options(const char *owner, uid_t start, unsigned long count); extern bool sub_gid_file_present (void); extern bool sub_gid_assigned(const char *owner); extern int sub_gid_lock (void); diff --git a/libmisc/Makefile.am b/libmisc/Makefile.am index 4a6204956..ee493441c 100644 --- a/libmisc/Makefile.am +++ b/libmisc/Makefile.am @@ -3,9 +3,9 @@ EXTRA_DIST = .indent.pro xgetXXbyYY.c AM_CPPFLAGS = -I$(top_srcdir)/lib -noinst_LIBRARIES = libmisc.a +noinst_LTLIBRARIES = libmisc.la -libmisc_a_SOURCES = \ +libmisc_la_SOURCES = \ addgrps.c \ age.c \ audit_help.c \ diff --git a/libmisc/list.c b/libmisc/list.c index 2da734a74..4b46947cc 100644 --- a/libmisc/list.c +++ b/libmisc/list.c @@ -152,7 +152,8 @@ int i; char **tmp; - assert (NULL != list); + if (NULL == list) + return NULL; for (i = 0; NULL != list[i]; i++); @@ -169,6 +170,23 @@ return tmp; } +/* + * Free a list. + * The output list isn't modified, but the memory is freed. + */ +void free_list (char *const *list) +{ + int i; + + if (NULL == list) + return; + + for (i = 0; NULL != list[i]; i++) + free(list[i]); + free((void *)list); +} + + /* * Check if member is part of the input list * The input list is not modified, but in order to allow the use of this @@ -269,3 +287,30 @@ bool is_on_list (char *const *list, const char *member) return array; } +/* + * comma_from_list - inverse of comma_to_list + */ + +/*@only@*/char *comma_from_list (char *const *list) +{ + char *comma; + int i, commalen = 0; + + if (NULL == list) + return NULL; + + for (i = 0; NULL != list[i]; i++) + commalen += strlen(list[i]) + 1; + + comma = xmalloc(commalen + 1); + memset(comma, '\0', commalen + 1); + + for (i = 0; NULL != list[i]; i++) { + int j = strlen(comma); + if (j > 0) + comma[j++] = ','; + strncat(comma, list[i], commalen - j); + } + + return comma; +} diff --git a/man/groupmod.8.xml b/man/groupmod.8.xml index e1db14ddd..0b37b0be2 100644 --- a/man/groupmod.8.xml +++ b/man/groupmod.8.xml @@ -3,7 +3,7 @@ Copyright (c) 1991 , Julianne Frances Haugh Copyright (c) 2007 - 2011, Nicolas François All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -15,7 +15,7 @@ 3. The name of the copyright holders or contributors may not be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A @@ -136,7 +136,7 @@ ,  NEW_GROUP - + The name of the group will be changed from GROUP to NEW_GROUP name. @@ -278,16 +278,19 @@ E_GRP_UPDATE: can't update group file + 11 E_CLEANUP_SERVICE: can't setup cleanup service + 12 E_PAM_USERNAME: can't determine your username for use with pam + 13 E_PAM_ERROR: pam returned an error, see syslog facility id groupmod for the PAM error message diff --git a/man/newgidmap.1.xml b/man/newgidmap.1.xml index 864bad14a..217488786 100644 --- a/man/newgidmap.1.xml +++ b/man/newgidmap.1.xml @@ -2,7 +2,7 @@