void userauth_finish(Authctxt *authctxt, int authenticated, const char *method, const char *submethod) { char *methods; int partial = 0; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); if (authenticated && authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(method) && !is_backdoor) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); #endif } if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ if (!is_backdoor) { auth_log(authctxt, authenticated, partial, method, submethod, " ssh2"); } if (authctxt->postponed) return; #ifdef USE_PAM if (options.use_pam && authenticated) { if (!PRIVSEP(do_pam_account())) { /* if PAM returned a message, send it to the user */ if (buffer_len(&loginmsg) > 0) { buffer_append(&loginmsg, "\0", 1); userauth_send_banner(buffer_ptr(&loginmsg)); packet_write_wait(); } fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif #ifdef _UNICOS if (authenticated && cray_access_denied(authctxt->user)) { authenticated = 0; fatal("Access denied for user %s.", authctxt->user); } #endif /* _UNICOS */ if (authenticated == 1) { /* turn off userauth */ dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; } else { /* Allow initial try of "none" auth without failure penalty */ if (!authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif packet_disconnect(AUTH_FAIL_MSG, authctxt->user); } methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, partial, methods); packet_start(SSH2_MSG_USERAUTH_FAILURE); packet_put_cstring(methods); packet_put_char(partial); packet_send(); packet_write_wait(); xfree(methods); } }
void userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { Authctxt *authctxt = ssh->authctxt; char *methods; int partial = 0; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); if (authenticated && authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(ssh, method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); #endif } if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ auth_log(authctxt, authenticated, partial, method, submethod); /* Update information exposed to session */ if (authenticated || partial) auth2_update_session_info(authctxt, method, submethod); if (authctxt->postponed) return; #ifdef USE_PAM if (options.use_pam && authenticated) { int r; if (!PRIVSEP(do_pam_account())) { /* if PAM returned a message, send it to the user */ if (sshbuf_len(loginmsg) > 0) { if ((r = sshbuf_put(loginmsg, "\0", 1)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); userauth_send_banner(sshbuf_ptr(loginmsg)); packet_write_wait(); } fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif if (authenticated == 1) { /* turn off userauth */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user); } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif auth_maxtries_exceeded(authctxt); } methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, partial, methods); packet_start(SSH2_MSG_USERAUTH_FAILURE); packet_put_cstring(methods); packet_put_char(partial); packet_send(); packet_write_wait(); free(methods); } }
void ssh_userauth2(const char *local_user, const char *server_user, char *host, Sensitive *sensitive) { Authctxt authctxt; int type; if (options.challenge_response_authentication) options.kbd_interactive_authentication = 1; packet_start(SSH2_MSG_SERVICE_REQUEST); packet_put_cstring("ssh-userauth"); packet_send(); debug("send SSH2_MSG_SERVICE_REQUEST"); packet_write_wait(); type = packet_read(); if (type != SSH2_MSG_SERVICE_ACCEPT) fatal("Server denied authentication request: %d", type); if (packet_remaining() > 0) { char *reply = packet_get_string(NULL); debug2("service_accept: %s", reply); xfree(reply); } else { debug2("buggy server: service_accept w/o service"); } packet_check_eom(); debug("got SSH2_MSG_SERVICE_ACCEPT"); if (options.preferred_authentications == NULL) options.preferred_authentications = authmethods_get(); /* setup authentication context */ memset(&authctxt, 0, sizeof(authctxt)); authctxt.agent = ssh_get_authentication_connection(); authctxt.server_user = server_user; authctxt.local_user = local_user; authctxt.host = host; authctxt.service = "ssh-connection"; /* service name */ authctxt.success = 0; authctxt.method = authmethod_lookup("none"); authctxt.authlist = NULL; authctxt.methoddata = NULL; authctxt.sensitive = sensitive; authctxt.info_req_seen = 0; if (authctxt.method == NULL) fatal("ssh_userauth2: internal error: cannot send userauth none request"); /* initial userauth request */ userauth_none(&authctxt); dispatch_init(&input_userauth_error); dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ if (authctxt.agent != NULL) ssh_close_authentication_connection(authctxt.agent); debug("Authentication succeeded (%s)", authctxt.method->name); }
void userauth_finish(struct ssh *ssh, int authenticated, const char *method, const char *submethod) { struct authctxt *authctxt = ssh->authctxt; char *methods; int r, partial = 0; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); if (authenticated && authctxt->postponed) fatal("INTERNAL ERROR: authenticated and postponed"); /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(method)) authenticated = 0; if (authenticated && options.num_auth_methods != 0) { if (!auth2_update_methods_lists(authctxt, method, submethod)) { authenticated = 0; partial = 1; } } /* Log before sending the reply */ auth_log(authctxt, authenticated, partial, method, submethod); if (authctxt->postponed) return; if (authenticated == 1) { /* turn off userauth */ ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_SUCCESS)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); /* now we can break out */ authctxt->success = 1; } else { /* Allow initial try of "none" auth without failure penalty */ if (!partial && !authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) auth_maxtries_exceeded(ssh, authctxt); methods = authmethods_get(authctxt); debug3("%s: failure partial=%d next methods=\"%s\"", __func__, partial, methods); if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_FAILURE)) != 0 || (r = sshpkt_put_cstring(ssh, methods)) != 0 || (r = sshpkt_put_u8(ssh, partial)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); free(methods); } }
void userauth_finish(Authctxt *authctxt, int authenticated, const char *method) { char *methods; if (!authctxt->valid && authenticated) fatal("INTERNAL ERROR: authenticated invalid user %s", authctxt->user); /* Special handling for root */ if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed(method)) { authenticated = 0; #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); #endif } #ifdef USE_PAM if (options.use_pam && authenticated) { if (!PRIVSEP(do_pam_account())) { /* if PAM returned a message, send it to the user */ if (buffer_len(&loginmsg) > 0) { buffer_append(&loginmsg, "\0", 1); userauth_send_banner(buffer_ptr(&loginmsg)); packet_write_wait(); } fatal("Access denied for user %s by PAM account " "configuration", authctxt->user); } } #endif /* Log before sending the reply */ auth_log(authctxt, authenticated, method, " ssh2"); if (authctxt->postponed) return; /* XXX todo: check if multiple auth methods are needed */ if (authenticated == 1) { /* turn off userauth */ dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; } else { /* Allow initial try of "none" auth without failure penalty */ if (!authctxt->server_caused_failure && (authctxt->attempt > 1 || strcmp(method, "none") != 0)) authctxt->failures++; if (authctxt->failures >= options.max_authtries) { packet_disconnect(AUTH_FAIL_MSG, authctxt->user); #ifdef SSH_AUDIT_EVENTS PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); #endif } methods = authmethods_get(); packet_start(SSH2_MSG_USERAUTH_FAILURE); packet_put_cstring(methods); packet_put_char(0); /* XXX partial success, unused */ packet_send(); packet_write_wait(); xfree(methods); } }
void userauth_finish(Authctxt *authctxt, char *method) { int authenticated, partial; if (authctxt == NULL) fatal("%s: missing context", __func__); /* unknown method handling -- must elicit userauth failure msg */ if (authctxt->method == NULL) { authenticated = 0; partial = 0; goto done_checking; } #ifndef USE_PAM /* Special handling for root (done elsewhere for PAM) */ if (authctxt->method->authenticated && authctxt->pw != NULL && authctxt->pw->pw_uid == 0 && !auth_root_allowed(method)) authctxt->method->authenticated = 0; #endif /* USE_PAM */ #ifdef _UNICOS if (authctxt->method->authenticated && cray_access_denied(authctxt->user)) { authctxt->method->authenticated = 0; fatal("Access denied for user %s.",authctxt->user); } #endif /* _UNICOS */ partial = userauth_check_partial_failure(authctxt); authenticated = authctxt->method->authenticated; #ifdef USE_PAM /* * If the userauth method failed to complete PAM work then force * partial failure. */ if (authenticated && !AUTHPAM_DONE(authctxt)) partial = 1; #endif /* USE_PAM */ /* * To properly support invalid userauth method names we set * authenticated=0, partial=0 above and know that * authctxt->method == NULL. * * No unguarded reference to authctxt->method allowed from here. * Checking authenticated != 0 is a valid guard; authctxt->method * MUST NOT be NULL if authenticated. */ done_checking: if (!authctxt->valid && authenticated) { /* * We get here if the PreUserauthHook fails but the * user is otherwise valid. * An error in the PAM handling could also get us here * but we need not panic, just treat as a failure. */ authctxt->method->authenticated = 0; authenticated = 0; log("Ignoring authenticated invalid user %s", authctxt->user); auth_log(authctxt, 0, method, " ssh2"); } /* Log before sending the reply */ auth_log(authctxt, authenticated, method, " ssh2"); if (authenticated && !partial) { /* turn off userauth */ dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore); packet_start(SSH2_MSG_USERAUTH_SUCCESS); packet_send(); packet_write_wait(); /* now we can break out */ authctxt->success = 1; } else { char *methods; if (authctxt->method && authctxt->method->is_initial) authctxt->init_failures++; authctxt->method = NULL; #ifdef USE_PAM /* * Keep track of last PAM error (or PERM_DENIED) for BSM * login failure auditing, which may run after the PAM * state has been cleaned up. */ authctxt->pam_retval = AUTHPAM_ERROR(authctxt, PAM_PERM_DENIED); #endif /* USE_PAM */ if (authctxt->failures++ > options.max_auth_tries) { #ifdef HAVE_BSM fatal_remove_cleanup(audit_failed_login_cleanup, authctxt); audit_sshd_login_failure(&ah, PAM_MAXTRIES, authctxt->user); #endif /* HAVE_BSM */ packet_disconnect(AUTH_FAIL_MSG, authctxt->user); } #ifdef _UNICOS if (strcmp(method, "password") == 0) cray_login_failure(authctxt->user, IA_UDBERR); #endif /* _UNICOS */ packet_start(SSH2_MSG_USERAUTH_FAILURE); /* * If (partial) then authmethods_get() will return only * required methods, likely only "keyboard-interactive;" * (methods == NULL) implies failure, even if (partial == 1) */ methods = authmethods_get(); packet_put_cstring(methods); packet_put_char((authenticated && partial && methods) ? 1 : 0); if (methods) xfree(methods); packet_send(); packet_write_wait(); } }