From be17dc9d31e805c03372b690dde67838b3bfc12d Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 24 May 2023 16:34:11 +0200 Subject: [PATCH] libssh: when keyboard-interactive auth fails, try password MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state machine had a mistake in that it would not carry on to that next step. This also adds a verbose output what methods that are available from the server and renames the macros that change to the next auth methods to try. Reported-by: 左潇峰 Fixes #11196 Closes #11197 --- lib/ssh-libssh.c | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/ssh-libssh.c b/lib/ssh-libssh.c index 7ebe61321419f..1cecb649cb623 100644 --- a/lib/ssh-libssh.c +++ b/lib/ssh-libssh.c @@ -442,7 +442,7 @@ static int myssh_is_known(struct Curl_easy *data) break; \ } -#define MOVE_TO_LAST_AUTH \ +#define MOVE_TO_PASSWD_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD) { \ rc = SSH_OK; \ state(conn, SSH_AUTH_PASS_INIT); \ @@ -452,25 +452,25 @@ static int myssh_is_known(struct Curl_easy *data) MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); \ } -#define MOVE_TO_TERTIARY_AUTH \ +#define MOVE_TO_KEY_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE) { \ rc = SSH_OK; \ state(conn, SSH_AUTH_KEY_INIT); \ break; \ } \ else { \ - MOVE_TO_LAST_AUTH; \ + MOVE_TO_PASSWD_AUTH; \ } -#define MOVE_TO_SECONDARY_AUTH \ +#define MOVE_TO_GSSAPI_AUTH \ if(sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC) { \ rc = SSH_OK; \ state(conn, SSH_AUTH_GSSAPI); \ break; \ } \ else { \ - MOVE_TO_TERTIARY_AUTH; \ + MOVE_TO_KEY_AUTH; \ } static int myssh_auth_interactive(struct connectdata *conn) @@ -617,6 +617,16 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } sshc->auth_methods = ssh_userauth_list(sshc->ssh_session, NULL); + if(sshc->auth_methods) + infof(data, "SSH authentication methods available: %s%s%s%s", + sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY ? + "public key, ": "", + sshc->auth_methods & SSH_AUTH_METHOD_GSSAPI_MIC ? + "GSSAPI, " : "", + sshc->auth_methods & SSH_AUTH_METHOD_INTERACTIVE ? + "keyboard-interactive, " : "", + sshc->auth_methods & SSH_AUTH_METHOD_PASSWORD ? + "password": ""); if(sshc->auth_methods & SSH_AUTH_METHOD_PUBLICKEY) { state(conn, SSH_AUTH_PKEY_INIT); infof(data, "Authentication using SSH public key file\n"); @@ -761,8 +761,8 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } case SSH_AUTH_PKEY_INIT: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY)) { - MOVE_TO_SECONDARY_AUTH; + MOVE_TO_GSSAPI_AUTH; } /* Two choices, (1) private key was given on CMD, * (2) use the "default" keys. */ @@ -776,7 +776,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } if(rc != SSH_OK) { - MOVE_TO_SECONDARY_AUTH; + MOVE_TO_GSSAPI_AUTH; } } @@ -826,7 +836,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break; } - MOVE_TO_SECONDARY_AUTH; + MOVE_TO_GSSAPI_AUTH; } break; case SSH_AUTH_PKEY: @@ -828,13 +828,13 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) } else { infof(data, "Failed public key authentication (rc: %d)\n", rc); - MOVE_TO_SECONDARY_AUTH; + MOVE_TO_GSSAPI_AUTH; } break; case SSH_AUTH_GSSAPI: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_GSSAPI)) { - MOVE_TO_TERTIARY_AUTH; + MOVE_TO_KEY_AUTH; } rc = ssh_userauth_gssapi(sshc->ssh_session); @@ -851,7 +851,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) break; } - MOVE_TO_TERTIARY_AUTH; + MOVE_TO_KEY_AUTH; break; case SSH_AUTH_KEY_INIT: @@ -736,13 +736,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) state(conn, SSH_AUTH_KEY); } else { - MOVE_TO_LAST_AUTH; + MOVE_TO_PASSWD_AUTH; } break; case SSH_AUTH_KEY: - - /* Authentication failed. Continue with keyboard-interactive now. */ + /* keyboard-interactive authentication */ rc = myssh_auth_interactive(conn); if(rc == SSH_AGAIN) { break; @@ -759,13 +759,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, bool *block) if(rc == SSH_OK) { sshc->authed = TRUE; infof(data, "completed keyboard interactive authentication\n"); + state(conn, SSH_AUTH_DONE); + } + else { + MOVE_TO_PASSWD_AUTH; } - state(conn, SSH_AUTH_DONE); break; case SSH_AUTH_PASS_INIT: if(!(data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD)) { - /* Host key authentication is intentionally not implemented */ MOVE_TO_ERROR_STATE(CURLE_LOGIN_DENIED); } state(conn, SSH_AUTH_PASS);