mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-09 09:54:25 +09:00
ssh_message_retrieve + memoryleak fixed in ssh_message_free
ssh_message_retrieve parses a specific SSH message and returns a pointer to it. Hacked ssh_message_get to use it. This is the first step to have asynchronous ssh messages callbacks.
This commit is contained in:
@@ -427,6 +427,10 @@ struct ssh_channel_request_open {
|
|||||||
u16 destination_port;
|
u16 destination_port;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ssh_service_request {
|
||||||
|
char *service;
|
||||||
|
};
|
||||||
|
|
||||||
struct ssh_channel_request {
|
struct ssh_channel_request {
|
||||||
int type;
|
int type;
|
||||||
CHANNEL *channel;
|
CHANNEL *channel;
|
||||||
@@ -454,6 +458,7 @@ struct ssh_message {
|
|||||||
struct ssh_auth_request auth_request;
|
struct ssh_auth_request auth_request;
|
||||||
struct ssh_channel_request_open channel_request_open;
|
struct ssh_channel_request_open channel_request_open;
|
||||||
struct ssh_channel_request channel_request;
|
struct ssh_channel_request channel_request;
|
||||||
|
struct ssh_service_request service_request;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ int ssh_accept(SSH_SESSION *session);
|
|||||||
#define SSH_AUTH_REQUEST 1
|
#define SSH_AUTH_REQUEST 1
|
||||||
#define SSH_CHANNEL_REQUEST_OPEN 2
|
#define SSH_CHANNEL_REQUEST_OPEN 2
|
||||||
#define SSH_CHANNEL_REQUEST 3
|
#define SSH_CHANNEL_REQUEST 3
|
||||||
|
#define SSH_SERVICE_REQUEST 4
|
||||||
|
|
||||||
#define SSH_AUTH_NONE (1<<0)
|
#define SSH_AUTH_NONE (1<<0)
|
||||||
#define SSH_AUTH_PASSWORD (1<<1)
|
#define SSH_AUTH_PASSWORD (1<<1)
|
||||||
@@ -149,6 +150,7 @@ int ssh_accept(SSH_SESSION *session);
|
|||||||
|
|
||||||
typedef struct ssh_message SSH_MESSAGE;
|
typedef struct ssh_message SSH_MESSAGE;
|
||||||
|
|
||||||
|
SSH_MESSAGE *ssh_message_retrieve(SSH_SESSION *session, u32 packettype);
|
||||||
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session);
|
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session);
|
||||||
int ssh_message_type(SSH_MESSAGE *msg);
|
int ssh_message_type(SSH_MESSAGE *msg);
|
||||||
int ssh_message_subtype(SSH_MESSAGE *msg);
|
int ssh_message_subtype(SSH_MESSAGE *msg);
|
||||||
@@ -168,6 +170,10 @@ char *ssh_message_channel_request_pty_term(SSH_MESSAGE *msg);
|
|||||||
char *ssh_message_channel_request_subsystem(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);
|
||||||
|
char *ssh_message_service_service(SSH_MESSAGE *msg);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
@@ -61,45 +61,66 @@ static SSH_MESSAGE *message_new(SSH_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;
|
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 packet");
|
ssh_set_error(session, SSH_FATAL, "Invalid SSH_MSG_SERVICE_REQUEST packet");
|
||||||
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;
|
goto error;
|
||||||
}
|
}
|
||||||
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
|
msg->type=SSH_SERVICE_REQUEST;
|
||||||
goto error;
|
msg->service_request.service=service_c;
|
||||||
}
|
error:
|
||||||
if (packet_send(session) != SSH_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
error:
|
|
||||||
string_free(service);
|
|
||||||
leave_function();
|
leave_function();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
static int ssh_message_service_request_reply_default(SSH_MESSAGE *msg) {
|
||||||
|
/* The only return code accepted by specifications are success or disconnect */
|
||||||
|
return ssh_message_service_reply_success(msg);
|
||||||
|
}
|
||||||
|
int ssh_message_service_reply_success(SSH_MESSAGE *msg) {
|
||||||
|
struct string_struct *service;
|
||||||
|
SSH_SESSION *session=msg->session;
|
||||||
|
if (msg == NULL) {
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
ssh_log(session, SSH_LOG_PACKET,
|
||||||
|
"Sending a SERVICE_ACCEPT for service %s", msg->service_request.service);
|
||||||
|
if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_ACCEPT) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
service=string_from_char(msg->service_request.service);
|
||||||
|
if (buffer_add_ssh_string(session->out_buffer, service) < 0) {
|
||||||
|
string_free(service);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
string_free(service);
|
||||||
|
return packet_send(msg->session);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ssh_message_service_service(SSH_MESSAGE *msg){
|
||||||
|
if (msg == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return msg->service_request.service;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_unimplemented(SSH_SESSION *session) {
|
static int handle_unimplemented(SSH_SESSION *session) {
|
||||||
@@ -661,52 +682,48 @@ static int ssh_message_channel_request_reply_default(SSH_MESSAGE *msg) {
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSH_MESSAGE *ssh_message_retrieve(SSH_SESSION *session, u32 packettype){
|
||||||
|
SSH_MESSAGE *msg=NULL;
|
||||||
|
enter_function();
|
||||||
|
switch(packettype) {
|
||||||
|
case SSH2_MSG_SERVICE_REQUEST:
|
||||||
|
msg=handle_service_request(session);
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_USERAUTH_REQUEST:
|
||||||
|
msg = handle_userauth_request(session);
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_OPEN:
|
||||||
|
msg = handle_channel_request_open(session);
|
||||||
|
break;
|
||||||
|
case SSH2_MSG_CHANNEL_REQUEST:
|
||||||
|
msg = handle_channel_request(session);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (handle_unimplemented(session) == 0) {
|
||||||
|
ssh_set_error(session, SSH_FATAL,
|
||||||
|
"Unhandled message %d\n", session->in_packet.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
leave_function();
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* \brief blocking message retrieval
|
||||||
|
* \bug does anything that is not a message, like a channel read/write
|
||||||
|
*/
|
||||||
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session) {
|
SSH_MESSAGE *ssh_message_get(SSH_SESSION *session) {
|
||||||
SSH_MESSAGE *msg = NULL;
|
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) {
|
} while(session->in_packet.type==SSH2_MSG_IGNORE || session->in_packet.type==SSH2_MSG_DEBUG);
|
||||||
case SSH2_MSG_SERVICE_REQUEST:
|
msg=ssh_message_retrieve(session,session->in_packet.type);
|
||||||
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);
|
|
||||||
|
|
||||||
error:
|
|
||||||
leave_function();
|
leave_function();
|
||||||
return NULL;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_message_type(SSH_MESSAGE *msg) {
|
int ssh_message_type(SSH_MESSAGE *msg) {
|
||||||
@@ -746,6 +763,8 @@ int ssh_message_reply_default(SSH_MESSAGE *msg) {
|
|||||||
return ssh_message_channel_request_open_reply_default(msg);
|
return ssh_message_channel_request_open_reply_default(msg);
|
||||||
case SSH_CHANNEL_REQUEST:
|
case SSH_CHANNEL_REQUEST:
|
||||||
return ssh_message_channel_request_reply_default(msg);
|
return ssh_message_channel_request_reply_default(msg);
|
||||||
|
case SSH_SERVICE_REQUEST:
|
||||||
|
return ssh_message_service_request_reply_default(msg);
|
||||||
default:
|
default:
|
||||||
ssh_log(msg->session, SSH_LOG_PACKET,
|
ssh_log(msg->session, SSH_LOG_PACKET,
|
||||||
"Don't know what to default reply to %d type",
|
"Don't know what to default reply to %d type",
|
||||||
@@ -784,6 +803,7 @@ void ssh_message_free(SSH_MESSAGE *msg){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ZERO_STRUCTP(msg);
|
ZERO_STRUCTP(msg);
|
||||||
|
SAFE_FREE(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user