/* * If we have setauthdb, retrieve the password registry for the user's * account then feed it to setauthdb. This may load registry-specific method * code. If we don't have setauthdb or have already called it this is a no-op. */ void aix_setauthdb(const char *user) { # ifdef HAVE_SETAUTHDB static char *registry = NULL; if (registry != NULL) /* have already done setauthdb */ return; if (setuserdb(S_READ) == -1) { debug3("%s: Could not open userdb to read", __func__); return; } if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { if (setauthdb(registry, NULL) == 0) debug3("%s: AIX/setauthdb set registry %s", __func__, registry); else debug3("%s: AIX/setauthdb set registry %s failed: %s", __func__, registry, strerror(errno)); } else debug3("%s: Could not read S_REGISTRY for user: %s", __func__, strerror(errno)); enduserdb(); # endif }
/* * aix_krb5_get_principal_name: returns the user's kerberos client principal name if * configured, otherwise NULL. Caller must free returned string. */ char * aix_krb5_get_principal_name(char *pw_name) { char *authname = NULL, *authdomain = NULL, *principal = NULL; setuserdb(S_READ); if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0) debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno)); if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0) debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno)); if (authdomain != NULL) xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain); else if (authname != NULL) principal = xstrdup(authname); enduserdb(); return principal; }
/* reset the state to the start of the user database */ void setpwent(void) { char *s; endpwent(); /* getuserattr returns a null separated list of users, with each user being of the form REGISTRY:USERNAME */ if (getuserattr("ALL", "users", &s, SEC_CHAR) == 0) { getpwent_state.all_users = s; getpwent_state.next = getpwent_state.all_users; } }
/* * Test specifically for the case where SYSTEM == NONE and AUTH1 contains * anything other than NONE or SYSTEM, which indicates that the admin has * configured the account for purely AUTH1-type authentication. * * Since authenticate() doesn't check AUTH1, and sshd can't sanely support * AUTH1 itself, in such a case authenticate() will allow access without * authentation, which is almost certainly not what the admin intends. * * (The native tools, eg login, will process the AUTH1 list in addition to * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods * have been deprecated since AIX 4.2.x and would be very difficult for sshd * to support. * * Returns 0 if an unsupportable combination is found, 1 otherwise. */ static int aix_valid_authentications(const char *user) { char *auth1, *sys, *p; int valid = 1; if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) { logit("Can't retrieve attribute SYSTEM for %s: %.100s", user, strerror(errno)); return 0; } debug3("AIX SYSTEM attribute %s", sys); if (strcmp(sys, "NONE") != 0) return 1; /* not "NONE", so is OK */ if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) { logit("Can't retrieve attribute auth1 for %s: %.100s", user, strerror(errno)); return 0; } p = auth1; /* A SEC_LIST is concatenated strings, ending with two NULs. */ while (p[0] != '\0' && p[1] != '\0') { debug3("AIX auth1 attribute list member %s", p); if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) { logit("Account %s has unsupported auth1 value '%s'", user, p); valid = 0; } p += strlen(p) + 1; } return (valid); }
/* * If we have setauthdb, retrieve the password registry for the user's * account then feed it to setauthdb. This will mean that subsequent AIX auth * functions will only use the specified loadable module. If we don't have * setauthdb this is a no-op. */ void aix_setauthdb(const char *user) { # ifdef HAVE_SETAUTHDB char *registry; if (setuserdb(S_READ) == -1) { debug3("%s: Could not open userdb to read", __func__); return; } if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { if (setauthdb(registry, old_registry) == 0) debug3("AIX/setauthdb set registry '%s'", registry); else debug3("AIX/setauthdb set registry '%s' failed: %s", registry, strerror(errno)); } else debug3("%s: Could not read S_REGISTRY for user: %s", __func__, strerror(errno)); enduserdb(); # endif /* HAVE_SETAUTHDB */ }
Boolean ssh_login_permitted(const char *user, SshUser uc) { char passwd[20]; /* Only for account lock check */ strncpy(passwd, uc->correct_encrypted_passwd, sizeof(passwd)); passwd[sizeof(passwd) - 1] = '\0'; #ifdef HAVE_USERSEC_H { char *expiration, current_time[100], normalized[100]; int rlogin_permitted; ssh_time t; struct SshCalendarTimeRec tm[1]; int account_is_locked; if (setuserdb(S_READ) < 0) { if (getuid() == 0) /* It's OK to fail here if we are not root */ { SSH_DEBUG(2, ("setuserdb S_READ failed: %.200s.", strerror(errno))); } return FALSE; } if (getuserattr((char *)user, S_RLOGINCHK, &rlogin_permitted, SEC_BOOL) < 0) { if (getuid() == 0) /* It's OK to fail here if we are not root */ { SSH_DEBUG(2, ("getuserattr S_RLOGINCHK failed: %.200s", strerror(errno))); } enduserdb(); return FALSE; } if (getuserattr((char *)user, S_EXPIRATION, &expiration, SEC_CHAR) < 0) { SSH_DEBUG(2, ("getuserattr S_EXPIRATION failed: %.200s.", strerror(errno))); enduserdb(); return FALSE; } #ifdef S_LOCKED if (getuserattr(user, S_LOCKED, &account_is_locked, SEC_BOOL) < 0) { SSH_DEBUG(2, ("getuserattr S_LOCKED failed: %.200s.", strerror(errno))); enduserdb(); return FALSE; } if (account_is_locked) { SSH_DEBUG(2, ("Account %.100s is locked.", user)); enduserdb(); return FALSE; } #endif /* S_LOCKED */ if (!rlogin_permitted) { SSH_DEBUG(2, ("Remote logins to account %.100s not permitted by " "user profile.", user)); enduserdb(); return FALSE; } if (strcmp(expiration, "0") == 0) { /* The account does not expire - return success immediately. */ enduserdb(); return TRUE; } if (strlen(expiration) != 10) { SSH_DEBUG(2, ("Account %.100s expiration date is in wrong format.", user)); enduserdb(); return FALSE; } t = ssh_time(); ssh_calendar_time(t, tm, TRUE); snprintf(current_time, sizeof(current_time), "%04d%02d%02d%02d%02d", tm->year, tm->month + 1, tm->monthday, tm->hour, tm->minute); if (expiration[8] < '7') /* Assume year < 70 is 20YY. */ strcpy(normalized, "20"); else strcpy(normalized, "19"); strcat(normalized, expiration + 8); strcat(normalized, expiration); normalized[12] = '\0'; if (strcmp(normalized, current_time) < 0) { SSH_DEBUG(2, ("Account %.100s has expired - access denied.", user)); enduserdb(); return FALSE; } enduserdb(); } #endif /* HAVE_USERSEC_H */ #ifdef HAVE_ETC_SHADOW { struct spwd *sp; sp = (struct spwd *)getspnam(user); #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(user); /* retry as user */ seteuid(UID_ROOT); } } #endif /* SECURE_RPC && NIS_PLUS */ if (!sp) { /* * Some systems, e.g.: IRIX, may or may not have /etc/shadow. * Just check if there is one. If such system is also an YP * client, then valid password might already be present in passwd * structure. Just check if it's other than "x". Assume that * YP server is always right if this is the case. * [email protected] */ struct stat sbf; if ((stat(SHADOW, &sbf) == 0) && strcmp(uc->correct_encrypted_passwd, "x") == 0) { SSH_DEBUG(2, ("Can't find %.100s's shadow - access denied.", user)); endspent(); return FALSE; } } else { SshTime today = ssh_time()/24/60/60; /* what a day! */ #ifdef HAVE_STRUCT_SPWD_EXPIRE /* Check for expiration date */ if (sp->sp_expire > 0 && today > sp->sp_expire) { SSH_DEBUG(2, ("Account %.100s has expired - access denied.", user)); endspent(); return FALSE; } #endif #ifdef HAVE_STRUCT_SPWD_INACT /* Check for last login */ if (sp->sp_inact > 0) { char buf[64]; SshTime llt; llt = ssh_user_get_last_login_time(uc, buf, sizeof(buf)); if (llt && (today - llt/24/60/60) > sp->sp_inact) { SSH_DEBUG(2, ("Account %.100s was inactive for more than %d days.", user, sp->sp_inact)); endspent(); return FALSE; } } #endif /* Check if password is valid */ if (sp->sp_lstchg == 0 || (sp->sp_max > 0 && today > sp->sp_lstchg + sp->sp_max)) { SSH_DEBUG(2, ("Account %.100s's password is too old - forced to change.", user)); uc->password_needs_change = TRUE; } strncpy(passwd, sp->sp_pwdp, sizeof(passwd)); passwd[sizeof(passwd) - 1] = '\0'; } endspent(); } #endif /* HAVE_ETC_SHADOW */ /* * Check if account is locked. Check if encrypted password starts * with "*LK*". */ { if (strncmp(passwd,"*LK*", 4) == 0) { SSH_DEBUG(2, ("Account %.100s is locked.", user)); return FALSE; } } #ifdef CHECK_ETC_SHELLS { int invalid = 1; char *shell = pwd->pw_shell, *etc_shell, *getusershell(); if (!shell || !*shell) shell = DEFAULT_SHELL; while (invalid && (etc_shell = getusershell())) invalid = strcmp(etc_shell, shell); endusershell(); if (invalid) { SSH_DEBUG(2, ("Account %.100s doesn't have valid shell", user)); return FALSE; } } #endif /* CHECK_ETC_SHELLS */ return TRUE; }