diff --git a/include/libssh/priv.h b/include/libssh/priv.h index d0d0ea2d..dab9aa73 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -324,6 +324,8 @@ struct keys_struct { const char *publickey; }; +struct ssh_message; + struct ssh_session { struct error_struct error; struct socket *socket; @@ -386,7 +388,8 @@ struct ssh_session { /* auths accepted by server */ int auth_methods; int hostkeys; /* contains type of host key wanted by client, in server impl */ - struct ssh_message *ssh_message; /* ssh message */ + struct ssh_list *ssh_message_list; /* list of delayed SSH messages */ + int (*ssh_message_callback)( struct ssh_session *session,struct ssh_message *msg); int log_verbosity; /*cached copy of the option structure */ int log_indent; /* indentation level in enter_function logs */ }; @@ -737,7 +740,7 @@ const void *_ssh_list_get_head(struct ssh_list *list); * @return the first element of the list */ #define ssh_list_get_head(type, ssh_list)\ - ((type)_ssh_list_head(ssh_list)) + ((type)_ssh_list_get_head(ssh_list)) /* channels1.c */ @@ -760,6 +763,7 @@ int match_hostname(const char *host, const char *pattern, unsigned int len); /* messages.c */ void message_handle(SSH_SESSION *session, u32 type); +int ssh_execute_message_callbacks(SSH_SESSION *session); /* log.c */ diff --git a/include/libssh/server.h b/include/libssh/server.h index 495a8c8f..915edd8d 100644 --- a/include/libssh/server.h +++ b/include/libssh/server.h @@ -173,7 +173,8 @@ 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); - +void ssh_set_message_callback(SSH_SESSION *session, + int(*ssh_message_callback)(struct ssh_session *session, struct ssh_message *msg)); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/libssh/messages.c b/libssh/messages.c index 425829bb..d67f9982 100644 --- a/libssh/messages.c +++ b/libssh/messages.c @@ -3,7 +3,7 @@ * * 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 * it under the terms of the GNU Lesser General Public License as published by @@ -46,18 +46,13 @@ static SSH_MESSAGE *message_new(SSH_SESSION *session){ - SSH_MESSAGE *msg = session->ssh_message; - + SSH_MESSAGE *msg = malloc(sizeof(SSH_MESSAGE)); if (msg == NULL) { - msg = malloc(sizeof(SSH_MESSAGE)); - if (msg == NULL) { - return NULL; - } - session->ssh_message = msg; + return NULL; } + memset(msg, 0, sizeof(*msg)); msg->session = session; - return msg; } @@ -815,9 +810,48 @@ void ssh_message_free(SSH_MESSAGE *msg){ void message_handle(SSH_SESSION *session, u32 type){ SSH_MESSAGE *msg=ssh_message_retrieve(session,type); if(msg){ - /* TODO store msg somewhere */ + if(!session->ssh_message_list){ + session->ssh_message_list=ssh_list_new(); + } + ssh_list_add(session->ssh_message_list,msg); } } + +/** @brief defines the SSH_MESSAGE callback + * @param session the current ssh session + * @param ssh_message_callback a function pointer to a callback taking the + * current ssh session and received message as parameters. the function returns + * 0 if the message has been parsed and treated sucessfuly, 1 otherwise (libssh + * must take care of the response). + */ +void ssh_set_message_callback(SSH_SESSION *session, + int(*ssh_message_callback)(struct ssh_session *session, struct ssh_message *msg)){ + session->ssh_message_callback=ssh_message_callback; +} + +int ssh_execute_message_callbacks(SSH_SESSION *session){ + SSH_MESSAGE *msg=NULL; + int ret; + if(!session->ssh_message_list) + return SSH_OK; + if(session->ssh_message_callback){ + while((msg=ssh_list_get_head(SSH_MESSAGE *, session->ssh_message_list)) != NULL){ + ret=session->ssh_message_callback(session,msg); + if(ret==1){ + ret = ssh_message_reply_default(msg); + if(ret != SSH_OK) + return ret; + } + } + } else { + while((msg=ssh_list_get_head(SSH_MESSAGE *, session->ssh_message_list)) != NULL){ + ret = ssh_message_reply_default(msg); + if(ret != SSH_OK) + return ret; + } + } + return SSH_OK; +} /** * @} */ diff --git a/libssh/packet.c b/libssh/packet.c index 870efd4a..2304441c 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -753,6 +753,9 @@ static int packet_wait2(SSH_SESSION *session, int type, int blocking) { case SSH2_MSG_CHANNEL_REQUEST: case SSH2_MSG_CHANNEL_EOF: case SSH2_MSG_CHANNEL_CLOSE: + case SSH2_MSG_SERVICE_REQUEST: + case SSH2_MSG_USERAUTH_REQUEST: + case SSH2_MSG_CHANNEL_OPEN: packet_parse(session); break; case SSH2_MSG_IGNORE: diff --git a/libssh/session.c b/libssh/session.c index e8f63361..c83fecdc 100644 --- a/libssh/session.c +++ b/libssh/session.c @@ -125,7 +125,14 @@ void ssh_cleanup(SSH_SESSION *session) { privatekey_free(session->dsa_key); privatekey_free(session->rsa_key); - ssh_message_free(session->ssh_message); + if(session->ssh_message_list){ + SSH_MESSAGE *msg; + while((msg=ssh_list_get_head(SSH_MESSAGE *,session->ssh_message_list)) + != NULL){ + ssh_message_free(msg); + } + ssh_list_free(session->ssh_message_list); + } ssh_options_free(session->options); /* burn connection, it could hang sensitive datas */