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

Reply via email to