void do_authentication(char *user, int privileged_port, int cipher_type) { int type; int authenticated = 0; int authentication_type = 0; char *password; int row, col, xpixel, ypixel; int password_attempts = 0; if (strlen(user) > 255) do_authentication_fail_loop(); /* Verify that the user is a valid user. We disallow usernames starting with any characters that are commonly used to start NIS entries. */ if (user[0] == '-' || user[0] == '+' || user[0] == '@') do_authentication_fail_loop(); debug("Attempting authentication for %.100s.", user); /* If the user has no password, accept authentication immediately. */ if (auth_password(user, "")) { /* Authentication with empty password succeeded. */ authentication_type = SSH_AUTH_PASSWORD; authenticated = 1; /* Success packet will be sent after loop below. */ } else { /* Indicate that authentication is needed. */ packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); } /* Loop until the user has been authenticated or the connection is closed. */ while (!authenticated) { /* Get a packet from the client. */ type = packet_read(); /* Process the packet. */ switch (type) { case SSH_CMSG_AUTH_RHOSTS: packet_get_all(); log_msg("Rhosts authentication disabled."); break; case SSH_CMSG_AUTH_RHOSTS_RSA: packet_get_all(); log_msg("Rhosts with RSA authentication disabled."); break; case SSH_CMSG_AUTH_RSA: packet_get_all(); log_msg("RSA authentication disabled."); break; case SSH_CMSG_AUTH_PASSWORD: if (cipher_type == SSH_CIPHER_NONE) { packet_get_all(); log_msg("Password authentication not available for unencrypted session."); break; } /* Password authentication requested. */ /* Read user password. It is in plain text, but was transmitted over the encrypted channel so it is not visible to an outside observer. */ password = packet_get_string(NULL); if (password_attempts >= 5) { /* Too many password authentication attempts. */ packet_disconnect("Too many password authentication attempts from %.100s for user %.100s.", get_canonical_hostname(), user); /*NOTREACHED*/} /* Count password authentication attempts, and log if appropriate. */ if (password_attempts > 0) { /* Log failures if attempted more than once. */ debug("Password authentication failed for user %.100s from %.100s.", user, get_canonical_hostname()); } password_attempts++; /* Try authentication with the password. */ if (auth_password(user, password)) { /* Successful authentication. */ /* Clear the password from memory. */ memset(password, 0, strlen(password)); xfree(password); log_msg("Password authentication for %.100s accepted.", user); authentication_type = SSH_AUTH_PASSWORD; authenticated = 1; break; } debug("Password authentication for %.100s failed.", user); memset(password, 0, strlen(password)); xfree(password); break; case SSH_CMSG_WINDOW_SIZE: debug("Window change received."); row = packet_get_int(); col = packet_get_int(); xpixel = packet_get_int(); ypixel = packet_get_int(); do_naws(row, col); break; default: /* Any unknown messages will be ignored (and failure returned) during authentication. */ packet_get_all(); log_msg("Unknown message during authentication: type %d", type); break; /* Respond with a failure message. */ } /* If successfully authenticated, break out of loop. */ if (authenticated) break; /* Send a message indicating that the authentication attempt failed. */ packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); } /* The user has been authenticated and accepted. */ packet_start(SSH_SMSG_SUCCESS); packet_send(); packet_write_wait(); /* Perform session preparation. */ do_authenticated(NULL); }
void do_authenticated(char *pw) { int type; int compression_level = 0, enable_compression_after_reply = 0; int row, col, xpixel, ypixel; unsigned long max_size; char *display = NULL, *proto = NULL, *data = NULL; /* Cancel the alarm we set to limit the time taken for authentication. */ alarm(0); /* Inform the channel mechanism that we are the server side and that the client may request to connect to any port at all. (The user could do it anyway, and we wouldn\'t know what is permitted except by the client telling us, so we can equally well trust the client not to request anything bogus.) */ /* We stay in this loop until the client requests to execute a shell or a command. */ while (1) { /* Get a packet from the client. */ type = packet_read(); /* Process the packet. */ switch (type) { case SSH_CMSG_REQUEST_COMPRESSION: /* COMMAN: k core said that compression is not useful */ goto fail; compression_level = packet_get_int(); if (compression_level < 1 || compression_level > 9) { packet_send_debug("Received illegal compression level %d.", compression_level); goto fail; } /* Enable compression after we have responded with SUCCESS. */ enable_compression_after_reply = 1; break; case SSH_CMSG_MAX_PACKET_SIZE: /* Get maximum size from paket. */ max_size = packet_get_int(); /* Make sure that it is acceptable. */ if (max_size < 4096 || max_size > 256 * 1024) { packet_send_debug("Received illegal max packet size %lu.", max_size); goto fail; } /* Set the size and return success. */ packet_set_max_size(max_size); break; case SSH_CMSG_REQUEST_PTY: packet_get_string(NULL); row = packet_get_int(); col = packet_get_int(); xpixel = packet_get_int(); ypixel = packet_get_int(); do_naws(row, col); packet_get_all(); debug("Allocating a pty not permitted for this authentication."); break; case SSH_CMSG_X11_REQUEST_FORWARDING: packet_get_all(); debug("X11 forwarding disabled in this site."); packet_send_debug("X11 forwarding disabled in this site."); goto fail; case SSH_CMSG_AGENT_REQUEST_FORWARDING: packet_get_all(); debug("Authentication agent forwarding not permitted for this authentication."); goto fail; case SSH_CMSG_PORT_FORWARD_REQUEST: packet_get_all(); debug("All port forwardings disabled in this site."); packet_send_debug("All port forwardings disabled in this site."); goto fail; case SSH_CMSG_EXEC_SHELL: /* Set interactive/non-interactive mode. */ packet_set_interactive(1, options.keepalives); if (forced_command != NULL) goto do_forced_command; debug("Forking shell."); do_exec_no_pty(NULL, pw, display, proto, data); return; case SSH_CMSG_EXEC_CMD: packet_get_all(); debug("command executing disabled in this site."); packet_send_debug("command executing disabled in this site."); goto fail; case SSH_CMSG_WINDOW_SIZE: debug("Window change received."); row = packet_get_int(); col = packet_get_int(); xpixel = packet_get_int(); ypixel = packet_get_int(); do_naws(row, col); break; default: /* Any unknown messages in this phase are ignored, and a failure message is returned. */ packet_get_all(); log_msg("Unknown packet type received after authentication: %d", type); goto fail; } /* The request was successfully processed. */ packet_start(SSH_SMSG_SUCCESS); packet_send(); packet_write_wait(); /* Enable compression now that we have replied if appropriate. */ if (enable_compression_after_reply) { enable_compression_after_reply = 0; packet_start_compression(compression_level); } continue; fail: /* The request failed. */ packet_get_all(); packet_start(SSH_SMSG_FAILURE); packet_send(); packet_write_wait(); continue; do_forced_command: /* There is a forced command specified for this login. Execute it. */ debug("Executing forced command: %.900s", forced_command); return; } }
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 (!use_privsep && 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) { /* * Should never happen -- if it does PAM's at fault * 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); #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(); } }