static void print_groups (const char *member) { int groups = 0; struct group *grp; struct passwd *pwd; int flag = 0; setgrent (); if ((pwd = getpwnam (member)) == 0) { fprintf (stderr, _("unknown user %s\n"), member); exit (1); } while ((grp = getgrent ())) { if (is_on_list (grp->gr_mem, member)) { if (groups++) putchar (' '); printf ("%s", grp->gr_name); if (grp->gr_gid == pwd->pw_gid) flag = 1; } } if (!flag && (grp = getgrgid (pwd->pw_gid))) { if (groups++) putchar (' '); printf ("%s", grp->gr_name); } if (groups) putchar ('\n'); }
static void check_perms (const struct group *gr) #endif { /* * Only root can use the -M and -A options. */ if (!amroot && (Aflg || Mflg)) { failure (); } #ifdef SHADOWGRP if (is_shadowgrp) { /* * The policy here for changing a group is that * 1) you must be root or * 2) you must be listed as an administrative member. * Administrative members can do anything to a group that * the root user can. */ if (!amroot && !is_on_list (sg->sg_adm, myname)) { failure (); } } else #endif /* SHADOWGRP */ { #ifdef FIRST_MEMBER_IS_ADMIN /* * The policy here for changing a group is that * 1) you must be root or * 2) you must be the first listed member of the group. * The first listed member of a group can do anything to * that group that the root user can. The rationale for * this hack is that the FIRST user is probably the most * important user in this entire group. * * This feature enabled by default could be a security * problem when installed on existing systems where the * first group member might be just a normal user. * --marekm */ if (!amroot) { if (gr->gr_mem[0] == (char *) 0) { failure (); } if (strcmp (gr->gr_mem[0], myname) != 0) { failure (); } } #else /* ! FIRST_MEMBER_IS_ADMIN */ if (!amroot) { failure (); } #endif } }
static int isgrp (const char *name, const char *group) { struct group *grp; grp = getgrnam (group); /* local, no need for xgetgrnam */ if (!grp || !grp->gr_mem) return 0; return is_on_list (grp->gr_mem, name); }
static bool iswheel (const char *username) { struct group *grp; grp = getgrnam ("wheel"); /* !USE_PAM, no need for xgetgrnam */ if ( (NULL ==grp) || (NULL == grp->gr_mem)) { return false; } return is_on_list (grp->gr_mem, username); }
/* Checks if a user is a member of a group */ static int is_on_group(const char *user_name, const char *group_name) { struct passwd *pwd; struct group *grp, *pgrp; char uname[LINE_LENGTH], gname[LINE_LENGTH]; if (!strlen(user_name)) return 0; if (!strlen(group_name)) return 0; memset(uname, 0, sizeof(uname)); strncpy(uname, user_name, LINE_LENGTH); memset(gname, 0, sizeof(gname)); strncpy(gname, group_name, LINE_LENGTH); setpwent(); pwd = getpwnam(uname); endpwent(); if (!pwd) return 0; /* the info about this group */ setgrent(); grp = getgrnam(gname); endgrent(); if (!grp) return 0; /* first check: is a member of the group_name group ? */ if (is_on_list(grp->gr_mem, uname)) return 1; /* next check: user primary group is group_name ? */ setgrent(); pgrp = getgrgid(pwd->pw_gid); endgrent(); if (!pgrp) return 0; if (!strcmp(pgrp->gr_name, gname)) return 1; return 0; }
/* * gpasswd - administer the /etc/group file */ int main (int argc, char **argv) { struct group grent; #ifdef SHADOWGRP struct sgrp sgent; #endif struct passwd *pw = NULL; #ifdef WITH_AUDIT audit_help_open (); #endif sanitize_env (); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); /* * Make a note of whether or not this command was invoked by root. * This will be used to bypass certain checks later on. Also, set * the real user ID to match the effective user ID. This will * prevent the invoker from issuing signals which would interfere * with this command. */ bywho = getuid (); Prog = Basename (argv[0]); OPENLOG ("gpasswd"); setbuf (stdout, NULL); setbuf (stderr, NULL); #ifdef SHADOWGRP is_shadowgrp = sgr_file_present (); #endif /* * Determine the name of the user that invoked this command. This * is really hit or miss because there are so many ways that command * can be executed and so many ways to trip up the routines that * report the user name. */ pw = get_my_pwent (); if (NULL == pw) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)", (unsigned long) getuid ())); exit (E_NOPERM); } myname = xstrdup (pw->pw_name); /* * Register an exit function to warn for any inconsistency that we * could create. */ if (atexit (do_cleanups) != 0) { fprintf(stderr, "%s: cannot set exit function\n", Prog); exit (1); } /* Parse the options */ process_flags (argc, argv); /* * Replicate the group so it can be modified later on. */ #ifdef SHADOWGRP get_group (&grent, &sgent); #else get_group (&grent); #endif /* * Check if the user is allowed to change the password of this group. */ #ifdef SHADOWGRP check_perms (&grent, &sgent); #else check_perms (&grent); #endif /* * Removing a password is straight forward. Just set the password * field to a "". */ if (rflg) { grent.gr_passwd = ""; /* XXX warning: const */ #ifdef SHADOWGRP sgent.sg_passwd = ""; /* XXX warning: const */ #endif goto output; } else if (Rflg) { /* * Same thing for restricting the group. Set the password * field to "!". */ grent.gr_passwd = "!"; /* XXX warning: const */ #ifdef SHADOWGRP sgent.sg_passwd = "!"; /* XXX warning: const */ #endif goto output; } /* * Adding a member to a member list is pretty straightforward as * well. Call the appropriate routine and split. */ if (aflg) { printf (_("Adding user %s to group %s\n"), user, group); grent.gr_mem = add_list (grent.gr_mem, user); #ifdef SHADOWGRP if (is_shadowgrp) { sgent.sg_mem = add_list (sgent.sg_mem, user); } #endif goto output; } /* * Removing a member from the member list is the same deal as adding * one, except the routine is different. */ if (dflg) { bool removed = false; printf (_("Removing user %s from group %s\n"), user, group); if (is_on_list (grent.gr_mem, user)) { removed = true; grent.gr_mem = del_list (grent.gr_mem, user); } #ifdef SHADOWGRP if (is_shadowgrp) { if (is_on_list (sgent.sg_mem, user)) { removed = true; sgent.sg_mem = del_list (sgent.sg_mem, user); } } #endif if (!removed) { fprintf (stderr, _("%s: user '%s' is not a member of '%s'\n"), Prog, user, group); exit (E_BAD_ARG); } goto output; } #ifdef SHADOWGRP /* * Replacing the entire list of administrators is simple. Check the * list to make sure everyone is a real user. Then slap the new list * in place. */ if (Aflg) { sgent.sg_adm = comma_to_list (admins); if (!Mflg) { goto output; } } #endif /* SHADOWGRP */ /* * Replacing the entire list of members is simple. Check the list to * make sure everyone is a real user. Then slap the new list in * place. */ if (Mflg) { #ifdef SHADOWGRP sgent.sg_mem = comma_to_list (members); #endif grent.gr_mem = comma_to_list (members); goto output; } /* * If the password is being changed, the input and output must both * be a tty. The typical keyboard signals are caught so the termio * modes can be restored. */ if ((isatty (0) == 0) || (isatty (1) == 0)) { fprintf (stderr, _("%s: Not a tty\n"), Prog); exit (E_NOPERM); } catch_signals (0); /* save tty modes */ (void) signal (SIGHUP, catch_signals); (void) signal (SIGINT, catch_signals); (void) signal (SIGQUIT, catch_signals); (void) signal (SIGTERM, catch_signals); #ifdef SIGTSTP (void) signal (SIGTSTP, catch_signals); #endif /* Prompt for the new password */ #ifdef SHADOWGRP change_passwd (&grent, &sgent); #else change_passwd (&grent); #endif /* * This is the common arrival point to output the new group file. * The freshly crafted entry is in allocated space. The group file * will be locked and opened for writing. The new entry will be * output, etc. */ output: if (setuid (0) != 0) { fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG ((LOG_ERR, "can't setuid(0)")); closelog (); exit (E_NOPERM); } pwd_init (); open_files (); #ifdef SHADOWGRP update_group (&grent, &sgent); #else update_group (&grent); #endif close_files (); nscd_flush_cache ("group"); exit (E_SUCCESS); }
static int update_gshadow (void) { int is_member; int was_member; int was_admin; int changed; const struct sgrp *sgrp; struct sgrp *nsgrp; if (!sgr_lock ()) { fprintf (stderr, _("%s: error locking shadow group file\n"), Prog); SYSLOG ((LOG_ERR, "error locking shadow group file")); return -1; } if (!sgr_open (O_RDWR)) { fprintf (stderr, _("%s: error opening shadow group file\n"), Prog); SYSLOG ((LOG_ERR, "error opening shadow group file")); sgr_unlock (); return -1; } changed = 0; /* * Scan through the entire shadow group file looking for the groups * that the user is a member of. */ while ((sgrp = sgr_next ())) { /* * See if the user was a member of this group */ was_member = is_on_list (sgrp->sg_mem, user_name); /* * See if the user was an administrator of this group */ was_admin = is_on_list (sgrp->sg_adm, user_name); /* * See if the user specified this group as one of their * concurrent groups. */ is_member = Gflg && is_on_list (user_groups, sgrp->sg_name); if (!was_member && !was_admin && !is_member) continue; nsgrp = __sgr_dup (sgrp); if (!nsgrp) { fprintf (stderr, _ ("%s: out of memory in update_gshadow\n"), Prog); sgr_unlock (); return -1; } if (was_admin && lflg) { nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); nsgrp->sg_adm = add_list (nsgrp->sg_adm, user_newname); changed = 1; SYSLOG ((LOG_INFO, "change admin `%s' to `%s' in shadow group `%s'", user_name, user_newname, nsgrp->sg_name)); } if (was_member && (!Gflg || is_member)) { if (lflg) { nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); nsgrp->sg_mem = add_list (nsgrp->sg_mem, user_newname); changed = 1; SYSLOG ((LOG_INFO, "change `%s' to `%s' in shadow group `%s'", user_name, user_newname, nsgrp->sg_name)); } } else if (was_member && Gflg && !is_member) { nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); changed = 1; SYSLOG ((LOG_INFO, "delete `%s' from shadow group `%s'", user_name, nsgrp->sg_name)); } else if (!was_member && Gflg && is_member) { nsgrp->sg_mem = add_list (nsgrp->sg_mem, lflg ? user_newname : user_name); changed = 1; SYSLOG ((LOG_INFO, "add `%s' to shadow group `%s'", lflg ? user_newname : user_name, nsgrp->sg_name)); } if (!changed) continue; changed = 0; /* * Update the group entry to reflect the changes. */ if (!sgr_update (nsgrp)) { fprintf (stderr, _("%s: error adding new group entry\n"), Prog); SYSLOG ((LOG_ERR, "error adding shadow group entry")); sgr_unlock (); return -1; } #ifdef NDBM /* * Update the DBM group file with the new entry as well. */ if (!sg_dbm_update (nsgrp)) { fprintf (stderr, _("%s: cannot add new dbm group entry\n"), Prog); SYSLOG ((LOG_ERR, "error adding dbm shadow group entry")); sgr_unlock (); return -1; } #endif /* NDBM */ } #ifdef NDBM endsgent (); #endif /* NDBM */ if (!sgr_close ()) { fprintf (stderr, _("%s: cannot rewrite shadow group file\n"), Prog); sgr_unlock (); return -1; } sgr_unlock (); return 0; }
static int update_group (void) { int is_member; int was_member; int changed; const struct group *grp; struct group *ngrp; /* * Lock and open the group file. This will load all of the group * entries. */ if (!gr_lock ()) { fprintf (stderr, _("%s: error locking group file\n"), Prog); SYSLOG ((LOG_ERR, "error locking group file")); return -1; } if (!gr_open (O_RDWR)) { fprintf (stderr, _("%s: error opening group file\n"), Prog); SYSLOG ((LOG_ERR, "error opening group file")); gr_unlock (); return -1; } changed = 0; /* * Scan through the entire group file looking for the groups that * the user is a member of. */ while ((grp = gr_next ())) { /* * See if the user specified this group as one of their * concurrent groups. */ was_member = is_on_list (grp->gr_mem, user_name); is_member = Gflg && is_on_list (user_groups, grp->gr_name); if (!was_member && !is_member) continue; ngrp = __gr_dup (grp); if (!ngrp) { fprintf (stderr, _("%s: out of memory in update_group\n"), Prog); gr_unlock (); return -1; } if (was_member && (!Gflg || is_member)) { if (lflg) { ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); ngrp->gr_mem = add_list (ngrp->gr_mem, user_newname); changed = 1; SYSLOG ((LOG_INFO, "change `%s' to `%s' in group `%s'", user_name, user_newname, ngrp->gr_name)); } } else if (was_member && Gflg && !is_member) { ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); changed = 1; SYSLOG ((LOG_INFO, "delete `%s' from group `%s'", user_name, ngrp->gr_name)); } else if (!was_member && Gflg && is_member) { ngrp->gr_mem = add_list (ngrp->gr_mem, lflg ? user_newname : user_name); changed = 1; SYSLOG ((LOG_INFO, "add `%s' to group `%s'", lflg ? user_newname : user_name, ngrp->gr_name)); } if (!changed) continue; changed = 0; if (!gr_update (ngrp)) { fprintf (stderr, _("%s: error adding new group entry\n"), Prog); SYSLOG ((LOG_ERR, "error adding group entry")); gr_unlock (); return -1; } #ifdef NDBM /* * Update the DBM group file with the new entry as well. */ if (!gr_dbm_update (ngrp)) { fprintf (stderr, _("%s: cannot add new dbm group entry\n"), Prog); SYSLOG ((LOG_ERR, "error adding dbm group entry")); gr_unlock (); return -1; } #endif /* NDBM */ } #ifdef NDBM endgrent (); #endif /* NDBM */ if (!gr_close ()) { fprintf (stderr, _("%s: cannot rewrite group file\n"), Prog); gr_unlock (); return -1; } gr_unlock (); return 0; }
static void update_groups(void) { const struct group *grp; struct group *ngrp; #ifdef SHADOWGRP const struct sgrp *sgrp; struct sgrp *nsgrp; #endif /* SHADOWGRP */ /* * Scan through the entire group file looking for the groups that * the user is a member of. */ for (gr_rewind (), grp = gr_next ();grp;grp = gr_next ()) { /* * See if the user specified this group as one of their * concurrent groups. */ if (!is_on_list(grp->gr_mem, user_name)) continue; /* * Delete the username from the list of group members and * update the group entry to reflect the change. */ ngrp = __gr_dup(grp); if (!ngrp) { exit(13); /* XXX */ } ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); if (!gr_update(ngrp)) fprintf(stderr, _("%s: error updating group entry\n"), Prog); /* * Update the DBM group file with the new entry as well. */ #ifdef NDBM if (!gr_dbm_update(ngrp)) fprintf(stderr, _("%s: cannot update dbm group entry\n"), Prog); #endif /* NDBM */ SYSLOG((LOG_INFO, "delete `%s' from group `%s'\n", user_name, ngrp->gr_name)); } #ifdef NDBM endgrent (); #endif /* NDBM */ #ifdef SHADOWGRP if (!is_shadow_grp) return; /* * Scan through the entire shadow group file looking for the groups * that the user is a member of. Both the administrative list and * the ordinary membership list is checked. */ for (sgr_rewind (), sgrp = sgr_next ();sgrp;sgrp = sgr_next ()) { int was_member, was_admin; /* * See if the user specified this group as one of their * concurrent groups. */ was_member = is_on_list(sgrp->sg_mem, user_name); was_admin = is_on_list(sgrp->sg_adm, user_name); if (!was_member && !was_admin) continue; nsgrp = __sgr_dup(sgrp); if (!nsgrp) { exit(13); /* XXX */ } if (was_member) nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); if (was_admin) nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); if (!sgr_update(nsgrp)) fprintf(stderr, _("%s: error updating group entry\n"), Prog); #ifdef NDBM /* * Update the DBM group file with the new entry as well. */ if (!sg_dbm_update(nsgrp)) fprintf(stderr, _("%s: cannot update dbm group entry\n"), Prog); #endif /* NDBM */ SYSLOG((LOG_INFO, "delete `%s' from shadow group `%s'\n", user_name, nsgrp->sg_name)); } #ifdef NDBM endsgent (); #endif /* NDBM */ #endif /* SHADOWGRP */ }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc ,const char **argv) { int ctrl; const char *username; char *fromsu; struct passwd *pwd, *tpwd; struct group *grp; int retval = PAM_AUTH_ERR; char use_group[BUFSIZ]; /* Init the optional group */ bzero(use_group,BUFSIZ); ctrl = _pam_parse(argc, argv, use_group); retval = pam_get_user(pamh,&username,NULL); if ((retval != PAM_SUCCESS) || (!username)) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_DEBUG,"can not get the username"); return PAM_SERVICE_ERR; } /* su to a uid 0 account ? */ pwd = getpwnam(username); if (!pwd) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"unknown user %s",username); return PAM_USER_UNKNOWN; } /* Now we know that the username exists, pass on to other modules... * the call to pam_get_user made this obsolete, so is commented out * * pam_set_item(pamh,PAM_USER,(const void *)username); */ /* is this user an UID 0 account ? */ if(pwd->pw_uid) { /* no need to check for wheel */ return PAM_IGNORE; } if (ctrl & PAM_USE_UID_ARG) { tpwd = getpwuid(getuid()); if (!tpwd) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"who is running me ?!"); return PAM_SERVICE_ERR; } fromsu = tpwd->pw_name; } else { fromsu = getlogin(); if (!fromsu) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"who is running me ?!"); return PAM_SERVICE_ERR; } } if (!use_group[0]) { if ((grp = getgrnam("wheel")) == NULL) { grp = getgrgid(0); } } else grp = getgrnam(use_group); if (!grp || !grp->gr_mem) { if (ctrl & PAM_DEBUG_ARG) { if (!use_group[0]) _pam_log(LOG_NOTICE,"no members in a GID 0 group"); else _pam_log(LOG_NOTICE,"no members in '%s' group",use_group); } if (ctrl & PAM_DENY_ARG) /* if this was meant to deny access to the members * of this group and the group does not exist, allow * access */ return PAM_IGNORE; else return PAM_AUTH_ERR; } if (is_on_list(grp->gr_mem, fromsu)) { if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"Access %s to '%s' for '%s'", (ctrl & PAM_DENY_ARG)?"denied":"granted", fromsu,username); if (ctrl & PAM_DENY_ARG) return PAM_PERM_DENIED; else if (ctrl & PAM_TRUST_ARG) return PAM_SUCCESS; else return PAM_IGNORE; } if (ctrl & PAM_DEBUG_ARG) _pam_log(LOG_NOTICE,"Access %s for '%s' to '%s'", (ctrl & PAM_DENY_ARG)?"granted":"denied",fromsu,username); if (ctrl & PAM_DENY_ARG) return PAM_SUCCESS; else return PAM_PERM_DENIED; }
/* * update_groups - delete user from secondary group set * * update_groups() takes the user name that was given and searches * the group files for membership in any group. * * we also check to see if they have any groups they own (the same * name is their user name) and delete them too (only if USERGROUPS_ENAB * is enabled). */ static void update_groups (void) { const struct group *grp; struct group *ngrp; #ifdef SHADOWGRP const struct sgrp *sgrp; struct sgrp *nsgrp; #endif /* SHADOWGRP */ /* * Scan through the entire group file looking for the groups that * the user is a member of. */ for (gr_rewind (), grp = gr_next (); NULL != grp; grp = gr_next ()) { /* * See if the user specified this group as one of their * concurrent groups. */ if (!is_on_list (grp->gr_mem, user_name)) { continue; } /* * Delete the username from the list of group members and * update the group entry to reflect the change. */ ngrp = __gr_dup (grp); if (NULL == ngrp) { fprintf (stderr, _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); exit (13); /* XXX */ } ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); if (gr_update (ngrp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); exit (E_GRP_UPDATE); } /* * Update the DBM group file with the new entry as well. */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user from group", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", user_name, ngrp->gr_name)); } if (getdef_bool ("USERGROUPS_ENAB")) { remove_usergroup (); } #ifdef SHADOWGRP if (!is_shadow_grp) { return; } /* * Scan through the entire shadow group file looking for the groups * that the user is a member of. Both the administrative list and * the ordinary membership list is checked. */ for (sgr_rewind (), sgrp = sgr_next (); NULL != sgrp; sgrp = sgr_next ()) { bool was_member, was_admin; /* * See if the user specified this group as one of their * concurrent groups. */ was_member = is_on_list (sgrp->sg_mem, user_name); was_admin = is_on_list (sgrp->sg_adm, user_name); if (!was_member && !was_admin) { continue; } nsgrp = __sgr_dup (sgrp); if (NULL == nsgrp) { fprintf (stderr, _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); exit (13); /* XXX */ } if (was_member) { nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); } if (was_admin) { nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); } if (sgr_update (nsgrp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user from shadow group", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", user_name, nsgrp->sg_name)); } #endif /* SHADOWGRP */ }
/* * update_groups - delete user from secondary group set * * update_groups() takes the user name that was given and searches * the group files for membership in any group. * * we also check to see if they have any groups they own (the same * name is their user name) and delete them too (only if USERGROUPS_ENAB * is enabled). */ static void update_groups (void) { const struct group *grp; struct group *ngrp; struct passwd *pwd; #ifdef SHADOWGRP bool deleted_user_group = false; const struct sgrp *sgrp; struct sgrp *nsgrp; #endif /* SHADOWGRP */ /* * Scan through the entire group file looking for the groups that * the user is a member of. */ for (gr_rewind (), grp = gr_next (); NULL != grp; grp = gr_next ()) { /* * See if the user specified this group as one of their * concurrent groups. */ if (!is_on_list (grp->gr_mem, user_name)) { continue; } /* * Delete the username from the list of group members and * update the group entry to reflect the change. */ ngrp = __gr_dup (grp); if (NULL == ngrp) { fprintf (stderr, _("%s: Out of memory. Cannot update %s.\n"), Prog, gr_dbname ()); exit (13); /* XXX */ } ngrp->gr_mem = del_list (ngrp->gr_mem, user_name); if (gr_update (ngrp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), ngrp->gr_name); exit (E_GRP_UPDATE); } /* * Update the DBM group file with the new entry as well. */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user from group", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "delete '%s' from group '%s'\n", user_name, ngrp->gr_name)); } /* * we've removed their name from all the groups above, so * 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 #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_GROUP, Prog, "deleting group", grp->gr_name, AUDIT_NO_ID, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "removed group '%s' owned by '%s'\n", grp->gr_name, user_name)); } } #ifdef SHADOWGRP if (!is_shadow_grp) { return; } /* * Scan through the entire shadow group file looking for the groups * that the user is a member of. Both the administrative list and * the ordinary membership list is checked. */ for (sgr_rewind (), sgrp = sgr_next (); NULL != sgrp; sgrp = sgr_next ()) { bool was_member, was_admin; /* * See if the user specified this group as one of their * concurrent groups. */ was_member = is_on_list (sgrp->sg_mem, user_name); was_admin = is_on_list (sgrp->sg_adm, user_name); if (!was_member && !was_admin) { continue; } nsgrp = __sgr_dup (sgrp); if (NULL == nsgrp) { fprintf (stderr, _("%s: Out of memory. Cannot update %s.\n"), Prog, sgr_dbname ()); exit (13); /* XXX */ } if (was_member) { nsgrp->sg_mem = del_list (nsgrp->sg_mem, user_name); } if (was_admin) { nsgrp->sg_adm = del_list (nsgrp->sg_adm, user_name); } if (sgr_update (nsgrp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), nsgrp->sg_name); exit (E_GRP_UPDATE); } #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user from shadow group", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "delete '%s' from shadow group '%s'\n", 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 */ }