static int _do_setpass(pam_handle_t* pamh, const char *forwho, const char *fromwhat, char *towhat, unsigned int ctrl, int remember) { struct passwd *pwd = NULL; int retval = 0; int unlocked = 0; char *master = NULL; D(("called")); pwd = getpwnam(forwho); if (pwd == NULL) { retval = PAM_AUTHTOK_ERR; goto done; } if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) { #ifdef HAVE_NIS if ((master=getNISserver(pamh, ctrl)) != NULL) { struct timeval timeout; struct yppasswd yppwd; CLIENT *clnt; int status; enum clnt_stat err; /* Unlock passwd file to avoid deadlock */ unlock_pwdf(); unlocked = 1; /* Initialize password information */ yppwd.newpw.pw_passwd = pwd->pw_passwd; yppwd.newpw.pw_name = pwd->pw_name; yppwd.newpw.pw_uid = pwd->pw_uid; yppwd.newpw.pw_gid = pwd->pw_gid; yppwd.newpw.pw_gecos = pwd->pw_gecos; yppwd.newpw.pw_dir = pwd->pw_dir; yppwd.newpw.pw_shell = pwd->pw_shell; yppwd.oldpass = fromwhat ? strdup (fromwhat) : strdup (""); yppwd.newpw.pw_passwd = towhat; D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); /* The yppasswd.x file said `unix authentication required', * so I added it. This is the only reason it is in here. * My yppasswdd doesn't use it, but maybe some others out there * do. --okir */ clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); clnt->cl_auth = authunix_create_default(); memset((char *) &status, '\0', sizeof(status)); timeout.tv_sec = 25; timeout.tv_usec = 0; err = clnt_call(clnt, YPPASSWDPROC_UPDATE, (xdrproc_t) xdr_yppasswd, (char *) &yppwd, (xdrproc_t) xdr_int, (char *) &status, timeout); free (yppwd.oldpass); if (err) { _make_remark(pamh, ctrl, PAM_TEXT_INFO, clnt_sperrno(err)); } else if (status) { D(("Error while changing NIS password.\n")); } D(("The password has%s been changed on %s.", (err || status) ? " not" : "", master)); pam_syslog(pamh, LOG_NOTICE, "password%s changed for %s on %s", (err || status) ? " not" : "", pwd->pw_name, master); auth_destroy(clnt->cl_auth); clnt_destroy(clnt); if (err || status) { _make_remark(pamh, ctrl, PAM_TEXT_INFO, _("NIS password could not be changed.")); retval = PAM_TRY_AGAIN; } #ifdef PAM_DEBUG sleep(5); #endif } else { retval = PAM_TRY_AGAIN; } #else if (on(UNIX_DEBUG, ctrl)) { pam_syslog(pamh, LOG_DEBUG, "No NIS support available"); } retval = PAM_TRY_AGAIN; #endif } if (_unix_comesfromsource(pamh, forwho, 1, 0)) { if(unlocked) { if (lock_pwdf() != PAM_SUCCESS) { return PAM_AUTHTOK_LOCK_BUSY; } } #ifdef WITH_SELINUX if (unix_selinux_confined()) return _unix_run_update_binary(pamh, ctrl, forwho, fromwhat, towhat, remember); #endif /* first, save old password */ if (save_old_password(pamh, forwho, fromwhat, remember)) { retval = PAM_AUTHTOK_ERR; goto done; } if (on(UNIX_SHADOW, ctrl) || is_pwd_shadowed(pwd)) { retval = unix_update_shadow(pamh, forwho, towhat); if (retval == PAM_SUCCESS) if (!is_pwd_shadowed(pwd)) retval = unix_update_passwd(pamh, forwho, "x"); } else { retval = unix_update_passwd(pamh, forwho, towhat); } } done: unlock_pwdf(); return retval; }
static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat, char *towhat, unsigned int ctrl, int remember) { struct passwd *pwd = NULL; int retval = 0; D(("called")); setpwent(); pwd = getpwnam(forwho); endpwent(); if (pwd == NULL) return PAM_AUTHTOK_ERR; if (on(UNIX_NIS, ctrl)) { struct timeval timeout; struct yppasswd yppwd; CLIENT *clnt; char *master; int status; int err = 0; /* Make RPC call to NIS server */ if ((master = getNISserver(pamh)) == NULL) return PAM_TRY_AGAIN; /* Initialize password information */ yppwd.newpw.pw_passwd = pwd->pw_passwd; yppwd.newpw.pw_name = pwd->pw_name; yppwd.newpw.pw_uid = pwd->pw_uid; yppwd.newpw.pw_gid = pwd->pw_gid; yppwd.newpw.pw_gecos = pwd->pw_gecos; yppwd.newpw.pw_dir = pwd->pw_dir; yppwd.newpw.pw_shell = pwd->pw_shell; yppwd.oldpass = fromwhat; yppwd.newpw.pw_passwd = towhat; D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho)); /* The yppasswd.x file said `unix authentication required', * so I added it. This is the only reason it is in here. * My yppasswdd doesn't use it, but maybe some others out there * do. --okir */ clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); clnt->cl_auth = authunix_create_default(); memset((char *) &status, '\0', sizeof(status)); timeout.tv_sec = 25; timeout.tv_usec = 0; err = clnt_call(clnt, YPPASSWDPROC_UPDATE, (xdrproc_t) xdr_yppasswd, (char *) &yppwd, (xdrproc_t) xdr_int, (char *) &status, timeout); if (err) { clnt_perrno(err); retval = PAM_TRY_AGAIN; } else if (status) { fprintf(stderr, "Error while changing NIS password.\n"); retval = PAM_TRY_AGAIN; } printf("\nThe password has%s been changed on %s.\n", (err || status) ? " not" : "", master); auth_destroy(clnt->cl_auth); clnt_destroy(clnt); if ((err || status) != 0) { retval = PAM_TRY_AGAIN; } #ifdef DEBUG sleep(5); #endif return retval; } /* first, save old password */ if (save_old_password(forwho, fromwhat, remember)) { return PAM_AUTHTOK_ERR; } if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) { retval = _update_shadow(forwho, towhat); if (retval == PAM_SUCCESS) retval = _update_passwd(forwho, "x"); } else { retval = _update_passwd(forwho, towhat); } return retval; }
static int set_password(const char *forwho, const char *shadow, const char *remember) { struct passwd *pwd = NULL; int retval; char pass[MAXPASS + 1]; char towhat[MAXPASS + 1]; int npass = 0; /* we don't care about number format errors because the helper should be called internally only */ int doshadow = atoi(shadow); int nremember = atoi(remember); char *passwords[] = { pass, towhat }; /* read the password from stdin (a pipe from the pam_unix module) */ npass = read_passwords(STDIN_FILENO, 2, passwords); if (npass != 2) { /* is it a valid password? */ if (npass == 1) { helper_log_err(LOG_DEBUG, "no new password supplied"); memset(pass, '\0', MAXPASS); } else { helper_log_err(LOG_DEBUG, "no valid passwords supplied"); } return PAM_AUTHTOK_ERR; } if (lock_pwdf() != PAM_SUCCESS) return PAM_AUTHTOK_LOCK_BUSY; pwd = getpwnam(forwho); if (pwd == NULL) { retval = PAM_USER_UNKNOWN; goto done; } /* If real caller uid is not root we must verify that received old pass agrees with the current one. We always allow change from null pass. */ if (getuid()) { retval = helper_verify_password(forwho, pass, 1); if (retval != PAM_SUCCESS) { goto done; } } /* first, save old password */ if (save_old_password(forwho, pass, nremember)) { retval = PAM_AUTHTOK_ERR; goto done; } if (doshadow || is_pwd_shadowed(pwd)) { retval = unix_update_shadow(forwho, towhat); if (retval == PAM_SUCCESS) if (!is_pwd_shadowed(pwd)) retval = unix_update_passwd(forwho, "x"); } else { retval = unix_update_passwd(forwho, towhat); } done: memset(pass, '\0', MAXPASS); memset(towhat, '\0', MAXPASS); unlock_pwdf(); if (retval == PAM_SUCCESS) { return PAM_SUCCESS; } else { return PAM_AUTHTOK_ERR; } }