From 758df265822928744ab20cec8e4929236b6b41e9 Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Sun, 24 Jan 2010 21:03:03 +0100 Subject: [PATCH] Made parts of SSH asynchronous (inc kex1) --- include/libssh/channels.h | 4 + include/libssh/kex.h | 3 + include/libssh/packet.h | 6 +- include/libssh/priv.h | 3 +- libssh/channels.c | 13 ++- libssh/channels1.c | 101 +++++++++------------ libssh/client.c | 1 - libssh/kex.c | 183 ++++++++++++++++++++------------------ libssh/packet1.c | 97 +++++++++----------- 9 files changed, 201 insertions(+), 210 deletions(-) diff --git a/include/libssh/channels.h b/include/libssh/channels.h index ae45f269..5e4901ba 100644 --- a/include/libssh/channels.h +++ b/include/libssh/channels.h @@ -78,5 +78,9 @@ uint32_t ssh_channel_new_id(ssh_session session); ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id); int channel_write_common(ssh_channel channel, const void *data, uint32_t len, int is_stderr); +#ifdef WITH_SSH1 +SSH_PACKET_CALLBACK(ssh_packet_data1); +SSH_PACKET_CALLBACK(ssh_packet_close1); +#endif #endif /* CHANNELS_H_ */ diff --git a/include/libssh/kex.h b/include/libssh/kex.h index 89030d95..ce2a102b 100644 --- a/include/libssh/kex.h +++ b/include/libssh/kex.h @@ -26,5 +26,8 @@ #include "libssh/callbacks.h" SSH_PACKET_CALLBACK(ssh_packet_kexinit); +#ifdef WITH_SSH1 +SSH_PACKET_CALLBACK(ssh_packet_publickey1); +#endif #endif /* KEX_H_ */ diff --git a/include/libssh/packet.h b/include/libssh/packet.h index 29701334..73ad6820 100644 --- a/include/libssh/packet.h +++ b/include/libssh/packet.h @@ -47,12 +47,16 @@ int packet_read(ssh_session session); int packet_send1(ssh_session session) ; void ssh_packet_set_default_callbacks1(ssh_session session); +SSH_PACKET_CALLBACK(ssh_packet_disconnect1); +SSH_PACKET_CALLBACK(ssh_packet_smsg_success1); +SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1); + #endif int packet_translate(ssh_session session); /* TODO: remove it when packet_wait is stripped out from libssh */ #ifdef WITH_SSH1 -int packet_wait(ssh_session session,int type,int blocking); +//int packet_wait(ssh_session session,int type,int blocking); #endif int packet_flush(ssh_session session, int enforce_blocking); diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 4b4aeba7..122dc129 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -191,6 +191,7 @@ int ssh_userauth1_offer_pubkey(ssh_session session, const char *username, int ssh_userauth1_password(ssh_session session, const char *username, const char *password); +#ifdef WITH_SSH1 /* channels1.c */ int channel_open_session1(ssh_channel channel); int channel_request_pty_size1(ssh_channel channel, const char *terminal, @@ -198,9 +199,9 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int channel_change_pty_size1(ssh_channel channel, int cols, int rows); int channel_request_shell1(ssh_channel channel); int channel_request_exec1(ssh_channel channel, const char *cmd); -int channel_handle1(ssh_session session, int type); int channel_write1(ssh_channel channel, const void *data, int len); +#endif /* match.c */ int match_hostname(const char *host, const char *pattern, unsigned int len); diff --git a/libssh/channels.c b/libssh/channels.c index 0a7bf383..aa310095 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -329,7 +329,8 @@ error: } /** @internal - * @brief parse a channel-related packet to resolve it to a ssh_channel. + * @brief parse a channel-related packet to resolve it to a ssh_channel. Works on SSH1 + * sessions too. * @param session current SSH session. * @param packet buffer to parse packet from. The read pointer will be moved after * the call. @@ -339,7 +340,11 @@ error: static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet) { ssh_channel channel; uint32_t chan; - +#ifdef WITH_SSH1 + /* With SSH1, the channel is always the first one */ + if(session->version==1) + return session->channels; +#endif if (buffer_get_u32(packet, &chan) != sizeof(uint32_t)) { ssh_set_error(session, SSH_FATAL, "Getting channel from message: short read"); @@ -1052,7 +1057,7 @@ void channel_set_blocking(ssh_channel channel, int blocking) { /** @internal * @brief handle a SSH_CHANNEL_SUCCESS packet and set the channel - * state. + * state. Also works on SSH1 sessions. */ SSH_PACKET_CALLBACK(ssh_packet_channel_success){ ssh_channel channel; @@ -1083,7 +1088,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_success){ /** @internal * @brief handle a SSH_CHANNEL_FAILURE packet and set the channel - * state. + * state. Also works on SSH1 sessions. */ SSH_PACKET_CALLBACK(ssh_packet_channel_failure){ ssh_channel channel; diff --git a/libssh/channels1.c b/libssh/channels1.c index 54dc5a36..1697754a 100644 --- a/libssh/channels1.c +++ b/libssh/channels1.c @@ -132,39 +132,45 @@ int channel_request_pty_size1(ssh_channel channel, const char *terminal, int col int channel_change_pty_size1(ssh_channel channel, int cols, int rows) { ssh_session session = channel->session; - + if(channel->request_state != SSH_CHANNEL_REQ_STATE_NONE){ + ssh_set_error(session,SSH_REQUEST_DENIED,"Wrong request state"); + return SSH_ERROR; + } if (buffer_add_u8(session->out_buffer, SSH_CMSG_WINDOW_SIZE) < 0 || buffer_add_u32(session->out_buffer, ntohl(rows)) < 0 || buffer_add_u32(session->out_buffer, ntohl(cols)) < 0 || buffer_add_u32(session->out_buffer, 0) < 0 || buffer_add_u32(session->out_buffer, 0) < 0) { - return -1; + return SSH_ERROR; } - + channel->request_state=SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session)) { - return -1; + return SSH_ERROR; } - ssh_log(session, SSH_LOG_RARE, "Change pty size send"); - - if (packet_wait(session, SSH_SMSG_SUCCESS, 1) != SSH_OK) { - return -1; + ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send"); + while(channel->request_state==SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_handle_packets(session,-1); } - - switch (session->in_packet.type) { - case SSH_SMSG_SUCCESS: - ssh_log(session, SSH_LOG_RARE, "pty size changed"); - return 0; - case SSH_SMSG_FAILURE: + switch(channel->request_state){ + case SSH_CHANNEL_REQ_STATE_ERROR: + case SSH_CHANNEL_REQ_STATE_PENDING: + case SSH_CHANNEL_REQ_STATE_NONE: + channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; + return SSH_ERROR; + case SSH_CHANNEL_REQ_STATE_ACCEPTED: + channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; + ssh_log(session, SSH_LOG_PROTOCOL, "pty size changed"); + return SSH_OK; + case SSH_CHANNEL_REQ_STATE_DENIED: + channel->request_state=SSH_CHANNEL_REQ_STATE_NONE; ssh_log(session, SSH_LOG_RARE, "pty size change denied"); ssh_set_error(session, SSH_REQUEST_DENIED, "pty size change denied"); - return -1; + return SSH_ERROR; } + // Not reached + return SSH_ERROR; - ssh_set_error(session, SSH_FATAL, "Received unexpected packet type %d", - session->in_packet.type); - - return -1; } int channel_request_shell1(ssh_channel channel) { @@ -208,35 +214,37 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) { return 0; } -static int channel_rcv_data1(ssh_session session, int is_stderr) { +SSH_PACKET_CALLBACK(ssh_packet_data1){ ssh_channel channel = session->channels; ssh_string str = NULL; - - str = buffer_get_ssh_string(session->in_buffer); + int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1); + (void)user; + str = buffer_get_ssh_string(packet); if (str == NULL) { ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n"); - return -1; + return SSH_PACKET_USED; } - ssh_log(session, SSH_LOG_RARE, + ssh_log(session, SSH_LOG_PROTOCOL, "Adding %zu bytes data in %d", string_len(str), is_stderr); if (channel_default_bufferize(channel, string_data(str), string_len(str), is_stderr) < 0) { string_free(str); - return -1; + return SSH_PACKET_USED; } string_free(str); - return 0; + return SSH_PACKET_USED; } -static int channel_rcv_close1(ssh_session session) { +SSH_PACKET_CALLBACK(ssh_packet_close1){ ssh_channel channel = session->channels; uint32_t status; - - buffer_get_u32(session->in_buffer, &status); + (void)type; + (void)user; + buffer_get_u32(packet, &status); /* * It's much more than a channel closing. spec says it's the last * message sent by server (strange) @@ -246,41 +254,12 @@ static int channel_rcv_close1(ssh_session session) { channel->open = 0; channel->remote_eof = 1; - if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) { - return -1; - } + buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION); + packet_send(session); - if (packet_send(session) != SSH_OK) { - return -1; - } - - return 0; + return SSH_PACKET_USED; } -int channel_handle1(ssh_session session, int type) { - ssh_log(session, SSH_LOG_RARE, "Channel_handle1(%d)", type); - switch (type) { - case SSH_SMSG_STDOUT_DATA: - if (channel_rcv_data1(session,0) < 0) { - return -1; - } - break; - case SSH_SMSG_STDERR_DATA: - if (channel_rcv_data1(session,1) < 0) { - return -1; - } - break; - case SSH_SMSG_EXITSTATUS: - if (channel_rcv_close1(session) < 0) { - return -1; - } - break; - default: - ssh_log(session, SSH_LOG_FUNCTIONS, "Unexpected message %d", type); - } - - return 0; -} int channel_write1(ssh_channel channel, const void *data, int len) { ssh_session session = channel->session; diff --git a/libssh/client.c b/libssh/client.c index 60ebcac3..70e60f27 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -601,7 +601,6 @@ void ssh_connection_callback(ssh_session session){ goto error; set_status(session,0.6); session->connected = 1; - session->session_state=SSH_SESSION_STATE_AUTHENTICATING; break; } #endif diff --git a/libssh/kex.c b/libssh/kex.c index 176ef5bd..70b3e910 100644 --- a/libssh/kex.c +++ b/libssh/kex.c @@ -597,7 +597,6 @@ static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey return data1; } - /* SSH-1 functions */ /* 2 SSH_SMSG_PUBLIC_KEY * @@ -612,15 +611,16 @@ static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey * 32-bit int supported_ciphers_mask * 32-bit int supported_authentications_mask */ - -int ssh_get_kex1(ssh_session session) { +/** + * @brief Wait for a SSH_SMSG_PUBLIC_KEY and does the key exchange + */ +SSH_PACKET_CALLBACK(ssh_packet_publickey1){ ssh_string server_exp = NULL; ssh_string server_mod = NULL; ssh_string host_exp = NULL; ssh_string host_mod = NULL; ssh_string serverkey = NULL; ssh_string hostkey = NULL; - ssh_string enc_session = NULL; ssh_public_key srv = NULL; ssh_public_key host = NULL; uint32_t server_bits; @@ -628,45 +628,43 @@ int ssh_get_kex1(ssh_session session) { uint32_t protocol_flags; uint32_t supported_ciphers_mask; uint32_t supported_authentications_mask; + ssh_string enc_session = NULL; uint16_t bits; - int rc = -1; int ko; - enter_function(); - ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); - if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) { - leave_function(); - return -1; - } - + (void)type; + (void)user; ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY"); - if (buffer_get_data(session->in_buffer, session->server_kex.cookie, 8) != 8) { + if(session->session_state != SSH_SESSION_STATE_INITIAL_KEX){ + ssh_set_error(session,SSH_FATAL,"SSH_KEXINIT received in wrong state"); + goto error; + } + if (buffer_get_data(packet, session->server_kex.cookie, 8) != 8) { ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer"); - leave_function(); - return -1; + goto error; } - buffer_get_u32(session->in_buffer, &server_bits); - server_exp = buffer_get_mpint(session->in_buffer); + buffer_get_u32(packet, &server_bits); + server_exp = buffer_get_mpint(packet); if (server_exp == NULL) { goto error; } - server_mod = buffer_get_mpint(session->in_buffer); + server_mod = buffer_get_mpint(packet); if (server_mod == NULL) { goto error; } - buffer_get_u32(session->in_buffer, &host_bits); - host_exp = buffer_get_mpint(session->in_buffer); + buffer_get_u32(packet, &host_bits); + host_exp = buffer_get_mpint(packet); if (host_exp == NULL) { goto error; } - host_mod = buffer_get_mpint(session->in_buffer); + host_mod = buffer_get_mpint(packet); if (host_mod == NULL) { goto error; } - buffer_get_u32(session->in_buffer, &protocol_flags); - buffer_get_u32(session->in_buffer, &supported_ciphers_mask); - ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask); + buffer_get_u32(packet, &protocol_flags); + buffer_get_u32(packet, &supported_ciphers_mask); + ko = buffer_get_u32(packet, &supported_authentications_mask); if ((ko != sizeof(uint32_t)) || !host_mod || !host_exp || !server_mod || !server_exp) { @@ -722,77 +720,92 @@ int ssh_get_kex1(ssh_session session) { ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES"); goto error; } - ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY"); - if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) { - goto error; - } - if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) { - goto error; - } - if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) { - goto error; - } + if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) { + goto error; + } + if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) { + goto error; + } + if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) { + goto error; + } - enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits); - if (enc_session == NULL) { - goto error; - } + enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits); + if (enc_session == NULL) { + goto error; + } - bits = string_len(enc_session) * 8 - 7; - ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session", - bits, string_len(enc_session)); - bits = htons(bits); - /* the encrypted mpint */ - if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) { - goto error; - } - if (buffer_add_data(session->out_buffer, string_data(enc_session), - string_len(enc_session)) < 0) { - goto error; - } - /* the protocol flags */ - if (buffer_add_u32(session->out_buffer, 0) < 0) { - goto error; - } + bits = string_len(enc_session) * 8 - 7; + ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session", + bits, string_len(enc_session)); + bits = htons(bits); + /* the encrypted mpint */ + if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) { + goto error; + } + if (buffer_add_data(session->out_buffer, string_data(enc_session), + string_len(enc_session)) < 0) { + goto error; + } + /* the protocol flags */ + if (buffer_add_u32(session->out_buffer, 0) < 0) { + goto error; + } + session->session_state=SSH_SESSION_STATE_KEXINIT_RECEIVED; + if (packet_send(session) != SSH_OK) { + goto error; + } - if (packet_send(session) != SSH_OK) { - goto error; - } + /* we can set encryption */ + if (crypt_set_algorithms(session)) { + goto error; + } - /* we can set encryption */ - if (crypt_set_algorithms(session)) { - goto error; - } - - session->current_crypto = session->next_crypto; - session->next_crypto = NULL; - - ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); - if (packet_wait(session,SSH_SMSG_SUCCESS,1) != SSH_OK) { - char buffer[1024] = {0}; - snprintf(buffer, sizeof(buffer), - "Key exchange failed: %s", ssh_get_error(session)); - ssh_set_error(session, SSH_FATAL, "%s",buffer); - goto error; - } - ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); - - rc = 0; + session->current_crypto = session->next_crypto; + session->next_crypto = NULL; + goto end; error: - string_free(host_mod); - string_free(host_exp); - string_free(server_mod); - string_free(server_exp); - string_free(serverkey); - string_free(hostkey); + session->session_state=SSH_SESSION_STATE_ERROR; +end: - publickey_free(srv); - publickey_free(host); + string_free(host_mod); + string_free(host_exp); + string_free(server_mod); + string_free(server_exp); + string_free(serverkey); + string_free(hostkey); + publickey_free(srv); + publickey_free(host); + + leave_function(); + return SSH_PACKET_USED; +} + +int ssh_get_kex1(ssh_session session) { + int ret=SSH_ERROR; + enter_function(); + ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); + /* Here the callback is called */ + while(session->session_state==SSH_SESSION_STATE_INITIAL_KEX){ + ssh_handle_packets(session,-1); + } + if(session->session_state==SSH_SESSION_STATE_ERROR) + goto error; + ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); + /* Waiting for SSH_SMSG_SUCCESS */ + while(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ + ssh_handle_packets(session,-1); + } + if(session->session_state==SSH_SESSION_STATE_ERROR) + goto error; + ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); + ret=SSH_OK; +error: leave_function(); - return rc; + return ret; } #endif /* WITH_SSH1 */ diff --git a/libssh/packet1.c b/libssh/packet1.c index 5c404378..7afab191 100644 --- a/libssh/packet1.c +++ b/libssh/packet1.c @@ -26,13 +26,13 @@ #include "libssh/session.h" #include "libssh/buffer.h" #include "libssh/socket.h" - +#include "libssh/kex.h" #ifdef WITH_SSH1 ssh_packet_callback default_packet_handlers1[]= { NULL, //SSH_MSG_NONE 0 - NULL, //SSH_MSG_DISCONNECT 1 - NULL, //SSH_SMSG_PUBLIC_KEY 2 + ssh_packet_disconnect1, //SSH_MSG_DISCONNECT 1 + ssh_packet_publickey1, //SSH_SMSG_PUBLIC_KEY 2 NULL, //SSH_CMSG_SESSION_KEY 3 NULL, //SSH_CMSG_USER 4 NULL, //SSH_CMSG_AUTH_RHOSTS 5 @@ -44,17 +44,17 @@ ssh_packet_callback default_packet_handlers1[]= { NULL, //SSH_CMSG_WINDOW_SIZE 11 NULL, //SSH_CMSG_EXEC_SHELL 12 NULL, //SSH_CMSG_EXEC_CMD 13 - NULL, //SSH_SMSG_SUCCESS 14 - NULL, //SSH_SMSG_FAILURE 15 + ssh_packet_smsg_success1, //SSH_SMSG_SUCCESS 14 + ssh_packet_smsg_failure1, //SSH_SMSG_FAILURE 15 NULL, //SSH_CMSG_STDIN_DATA 16 - NULL, //SSH_SMSG_STDOUT_DATA 17 - NULL, //SSH_SMSG_STDERR_DATA 18 + ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17 + ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18 NULL, //SSH_CMSG_EOF 19 NULL, //SSH_SMSG_EXITSTATUS 20 NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22 NULL, //SSH_MSG_CHANNEL_DATA 23 - NULL, //SSH_MSG_CHANNEL_CLOSE 24 + ssh_packet_close1, //SSH_MSG_CHANNEL_CLOSE 24 NULL, //SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 26 NULL, //SSH_SMSG_X11_OPEN 27 @@ -62,19 +62,11 @@ ssh_packet_callback default_packet_handlers1[]= { NULL, //SSH_MSG_PORT_OPEN 29 NULL, //SSH_CMSG_AGENT_REQUEST_FORWARDING 30 NULL, //SSH_SMSG_AGENT_OPEN 31 - NULL, //SSH_MSG_IGNORE 32 + ssh_packet_ignore_callback, //SSH_MSG_IGNORE 32 NULL, //SSH_CMSG_EXIT_CONFIRMATION 33 NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 34 NULL, //SSH_CMSG_AUTH_RHOSTS_RSA 35 - NULL, //SSH_MSG_DEBUG 36 - NULL, //SSH_CMSG_REQUEST_COMPRESSION 37 - NULL, //SSH_CMSG_MAX_PACKET_SIZE 38 - NULL, //SSH_CMSG_AUTH_TIS 39 - NULL, //SSH_SMSG_AUTH_TIS_CHALLENGE 40 - NULL, //SSH_CMSG_AUTH_TIS_RESPONSE 41 - NULL, //SSH_CMSG_AUTH_KERBEROS 42 - NULL, //SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 - NULL, //SSH_CMSG_HAVE_KERBEROS_TGT 44 + ssh_packet_ignore_callback, //SSH_MSG_DEBUG 36 }; /** @internal @@ -316,37 +308,37 @@ error: return rc; /* SSH_OK, AGAIN or ERROR */ } +SSH_PACKET_CALLBACK(ssh_packet_disconnect1){ + (void)packet; + (void)user; + (void)type; + ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT"); + ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT"); + ssh_socket_close(session->socket); + session->alive = 0; + return SSH_PACKET_USED; +} -static void packet_parse(ssh_session session) { - uint8_t type = session->in_packet.type; - - if (session->version == 1) { - /* SSH-1 */ - switch(type) { - case SSH_MSG_DISCONNECT: - ssh_log(session, SSH_LOG_PACKET, "Received SSH_MSG_DISCONNECT"); - ssh_set_error(session, SSH_FATAL, "Received SSH_MSG_DISCONNECT"); - - ssh_socket_close(session->socket); - session->alive = 0; - return; - case SSH_SMSG_STDOUT_DATA: - case SSH_SMSG_STDERR_DATA: - case SSH_SMSG_EXITSTATUS: - channel_handle1(session,type); - return; - case SSH_MSG_DEBUG: - case SSH_MSG_IGNORE: - break; - default: - ssh_log(session, SSH_LOG_PACKET, - "Unexpected message code %d", type); - } - return; +SSH_PACKET_CALLBACK(ssh_packet_smsg_success1){ + if(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ + session->session_state=SSH_SESSION_STATE_AUTHENTICATING; + return SSH_PACKET_USED; } else { + return ssh_packet_channel_success(session,type,packet,user); } } +SSH_PACKET_CALLBACK(ssh_packet_smsg_failure1){ + if(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){ + session->session_state=SSH_SESSION_STATE_ERROR; + ssh_set_error(session,SSH_FATAL,"Key exchange failed: received SSH_SMSG_FAILURE"); + return SSH_PACKET_USED; + } else { + return ssh_packet_channel_failure(session,type,packet,user); + } +} + + int packet_wait(ssh_session session, int type, int blocking) { enter_function(); @@ -363,24 +355,15 @@ int packet_wait(ssh_session session, int type, int blocking) { session->in_packet.type); switch (session->in_packet.type) { case SSH_MSG_DISCONNECT: - packet_parse(session); - leave_function(); - return SSH_ERROR; case SSH_SMSG_STDOUT_DATA: case SSH_SMSG_STDERR_DATA: - case SSH_SMSG_EXITSTATUS: - if (channel_handle1(session,type) < 0) { - leave_function(); - return SSH_ERROR; - } - break; case SSH_MSG_DEBUG: case SSH_MSG_IGNORE: + ssh_packet_process(session,type); + break; + case SSH_SMSG_EXITSTATUS: + //This packet must be parsed too break; - /* case SSH2_MSG_CHANNEL_CLOSE: - packet_parse(session); - break;; - */ default: if (type && (type != session->in_packet.type)) { ssh_set_error(session, SSH_FATAL,