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 @@