[Pkg-shadow-commits] r1442 - in upstream/trunk: . lib man
nekral-guest at alioth.debian.org
nekral-guest at alioth.debian.org
Fri Nov 23 00:07:59 UTC 2007
Author: nekral-guest
Date: 2007-11-23 00:07:59 +0000 (Fri, 23 Nov 2007)
New Revision: 1442
Modified:
upstream/trunk/ChangeLog
upstream/trunk/NEWS
upstream/trunk/lib/commonio.c
upstream/trunk/lib/commonio.h
upstream/trunk/lib/getdef.c
upstream/trunk/lib/groupio.c
upstream/trunk/lib/pwio.c
upstream/trunk/lib/sgroupio.c
upstream/trunk/lib/shadowio.c
upstream/trunk/man/login.defs.5.xml
Log:
* NEWS, lib/getdef.c, man/login.defs.5.xml: New login.defs
variable: MAX_MEMBERS_PER_GROUP. Used for the split groups support.
* lib/commonio.c, lib/commonio.h: Add an open_hook and close_hook
operation. They are called after the database is actually opened
and parse, or before it is closed.
* lib/groupio.c: Add an open_hook to merge split groups, and an
close group to split groups if MAX_MEMBERS_PER_GROUP is set.
This fixes gpasswd and chgpasswd when split groups are used.
* lib/sgroupio.c, lib/shadowio.c, lib/pwio.c: No open or close
hooks for these databases. (unsure about what should be the gshadow
behavior for split groups)
Modified: upstream/trunk/ChangeLog
===================================================================
--- upstream/trunk/ChangeLog 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/ChangeLog 2007-11-23 00:07:59 UTC (rev 1442)
@@ -1,5 +1,19 @@
2007-11-22 Nicolas François <nicolas.francois at centraliens.net>
+ * NEWS, lib/getdef.c, man/login.defs.5.xml: New login.defs
+ variable: MAX_MEMBERS_PER_GROUP. Used for the split groups support.
+ * lib/commonio.c, lib/commonio.h: Add an open_hook and close_hook
+ operation. They are called after the database is actually opened
+ and parse, or before it is closed.
+ * lib/groupio.c: Add an open_hook to merge split groups, and an
+ close group to split groups if MAX_MEMBERS_PER_GROUP is set.
+ This fixes gpasswd and chgpasswd when split groups are used.
+ * lib/sgroupio.c, lib/shadowio.c, lib/pwio.c: No open or close
+ hooks for these databases. (unsure about what should be the gshadow
+ behavior for split groups)
+
+2007-11-22 Nicolas François <nicolas.francois at centraliens.net>
+
* NEWS, src/gpasswd.c: Read the group and shadow groups using
gr_locate and sgr_locate. gpasswd write in the file database. Thus
it should read information from the file database, not using
Modified: upstream/trunk/NEWS
===================================================================
--- upstream/trunk/NEWS 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/NEWS 2007-11-23 00:07:59 UTC (rev 1442)
@@ -46,6 +46,10 @@
- gpasswd: Only read information from the local file group database. It
writes the changes in /etc/group and/or /etc/gshadow, but used to read
information from getgrnam (hence possibly from another group database).
+- New login.defs variable: MAX_MEMBERS_PER_GROUP. It should provide a
+ better support for split groups. Be careful when using this variable:
+ not all tools support well split groups (in or out of the shadow
+ tool suite). It fixes gpasswd and chgpasswd when split groups are used.
*** documentation:
- Generate the translated manpages from PO at build time.
Modified: upstream/trunk/lib/commonio.c
===================================================================
--- upstream/trunk/lib/commonio.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/commonio.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -520,6 +520,9 @@
if (ferror (db->fp))
goto cleanup_errno;
+ if (db->ops->open_hook && !db->ops->open_hook ())
+ goto cleanup_errno;
+
db->isopen = 1;
return 1;
@@ -669,6 +672,9 @@
goto success;
}
+ if (db->ops->close_hook && !db->ops->close_hook ())
+ goto fail;
+
memzero (&sb, sizeof sb);
if (db->fp) {
if (fstat (fileno (db->fp), &sb)) {
Modified: upstream/trunk/lib/commonio.h
===================================================================
--- upstream/trunk/lib/commonio.h 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/commonio.h 2007-11-23 00:07:59 UTC (rev 1442)
@@ -52,6 +52,15 @@
*/
char *(*fgets) (char *, int, FILE *);
int (*fputs) (const char *, FILE *);
+
+ /*
+ * open_hook and close_hook.
+ * If non NULL, these functions will be called after the database
+ * is open or before it is closed.
+ * They return 0 on failure and 1 on success.
+ */
+ int (*open_hook) (void);
+ int (*close_hook) (void);
};
/*
Modified: upstream/trunk/lib/getdef.c
===================================================================
--- upstream/trunk/lib/getdef.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/getdef.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -68,6 +68,7 @@
{"LOG_UNKFAIL_ENAB", NULL},
{"MAIL_DIR", NULL},
{"MAIL_FILE", NULL},
+ {"MAX_MEMBERS_PER_GROUP", NULL},
{"MD5_CRYPT_ENAB", NULL},
{"PASS_MAX_DAYS", NULL},
{"PASS_MIN_DAYS", NULL},
Modified: upstream/trunk/lib/groupio.c
===================================================================
--- upstream/trunk/lib/groupio.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/groupio.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -10,6 +10,11 @@
extern int putgrent (const struct group *, FILE *);
extern struct group *sgetgrent (const char *);
+static struct commonio_entry *merge_group_entries (struct commonio_entry *,
+ struct commonio_entry *);
+static int split_groups (unsigned int);
+static int group_open_hook (void);
+
static void *group_dup (const void *ent)
{
const struct group *gr = ent;
@@ -49,6 +54,16 @@
return (putgrent (gr, file) == -1) ? -1 : 0;
}
+static int group_close_hook (void)
+{
+ unsigned int max_members = getdef_unum("MAX_MEMBERS_PER_GROUP", 0);
+
+ if (0 == max_members)
+ return 1;
+
+ return split_groups (max_members);
+}
+
static struct commonio_ops group_ops = {
group_dup,
group_free,
@@ -56,7 +71,9 @@
group_parse,
group_put,
fgetsx,
- fputsx
+ fputsx,
+ group_open_hook,
+ group_close_hook
};
static struct commonio_db group_db = {
@@ -170,3 +187,171 @@
{
return commonio_sort (&group_db, gr_cmp);
}
+
+static int group_open_hook (void)
+{
+ unsigned int max_members = getdef_unum("MAX_MEMBERS_PER_GROUP", 0);
+ struct commonio_entry *gr1, *gr2;
+
+ if (0 == max_members)
+ return 1;
+
+ for (gr1 = group_db.head; gr1; gr1 = gr1->next) {
+ for (gr2 = gr1->next; gr2; gr2 = gr2->next) {
+ struct group *g1 = (struct group *)gr1->eptr;
+ struct group *g2 = (struct group *)gr2->eptr;
+ if (NULL != g1 &&
+ NULL != g2 &&
+ 0 == strcmp (g1->gr_name, g2->gr_name) &&
+ 0 == strcmp (g1->gr_passwd, g2->gr_passwd) &&
+ g1->gr_gid == g2->gr_gid) {
+ /* Both group entries refer to the same
+ * group. It is a split group. Merge the
+ * members. */
+ gr1 = merge_group_entries (gr1, gr2);
+ if (NULL == gr1)
+ return 0;
+ /* Unlink gr2 */
+ if (NULL != gr2->next)
+ gr2->next->prev = gr2->prev;
+ gr2->prev->next = gr2->next;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Merge the list of members of the two group entries.
+ *
+ * The commonio_entry arguments shall be group entries.
+ *
+ * You should not merge the members of two groups if they don't have the
+ * same name, password and gid.
+ *
+ * It merge the members of the second entry in the first one, and return
+ * the modified first entry on success, or NUll on failure (with errno
+ * set).
+ */
+static struct commonio_entry *merge_group_entries (struct commonio_entry *gr1,
+ struct commonio_entry *gr2)
+{
+ struct group *gptr1;
+ struct group *gptr2;
+ char *member;
+ char **new_members;
+ int members = 0;
+ char *new_line;
+ int new_line_len, i;
+ if (NULL == gr2 || NULL == gr1) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ gptr1 = (struct group *)gr1->eptr;
+ gptr2 = (struct group *)gr2->eptr;
+ if (NULL == gptr2 || NULL == gptr1) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Concatenate the 2 lines */
+ new_line_len = strlen (gr1->line) + strlen (gr2->line) +1;
+ new_line = (char *)malloc ((new_line_len + 1) * sizeof(char*));
+ if (NULL == new_line) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ snprintf(new_line, new_line_len, "%s\n%s", gr1->line, gr2->line);
+ new_line[new_line_len] = '\0';
+
+ /* Concatenate the 2 list of members */
+ for (i=0; NULL != gptr1->gr_mem[i]; i++);
+ members += i;
+ for (i=0; NULL != gptr2->gr_mem[i]; i++) {
+ char **pmember = gptr1->gr_mem;
+ while (NULL != *pmember) {
+ if (0 == strcmp(*pmember, gptr2->gr_mem[i]))
+ break;
+ pmember++;
+ }
+ if (NULL == *pmember)
+ members++;
+ }
+ new_members = (char **)malloc ( (members+1) * sizeof(char*) );
+ if (NULL == new_members) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ for (i=0; NULL != gptr1->gr_mem[i]; i++)
+ new_members[i] = gptr1->gr_mem[i];
+ members = i;
+ for (i=0; NULL != gptr2->gr_mem[i]; i++) {
+ char **pmember = new_members;
+ while (NULL != *pmember) {
+ if (0 == strcmp(*pmember, gptr2->gr_mem[i]))
+ break;
+ pmember++;
+ }
+ if (NULL == *pmember) {
+ new_members[members++] = gptr2->gr_mem[i];
+ new_members[members] = NULL;
+ }
+ }
+
+ gr1->line = new_line;
+ gptr1->gr_mem = new_members;
+
+ return gr1;
+}
+
+/*
+ * Scan the group database and split the groups which have more members
+ * than specified, if this is the result from a current change.
+ *
+ * Return 0 on failure (errno set) and 1 on success.
+ */
+static int split_groups (unsigned int max_members)
+{
+ struct commonio_entry *gr;
+
+ for (gr = group_db.head; gr; gr = gr->next) {
+ struct group *gptr = (struct group *)gr->eptr;
+ struct commonio_entry *new;
+ struct group *new_gptr;
+ unsigned int members = 0;
+
+ /* Check if this group must be split */
+ if (!gr->changed)
+ continue;
+ if (NULL == gptr)
+ continue;
+ for (members = 0; NULL != gptr->gr_mem[members]; members++);
+ if (members <= max_members)
+ continue;
+
+ new = (struct commonio_entry *) malloc (sizeof *new);
+ new->eptr = group_dup(gr->eptr);
+ if (NULL == new->eptr) {
+ errno = ENOMEM;
+ return 0;
+ }
+ new_gptr = (struct group *)new->eptr;
+ new->line = NULL;
+ new->changed = 1;
+
+ /* Enforce the maximum number of members on gptr */
+ gptr->gr_mem[max_members] = NULL;
+ /* The number of members in new_gptr will be check later */
+ new_gptr->gr_mem = &new_gptr->gr_mem[max_members];
+
+ /* insert the new entry in the list */
+ new->prev = gr;
+ new->next = gr->next;
+ gr->next = new;
+ }
+
+ return 1;
+}
+
Modified: upstream/trunk/lib/pwio.c
===================================================================
--- upstream/trunk/lib/pwio.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/pwio.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -57,7 +57,9 @@
passwd_parse,
passwd_put,
fgets,
- fputs
+ fputs,
+ NULL, /* open_hook */
+ NULL /* close_hook */
};
static struct commonio_db passwd_db = {
Modified: upstream/trunk/lib/sgroupio.c
===================================================================
--- upstream/trunk/lib/sgroupio.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/sgroupio.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -100,7 +100,9 @@
gshadow_parse,
gshadow_put,
fgetsx,
- fputsx
+ fputsx,
+ NULL, /* open_hook */
+ NULL /* close_hook */
};
static struct commonio_db gshadow_db = {
Modified: upstream/trunk/lib/shadowio.c
===================================================================
--- upstream/trunk/lib/shadowio.c 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/lib/shadowio.c 2007-11-23 00:07:59 UTC (rev 1442)
@@ -54,7 +54,9 @@
shadow_parse,
shadow_put,
fgets,
- fputs
+ fputs,
+ NULL, /* open_hook */
+ NULL /* close_hook */
};
static struct commonio_db shadow_db = {
Modified: upstream/trunk/man/login.defs.5.xml
===================================================================
--- upstream/trunk/man/login.defs.5.xml 2007-11-22 21:55:12 UTC (rev 1441)
+++ upstream/trunk/man/login.defs.5.xml 2007-11-23 00:07:59 UTC (rev 1442)
@@ -122,6 +122,36 @@
</listitem>
</varlistentry>
<varlistentry>
+ <term>MAX_MEMBERS_PER_GROUP (number)</term>
+ <listitem>
+ <para>
+ Maximum members per group entry. When the maximum is reached,
+ a new group entry (line) is started is
+ <filename>/etc/group</filename> (with the same name, same
+ password, and same GID).
+ </para>
+ <para>
+ The default value is 0, meaning that there are no limits in
+ the number of members in a group.
+ </para>
+ <!-- Note: on HP, split groups have the same ID, but different
+ names. -->
+ <para>
+ This feature (split group) permits to limit the length of
+ lines in the group file. This is useful to make sure that
+ lines for NIS groups are not larger than 1024 characters.
+ </para>
+ <para>
+ If you need to enforce such limit, you can use 25.
+ </para>
+ <para>
+ Note: split groups may not be supported by all tools (even in
+ the Shadow toolsuite. Yous hould not use this variable unless
+ you really need it.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>MD5_CRYPT_ENAB (boolean)</term>
<listitem>
<para>
More information about the Pkg-shadow-commits
mailing list