PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[]) { #ifndef _OPENPAM const void *ptr; const struct pam_conv *conv; struct pam_message msg; const struct pam_message *msgp; struct pam_response *resp; #endif struct passwd *pwd; const char *user; char *pad; int pam_err, retry; FILE *file = NULL; char *pw = NULL, *offset = NULL, *num = NULL; /* identify user */ if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) return (pam_err); if ((pwd = getpwnam(user)) == NULL) return (PAM_USER_UNKNOWN); /* get password */ #ifndef _OPENPAM pam_err = pam_get_item(pamh, PAM_CONV, &ptr); if (pam_err != PAM_SUCCESS) return (PAM_SYSTEM_ERR); conv = ptr; msg.msg_style = PAM_PROMPT_ECHO_ON; msg.msg = password_prompt; msgp = &msg; #endif pad = NULL; for (retry = 0; retry < 3; ++retry) { #ifdef _OPENPAM pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, (const char **)&pad, NULL); #else resp = NULL; pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr); if (resp != NULL) { if (pam_err == PAM_SUCCESS) pad = resp->resp; else free(resp->resp); free(resp); } // change to PAM_PROMPT_ECHO_OFF, if you want no password-echo msg.msg_style = PAM_PROMPT_ECHO_ON; #endif if (pam_err == PAM_SUCCESS) break; } if (pam_err == PAM_CONV_ERR) return (pam_err); if (pam_err != PAM_SUCCESS) return (PAM_AUTH_ERR); // open file if((file = fopen(PASSWD_FILE, "r+")) == NULL) return PAM_AUTH_ERR; // parse file if(_parse_passwd(file, user, &pw, &offset, &num) != 0) return _cleanup(file, PAM_AUTH_ERR); // check, if authentication is successfull int i; if((i = openkubus_authenticate(pad, pw, atoi(offset), atoi(num))) > 0) { // update number in password file _update_passwd(file, num, i+1); return _cleanup(file, PAM_SUCCESS); } return _cleanup(file, PAM_AUTH_ERR); }
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; }