/* * Get a password entry by uid and allocate space for it. */ struct passwd * sudo_getpwuid(uid_t uid) { struct cache_item key, *item; struct rbnode *node; debug_decl(sudo_getpwuid, SUDO_DEBUG_NSS) key.k.uid = uid; if ((node = rbfind(pwcache_byuid, &key)) != NULL) { item = (struct cache_item *) node->data; goto done; } /* * Cache passwd db entry if it exists or a negative response if not. */ #ifdef HAVE_SETAUTHDB aix_setauthdb(IDtouser(uid)); #endif item = sudo_make_pwitem(uid, NULL); if (item == NULL) { item = ecalloc(1, sizeof(*item)); item->refcnt = 1; item->k.uid = uid; /* item->d.pw = NULL; */ } if (rbinsert(pwcache_byuid, item) != NULL) fatalx(_("unable to cache uid %u, already exists"), (unsigned int) uid); #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif done: item->refcnt++; debug_return_ptr(item->d.pw); }
/* * Do authentication via AIX's authenticate routine. We loop until the * reenter parameter is 0, but normally authenticate is called only once. * * Note: this function returns 1 on success, whereas AIX's authenticate() * returns 0. */ int sys_auth_passwd(Authctxt *ctxt, const char *password) { char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name; int authsuccess = 0, expired, reenter, result; do { result = authenticate((char *)name, (char *)password, &reenter, &authmsg); aix_remove_embedded_newlines(authmsg); debug3("AIX/authenticate result %d, authmsg %.100s", result, authmsg); } while (reenter); if (!aix_valid_authentications(name)) result = -1; if (result == 0) { authsuccess = 1; /* * Record successful login. We don't have a pty yet, so just * label the line as "ssh" */ aix_setauthdb(name); /* * Check if the user's password is expired. */ expired = passwdexpired(name, &msg); if (msg && *msg) { buffer_append(ctxt->loginmsg, msg, strlen(msg)); aix_remove_embedded_newlines(msg); } debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); switch (expired) { case 0: /* password not expired */ break; case 1: /* expired, password change required */ ctxt->force_pwchange = 1; break; default: /* user can't change(2) or other error (-1) */ logit("Password can't be changed for user %s: %.100s", name, msg); if (msg) xfree(msg); authsuccess = 0; } aix_restoreauthdb(); } if (authmsg != NULL) xfree(authmsg); return authsuccess; }
/* * record_failed_login: generic "login failed" interface function */ void record_failed_login(const char *user, const char *ttyname) { char *hostname = get_canonical_hostname(options.use_dns); if (geteuid() != 0) return; aix_setauthdb(user); # ifdef AIX_LOGINFAILED_4ARG loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH); # else loginfailed((char *)user, hostname, (char *)ttyname); # endif }
/* * record_failed_login: generic "login failed" interface function */ void record_failed_login(const char *user, const char *hostname, const char *ttyname) { if (geteuid() != 0) return; aix_setauthdb(user); # ifdef AIX_LOGINFAILED_4ARG loginfailed((char *)user, (char *)hostname, (char *)ttyname, AUDIT_FAIL_AUTH); # else loginfailed((char *)user, (char *)hostname, (char *)ttyname); # endif aix_restoreauthdb(); }
int sys_auth_record_login(const char *user, const char *host, const char *ttynm) { char *msg; int success = 0; aix_setauthdb(user); if (loginsuccess((char *)user, host, ttynm, &msg) == 0) { success = 1; if (msg != NULL) { debug("AIX/loginsuccess: msg %s", __func__, msg); buffer_append(&loginmsg, msg, strlen(msg)); xfree(msg); } } aix_restoreauthdb(); return (success); }
int sys_auth_record_login(const char *user, const char *host, const char *ttynm, Buffer *loginmsg) { char *msg = NULL; int success = 0; aix_setauthdb(user); if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { success = 1; if (msg != NULL) { debug("AIX/loginsuccess: msg %s", msg); if (lastlogin_msg == NULL) lastlogin_msg = msg; } } aix_restoreauthdb(); return (success); }
int sys_auth_record_login(const char *user, const char *host, const char *ttynm, Buffer *loginmsg) { char *msg = NULL; static int msg_done = 0; int success = 0; aix_setauthdb(user); if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { success = 1; if (msg != NULL && loginmsg != NULL && !msg_done) { debug("AIX/loginsuccess: msg %s", msg); buffer_append(loginmsg, msg, strlen(msg)); xfree(msg); msg_done = 1; } } aix_restoreauthdb(); return (success); }
/* * Get a password entry by name and allocate space for it. */ struct passwd * sudo_getpwnam(const char *name) { struct cache_item key, *item; struct rbnode *node; size_t len; debug_decl(sudo_getpwnam, SUDO_DEBUG_NSS) key.k.name = (char *) name; if ((node = rbfind(pwcache_byname, &key)) != NULL) { item = (struct cache_item *) node->data; goto done; } /* * Cache passwd db entry if it exists or a negative response if not. */ #ifdef HAVE_SETAUTHDB aix_setauthdb((char *) name); #endif if ((key.d.pw = getpwnam(name)) != NULL) { item = make_pwitem(key.d.pw, name); if (rbinsert(pwcache_byname, item) != NULL) errorx(1, _("unable to cache user %s, already exists"), name); } else { len = strlen(name) + 1; item = ecalloc(1, sizeof(*item) + len); item->refcnt = 1; item->k.name = (char *) item + sizeof(*item); memcpy(item->k.name, name, len); /* item->d.pw = NULL; */ if (rbinsert(pwcache_byname, item) != NULL) errorx(1, _("unable to cache user %s, already exists"), name); } #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif done: item->refcnt++; debug_return_ptr(item->d.pw); }
/* * BSD-compatible getgrouplist(3) using getgrset(3) */ int getgrouplist(const char *name, gid_t basegid, gid_t *groups, int *ngroupsp) { char *cp, *grset = NULL; int i, ngroups = 1; int grpsize = *ngroupsp; int rval = -1; gid_t gid; /* We support BSD semantics where the first element is the base gid */ if (grpsize <= 0) return -1; groups[0] = basegid; #ifdef HAVE_SETAUTHDB aix_setauthdb((char *) name); #endif if ((grset = getgrset(name)) != NULL) { const char *errstr; for (cp = strtok(grset, ","); cp != NULL; cp = strtok(NULL, ",")) { gid = atoid(cp, NULL, NULL, &errstr); if (errstr == NULL && gid != basegid) { if (ngroups == grpsize) goto done; groups[ngroups++] = gid; } } } rval = 0; done: free(grset); #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif *ngroupsp = ngroups; return rval; }
/* * Get a password entry by uid and allocate space for it. * Fills in pw_passwd from shadow file if necessary. */ struct passwd * sudo_getpwuid(uid_t uid) { struct cache_item key, *item; struct rbnode *node; key.k.uid = uid; if ((node = rbfind(pwcache_byuid, &key)) != NULL) { item = (struct cache_item *) node->data; goto done; } /* * Cache passwd db entry if it exists or a negative response if not. */ #ifdef HAVE_SETAUTHDB aix_setauthdb(IDtouser(uid)); #endif if ((key.d.pw = getpwuid(uid)) != NULL) { item = make_pwitem(key.d.pw, NULL); if (rbinsert(pwcache_byuid, item) != NULL) errorx(1, "unable to cache uid %u (%s), already exists", (unsigned int) uid, item->d.pw->pw_name); } else { item = emalloc(sizeof(*item)); item->refcnt = 1; item->k.uid = uid; item->d.pw = NULL; if (rbinsert(pwcache_byuid, item) != NULL) errorx(1, "unable to cache uid %u, already exists", (unsigned int) uid); } #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif done: item->refcnt++; return item->d.pw; }
/* Reset user_groups based on passwd entry. */ static void reset_groups(struct passwd *pw) { #if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS) if (pw != sudo_user.pw) { # ifdef HAVE_SETAUTHDB aix_setauthdb(pw->pw_name); # endif if (initgroups(pw->pw_name, pw->pw_gid) == -1) log_error(USE_ERRNO|MSG_ONLY, "can't reset group vector"); efree(user_groups); user_groups = NULL; if ((user_ngroups = getgroups(0, NULL)) > 0) { user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T)); if (getgroups(user_ngroups, user_groups) < 0) log_error(USE_ERRNO|MSG_ONLY, "can't get group vector"); } # ifdef HAVE_SETAUTHDB aix_restoreauthdb(); # endif } #endif }
struct passwd * getpwnamallow(const char *user) { #ifdef HAVE_LOGIN_CAP extern login_cap_t *lc; #ifdef BSD_AUTH auth_session_t *as; #endif #endif struct passwd *pw; parse_server_match_config(&options, user, get_canonical_hostname(options.use_dns), get_remote_ipaddr()); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_setauthdb(user); #endif pw = getpwnam(user); #if defined(_AIX) && defined(HAVE_SETAUTHDB) aix_restoreauthdb(); #endif #ifdef HAVE_CYGWIN /* * Windows usernames are case-insensitive. To avoid later problems * when trying to match the username, the user is only allowed to * login if the username is given in the same case as stored in the * user database. */ if (pw != NULL && strcmp(user, pw->pw_name) != 0) { logit("Login name %.100s does not match stored username %.100s", user, pw->pw_name); pw = NULL; } #endif if (pw == NULL) { logit("Invalid user %.100s from %.100s", user, get_remote_ipaddr()); #ifdef CUSTOM_FAILED_LOGIN record_failed_login(user, get_canonical_hostname(options.use_dns), "ssh"); #endif #ifdef SSH_AUDIT_EVENTS audit_event(SSH_INVALID_USER); #endif /* SSH_AUDIT_EVENTS */ return (NULL); } if (!allowed_user(pw)) return (NULL); #ifdef HAVE_LOGIN_CAP if ((lc = login_getclass(pw->pw_class)) == NULL) { debug("unable to get login class: %s", user); return (NULL); } #ifdef BSD_AUTH if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 || auth_approval(as, lc, pw->pw_name, "ssh") <= 0) { debug("Approval failure for %s", user); pw = NULL; } if (as != NULL) auth_close(as); #endif #endif if (pw != NULL) return (pwcopy(pw)); return (NULL); }
int user_in_group(struct passwd *pw, const char *group) { #ifdef HAVE_MBR_CHECK_MEMBERSHIP uuid_t gu, uu; int ismember; #else char **gr_mem; int i; #endif struct group *grp; int retval = FALSE; #ifdef HAVE_SETAUTHDB aix_setauthdb(pw->pw_name); #endif grp = sudo_getgrnam(group); #ifdef HAVE_SETAUTHDB aix_restoreauthdb(); #endif if (grp == NULL) goto done; /* check against user's primary (passwd file) gid */ if (grp->gr_gid == pw->pw_gid) { retval = TRUE; goto done; } #ifdef HAVE_MBR_CHECK_MEMBERSHIP /* If we are matching the invoking user use the stashed uuid. */ if (strcmp(pw->pw_name, user_name) == 0) { if (mbr_gid_to_uuid(grp->gr_gid, gu) == 0 && mbr_check_membership(user_uuid, gu, &ismember) == 0 && ismember) { retval = TRUE; goto done; } } else { if (mbr_uid_to_uuid(pw->pw_uid, uu) == 0 && mbr_gid_to_uuid(grp->gr_gid, gu) == 0 && mbr_check_membership(uu, gu, &ismember) == 0 && ismember) { retval = TRUE; goto done; } } #else /* HAVE_MBR_CHECK_MEMBERSHIP */ # ifdef HAVE_GETGROUPS /* * If we are matching the invoking or list user and that user has a * supplementary group vector, check it. */ if (user_ngroups > 0 && strcmp(pw->pw_name, list_pw ? list_pw->pw_name : user_name) == 0) { for (i = 0; i < user_ngroups; i++) { if (grp->gr_gid == user_groups[i]) { retval = TRUE; goto done; } } } else # endif /* HAVE_GETGROUPS */ { if (grp != NULL && grp->gr_mem != NULL) { for (gr_mem = grp->gr_mem; *gr_mem; gr_mem++) { if (strcmp(*gr_mem, pw->pw_name) == 0) { retval = TRUE; goto done; } } } } #endif /* HAVE_MBR_CHECK_MEMBERSHIP */ done: if (grp != NULL) gr_delref(grp); return retval; }
/* * Tries to authenticate the user using password. Returns true if * authentication succeeds. */ int auth_password(Authctxt *authctxt, const char *password) { struct passwd * pw = authctxt->pw; int ok = authctxt->valid; /* deny if no user. */ if (pw == NULL) return 0; #ifndef HAVE_CYGWIN if (pw && pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES) ok = 0; #endif if (*password == '\0' && options.permit_empty_passwd == 0) return 0; #if defined(HAVE_OSF_SIA) return auth_sia_password(authctxt, password) && ok; #else # ifdef KRB5 if (options.kerberos_authentication == 1) { int ret = auth_krb5_password(authctxt, password); if (ret == 1 || ret == 0) return ret && ok; /* Fall back to ordinary passwd authentication. */ } # endif # ifdef HAVE_CYGWIN if (is_winnt) { HANDLE hToken = cygwin_logon_user(pw, password); if (hToken == INVALID_HANDLE_VALUE) return 0; cygwin_set_impersonation_token(hToken); return ok; } # endif # ifdef WITH_AIXAUTHENTICATE { char *authmsg = NULL; int reenter = 1; int authsuccess = 0; if (authenticate(pw->pw_name, password, &reenter, &authmsg) == 0 && ok) { char *msg; char *host = (char *)get_canonical_hostname(options.use_dns); authsuccess = 1; aix_remove_embedded_newlines(authmsg); debug3("AIX/authenticate succeeded for user %s: %.100s", pw->pw_name, authmsg); /* No pty yet, so just label the line as "ssh" */ aix_setauthdb(authctxt->user); if (loginsuccess(authctxt->user, host, "ssh", &msg) == 0) { if (msg != NULL) { debug("%s: msg %s", __func__, msg); buffer_append(&loginmsg, msg, strlen(msg)); xfree(msg); } } } else { debug3("AIX/authenticate failed for user %s: %.100s", pw->pw_name, authmsg); } if (authmsg != NULL) xfree(authmsg); return authsuccess; } # endif # ifdef BSD_AUTH if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh", (char *)password) == 0) return 0; else return ok; # else { /* 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 ok; else { /* Encrypt the candidate password using the proper salt. */ char *encrypted_password = xcrypt(password, (pw_password[0] && pw_password[1]) ? pw_password : "******"); /* * Authentication is accepted if the encrypted passwords * are identical. */ return (strcmp(encrypted_password, pw_password) == 0) && ok; } } # endif #endif /* !HAVE_OSF_SIA */ }