--- shadow-4.0.18.1/src/useradd.c.sysAccount 2007-03-12 10:49:14.000000000 +0100 +++ shadow-4.0.18.1/src/useradd.c 2007-03-12 12:15:57.000000000 +0100 @@ -854,6 +854,7 @@ { const struct passwd *pwd; uid_t uid_min, uid_max; + char * index; if (!rflg) { uid_min = getdef_unum ("UID_MIN", 500); @@ -862,6 +863,8 @@ else { uid_min = 1; uid_max = getdef_unum ("UID_MIN", 500) - 1; + index = alloca (sizeof (char) * uid_max +1); + memset (index, 0, sizeof (char) * uid_max + 1); } /* @@ -901,11 +904,24 @@ #endif exit (E_UID_IN_USE); } - if (!uflg && pwd->pw_uid >= user_id) { + if (!uflg && !rflg && pwd->pw_uid >= user_id) { if (pwd->pw_uid > uid_max) continue; user_id = pwd->pw_uid + 1; } + /* create index of occupied system accounts UIDs */ + if (!uflg && rflg && (pwd->pw_uid <= uid_max)) + index[pwd->pw_uid] = 1; + + } + + /* find free system account */ + if(!uflg && rflg) { + for( user_id = uid_max; (user_id >= uid_min) && index[user_id]; user_id--); + if ( user_id < uid_min ) { + fprintf (stderr, _("%s: can't get unique UID\n"), Prog); + fail_exit (E_UID_IN_USE); + } } /* @@ -946,6 +962,7 @@ { const struct group *grp; gid_t gid_min, gid_max; + char * index; if (!rflg) { gid_min = getdef_unum ("GID_MIN", 500); @@ -953,7 +970,9 @@ } else { gid_min = 1; gid_max = getdef_unum ("GID_MIN", 500) - 1; - } + index = alloca (sizeof (char) * gid_max +1); + memset (index, 0, sizeof (char) * gid_max + 1); + } /* * Start with some GID value if the user didn't provide us with @@ -978,12 +997,16 @@ user_gid = grp->gr_gid; return; } - if (grp->gr_gid >= user_gid) { + if (!rflg && grp->gr_gid >= user_gid) { if (grp->gr_gid > gid_max) continue; user_gid = grp->gr_gid + 1; } + /* create index of occupied system accounts GIDs */ + if (rflg && (grp->gr_gid <= gid_max)) + index[grp->gr_gid] = 1; } + #ifndef NO_GETGRENT /* glibc does have this, so ... */ /* A quick test gets here: if the UID is available * as a GID, go ahead and use it */ @@ -992,6 +1015,18 @@ return; } #endif + + /* find free system account */ + if(rflg) { + for( user_gid = gid_max; (user_gid >= gid_min) && index[user_gid]; user_gid--); + if ( user_gid < gid_min ) { + fprintf (stderr, + "%s: can't get unique gid (run out of GIDs)\n", + Prog); + fail_exit (4); + } + } + if (user_gid == gid_max + 1) { for (user_gid = gid_min; user_gid < gid_max; user_gid++) { #ifdef NO_GETGRENT --- shadow-4.0.18.1/src/groupadd.c.sysAccount 2007-03-12 10:49:14.000000000 +0100 +++ shadow-4.0.18.1/src/groupadd.c 2007-03-12 10:49:14.000000000 +0100 @@ -199,6 +199,7 @@ { const struct group *grp; gid_t gid_min, gid_max; + char * index; if (!rflg) { gid_min = getdef_unum ("GID_MIN", 500); @@ -206,7 +207,9 @@ } else { gid_min = 1; gid_max = getdef_unum ("GID_MIN", 500) - 1; - } + index = alloca (sizeof (char) * gid_max +1); + memset (index, 0, sizeof (char) * gid_max + 1); + } /* * Start with some GID value if the user didn't provide us with @@ -251,12 +254,25 @@ Prog, (unsigned int) group_id); fail_exit (E_GID_IN_USE); } - if (!gflg && grp->gr_gid >= group_id) { + if (!gflg && !rflg && grp->gr_gid >= group_id) { if (grp->gr_gid > gid_max) continue; group_id = grp->gr_gid + 1; } + /* create index of occupied system accounts UIDs */ + if (!gflg && rflg && (grp->gr_gid <= gid_max)) + index[grp->gr_gid] = 1; + } + + /* find free system account */ + if(!gflg && rflg) { + for( group_id = gid_max; (group_id >= gid_min) && index[group_id]; group_id--); + if ( group_id < gid_min ) { + fprintf (stderr, _("%s: can't get unique GID\n"), Prog); + fail_exit (E_GID_IN_USE); + } } + if (!gflg && group_id == gid_max + 1) { for (group_id = gid_min; group_id < gid_max; group_id++) { #ifdef NO_GETGRENT