diff options
-rw-r--r-- | include/libssh/server.h | 35 | ||||
-rw-r--r-- | libssh/channels.c | 58 | ||||
-rw-r--r-- | libssh/channels1.c | 5 | ||||
-rw-r--r-- | libssh/messages.c | 200 |
4 files changed, 273 insertions, 25 deletions
diff --git a/include/libssh/server.h b/include/libssh/server.h index e441226b..b06ff897 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -136,9 +136,10 @@ int ssh_accept(SSH_SESSION *session); #define SSH_AUTH_UNKNOWN 0 #define SSH_CHANNEL_SESSION 1 -#define SSH_CHANNEL_TCPIP 2 -#define SSH_CHANNEL_X11 3 -#define SSH_CHANNEL_UNKNOWN 4 +#define SSH_CHANNEL_DIRECT_TCPIP 2 +#define SSH_CHANNEL_FORWARDED_TCPIP 3 +#define SSH_CHANNEL_X11 4 +#define SSH_CHANNEL_UNKNOWN 5 #define SSH_CHANNEL_REQUEST_PTY 1 #define SSH_CHANNEL_REQUEST_EXEC 2 @@ -165,11 +166,6 @@ int ssh_message_auth_reply_pk_ok(SSH_MESSAGE *msg, ssh_string algo, ssh_string p int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods); ssh_channel ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg); - -ssh_channel ssh_message_channel_request_channel(SSH_MESSAGE *msg); -// returns the TERM env variable -char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg); -char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg); int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg); int ssh_message_service_reply_success(SSH_MESSAGE *msg); @@ -177,6 +173,29 @@ char *ssh_message_service_service(SSH_MESSAGE *msg); void ssh_set_message_callback(SSH_SESSION *session, int(*ssh_message_callback)(ssh_session session, struct ssh_message *msg)); + +int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len); + +char *ssh_message_channel_request_open_originator(SSH_MESSAGE *msg); +int ssh_message_channel_request_open_originator_port(SSH_MESSAGE *msg); +char *ssh_message_channel_request_open_destination(SSH_MESSAGE *msg); +int ssh_message_channel_request_open_destination_port(SSH_MESSAGE *msg); + +ssh_channel ssh_message_channel_request_channel(SSH_MESSAGE *msg); + +char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg); +int ssh_message_channel_request_pty_width(SSH_MESSAGE *msg); +int ssh_message_channel_request_pty_height(SSH_MESSAGE *msg); +int ssh_message_channel_request_pty_pxwidth(SSH_MESSAGE *msg); +int ssh_message_channel_request_pty_pxheight(SSH_MESSAGE *msg); + +char *ssh_message_channel_request_env_name(SSH_MESSAGE *msg); +char *ssh_message_channel_request_env_value(SSH_MESSAGE *msg); + +char *ssh_message_channel_request_command(SSH_MESSAGE *msg); + +char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libssh/channels.c b/libssh/channels.c index cf8bbf65..f40ebc93 100644 --- a/libssh/channels.c +++ b/libssh/channels.c @@ -472,6 +472,7 @@ static void channel_rcv_request(SSH_SESSION *session) { ssh_string request_s; char *request; uint32_t status; + uint32_t startpos = session->in_buffer->pos; enter_function(); @@ -542,8 +543,13 @@ static void channel_rcv_request(SSH_SESSION *session) { leave_function(); return; } + /* TODO call message_handle since it handles channel requests as messages */ /* *but* reset buffer before !! */ + + session->in_buffer->pos = startpos; + message_handle(session, SSH2_MSG_CHANNEL_REQUEST); + ssh_log(session, SSH_LOG_PACKET, "Unknown request %s", request); SAFE_FREE(request); @@ -852,20 +858,7 @@ error: return rc; } -/** - * @brief Blocking write on channel. - * - * @param channel The channel to write to. - * - * @param data A pointer to the data to write. - * - * @param len The length of the buffer to write to. - * - * @return The number of bytes written, SSH_ERROR on error. - * - * @see channel_read() - */ -int channel_write(ssh_channel channel, const void *data, uint32_t len) { +int channel_write_common(ssh_channel channel, const void *data, uint32_t len, int is_stderr) { SSH_SESSION *session = channel->session; int origlen = len; int effectivelen; @@ -916,7 +909,8 @@ int channel_write(ssh_channel channel, const void *data, uint32_t len) { effectivelen = len; } - if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_DATA) < 0 || + if (buffer_add_u8(session->out_buffer, is_stderr ? + SSH2_MSG_CHANNEL_EXTENDED_DATA : SSH2_MSG_CHANNEL_DATA) < 0 || buffer_add_u32(session->out_buffer, htonl(channel->remote_channel)) < 0 || buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 || @@ -947,6 +941,40 @@ error: } /** + * @brief Blocking write on channel. + * + * @param channel The channel to write to. + * + * @param data A pointer to the data to write. + * + * @param len The length of the buffer to write to. + * + * @return The number of bytes written, SSH_ERROR on error. + * + * @see channel_read() + */ +int channel_write(ssh_channel channel, const void *data, uint32_t len) { + return channel_write_common(channel, data, len, 0); +} + +/** + * @brief Blocking write on channel for stderr. + * + * @param channel The channel to write to. + * + * @param data A pointer to the data to write. + * + * @param len The length of the buffer to write to. + * + * @return The number of bytes written, SSH_ERROR on error. + * + * @see channel_read() + */ +int channel_write_stderr(ssh_channel channel, const void *data, uint32_t len) { + return channel_write_common(channel, data, len, 1); +} + +/** * @brief Check if the channel is open or not. * * @param channel The channel to check. diff --git a/libssh/channels1.c b/libssh/channels1.c index e502ba32..611c99b7 100644 --- a/libssh/channels1.c +++ b/libssh/channels1.c @@ -261,6 +261,11 @@ int channel_handle1(SSH_SESSION *session, int type) { 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; diff --git a/libssh/messages.c b/libssh/messages.c index 151cdd7f..e5ddeab7 100644 --- a/libssh/messages.c +++ b/libssh/messages.c @@ -425,9 +425,9 @@ int ssh_message_auth_reply_pk_ok(SSH_MESSAGE *msg, ssh_string algo, ssh_string p static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) { SSH_MESSAGE *msg = NULL; - ssh_string type = NULL; + ssh_string type = NULL, *originator = NULL, *destination = NULL; char *type_c = NULL; - uint32_t sender, window, packet; + uint32_t sender, window, packet, originator_port, destination_port; enter_function(); @@ -467,6 +467,97 @@ static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) { return msg; } + if (strcmp(type_c,"direct-tcpip") == 0) { + destination = buffer_get_ssh_string(session->in_buffer); + if (destination == NULL) { + goto error; + } + msg->channel_request_open.destination = string_to_char(type); + if (msg->channel_request_open.destination == NULL) { + string_free(destination); + goto error; + } + string_free(destination); + + buffer_get_u32(session->in_buffer, &destination_port); + msg->channel_request_open.destination_port = ntohl(destination_port); + + originator = buffer_get_ssh_string(session->in_buffer); + if (originator == NULL) { + goto error; + } + msg->channel_request_open.originator = string_to_char(type); + if (msg->channel_request_open.originator == NULL) { + string_free(originator); + goto error; + } + string_free(originator); + + buffer_get_u32(session->in_buffer, &originator_port); + msg->channel_request_open.originator_port = ntohl(originator_port); + + msg->channel_request_open.type = SSH_CHANNEL_DIRECT_TCPIP; + SAFE_FREE(type_c); + leave_function(); + return msg; + } + + if (strcmp(type_c,"forwarded-tcpip") == 0) { + destination = buffer_get_ssh_string(session->in_buffer); + if (destination == NULL) { + goto error; + } + msg->channel_request_open.destination = string_to_char(type); + if (msg->channel_request_open.destination == NULL) { + string_free(destination); + goto error; + } + string_free(destination); + + buffer_get_u32(session->in_buffer, &destination_port); + msg->channel_request_open.destination_port = ntohl(destination_port); + + originator = buffer_get_ssh_string(session->in_buffer); + if (originator == NULL) { + goto error; + } + msg->channel_request_open.originator = string_to_char(type); + if (msg->channel_request_open.originator == NULL) { + string_free(originator); + goto error; + } + string_free(originator); + + buffer_get_u32(session->in_buffer, &originator_port); + msg->channel_request_open.originator_port = ntohl(originator_port); + + msg->channel_request_open.type = SSH_CHANNEL_FORWARDED_TCPIP; + SAFE_FREE(type_c); + leave_function(); + return msg; + } + + if (strcmp(type_c,"x11") == 0) { + originator = buffer_get_ssh_string(session->in_buffer); + if (originator == NULL) { + goto error; + } + msg->channel_request_open.originator = string_to_char(type); + if (msg->channel_request_open.originator == NULL) { + string_free(originator); + goto error; + } + string_free(originator); + + buffer_get_u32(session->in_buffer, &originator_port); + msg->channel_request_open.originator_port = ntohl(originator_port); + + msg->channel_request_open.type = SSH_CHANNEL_X11; + SAFE_FREE(type_c); + leave_function(); + return msg; + } + msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN; SAFE_FREE(type_c); @@ -642,6 +733,26 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) { return msg; } + if (strcmp(type_c, "window-change") == 0) { + STRING *term = NULL; + SAFE_FREE(type_c); + + msg->channel_request.type = SSH_CHANNEL_REQUEST_WINDOW_CHANGE; + + buffer_get_u32(session->in_buffer, &msg->channel_request.width); + buffer_get_u32(session->in_buffer, &msg->channel_request.height); + buffer_get_u32(session->in_buffer, &msg->channel_request.pxwidth); + buffer_get_u32(session->in_buffer, &msg->channel_request.pxheight); + + msg->channel_request.width = ntohl(msg->channel_request.width); + msg->channel_request.height = ntohl(msg->channel_request.height); + msg->channel_request.pxwidth = ntohl(msg->channel_request.pxwidth); + msg->channel_request.pxheight = ntohl(msg->channel_request.pxheight); + + leave_function(); + return msg; + } + if (strcmp(type_c, "subsystem") == 0) { ssh_string subsys = NULL; char *subsys_c = NULL; @@ -673,6 +784,7 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) { leave_function(); return msg; } + if (strcmp(type_c, "exec") == 0) { ssh_string cmd = NULL; @@ -695,6 +807,38 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) { return msg; } + if (strcmp(type_c, "env") == 0) { + STRING *name = NULL; + STRING *value = NULL; + + SAFE_FREE(type_c); + + name = buffer_get_ssh_string(session->in_buffer); + if (name == NULL) { + goto error; + } + value = buffer_get_ssh_string(session->in_buffer); + if (value == NULL) { + string_free(name); + goto error; + } + + msg->channel_request.type = SSH_CHANNEL_REQUEST_ENV; + msg->channel_request.var_name = string_to_char(name); + msg->channel_request.var_value = string_to_char(value); + if (msg->channel_request.var_name == NULL || + msg->channel_request.var_value == NULL) { + string_free(name); + string_free(value); + goto error; + } + string_free(name); + string_free(value); + + leave_function(); + return msg; + } + msg->channel_request.type = SSH_CHANNEL_UNKNOWN; SAFE_FREE(type_c); @@ -709,6 +853,58 @@ error: return NULL; } +char *ssh_message_channel_request_open_originator(SSH_MESSAGE *msg){ + return msg->channel_request_open.originator; +} + +int ssh_message_channel_request_open_originator_port(SSH_MESSAGE *msg){ + return msg->channel_request_open.originator_port; +} + +char *ssh_message_channel_request_open_destination(SSH_MESSAGE *msg){ + return msg->channel_request_open.destination; +} + +int ssh_message_channel_request_open_destination_port(SSH_MESSAGE *msg){ + return msg->channel_request_open.destination_port; +} + +CHANNEL *ssh_message_channel_request_channel(SSH_MESSAGE *msg){ + return msg->channel_request.channel; +} + +char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg){ + return msg->channel_request.TERM; +} + +int ssh_message_channel_request_pty_width(SSH_MESSAGE *msg){ + return msg->channel_request.width; +} + +int ssh_message_channel_request_pty_height(SSH_MESSAGE *msg){ + return msg->channel_request.height; +} + +int ssh_message_channel_request_pty_pxwidth(SSH_MESSAGE *msg){ + return msg->channel_request.pxwidth; +} + +int ssh_message_channel_request_pty_pxheight(SSH_MESSAGE *msg){ + return msg->channel_request.pxheight; +} + +char *ssh_message_channel_request_env_name(SSH_MESSAGE *msg){ + return msg->channel_request.var_name; +} + +char *ssh_message_channel_request_env_value(SSH_MESSAGE *msg){ + return msg->channel_request.var_value; +} + +char *ssh_message_channel_request_command(SSH_MESSAGE *msg){ + return msg->channel_request.command; +} + char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg){ return msg->channel_request.subsystem; } |