Made parts of SSH asynchronous (inc kex1)
Этот коммит содержится в:
родитель
6ae558b541
Коммит
758df26582
@ -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);
|
ssh_channel ssh_channel_from_local(ssh_session session, uint32_t id);
|
||||||
int channel_write_common(ssh_channel channel, const void *data,
|
int channel_write_common(ssh_channel channel, const void *data,
|
||||||
uint32_t len, int is_stderr);
|
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_ */
|
#endif /* CHANNELS_H_ */
|
||||||
|
@ -26,5 +26,8 @@
|
|||||||
#include "libssh/callbacks.h"
|
#include "libssh/callbacks.h"
|
||||||
|
|
||||||
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
SSH_PACKET_CALLBACK(ssh_packet_kexinit);
|
||||||
|
#ifdef WITH_SSH1
|
||||||
|
SSH_PACKET_CALLBACK(ssh_packet_publickey1);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* KEX_H_ */
|
#endif /* KEX_H_ */
|
||||||
|
@ -47,12 +47,16 @@ int packet_read(ssh_session session);
|
|||||||
int packet_send1(ssh_session session) ;
|
int packet_send1(ssh_session session) ;
|
||||||
void ssh_packet_set_default_callbacks1(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
|
#endif
|
||||||
|
|
||||||
int packet_translate(ssh_session session);
|
int packet_translate(ssh_session session);
|
||||||
/* TODO: remove it when packet_wait is stripped out from libssh */
|
/* TODO: remove it when packet_wait is stripped out from libssh */
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
int packet_wait(ssh_session session,int type,int blocking);
|
//int packet_wait(ssh_session session,int type,int blocking);
|
||||||
#endif
|
#endif
|
||||||
int packet_flush(ssh_session session, int enforce_blocking);
|
int packet_flush(ssh_session session, int enforce_blocking);
|
||||||
|
|
||||||
|
@ -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,
|
int ssh_userauth1_password(ssh_session session, const char *username,
|
||||||
const char *password);
|
const char *password);
|
||||||
|
|
||||||
|
#ifdef WITH_SSH1
|
||||||
/* channels1.c */
|
/* channels1.c */
|
||||||
int channel_open_session1(ssh_channel channel);
|
int channel_open_session1(ssh_channel channel);
|
||||||
int channel_request_pty_size1(ssh_channel channel, const char *terminal,
|
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_change_pty_size1(ssh_channel channel, int cols, int rows);
|
||||||
int channel_request_shell1(ssh_channel channel);
|
int channel_request_shell1(ssh_channel channel);
|
||||||
int channel_request_exec1(ssh_channel channel, const char *cmd);
|
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);
|
int channel_write1(ssh_channel channel, const void *data, int len);
|
||||||
|
|
||||||
|
#endif
|
||||||
/* match.c */
|
/* match.c */
|
||||||
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
int match_hostname(const char *host, const char *pattern, unsigned int len);
|
||||||
|
|
||||||
|
@ -329,7 +329,8 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @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 session current SSH session.
|
||||||
* @param packet buffer to parse packet from. The read pointer will be moved after
|
* @param packet buffer to parse packet from. The read pointer will be moved after
|
||||||
* the call.
|
* the call.
|
||||||
@ -339,7 +340,11 @@ error:
|
|||||||
static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet) {
|
static ssh_channel channel_from_msg(ssh_session session, ssh_buffer packet) {
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
uint32_t chan;
|
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)) {
|
if (buffer_get_u32(packet, &chan) != sizeof(uint32_t)) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
"Getting channel from message: short read");
|
"Getting channel from message: short read");
|
||||||
@ -1052,7 +1057,7 @@ void channel_set_blocking(ssh_channel channel, int blocking) {
|
|||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief handle a SSH_CHANNEL_SUCCESS packet and set the channel
|
* @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_PACKET_CALLBACK(ssh_packet_channel_success){
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
@ -1083,7 +1088,7 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_success){
|
|||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief handle a SSH_CHANNEL_FAILURE packet and set the channel
|
* @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_PACKET_CALLBACK(ssh_packet_channel_failure){
|
||||||
ssh_channel channel;
|
ssh_channel channel;
|
||||||
|
@ -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) {
|
int channel_change_pty_size1(ssh_channel channel, int cols, int rows) {
|
||||||
ssh_session session = channel->session;
|
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 ||
|
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(rows)) < 0 ||
|
||||||
buffer_add_u32(session->out_buffer, ntohl(cols)) < 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 ||
|
||||||
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)) {
|
if (packet_send(session)) {
|
||||||
return -1;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_RARE, "Change pty size send");
|
ssh_log(session, SSH_LOG_PROTOCOL, "Change pty size send");
|
||||||
|
while(channel->request_state==SSH_CHANNEL_REQ_STATE_PENDING){
|
||||||
if (packet_wait(session, SSH_SMSG_SUCCESS, 1) != SSH_OK) {
|
ssh_handle_packets(session,-1);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
switch(channel->request_state){
|
||||||
switch (session->in_packet.type) {
|
case SSH_CHANNEL_REQ_STATE_ERROR:
|
||||||
case SSH_SMSG_SUCCESS:
|
case SSH_CHANNEL_REQ_STATE_PENDING:
|
||||||
ssh_log(session, SSH_LOG_RARE, "pty size changed");
|
case SSH_CHANNEL_REQ_STATE_NONE:
|
||||||
return 0;
|
channel->request_state=SSH_CHANNEL_REQ_STATE_NONE;
|
||||||
case SSH_SMSG_FAILURE:
|
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_log(session, SSH_LOG_RARE, "pty size change denied");
|
||||||
ssh_set_error(session, SSH_REQUEST_DENIED, "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) {
|
int channel_request_shell1(ssh_channel channel) {
|
||||||
@ -208,35 +214,37 @@ int channel_request_exec1(ssh_channel channel, const char *cmd) {
|
|||||||
return 0;
|
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_channel channel = session->channels;
|
||||||
ssh_string str = NULL;
|
ssh_string str = NULL;
|
||||||
|
int is_stderr=(type==SSH_SMSG_STDOUT_DATA ? 0 : 1);
|
||||||
str = buffer_get_ssh_string(session->in_buffer);
|
(void)user;
|
||||||
|
str = buffer_get_ssh_string(packet);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
ssh_log(session, SSH_LOG_FUNCTIONS, "Invalid data packet !\n");
|
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",
|
"Adding %zu bytes data in %d",
|
||||||
string_len(str), is_stderr);
|
string_len(str), is_stderr);
|
||||||
|
|
||||||
if (channel_default_bufferize(channel, string_data(str), string_len(str),
|
if (channel_default_bufferize(channel, string_data(str), string_len(str),
|
||||||
is_stderr) < 0) {
|
is_stderr) < 0) {
|
||||||
string_free(str);
|
string_free(str);
|
||||||
return -1;
|
return SSH_PACKET_USED;
|
||||||
}
|
}
|
||||||
string_free(str);
|
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;
|
ssh_channel channel = session->channels;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
(void)type;
|
||||||
buffer_get_u32(session->in_buffer, &status);
|
(void)user;
|
||||||
|
buffer_get_u32(packet, &status);
|
||||||
/*
|
/*
|
||||||
* It's much more than a channel closing. spec says it's the last
|
* It's much more than a channel closing. spec says it's the last
|
||||||
* message sent by server (strange)
|
* message sent by server (strange)
|
||||||
@ -246,41 +254,12 @@ static int channel_rcv_close1(ssh_session session) {
|
|||||||
channel->open = 0;
|
channel->open = 0;
|
||||||
channel->remote_eof = 1;
|
channel->remote_eof = 1;
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION) < 0) {
|
buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION);
|
||||||
return -1;
|
packet_send(session);
|
||||||
}
|
|
||||||
|
|
||||||
if (packet_send(session) != SSH_OK) {
|
return SSH_PACKET_USED;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
int channel_write1(ssh_channel channel, const void *data, int len) {
|
||||||
ssh_session session = channel->session;
|
ssh_session session = channel->session;
|
||||||
|
@ -601,7 +601,6 @@ void ssh_connection_callback(ssh_session session){
|
|||||||
goto error;
|
goto error;
|
||||||
set_status(session,0.6);
|
set_status(session,0.6);
|
||||||
session->connected = 1;
|
session->connected = 1;
|
||||||
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
183
libssh/kex.c
183
libssh/kex.c
@ -597,7 +597,6 @@ static ssh_string encrypt_session_key(ssh_session session, ssh_public_key srvkey
|
|||||||
return data1;
|
return data1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* SSH-1 functions */
|
/* SSH-1 functions */
|
||||||
/* 2 SSH_SMSG_PUBLIC_KEY
|
/* 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_ciphers_mask
|
||||||
* 32-bit int supported_authentications_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_exp = NULL;
|
||||||
ssh_string server_mod = NULL;
|
ssh_string server_mod = NULL;
|
||||||
ssh_string host_exp = NULL;
|
ssh_string host_exp = NULL;
|
||||||
ssh_string host_mod = NULL;
|
ssh_string host_mod = NULL;
|
||||||
ssh_string serverkey = NULL;
|
ssh_string serverkey = NULL;
|
||||||
ssh_string hostkey = NULL;
|
ssh_string hostkey = NULL;
|
||||||
ssh_string enc_session = NULL;
|
|
||||||
ssh_public_key srv = NULL;
|
ssh_public_key srv = NULL;
|
||||||
ssh_public_key host = NULL;
|
ssh_public_key host = NULL;
|
||||||
uint32_t server_bits;
|
uint32_t server_bits;
|
||||||
@ -628,45 +628,43 @@ int ssh_get_kex1(ssh_session session) {
|
|||||||
uint32_t protocol_flags;
|
uint32_t protocol_flags;
|
||||||
uint32_t supported_ciphers_mask;
|
uint32_t supported_ciphers_mask;
|
||||||
uint32_t supported_authentications_mask;
|
uint32_t supported_authentications_mask;
|
||||||
|
ssh_string enc_session = NULL;
|
||||||
uint16_t bits;
|
uint16_t bits;
|
||||||
int rc = -1;
|
|
||||||
int ko;
|
int ko;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY");
|
(void)type;
|
||||||
if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) {
|
(void)user;
|
||||||
leave_function();
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY");
|
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");
|
ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer");
|
||||||
leave_function();
|
goto error;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_get_u32(session->in_buffer, &server_bits);
|
buffer_get_u32(packet, &server_bits);
|
||||||
server_exp = buffer_get_mpint(session->in_buffer);
|
server_exp = buffer_get_mpint(packet);
|
||||||
if (server_exp == NULL) {
|
if (server_exp == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
server_mod = buffer_get_mpint(session->in_buffer);
|
server_mod = buffer_get_mpint(packet);
|
||||||
if (server_mod == NULL) {
|
if (server_mod == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
buffer_get_u32(session->in_buffer, &host_bits);
|
buffer_get_u32(packet, &host_bits);
|
||||||
host_exp = buffer_get_mpint(session->in_buffer);
|
host_exp = buffer_get_mpint(packet);
|
||||||
if (host_exp == NULL) {
|
if (host_exp == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
host_mod = buffer_get_mpint(session->in_buffer);
|
host_mod = buffer_get_mpint(packet);
|
||||||
if (host_mod == NULL) {
|
if (host_mod == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
buffer_get_u32(session->in_buffer, &protocol_flags);
|
buffer_get_u32(packet, &protocol_flags);
|
||||||
buffer_get_u32(session->in_buffer, &supported_ciphers_mask);
|
buffer_get_u32(packet, &supported_ciphers_mask);
|
||||||
ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask);
|
ko = buffer_get_u32(packet, &supported_authentications_mask);
|
||||||
|
|
||||||
if ((ko != sizeof(uint32_t)) || !host_mod || !host_exp
|
if ((ko != sizeof(uint32_t)) || !host_mod || !host_exp
|
||||||
|| !server_mod || !server_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");
|
ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY");
|
ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY");
|
||||||
|
|
||||||
if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) {
|
if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) {
|
if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) {
|
if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits);
|
enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits);
|
||||||
if (enc_session == NULL) {
|
if (enc_session == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = string_len(enc_session) * 8 - 7;
|
bits = string_len(enc_session) * 8 - 7;
|
||||||
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
|
ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session",
|
||||||
bits, string_len(enc_session));
|
bits, string_len(enc_session));
|
||||||
bits = htons(bits);
|
bits = htons(bits);
|
||||||
/* the encrypted mpint */
|
/* the encrypted mpint */
|
||||||
if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) {
|
if (buffer_add_data(session->out_buffer, &bits, sizeof(uint16_t)) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_data(session->out_buffer, string_data(enc_session),
|
if (buffer_add_data(session->out_buffer, string_data(enc_session),
|
||||||
string_len(enc_session)) < 0) {
|
string_len(enc_session)) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/* the protocol flags */
|
/* the protocol flags */
|
||||||
if (buffer_add_u32(session->out_buffer, 0) < 0) {
|
if (buffer_add_u32(session->out_buffer, 0) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
session->session_state=SSH_SESSION_STATE_KEXINIT_RECEIVED;
|
||||||
|
if (packet_send(session) != SSH_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (packet_send(session) != SSH_OK) {
|
/* we can set encryption */
|
||||||
goto error;
|
if (crypt_set_algorithms(session)) {
|
||||||
}
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
/* we can set encryption */
|
session->current_crypto = session->next_crypto;
|
||||||
if (crypt_set_algorithms(session)) {
|
session->next_crypto = NULL;
|
||||||
goto error;
|
goto end;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
error:
|
error:
|
||||||
string_free(host_mod);
|
session->session_state=SSH_SESSION_STATE_ERROR;
|
||||||
string_free(host_exp);
|
end:
|
||||||
string_free(server_mod);
|
|
||||||
string_free(server_exp);
|
|
||||||
string_free(serverkey);
|
|
||||||
string_free(hostkey);
|
|
||||||
|
|
||||||
publickey_free(srv);
|
string_free(host_mod);
|
||||||
publickey_free(host);
|
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();
|
leave_function();
|
||||||
return rc;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_SSH1 */
|
#endif /* WITH_SSH1 */
|
||||||
|
@ -26,13 +26,13 @@
|
|||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
#include "libssh/socket.h"
|
#include "libssh/socket.h"
|
||||||
|
#include "libssh/kex.h"
|
||||||
#ifdef WITH_SSH1
|
#ifdef WITH_SSH1
|
||||||
|
|
||||||
ssh_packet_callback default_packet_handlers1[]= {
|
ssh_packet_callback default_packet_handlers1[]= {
|
||||||
NULL, //SSH_MSG_NONE 0
|
NULL, //SSH_MSG_NONE 0
|
||||||
NULL, //SSH_MSG_DISCONNECT 1
|
ssh_packet_disconnect1, //SSH_MSG_DISCONNECT 1
|
||||||
NULL, //SSH_SMSG_PUBLIC_KEY 2
|
ssh_packet_publickey1, //SSH_SMSG_PUBLIC_KEY 2
|
||||||
NULL, //SSH_CMSG_SESSION_KEY 3
|
NULL, //SSH_CMSG_SESSION_KEY 3
|
||||||
NULL, //SSH_CMSG_USER 4
|
NULL, //SSH_CMSG_USER 4
|
||||||
NULL, //SSH_CMSG_AUTH_RHOSTS 5
|
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_WINDOW_SIZE 11
|
||||||
NULL, //SSH_CMSG_EXEC_SHELL 12
|
NULL, //SSH_CMSG_EXEC_SHELL 12
|
||||||
NULL, //SSH_CMSG_EXEC_CMD 13
|
NULL, //SSH_CMSG_EXEC_CMD 13
|
||||||
NULL, //SSH_SMSG_SUCCESS 14
|
ssh_packet_smsg_success1, //SSH_SMSG_SUCCESS 14
|
||||||
NULL, //SSH_SMSG_FAILURE 15
|
ssh_packet_smsg_failure1, //SSH_SMSG_FAILURE 15
|
||||||
NULL, //SSH_CMSG_STDIN_DATA 16
|
NULL, //SSH_CMSG_STDIN_DATA 16
|
||||||
NULL, //SSH_SMSG_STDOUT_DATA 17
|
ssh_packet_data1, //SSH_SMSG_STDOUT_DATA 17
|
||||||
NULL, //SSH_SMSG_STDERR_DATA 18
|
ssh_packet_data1, //SSH_SMSG_STDERR_DATA 18
|
||||||
NULL, //SSH_CMSG_EOF 19
|
NULL, //SSH_CMSG_EOF 19
|
||||||
NULL, //SSH_SMSG_EXITSTATUS 20
|
NULL, //SSH_SMSG_EXITSTATUS 20
|
||||||
NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21
|
NULL, //SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21
|
||||||
NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22
|
NULL, //SSH_MSG_CHANNEL_OPEN_FAILURE 22
|
||||||
NULL, //SSH_MSG_CHANNEL_DATA 23
|
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_MSG_CHANNEL_CLOSE_CONFIRMATION 25
|
||||||
NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 26
|
NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 26
|
||||||
NULL, //SSH_SMSG_X11_OPEN 27
|
NULL, //SSH_SMSG_X11_OPEN 27
|
||||||
@ -62,19 +62,11 @@ ssh_packet_callback default_packet_handlers1[]= {
|
|||||||
NULL, //SSH_MSG_PORT_OPEN 29
|
NULL, //SSH_MSG_PORT_OPEN 29
|
||||||
NULL, //SSH_CMSG_AGENT_REQUEST_FORWARDING 30
|
NULL, //SSH_CMSG_AGENT_REQUEST_FORWARDING 30
|
||||||
NULL, //SSH_SMSG_AGENT_OPEN 31
|
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_EXIT_CONFIRMATION 33
|
||||||
NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 34
|
NULL, //SSH_CMSG_X11_REQUEST_FORWARDING 34
|
||||||
NULL, //SSH_CMSG_AUTH_RHOSTS_RSA 35
|
NULL, //SSH_CMSG_AUTH_RHOSTS_RSA 35
|
||||||
NULL, //SSH_MSG_DEBUG 36
|
ssh_packet_ignore_callback, //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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
@ -316,37 +308,37 @@ error:
|
|||||||
return rc; /* SSH_OK, AGAIN or 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) {
|
SSH_PACKET_CALLBACK(ssh_packet_smsg_success1){
|
||||||
uint8_t type = session->in_packet.type;
|
if(session->session_state==SSH_SESSION_STATE_KEXINIT_RECEIVED){
|
||||||
|
session->session_state=SSH_SESSION_STATE_AUTHENTICATING;
|
||||||
if (session->version == 1) {
|
return SSH_PACKET_USED;
|
||||||
/* 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;
|
|
||||||
} else {
|
} 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) {
|
int packet_wait(ssh_session session, int type, int blocking) {
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
@ -363,24 +355,15 @@ int packet_wait(ssh_session session, int type, int blocking) {
|
|||||||
session->in_packet.type);
|
session->in_packet.type);
|
||||||
switch (session->in_packet.type) {
|
switch (session->in_packet.type) {
|
||||||
case SSH_MSG_DISCONNECT:
|
case SSH_MSG_DISCONNECT:
|
||||||
packet_parse(session);
|
|
||||||
leave_function();
|
|
||||||
return SSH_ERROR;
|
|
||||||
case SSH_SMSG_STDOUT_DATA:
|
case SSH_SMSG_STDOUT_DATA:
|
||||||
case SSH_SMSG_STDERR_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_DEBUG:
|
||||||
case SSH_MSG_IGNORE:
|
case SSH_MSG_IGNORE:
|
||||||
|
ssh_packet_process(session,type);
|
||||||
|
break;
|
||||||
|
case SSH_SMSG_EXITSTATUS:
|
||||||
|
//This packet must be parsed too
|
||||||
break;
|
break;
|
||||||
/* case SSH2_MSG_CHANNEL_CLOSE:
|
|
||||||
packet_parse(session);
|
|
||||||
break;;
|
|
||||||
*/
|
|
||||||
default:
|
default:
|
||||||
if (type && (type != session->in_packet.type)) {
|
if (type && (type != session->in_packet.type)) {
|
||||||
ssh_set_error(session, SSH_FATAL,
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
Загрузка…
Ссылка в новой задаче
Block a user