diff options
-rw-r--r-- | include/libssh/channels.h | 2 | ||||
-rw-r--r-- | include/libssh/session.h | 3 | ||||
-rw-r--r-- | libssh/channels.c | 102 | ||||
-rw-r--r-- | libssh/packet.c | 4 |
4 files changed, 91 insertions, 20 deletions
diff --git a/include/libssh/channels.h b/include/libssh/channels.h index 5b9fc789..ae45f269 100644 --- a/include/libssh/channels.h +++ b/include/libssh/channels.h @@ -68,6 +68,8 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open_conf); SSH_PACKET_CALLBACK(ssh_packet_channel_open_fail); SSH_PACKET_CALLBACK(ssh_packet_channel_success); SSH_PACKET_CALLBACK(ssh_packet_channel_failure); +SSH_PACKET_CALLBACK(ssh_request_success); +SSH_PACKET_CALLBACK(ssh_request_denied); ssh_channel channel_new(ssh_session session); int channel_default_bufferize(ssh_channel channel, void *data, int len, diff --git a/include/libssh/session.h b/include/libssh/session.h index 64b91d90..dd13e700 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -25,6 +25,7 @@ #include "libssh/packet.h" #include "libssh/pcap.h" #include "libssh/auth.h" +#include "libssh/channels.h" typedef struct ssh_kbdint_struct* ssh_kbdint; @@ -82,7 +83,7 @@ struct ssh_session_struct { int dh_handshake_state; enum ssh_auth_service_state_e auth_service_state; enum ssh_auth_state_e auth_state; - + enum ssh_channel_request_state_e global_req_state; ssh_string dh_server_signature; //information used by dh_handshake. KEX server_kex; KEX client_kex; diff --git a/libssh/channels.c b/libssh/channels.c index ea8ee7d0..0108f631 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -1499,13 +1499,70 @@ ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms) { return channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms); } +/** @internal + * @brief handle a SSH_REQUEST_SUCCESS packet normally sent after a global request. + */ +SSH_PACKET_CALLBACK(ssh_request_success){ + (void)type; + (void)user; + (void)packet; + enter_function(); + + ssh_log(session, SSH_LOG_PACKET, + "Received SSH_REQUEST_SUCCESS"); + if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_log(session, SSH_LOG_RARE, "SSH_REQUEST_SUCCESS received in incorrect state %d", + session->global_req_state); + } else { + session->global_req_state=SSH_CHANNEL_REQ_STATE_ACCEPTED; + } + + leave_function(); + return SSH_PACKET_USED; +} + +/** @internal + * @brief handle a SSH_REQUEST_DENIED packet normally sent after a global request. + */ +SSH_PACKET_CALLBACK(ssh_request_denied){ + (void)type; + (void)user; + (void)packet; + enter_function(); + + ssh_log(session, SSH_LOG_PACKET, + "Received SSH_REQUEST_FAILURE"); + if(session->global_req_state != SSH_CHANNEL_REQ_STATE_PENDING){ + ssh_log(session, SSH_LOG_RARE, "SSH_REQUEST_DENIED received in incorrect state %d", + session->global_req_state); + } else { + session->global_req_state=SSH_CHANNEL_REQ_STATE_DENIED; + } + + leave_function(); + return SSH_PACKET_USED; + +} + +/** @brief sends a global request (needed for forward listening) and wait + * for the result. + * @param session ssh session handle + * @param request the type of request (defined in RFC) + * @param buffer additional data to put in packet + * @param reply expect a reply from server + * @return SSH_OK or SSH_ERROR + */ static int global_request(ssh_session session, const char *request, ssh_buffer buffer, int reply) { ssh_string req = NULL; int rc = SSH_ERROR; enter_function(); - + if(session->global_req_state != SSH_CHANNEL_REQ_STATE_NONE){ + ssh_set_error(session,SSH_FATAL,"Invalid state in start of global_request()"); + leave_function(); + return rc; + } req = string_from_char(request); if (req == NULL) { goto error; @@ -1517,6 +1574,7 @@ static int global_request(ssh_session session, const char *request, goto error; } string_free(req); + req=NULL; if (buffer != NULL) { if (buffer_add_data(session->out_buffer, buffer_get(buffer), @@ -1524,40 +1582,50 @@ static int global_request(ssh_session session, const char *request, goto error; } } - + session->global_req_state = SSH_CHANNEL_REQ_STATE_PENDING; if (packet_send(session) != SSH_OK) { leave_function(); return rc; } - ssh_log(session, SSH_LOG_RARE, + ssh_log(session, SSH_LOG_PACKET, "Sent a SSH_MSG_GLOBAL_REQUEST %s", request); if (reply == 0) { + session->global_req_state=SSH_CHANNEL_REQ_STATE_NONE; leave_function(); return SSH_OK; } - - rc = packet_wait(session, SSH2_MSG_REQUEST_SUCCESS, 1); - if (rc == SSH_ERROR) { - if (session->in_packet.type == SSH2_MSG_REQUEST_FAILURE) { + while(session->global_req_state == SSH_CHANNEL_REQ_STATE_PENDING){ + rc=ssh_handle_packets(session); + if(rc==SSH_ERROR){ + session->global_req_state = SSH_CHANNEL_REQ_STATE_ERROR; + break; + } + } + switch(session->global_req_state){ + case SSH_CHANNEL_REQ_STATE_ACCEPTED: + ssh_log(session, SSH_LOG_PROTOCOL, "Global request %s success",request); + rc=SSH_OK; + break; + case SSH_CHANNEL_REQ_STATE_DENIED: ssh_log(session, SSH_LOG_PACKET, - "%s channel request failed", request); + "Global request %s failed", request); ssh_set_error(session, SSH_REQUEST_DENIED, - "Channel request %s failed", request); - } else { - ssh_log(session, SSH_LOG_RARE, - "Received an unexpected %d message", session->in_packet.type); - } - } else { - ssh_log(session, SSH_LOG_RARE, "Received a SUCCESS"); + "Global request %s failed", request); + rc=SSH_ERROR; + break; + case SSH_CHANNEL_REQ_STATE_ERROR: + case SSH_CHANNEL_REQ_STATE_NONE: + case SSH_CHANNEL_REQ_STATE_PENDING: + rc=SSH_ERROR; + break; + } leave_function(); return rc; error: - buffer_reinit(session->out_buffer); string_free(req); - leave_function(); return rc; } diff --git a/libssh/packet.c b/libssh/packet.c index f88fbe62..4744b014 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -78,8 +78,8 @@ ssh_packet_callback default_packet_handlers[]= { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //62-79 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //#define SSH2_MSG_GLOBAL_REQUEST 80 - NULL, //#define SSH2_MSG_REQUEST_SUCCESS 81 - NULL, //#define SSH2_MSG_REQUEST_FAILURE 82 + ssh_request_success, //#define SSH2_MSG_REQUEST_SUCCESS 81 + ssh_request_denied, //#define SSH2_MSG_REQUEST_FAILURE 82 NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 83-89 NULL, //#define SSH2_MSG_CHANNEL_OPEN 90 ssh_packet_channel_open_conf, //#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91 |