mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-29 01:03:57 +03:00
Fleshed out server interface
- Enables channel_request_open types of DIRECT_TCPIP, FORWARDED_TCPIP and X11 (ie. implemented the handling of those channel_request_open types). - Adds functions to retrieve the extra information relating to channel_request_open messages and channel_request messages. - Adds a channel_write_stderr method (obviously for writing to the STDERR channel from server side) - well, technically just converted the exiting channel_write to take an extra argument and created two wrapper functions. - Actually does the invoking of message_handle() from channel_recv_request. - Implemented the handling of the window-change and env channel_requests. - Implemented a few functions in server.h that were declared but not defined (eg. ssh_message_channel_request_channel). Signed-off-by: Preston A. Elder <prez@neuromancy.net> Signed-off-by: Andreas Schneider <mail@cynapses.org>
This commit is contained in:
committed by
Andreas Schneider
parent
b4111c5c18
commit
4f70cc13e2
@@ -136,9 +136,10 @@ int ssh_accept(SSH_SESSION *session);
|
|||||||
#define SSH_AUTH_UNKNOWN 0
|
#define SSH_AUTH_UNKNOWN 0
|
||||||
|
|
||||||
#define SSH_CHANNEL_SESSION 1
|
#define SSH_CHANNEL_SESSION 1
|
||||||
#define SSH_CHANNEL_TCPIP 2
|
#define SSH_CHANNEL_DIRECT_TCPIP 2
|
||||||
#define SSH_CHANNEL_X11 3
|
#define SSH_CHANNEL_FORWARDED_TCPIP 3
|
||||||
#define SSH_CHANNEL_UNKNOWN 4
|
#define SSH_CHANNEL_X11 4
|
||||||
|
#define SSH_CHANNEL_UNKNOWN 5
|
||||||
|
|
||||||
#define SSH_CHANNEL_REQUEST_PTY 1
|
#define SSH_CHANNEL_REQUEST_PTY 1
|
||||||
#define SSH_CHANNEL_REQUEST_EXEC 2
|
#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);
|
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_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_channel_request_reply_success(SSH_MESSAGE *msg);
|
||||||
|
|
||||||
int ssh_message_service_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,
|
void ssh_set_message_callback(SSH_SESSION *session,
|
||||||
int(*ssh_message_callback)(ssh_session session, struct ssh_message *msg));
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -472,6 +472,7 @@ static void channel_rcv_request(SSH_SESSION *session) {
|
|||||||
ssh_string request_s;
|
ssh_string request_s;
|
||||||
char *request;
|
char *request;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
|
uint32_t startpos = session->in_buffer->pos;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
@@ -542,8 +543,13 @@ static void channel_rcv_request(SSH_SESSION *session) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO call message_handle since it handles channel requests as messages */
|
/* TODO call message_handle since it handles channel requests as messages */
|
||||||
/* *but* reset buffer before !! */
|
/* *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);
|
ssh_log(session, SSH_LOG_PACKET, "Unknown request %s", request);
|
||||||
SAFE_FREE(request);
|
SAFE_FREE(request);
|
||||||
|
|
||||||
@@ -852,20 +858,7 @@ error:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
int channel_write_common(ssh_channel channel, const void *data, uint32_t len, int is_stderr) {
|
||||||
* @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) {
|
|
||||||
SSH_SESSION *session = channel->session;
|
SSH_SESSION *session = channel->session;
|
||||||
int origlen = len;
|
int origlen = len;
|
||||||
int effectivelen;
|
int effectivelen;
|
||||||
@@ -916,7 +909,8 @@ int channel_write(ssh_channel channel, const void *data, uint32_t len) {
|
|||||||
effectivelen = 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,
|
buffer_add_u32(session->out_buffer,
|
||||||
htonl(channel->remote_channel)) < 0 ||
|
htonl(channel->remote_channel)) < 0 ||
|
||||||
buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
|
||||||
@@ -946,6 +940,40 @@ error:
|
|||||||
return SSH_ERROR;
|
return SSH_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.
|
* @brief Check if the channel is open or not.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -261,6 +261,11 @@ int channel_handle1(SSH_SESSION *session, int type) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SSH_SMSG_STDERR_DATA:
|
||||||
|
if (channel_rcv_data1(session,1) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SSH_SMSG_EXITSTATUS:
|
case SSH_SMSG_EXITSTATUS:
|
||||||
if (channel_rcv_close1(session) < 0) {
|
if (channel_rcv_close1(session) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -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) {
|
static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) {
|
||||||
SSH_MESSAGE *msg = NULL;
|
SSH_MESSAGE *msg = NULL;
|
||||||
ssh_string type = NULL;
|
ssh_string type = NULL, *originator = NULL, *destination = NULL;
|
||||||
char *type_c = NULL;
|
char *type_c = NULL;
|
||||||
uint32_t sender, window, packet;
|
uint32_t sender, window, packet, originator_port, destination_port;
|
||||||
|
|
||||||
enter_function();
|
enter_function();
|
||||||
|
|
||||||
@@ -467,6 +467,97 @@ static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) {
|
|||||||
return msg;
|
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;
|
msg->channel_request_open.type = SSH_CHANNEL_UNKNOWN;
|
||||||
SAFE_FREE(type_c);
|
SAFE_FREE(type_c);
|
||||||
|
|
||||||
@@ -642,6 +733,26 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) {
|
|||||||
return msg;
|
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) {
|
if (strcmp(type_c, "subsystem") == 0) {
|
||||||
ssh_string subsys = NULL;
|
ssh_string subsys = NULL;
|
||||||
char *subsys_c = NULL;
|
char *subsys_c = NULL;
|
||||||
@@ -673,6 +784,7 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(type_c, "exec") == 0) {
|
if (strcmp(type_c, "exec") == 0) {
|
||||||
ssh_string cmd = NULL;
|
ssh_string cmd = NULL;
|
||||||
|
|
||||||
@@ -695,6 +807,38 @@ static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) {
|
|||||||
return msg;
|
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;
|
msg->channel_request.type = SSH_CHANNEL_UNKNOWN;
|
||||||
SAFE_FREE(type_c);
|
SAFE_FREE(type_c);
|
||||||
|
|
||||||
@@ -709,6 +853,58 @@ error:
|
|||||||
return NULL;
|
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){
|
char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg){
|
||||||
return msg->channel_request.subsystem;
|
return msg->channel_request.subsystem;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user