* NEWS, src/userdel.c: Report errors to remove the user's mailbox.

* NEWS, src/userdel.c: When USERGROUPS_ENAB is enabled, remove the
	user's group when the user was the only member. This is still not
	complete, as the user could have been specified twice in the
	members.
	* NEWS, src/userdel.c: Do not fail when -r is used and the home
	directory does not exist.
This commit is contained in:
nekral-guest 2009-05-22 10:41:10 +00:00
parent 738ebc04b9
commit 604c7d72d9
3 changed files with 71 additions and 20 deletions

View File

@ -1,4 +1,14 @@
2009-05-21 Nicolas François <nicolas.francois@centraliens.net> 2009-05-22 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, src/userdel.c: Report errors to remove the user's mailbox.
* NEWS, src/userdel.c: When USERGROUPS_ENAB is enabled, remove the
user's group when the user was the only member. This is still not
complete, as the user could have been specified twice in the
members.
* NEWS, src/userdel.c: Do not fail when -r is used and the home
directory does not exist.
2009-05-22 Nicolas François <nicolas.francois@centraliens.net>
* libmisc/copydir.c: Added warning for relative symlinks. * libmisc/copydir.c: Added warning for relative symlinks.
* libmisc/copydir.c (remove_tree): There is no need to check if * libmisc/copydir.c (remove_tree): There is no need to check if

4
NEWS
View File

@ -10,6 +10,10 @@ shadow-4.1.4 -> shadow-4.1.4.1 UNRELEASED
the user is running some processes. the user is running some processes.
* If not on Linux, continue to search for an utmp record, but make sure * If not on Linux, continue to search for an utmp record, but make sure
the process recorded in the utmp entry is still running. the process recorded in the utmp entry is still running.
* Report failures to remove the user's mailbox
* When USERGROUPS_ENAB is enabled, remove the user's group when the
user was the only member.
* Do not fail when -r is used and the home directory does not exist.
- usermod - usermod
* Check if the user is busy when the user's UID, name or home directory * Check if the user is busy when the user's UID, name or home directory
is changed. is changed.

View File

