* NEWS, src/userdel.c: Do not remove a group with the same name as
the user (usergroup) if this group isn't the user's primary group.
This commit is contained in:
parent
14f44bd9c9
commit
a8ca723277
@ -1,3 +1,8 @@
|
|||||||
|
2011-06-05 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
|
* NEWS, src/userdel.c: Do not remove a group with the same name as
|
||||||
|
the user (usergroup) if this group isn't the user's primary group.
|
||||||
|
|
||||||
2011-06-04 Nicolas François <nicolas.francois@centraliens.net>
|
2011-06-04 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* NEWS, src/userdel.c: Check the existence of the user's mail
|
* NEWS, src/userdel.c: Check the existence of the user's mail
|
||||||
|
2
NEWS
2
NEWS
@ -47,6 +47,8 @@ shadow-4.1.4.3 -> shadow-4.1.5 UNRELEASED
|
|||||||
- userdel
|
- userdel
|
||||||
* Check the existence of the user's mail spool before trying to remove
|
* Check the existence of the user's mail spool before trying to remove
|
||||||
it. If it does not exist, a warning is issued, but no failure.
|
it. If it does not exist, a warning is issued, but no failure.
|
||||||
|
* Do not remove a group with the same name as the user (usergroup) if
|
||||||
|
this group isn't the user's primary group.
|
||||||
- usermod
|
- usermod
|
||||||
* Accept options in any order (username not necessarily at the end)
|
* Accept options in any order (username not necessarily at the end)
|
||||||
|
|
||||||
|
182
src/userdel.c
182
src/userdel.c
@ -82,6 +82,7 @@ const char *Prog;
|
|||||||
|
|
||||||
static char *user_name;
|
static char *user_name;
|
||||||
static uid_t user_id;
|
static uid_t user_id;
|
||||||
|
static gid_t user_gid;
|
||||||
static char *user_home;
|
static char *user_home;
|
||||||
|
|
||||||
static bool fflg = false;
|
static bool fflg = false;
|
||||||
@ -100,6 +101,7 @@ static bool spw_locked = false;
|
|||||||
/* local function prototypes */
|
/* local function prototypes */
|
||||||
static void usage (int status);
|
static void usage (int status);
|
||||||
static void update_groups (void);
|
static void update_groups (void);
|
||||||
|
static void remove_usergroup (void);
|
||||||
static void close_files (void);
|
static void close_files (void);
|
||||||
static void fail_exit (int);
|
static void fail_exit (int);
|
||||||
static void open_files (void);
|
static void open_files (void);
|
||||||
@ -145,10 +147,8 @@ static void update_groups (void)
|
|||||||
{
|
{
|
||||||
const struct group *grp;
|
const struct group *grp;
|
||||||
struct group *ngrp;
|
struct group *ngrp;
|
||||||
struct passwd *pwd;
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
bool deleted_user_group = false;
|
|
||||||
const struct sgrp *sgrp;
|
const struct sgrp *sgrp;
|
||||||
struct sgrp *nsgrp;
|
struct sgrp *nsgrp;
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
@ -199,69 +199,10 @@ static void update_groups (void)
|
|||||||
user_name, ngrp->gr_name));
|
user_name, ngrp->gr_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (getdef_bool ("USERGROUPS_ENAB")) {
|
||||||
* we've removed their name from all the groups above, so
|
remove_usergroup ();
|
||||||
* now if they have a group with the same name as their
|
|
||||||
* user name, with no members, we delete it.
|
|
||||||
* FIXME: below, the check for grp->gr_mem[0] is not sufficient.
|
|
||||||
* We should retrieve the group with gr_locate and check
|
|
||||||
* that gr_mem is empty.
|
|
||||||
*/
|
|
||||||
grp = xgetgrnam (user_name);
|
|
||||||
if ( (NULL != grp)
|
|
||||||
&& getdef_bool ("USERGROUPS_ENAB")
|
|
||||||
&& ( (NULL == grp->gr_mem[0])
|
|
||||||
|| ( (NULL == grp->gr_mem[1])
|
|
||||||
&& (strcmp (grp->gr_mem[0], user_name) == 0)))) {
|
|
||||||
|
|
||||||
pwd = NULL;
|
|
||||||
if (!fflg) {
|
|
||||||
/*
|
|
||||||
* Scan the passwd file to check if this group is still
|
|
||||||
* used as a primary group.
|
|
||||||
*/
|
|
||||||
setpwent ();
|
|
||||||
while ((pwd = getpwent ()) != NULL) {
|
|
||||||
if (strcmp (pwd->pw_name, user_name) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pwd->pw_gid == grp->gr_gid) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: group %s is the primary group of another user and is not removed.\n"),
|
|
||||||
Prog, grp->gr_name);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
endpwent ();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NULL == pwd) {
|
|
||||||
/*
|
|
||||||
* We can remove this group, it is not the primary
|
|
||||||
* group of any remaining user.
|
|
||||||
*/
|
|
||||||
if (gr_remove (grp->gr_name) == 0) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
|
||||||
Prog, grp->gr_name, gr_dbname ());
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
|
||||||
deleted_user_group = true;
|
|
||||||
#endif /* SHADOWGRP */
|
|
||||||
|
|
||||||
#ifdef WITH_AUDIT
|
|
||||||
audit_logger (AUDIT_DEL_GROUP, Prog,
|
|
||||||
"deleting group",
|
|
||||||
grp->gr_name, AUDIT_NO_ID,
|
|
||||||
SHADOW_AUDIT_SUCCESS);
|
|
||||||
#endif /* WITH_AUDIT */
|
|
||||||
SYSLOG ((LOG_INFO,
|
|
||||||
"removed group '%s' owned by '%s'\n",
|
|
||||||
grp->gr_name, user_name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef SHADOWGRP
|
#ifdef SHADOWGRP
|
||||||
if (!is_shadow_grp) {
|
if (!is_shadow_grp) {
|
||||||
return;
|
return;
|
||||||
@ -317,21 +258,111 @@ static void update_groups (void)
|
|||||||
SHADOW_AUDIT_SUCCESS);
|
SHADOW_AUDIT_SUCCESS);
|
||||||
#endif /* WITH_AUDIT */
|
#endif /* WITH_AUDIT */
|
||||||
SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n",
|
SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n",
|
||||||
user_name, nsgrp->sg_name));
|
user_name, nsgrp->sg_name));
|
||||||
}
|
|
||||||
|
|
||||||
if ( deleted_user_group
|
|
||||||
&& (sgr_locate (user_name) != NULL)) {
|
|
||||||
if (sgr_remove (user_name) == 0) {
|
|
||||||
fprintf (stderr,
|
|
||||||
_("%s: cannot remove entry '%s' from %s\n"),
|
|
||||||
Prog, user_name, sgr_dbname ());
|
|
||||||
fail_exit (E_GRP_UPDATE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif /* SHADOWGRP */
|
#endif /* SHADOWGRP */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* remove_usergroup - delete the user's group if it is a usergroup
|
||||||
|
*
|
||||||
|
* An usergroup is removed if
|
||||||
|
* + it has the same name as the user
|
||||||
|
* + it is the primary group of the user
|
||||||
|
* + it has no other members
|
||||||
|
* + it is not the primary group of any other user
|
||||||
|
*/
|
||||||
|
static void remove_usergroup (void)
|
||||||
|
{
|
||||||
|
const struct group *grp;
|
||||||
|
const struct passwd *pwd = NULL;
|
||||||
|
|
||||||
|
grp = gr_locate (user_name);
|
||||||
|
if (NULL == grp) {
|
||||||
|
/* This user has no usergroup. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grp->gr_gid != user_gid) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: group %s not removed because it is not the primary group of user %s.\n"),
|
||||||
|
Prog, grp->gr_name, user_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != grp->gr_mem[0]) {
|
||||||
|
/* The usergroup has other members. */
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: group %s not removed because it has other members.\n"),
|
||||||
|
Prog, grp->gr_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fflg) {
|
||||||
|
/*
|
||||||
|
* Scan the passwd file to check if this group is still
|
||||||
|
* used as a primary group.
|
||||||
|
*/
|
||||||
|
setpwent ();
|
||||||
|
while ((pwd = getpwent ()) != NULL) {
|
||||||
|
if (strcmp (pwd->pw_name, user_name) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (pwd->pw_gid == grp->gr_gid) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: group %s is the primary group of another user and is not removed.\n"),
|
||||||
|
Prog, grp->gr_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
endpwent ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == pwd) {
|
||||||
|
/*
|
||||||
|
* We can remove this group, it is not the primary
|
||||||
|
* group of any remaining user.
|
||||||
|
*/
|
||||||
|
if (gr_remove (grp->gr_name) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
|
Prog, grp->gr_name, gr_dbname ());
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
|
"deleting group",
|
||||||
|
grp->gr_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
|
#endif /* WITH_AUDIT */
|
||||||
|
SYSLOG ((LOG_INFO,
|
||||||
|
"removed group '%s' owned by '%s'\n",
|
||||||
|
grp->gr_name, user_name));
|
||||||
|
|
||||||
|
#ifdef SHADOWGRP
|
||||||
|
if (sgr_locate (user_name) != NULL) {
|
||||||
|
if (sgr_remove (user_name) == 0) {
|
||||||
|
fprintf (stderr,
|
||||||
|
_("%s: cannot remove entry '%s' from %s\n"),
|
||||||
|
Prog, user_name, sgr_dbname ());
|
||||||
|
fail_exit (E_GRP_UPDATE);
|
||||||
|
}
|
||||||
|
#ifdef WITH_AUDIT
|
||||||
|
audit_logger (AUDIT_DEL_GROUP, Prog,
|
||||||
|
"deleting shadow group",
|
||||||
|
grp->gr_name, AUDIT_NO_ID,
|
||||||
|
SHADOW_AUDIT_SUCCESS);
|
||||||
|
#endif /* WITH_AUDIT */
|
||||||
|
SYSLOG ((LOG_INFO,
|
||||||
|
"removed shadow group '%s' owned by '%s'\n",
|
||||||
|
grp->gr_name, user_name));
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* SHADOWGRP */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* close_files - close all of the files that were opened
|
* close_files - close all of the files that were opened
|
||||||
*
|
*
|
||||||
@ -925,6 +956,7 @@ int main (int argc, char **argv)
|
|||||||
exit (E_NOTFOUND);
|
exit (E_NOTFOUND);
|
||||||
}
|
}
|
||||||
user_id = pwd->pw_uid;
|
user_id = pwd->pw_uid;
|
||||||
|
user_gid = pwd->pw_gid;
|
||||||
user_home = xstrdup (pwd->pw_dir);
|
user_home = xstrdup (pwd->pw_dir);
|
||||||
}
|
}
|
||||||
#ifdef WITH_TCB
|
#ifdef WITH_TCB
|
||||||
|
Loading…
x
Reference in New Issue
Block a user