/**************************************************************************** update the enhanced security database. Only relevant for OSF1 at the moment. ****************************************************************************/ static void update_protected_database( char *user, BOOL result) { #ifdef OSF1_ENH_SEC struct pr_passwd *mypasswd; time_t starttime; mypasswd = getprpwnam (user); starttime = time (NULL); if (result) { mypasswd->ufld.fd_slogin = starttime; mypasswd->ufld.fd_nlogins = 0; putprpwnam(user,mypasswd); DEBUG(3,("Update protected database for Account %s after succesful connection\n",user)); } else { mypasswd->ufld.fd_ulogin = starttime; mypasswd->ufld.fd_nlogins = mypasswd->ufld.fd_nlogins + 1; if ( mypasswd->ufld.fd_max_tries != 0 && mypasswd->ufld.fd_nlogins > mypasswd->ufld.fd_max_tries ) { mypasswd->uflg.fg_lock = 0; DEBUG(3,("Account is disabled -- see Account Administrator.\n")); } putprpwnam ( user , mypasswd ); DEBUG(3,("Update protected database for Account %s after refusing connection\n",user)); } #else DEBUG(6,("Updated database with %s %s\n",user,BOOLSTR(result))); #endif }
char * shadow_pw(struct passwd *pw) { char *pw_password = pw->pw_passwd; # if defined(HAVE_SHADOW_H) && !defined(DISABLE_SHADOW) struct spwd *spw = getspnam(pw->pw_name); if (spw != NULL) pw_password = spw->sp_pwdp; # endif #ifdef USE_LIBIAF return(get_iaf_password(pw)); #endif # if defined(HAVE_GETPWANAM) && !defined(DISABLE_SHADOW) struct passwd_adjunct *spw; if (issecure() && (spw = getpwanam(pw->pw_name)) != NULL) pw_password = spw->pwa_passwd; # elif defined(HAVE_SECUREWARE) struct pr_passwd *spw = getprpwnam(pw->pw_name); if (spw != NULL) pw_password = spw->ufld.fd_encrypt; # endif return pw_password; }
/* * Checks password expiry for platforms that use shadow passwd files. * Returns: 1 = password expired, 0 = password not expired */ int auth_shadow_pwexpired(Authctxt *ctxt) { struct spwd *spw = NULL; const char *user = ctxt->pw->pw_name; char buf[256]; time_t today; int daysleft, disabled = 0; if ((spw = getspnam((char *)user)) == NULL) { error("Could not get shadow information for %.100s", user); return 0; } today = time(NULL) / DAY; debug3("%s: today %d sp_lstchg %d sp_max %d", __func__, (int)today, (int)spw->sp_lstchg, (int)spw->sp_max); #if defined(__hpux) && !defined(HAVE_SECUREWARE) if (iscomsec()) { struct pr_passwd *pr; pr = getprpwnam((char *)user); /* Test for Trusted Mode expiry disabled */ if (pr != NULL && pr->ufld.fd_min == 0 && pr->ufld.fd_lifetime == 0 && pr->ufld.fd_expire == 0 && pr->ufld.fd_pw_expire_warning == 0 && pr->ufld.fd_schange != 0) disabled = 1; } #endif /* TODO: check sp_inact */ daysleft = spw->sp_lstchg + spw->sp_max - today; if (disabled) { debug3("password expiration disabled"); } else if (spw->sp_lstchg == 0) { logit("User %.100s password has expired (root forced)", user); return 1; } else if (spw->sp_max == -1) { debug3("password expiration disabled"); } else if (daysleft < 0) { logit("User %.100s password has expired (password aged)", user); return 1; } else if (daysleft <= spw->sp_warn) { debug3("password will expire in %d days", daysleft); snprintf(buf, sizeof(buf), "Your password will expire in %d day%s.\n", daysleft, daysleft == 1 ? "" : "s"); buffer_append(&loginmsg, buf, strlen(buf)); } return 0; }
/**************************************************************************** check if a username/password is OK ****************************************************************************/ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd) { pstring pass2; int level = lp_passwordlevel(); struct passwd *pass; char challenge[8]; BOOL update_encrypted = lp_update_encrypted(); struct smb_passwd *smb_pass; BOOL challenge_done = False; if (password) password[pwlen] = 0; if (pwlen == 24) challenge_done = last_challenge(challenge); #if DEBUG_PASSWORD if (challenge_done) { int i; DEBUG(100,("checking user=[%s] pass=[",user)); for( i = 0; i < 24; i++) DEBUG(100,("%0x ", (unsigned char)password[i])); DEBUG(100,("]\n")); } else { DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password)); } #endif if (!password) return(False); if (((!*password) || (!pwlen)) && !lp_null_passwords()) return(False); if (pwd && !user) { pass = (struct passwd *) pwd; user = pass->pw_name; } else pass = Get_Pwnam(user,True); DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done)); if ((pwlen == 24) && challenge_done) { DEBUG(4,("Checking SMB password for user %s (l=24)\n",user)); if (!pass) { DEBUG(3,("Couldn't find user %s\n",user)); return(False); } /* non-null username indicates search by username not smb userid */ smb_pass = get_smbpwd_entry(user, 0); if (!smb_pass) { DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user)); return(False); } if(smb_pass->acct_ctrl & ACB_DISABLED) { DEBUG(3,("password_ok: account for user %s was disabled.\n", user)); return(False); } /* Ensure the uid's match */ if (smb_pass->smb_userid != pass->pw_uid) { DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n")); return(False); } if (Protocol >= PROTOCOL_NT1) { /* We have the NT MD4 hash challenge available - see if we can use it (ie. does it exist in the smbpasswd file). */ if (smb_pass->smb_nt_passwd != NULL) { DEBUG(4,("Checking NT MD4 password\n")); if (smb_password_check(password, smb_pass->smb_nt_passwd, (unsigned char *)challenge)) { update_protected_database(user,True); return(True); } DEBUG(4,("NT MD4 password check failed\n")); } } /* Try against the lanman password */ if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ )) { /* No password. */ DEBUG(1,("password_ok: User %s has NO PASSWORD !\n", user)); update_protected_database(user,True); return(True); } if ((smb_pass->smb_passwd != NULL) && smb_password_check(password, smb_pass->smb_passwd, (unsigned char *)challenge)) { update_protected_database(user,True); return(True); } DEBUG(3,("Error smb_password_check failed\n")); } DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen)); if (!pass) { DEBUG(3,("Couldn't find user %s\n",user)); return(False); } #ifdef SHADOW_PWD { struct spwd *spass; /* many shadow systems require you to be root to get the password, in most cases this should already be the case when this function is called, except perhaps for IPC password changing requests */ spass = getspnam(pass->pw_name); if (spass && spass->sp_pwdp) pass->pw_passwd = spass->sp_pwdp; } #elif defined(IA_UINFO) { /* Need to get password with SVR4.2's ia_ functions instead of get{sp,pw}ent functions. Required by UnixWare 2.x, tested on version 2.1. ([email protected]) */ uinfo_t uinfo; if (ia_openinfo(pass->pw_name, &uinfo) != -1) ia_get_logpwd(uinfo, &(pass->pw_passwd)); } #endif #ifdef SecureWare { struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); if (pr_pw && pr_pw->ufld.fd_encrypt) pass->pw_passwd = pr_pw->ufld.fd_encrypt; } #endif #ifdef HPUX_10_TRUSTED { struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); if (pr_pw && pr_pw->ufld.fd_encrypt) pass->pw_passwd = pr_pw->ufld.fd_encrypt; } #endif #ifdef OSF1_ENH_SEC { struct pr_passwd *mypasswd; DEBUG(5,("Checking password for user %s in OSF1_ENH_SEC\n",user)); mypasswd = getprpwnam (user); if ( mypasswd ) { pstrcpy(pass->pw_name,mypasswd->ufld.fd_name); pstrcpy(pass->pw_passwd,mypasswd->ufld.fd_encrypt); } else { DEBUG(5,("No entry for user %s in protected database !\n",user)); return(False); } } #endif #ifdef ULTRIX_AUTH { AUTHORIZATION *ap = getauthuid( pass->pw_uid ); if (ap) { pstrcpy( pass->pw_passwd, ap->a_password ); endauthent(); } } #endif /* extract relevant info */ fstrcpy(this_user,pass->pw_name); fstrcpy(this_salt,pass->pw_passwd); #ifdef HPUX /* The crypt on HPUX won't work with more than 2 salt characters. */ this_salt[2] = 0; #endif /* HPUX */ fstrcpy(this_crypted,pass->pw_passwd); if (!*this_crypted) { if (!lp_null_passwords()) { DEBUG(2,("Disallowing access to %s due to null password\n",this_user)); return(False); } #ifndef PWDAUTH if (!*password) { DEBUG(3,("Allowing access to %s with null password\n",this_user)); return(True); } #endif } /* try it as it came to us */ if (password_check(password)) { update_protected_database(user,True); if (pass && update_encrypted) update_smbpassword_file(pass,password); return(True); } /* if the password was given to us with mixed case then we don't need to proceed as we know it hasn't been case modified by the client */ if (strhasupper(password) && strhaslower(password)) return(False); /* make a copy of it */ StrnCpy(pass2,password,sizeof(pstring)-1); /* try all lowercase */ strlower(password); if (password_check(password)) { update_protected_database(user,True); if (pass && update_encrypted) update_smbpassword_file(pass,password); return(True); } /* give up? */ if (level < 1) { update_protected_database(user,False); /* restore it */ pstrcpy(password,pass2); return(False); } /* last chance - all combinations of up to level chars upper! */ strlower(password); if (string_combinations(password,password_check,level)) { update_protected_database(user,True); if (pass && update_encrypted) update_smbpassword_file(pass,password); return(True); } update_protected_database(user,False); /* restore it */ pstrcpy(password,pass2); return(False); }
static char *_get_pw_info(pool *p, const char *u, time_t *lstchg, time_t *min, time_t *max, time_t *warn, time_t *inact, time_t *expire) { char *cpw = NULL; #if defined(HAVE_GETPRPWENT) || defined(COMSEC) struct pr_passwd *prpw; #endif #if !defined(HAVE_GETPRPWENT) || defined(COMSEC) struct passwd *pw; #endif /* Some platforms (i.e. BSD) provide "transparent" shadowing, which * requires that we are root in order to have the password member * filled in. */ PRIVS_ROOT #if !defined(HAVE_GETPRPWENT) || defined(COMSEC) # ifdef COMSEC if (!iscomsec()) { # endif /* COMSEC */ endpwent(); #if defined(BSDI3) || defined(BSDI4) /* endpwent() seems to be buggy on BSDI3.1 (is this true for 4.0?) * setpassent(0) _seems_ to do the same thing, however this conflicts * with the man page documented behavior. Argh, why do all the bsds * have to be different in this area (except OpenBSD, grin). */ setpassent(0); #else /* BSDI3 || BSDI4 */ setpwent(); #endif /* BSDI3 || BSDI4 */ pw = getpwnam(u); if (pw) { cpw = pstrdup(p, pw->pw_passwd); if (lstchg) *lstchg = (time_t) -1; if (min) *min = (time_t) -1; if (max) *max = (time_t) -1; if (warn) *warn = (time_t) -1; if (inact) *inact = (time_t) -1; if (expire) *expire = (time_t) -1; } endpwent(); #ifdef COMSEC } else { #endif /* COMSEC */ #endif /* !HAVE_GETPRWENT or COMSEC */ #if defined(HAVE_GETPRPWENT) || defined(COMSEC) endprpwent(); setprpwent(); prpw = getprpwnam((char *) u); if (prpw) { cpw = pstrdup(p, prpw->ufld.fd_encrypt); if (lstchg) *lstchg = (time_t) -1; if (min) *min = prpw->ufld.fd_min; if (max) *max = (time_t) -1; if (warn) *warn = (time_t) -1; if (inact) *inact = (time_t) -1; if (expire) *expire = prpw->ufld.fd_expire; } endprpwent(); #ifdef COMSEC } #endif /* COMSEC */ #endif /* HAVE_GETPRPWENT or COMSEC */ PRIVS_RELINQUISH #if defined(BSDI3) || defined(BSDI4) setpassent(1); #endif return cpw; }
NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *password, int pwlen, BOOL (*fn) (const char *, const char *), BOOL run_cracker) { pstring pass2; int level = lp_passwordlevel(); NTSTATUS nt_status; #ifdef DEBUG_PASSWORD DEBUG(100, ("checking user=[%s] pass=[%s]\n", user, password)); #endif if (!password) return NT_STATUS_LOGON_FAILURE; if (((!*password) || (!pwlen)) && !lp_null_passwords()) return NT_STATUS_LOGON_FAILURE; #if defined(WITH_PAM) /* * If we're using PAM we want to short-circuit all the * checks below and dive straight into the PAM code. */ fstrcpy(this_user, user); DEBUG(4, ("pass_check: Checking (PAM) password for user %s (l=%d)\n", user, pwlen)); #else /* Not using PAM */ DEBUG(4, ("pass_check: Checking password for user %s (l=%d)\n", user, pwlen)); if (!pass) { DEBUG(3, ("Couldn't find user %s\n", user)); return NT_STATUS_NO_SUCH_USER; } /* Copy into global for the convenience of looping code */ /* Also the place to keep the 'password' no matter what crazy struct it started in... */ fstrcpy(this_crypted, pass->pw_passwd); fstrcpy(this_salt, pass->pw_passwd); #ifdef HAVE_GETSPNAM { struct spwd *spass; /* many shadow systems require you to be root to get the password, in most cases this should already be the case when this function is called, except perhaps for IPC password changing requests */ spass = getspnam(pass->pw_name); if (spass && spass->sp_pwdp) { fstrcpy(this_crypted, spass->sp_pwdp); fstrcpy(this_salt, spass->sp_pwdp); } } #elif defined(IA_UINFO) { /* Need to get password with SVR4.2's ia_ functions instead of get{sp,pw}ent functions. Required by UnixWare 2.x, tested on version 2.1. ([email protected]) */ uinfo_t uinfo; if (ia_openinfo(pass->pw_name, &uinfo) != -1) ia_get_logpwd(uinfo, &(pass->pw_passwd)); } #endif #ifdef HAVE_GETPRPWNAM { struct pr_passwd *pr_pw = getprpwnam(pass->pw_name); if (pr_pw && pr_pw->ufld.fd_encrypt) fstrcpy(this_crypted, pr_pw->ufld.fd_encrypt); } #endif #ifdef HAVE_GETPWANAM { struct passwd_adjunct *pwret; pwret = getpwanam(s); if (pwret && pwret->pwa_passwd) fstrcpy(this_crypted, pwret->pwa_passwd); } #endif #ifdef OSF1_ENH_SEC { struct pr_passwd *mypasswd; DEBUG(5, ("Checking password for user %s in OSF1_ENH_SEC\n", user)); mypasswd = getprpwnam(user); if (mypasswd) { fstrcpy(this_user, mypasswd->ufld.fd_name); fstrcpy(this_crypted, mypasswd->ufld.fd_encrypt); } else { DEBUG(5, ("OSF1_ENH_SEC: No entry for user %s in protected database !\n", user)); } } #endif #ifdef ULTRIX_AUTH { AUTHORIZATION *ap = getauthuid(pass->pw_uid); if (ap) { fstrcpy(this_crypted, ap->a_password); endauthent(); } } #endif #if defined(HAVE_TRUNCATED_SALT) /* crypt on some platforms (HPUX in particular) won't work with more than 2 salt characters. */ this_salt[2] = 0; #endif if (!*this_crypted) { if (!lp_null_passwords()) { DEBUG(2, ("Disallowing %s with null password\n", this_user)); return NT_STATUS_LOGON_FAILURE; } if (!*password) { DEBUG(3, ("Allowing access to %s with null password\n", this_user)); return NT_STATUS_OK; } } #endif /* defined(WITH_PAM) */ /* try it as it came to us */ nt_status = password_check(password); if NT_STATUS_IS_OK(nt_status) { if (fn) { fn(user, password); } return (nt_status); } else if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD)) {
/* As above, but uses struct passwd. This function does all the work. */ SshUser ssh_user_initialize_with_pw(struct passwd *pw, Boolean privileged) { SshUser uc; char correct_passwd[200]; if (!pw) return NULL; uc = ssh_xcalloc(1, sizeof(*uc)); uc->name = ssh_xstrdup(pw->pw_name); uc->dir = ssh_xstrdup(pw->pw_dir); uc->uid = pw->pw_uid; uc->gid = pw->pw_gid; if (strcmp(pw->pw_shell, "") == 0) { uc->shell = ssh_xstrdup("/bin/sh"); } else { uc->shell = ssh_xstrdup(pw->pw_shell); } if (privileged) { /* Save the encrypted password. */ strncpy(correct_passwd, pw->pw_passwd, sizeof(correct_passwd)); #ifdef HAVE_SIA /* pr->pw_passwd may not be the real encrypted password (it won't be under Enhanced Security), but we don't care because we never look at uc->correct_encrypted_passwd. We let my_sia_validate_user() do all the work instead. */ #else /* HAVE_SIA */ /* If we have shadow passwords, lookup the real encrypted password from the shadow file, and replace the saved encrypted password with the real encrypted password. */ #if defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH) { struct pr_passwd *pr = getprpwnam(ssh_user_name(uc)); pr = getprpwnam(ssh_user_name(uc)); if (pr) strncpy(correct_passwd, pr->ufld.fd_encrypt, sizeof(correct_passwd)); endprpwent(); } #else /* defined(HAVE_SCO_ETC_SHADOW) || defined(HAVE_HPUX_TCB_AUTH) */ #ifdef HAVE_ETC_SHADOW { struct spwd *sp = getspnam(ssh_user_name(uc)); #if defined(SECURE_RPC) && defined(NIS_PLUS) if (geteuid() == UID_ROOT && ssh_user_uid(uc) != UID_ROOT && (!sp || !sp->sp_pwdp || !strcmp(sp->sp_pwdp,"*NP*"))) if (seteuid(ssh_user_uid(uc)) >= 0) { sp = getspnam(ssh_user_name(uc)); /* retry as user */ seteuid(UID_ROOT); } #endif /* SECURE_RPC && NIS_PLUS */ if (sp) strncpy(correct_passwd, sp->sp_pwdp, sizeof(correct_passwd)); endspent(); } #else /* HAVE_ETC_SHADOW */ #ifdef HAVE_ETC_SECURITY_PASSWD_ADJUNCT { struct passwd_adjunct *sp = getpwanam(ssh_user_name(uc)); if (sp) strncpy(correct_passwd, sp->pwa_passwd, sizeof(correct_passwd)); endpwaent(); } #else /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */ #ifdef HAVE_ETC_SECURITY_PASSWD /* AIX, at least. Is there an easier way? */ { FILE *f; char line[1024], looking_for_user[200], *cp; int found_user = 0; f = fopen("/etc/security/passwd", "r"); if (f) { /* XXX: user next line was server_user, is this OK? */ snprintf(looking_for_user, sizeof(looking_for_user), "%.190s:", user); while (fgets(line, sizeof(line), f)) { if (strchr(line, '\n')) *strchr(line, '\n') = 0; if (strcmp(line, looking_for_user) == 0) found_user = 1; else if (line[0] != '\t' && line[0] != ' ') found_user = 0; else if (found_user) { for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (strncmp(cp, "password = "******"password = "******"password = "), sizeof(correct_passwd)); correct_passwd[sizeof(correct_passwd) - 1] = 0; break; } } } fclose(f); } } #endif /* HAVE_ETC_SECURITY_PASSWD */ #endif /* HAVE_ETC_SECURITY_PASSWD_ADJUNCT */ #endif /* HAVE_ETC_SHADOW */ #endif /* HAVE_SCO_ETC_SHADOW */ #endif /* HAVE_SIA */ uc->correct_encrypted_passwd = ssh_xstrdup(correct_passwd); uc->login_allowed = ssh_login_permitted(uc->name, uc); } else /* !privileged */ { uc->correct_encrypted_passwd = NULL; uc->login_allowed = TRUE; uc->password_needs_change = FALSE; } /* XXX should check password expirations (some systems already do this in ssh_login_permitted). */ return uc; }