static int send_username(ssh_session session, const char *username) { ssh_string user = NULL; /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */ if(session->auth_service_state == SSH_AUTH_SERVICE_USER_SENT) { if(session->auth_state == SSH_AUTH_STATE_FAILED) return SSH_AUTH_DENIED; if(session->auth_state == SSH_AUTH_STATE_SUCCESS) return SSH_AUTH_SUCCESS; return SSH_AUTH_ERROR; } if (!username) { if(!(username = session->username)) { if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { session->auth_service_state = SSH_AUTH_SERVICE_DENIED; return SSH_ERROR; } else { username = session->username; } } } user = ssh_string_from_char(username); if (user == NULL) { return SSH_AUTH_ERROR; } if (buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, user) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } ssh_string_free(user); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { return SSH_AUTH_ERROR; } if(wait_auth1_status(session) == SSH_AUTH_SUCCESS){ session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_state=SSH_AUTH_STATE_SUCCESS; return SSH_AUTH_SUCCESS; } else { session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; ssh_set_error(session,SSH_REQUEST_DENIED,"Password authentication necessary for user %s",username); return SSH_AUTH_DENIED; } }
int ssh_userauth1_password(ssh_session session, const char *username, const char *password) { ssh_string pwd = NULL; int rc; enter_function(); rc = send_username(session, username); if (rc != SSH_AUTH_DENIED) { leave_function(); return rc; } /* we trick a bit here. A known flaw in SSH1 protocol is that it's * easy to guess password sizes. * not that sure ... */ /* XXX fix me here ! */ /* cisco IOS doesn't like when a password is followed by zeroes and random pad. */ if(1 || strlen(password) >= 128) { /* not risky to disclose the size of such a big password .. */ pwd = ssh_string_from_char(password); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } } else { /* fill the password string from random things. the strcpy * ensure there is at least a nul byte after the password. * most implementation won't see the garbage at end. * why garbage ? because nul bytes will be compressed by * gzip and disclose password len. */ pwd = ssh_string_new(128); if (pwd == NULL) { leave_function(); return SSH_AUTH_ERROR; } ssh_get_random( pwd->string, 128, 0); strcpy((char *) pwd->string, password); } if (buffer_add_u8(session->out_buffer, SSH_CMSG_AUTH_PASSWORD) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } if (buffer_add_ssh_string(session->out_buffer, pwd) < 0) { ssh_string_burn(pwd); ssh_string_free(pwd); leave_function(); return SSH_AUTH_ERROR; } ssh_string_burn(pwd); ssh_string_free(pwd); session->auth_state=SSH_AUTH_STATE_NONE; if (packet_send(session) == SSH_ERROR) { leave_function(); return SSH_AUTH_ERROR; } rc = wait_auth1_status(session); leave_function(); return rc; }
static int send_username(ssh_session session, const char *username) { ssh_string user = NULL; int rc; /* returns SSH_AUTH_SUCCESS or SSH_AUTH_DENIED */ if(session->auth_service_state == SSH_AUTH_SERVICE_USER_SENT) { if(session->auth_state == SSH_AUTH_STATE_FAILED) return SSH_AUTH_DENIED; if(session->auth_state == SSH_AUTH_STATE_SUCCESS) return SSH_AUTH_SUCCESS; return SSH_AUTH_ERROR; } if (session->auth_service_state == SSH_AUTH_SERVICE_SENT) goto pending; if (!username) { if(!(username = session->opts.username)) { if (ssh_options_set(session, SSH_OPTIONS_USER, NULL) < 0) { session->auth_service_state = SSH_AUTH_SERVICE_DENIED; return SSH_ERROR; } else { username = session->opts.username; } } } user = ssh_string_from_char(username); if (user == NULL) { return SSH_AUTH_ERROR; } if (ssh_buffer_add_u8(session->out_buffer, SSH_CMSG_USER) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } if (ssh_buffer_add_ssh_string(session->out_buffer, user) < 0) { ssh_string_free(user); return SSH_AUTH_ERROR; } ssh_string_free(user); session->auth_state=SSH_AUTH_STATE_NONE; session->auth_service_state = SSH_AUTH_SERVICE_SENT; if (ssh_packet_send(session) == SSH_ERROR) { return SSH_AUTH_ERROR; } pending: rc = wait_auth1_status(session); switch (rc){ case SSH_AUTH_SUCCESS: session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; session->auth_state=SSH_AUTH_STATE_SUCCESS; ssh_set_error(session, SSH_NO_ERROR, "Authentication successful"); return SSH_AUTH_SUCCESS; case SSH_AUTH_DENIED: session->auth_service_state=SSH_AUTH_SERVICE_USER_SENT; ssh_set_error(session,SSH_REQUEST_DENIED,"Password authentication necessary for user %s",username); return SSH_AUTH_DENIED; case SSH_AUTH_AGAIN: return SSH_AUTH_AGAIN; default: session->auth_service_state = SSH_AUTH_SERVICE_NONE; session->auth_state=SSH_AUTH_STATE_ERROR; return SSH_AUTH_ERROR; } }