This adds support for handling expired passwords in the client. Signed-off-by: Joakim Tjernlund <joakim.tjernl...@infinera.com> --- auth.h | 1 + cli-auth.c | 8 ++----- cli-authpasswd.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 6 deletions(-)
diff --git a/auth.h b/auth.h index a6bb3f1..a0aa3a4 100644 --- a/auth.h +++ b/auth.h @@ -39,6 +39,7 @@ void send_msg_userauth_success(); void send_msg_userauth_chauthtok(); void send_msg_userauth_banner(buffer *msg); void svr_auth_password(); +void cli_auth_new_password(); void svr_auth_pubkey(); void svr_auth_pam(const char * username, int createLocalUser); diff --git a/cli-auth.c b/cli-auth.c index da0d9d5..1eb93e7 100644 --- a/cli-auth.c +++ b/cli-auth.c @@ -137,12 +137,8 @@ void recv_msg_userauth_specific_60() { #ifdef ENABLE_CLI_PASSWORD_AUTH if (cli_ses.lastauthtype == AUTH_TYPE_PASSWORD) { - /* Eventually there could be proper password-changing - * support. However currently few servers seem to - * implement it, and password auth is last-resort - * regardless - keyboard-interactive is more likely - * to be used anyway. */ - dropbear_close("Your password has expired."); + cli_auth_new_password(); + return; } #endif diff --git a/cli-authpasswd.c b/cli-authpasswd.c index 3cf49a2..72e6f2e 100644 --- a/cli-authpasswd.c +++ b/cli-authpasswd.c @@ -158,4 +158,75 @@ void cli_auth_password() { TRACE(("leave cli_auth_password")) } + +static char *ask_password(char* prompt) +{ + char* password = NULL; + +#ifdef ENABLE_CLI_ASKPASS_HELPER + if (want_askpass()) + { + password = gui_getpass(prompt); + if (!password) { + dropbear_exit("No password"); + } + } else +#endif + { + password = getpass_or_cancel(prompt); + } + return password; +} + +void cli_auth_new_password() { + + char* password = NULL; + char* new_password = NULL; + char* new2_password = NULL; + char prompt[80]; + + TRACE(("enter cli_auth_password")) + CHECKCLEARTOWRITE(); + + snprintf(prompt, sizeof(prompt), "Enter %s@%s's old password: ", + cli_opts.username, cli_opts.remotehost); + password = strdup(ask_password(prompt)); + do { + snprintf(prompt, sizeof(prompt), "Enter %s@%s's new password: ", + cli_opts.username, cli_opts.remotehost); + new_password = strdup(ask_password(prompt)); + snprintf(prompt, sizeof(prompt), "Retype %s@%s's new password: ", + cli_opts.username, cli_opts.remotehost); + new2_password = strdup(ask_password(prompt)); + if (strcmp(new_password, new2_password) == 0) + break; /* Both passworde match, continue with login */ + fprintf(stderr, "Mismatch; try again, Ctrl-C to quit\n"); + } while (1); + buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST); + + buf_putstring(ses.writepayload, cli_opts.username, + strlen(cli_opts.username)); + + buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION, + SSH_SERVICE_CONNECTION_LEN); + + buf_putstring(ses.writepayload, AUTH_METHOD_PASSWORD, + AUTH_METHOD_PASSWORD_LEN); + + buf_putbyte(ses.writepayload, 1); /* TRUE */ + buf_putstring(ses.writepayload, password, strlen(password)); + buf_putstring(ses.writepayload, new_password, strlen(new_password)); + + encrypt_packet(); + m_burn(password, strlen(password)); + if (new_password) + m_burn(new_password, strlen(new_password)); + if (new2_password) + m_burn(new2_password, strlen(new2_password)); + free(password); + free(new_password); + free(new2_password); + TRACE(("leave cli_auth_password")) +} + #endif /* ENABLE_CLI_PASSWORD_AUTH */ -- 2.7.3