From 6f3505bf6b3a747df2f6dec55b29228d1b0a0a4e Mon Sep 17 00:00:00 2001 From: Aris Adamantiadis Date: Sat, 26 Dec 2009 16:51:33 +0100 Subject: [PATCH] Asynchronous service request --- include/libssh/priv.h | 1 + include/libssh/session.h | 17 ++++++- libssh/auth.c | 22 +++++---- libssh/client.c | 96 ++++++++++++++++++++++++---------------- libssh/packet.c | 2 +- 5 files changed, 89 insertions(+), 49 deletions(-) diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 1b751842..1f2a1216 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -123,6 +123,7 @@ int ssh_send_banner(ssh_session session, int is_server); void ssh_connection_callback(ssh_session session); SSH_PACKET_CALLBACK(ssh_packet_dh_reply); SSH_PACKET_CALLBACK(ssh_packet_newkeys); +SSH_PACKET_CALLBACK(ssh_packet_service_accept); /* config.c */ int ssh_config_parse_file(ssh_session session, const char *filename); diff --git a/include/libssh/session.h b/include/libssh/session.h index c7584994..5cf5af5a 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -41,6 +41,20 @@ enum ssh_session_state_e { SSH_SESSION_STATE_ERROR }; +/** @internal + * @brief states of the authentication service request + */ +enum ssh_auth_service_state_e { + /** initial state */ + SSH_AUTH_SERVICE_NONE=0, + /** Authentication service request packet sent */ + SSH_AUTH_SERVICE_SENT, + /** Service accepted */ + SSH_AUTH_SERVICE_ACCEPTED, + /** Access to service denied (fatal) */ + SSH_AUTH_SERVICE_DENIED +}; + struct ssh_session_struct { struct error_struct error; struct ssh_socket_struct *socket; @@ -60,7 +74,7 @@ struct ssh_session_struct { /* !=0 when the user got a session handle */ int alive; /* two previous are deprecated */ - int auth_service_asked; +// int auth_service_asked; /* socket status */ int blocking; // functions should block @@ -78,6 +92,7 @@ struct ssh_session_struct { enum ssh_session_state_e session_state; int packet_state; int dh_handshake_state; + enum ssh_auth_service_state_e auth_service_state; ssh_string dh_server_signature; //information used by dh_handshake. KEX server_kex; diff --git a/libssh/auth.c b/libssh/auth.c index 9349cc72..409917fa 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -45,19 +45,23 @@ /** \addtogroup ssh_auth * @{ */ +/** + * @internal + * @brief ask access to the ssh-userauth service + * @param session SSH session handle + * @returns SSH_OK on success + * @returns SSH_ERROR on error + * @bug current implementation is blocking + */ static int ask_userauth(ssh_session session) { int rc = 0; enter_function(); - - if (session->auth_service_asked) { - rc = 0; - } else if (ssh_service_request(session,"ssh-userauth")) { - rc = -1; - } else { - session->auth_service_asked++; - } - + do { + rc=ssh_service_request(session,"ssh-userauth"); + if(rc==SSH_AGAIN) + ssh_handle_packets(session); + } while(rc==SSH_AGAIN); leave_function(); return rc; } diff --git a/libssh/client.c b/libssh/client.c index 9af62e2c..5ced48e2 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -466,6 +466,23 @@ error: return rc; } +/** + * @internal + * @brief handles a SSH_SERVICE_ACCEPT packet + * + */ +SSH_PACKET_CALLBACK(ssh_packet_service_accept){ + (void)packet; + (void)type; + (void)user; + enter_function(); + session->auth_service_state=SSH_AUTH_SERVICE_ACCEPTED; + ssh_log(session, SSH_LOG_PACKET, + "Received SSH_MSG_SERVICE_ACCEPT"); + leave_function(); + return SSH_PACKET_USED; +} + /** * @internal * @@ -476,52 +493,55 @@ error: * @param session The session to use to ask for a service request. * @param service The service request. * - * @return 0 on success, < 0 on error. + * @return SSH_OK on success + * @return SSH_ERROR on error + * @return SSH_AGAIN No response received yet + * @bug actually only works with ssh-userauth */ int ssh_service_request(ssh_session session, const char *service) { ssh_string service_s = NULL; - + int rc=SSH_ERROR; enter_function(); + switch(session->auth_service_state){ + case SSH_AUTH_SERVICE_NONE: + if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) { + break; + } + service_s = string_from_char(service); + if (service_s == NULL) { + break; + } - if (buffer_add_u8(session->out_buffer, SSH2_MSG_SERVICE_REQUEST) < 0) { - leave_function(); - return -1; + if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) { + string_free(service_s); + break; + } + string_free(service_s); + + if (packet_send(session) != SSH_OK) { + ssh_set_error(session, SSH_FATAL, + "Sending SSH2_MSG_SERVICE_REQUEST failed."); + break; + } + + ssh_log(session, SSH_LOG_PACKET, + "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); + session->auth_service_state=SSH_AUTH_SERVICE_SENT; + rc=SSH_AGAIN; + break; + case SSH_AUTH_SERVICE_DENIED: + ssh_set_error(session,SSH_FATAL,"ssh_auth_service request denied"); + break; + case SSH_AUTH_SERVICE_ACCEPTED: + rc=SSH_OK; + break; + case SSH_AUTH_SERVICE_SENT: + rc=SSH_AGAIN; + break; } - service_s = string_from_char(service); - if (service_s == NULL) { - leave_function(); - return -1; - } - - if (buffer_add_ssh_string(session->out_buffer,service_s) < 0) { - string_free(service_s); - leave_function(); - return -1; - } - string_free(service_s); - - if (packet_send(session) != SSH_OK) { - ssh_set_error(session, SSH_FATAL, - "Sending SSH2_MSG_SERVICE_REQUEST failed."); - leave_function(); - return -1; - } - - ssh_log(session, SSH_LOG_PACKET, - "Sent SSH_MSG_SERVICE_REQUEST (service %s)", service); - - if (packet_wait(session,SSH2_MSG_SERVICE_ACCEPT,1) != SSH_OK) { - ssh_set_error(session, SSH_FATAL, "Did not receive SERVICE_ACCEPT"); - leave_function(); - return -1; - } - - ssh_log(session, SSH_LOG_PACKET, - "Received SSH_MSG_SERVICE_ACCEPT (service %s)", service); - leave_function(); - return 0; + return rc; } /** \addtogroup ssh_session diff --git a/libssh/packet.c b/libssh/packet.c index dba00772..fb2e5636 100644 --- a/libssh/packet.c +++ b/libssh/packet.c @@ -53,7 +53,7 @@ ssh_packet_callback default_packet_handlers[]= { NULL, //#define SSH2_MSG_UNIMPLEMENTED 3 ssh_packet_ignore_callback, //#define SSH2_MSG_DEBUG 4 NULL, //#define SSH2_MSG_SERVICE_REQUEST 5 - NULL, //#define SSH2_MSG_SERVICE_ACCEPT 6 + ssh_packet_service_accept, //#define SSH2_MSG_SERVICE_ACCEPT 6 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 7-19 ssh_packet_kexinit, //#define SSH2_MSG_KEXINIT 20