aboutsummaryrefslogtreecommitdiff
path: root/libssh
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2009-12-26 21:59:37 +0100
committerAris Adamantiadis <aris@0xbadc0de.be>2009-12-26 21:59:37 +0100
commita229cb46763cb4a1be1a0e3b6d93e6e0d106561d (patch)
tree15ef2b43daac6c125bc12f9badb0b03681910efc /libssh
parent682ed1812364bd42fef6f331486c5d8f5a72ef21 (diff)
downloadlibssh-a229cb46763cb4a1be1a0e3b6d93e6e0d106561d.tar.gz
libssh-a229cb46763cb4a1be1a0e3b6d93e6e0d106561d.tar.xz
libssh-a229cb46763cb4a1be1a0e3b6d93e6e0d106561d.zip
Asynchronous authentication works !
Diffstat (limited to 'libssh')
-rw-r--r--libssh/auth.c238
-rw-r--r--libssh/packet.c7
2 files changed, 145 insertions, 100 deletions
diff --git a/libssh/auth.c b/libssh/auth.c
index 4636c3e7..a6e5fad6 100644
--- a/libssh/auth.c
+++ b/libssh/auth.c
@@ -68,7 +68,7 @@ static int ask_userauth(ssh_session session) {
}
/** @internal
- * @handles a SSH_USERAUTH_BANNER packet
+ * @brief handles a SSH_USERAUTH_BANNER packet
* This banner should be shown to user prior to authentication
*/
SSH_PACKET_CALLBACK(ssh_packet_userauth_banner){
@@ -91,96 +91,141 @@ SSH_PACKET_CALLBACK(ssh_packet_userauth_banner){
return SSH_PACKET_USED;
}
-
-static int wait_auth_status(ssh_session session, int kbdint) {
+/** @internal
+ * @brief handles a SSH_USERAUTH_FAILURE packet
+ * This handles the complete or partial authentication
+ * failure.
+ */
+SSH_PACKET_CALLBACK(ssh_packet_userauth_failure){
char *auth_methods = NULL;
ssh_string auth;
- int rc = SSH_AUTH_ERROR;
- int cont = 1;
uint8_t partial = 0;
-
+ (void) type;
+ (void) user;
enter_function();
- while (cont) {
- if (packet_read(session) != SSH_OK) {
- break;
- }
- if (packet_translate(session) != SSH_OK) {
- break;
- }
+ auth = buffer_get_ssh_string(packet);
+ if (auth == NULL || buffer_get_u8(packet, &partial) != 1) {
+ ssh_set_error(session, SSH_FATAL,
+ "Invalid SSH_MSG_USERAUTH_FAILURE message");
+ session->auth_state=SSH_AUTH_STATE_ERROR;
+ goto end;
+ }
- switch (session->in_packet.type) {
- case SSH2_MSG_USERAUTH_FAILURE:
- auth = buffer_get_ssh_string(session->in_buffer);
- if (auth == NULL || buffer_get_u8(session->in_buffer, &partial) != 1) {
- ssh_set_error(session, SSH_FATAL,
- "Invalid SSH_MSG_USERAUTH_FAILURE message");
- leave_function();
- return SSH_AUTH_ERROR;
- }
+ auth_methods = string_to_char(auth);
+ if (auth_methods == NULL) {
+ ssh_set_error_oom(session);
+ goto end;
+ }
- auth_methods = string_to_char(auth);
- if (auth_methods == NULL) {
- ssh_set_error(session, SSH_FATAL,
- "Not enough space");
- string_free(auth);
- leave_function();
- return SSH_AUTH_ERROR;
- }
+ if (partial) {
+ session->auth_state=SSH_AUTH_STATE_PARTIAL;
+ ssh_log(session,SSH_LOG_PROTOCOL,
+ "Partial success. Authentication that can continue: %s",
+ auth_methods);
+ } else {
+ session->auth_state=SSH_AUTH_STATE_FAILED;
+ ssh_log(session, SSH_LOG_PROTOCOL,
+ "Access denied. Authentication that can continue: %s",
+ auth_methods);
+ ssh_set_error(session, SSH_REQUEST_DENIED,
+ "Access denied. Authentication that can continue: %s",
+ auth_methods);
- if (partial) {
- rc = SSH_AUTH_PARTIAL;
- ssh_set_error(session, SSH_NO_ERROR,
- "Partial success. Authentication that can continue: %s",
- auth_methods);
- } else {
- rc = SSH_AUTH_DENIED;
- ssh_set_error(session, SSH_REQUEST_DENIED,
- "Access denied. Authentication that can continue: %s",
- auth_methods);
-
- session->auth_methods = 0;
- if (strstr(auth_methods, "password") != NULL) {
- session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
- }
- if (strstr(auth_methods, "keyboard-interactive") != NULL) {
- session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
- }
- if (strstr(auth_methods, "publickey") != NULL) {
- session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
- }
- if (strstr(auth_methods, "hostbased") != NULL) {
- session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED;
- }
- }
+ session->auth_methods = 0;
+ }
+ if (strstr(auth_methods, "password") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_PASSWORD;
+ }
+ if (strstr(auth_methods, "keyboard-interactive") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_INTERACTIVE;
+ }
+ if (strstr(auth_methods, "publickey") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_PUBLICKEY;
+ }
+ if (strstr(auth_methods, "hostbased") != NULL) {
+ session->auth_methods |= SSH_AUTH_METHOD_HOSTBASED;
+ }
- string_free(auth);
- SAFE_FREE(auth_methods);
- cont = 0;
- break;
- case SSH2_MSG_USERAUTH_PK_OK:
- /* SSH monkeys have defined the same number for both */
- /* SSH_MSG_USERAUTH_PK_OK and SSH_MSG_USERAUTH_INFO_REQUEST */
- /* which is not really smart; */
- /*case SSH2_MSG_USERAUTH_INFO_REQUEST: */
- if (kbdint) {
- rc = SSH_AUTH_INFO;
- cont = 0;
- break;
- }
- /* continue through success */
- case SSH2_MSG_USERAUTH_SUCCESS:
- rc = SSH_AUTH_SUCCESS;
- cont = 0;
- break;
-
- default:
- //packet_parse(session);
- //FIXME: broken
- break;
- }
+end:
+ string_free(auth);
+ SAFE_FREE(auth_methods);
+ leave_function();
+ return SSH_PACKET_USED;
+}
+
+/** @internal
+ * @brief handles a SSH_USERAUTH_SUCCESS packet
+ * It is also used to communicate the new to the
+ * upper levels.
+ */
+SSH_PACKET_CALLBACK(ssh_packet_userauth_success){
+ enter_function();
+ (void)packet;
+ (void)type;
+ (void)user;
+ ssh_log(session,SSH_LOG_PACKET,"Received SSH_USERAUTH_SUCCESS");
+ ssh_log(session,SSH_LOG_PROTOCOL,"Authentication successful");
+ session->auth_state=SSH_AUTH_STATE_SUCCESS;
+ session->session_state=SSH_SESSION_STATE_AUTHENTICATED;
+ leave_function();
+ return SSH_PACKET_USED;
+}
+
+/** @internal
+ * @brief handles a SSH_USERAUTH_PK_OK or SSH_USERAUTH_INFO_REQUEST packet
+ * Since the two types of packets share the same code, additional
+ * work is done to understand if we are in a public key or
+ * keyboard-interactive context.
+ */
+SSH_PACKET_CALLBACK(ssh_packet_userauth_pk_ok){
+ enter_function();
+ (void)packet;
+ (void)type;
+ (void)user;
+ ssh_log(session,SSH_LOG_PACKET,"Received SSH_USERAUTH_PK_OK/INFO_REQUEST");
+ if(session->kbdint){
+ /* Assuming we are in keyboard-interactive context */
+ ssh_log(session,SSH_LOG_PACKET,"keyboard-interactive context exists, assuming SSH_USERAUTH_INFO_REQUEST");
+ session->auth_state=SSH_AUTH_STATE_INFO;
+ } else {
+ session->auth_state=SSH_AUTH_STATE_PK_OK;
+ ssh_log(session,SSH_LOG_PACKET,"assuming SSH_USERAUTH_PK_OK");
}
+ leave_function();
+ return SSH_PACKET_USED;
+}
+
+static int wait_auth_status(ssh_session session) {
+ int rc = SSH_AUTH_ERROR;
+
+ enter_function();
+ while (session->auth_state == SSH_AUTH_STATE_NONE) {
+ ssh_handle_packets(session);
+ }
+ switch(session->auth_state){
+ case SSH_AUTH_STATE_ERROR:
+ rc=SSH_AUTH_ERROR;
+ break;
+ case SSH_AUTH_STATE_FAILED:
+ rc=SSH_AUTH_DENIED;
+ break;
+ case SSH_AUTH_STATE_INFO:
+ rc=SSH_AUTH_INFO;
+ break;
+ case SSH_AUTH_STATE_PARTIAL:
+ rc=SSH_AUTH_PARTIAL;
+ break;
+ case SSH_AUTH_STATE_PK_OK:
+ case SSH_AUTH_STATE_SUCCESS:
+ rc=SSH_AUTH_SUCCESS;
+ break;
+ case SSH_AUTH_STATE_NONE:
+ /* not reached */
+ rc=SSH_AUTH_ERROR;
+ break;
+ }
leave_function();
return rc;
}
@@ -212,9 +257,7 @@ int ssh_userauth_list(ssh_session session, const char *username) {
*
* @param session The ssh session to use.
*
- * @param username The username to authenticate. You can specify NULL if
- * ssh_option_set_username() has been used. You cannot try
- * two different logins in a row.
+ * @param username Deprecated, set to NULL.
*
* @returns SSH_AUTH_ERROR: A serious error happened.\n
* SSH_AUTH_DENIED: Authentication failed: use another method\n
@@ -280,12 +323,12 @@ int ssh_userauth_none(ssh_session session, const char *username) {
string_free(service);
string_free(method);
string_free(user);
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) == SSH_ERROR) {
leave_function();
return rc;
}
- rc = wait_auth_status(session, 0);
+ rc = wait_auth_status(session);
leave_function();
return rc;
@@ -394,12 +437,12 @@ int ssh_userauth_offer_pubkey(ssh_session session, const char *username,
string_free(method);
string_free(service);
string_free(algo);
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session,0);
+ rc = wait_auth_status(session);
leave_function();
return rc;
@@ -514,12 +557,12 @@ int ssh_userauth_pubkey(ssh_session session, const char *username,
goto error;
}
string_free(sign);
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session,0);
+ rc = wait_auth_status(session);
}
leave_function();
@@ -632,11 +675,12 @@ int ssh_userauth_agent_pubkey(ssh_session session, const char *username,
goto error;
}
string_free(sign);
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session,0);
+ rc = wait_auth_status(session);
}
string_free(user);
@@ -751,12 +795,12 @@ int ssh_userauth_password(ssh_session session, const char *username,
string_free(method);
string_burn(pwd);
string_free(pwd);
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session, 0);
+ rc = wait_auth_status(session);
leave_function();
return rc;
@@ -1161,12 +1205,12 @@ static int kbdauth_init(ssh_session session, const char *user,
string_free(service);
string_free(method);
string_free(sub);
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session,1);
+ rc = wait_auth_status(session);
leave_function();
return rc;
@@ -1328,12 +1372,12 @@ static int kbdauth_send(ssh_session session) {
string_burn(answer);
string_free(answer);
}
-
+ session->auth_state=SSH_AUTH_STATE_NONE;
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
- rc = wait_auth_status(session,1);
+ rc = wait_auth_status(session);
leave_function();
return rc;
@@ -1405,7 +1449,7 @@ int ssh_userauth_kbdint(ssh_session session, const char *user,
leave_function();
return rc; /* error or first try success */
}
-
+ /* TODO: put this in packet handler */
rc = kbdauth_info_get(session);
if (rc == SSH_AUTH_ERROR) {
kbdint_free(session->kbdint);
diff --git a/libssh/packet.c b/libssh/packet.c
index f3263cc1..45ae3602 100644
--- a/libssh/packet.c
+++ b/libssh/packet.c
@@ -68,10 +68,11 @@ ssh_packet_callback default_packet_handlers[]= {
NULL, NULL, NULL, NULL, NULL, // 35-49
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, //#define SSH2_MSG_USERAUTH_REQUEST 50
- NULL, //#define SSH2_MSG_USERAUTH_FAILURE 51
- NULL, //#define SSH2_MSG_USERAUTH_SUCCESS 52
+ ssh_packet_userauth_failure, //#define SSH2_MSG_USERAUTH_FAILURE 51
+ ssh_packet_userauth_success, //#define SSH2_MSG_USERAUTH_SUCCESS 52
ssh_packet_userauth_banner, //#define SSH2_MSG_USERAUTH_BANNER 53
- NULL, //#define SSH2_MSG_USERAUTH_PK_OK 60 SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
+ NULL,NULL,NULL,NULL,NULL,NULL, // 54-59
+ ssh_packet_userauth_pk_ok, //#define SSH2_MSG_USERAUTH_PK_OK 60 SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
//SSH2_MSG_USERAUTH_INFO_REQUEST 60
NULL, //#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, //62-79