/* * fail_exit - undo as much as possible */ static void fail_exit (int code) { if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } if (gr_locked) { if (gr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); /* continue */ } } #ifdef SHADOWGRP if (sgr_locked) { if (sgr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); /* continue */ } } #endif exit (code); }
/* * close_files - close and unlock the password databases */ static void close_files (void) { if (is_shadow_pwd) { if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (1); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; } if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (1); } if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } pw_locked = false; }
/* * close_files - close and unlock the password/shadow databases */ static void close_files (void) { /* * Now close the shadow password file, which will cause all of the * entries to be re-written. */ if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (E_NOPERM); } /* * Close the password file. If any entries were modified, the file * will be re-written. */ if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (E_NOPERM); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } pw_locked = false; }
/* * fail_exit - do some cleanup and exit with the given error code */ static /*@noreturn@*/void fail_exit (int code) { if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } closelog (); #ifdef WITH_AUDIT if (E_SUCCESS != code) { audit_logger (AUDIT_USER_CHAUTHTOK, Prog, "change age", user_name, (unsigned int) user_uid, 0); } #endif exit (code); }
/* * fail_exit - do some cleanup and exit with the given error code */ static void fail_exit (int code) { if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); if (use_system_spw_file) { SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); } /* continue */ } } if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); if (use_system_pw_file) { SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); } /* continue */ } } closelog (); exit (code); }
/* * close_files - close all of the files that were opened * * close_files() closes all of the files that were opened for this * new user. This causes any modified entries to be written out. */ static void close_files (void) { if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (E_PW_UPDATE); } if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } pw_locked = false; if (is_shadow_pwd) { if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (E_PW_UPDATE); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; } if (gr_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); fail_exit (E_GRP_UPDATE); } if (gr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); /* continue */ } gr_locked = false; #ifdef SHADOWGRP if (is_shadow_grp) { if (sgr_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); fail_exit (E_GRP_UPDATE); } if (sgr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); /* continue */ } sgr_locked = false; } #endif /* SHADOWGRP */ }
/* * fail_exit - exit with a failure code after unlocking the files */ static void fail_exit (int code) { if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } if (gr_locked) { if (gr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); /* continue */ } } if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } #ifdef SHADOWGRP if (sgr_locked) { if (sgr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); /* continue */ } } #endif /* SHADOWGRP */ #ifdef ENABLE_SUBIDS if (sub_uid_locked) { if (sub_uid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); /* continue */ } } if (sub_gid_locked) { if (sub_gid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); /* continue */ } } #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ exit (code); }
/* * open_files - open the shadow database * * In read-only mode, the databases are not locked and are opened * only for reading. */ static void open_files (void) { bool use_tcb = false; #ifdef WITH_TCB use_tcb = getdef_bool ("USE_TCB"); #endif /* WITH_TCB */ /* * Lock the files if we aren't in "read-only" mode */ if (!read_only) { if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (E_CANTLOCK); } pw_locked = true; if (is_shadow && !use_tcb) { if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (E_CANTLOCK); } spw_locked = true; } } /* * Open the files. Use O_RDONLY if we are in read_only mode, O_RDWR * otherwise. */ if (pw_open (read_only ? O_RDONLY : O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); if (use_system_pw_file) { SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); } fail_exit (E_CANTOPEN); } pw_opened = true; if (is_shadow && !use_tcb) { if (spw_open (read_only ? O_RDONLY : O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); if (use_system_spw_file) { SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); } fail_exit (E_CANTOPEN); } spw_opened = true; } }
static void fail_exit (int status) { if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } exit (status); }
/* * open_files - open the shadow database * * In read-only mode, the databases are not locked and are opened * only for reading. */ static void open_files (bool readonly) { /* * Lock and open the password file. This loads all of the password * file entries into memory. Then we get a pointer to the password * file entry for the requested user. */ if (!readonly) { if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (E_NOPERM); } pw_locked = true; } if (pw_open (readonly ? O_RDONLY: O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); fail_exit (E_NOPERM); } /* * For shadow password files we have to lock the file and read in * the entries as was done for the password file. The user entries * does not have to exist in this case; a new entry will be created * for this user if one does not exist already. */ if (!readonly) { if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (E_NOPERM); } spw_locked = true; } if (spw_open (readonly ? O_RDONLY: O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); fail_exit (E_NOPERM); } }
/* * close_files - close and unlock the password/shadow databases * * If changed is not set, the databases are not closed, and no * changes are committed in the databases. The databases are * unlocked anyway. */ static void close_files (bool changed) { /* * All done. If there were no change we can just abandon any * changes to the files. */ if (changed) { if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pwd_file); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pwd_file)); fail_exit (E_CANTUPDATE); } if (is_shadow && (spw_close () == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_file); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_file)); fail_exit (E_CANTUPDATE); } } /* * Don't be anti-social - unlock the files when you're done. */ if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } spw_locked = false; if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } pw_locked = false; }
/* * fail_exit - exit with a failure code after unlocking the files */ static void fail_exit (int code) { #ifndef USE_PAM if (pw_locked) { if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } } if (spw_locked) { if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } } #endif /* !USE_PAM */ exit (code); }
/* * update_age - update the aging information in the database * * It will not return in case of error */ static void update_age (/*@null@*/const struct spwd *sp, /*@notnull@*/const struct passwd *pw) { struct spwd spwent; /* * There was no shadow entry. The new entry will have the encrypted * password transferred from the normal password file along with the * aging information. */ if (NULL == sp) { struct passwd pwent = *pw; memzero (&spwent, sizeof spwent); spwent.sp_namp = xstrdup (pwent.pw_name); spwent.sp_pwdp = xstrdup (pwent.pw_passwd); spwent.sp_flag = SHADOW_SP_FLAG_UNSET; pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ if (pw_update (&pwent) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pwent.pw_name); fail_exit (E_NOPERM); } } else { spwent.sp_namp = xstrdup (sp->sp_namp); spwent.sp_pwdp = xstrdup (sp->sp_pwdp); spwent.sp_flag = sp->sp_flag; } /* * Copy the fields back to the shadow file entry and write the * modified entry back to the shadow file. Closing the shadow and * password files will commit any changes that have been made. */ spwent.sp_max = maxdays; spwent.sp_min = mindays; spwent.sp_lstchg = lstchgdate; spwent.sp_warn = warndays; spwent.sp_inact = inactdays; spwent.sp_expire = expdate; if (spw_update (&spwent) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spwent.sp_namp); fail_exit (E_NOPERM); } }
/* * open_files - lock and open the password databases */ static void open_files (void) { /* * Lock the password file and open it for reading and writing. This * will bring all of the entries into memory where they may be updated. */ if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (1); } pw_locked = true; if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); fail_exit (1); } /* Do the same for the shadowed database, if it exist */ if (is_shadow_pwd) { if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (1); } spw_locked = true; if (spw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); fail_exit (1); } } }
/* * update_user - delete the user entries * * update_user() deletes the password file entries for this user * and will update the group entries as required. */ static void update_user (void) { if (pw_remove (user_name) == 0) { fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, user_name, pw_dbname ()); fail_exit (E_PW_UPDATE); } if ( is_shadow_pwd && (spw_locate (user_name) != NULL) && (spw_remove (user_name) == 0)) { fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, user_name, spw_dbname ()); fail_exit (E_PW_UPDATE); } #ifdef ENABLE_SUBIDS if (is_sub_uid && sub_uid_remove(user_name, 0, ULONG_MAX) == 0) { fprintf (stderr, _("%s: cannot remove entry %lu from %s\n"), Prog, (unsigned long)user_id, sub_uid_dbname ()); fail_exit (E_SUB_UID_UPDATE); } if (is_sub_gid && sub_gid_remove(user_name, 0, ULONG_MAX) == 0) { fprintf (stderr, _("%s: cannot remove entry %lu from %s\n"), Prog, (unsigned long)user_id, sub_gid_dbname ()); fail_exit (E_SUB_GID_UPDATE); } #endif /* ENABLE_SUBIDS */ #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user entries", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif /* WITH_AUDIT */ SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); }
/* * update_user - delete the user entries * * update_user() deletes the password file entries for this user * and will update the group entries as required. */ static void update_user (void) { if (pw_remove (user_name) == 0) { fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, user_name, pw_dbname ()); fail_exit (E_PW_UPDATE); } if ( is_shadow_pwd && (spw_locate (user_name) != NULL) && (spw_remove (user_name) == 0)) { fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, user_name, spw_dbname ()); fail_exit (E_PW_UPDATE); } #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user entries", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); #endif SYSLOG ((LOG_INFO, "delete user '%s'\n", user_name)); }
int main (int argc, char **argv) { const struct passwd *pw; struct passwd pwent; const struct spwd *spwd; if (1 != argc) { (void) fputs (_("Usage: pwunconv\n"), stderr); } Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); OPENLOG ("pwunconv"); #ifdef WITH_TCB if (getdef_bool("USE_TCB")) { fprintf(stderr, _("%s: can't work with tcb enabled\n"), Prog); exit(1); } #endif /* WITH_TCB */ if (!spw_file_present ()) { /* shadow not installed, do nothing */ exit (0); } if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (5); } pw_locked = true; if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); fail_exit (1); } if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (5); } spw_locked = true; if (spw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); fail_exit (1); } pw_rewind (); while ((pw = pw_next ()) != NULL) { spwd = spw_locate (pw->pw_name); if (NULL == spwd) { continue; } pwent = *pw; /* * Update password if non-shadow is "x". */ if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) { pwent.pw_passwd = spwd->sp_pwdp; } /* * Password aging works differently in the two different * systems. With shadow password files you apparently must * have some aging information. The maxweeks or minweeks * may not map exactly. In pwconv we set max == 10000, * which is about 30 years. Here we have to undo that * kludge. So, if maxdays == 10000, no aging information is * put into the new file. Otherwise, the days are converted * to weeks and so on. */ if (pw_update (&pwent) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pwent.pw_name); fail_exit (3); } } if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (3); } if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (3); } if (unlink (SHADOW) != 0) { fprintf (stderr, _("%s: cannot delete %s\n"), Prog, SHADOW); SYSLOG ((LOG_ERR, "cannot delete %s", SHADOW)); fail_exit (3); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } nscd_flush_cache ("passwd"); return 0; }
/* * pwck - verify password file integrity */ int main (int argc, char **argv) { int errors = 0; bool changed = false; /* * Get my name so that I can use it to report errors. */ Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); OPENLOG ("pwck"); /* Parse the command line arguments */ process_flags (argc, argv); open_files (); if (sort_mode) { if (pw_sort () != 0) { fprintf (stderr, _("%s: cannot sort entries in %s\n"), Prog, pw_dbname ()); fail_exit (E_CANTSORT); } if (is_shadow) { if (spw_sort () != 0) { fprintf (stderr, _("%s: cannot sort entries in %s\n"), Prog, spw_dbname ()); fail_exit (E_CANTSORT); } } changed = true; } else { check_pw_file (&errors, &changed); if (is_shadow) { check_spw_file (&errors, &changed); } } close_files (changed); nscd_flush_cache ("passwd"); /* * Tell the user what we did and exit. */ if (0 != errors) { printf (changed ? _("%s: the files have been updated\n") : _("%s: no changes\n"), Prog); } closelog (); return ((0 != errors) ? E_BADENTRY : E_OKAY); }
static void open_files (void) { if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking password file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } pw_locked = true; if (pw_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening password file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } if (is_shadow_pwd) { if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking shadow password file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } spw_locked = true; if (spw_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening shadow password file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_PW_UPDATE); } } if (gr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } gr_locked = true; if (gr_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } #ifdef SHADOWGRP if (is_shadow_grp) { if (sgr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking shadow group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } sgr_locked= true; if (sgr_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening shadow group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_GRP_UPDATE); } } #endif /* SHADOWGRP */ #ifdef ENABLE_SUBIDS if (is_sub_uid) { if (sub_uid_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_uid_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking subordinate user file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SUB_UID_UPDATE); } sub_uid_locked = true; if (sub_uid_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening subordinate user file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SUB_UID_UPDATE); } } if (is_sub_gid) { if (sub_gid_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_gid_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "locking subordinate group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SUB_GID_UPDATE); } sub_gid_locked = true; if (sub_gid_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "opening subordinate group file", user_name, (unsigned int) user_id, SHADOW_AUDIT_FAILURE); #endif /* WITH_AUDIT */ fail_exit (E_SUB_GID_UPDATE); } } #endif /* ENABLE_SUBIDS */ }
int main (int argc, char **argv) { bool editshadow = false; char *a; bool do_vipw; (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); progname = ((a = strrchr (*argv, '/')) ? a + 1 : *argv); do_vipw = (strcmp (progname, "vigr") != 0); OPENLOG (do_vipw ? "vipw" : "vigr"); { /* * Parse the command line options. */ int c; static struct option long_options[] = { {"group", no_argument, NULL, 'g'}, {"help", no_argument, NULL, 'h'}, {"passwd", no_argument, NULL, 'p'}, {"quiet", no_argument, NULL, 'q'}, {"shadow", no_argument, NULL, 's'}, #ifdef WITH_TCB {"user", required_argument, NULL, 'u'}, #endif /* WITH_TCB */ {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, #ifdef WITH_TCB "ghpqsu:", #else /* !WITH_TCB */ "ghpqs", #endif /* !WITH_TCB */ long_options, NULL)) != -1) { switch (c) { case 'g': do_vipw = false; break; case 'h': usage (E_SUCCESS); break; case 'p': do_vipw = true; break; case 'q': quiet = true; break; case 's': editshadow = true; break; #ifdef WITH_TCB case 'u': user = optarg; break; #endif /* WITH_TCB */ default: usage (E_USAGE); } } } if (do_vipw) { if (editshadow) { #ifdef WITH_TCB if (getdef_bool ("USE_TCB") && (NULL != user)) { if (shadowtcb_set_user (user) == SHADOWTCB_FAILURE) { fprintf (stderr, _("%s: failed to find tcb directory for %s\n"), progname, user); return E_SHADOW_NOTFOUND; } tcb_mode = true; } #endif /* WITH_TCB */ vipwedit (spw_dbname (), spw_lock, spw_unlock); printf (MSG_WARN_EDIT_OTHER_FILE, spw_dbname (), pw_dbname (), "vipw"); } else { vipwedit (pw_dbname (), pw_lock, pw_unlock); if (spw_file_present ()) { printf (MSG_WARN_EDIT_OTHER_FILE, pw_dbname (), spw_dbname (), "vipw -s"); } } } else { #ifdef SHADOWGRP if (editshadow) { vipwedit (sgr_dbname (), sgr_lock, sgr_unlock); printf (MSG_WARN_EDIT_OTHER_FILE, sgr_dbname (), gr_dbname (), "vigr"); } else { #endif /* SHADOWGRP */ vipwedit (gr_dbname (), gr_lock, gr_unlock); #ifdef SHADOWGRP if (sgr_file_present ()) { printf (MSG_WARN_EDIT_OTHER_FILE, gr_dbname (), sgr_dbname (), "vigr -s"); } } #endif /* SHADOWGRP */ } nscd_flush_cache ("passwd"); nscd_flush_cache ("group"); return E_SUCCESS; }
/* * check_pw_file - check the content of the passwd file */ static void check_pw_file (int *errors, bool *changed) { struct commonio_entry *pfe, *tpfe; struct passwd *pwd; struct spwd *spw; /* * Loop through the entire password file. */ for (pfe = __pw_get_head (); NULL != pfe; pfe = pfe->next) { /* * If this is a NIS line, skip it. You can't "know" what NIS * is going to do without directly asking NIS ... */ if (('+' == pfe->line[0]) || ('-' == pfe->line[0])) { continue; } /* * Start with the entries that are completely corrupt. They * have no (struct passwd) entry because they couldn't be * parsed properly. */ if (NULL == pfe->eptr) { /* * Tell the user this entire line is bogus and ask * them to delete it. */ puts (_("invalid password file entry")); printf (_("delete line '%s'? "), pfe->line); *errors += 1; /* * prompt the user to delete the entry or not */ if (!yes_or_no (read_only)) { continue; } /* * All password 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_pw: SYSLOG ((LOG_INFO, "delete passwd line '%s'", pfe->line)); *changed = true; __pw_del_entry (pfe); continue; } /* * Password structure is good, start using it. */ pwd = pfe->eptr; /* * Make sure this entry has a unique name. */ for (tpfe = __pw_get_head (); NULL != tpfe; tpfe = tpfe->next) { const struct passwd *ent = tpfe->eptr; /* * Don't check this entry */ if (tpfe == pfe) { continue; } /* * Don't check invalid entries. */ if (NULL == ent) { continue; } if (strcmp (pwd->pw_name, ent->pw_name) != 0) { continue; } /* * Tell the user this entry is a duplicate of * another and ask them to delete it. */ puts (_("duplicate password entry")); printf (_("delete line '%s'? "), pfe->line); *errors += 1; /* * prompt the user to delete the entry or not */ if (yes_or_no (read_only)) { goto delete_pw; } } /* * Check for invalid usernames. --marekm */ if (!is_valid_user_name (pwd->pw_name)) { printf (_("invalid user name '%s'\n"), pwd->pw_name); *errors += 1; } /* * Check for invalid user ID. */ if (pwd->pw_uid == (uid_t)-1) { printf (_("invalid user ID '%lu'\n"), (long unsigned int)pwd->pw_uid); *errors += 1; } /* * Make sure the primary group exists */ /* local, no need for xgetgrgid */ if (!quiet && (NULL == getgrgid (pwd->pw_gid))) { /* * No primary group, just give a warning */ printf (_("user '%s': no group %lu\n"), pwd->pw_name, (unsigned long) pwd->pw_gid); *errors += 1; } /* * Make sure the home directory exists */ if (!quiet && (access (pwd->pw_dir, F_OK) != 0)) { /* * Home directory doesn't exist, give a warning */ printf (_("user '%s': directory '%s' does not exist\n"), pwd->pw_name, pwd->pw_dir); *errors += 1; } /* * Make sure the login shell is executable */ if ( !quiet && ('\0' != pwd->pw_shell[0]) && (access (pwd->pw_shell, F_OK) != 0)) { /* * Login shell doesn't exist, give a warning */ printf (_("user '%s': program '%s' does not exist\n"), pwd->pw_name, pwd->pw_shell); *errors += 1; } /* * Make sure this entry exists in the /etc/shadow file. */ if (is_shadow) { spw = (struct spwd *) spw_locate (pwd->pw_name); if (NULL == spw) { printf (_("no matching password file entry in %s\n"), spw_file); printf (_("add user '%s' in %s? "), pwd->pw_name, spw_file); *errors += 1; if (yes_or_no (read_only)) { struct spwd sp; struct passwd pw; sp.sp_namp = pwd->pw_name; sp.sp_pwdp = pwd->pw_passwd; sp.sp_min = getdef_num ("PASS_MIN_DAYS", -1); sp.sp_max = getdef_num ("PASS_MAX_DAYS", -1); sp.sp_warn = getdef_num ("PASS_WARN_AGE", -1); sp.sp_inact = -1; sp.sp_expire = -1; sp.sp_flag = SHADOW_SP_FLAG_UNSET; sp.sp_lstchg = (long) time ((time_t *) 0) / SCALE; if (0 == sp.sp_lstchg) { /* Better disable aging than * requiring a password change */ sp.sp_lstchg = -1; } *changed = true; if (spw_update (&sp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), sp.sp_namp); exit (E_CANTUPDATE); } /* remove password from /etc/passwd */ pw = *pwd; pw.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ if (pw_update (&pw) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pw.pw_name); exit (E_CANTUPDATE); } } } else { /* The passwd entry has a shadow counterpart. * Make sure no passwords are in passwd. */ if (strcmp (pwd->pw_passwd, SHADOW_PASSWD_STRING) != 0) { printf (_("user %s has an entry in %s, but its password field in %s is not set to 'x'\n"), pwd->pw_name, spw_file, pwd_file); *errors += 1; } } } } }
int main (int argc, char **argv) { const struct passwd *pw; struct passwd pwent; const struct spwd *sp; struct spwd spent; Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_root_flag ("-R", argc, argv); OPENLOG ("pwconv"); process_flags (argc, argv); #ifdef WITH_TCB if (getdef_bool("USE_TCB")) { fprintf (stderr, _("%s: can't work with tcb enabled\n"), Prog); exit (E_FAILURE); } #endif /* WITH_TCB */ if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (E_PWDBUSY); } pw_locked = true; if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); fail_exit (E_MISSING); } if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (E_PWDBUSY); } spw_locked = true; if (spw_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); fail_exit (E_FAILURE); } /* * Remove /etc/shadow entries for users not in /etc/passwd. */ (void) spw_rewind (); while ((sp = spw_next ()) != NULL) { if (pw_locate (sp->sp_namp) != NULL) { continue; } if (spw_remove (sp->sp_namp) == 0) { /* * This shouldn't happen (the entry exists) but... */ fprintf (stderr, _("%s: cannot remove entry '%s' from %s\n"), Prog, sp->sp_namp, spw_dbname ()); fail_exit (E_FAILURE); } } /* * Update shadow entries which don't have "x" as pw_passwd. Add any * missing shadow entries. */ (void) pw_rewind (); while ((pw = pw_next ()) != NULL) { sp = spw_locate (pw->pw_name); if (NULL != sp) { /* do we need to update this entry? */ if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) { continue; } /* update existing shadow entry */ spent = *sp; } else { /* add new shadow entry */ memset (&spent, 0, sizeof spent); spent.sp_namp = pw->pw_name; spent.sp_min = getdef_num ("PASS_MIN_DAYS", -1); spent.sp_max = getdef_num ("PASS_MAX_DAYS", -1); spent.sp_warn = getdef_num ("PASS_WARN_AGE", -1); spent.sp_inact = -1; spent.sp_expire = -1; spent.sp_flag = SHADOW_SP_FLAG_UNSET; } spent.sp_pwdp = pw->pw_passwd; spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE; if (0 == spent.sp_lstchg) { /* Better disable aging than requiring a password * change */ spent.sp_lstchg = -1; } if (spw_update (&spent) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), spent.sp_namp); fail_exit (E_FAILURE); } /* remove password from /etc/passwd */ pwent = *pw; pwent.pw_passwd = SHADOW_PASSWD_STRING; /* XXX warning: const */ if (pw_update (&pwent) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), pwent.pw_name); fail_exit (E_FAILURE); } } if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (E_FAILURE); } if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (E_FAILURE); } /* /etc/passwd- (backup file) */ if (chmod (PASSWD_FILE "-", 0600) != 0) { fprintf (stderr, _("%s: failed to change the mode of %s to 0600\n"), Prog, PASSWD_FILE "-"); SYSLOG ((LOG_ERR, "failed to change the mode of %s to 0600", PASSWD_FILE "-")); /* continue */ } if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } nscd_flush_cache ("passwd"); return E_SUCCESS; }
static void update_shadow (void) { const struct spwd *sp; struct spwd *nsp; if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); exit (E_PWDBUSY); } spw_locked = true; if (spw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ())); fail_exit (E_FAILURE); } sp = spw_locate (name); if (NULL == sp) { /* Try to update the password in /etc/passwd instead. */ (void) spw_close (); update_noshadow (); if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; return; } nsp = __spw_dup (sp); if (NULL == nsp) { oom (); } nsp->sp_pwdp = update_crypt_pw (nsp->sp_pwdp); if (xflg) { nsp->sp_max = (age_max * DAY) / SCALE; } if (nflg) { nsp->sp_min = (age_min * DAY) / SCALE; } if (wflg) { nsp->sp_warn = (warn * DAY) / SCALE; } if (iflg) { nsp->sp_inact = (inact * DAY) / SCALE; } #ifndef USE_PAM if (do_update_age) { nsp->sp_lstchg = (long) time ((time_t *) 0) / SCALE; if (0 == nsp->sp_lstchg) { /* Better disable aging than requiring a password * change */ nsp->sp_lstchg = -1; } } #endif /* !USE_PAM */ /* * Force change on next login, like SunOS 4.x passwd -e or Solaris * 2.x passwd -f. Solaris 2.x seems to do the same thing (set * sp_lstchg to 0). */ if (eflg) { nsp->sp_lstchg = 0; } if (spw_update (nsp) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, spw_dbname (), nsp->sp_namp); fail_exit (E_FAILURE); } if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (E_FAILURE); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; }
int main (int argc, char **argv) { char buf[BUFSIZ]; char *name; char *newpwd; char *cp; #ifndef USE_PAM const struct spwd *sp; struct spwd newsp; const struct passwd *pw; struct passwd newpw; #endif /* !USE_PAM */ int errors = 0; int line = 0; Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); process_flags (argc, argv); OPENLOG ("chpasswd"); check_perms (); #ifndef USE_PAM is_shadow_pwd = spw_file_present (); open_files (); #endif /* * Read each line, separating the user name from the password. The * password entry for each user will be looked up in the appropriate * file (shadow or passwd) and the password changed. For shadow * files the last change date is set directly, for passwd files the * last change date is set in the age only if aging information is * present. */ while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) { line++; cp = strrchr (buf, '\n'); if (NULL != cp) { *cp = '\0'; } else { if (feof (stdin) == 0) { fprintf (stderr, _("%s: line %d: line too long\n"), Prog, line); errors++; continue; } } /* * The username is the first field. It is separated from the * password with a ":" character which is replaced with a * NUL to give the new password. The new password will then * be encrypted in the normal fashion with a new salt * generated, unless the '-e' is given, in which case it is * assumed to already be encrypted. */ name = buf; cp = strchr (name, ':'); if (NULL != cp) { *cp = '\0'; cp++; } else { fprintf (stderr, _("%s: line %d: missing new password\n"), Prog, line); errors++; continue; } newpwd = cp; #ifdef USE_PAM if (do_pam_passwd_non_interractive ("chpasswd", name, newpwd) != 0) { fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, line, name); errors++; } #else /* !USE_PAM */ if ( !eflg && ( (NULL == crypt_method) || (0 != strcmp (crypt_method, "NONE")))) { void *arg = NULL; if (md5flg) { crypt_method = "MD5"; } else if (crypt_method != NULL) { #ifdef USE_SHA_CRYPT if (sflg) { arg = &sha_rounds; } #endif } else { crypt_method = NULL; } cp = pw_encrypt (newpwd, crypt_make_salt(crypt_method, arg)); } /* * Get the password file entry for this user. The user must * already exist. */ pw = pw_locate (name); if (NULL == pw) { fprintf (stderr, _("%s: line %d: user '%s' does not exist\n"), Prog, line, name); errors++; continue; } if (is_shadow_pwd) { sp = spw_locate (name); } else { sp = NULL; } /* * The freshly encrypted new password is merged into the * user's password file entry and the last password change * date is set to the current date. */ if (NULL != sp) { newsp = *sp; newsp.sp_pwdp = cp; newsp.sp_lstchg = (long) time ((time_t *)NULL) / SCALE; if (0 == newsp.sp_lstchg) { /* Better disable aging than requiring a * password change */ newsp.sp_lstchg = -1; } } else { newpw = *pw; newpw.pw_passwd = cp; } /* * The updated password file entry is then put back and will * be written to the password file later, after all the * other entries have been updated as well. */ if (NULL != sp) { if (spw_update (&newsp) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, spw_dbname (), newsp.sp_namp); errors++; continue; } } else { if (pw_update (&newpw) == 0) { fprintf (stderr, _("%s: line %d: failed to prepare the new %s entry '%s'\n"), Prog, line, pw_dbname (), newpw.pw_name); errors++; continue; } } #endif /* !USE_PAM */ } /* * Any detected errors will cause the entire set of changes to be * aborted. Unlocking the password file will cause all of the * changes to be ignored. Otherwise the file is closed, causing the * changes to be written out all at once, and then unlocked * afterwards. * * With PAM, it is not possible to delay the update of the * password database. */ if (0 != errors) { #ifndef USE_PAM fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); #endif fail_exit (1); } #ifndef USE_PAM /* Save the changes */ close_files (); #endif nscd_flush_cache ("passwd"); return (0); }
/* * open_files - lock and open the password, group and shadow databases */ static void open_files (void) { /* * Lock the password files and open them for update. This will bring * all of the entries into memory where they may be searched for an * modified, or new entries added. The password file is the key - if * it gets locked, assume the others can be locked right away. */ if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); fail_exit (EXIT_FAILURE); } pw_locked = true; if (is_shadow) { if (spw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, spw_dbname ()); fail_exit (EXIT_FAILURE); } spw_locked = true; } if (gr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); fail_exit (EXIT_FAILURE); } gr_locked = true; #ifdef SHADOWGRP if (is_shadow_grp) { if (sgr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); fail_exit (EXIT_FAILURE); } sgr_locked = true; } #endif #ifdef ENABLE_SUBIDS if (is_sub_uid) { if (sub_uid_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_uid_dbname ()); fail_exit (EXIT_FAILURE); } sub_uid_locked = true; } if (is_sub_gid) { if (sub_gid_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sub_gid_dbname ()); fail_exit (EXIT_FAILURE); } sub_gid_locked = true; } #endif /* ENABLE_SUBIDS */ if (pw_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); fail_exit (EXIT_FAILURE); } if (is_shadow && (spw_open (O_CREAT | O_RDWR) == 0)) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, spw_dbname ()); fail_exit (EXIT_FAILURE); } if (gr_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); fail_exit (EXIT_FAILURE); } #ifdef SHADOWGRP if (is_shadow_grp && (sgr_open (O_CREAT | O_RDWR) == 0)) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); fail_exit (EXIT_FAILURE); } #endif #ifdef ENABLE_SUBIDS if (is_sub_uid) { if (sub_uid_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sub_uid_dbname ()); fail_exit (EXIT_FAILURE); } } if (is_sub_gid) { if (sub_gid_open (O_CREAT | O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sub_gid_dbname ()); fail_exit (EXIT_FAILURE); } } #endif /* ENABLE_SUBIDS */ }
/* * close_files - close and unlock the password, group and shadow databases */ static void close_files (void) { if (pw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ())); fail_exit (EXIT_FAILURE); } if (pw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ())); /* continue */ } pw_locked = false; if (is_shadow) { if (spw_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ())); fail_exit (EXIT_FAILURE); } if (spw_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ())); /* continue */ } spw_locked = false; } if (gr_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ())); fail_exit (EXIT_FAILURE); } #ifdef ENABLE_SUBIDS if (is_sub_uid && (sub_uid_close () == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_uid_dbname ())); fail_exit (EXIT_FAILURE); } if (is_sub_gid && (sub_gid_close () == 0)) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sub_gid_dbname ())); fail_exit (EXIT_FAILURE); } #endif /* ENABLE_SUBIDS */ if (gr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ())); /* continue */ } gr_locked = false; #ifdef SHADOWGRP if (is_shadow_grp) { if (sgr_close () == 0) { fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ())); fail_exit (EXIT_FAILURE); } if (sgr_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ())); /* continue */ } sgr_locked = false; } #endif #ifdef ENABLE_SUBIDS if (is_sub_uid) { if (sub_uid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_uid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_uid_dbname ())); /* continue */ } sub_uid_locked = false; } if (is_sub_gid) { if (sub_gid_unlock () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sub_gid_dbname ()); SYSLOG ((LOG_ERR, "failed to unlock %s", sub_gid_dbname ())); /* continue */ } sub_gid_locked = false; } #endif /* ENABLE_SUBIDS */ }