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; }
/* 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; }