/* * check_new_name - check the new name for uniqueness * * check_new_name() insures that the new name does not exist already. * You can't have the same name twice, period. */ static void check_new_name (void) { /* * Make sure they are actually changing the name. */ if (strcmp (group_name, group_newname) == 0) { nflg = 0; return; } if (is_valid_group_name (group_newname)) { /* * If the entry is found, too bad. */ /* local, no need for xgetgrnam */ if (getgrnam (group_newname) != NULL) { fprintf (stderr, _("%s: group '%s' already exists\n"), Prog, group_newname); exit (E_NAME_IN_USE); } return; } /* * All invalid group names land here. */ fprintf (stderr, _("%s: invalid group name '%s'\n"), Prog, group_newname); exit (E_BAD_ARG); }
/* * check_new_name - check the new name for validity * * check_new_name() insures that the new name doesn't contain any * illegal characters. */ static void check_new_name (void) { if (is_valid_group_name (group_name)) { return; } /* * All invalid group names land here. */ fprintf (stderr, _("%s: '%s' is not a valid group name\n"), Prog, group_name); exit (E_BAD_ARG); }
/* * check_grp_file - check the content of the group file */ static void check_grp_file (int *errors, bool *changed) { struct commonio_entry *gre, *tgre; struct group *grp; #ifdef SHADOWGRP struct sgrp *sgr; #endif /* * Loop through the entire group file. */ for (gre = __gr_get_head (); NULL != gre; gre = gre->next) { /* * Skip all NIS entries. */ if ((gre->line[0] == '+') || (gre->line[0] == '-')) { continue; } /* * Start with the entries that are completely corrupt. They * have no (struct group) entry because they couldn't be * parsed properly. */ if (NULL == gre->eptr) { /* * Tell the user this entire line is bogus and ask * them to delete it. */ (void) puts (_("invalid group file entry")); printf (_("delete line '%s'? "), gre->line); *errors += 1; /* * prompt the user to delete the entry or not */ if (!yes_or_no (read_only)) { continue; } /* * All group file deletions wind up here. This code * removes the current entry from the linked list. * When done, it skips back to the top of the loop * to try out the next list element. */ delete_gr: SYSLOG ((LOG_INFO, "delete group line '%s'", gre->line)); *changed = true; __gr_del_entry (gre); continue; } /* * Group structure is good, start using it. */ grp = gre->eptr; /* * Make sure this entry has a unique name. */ for (tgre = __gr_get_head (); NULL != tgre; tgre = tgre->next) { const struct group *ent = tgre->eptr; /* * Don't check this entry */ if (tgre == gre) { continue; } /* * Don't check invalid entries. */ if (NULL == ent) { continue; } if (strcmp (grp->gr_name, ent->gr_name) != 0) { continue; } /* * Tell the user this entry is a duplicate of * another and ask them to delete it. */ (void) puts (_("duplicate group entry")); printf (_("delete line '%s'? "), gre->line); *errors += 1; /* * prompt the user to delete the entry or not */ if (yes_or_no (read_only)) { goto delete_gr; } } /* * Check for invalid group names. --marekm */ if (!is_valid_group_name (grp->gr_name)) { *errors += 1; printf (_("invalid group name '%s'\n"), grp->gr_name); } /* * Check for invalid group ID. */ if (grp->gr_gid == (gid_t)-1) { printf (_("invalid group ID '%lu'\n"), (long unsigned int)grp->gr_gid); *errors += 1; } /* * Workaround for a NYS libc 5.3.12 bug on RedHat 4.2 - * groups with no members are returned as groups with one * member "", causing grpck to fail. --marekm */ if ( (NULL != grp->gr_mem[0]) && (NULL == grp->gr_mem[1]) && ('\0' == grp->gr_mem[0][0])) { grp->gr_mem[0] = NULL; } if (check_members (grp->gr_name, grp->gr_mem, _("group %s: no user %s\n"), _("delete member '%s'? "), "delete member '%s' from group '%s'", errors) == 1) { *changed = true; gre->changed = true; __gr_set_changed (); } #ifdef SHADOWGRP /* * Make sure this entry exists in the /etc/gshadow file. */ if (is_shadow) { sgr = (struct sgrp *) sgr_locate (grp->gr_name); if (sgr == NULL) { printf (_("no matching group file entry in %s\n"), sgr_file); printf (_("add group '%s' in %s? "), grp->gr_name, sgr_file); *errors += 1; if (yes_or_no (read_only)) { struct sgrp sg; struct group gr; static char *empty = NULL; sg.sg_name = grp->gr_name; sg.sg_passwd = grp->gr_passwd; sg.sg_adm = ∅ sg.sg_mem = grp->gr_mem; SYSLOG ((LOG_INFO, "add group '%s' to '%s'", grp->gr_name, sgr_file)); *changed = true; if (sgr_update (&sg) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, sgr_dbname (), sg.sg_name); fail_exit (E_CANT_UPDATE); } /* remove password from /etc/group */ gr = *grp; gr.gr_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ if (gr_update (&gr) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, gr_dbname (), gr.gr_name); fail_exit (E_CANT_UPDATE); } } } else { /** * Verify that all the members defined in /etc/group are also * present in /etc/gshadow. */ compare_members_lists (grp->gr_name, grp->gr_mem, sgr->sg_mem, grp_file, sgr_file); /* The group entry has a gshadow counterpart. * Make sure no passwords are in group. */ if (strcmp (grp->gr_passwd, SHADOW_PASSWD_STRING) != 0) { printf (_("group %s has an entry in %s, but its password field in %s is not set to 'x'\n"), grp->gr_name, sgr_file, grp_file); *errors += 1; } } } #endif } }
/* * add_group - create a new group or add a user to an existing group */ static int add_group (const char *name, const char *gid, gid_t *ngid, uid_t uid) { const struct group *grp; struct group grent; char *members[1]; #ifdef SHADOWGRP const struct sgrp *sg; #endif /* * Start by seeing if the named group already exists. This will be * very easy to deal with if it does. */ grp = getgrnam (gid); if (NULL == grp) { grp = gr_locate (gid); } if (NULL != grp) { /* The user will use this ID for her primary group */ *ngid = grp->gr_gid; /* Don't check gshadow */ return 0; } if (isdigit (gid[0])) { /* * The GID is a number, which means either this is a brand * new group, or an existing group. */ if (get_gid (gid, &grent.gr_gid) == 0) { fprintf (stderr, _("%s: invalid group ID '%s'\n"), Prog, gid); return -1; } /* Look in both the system database (getgrgid) and in the * internal database (gr_locate_gid), which may contain * uncommitted changes */ if ( (getgrgid ((gid_t) grent.gr_gid) != NULL) || (gr_locate_gid ((gid_t) grent.gr_gid) != NULL)) { /* The user will use this ID for her * primary group */ *ngid = (gid_t) grent.gr_gid; return 0; } /* Do not create groups with GID == (gid_t)-1 */ if (grent.gr_gid == (gid_t)-1) { fprintf (stderr, _("%s: invalid group ID '%s'\n"), Prog, gid); return -1; } } else { /* The gid parameter can be "" or a name which is not * already the name of an existing group. * In both cases, figure out what group ID can be used. */ if (find_new_gid(rflg, &grent.gr_gid, &uid) < 0) { return -1; } } /* * Now I have all of the fields required to create the new group. */ if (('\0' != gid[0]) && (!isdigit (gid[0]))) { grent.gr_name = xstrdup (gid); } else { grent.gr_name = xstrdup (name); /* FIXME: check if the group exists */ } /* Check if this is a valid group name */ if (!is_valid_group_name (grent.gr_name)) { fprintf (stderr, _("%s: invalid group name '%s'\n"), Prog, grent.gr_name); if (grent.gr_name) free (grent.gr_name); return -1; } grent.gr_passwd = "*"; /* XXX warning: const */ members[0] = NULL; grent.gr_mem = members; *ngid = grent.gr_gid; #ifdef SHADOWGRP if (is_shadow_grp) { sg = sgr_locate (grent.gr_name); if (NULL != sg) { fprintf (stderr, _("%s: group '%s' is a shadow group, but does not exist in /etc/group\n"), Prog, grent.gr_name); return -1; } } #endif #ifdef SHADOWGRP if (is_shadow_grp) { struct sgrp sgrent; char *admins[1]; sgrent.sg_name = grent.gr_name; sgrent.sg_passwd = "*"; /* XXX warning: const */ grent.gr_passwd = "x"; /* XXX warning: const */ admins[0] = NULL; sgrent.sg_adm = admins; sgrent.sg_mem = members; if (sgr_update (&sgrent) == 0) { return -1; } } #endif if (gr_update (&grent) == 0) { return -1; } return 0; }