]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
auth-pam: Immediately report interactive instructions to clients
authorMarco Trevisan (Treviño) <mail@3v1n0.net>
Tue, 17 Oct 2023 02:27:32 +0000 (04:27 +0200)
committerDarren Tucker <dtucker@dtucker.net>
Mon, 16 Feb 2026 01:15:16 +0000 (20:15 -0500)
SSH keyboard-interactive authentication method supports instructions but
sshd didn't show them until an user prompt was requested.

This is quite inconvenient for various PAM modules that need to notify
an user without requiring for their explicit input.

So, properly implement RFC4256 making instructions to be shown to users
when they are requested from PAM.

Closes: https://bugzilla.mindrot.org/show_bug.cgi?id=2876
auth-pam.c

index 0b247421b296b8a9e25e8c70aad6272b3269505f..cb9e0bc31990f4dac34851c7e110f9c466c74fd7 100644 (file)
@@ -136,6 +136,7 @@ typedef int SshPamDone;
 #define SshPamError -1
 #define SshPamNone 0
 #define SshPamAuthenticated 1
+#define SshPamAgain 2
 
 struct pam_ctxt {
        sp_pthread_t     pam_thread;
@@ -868,6 +869,8 @@ sshpam_query(void *ctx, char **name, char **info,
        **prompts = NULL;
        plen = 0;
        *echo_on = xmalloc(sizeof(u_int));
+       ctxt->pam_done = SshPamNone;
+
        while (ssh_msg_recv(ctxt->pam_psock, buffer) == 0) {
                if (++nmesg > PAM_MAX_NUM_MSG)
                        fatal_f("too many query messages");
@@ -888,15 +891,13 @@ sshpam_query(void *ctx, char **name, char **info,
                        return (0);
                case PAM_ERROR_MSG:
                case PAM_TEXT_INFO:
-                       /* accumulate messages */
-                       len = plen + mlen + 2;
-                       **prompts = xreallocarray(**prompts, 1, len);
-                       strlcpy(**prompts + plen, msg, len - plen);
-                       plen += mlen;
-                       strlcat(**prompts + plen, "\n", len - plen);
-                       plen++;
-                       free(msg);
-                       break;
+                       *num = 0;
+                       free(*info);
+                       *info = msg; /* Steal the message */
+                       msg = NULL;
+                       ctxt->pam_done = SshPamAgain;
+                       sshbuf_free(buffer);
+                       return (0);
                case PAM_ACCT_EXPIRED:
                case PAM_MAXTRIES:
                        if (type == PAM_ACCT_EXPIRED)
@@ -1000,6 +1001,8 @@ sshpam_respond(void *ctx, u_int num, char **resp)
                return (0);
        case SshPamNone:
                break;
+       case SshPamAgain:
+               return 1;       /* KbdintResultAgain */
        default:
                return (-1);
        }