@ -106,7 +106,7 @@ static void user_cancel (const char *);
static bool path_prefix (const char *, const char *); static bool path_prefix (const char *, const char *);
#endif #endif
static int is_owner (uid_t, const char *); static int is_owner (uid_t, const char *);
static void remove_mailbox (void); static int remove_mailbox (void);
/* /*
* usage - display usage message and exit * usage - display usage message and exit
@ -196,11 +196,16 @@ static void update_groups (void)
* we've removed their name from all the groups above, so * we've removed their name from all the groups above, so
* now if they have a group with the same name as their * now if they have a group with the same name as their
* user name, with no members, we delete it. * 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); grp = xgetgrnam (user_name);
if ( (NULL != grp) if ( (NULL != grp)
&& getdef_bool ("USERGROUPS_ENAB") && getdef_bool ("USERGROUPS_ENAB")
&& (NULL == grp->gr_mem[0])) { && ( (NULL == grp->gr_mem[0])
|| ( (NULL == grp->gr_mem[1])
&& (strcmp (grp->gr_mem[0], user_name) == 0)))) {
pwd = NULL; pwd = NULL;
if (!fflg) { if (!fflg) {
@ -615,21 +620,36 @@ static bool path_prefix (const char *s1, const char *s2)
} }
#endif #endif
/*
* is_owner - Check if path is owned by uid
*
* Return
* 1: path exists and is owned by uid
* 0: path is not owned by uid, or a failure occured
* -1: path does not exist
*/
static int is_owner (uid_t uid, const char *path) static int is_owner (uid_t uid, const char *path)
{ {
struct stat st; struct stat st;
errno = 0;
if (stat (path, &st) != 0) { if (stat (path, &st) != 0) {
if ((ENOENT == errno) || (ENOTDIR == errno)) {
/* The file or directory does not exist */
return -1; return -1;
} else {
return 0;
}
} }
return (st.st_uid == uid); return (st.st_uid == uid);
} }
static void remove_mailbox (void) static int remove_mailbox (void)
{ {
const char *maildir; const char *maildir;
char mailfile[1024]; char mailfile[1024];
int i; int i;
int errors = 0;
maildir = getdef_str ("MAIL_DIR"); maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR #ifdef MAIL_SPOOL_DIR
@ -638,12 +658,14 @@ static void remove_mailbox (void)
} }
#endif #endif
if (NULL == maildir) { if (NULL == maildir) {
return; return 0;
} }
snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name); snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name);
if (fflg) { if (fflg) {
if (unlink (mailfile) != 0) { if (unlink (mailfile) != 0) {
fprintf (stderr, _("%s: warning: can't remove %s: %s"), Prog, mailfile, strerror (errno)); fprintf (stderr,
_("%s: warning: can't remove %s: %s\n"),
Prog, mailfile, strerror (errno));
SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno)));
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog, audit_logger (AUDIT_DEL_USER, Prog,
@ -651,6 +673,7 @@ static void remove_mailbox (void)
user_name, (unsigned int) user_id, user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE); SHADOW_AUDIT_FAILURE);
#endif #endif
errors = 1;
/* continue */ /* continue */
} }
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
@ -662,26 +685,30 @@ static void remove_mailbox (void)
SHADOW_AUDIT_SUCCESS); SHADOW_AUDIT_SUCCESS);
} }
#endif #endif
return; return errors;
} }
i = is_owner (user_id, mailfile); i = is_owner (user_id, mailfile);
if (i == 0) { if (i == 0) {
fprintf (stderr, fprintf (stderr,
_("%s: %s not owned by %s, not removing\n"), _("%s: %s not owned by %s, not removing\n"),
Prog, mailfile, user_name); Prog, mailfile, user_name);
SYSLOG ((LOG_ERR, "%s not owned by %s, not removed", mailfile, strerror (errno))); SYSLOG ((LOG_ERR,
"%s not owned by %s, not removed",
mailfile, strerror (errno)));
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog, audit_logger (AUDIT_DEL_USER, Prog,
"deleting mail file", "deleting mail file",
user_name, (unsigned int) user_id, user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE); SHADOW_AUDIT_FAILURE);
#endif #endif
return; return 1;
} else if (i == -1) { } else if (i == -1) {
return; /* mailbox doesn't exist */ return 0; /* mailbox doesn't exist */
} }
if (unlink (mailfile) != 0) { if (unlink (mailfile) != 0) {
fprintf (stderr, _("%s: warning: can't remove %s: %s"), Prog, mailfile, strerror (errno)); fprintf (stderr,
_("%s: warning: can't remove %s: %s\n"),
Prog, mailfile, strerror (errno));
SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno))); SYSLOG ((LOG_ERR, "Cannot remove %s: %s", mailfile, strerror (errno)));
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
audit_logger (AUDIT_DEL_USER, Prog, audit_logger (AUDIT_DEL_USER, Prog,
@ -689,6 +716,7 @@ static void remove_mailbox (void)
user_name, (unsigned int) user_id, user_name, (unsigned int) user_id,
SHADOW_AUDIT_FAILURE); SHADOW_AUDIT_FAILURE);
#endif #endif
errors = 1;
/* continue */ /* continue */
} }
#ifdef WITH_AUDIT #ifdef WITH_AUDIT
@ -700,6 +728,7 @@ static void remove_mailbox (void)
SHADOW_AUDIT_SUCCESS); SHADOW_AUDIT_SUCCESS);
} }
#endif #endif
return errors;
} }
/* /*
@ -868,9 +897,16 @@ int main (int argc, char **argv)
update_groups (); update_groups ();
if (rflg) { if (rflg) {
remove_mailbox (); errors += remove_mailbox ();
} }
if (rflg && !fflg && (is_owner (user_id, user_home) == 0)) { if (rflg) {
int home_owned = is_owner (user_id, user_home);
if (-1 == home_owned) {
fprintf (stderr,
_("%s: %s home directory (%s) not found\n"),
Prog, user_name, user_home);
rflg = 0;
} else if ((0 == home_owned) && !fflg) {
fprintf (stderr, fprintf (stderr,
_("%s: %s not owned by %s, not removing\n"), _("%s: %s not owned by %s, not removing\n"),
Prog, user_home, user_name); Prog, user_home, user_name);
@ -878,6 +914,7 @@ int main (int argc, char **argv)
errors++; errors++;
/* continue */ /* continue */
} }
}
#ifdef EXTRA_CHECK_HOME_DIR #ifdef EXTRA_CHECK_HOME_DIR
/* This may be slow, the above should be good enough. */ /* This may be slow, the above should be good enough. */