aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/server.h35
-rw-r--r--libssh/channels.c58
-rw-r--r--libssh/channels1.c5
-rw-r--r--libssh/messages.c200
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;
}