messages.c   messages.c 
/* /*
* messages.c - message parsion for the server * messages.c - message parsion for the server
* *
* This file is part of the SSH Library * This file is part of the SSH Library
* *
* Copyright (c) 2003-2005 by Aris Adamantiadis * Copyright (c) 2003-2009 by Aris Adamantiadis
* *
* The SSH Library is free software; you can redistribute it and/or modify * The SSH Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by * it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your * the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version. * option) any later version.
* *
* The SSH Library is distributed in the hope that it will be useful, but * The SSH Library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILI TY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details. * License for more details.
skipping to change at line 44 skipping to change at line 44
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifndef _WIN32 #ifndef _WIN32
#include <arpa/inet.h> #include <arpa/inet.h>
#endif #endif
#include "libssh/libssh.h" #include "libssh/libssh.h"
#include "libssh/priv.h" #include "libssh/priv.h"
#include "libssh/server.h"
#include "libssh/ssh2.h" #include "libssh/ssh2.h"
#include "libssh/buffer.h"
#include "libssh/packet.h"
#include "libssh/channels.h"
#include "libssh/session.h"
#include "libssh/misc.h"
#include "libssh/keys.h"
#include "libssh/dh.h"
#include "libssh/messages.h"
static SSH_MESSAGE *message_new(SSH_SESSION *session){ static ssh_message message_new(ssh_session session){
SSH_MESSAGE *msg = session->ssh_message; ssh_message msg = malloc(sizeof(struct ssh_message_struct));
if (msg == NULL) { if (msg == NULL) {
msg = malloc(sizeof(SSH_MESSAGE)); return NULL;
if (msg == NULL) {
return NULL;
}
session->ssh_message = msg;
} }
memset(msg, 0, sizeof(*msg)); ZERO_STRUCTP(msg);
msg->session = session; msg->session = session;
return msg; return msg;
} }
static int handle_service_request(SSH_SESSION *session) { static ssh_message handle_service_request(ssh_session session) {
STRING *service = NULL; ssh_string service = NULL;
char *service_c = NULL; char *service_c = NULL;
int rc = -1; ssh_message msg=NULL;
enter_function(); enter_function();
service = buffer_get_ssh_string(session->in_buffer); service = buffer_get_ssh_string(session->in_buffer);
if (service == NULL) { if (service == NULL) {
ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST pack et"); ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST pack et");
leave_function(); goto error;
return -1;
} }
service_c = string_to_char(service); service_c = string_to_char(service);
if (service_c == NULL) { if (service_c == NULL) {
goto error; goto error;
} }
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Sending a SERVICE_ACCEPT for service %s", service_c); "Received a SERVICE_REQUEST for service %s", service_c);
SAFE_FREE(service_c); msg=message_new(session);
if(!msg){
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) { SAFE_FREE(service_c);
goto error;
}
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
goto error; goto error;
} }
if (packet_send(session) != SSH_OK) { msg->type=SSH_REQUEST_SERVICE;
goto error; msg->service_request.service=service_c;
} error:
rc = 0;
error:
string_free(service); string_free(service);
leave_function(); leave_function();
return msg;
return rc;
} }
static int handle_unimplemented(SSH_SESSION *session) { static int handle_unimplemented(ssh_session session) {
if (buffer_add_u32(session->out_buffer, htonl(session->recv_seq - 1)) < 0 ) { if (buffer_add_u32(session->out_buffer, htonl(session->recv_seq - 1)) < 0 ) {
return -1; return -1;
} }
if (packet_send(session) != SSH_OK) { if (packet_send(session) != SSH_OK) {
return -1; return -1;
} }
return 0; return 0;
} }
static SSH_MESSAGE *handle_userauth_request(SSH_SESSION *session){ static ssh_message handle_userauth_request(ssh_session session){
STRING *user = NULL; ssh_string user = NULL;
STRING *service = NULL; ssh_string service = NULL;
STRING *method = NULL; ssh_string method = NULL;
SSH_MESSAGE *msg = NULL; ssh_message msg = NULL;
char *service_c = NULL; char *service_c = NULL;
char *method_c = NULL; char *method_c = NULL;
uint32_t method_size = 0;
enter_function(); enter_function();
msg = message_new(session); msg = message_new(session);
if (msg == NULL) { if (msg == NULL) {
return NULL; return NULL;
} }
user = buffer_get_ssh_string(session->in_buffer); user = buffer_get_ssh_string(session->in_buffer);
if (user == NULL) { if (user == NULL) {
skipping to change at line 144 skipping to change at line 137
} }
service = buffer_get_ssh_string(session->in_buffer); service = buffer_get_ssh_string(session->in_buffer);
if (service == NULL) { if (service == NULL) {
goto error; goto error;
} }
method = buffer_get_ssh_string(session->in_buffer); method = buffer_get_ssh_string(session->in_buffer);
if (method == NULL) { if (method == NULL) {
goto error; goto error;
} }
msg->type = SSH_AUTH_REQUEST; msg->type = SSH_REQUEST_AUTH;
msg->auth_request.username = string_to_char(user); msg->auth_request.username = string_to_char(user);
if (msg->auth_request.username == NULL) { if (msg->auth_request.username == NULL) {
goto error; goto error;
} }
string_free(user); string_free(user);
user = NULL;
service_c = string_to_char(service); service_c = string_to_char(service);
if (service_c == NULL) { if (service_c == NULL) {
goto error; goto error;
} }
method_c = string_to_char(method); method_c = string_to_char(method);
if (method_c == NULL) { if (method_c == NULL) {
goto error; goto error;
} }
method_size = string_len(method);
string_free(service); string_free(service);
service = NULL;
string_free(method); string_free(method);
method = NULL;
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Auth request for service %s, method %s for user '%s'", "Auth request for service %s, method %s for user '%s'",
service_c, method_c, service_c, method_c,
msg->auth_request.username); msg->auth_request.username);
SAFE_FREE(service_c); if (strncmp(method_c, "none", method_size) == 0) {
msg->auth_request.method = SSH_AUTH_METHOD_NONE;
if (strcmp(method_c, "none") == 0) { SAFE_FREE(service_c);
msg->auth_request.method = SSH_AUTH_NONE;
SAFE_FREE(method_c); SAFE_FREE(method_c);
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(method_c, "password") == 0) { if (strncmp(method_c, "password", method_size) == 0) {
STRING *pass = NULL; ssh_string pass = NULL;
u8 tmp; uint8_t tmp;
msg->auth_request.method = SSH_AUTH_PASSWORD; msg->auth_request.method = SSH_AUTH_METHOD_PASSWORD;
SAFE_FREE(service_c);
SAFE_FREE(method_c); SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &tmp); buffer_get_u8(session->in_buffer, &tmp);
pass = buffer_get_ssh_string(session->in_buffer); pass = buffer_get_ssh_string(session->in_buffer);
if (pass == NULL) { if (pass == NULL) {
goto error; goto error;
} }
msg->auth_request.password = string_to_char(pass); msg->auth_request.password = string_to_char(pass);
string_burn(pass);
string_free(pass); string_free(pass);
pass = NULL;
if (msg->auth_request.password == NULL) { if (msg->auth_request.password == NULL) {
goto error; goto error;
} }
leave_function(); leave_function();
return msg; return msg;
} }
msg->auth_request.method = SSH_AUTH_UNKNOWN; if (strncmp(method_c, "publickey", method_size) == 0) {
ssh_string algo = NULL;
ssh_string publickey = NULL;
uint8_t has_sign;
msg->auth_request.method = SSH_AUTH_METHOD_PUBLICKEY;
SAFE_FREE(method_c);
buffer_get_u8(session->in_buffer, &has_sign);
algo = buffer_get_ssh_string(session->in_buffer);
if (algo == NULL) {
goto error;
}
publickey = buffer_get_ssh_string(session->in_buffer);
if (publickey == NULL) {
string_free(algo);
algo = NULL;
goto error;
}
msg->auth_request.public_key = publickey_from_string(session, publickey
);
string_free(algo);
algo = NULL;
string_free(publickey);
publickey = NULL;
if (msg->auth_request.public_key == NULL) {
goto error;
}
msg->auth_request.signature_state = 0;
// has a valid signature ?
if(has_sign) {
SIGNATURE *signature = NULL;
ssh_public_key public_key = msg->auth_request.public_key;
ssh_string sign = NULL;
ssh_buffer digest = NULL;
sign = buffer_get_ssh_string(session->in_buffer);
if(sign == NULL) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature packet from pee
r");
msg->auth_request.signature_state = -2;
goto error;
}
signature = signature_from_string(session, sign, public_key,
public_key->type);
digest = ssh_userauth_build_digest(session, msg, service_c);
if ((digest == NULL || signature == NULL) ||
(digest != NULL && signature != NULL &&
sig_verify(session, public_key, signature,
buffer_get(digest), buffer_get_len(digest)) < 0)) {
ssh_log(session, SSH_LOG_PACKET, "Invalid signature from peer");
string_free(sign);
sign = NULL;
buffer_free(digest);
digest = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = -1;
goto error;
}
else
ssh_log(session, SSH_LOG_PACKET, "Valid signature received");
buffer_free(digest);
digest = NULL;
string_free(sign);
sign = NULL;
signature_free(signature);
signature = NULL;
msg->auth_request.signature_state = 1;
}
SAFE_FREE(service_c);
leave_function();
return msg;
}
msg->auth_request.method = SSH_AUTH_METHOD_UNKNOWN;
SAFE_FREE(method_c); SAFE_FREE(method_c);
leave_function(); leave_function();
return msg; return msg;
error: error:
string_free(user); string_free(user);
string_free(service); string_free(service);
string_free(method); string_free(method);
SAFE_FREE(method_c); SAFE_FREE(method_c);
SAFE_FREE(service_c); SAFE_FREE(service_c);
ssh_message_free(msg); ssh_message_free(msg);
leave_function(); leave_function();
return NULL; return NULL;
} }
char *ssh_message_auth_user(SSH_MESSAGE *msg) { static ssh_message handle_channel_request_open(ssh_session session) {
if (msg == NULL) { ssh_message msg = NULL;
return NULL; ssh_string type = NULL, originator = NULL, destination = NULL;
}
return msg->auth_request.username;
}
char *ssh_message_auth_password(SSH_MESSAGE *msg){
if (msg == NULL) {
return NULL;
}
return msg->auth_request.password;
}
int ssh_message_auth_set_methods(SSH_MESSAGE *msg, int methods) {
if (msg == NULL || msg->session == NULL) {
return -1;
}
msg->session->auth_methods = methods;
return 0;
}
static int ssh_message_auth_reply_default(SSH_MESSAGE *msg,int partial) {
SSH_SESSION *session = msg->session;
char methods_c[128] = {0};
STRING *methods = NULL;
int rc = SSH_ERROR;
enter_function();
if (buffer_add_u8(session->out_buffer, SSH2_MSG_USERAUTH_FAILURE) < 0) {
return rc;
}
if (session->auth_methods == 0) {
session->auth_methods = SSH_AUTH_PUBLICKEY | SSH_AUTH_PASSWORD;
}
if (session->auth_methods & SSH_AUTH_PUBLICKEY) {
strcat(methods_c, "publickey,");
}
if (session->auth_methods & SSH_AUTH_KEYBINT) {
strcat(methods_c, "keyboard-interactive,");
}
if (session->auth_methods & SSH_AUTH_PASSWORD) {
strcat(methods_c, "password,");
}
if (session->auth_methods & SSH_AUTH_HOSTBASED) {
strcat(methods_c, "hostbased,");
}
/* Strip the comma. */
methods_c[strlen(methods_c) - 1] = '\0'; // strip the comma. We are sure
there is at
ssh_log(session, SSH_LOG_PACKET,
"Sending a auth failure. methods that can continue: %s", methods_c);
methods = string_from_char(methods_c);
if (methods == NULL) {
goto error;
}
if (buffer_add_ssh_string(msg->session->out_buffer, methods) < 0) {
goto error;
}
if (partial) {
if (buffer_add_u8(session->out_buffer, 1) < 0) {
goto error;
}
} else {
if (buffer_add_u8(session->out_buffer, 0) < 0) {
goto error;
}
}
rc = packet_send(msg->session);
error:
string_free(methods);
leave_function();
return rc;
}
int ssh_message_auth_reply_success(SSH_MESSAGE *msg, int partial) {
if (msg == NULL) {
return SSH_ERROR;
}
if (partial) {
return ssh_message_auth_reply_default(msg, partial);
}
if (buffer_add_u8(msg->session->out_buffer,SSH2_MSG_USERAUTH_SUCCESS) < 0
) {
return SSH_ERROR;
}
return packet_send(msg->session);
}
static SSH_MESSAGE *handle_channel_request_open(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
STRING *type = NULL;
char *type_c = NULL; char *type_c = NULL;
u32 sender, window, packet; uint32_t sender, window, packet, originator_port, destination_port;
enter_function(); enter_function();
msg = message_new(session); msg = message_new(session);
if (msg == NULL) { if (msg == NULL) {
ssh_set_error_oom(session);
leave_function(); leave_function();
return NULL; return NULL;
} }
msg->type = SSH_CHANNEL_REQUEST_OPEN; msg->type = SSH_REQUEST_CHANNEL_OPEN;
type = buffer_get_ssh_string(session->in_buffer); type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) { if (type == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
type_c = string_to_char(type); type_c = string_to_char(type);
if (type_c == NULL) { if (type_c == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Clients wants to open a %s channel", type_c); "Clients wants to open a %s channel", type_c);
string_free(type); string_free(type);
buffer_get_u32(session->in_buffer, &sender); buffer_get_u32(session->in_buffer, &sender);
buffer_get_u32(session->in_buffer, &window); buffer_get_u32(session->in_buffer, &window);
buffer_get_u32(session->in_buffer, &packet); buffer_get_u32(session->in_buffer, &packet);
skipping to change at line 363 skipping to change at line 338
msg->channel_request_open.window = ntohl(window); msg->channel_request_open.window = ntohl(window);
msg->channel_request_open.packet_size = ntohl(packet); msg->channel_request_open.packet_size = ntohl(packet);
if (strcmp(type_c,"session") == 0) { if (strcmp(type_c,"session") == 0) {
msg->channel_request_open.type = SSH_CHANNEL_SESSION; msg->channel_request_open.type = SSH_CHANNEL_SESSION;
SAFE_FREE(type_c); SAFE_FREE(type_c);
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(type_c,"direct-tcpip") == 0) {
destination = buffer_get_ssh_string(session->in_buffer);
if (destination == NULL) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
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) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
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) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.destination = string_to_char(type);
if (msg->channel_request_open.destination == NULL) {
ssh_set_error_oom(session);
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) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
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) {
ssh_set_error_oom(session);
goto error;
}
msg->channel_request_open.originator = string_to_char(type);
if (msg->channel_request_open.originator == NULL) {
ssh_set_error_oom(session);
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);
leave_function(); leave_function();
return msg; return msg;
error: error:
string_free(type); string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
ssh_message_free(msg); ssh_message_free(msg);
leave_function(); leave_function();
return NULL; return NULL;
} }
CHANNEL *ssh_message_channel_request_open_reply_accept(SSH_MESSAGE *msg) { ssh_channel ssh_message_channel_request_open_reply_accept(ssh_message msg)
SSH_SESSION *session = msg->session; {
CHANNEL *chan = NULL; ssh_session session = msg->session;
ssh_channel chan = NULL;
enter_function(); enter_function();
if (msg == NULL) { if (msg == NULL) {
leave_function(); leave_function();
return NULL; return NULL;
} }
chan = channel_new(session); chan = channel_new(session);
if (chan == NULL) { if (chan == NULL) {
skipping to change at line 434 skipping to change at line 510
leave_function(); leave_function();
return chan; return chan;
error: error:
channel_free(chan); channel_free(chan);
leave_function(); leave_function();
return NULL; return NULL;
} }
static int ssh_message_channel_request_open_reply_default(SSH_MESSAGE *msg) static ssh_message handle_channel_request(ssh_session session) {
{ ssh_message msg = NULL;
ssh_log(msg->session, SSH_LOG_FUNCTIONS, "Refusing a channel"); ssh_string type = NULL;
if (buffer_add_u8(msg->session->out_buffer
, SSH2_MSG_CHANNEL_OPEN_FAILURE) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(msg->channel_request_open.sender)) < 0) {
goto error;
}
if (buffer_add_u32(msg->session->out_buffer,
htonl(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED)) < 0) {
goto error;
}
/* reason is an empty string */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
/* language too */
if (buffer_add_u32(msg->session->out_buffer, 0) < 0) {
goto error;
}
return packet_send(msg->session);
error:
return SSH_ERROR;
}
static SSH_MESSAGE *handle_channel_request(SSH_SESSION *session) {
SSH_MESSAGE *msg = NULL;
STRING *type = NULL;
char *type_c = NULL; char *type_c = NULL;
u32 channel; uint32_t channel;
u8 want_reply; uint8_t want_reply;
enter_function(); enter_function();
msg = message_new(session); msg = message_new(session);
if (msg == NULL) { if (msg == NULL) {
ssh_set_error_oom(session);
return NULL; return NULL;
} }
buffer_get_u32(session->in_buffer, &channel); buffer_get_u32(session->in_buffer, &channel);
channel = ntohl(channel); channel = ntohl(channel);
type = buffer_get_ssh_string(session->in_buffer); type = buffer_get_ssh_string(session->in_buffer);
if (type == NULL) { if (type == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
type_c = string_to_char(type); type_c = string_to_char(type);
if (type_c == NULL) { if (type_c == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
string_free(type); string_free(type);
buffer_get_u8(session->in_buffer,&want_reply); buffer_get_u8(session->in_buffer,&want_reply);
ssh_log(session, SSH_LOG_PACKET, ssh_log(session, SSH_LOG_PACKET,
"Received a %s channel_request for channel %d (want_reply=%hhd)", "Received a %s channel_request for channel %d (want_reply=%hhd)",
type_c, channel, want_reply); type_c, channel, want_reply);
msg->type = SSH_CHANNEL_REQUEST; msg->type = SSH_REQUEST_CHANNEL;
msg->channel_request.channel = ssh_channel_from_local(session, channel); msg->channel_request.channel = ssh_channel_from_local(session, channel);
if (msg->channel_request.channel == NULL) {
ssh_set_error(session, SSH_FATAL, "There are no channels with the id %u
.",
channel);
goto error;
}
msg->channel_request.want_reply = want_reply; msg->channel_request.want_reply = want_reply;
if (strcmp(type_c, "pty-req") == 0) { if (strcmp(type_c, "pty-req") == 0) {
STRING *term = NULL; ssh_string term = NULL;
char *term_c = NULL; char *term_c = NULL;
SAFE_FREE(type_c); SAFE_FREE(type_c);
term = buffer_get_ssh_string(session->in_buffer); term = buffer_get_ssh_string(session->in_buffer);
if (term == NULL) { if (term == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
term_c = string_to_char(term); term_c = string_to_char(term);
if (term_c == NULL) { if (term_c == NULL) {
ssh_set_error_oom(session);
string_free(term); string_free(term);
goto error; goto error;
} }
string_free(term); string_free(term);
msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY; msg->channel_request.type = SSH_CHANNEL_REQUEST_PTY;
msg->channel_request.TERM = term_c; msg->channel_request.TERM = term_c;
buffer_get_u32(session->in_buffer, &msg->channel_request.width); 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.height);
skipping to change at line 538 skipping to change at line 595
msg->channel_request.modes = buffer_get_ssh_string(session->in_buffer); msg->channel_request.modes = buffer_get_ssh_string(session->in_buffer);
if (msg->channel_request.modes == NULL) { if (msg->channel_request.modes == NULL) {
SAFE_FREE(term_c); SAFE_FREE(term_c);
goto error; goto error;
} }
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(type_c, "window-change") == 0) {
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) {
STRING *subsys = NULL; ssh_string subsys = NULL;
char *subsys_c = NULL; char *subsys_c = NULL;
SAFE_FREE(type_c); SAFE_FREE(type_c);
subsys = buffer_get_ssh_string(session->in_buffer); subsys = buffer_get_ssh_string(session->in_buffer);
if (subsys == NULL) { if (subsys == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
subsys_c = string_to_char(subsys); subsys_c = string_to_char(subsys);
if (subsys_c == NULL) { if (subsys_c == NULL) {
ssh_set_error_oom(session);
string_free(subsys); string_free(subsys);
goto error; goto error;
} }
string_free(subsys); string_free(subsys);
msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM; msg->channel_request.type = SSH_CHANNEL_REQUEST_SUBSYSTEM;
msg->channel_request.subsystem = subsys_c; msg->channel_request.subsystem = subsys_c;
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(type_c, "shell") == 0) { if (strcmp(type_c, "shell") == 0) {
SAFE_FREE(type_c); SAFE_FREE(type_c);
msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL; msg->channel_request.type = SSH_CHANNEL_REQUEST_SHELL;
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(type_c, "exec") == 0) { if (strcmp(type_c, "exec") == 0) {
STRING *cmd = NULL; ssh_string cmd = NULL;
SAFE_FREE(type_c); SAFE_FREE(type_c);
cmd = buffer_get_ssh_string(session->in_buffer); cmd = buffer_get_ssh_string(session->in_buffer);
if (cmd == NULL) { if (cmd == NULL) {
ssh_set_error_oom(session);
goto error; goto error;
} }
msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC; msg->channel_request.type = SSH_CHANNEL_REQUEST_EXEC;
msg->channel_request.command = string_to_char(cmd); msg->channel_request.command = string_to_char(cmd);
if (msg->channel_request.command == NULL) { if (msg->channel_request.command == NULL) {
string_free(cmd); string_free(cmd);
goto error; goto error;
} }
string_free(cmd); string_free(cmd);
leave_function(); leave_function();
return msg; return msg;
} }
if (strcmp(type_c, "env") == 0) {
ssh_string name = NULL;
ssh_string value = NULL;
SAFE_FREE(type_c);
name = buffer_get_ssh_string(session->in_buffer);
if (name == NULL) {
ssh_set_error_oom(session);
goto error;
}
value = buffer_get_ssh_string(session->in_buffer);
if (value == NULL) {
ssh_set_error_oom(session);
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);
leave_function(); leave_function();
return msg; return msg;
error: error:
string_free(type); string_free(type);
SAFE_FREE(type_c); SAFE_FREE(type_c);
ssh_message_free(msg); ssh_message_free(msg);
leave_function(); leave_function();
return NULL; return NULL;
} }
char *ssh_message_channel_request_subsystem(SSH_MESSAGE *msg){ int ssh_message_channel_request_reply_success(ssh_message msg) {
return msg->channel_request.subsystem; uint32_t channel;
}
int ssh_message_channel_request_reply_success(SSH_MESSAGE *msg) {
u32 channel;
if (msg == NULL) { if (msg == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
if (msg->channel_request.want_reply) { if (msg->channel_request.want_reply) {
channel = msg->channel_request.channel->remote_channel; channel = msg->channel_request.channel->remote_channel;
ssh_log(msg->session, SSH_LOG_PACKET, ssh_log(msg->session, SSH_LOG_PACKET,
"Sending a channel_request success to channel %d", channel); "Sending a channel_request success to channel %d", channel);
skipping to change at line 638 skipping to change at line 748
return packet_send(msg->session); return packet_send(msg->session);
} }
ssh_log(msg->session, SSH_LOG_PACKET, ssh_log(msg->session, SSH_LOG_PACKET,
"The client doesn't want to know the request succeeded"); "The client doesn't want to know the request succeeded");
return SSH_OK; return SSH_OK;
} }
static int ssh_message_channel_request_reply_default(SSH_MESSAGE *msg) { ssh_message ssh_message_retrieve(ssh_session session, uint32_t packettype){
u32 channel; ssh_message msg=NULL;
enter_function();
if (msg->channel_request.want_reply) { switch(packettype) {
channel = msg->channel_request.channel->remote_channel; case SSH2_MSG_SERVICE_REQUEST:
msg=handle_service_request(session);
ssh_log(msg->session, SSH_LOG_PACKET, break;
"Sending a default channel_request denied to channel %d", channel); case SSH2_MSG_USERAUTH_REQUEST:
msg = handle_userauth_request(session);
if (buffer_add_u8(msg->session->out_buffer, SSH2_MSG_CHANNEL_FAILURE) < break;
0) { case SSH2_MSG_CHANNEL_OPEN:
return SSH_ERROR; msg = handle_channel_request_open(session);
} break;
if (buffer_add_u32(msg->session->out_buffer, htonl(channel)) < 0) { case SSH2_MSG_CHANNEL_REQUEST:
return SSH_ERROR; msg = handle_channel_request(session);
} break;
default:
return packet_send(msg->session); if (handle_unimplemented(session) == 0) {
ssh_set_error(session, SSH_FATAL,
"Unhandled message %d\n", session->in_packet.type);
}
} }
leave_function();
ssh_log(msg->session, SSH_LOG_PACKET, return msg;
"The client doesn't want to know the request failed!");
return SSH_OK;
} }
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session) { /* \brief blocking message retrieval
SSH_MESSAGE *msg = NULL; * \bug does anything that is not a message, like a channel read/write
*/
ssh_message ssh_message_get(ssh_session session) {
ssh_message msg = NULL;
enter_function(); enter_function();
do { do {
if ((packet_read(session) != SSH_OK) || if ((packet_read(session) != SSH_OK) ||
(packet_translate(session) != SSH_OK)) { (packet_translate(session) != SSH_OK)) {
goto error; leave_function();
} return NULL;
switch(session->in_packet.type) {
case SSH2_MSG_SERVICE_REQUEST:
if (handle_service_request(session) < 0) {
goto error;
}
break;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
break;
case SSH2_MSG_USERAUTH_REQUEST:
msg = handle_userauth_request(session);
leave_function();
return msg;
case SSH2_MSG_CHANNEL_OPEN:
msg = handle_channel_request_open(session);
leave_function();
return msg;
case SSH2_MSG_CHANNEL_REQUEST:
msg = handle_channel_request(session);
leave_function();
return msg;
default:
if (handle_unimplemented(session) == 0) {
ssh_set_error(session, SSH_FATAL,
"Unhandled message %d\n", session->in_packet.type);
}
goto error;
} }
} while(1); } while(session->in_packet.type==SSH2_MSG_IGNORE || session->in_packet.ty
pe==SSH2_MSG_DEBUG);
error: msg=ssh_message_retrieve(session,session->in_packet.type);
leave_function(); leave_function();
return NULL; return msg;
} }
int ssh_message_type(SSH_MESSAGE *msg) { int ssh_message_type(ssh_message msg) {
if (msg == NULL) { if (msg == NULL) {
return -1; return -1;
} }
return msg->type; return msg->type;
} }
int ssh_message_subtype(SSH_MESSAGE *msg) { int ssh_message_subtype(ssh_message msg) {
if (msg == NULL) { if (msg == NULL) {
return -1; return -1;
} }
switch(msg->type) { switch(msg->type) {
case SSH_AUTH_REQUEST: case SSH_REQUEST_AUTH:
return msg->auth_request.method; return msg->auth_request.method;
case SSH_CHANNEL_REQUEST_OPEN: case SSH_REQUEST_CHANNEL_OPEN:
return msg->channel_request_open.type; return msg->channel_request_open.type;
case SSH_CHANNEL_REQUEST: case SSH_REQUEST_CHANNEL:
return msg->channel_request.type; return msg->channel_request.type;
} }
return -1; return -1;
} }
int ssh_message_reply_default(SSH_MESSAGE *msg) { void ssh_message_free(ssh_message msg){
if (msg == NULL) {
return -1;
}
switch(msg->type) {
case SSH_AUTH_REQUEST:
return ssh_message_auth_reply_default(msg, 0);
case SSH_CHANNEL_REQUEST_OPEN:
return ssh_message_channel_request_open_reply_default(msg);
case SSH_CHANNEL_REQUEST:
return ssh_message_channel_request_reply_default(msg);
default:
ssh_log(msg->session, SSH_LOG_PACKET,
"Don't know what to default reply to %d type",
msg->type);
break;
}
return -1;
}
void ssh_message_free(SSH_MESSAGE *msg){
if (msg == NULL) { if (msg == NULL) {
return; return;
} }
switch(msg->type) { switch(msg->type) {
case SSH_AUTH_REQUEST: case SSH_REQUEST_AUTH:
SAFE_FREE(msg->auth_request.username); SAFE_FREE(msg->auth_request.username);
if (msg->auth_request.password) { if (msg->auth_request.password) {
memset(msg->auth_request.password, 0, memset(msg->auth_request.password, 0,
strlen(msg->auth_request.password)); strlen(msg->auth_request.password));
SAFE_FREE(msg->auth_request.password); SAFE_FREE(msg->auth_request.password);
} }
publickey_free(msg->auth_request.public_key);
break; break;
case SSH_CHANNEL_REQUEST_OPEN: case SSH_REQUEST_CHANNEL_OPEN:
SAFE_FREE(msg->channel_request_open.originator); SAFE_FREE(msg->channel_request_open.originator);
SAFE_FREE(msg->channel_request_open.destination); SAFE_FREE(msg->channel_request_open.destination);
break; break;
case SSH_CHANNEL_REQUEST: case SSH_REQUEST_CHANNEL:
SAFE_FREE(msg->channel_request.TERM); SAFE_FREE(msg->channel_request.TERM);
SAFE_FREE(msg->channel_request.modes); SAFE_FREE(msg->channel_request.modes);
SAFE_FREE(msg->channel_request.var_name); SAFE_FREE(msg->channel_request.var_name);
SAFE_FREE(msg->channel_request.var_value); SAFE_FREE(msg->channel_request.var_value);
SAFE_FREE(msg->channel_request.command); SAFE_FREE(msg->channel_request.command);
SAFE_FREE(msg->channel_request.subsystem); SAFE_FREE(msg->channel_request.subsystem);
break; break;
case SSH_REQUEST_SERVICE:
SAFE_FREE(msg->service_request.service);
break;
} }
ZERO_STRUCTP(msg); ZERO_STRUCTP(msg);
SAFE_FREE(msg); SAFE_FREE(msg);
} }
/** \internal
* \brief handle various SSH request messages and stack them for callback
* \param session SSH session
* \param type packet type
* \returns nothing
*/
void message_handle(ssh_session session, uint32_t type){
ssh_message msg=ssh_message_retrieve(session,type);
ssh_log(session,SSH_LOG_PROTOCOL,"Stacking message from packet type %d",t
ype);
if(msg){
if(!session->ssh_message_list){
session->ssh_message_list=ssh_list_new();
}
ssh_list_add(session->ssh_message_list,msg);
}
}
/** /**
* @} * @}
*/ */
/* vim: set ts=2 sw=2 et cindent: */ /* vim: set ts=2 sw=2 et cindent: */
 End of changes. 75 change blocks. 
302 lines changed or deleted 383 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/