aboutsummaryrefslogtreecommitdiff
path: root/src/messages.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messages.c')
-rw-r--r--src/messages.c169
1 files changed, 108 insertions, 61 deletions
diff --git a/src/messages.c b/src/messages.c
index 25683b23..be9462ac 100644
--- a/src/messages.c
+++ b/src/messages.c
@@ -54,7 +54,7 @@
* This file contains the message parsing utilities for client and server
* programs using libssh.
*
- * On the server the the main loop of the program will call
+ * On the server the main loop of the program will call
* ssh_message_get(session) to get messages as they come. They are not 1-1 with
* the protocol messages. Then, the user will know what kind of a message it is
* and use the appropriate functions to handle it (or use the default handlers
@@ -79,7 +79,7 @@ static ssh_message ssh_message_new(ssh_session session)
#ifndef WITH_SERVER
-/* Reduced version of the reply default that only reply with
+/* Reduced version of the reply default that only replies with
* SSH_MSG_UNIMPLEMENTED
*/
static int ssh_message_reply_default(ssh_message msg) {
@@ -160,7 +160,7 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
if (channel != NULL) {
rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
if (rc != SSH_OK) {
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_TRACE,
"Failed to send reply for accepting a channel "
"open");
}
@@ -237,7 +237,7 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
msg->channel_request.pxwidth,
msg->channel_request.pxheight);
if (rc != SSH_OK) {
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_TRACE,
"Failed to iterate callbacks for window change");
}
return SSH_OK;
@@ -317,6 +317,17 @@ static int ssh_execute_server_request(ssh_session session, ssh_message msg)
return SSH_AGAIN;
}
+static int ssh_reply_channel_open_request(ssh_message msg, ssh_channel channel)
+{
+ if (channel != NULL) {
+ return ssh_message_channel_request_open_reply_accept_channel(msg, channel);
+ }
+
+ ssh_message_reply_default(msg);
+
+ return SSH_OK;
+}
+
static int ssh_execute_client_request(ssh_session session, ssh_message msg)
{
ssh_channel channel = NULL;
@@ -329,30 +340,26 @@ static int ssh_execute_client_request(ssh_session session, ssh_message msg)
msg->channel_request_open.originator,
msg->channel_request_open.originator_port,
session->common.callbacks->userdata);
- if (channel != NULL) {
- rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
- return rc;
- } else {
- ssh_message_reply_default(msg);
- }
-
- return SSH_OK;
+ return ssh_reply_channel_open_request(msg, channel);
} else if (msg->type == SSH_REQUEST_CHANNEL_OPEN
&& msg->channel_request_open.type == SSH_CHANNEL_AUTH_AGENT
&& ssh_callbacks_exists(session->common.callbacks, channel_open_request_auth_agent_function)) {
channel = session->common.callbacks->channel_open_request_auth_agent_function (session,
session->common.callbacks->userdata);
- if (channel != NULL) {
- rc = ssh_message_channel_request_open_reply_accept_channel(msg, channel);
-
- return rc;
- } else {
- ssh_message_reply_default(msg);
- }
+ return ssh_reply_channel_open_request(msg, channel);
+ } else if (msg->type == SSH_REQUEST_CHANNEL_OPEN
+ && msg->channel_request_open.type == SSH_CHANNEL_FORWARDED_TCPIP
+ && ssh_callbacks_exists(session->common.callbacks, channel_open_request_forwarded_tcpip_function)) {
+ channel = session->common.callbacks->channel_open_request_forwarded_tcpip_function(session,
+ msg->channel_request_open.destination,
+ msg->channel_request_open.destination_port,
+ msg->channel_request_open.originator,
+ msg->channel_request_open.originator_port,
+ session->common.callbacks->userdata);
- return SSH_OK;
+ return ssh_reply_channel_open_request(msg, channel);
}
return rc;
@@ -513,24 +520,30 @@ static int ssh_message_termination(void *s){
* @warning This function blocks until a message has been received. Betterset up
* a callback if this behavior is unwanted.
*/
-ssh_message ssh_message_get(ssh_session session) {
- ssh_message msg = NULL;
- int rc;
+ssh_message ssh_message_get(ssh_session session)
+{
+ ssh_message msg = NULL;
+ int rc;
- msg=ssh_message_pop_head(session);
- if(msg) {
- return msg;
- }
- if(session->ssh_message_list == NULL) {
- session->ssh_message_list = ssh_list_new();
- }
- rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
- ssh_message_termination, session);
- if(rc || session->session_state == SSH_SESSION_STATE_ERROR)
- return NULL;
- msg=ssh_list_pop_head(ssh_message, session->ssh_message_list);
+ msg = ssh_message_pop_head(session);
+ if (msg != NULL) {
+ return msg;
+ }
+ if (session->ssh_message_list == NULL) {
+ session->ssh_message_list = ssh_list_new();
+ if (session->ssh_message_list == NULL) {
+ ssh_set_error_oom(session);
+ return NULL;
+ }
+ }
+ rc = ssh_handle_packets_termination(session, SSH_TIMEOUT_USER,
+ ssh_message_termination, session);
+ if (rc || session->session_state == SSH_SESSION_STATE_ERROR) {
+ return NULL;
+ }
+ msg = ssh_list_pop_head(ssh_message, session->ssh_message_list);
- return msg;
+ return msg;
}
/**
@@ -587,6 +600,7 @@ void ssh_message_free(ssh_message msg){
switch(msg->type) {
case SSH_REQUEST_AUTH:
SAFE_FREE(msg->auth_request.username);
+ SAFE_FREE(msg->auth_request.sigtype);
if (msg->auth_request.password) {
explicit_bzero(msg->auth_request.password,
strlen(msg->auth_request.password));
@@ -708,8 +722,8 @@ static ssh_buffer ssh_msg_userauth_build_digest(ssh_session session,
rc = ssh_buffer_pack(buffer,
"dPbsssbsS",
- crypto->digest_len, /* session ID string */
- (size_t)crypto->digest_len, crypto->session_id,
+ crypto->session_id_len, /* session ID string */
+ crypto->session_id_len, crypto->session_id,
SSH2_MSG_USERAUTH_REQUEST, /* type */
msg->auth_request.username,
service,
@@ -768,7 +782,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
cmp = strcmp(service, "ssh-connection");
if (cmp != 0) {
- SSH_LOG(SSH_LOG_WARNING,
+ SSH_LOG(SSH_LOG_TRACE,
"Invalid service request: %s",
service);
goto end;
@@ -846,6 +860,14 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_request){
goto error;
}
msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_NONE;
+ msg->auth_request.sigtype = strdup(ssh_string_get_char(algo));
+ if (msg->auth_request.sigtype == NULL) {
+ msg->auth_request.signature_state = SSH_PUBLICKEY_STATE_ERROR;
+ SSH_STRING_FREE(algo);
+ algo = NULL;
+ goto error;
+ }
+
// has a valid signature ?
if(has_sign) {
ssh_string sig_blob = NULL;
@@ -1040,7 +1062,7 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
}
if (session->kbdint == NULL) {
- SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Got a keyboard-interactive "
+ SSH_LOG(SSH_LOG_DEBUG, "Warning: Got a keyboard-interactive "
"response but it seems we didn't send the request.");
session->kbdint = ssh_kbdint_new();
@@ -1061,10 +1083,10 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
session->kbdint->nanswers = 0;
}
- SSH_LOG(SSH_LOG_PACKET,"kbdint: %d answers",nanswers);
+ SSH_LOG(SSH_LOG_PACKET,"kbdint: %" PRIu32 " answers", nanswers);
if (nanswers > KBDINT_MAX_PROMPT) {
ssh_set_error(session, SSH_FATAL,
- "Too much answers received from client: %u (0x%.4x)",
+ "Too much answers received from client: %" PRIu32 " (0x%.4" PRIx32 ")",
nanswers, nanswers);
ssh_kbdint_free(session->kbdint);
session->kbdint = NULL;
@@ -1074,8 +1096,8 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_info_response){
if(nanswers != session->kbdint->nprompts) {
/* warn but let the application handle this case */
- SSH_LOG(SSH_LOG_PROTOCOL, "Warning: Number of prompts and answers"
- " mismatch: p=%u a=%u", session->kbdint->nprompts, nanswers);
+ SSH_LOG(SSH_LOG_DEBUG, "Warning: Number of prompts and answers"
+ " mismatch: p=%" PRIu32 " a=%" PRIu32, session->kbdint->nprompts, nanswers);
}
session->kbdint->nanswers = nanswers;
@@ -1154,8 +1176,16 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open){
ssh_set_error(session,SSH_FATAL, "Invalid state when receiving channel open request (must be authenticated)");
goto error;
}
-
- if (strcmp(type_c,"session") == 0) {
+
+ if (strcmp(type_c, "session") == 0) {
+ if (session->flags & SSH_SESSION_FLAG_NO_MORE_SESSIONS) {
+ ssh_session_set_disconnect_message(session, "No more sessions allowed!");
+ ssh_set_error(session, SSH_FATAL, "No more sessions allowed!");
+ session->session_state = SSH_SESSION_STATE_ERROR;
+ ssh_disconnect(session);
+ goto error;
+ }
+
msg->channel_request_open.type = SSH_CHANNEL_SESSION;
SAFE_FREE(type_c);
goto end;
@@ -1168,9 +1198,9 @@ SSH_PACKET_CALLBACK(ssh_packet_channel_open){
&destination_port,
&msg->channel_request_open.originator,
&originator_port);
- if (rc != SSH_OK) {
- goto error;
- }
+ if (rc != SSH_OK) {
+ goto error;
+ }
msg->channel_request_open.destination_port = (uint16_t) destination_port;
msg->channel_request_open.originator_port = (uint16_t) originator_port;
@@ -1233,7 +1263,7 @@ end:
*
* @param[in] chan The channel the request is made on.
*
- * @returns SSH_OK on success, SSH_ERROR if an error occured.
+ * @returns SSH_OK on success, SSH_ERROR if an error occurred.
*/
int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_channel chan) {
ssh_session session;
@@ -1267,7 +1297,7 @@ int ssh_message_channel_request_open_reply_accept_channel(ssh_message msg, ssh_c
}
SSH_LOG(SSH_LOG_PACKET,
- "Accepting a channel request_open for chan %d",
+ "Accepting a channel request_open for chan %" PRIu32,
chan->remote_channel);
rc = ssh_packet_send(session);
@@ -1324,7 +1354,7 @@ ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg) {
*
* @param[in] want_reply The want_reply field from the request.
*
- * @returns SSH_OK on success, SSH_ERROR if an error occured.
+ * @returns SSH_OK on success, SSH_ERROR if an error occurred.
*/
int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel, ssh_buffer packet,
const char *request, uint8_t want_reply) {
@@ -1338,7 +1368,7 @@ int ssh_message_handle_channel_request(ssh_session session, ssh_channel channel,
}
SSH_LOG(SSH_LOG_PACKET,
- "Received a %s channel_request for channel (%d:%d) (want_reply=%hhd)",
+ "Received a %s channel_request for channel (%" PRIu32 ":%" PRIu32 ") (want_reply=%hhd)",
request, channel->local_channel, channel->remote_channel, want_reply);
msg->type = SSH_REQUEST_CHANNEL;
@@ -1438,6 +1468,14 @@ error:
return SSH_ERROR;
}
+/** @internal
+ *
+ * @brief Sends a successful channel request reply
+ *
+ * @param msg A message to reply to
+ *
+ * @returns SSH_OK on success, SSH_ERROR if an error occurred.
+ */
int ssh_message_channel_request_reply_success(ssh_message msg) {
uint32_t channel;
int rc;
@@ -1450,7 +1488,7 @@ int ssh_message_channel_request_reply_success(ssh_message msg) {
channel = msg->channel_request.channel->remote_channel;
SSH_LOG(SSH_LOG_PACKET,
- "Sending a channel_request success to channel %d", channel);
+ "Sending a channel_request success to channel %" PRIu32, channel);
rc = ssh_buffer_pack(msg->session->out_buffer,
"bd",
@@ -1481,7 +1519,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
(void)type;
(void)packet;
- SSH_LOG(SSH_LOG_PROTOCOL,"Received SSH_MSG_GLOBAL_REQUEST packet");
+ SSH_LOG(SSH_LOG_DEBUG,"Received SSH_MSG_GLOBAL_REQUEST packet");
r = ssh_buffer_unpack(packet, "sb",
&request,
&want_reply);
@@ -1513,12 +1551,12 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
msg->global_request.type = SSH_GLOBAL_REQUEST_TCPIP_FORWARD;
msg->global_request.want_reply = want_reply;
- SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
+ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
msg->global_request.bind_address,
msg->global_request.bind_port);
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
- SSH_LOG(SSH_LOG_PROTOCOL, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request,
+ SSH_LOG(SSH_LOG_DEBUG, "Calling callback for SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request,
want_reply, msg->global_request.bind_address,
msg->global_request.bind_port);
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
@@ -1543,7 +1581,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
msg->global_request.type = SSH_GLOBAL_REQUEST_CANCEL_TCPIP_FORWARD;
msg->global_request.want_reply = want_reply;
- SSH_LOG(SSH_LOG_PROTOCOL, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
+ SSH_LOG(SSH_LOG_DEBUG, "Received SSH_MSG_GLOBAL_REQUEST %s %d %s:%d", request, want_reply,
msg->global_request.bind_address,
msg->global_request.bind_port);
@@ -1557,14 +1595,23 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
} else if(strcmp(request, "keepalive@openssh.com") == 0) {
msg->global_request.type = SSH_GLOBAL_REQUEST_KEEPALIVE;
msg->global_request.want_reply = want_reply;
- SSH_LOG(SSH_LOG_PROTOCOL, "Received keepalive@openssh.com %d", want_reply);
+ SSH_LOG(SSH_LOG_DEBUG, "Received keepalive@openssh.com %d", want_reply);
if(ssh_callbacks_exists(session->common.callbacks, global_request_function)) {
session->common.callbacks->global_request_function(session, msg, session->common.callbacks->userdata);
} else {
ssh_message_global_request_reply_success(msg, 0);
}
+ } else if (strcmp(request, "no-more-sessions@openssh.com") == 0) {
+ msg->global_request.type = SSH_GLOBAL_REQUEST_NO_MORE_SESSIONS;
+ msg->global_request.want_reply = want_reply;
+
+ SSH_LOG(SSH_LOG_PROTOCOL, "Received no-more-sessions@openssh.com %d", want_reply);
+
+ ssh_message_global_request_reply_success(msg, 0);
+
+ session->flags |= SSH_SESSION_FLAG_NO_MORE_SESSIONS;
} else {
- SSH_LOG(SSH_LOG_PROTOCOL, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, "
+ SSH_LOG(SSH_LOG_DEBUG, "UNKNOWN SSH_MSG_GLOBAL_REQUEST %s, "
"want_reply = %d", request, want_reply);
goto reply_with_failure;
}
@@ -1597,7 +1644,7 @@ reply_with_failure:
error:
SAFE_FREE(msg);
SAFE_FREE(request);
- SSH_LOG(SSH_LOG_WARNING, "Invalid SSH_MSG_GLOBAL_REQUEST packet");
+ SSH_LOG(SSH_LOG_TRACE, "Invalid SSH_MSG_GLOBAL_REQUEST packet");
return rc;
}