/* * 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); }
/* * 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; }
void update_primary_groups (gid_t ogid, gid_t ngid) { struct passwd *pwd; setpwent (); while ((pwd = getpwent ()) != NULL) { if (pwd->pw_gid == ogid) { const struct passwd *lpwd; struct passwd npwd; lpwd = pw_locate (pwd->pw_name); if (NULL == lpwd) { fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), Prog, pwd->pw_name, pw_dbname ()); exit (E_GRP_UPDATE); } else { npwd = *lpwd; npwd.pw_gid = ngid; if (pw_update (&npwd) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), npwd.pw_name); exit (E_GRP_UPDATE); } } } } endpwent (); }
/* * 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); }
/* * 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; } }
/* * fail_exit - exit with an error and do some cleanup */ 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 */ } } pw_locked = false; closelog (); exit (code); }
/* * open_files - open the accounts databases * * open_files() opens the group, gshadow, and passwd databases. */ static void open_files (void) { if (gr_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); exit (E_GRP_UPDATE); } #ifdef SHADOWGRP if ( is_shadow_grp && (pflg || nflg)) { if (sgr_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", sgr_dbname ())); exit (E_GRP_UPDATE); } } #endif /* SHADOWGRP */ if (gflg) { if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ())); exit (E_GRP_UPDATE); } } }
/* * lock_files - lock the accounts databases * * lock_files() locks the group, gshadow, and passwd databases. */ static void lock_files (void) { if (gr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, gr_dbname ()); exit (E_GRP_UPDATE); } add_cleanup (cleanup_unlock_group, NULL); #ifdef SHADOWGRP if ( is_shadow_grp && (pflg || nflg)) { if (sgr_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, sgr_dbname ()); exit (E_GRP_UPDATE); } add_cleanup (cleanup_unlock_gshadow, NULL); } #endif if (gflg) { if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); exit (E_GRP_UPDATE); } add_cleanup (cleanup_unlock_passwd, NULL); } }
static void update_noshadow (void) { const struct passwd *pw; struct passwd *npw; if (pw_lock () == 0) { fprintf (stderr, _("%s: cannot lock %s; try again later.\n"), Prog, pw_dbname ()); exit (E_PWDBUSY); } pw_locked = true; if (pw_open (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ())); fail_exit (E_MISSING); } pw = pw_locate (name); if (NULL == pw) { fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), Prog, name, pw_dbname ()); fail_exit (E_NOPERM); } npw = __pw_dup (pw); if (NULL == npw) { oom (); } npw->pw_passwd = update_crypt_pw (npw->pw_passwd); if (pw_update (npw) == 0) { fprintf (stderr, _("%s: failed to prepare the new %s entry '%s'\n"), Prog, pw_dbname (), npw->pw_name); 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); } 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; }
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)); }
/* * 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; } } } } }
/* * 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); }
/* * 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 */ }
int main (int argc, char **argv) { char buf[BUFSIZ]; char *fields[8]; int nfields; char *cp; const struct passwd *pw; struct passwd newpw; int errors = 0; int line = 0; uid_t uid; gid_t gid; #ifdef USE_PAM int *lines = NULL; char **usernames = NULL; char **passwords = NULL; unsigned int nusers = 0; #endif /* USE_PAM */ Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); /* FIXME: will not work with an input file */ process_root_flag ("-R", argc, argv); OPENLOG ("newusers"); process_flags (argc, argv); check_perms (); is_shadow = spw_file_present (); #ifdef SHADOWGRP is_shadow_grp = sgr_file_present (); #endif #ifdef ENABLE_SUBIDS is_sub_uid = sub_uid_file_present () && !rflg; is_sub_gid = sub_gid_file_present () && !rflg; #endif /* ENABLE_SUBIDS */ open_files (); /* * Read each line. The line has the same format as a password file * entry, except that certain fields are not constrained to be * numerical values. If a group ID is entered which does not already * exist, an attempt is made to allocate the same group ID as the * numerical user ID. Should that fail, the next available group ID * over 100 is allocated. The pw_gid field will be updated with that * value. */ 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; } } /* * Break the string into fields and screw around with them. * There MUST be 7 colon separated fields, although the * values aren't that particular. */ for (cp = buf, nfields = 0; nfields < 7; nfields++) { fields[nfields] = cp; cp = strchr (cp, ':'); if (NULL != cp) { *cp = '\0'; cp++; } else { break; } } if (nfields != 6) { fprintf (stderr, _("%s: line %d: invalid line\n"), Prog, line); errors++; continue; } /* * First check if we have to create or update an user */ pw = pw_locate (fields[0]); /* local, no need for xgetpwnam */ if ( (NULL == pw) && (getpwnam (fields[0]) != NULL)) { fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]); errors++; continue; } if ( (NULL == pw) && (get_user_id (fields[2], &uid) != 0)) { fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); errors++; continue; } /* * Processed is the group name. A new group will be * created if the group name is non-numeric and does not * already exist. If the group name is a number (which is not * an existing GID), a group with the same name as the user * will be created, with the given GID. The given or created * group will be the primary group of the user. If * there is no named group to be a member of, the UID will * be figured out and that value will be a candidate for a * new group, if that group ID exists, a whole new group ID * will be made up. */ if ( (NULL == pw) && (add_group (fields[0], fields[3], &gid, uid) != 0)) { fprintf (stderr, _("%s: line %d: can't create group\n"), Prog, line); errors++; continue; } /* * Now we work on the user ID. It has to be specified either * as a numerical value, or left blank. If it is a numerical * value, that value will be used, otherwise the next * available user ID is computed and used. After this there * will at least be a (struct passwd) for the user. */ if ( (NULL == pw) && (add_user (fields[0], uid, gid) != 0)) { fprintf (stderr, _("%s: line %d: can't create user\n"), Prog, line); errors++; continue; } /* * The password, gecos field, directory, and shell fields * all come next. */ pw = pw_locate (fields[0]); if (NULL == pw) { fprintf (stderr, _("%s: line %d: user '%s' does not exist in %s\n"), Prog, line, fields[0], pw_dbname ()); errors++; continue; } newpw = *pw; #ifdef USE_PAM /* keep the list of user/password for later update by PAM */ nusers++; lines = realloc (lines, sizeof (lines[0]) * nusers); usernames = realloc (usernames, sizeof (usernames[0]) * nusers); passwords = realloc (passwords, sizeof (passwords[0]) * nusers); lines[nusers-1] = line; usernames[nusers-1] = strdup (fields[0]); passwords[nusers-1] = strdup (fields[1]); #endif /* USE_PAM */ if (add_passwd (&newpw, fields[1]) != 0) { fprintf (stderr, _("%s: line %d: can't update password\n"), Prog, line); errors++; continue; } if ('\0' != fields[4][0]) { newpw.pw_gecos = fields[4]; } if ('\0' != fields[5][0]) { newpw.pw_dir = fields[5]; } if ('\0' != fields[6][0]) { newpw.pw_shell = fields[6]; } if ( ('\0' != fields[5][0]) && (access (newpw.pw_dir, F_OK) != 0)) { /* FIXME: should check for directory */ mode_t msk = 0777 & ~getdef_num ("UMASK", GETDEF_DEFAULT_UMASK); if (mkdir (newpw.pw_dir, msk) != 0) { fprintf (stderr, _("%s: line %d: mkdir %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); } else if (chown (newpw.pw_dir, newpw.pw_uid, newpw.pw_gid) != 0) { fprintf (stderr, _("%s: line %d: chown %s failed: %s\n"), Prog, line, newpw.pw_dir, strerror (errno)); } } /* * Update the password entry with the new changes made. */ if (pw_update (&newpw) == 0) { fprintf (stderr, _("%s: line %d: can't update entry\n"), Prog, line); errors++; continue; } #ifdef ENABLE_SUBIDS /* * Add subordinate uids if the user does not have them. */ if (is_sub_uid && !sub_uid_assigned(fields[0])) { uid_t sub_uid_start = 0; unsigned long sub_uid_count = 0; if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) { if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) { fprintf (stderr, _("%s: failed to prepare new %s entry\n"), Prog, sub_uid_dbname ()); } } else { fprintf (stderr, _("%s: can't find subordinate user range\n"), Prog); errors++; } } /* * Add subordinate gids if the user does not have them. */ if (is_sub_gid && !sub_gid_assigned(fields[0])) { gid_t sub_gid_start = 0; unsigned long sub_gid_count = 0; if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) { if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) { fprintf (stderr, _("%s: failed to prepare new %s entry\n"), Prog, sub_uid_dbname ()); } } else { fprintf (stderr, _("%s: can't find subordinate group range\n"), Prog); errors++; } } #endif /* ENABLE_SUBIDS */ } /* * 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. */ if (0 != errors) { fprintf (stderr, _("%s: error detected, changes ignored\n"), Prog); fail_exit (EXIT_FAILURE); } close_files (); nscd_flush_cache ("passwd"); nscd_flush_cache ("group"); sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP); #ifdef USE_PAM unsigned int i; /* Now update the passwords using PAM */ for (i = 0; i < nusers; i++) { if (do_pam_passwd_non_interactive ("newusers", usernames[i], passwords[i]) != 0) { fprintf (stderr, _("%s: (line %d, user %s) password not changed\n"), Prog, lines[i], usernames[i]); errors++; } } #endif /* USE_PAM */ return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE); }
/* * update_gecos - update the gecos fields in the password database * * Commit the user's entry after changing her gecos field. */ static void update_gecos (const char *user, char *gecos) { const struct passwd *pw; /* The user's password file entry */ struct passwd pwent; /* modified password file entry */ /* * Before going any further, raise the ulimit to prevent colliding * into a lowered ulimit, and set the real UID to root to protect * against unexpected signals. Any keyboard signals are set to be * ignored. */ if (setuid (0) != 0) { fputs (_("Cannot change ID to root.\n"), stderr); SYSLOG ((LOG_ERR, "can't setuid(0)")); fail_exit (E_NOPERM); } pwd_init (); /* * The passwd entry is now ready to be committed back to the * password file. Get a lock on the file and open it. */ 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 (O_RDWR) == 0) { fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ()); fail_exit (E_NOPERM); } /* * Get the entry to update using pw_locate() - we want the real one * from /etc/passwd, not the one from getpwnam() which could contain * the shadow password if (despite the warnings) someone enables * AUTOSHADOW (or SHADOW_COMPAT in libc). --marekm */ pw = pw_locate (user); if (NULL == pw) { fprintf (stderr, _("%s: user '%s' does not exist in %s\n"), Prog, user, pw_dbname ()); fail_exit (E_NOPERM); } /* * Make a copy of the entry, then change the gecos field. The other * fields remain unchanged. */ pwent = *pw; pwent.pw_gecos = gecos; /* * Update the passwd file entry. If there is a DBM file, update that * entry as well. */ 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); } /* * Changes have all been made, so commit them and unlock the file. */ 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 (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; }
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; }
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); }
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; }
/* * 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 */ }