int secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth) { char *pw_epasswd = auth->data; #ifdef __alpha extern int crypt_type; # ifdef HAVE_DISPCRYPT if (strcmp(pw_epasswd, dispcrypt(pass, pw_epasswd, crypt_type)) == 0) return AUTH_SUCCESS; # else if (crypt_type == AUTH_CRYPT_BIGCRYPT) { if (strcmp(pw_epasswd, bigcrypt(pass, pw_epasswd)) == 0) return AUTH_SUCCESS; } else if (crypt_type == AUTH_CRYPT_CRYPT16) { if (strcmp(pw_epasswd, crypt(pass, pw_epasswd)) == 0) return AUTH_SUCCESS; } # endif /* HAVE_DISPCRYPT */ #elif defined(HAVE_BIGCRYPT) if (strcmp(pw_epasswd, bigcrypt(pass, pw_epasswd)) == 0) return AUTH_SUCCESS; #endif /* __alpha */ return AUTH_FAILURE; }
char * xcrypt(const char *password, const char *salt) { char *crypted; /* * If we don't have a salt we are encrypting a fake password for * for timing purposes. Pick an appropriate salt. */ if (salt == NULL) salt = pick_salt(); # ifdef HAVE_MD5_PASSWORDS if (is_md5_salt(salt)) crypted = md5_crypt(password, salt); else crypted = crypt(password, salt); # elif defined(__hpux) && !defined(HAVE_SECUREWARE) if (iscomsec()) crypted = bigcrypt(password, salt); else crypted = crypt(password, salt); # elif defined(HAVE_SECUREWARE) crypted = bigcrypt(password, salt); # else crypted = crypt(password, salt); # endif return crypted; }
void priv_gpass(char *gpass) { char *xgpass = NULL; struct acgrp *grp; uid_t uid; gid_t gid; if (group_given == 0) { reply(503, "Give group name with SITE GROUP first."); return; } /* OK, now they're getting a chance to specify a password. Make them * give the group name again if they fail... */ group_given = 0; grp = priv_getent(groupname); if (passbuf && gpass && *gpass != '\0' && grp && *grp->gpass != '\0') #if defined(SecureWare) || defined(HPUX_10_TRUSTED) xgpass = bigcrypt(gpass, grp->gpass); #else xgpass = crypt(gpass, grp->gpass); #endif if (!(((gpass != NULL) && (*gpass != '\0') && (grp != NULL) && (*grp->gpass != '\0') && (strcmp(xgpass, grp->gpass) == 0)) || (((gpass == NULL) || (*gpass == '\0')) && (grp != NULL) && (*grp->gpass == '\0')) )) { reply(530, "Group access request incorrect."); grp = NULL; if (++group_attempts >= lgi_failure_threshold) { syslog(LOG_NOTICE, "repeated group access failures from %s, group %s", remoteident, groupname); exit(0); } sleep(group_attempts); /* slow down password crackers */ return; } uid = geteuid(); gid = grp->gr_gid; delay_signaling(); /* we can't allow any signals while euid==0: kinch */ seteuid(0); setegid(gid); seteuid(uid); enable_signaling(); /* we can allow signals once again: kinch */ reply(200, "Group access enabled."); group_attempts = 0; }
int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "Usage: %s password salt\n", strchr(argv[0], '/') ? (strchr(argv[0], '/') + 1) : argv[0]); return 0; } fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2])); return 0; }
static Bool passwds_match_p (const char *cleartext, const char *ciphertext) { char *s = 0; /* note that on some systems, crypt() may return null */ s = (char *) crypt (cleartext, ciphertext); if (s && !strcmp (s, ciphertext)) return True; #ifdef HAVE_BIGCRYPT /* There seems to be no way to tell at runtime if an HP machine is in "trusted" mode, and thereby, which of crypt() or bigcrypt() we should be calling to compare passwords. So call them both, and see which one works. */ s = (char *) bigcrypt (cleartext, ciphertext); if (s && !strcmp (s, ciphertext)) return True; #endif /* HAVE_BIGCRYPT */ return False; }
int sys_auth_passwd(Authctxt *authctxt, const char *password) { struct passwd *pw = authctxt->pw; char *salt; int result; /* Just use the supplied fake password if authctxt is invalid */ char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; /* Check for users with no password. */ if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) return (1); /* Encrypt the candidate password using the proper salt. */ salt = (pw_password[0] && pw_password[1]) ? pw_password : "******"; /* * Authentication is accepted if the encrypted passwords * are identical. */ #ifdef UNIXWARE_LONG_PASSWORDS if (!nischeck(pw->pw_name)) { result = ((strcmp(bigcrypt(password, salt), pw_password) == 0) || (strcmp(osr5bigcrypt(password, salt), pw_password) == 0)); } else #endif /* UNIXWARE_LONG_PASSWORDS */ result = (strcmp(xcrypt(password, salt), pw_password) == 0); #ifdef USE_LIBIAF if (authctxt->valid) free(pw_password); #endif return(result); }
/**************************************************************************** core of password checking routine ****************************************************************************/ BOOL password_check(char *password) { #ifdef USE_PAM /* This falls through if the password check fails - if NO_CRYPT is defined this causes an error msg saying Warning - no crypt available - if NO_CRYPT is NOT defined this is a potential security hole as it may authenticate via the crypt call when PAM settings say it should fail. if (pam_auth(this_user,password)) return(True); Hence we make a direct return to avoid a second chance!!! */ return (pam_auth(this_user,password)); #endif #ifdef AFS_AUTH if (afs_auth(this_user,password)) return(True); #endif #ifdef DFS_AUTH if (dfs_auth(this_user,password)) return(True); #endif #ifdef KRB5_AUTH if (krb5_auth(this_user,password)) return(True); #endif #ifdef KRB4_AUTH if (krb4_auth(this_user,password)) return(True); #endif #ifdef PWDAUTH if (pwdauth(this_user,password) == 0) return(True); #endif #ifdef OSF1_ENH_SEC { BOOL ret = (strcmp(osf1_bigcrypt(password,this_salt),this_crypted) == 0); if(!ret) { DEBUG(2,("password_check: OSF1_ENH_SEC failed. Trying normal crypt.\n")); ret = (strcmp((char *)crypt(password,this_salt),this_crypted) == 0); } return ret; } #endif #ifdef ULTRIX_AUTH return (strcmp((char *)crypt16(password, this_salt ),this_crypted) == 0); #endif #ifdef LINUX_BIGCRYPT return(linux_bigcrypt(password,this_salt,this_crypted)); #endif #ifdef HPUX_10_TRUSTED return(strcmp(bigcrypt(password,this_salt),this_crypted) == 0); #endif #ifdef NO_CRYPT DEBUG(1,("Warning - no crypt available\n")); return(False); #else return(strcmp((char *)crypt(password,this_salt),this_crypted) == 0); #endif }
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv) { unsigned int ctrl, lctrl; int retval, i; int remember = -1; /* <DO NOT free() THESE> */ const char *user; char *pass_old, *pass_new; /* </DO NOT free() THESE> */ D(("called.")); #ifdef USE_LCKPWDF /* our current locking system requires that we lock the entire password database. This avoids both livelock and deadlock. */ /* These values for the number of attempts and the sleep time are, of course, completely arbitrary. My reading of the PAM docs is that, once pam_chauthtok() has been called with PAM_UPDATE_AUTHTOK, we are obliged to take any reasonable steps to make sure the token is updated; so retrying for 1/10 sec. isn't overdoing it. The other possibility is to call lckpwdf() on the first pam_chauthtok() pass, and hold the lock until released in the second pass--but is this guaranteed to work? -SRL */ i=0; while((retval = lckpwdf()) != 0 && i < 100) { usleep(1000); } if(retval != 0) { return PAM_AUTHTOK_LOCK_BUSY; } #endif ctrl = _set_ctrl(pamh, flags, &remember, argc, argv); /* * First get the name of a user */ retval = pam_get_user(pamh, &user, "Username: "******"bad username [%s]", user); #ifdef USE_LCKPWDF ulckpwdf(); #endif return PAM_USER_UNKNOWN; } if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl)) _log_err(LOG_DEBUG, pamh, "username [%s] obtained", user); } else { if (on(UNIX_DEBUG, ctrl)) _log_err(LOG_DEBUG, pamh, "password - could not identify user"); #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } D(("Got username of %s", user)); /* * This is not an AUTH module! */ if (on(UNIX__NONULL, ctrl)) set(UNIX__NULLOK, ctrl); if (on(UNIX__PRELIM, ctrl)) { /* * obtain and verify the current password (OLDAUTHTOK) for * the user. */ char *Announce; D(("prelim check")); if (_unix_blankpasswd(ctrl, user)) { #ifdef USE_LCKPWDF ulckpwdf(); #endif return PAM_SUCCESS; } else if (off(UNIX__IAMROOT, ctrl)) { /* instruct user what is happening */ #define greeting "Changing password for " Announce = (char *) malloc(sizeof(greeting) + strlen(user)); if (Announce == NULL) { _log_err(LOG_CRIT, pamh, "password - out of memory"); #ifdef USE_LCKPWDF ulckpwdf(); #endif return PAM_BUF_ERR; } (void) strcpy(Announce, greeting); (void) strcpy(Announce + sizeof(greeting) - 1, user); #undef greeting lctrl = ctrl; set(UNIX__OLD_PASSWD, lctrl); retval = _unix_read_password(pamh, lctrl ,Announce ,"(current) UNIX password: "******"password - (old) token not obtained"); #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } /* verify that this is the password for this user */ retval = _unix_verify_password(pamh, user, pass_old, ctrl); } else { D(("process run by root so do nothing this time around")); pass_old = NULL; retval = PAM_SUCCESS; /* root doesn't have too */ } if (retval != PAM_SUCCESS) { D(("Authentication failed")); pass_old = NULL; #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); pass_old = NULL; if (retval != PAM_SUCCESS) { _log_err(LOG_CRIT, pamh, "failed to set PAM_OLDAUTHTOK"); } retval = _unix_verify_shadow(user, ctrl); if (retval == PAM_AUTHTOK_ERR) { if (off(UNIX__IAMROOT, ctrl)) _make_remark(pamh, ctrl, PAM_ERROR_MSG, "You must wait longer to change your password"); else retval = PAM_SUCCESS; } } else if (on(UNIX__UPDATE, ctrl)) { /* * tpass is used below to store the _pam_md() return; it * should be _pam_delete()'d. */ char *tpass = NULL; int retry = 0; /* * obtain the proposed password */ D(("do update")); /* * get the old token back. NULL was ok only if root [at this * point we assume that this has already been enforced on a * previous call to this function]. */ if (off(UNIX_NOT_SET_PASS, ctrl)) { retval = pam_get_item(pamh, PAM_OLDAUTHTOK ,(const void **) &pass_old); } else { retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK ,(const void **) &pass_old); if (retval == PAM_NO_MODULE_DATA) { retval = PAM_SUCCESS; pass_old = NULL; } } D(("pass_old [%s]", pass_old)); if (retval != PAM_SUCCESS) { _log_err(LOG_NOTICE, pamh, "user not authenticated"); #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } retval = _unix_verify_shadow(user, ctrl); if (retval != PAM_SUCCESS) { _log_err(LOG_NOTICE, pamh, "user not authenticated 2"); #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } D(("get new password now")); lctrl = ctrl; if (on(UNIX_USE_AUTHTOK, lctrl)) { set(UNIX_USE_FIRST_PASS, lctrl); } retry = 0; retval = PAM_AUTHTOK_ERR; while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { /* * use_authtok is to force the use of a previously entered * password -- needed for pluggable password strength checking */ retval = _unix_read_password(pamh, lctrl ,NULL ,"Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained"); } pass_old = NULL; /* tidy up */ #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } D(("returned to _unix_chauthtok")); /* * At this point we know who the user is and what they * propose as their new password. Verify that the new * password is acceptable. */ if (pass_new[0] == '\0') { /* "\0" password = NULL */ pass_new = NULL; } retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new); } if (retval != PAM_SUCCESS) { _log_err(LOG_NOTICE, pamh, "new password not acceptable"); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_new = pass_old = NULL; /* tidy up */ #ifdef USE_LCKPWDF ulckpwdf(); #endif return retval; } /* * By reaching here we have approved the passwords and must now * rebuild the password database file. */ /* * First we encrypt the new password. */ if (on(UNIX_MD5_PASS, ctrl)) { tpass = crypt_md5_wrapper(pass_new); } else { /* * Salt manipulation is stolen from Rick Faith's passwd * program. Sorry Rick :) -- alex */ time_t tm; char salt[3]; time(&tm); salt[0] = bin_to_ascii(tm & 0x3f); salt[1] = bin_to_ascii((tm >> 6) & 0x3f); salt[2] = '\0'; if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) { /* * to avoid using the _extensions_ of the bigcrypt() * function we truncate the newly entered password */ char *temp = malloc(9); char *e; if (temp == NULL) { _log_err(LOG_CRIT, pamh, "out of memory for password"); _pam_overwrite(pass_new); _pam_overwrite(pass_old); pass_new = pass_old = NULL; /* tidy up */ #ifdef USE_LCKPWDF ulckpwdf(); #endif return PAM_BUF_ERR; } /* copy first 8 bytes of password */ strncpy(temp, pass_new, 8); temp[8] = '\0'; /* no longer need cleartext */ e = bigcrypt(temp, salt); tpass = x_strdup(e); _pam_overwrite(e); _pam_delete(temp); /* tidy up */ } else { char *e; /* no longer need cleartext */ e = bigcrypt(pass_new, salt); tpass = x_strdup(e); _pam_overwrite(e); } } D(("password processed")); /* update the password database(s) -- race conditions..? */ retval = _do_setpass(pamh, user, pass_old, tpass, ctrl, remember); _pam_overwrite(pass_new); _pam_overwrite(pass_old); _pam_delete(tpass); pass_old = pass_new = NULL; } else { /* something has broken with the module */
int verify_pwd_hash(const char *p, char *hash, unsigned int nullok) { size_t hash_len; char *pp = NULL; int retval; D(("called")); strip_hpux_aging(hash); hash_len = strlen(hash); if (!hash_len) { /* the stored password is NULL */ if (nullok) { /* this means we've succeeded */ D(("user has empty password - access granted")); retval = PAM_SUCCESS; } else { D(("user has empty password - access denied")); retval = PAM_AUTH_ERR; } } else if (!p || *hash == '*' || *hash == '!') { retval = PAM_AUTH_ERR; } else { if (!strncmp(hash, "$1$", 3)) { pp = Goodcrypt_md5(p, hash); if (pp && strcmp(pp, hash) != 0) { _pam_delete(pp); pp = Brokencrypt_md5(p, hash); } } else if (*hash != '$' && hash_len >= 13) { pp = bigcrypt(p, hash); if (pp && hash_len == 13 && strlen(pp) > hash_len) { _pam_overwrite(pp + hash_len); } } else { /* * Ok, we don't know the crypt algorithm, but maybe * libcrypt knows about it? We should try it. */ #ifdef HAVE_CRYPT_R struct crypt_data *cdata; cdata = malloc(sizeof(*cdata)); if (cdata != NULL) { cdata->initialized = 0; pp = x_strdup(crypt_r(p, hash, cdata)); memset(cdata, '\0', sizeof(*cdata)); free(cdata); } #else pp = x_strdup(crypt(p, hash)); #endif } p = NULL; /* no longer needed here */ /* the moment of truth -- do we agree with the password? */ D(("comparing state of pp[%s] and hash[%s]", pp, hash)); if (pp && strcmp(pp, hash) == 0) { retval = PAM_SUCCESS; } else { retval = PAM_AUTH_ERR; } } if (pp) _pam_delete(pp); D(("done [%d].", retval)); return retval; }
PAMH_ARG_DECL(char * create_password_hash, const char *password, unsigned int ctrl, int rounds) { const char *algoid; char salt[64]; /* contains rounds number + max 16 bytes of salt + algo id */ char *sp; if (on(UNIX_MD5_PASS, ctrl)) { /* algoid = "$1" */ return crypt_md5_wrapper(password); } else if (on(UNIX_BLOWFISH_PASS, ctrl)) { algoid = "$2a$"; } else if (on(UNIX_SHA256_PASS, ctrl)) { algoid = "$5$"; } else if (on(UNIX_SHA512_PASS, ctrl)) { algoid = "$6$"; } else { /* must be crypt/bigcrypt */ char tmppass[9]; char *crypted; crypt_make_salt(salt, 2); if (off(UNIX_BIGCRYPT, ctrl) && strlen(password) > 8) { strncpy(tmppass, password, sizeof(tmppass)-1); tmppass[sizeof(tmppass)-1] = '\0'; password = tmppass; } crypted = bigcrypt(password, salt); memset(tmppass, '\0', sizeof(tmppass)); password = NULL; return crypted; } #ifdef HAVE_CRYPT_GENSALT_R if (on(UNIX_BLOWFISH_PASS, ctrl)) { char entropy[17]; crypt_make_salt(entropy, sizeof(entropy) - 1); sp = crypt_gensalt_r (algoid, rounds, entropy, sizeof(entropy), salt, sizeof(salt)); } else { #endif sp = stpcpy(salt, algoid); if (on(UNIX_ALGO_ROUNDS, ctrl)) { sp += snprintf(sp, sizeof(salt) - 3, "rounds=%u$", rounds); } crypt_make_salt(sp, 8); /* For now be conservative so the resulting hashes * are not too long. 8 bytes of salt prevents dictionary * attacks well enough. */ #ifdef HAVE_CRYPT_GENSALT_R } #endif sp = crypt(password, salt); if (strncmp(algoid, sp, strlen(algoid)) != 0) { /* libxcrypt/libc doesn't know the algorithm, use MD5 */ pam_syslog(pamh, LOG_ERR, "Algo %s not supported by the crypto backend, " "falling back to MD5\n", on(UNIX_BLOWFISH_PASS, ctrl) ? "blowfish" : on(UNIX_SHA256_PASS, ctrl) ? "sha256" : on(UNIX_SHA512_PASS, ctrl) ? "sha512" : algoid); memset(sp, '\0', strlen(sp)); return crypt_md5_wrapper(password); } return x_strdup(sp); }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int i; const char *name; char const * password; char const * pwdfilename = NULL; char const * stored_crypted_password = NULL; char const * crypted_password; FILE *pwdfile; int use_flock = 0; int use_delay = 1; int legacy_crypt = 0; int debug = 0; char * linebuf = NULL; size_t linebuflen; #ifdef USE_CRYPT_R struct crypt_data crypt_buf; #endif /* we require the pwdfile switch and argument to be present, else we don't work */ for (i = 0; i < argc; ++i) { if (!strcmp(argv[i], "pwdfile") && i + 1 < argc) pwdfilename = argv[++i]; else if (!strncmp(argv[i], "pwdfile=", strlen("pwdfile="))) pwdfilename = argv[i] + strlen("pwdfile="); else if (!strcmp(argv[i], "flock")) use_flock = 1; else if (!strcmp(argv[i], "noflock")) use_flock = 0; else if (!strcmp(argv[i], "nodelay")) use_delay = 0; else if (!strcmp(argv[i], "debug")) debug = 1; else if (!strcmp(argv[i], "legacy_crypt")) legacy_crypt = 1; } #ifdef HAVE_PAM_FAIL_DELAY if (use_delay) { if (debug) pam_syslog(pamh, LOG_DEBUG, "setting fail delay"); (void) pam_fail_delay(pamh, 2000000); /* 2 sec */ } #endif if (!pwdfilename) { pam_syslog(pamh, LOG_ERR, "password file name not specified"); return PAM_AUTHINFO_UNAVAIL; } if (pam_get_user(pamh, &name, NULL) != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "couldn't get username from PAM stack"); return PAM_AUTH_ERR; } if (debug) pam_syslog(pamh, LOG_DEBUG, "username is %s", name); if (!(pwdfile = fopen(pwdfilename, "r"))) { pam_syslog(pamh, LOG_ALERT, "couldn't open password file %s", pwdfilename); return PAM_AUTHINFO_UNAVAIL; } if (use_flock && lock_fd(fileno(pwdfile)) == -1) { pam_syslog(pamh, LOG_ALERT, "couldn't lock password file %s", pwdfilename); fclose(pwdfile); return PAM_AUTHINFO_UNAVAIL; } /* get the crypted password corresponding to this user out of pwdfile */ while (getline(&linebuf, &linebuflen, pwdfile) > 0) { /* strsep changes its argument, make a copy */ char * nexttok = linebuf; /* first field: username */ char * curtok = strsep(&nexttok, ":"); /* skip non-matching usernames */ if (strcmp(curtok, name)) continue; /* second field: password (until next colon or newline) */ if ((curtok = strsep(&nexttok, ":\n"))) { stored_crypted_password = curtok; break; } } fclose(pwdfile); /* we keep linebuf (allocated by getline), stored_crypted_password is pointing into it */ if (!stored_crypted_password) if (debug) pam_syslog(pamh, LOG_ERR, "user not found in password database"); if (stored_crypted_password && !strlen(stored_crypted_password)) { if (debug) pam_syslog(pamh, LOG_DEBUG, "user has empty password field"); free(linebuf); return flags & PAM_DISALLOW_NULL_AUTHTOK ? PAM_AUTH_ERR : PAM_SUCCESS; } if (pam_get_authtok(pamh, PAM_AUTHTOK, &password, NULL) != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "couldn't get password from PAM stack"); free(linebuf); return PAM_AUTH_ERR; } if (!stored_crypted_password) { free(linebuf); return PAM_USER_UNKNOWN; } if (debug) pam_syslog(pamh, LOG_DEBUG, "got crypted password == '%s'", stored_crypted_password); #ifdef USE_CRYPT_R crypt_buf.initialized = 0; if (!(crypted_password = crypt_r(password, stored_crypted_password, &crypt_buf))) #else if (!(crypted_password = crypt(password, stored_crypted_password))) #endif { pam_syslog(pamh, LOG_ERR, "crypt() failed"); free(linebuf); return PAM_AUTH_ERR; } if (legacy_crypt && strcmp(crypted_password, stored_crypted_password)) { if (!strncmp(stored_crypted_password, "$1$", 3)) crypted_password = Brokencrypt_md5(password, stored_crypted_password); else crypted_password = bigcrypt(password, stored_crypted_password); } if (strcmp(crypted_password, stored_crypted_password)) { pam_syslog(pamh, LOG_NOTICE, "wrong password for user %s", name); free(linebuf); return PAM_AUTH_ERR; } if (debug) pam_syslog(pamh, LOG_DEBUG, "passwords match"); free(linebuf); return PAM_SUCCESS; }
static int _unix_verify_password(const char *name, const char *p, int opt) { struct passwd *pwd = NULL; struct spwd *spwdent = NULL; char *salt = NULL; char *pp = NULL; int retval = UNIX_FAILED; /* UNIX passwords area */ setpwent(); pwd = getpwnam(name); /* Get password file entry... */ endpwent(); if (pwd != NULL) { if (strcmp(pwd->pw_passwd, "x") == 0) { /* * ...and shadow password file entry for this user, * if shadowing is enabled */ setspent(); spwdent = getspnam(name); endspent(); if (spwdent != NULL) salt = x_strdup(spwdent->sp_pwdp); else pwd = NULL; } else { if (strcmp(pwd->pw_passwd, "*NP*") == 0) { /* NIS+ */ uid_t save_uid; save_uid = geteuid(); seteuid(pwd->pw_uid); spwdent = getspnam(name); seteuid(save_uid); salt = x_strdup(spwdent->sp_pwdp); } else { salt = x_strdup(pwd->pw_passwd); } } } if (pwd == NULL || salt == NULL) { _log_err(LOG_ALERT, "check pass; user unknown"); p = NULL; return retval; } if (strlen(salt) == 0) return (opt == 0) ? UNIX_FAILED : UNIX_PASSED; /* the moment of truth -- do we agree with the password? */ retval = UNIX_FAILED; if (!strncmp(salt, "$1$", 3)) { pp = Goodcrypt_md5(p, salt); if (strcmp(pp, salt) == 0) { retval = UNIX_PASSED; } else { pp = Brokencrypt_md5(p, salt); if (strcmp(pp, salt) == 0) retval = UNIX_PASSED; } } else { pp = bigcrypt(p, salt); if (strcmp(pp, salt) == 0) { retval = UNIX_PASSED; } } p = NULL; /* no longer needed here */ /* clean up */ { char *tp = pp; if (pp != NULL) { while (tp && *tp) *tp++ = '\0'; } pp = tp = NULL; } return retval; }
/* expected hook for auth service */ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { int retval, pcnt, pwdfilename_found; const char *name; char *password; char pwdfilename[PWDFN_LEN]; char salt[12], stored_crypted_password[CRYPTED_BCPWD_LEN+1]; char *crypted_password; FILE *pwdfile; int use_flock = 0; int use_delay = 1; int temp_result = 0; /* we require the pwdfile switch and argument to be present, else we don't work */ /* pcnt is the parameter counter variable for iterating through argv */ pcnt = pwdfilename_found = 0; do { /* see if the current parameter looks like "pwdfile" */ if (strcmp(argv[pcnt],PWDF_PARAM)==0) { /* if argv is long enough, grab the subsequent parameter */ if (pcnt+1 < argc) { /* make sure we can't overflow */ strncpy(pwdfilename,argv[++pcnt],PWDFN_LEN); /* indicate that we've found it */ pwdfilename_found = 1; } /* also check for "pwdfile=blah" */ } else if (strncmp(argv[pcnt],PWDF_PARAM "=",sizeof(PWDF_PARAM "=")-1)==0) { /* make sure we can't overflow */ strncpy(pwdfilename,argv[pcnt]+sizeof(PWDF_PARAM),PWDFN_LEN); /* indicate that we've found it */ pwdfilename_found = 1; } else if (strcmp(argv[pcnt],FLOCK_PARAM)==0) { /* we have a "flock" parameter */ use_flock = 1; } else if (strcmp(argv[pcnt],"no" FLOCK_PARAM)==0) { /* or a "noflock" parameter */ use_flock = 0; } else if (strcmp(argv[pcnt],NODELAY_PARAM)==0) { /* no delay on authentication failure */ use_delay = 0; } } while (++pcnt < argc); #ifdef HAVE_PAM_FAIL_DELAY if (use_delay) { D(("setting delay")); (void) pam_fail_delay(pamh, 2000000); /* 2 sec delay for on failure */ } #endif /* for some or other reason, the password file wasn't specified */ if (!pwdfilename_found) { _pam_log(LOG_ERR,"password file name not specified"); return PAM_AUTHINFO_UNAVAIL; } /* DEBUG */ D(_pam_log(LOG_ERR, "password filename extracted")); /* now try to open the password file */ if ((pwdfile=fopen(pwdfilename,"r"))==NULL) { _pam_log(LOG_ERR,"couldn't open password file %s",pwdfilename); return PAM_AUTHINFO_UNAVAIL; } /* set a lock on the password file */ if (use_flock && lock_fd(fileno(pwdfile)) == -1) { _pam_log(LOG_ERR,"couldn't lock password file %s",pwdfilename); return PAM_AUTHINFO_UNAVAIL; } /* get user name */ if ((retval = pam_get_user(pamh,&name,"login: "******"username not found"); fclose(pwdfile); return retval; } /* DEBUG */ D(_pam_log(LOG_ERR,"username is %s", name)); /* get password - code from pam_unix_auth.c */ pam_get_item(pamh, PAM_AUTHTOK, (void *)&password); if (!password) { retval = _set_auth_tok(pamh, flags, argc, argv); if (retval!=PAM_SUCCESS) { fclose(pwdfile); return retval; } } pam_get_item(pamh, PAM_AUTHTOK, (void *)&password); if ((retval = pam_get_item(pamh, PAM_AUTHTOK, (void *)&password)) != PAM_SUCCESS) { _pam_log(LOG_ERR, "auth token not found"); fclose(pwdfile); return retval; } /* DEBUG */ D(_pam_log(LOG_ERR,"got password from user", password)); /* now crypt password and compare to the user entry in the password file */ /* first make sure password is long enough -- may I do this? */ if (strlen(password)<2 || password==NULL) { _pam_log(LOG_ERR,"password too short or NULL"); fclose(pwdfile); return PAM_AUTH_ERR; } /* get the crypted password corresponding to this user */ if (!fgetpwnam(pwdfile, name, stored_crypted_password)) { _pam_log(LOG_ERR,"user not found in password database"); fclose(pwdfile); return PAM_AUTHINFO_UNAVAIL; } /* DEBUG */ D(_pam_log(LOG_ERR,"got crypted password == '%s'", stored_crypted_password)); temp_result = 0; /* Extract the salt and set the passwd length, depending on MD5 or DES */ if (strncmp(stored_crypted_password, "$1$", 3) == 0) { D(_pam_log(LOG_ERR,"password hash type is 'md5'")); /* get out the salt into "salt" */ strncpy(salt, stored_crypted_password, 11); salt[11] = '\0'; stored_crypted_password[CRYPTED_MD5PWD_LEN] = '\0'; /* try both md5 crypts */ crypted_password = Goodcrypt_md5(password, salt); if (strcmp(crypted_password, stored_crypted_password) == 0) { temp_result = 1; } else { crypted_password = Brokencrypt_md5(password, salt); if (strcmp(crypted_password, stored_crypted_password) == 0) { temp_result = 1; } } } else { /* get the salt out into "salt" */ strncpy(salt, stored_crypted_password, 2); salt[2] = '\0'; stored_crypted_password[CRYPTED_BCPWD_LEN] = '\0'; if (strlen(stored_crypted_password) <= CRYPTED_DESPWD_LEN) { D(_pam_log(LOG_ERR,"password hash type is 'crypt'")); crypted_password = crypt(password, salt); } else { D(_pam_log(LOG_ERR,"password hash type is 'bigcrypt'")); crypted_password = bigcrypt(password, salt); } if (strcmp(crypted_password, stored_crypted_password) == 0) { temp_result = 1; } } /* DEBUG */ D(_pam_log(LOG_ERR,"user password crypted is '%s'", crypted_password)); /* if things don't match up, complain */ if (!temp_result) { _pam_log(LOG_ERR,"wrong password for user %s",name); fclose(pwdfile); return PAM_AUTH_ERR; } /* DEBUG */ D(_pam_log(LOG_ERR,"passwords match")); /* we've gotten here, i.e. authentication was sucessful! */ fclose(pwdfile); return PAM_SUCCESS; }
/**************************************************************************** core of password checking routine ****************************************************************************/ static NTSTATUS password_check(const char *password) { #ifdef WITH_PAM return smb_pam_passcheck(this_user, password); #else BOOL ret; #ifdef WITH_AFS if (afs_auth(this_user, password)) return NT_STATUS_OK; #endif /* WITH_AFS */ #ifdef WITH_DFS if (dfs_auth(this_user, password)) return NT_STATUS_OK; #endif /* WITH_DFS */ #ifdef OSF1_ENH_SEC ret = (strcmp(osf1_bigcrypt(password, this_salt), this_crypted) == 0); if (!ret) { DEBUG(2, ("OSF1_ENH_SEC failed. Trying normal crypt.\n")); ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0); } if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* OSF1_ENH_SEC */ #ifdef ULTRIX_AUTH ret = (strcmp((char *)crypt16(password, this_salt), this_crypted) == 0); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* ULTRIX_AUTH */ #ifdef LINUX_BIGCRYPT ret = (linux_bigcrypt(password, this_salt, this_crypted)); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* LINUX_BIGCRYPT */ #if defined(HAVE_BIGCRYPT) && defined(HAVE_CRYPT) && defined(USE_BOTH_CRYPT_CALLS) /* * Some systems have bigcrypt in the C library but might not * actually use it for the password hashes (HPUX 10.20) is * a noteable example. So we try bigcrypt first, followed * by crypt. */ if (strcmp(bigcrypt(password, this_salt), this_crypted) == 0) return NT_STATUS_OK; else ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #else /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ #ifdef HAVE_BIGCRYPT ret = (strcmp(bigcrypt(password, this_salt), this_crypted) == 0); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* HAVE_BIGCRYPT */ #ifndef HAVE_CRYPT DEBUG(1, ("Warning - no crypt available\n")); return NT_STATUS_LOGON_FAILURE; #else /* HAVE_CRYPT */ ret = (strcmp((char *)crypt(password, this_salt), this_crypted) == 0); if (ret) { return NT_STATUS_OK; } else { return NT_STATUS_WRONG_PASSWORD; } #endif /* HAVE_CRYPT */ #endif /* HAVE_BIGCRYPT && HAVE_CRYPT && USE_BOTH_CRYPT_CALLS */ #endif /* WITH_PAM */ }
/* Returns TRUE if login is allowed with the given local password. */ #ifdef HAVE_SIA Boolean ssh_user_validate_local_password(SshUser uc, const char *password, const char *remote_host) #else /* HAVE_SIA */ Boolean ssh_user_validate_local_password(SshUser uc, const char *password) #endif /* HAVE_SIA */ { char *encrypted_password; const char *correct_passwd = uc->correct_encrypted_passwd; #ifdef HAVE_ULTRIX_SHADOW_PASSWORDS { struct svcinfo *svp; struct passwd *pw; pw = getpwnam(uc->name); if (!pw) return FALSE; svp = getsvc(); if (svp == NULL) { error("getsvc() failed in ultrix code in auth_passwd"); return FALSE; } if ((svp->svcauth.seclevel == SEC_UPGRADE && strcmp(pw->pw_passwd, "*") == 0) || svp->svcauth.seclevel == SEC_ENHANCED) return authenticate_user(pw, password, "/dev/ttypXX") >= 0; } #endif /* HAVE_ULTRIX_SHADOW_PASSWORDS */ #ifdef HAVE_SIA { int argc; char **argv; /* Passing a collection routine to my_sia_validate_user() here would be useless and could be harmful. It would be useless because at this point, stdin/stdout/stderr are all redirected to /dev/null. It would be harmful if the collection routine tried to print anything to stdout, say, a warning that the password is incorrect. At this point, nothing has been printed to stdout yet and it's redirected to /dev/null. Printing to stdout now would initialize it as fully buffered (not line buffered) since /dev/null isn't a tty. That would cause problems later on in the child, which gets a copy of the stdout structure. When the child printed /etc/motd and the mail notice, the user wouldn't see them because they'd be stuck in the stdout buffer. */ get_sia_args(&argc, &argv); if (my_sia_validate_user(NULL, argc, argv, (char *)remote_host, uc->name, NULL, 0, NULL, (char *)password) == SIASUCCESS) return TRUE; else return FALSE; } #endif /* HAVE_SIA */ /* Encrypt the candidate password using the proper salt. */ #if defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH) encrypted_password = bigcrypt(password, (correct_passwd[0] && correct_passwd[1]) ? correct_passwd : "xx"); #else /* defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH) */ encrypted_password = crypt(password, (correct_passwd[0] && correct_passwd[1]) ? correct_passwd : "xx"); #endif /* HAVE_SCO_ETC_SHADOW */ /* Authentication is accepted if the encrypted passwords are identical. */ return strcmp(encrypted_password, correct_passwd) == 0; }