]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
Handle PAM_MAXTRIES from modules.
authorDarren Tucker <dtucker@zip.com.au>
Sun, 17 Jul 2016 23:33:25 +0000 (09:33 +1000)
committerDarren Tucker <dtucker@zip.com.au>
Sun, 17 Jul 2016 23:33:25 +0000 (09:33 +1000)
bz#2249: handle the case where PAM returns PAM_MAXTRIES by ceasing to offer
password and keyboard-interative authentication methods.  Should prevent
"sshd ignoring max retries" warnings in the log.  ok djm@

It probably won't trigger with keyboard-interactive in the default
configuration because the retry counter is stored in module-private
storage which goes away with the sshd PAM process (see bz#688).  On the
other hand, those cases probably won't log a warning either.

auth-pam.c
auth-pam.h
monitor.c
monitor_wrap.c

index 465b5a702dbd3ab9a55096c8a6196e054d27a876..1f13c181cae142f7dc3b741666fcc54e08c437fd 100644 (file)
@@ -229,6 +229,7 @@ static int sshpam_authenticated = 0;
 static int sshpam_session_open = 0;
 static int sshpam_cred_established = 0;
 static int sshpam_account_status = -1;
+static int sshpam_maxtries_reached = 0;
 static char **sshpam_env = NULL;
 static Authctxt *sshpam_authctxt = NULL;
 static const char *sshpam_password = NULL;
@@ -450,6 +451,8 @@ sshpam_thread(void *ctxtp)
        if (sshpam_err != PAM_SUCCESS)
                goto auth_fail;
        sshpam_err = pam_authenticate(sshpam_handle, flags);
+       if (sshpam_err == PAM_MAXTRIES)
+               sshpam_set_maxtries_reached(1);
        if (sshpam_err != PAM_SUCCESS)
                goto auth_fail;
 
@@ -501,6 +504,8 @@ sshpam_thread(void *ctxtp)
        /* XXX - can't do much about an error here */
        if (sshpam_err == PAM_ACCT_EXPIRED)
                ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, &buffer);
+       else if (sshpam_maxtries_reached)
+               ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, &buffer);
        else
                ssh_msg_send(ctxt->pam_csock, PAM_AUTH_ERR, &buffer);
        buffer_free(&buffer);
@@ -741,7 +746,11 @@ sshpam_query(void *ctx, char **name, char **info,
                        free(msg);
                        break;
                case PAM_ACCT_EXPIRED:
-                       sshpam_account_status = 0;
+               case PAM_MAXTRIES:
+                       if (type == PAM_ACCT_EXPIRED)
+                               sshpam_account_status = 0;
+                       if (type == PAM_MAXTRIES)
+                               sshpam_set_maxtries_reached(1);
                        /* FALLTHROUGH */
                case PAM_AUTH_ERR:
                        debug3("PAM: %s", pam_strerror(sshpam_handle, type));
@@ -1218,6 +1227,8 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
        sshpam_err = pam_authenticate(sshpam_handle, flags);
        sshpam_password = NULL;
        free(fake);
+       if (sshpam_err == PAM_MAXTRIES)
+               sshpam_set_maxtries_reached(1);
        if (sshpam_err == PAM_SUCCESS && authctxt->valid) {
                debug("PAM: password authentication accepted for %.100s",
                    authctxt->user);
@@ -1229,4 +1240,21 @@ sshpam_auth_passwd(Authctxt *authctxt, const char *password)
                return 0;
        }
 }
+
+int
+sshpam_get_maxtries_reached(void)
+{
+       return sshpam_maxtries_reached;
+}
+
+void
+sshpam_set_maxtries_reached(int reached)
+{
+       if (reached == 0 || sshpam_maxtries_reached)
+               return;
+       sshpam_maxtries_reached = 1;
+       options.password_authentication = 0;
+       options.kbd_interactive_authentication = 0;
+       options.challenge_response_authentication = 0;
+}
 #endif /* USE_PAM */
index a1a2b52d8804289c58cdccb2c056d72614af5411..2e9a0c0a3816226cca8c1b293bb292bbec951d8a 100644 (file)
@@ -45,6 +45,8 @@ void free_pam_environment(char **);
 void sshpam_thread_cleanup(void);
 void sshpam_cleanup(void);
 int sshpam_auth_passwd(Authctxt *, const char *);
+int sshpam_get_maxtries_reached(void);
+void sshpam_set_maxtries_reached(int);
 int is_pam_session_open(void);
 
 #endif /* USE_PAM */
index 8b3c27a76fb4d88ab78015ee023e0ac0cf6b9ca8..fbe965e7cccc625ac0e17c8224daa830994b2d38 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -75,6 +75,7 @@
 #include "cipher.h"
 #include "kex.h"
 #include "dh.h"
+#include "auth-pam.h"
 #ifdef TARGET_OS_MAC   /* XXX Broken krb5 headers on Mac */
 #undef TARGET_OS_MAC
 #include "zlib.h"
@@ -920,6 +921,9 @@ mm_answer_authpassword(int sock, Buffer *m)
 
        buffer_clear(m);
        buffer_put_int(m, authenticated);
+#ifdef USE_PAM
+       buffer_put_int(m, sshpam_get_maxtries_reached());
+#endif
 
        debug3("%s: sending result %d", __func__, authenticated);
        mm_request_send(sock, MONITOR_ANS_AUTHPASSWORD, m);
@@ -1119,6 +1123,7 @@ mm_answer_pam_query(int sock, Buffer *m)
        free(name);
        buffer_put_cstring(m, info);
        free(info);
+       buffer_put_int(m, sshpam_get_maxtries_reached());
        buffer_put_int(m, num);
        for (i = 0; i < num; ++i) {
                buffer_put_cstring(m, prompts[i]);
index 552004902b2c511daec7083ddc0cc74e7de94a1d..99dc13b61cd29d9e5e9b15ead4555eb6a135afed 100644 (file)
@@ -60,6 +60,7 @@
 #include "packet.h"
 #include "mac.h"
 #include "log.h"
+#include "auth-pam.h"
 #ifdef TARGET_OS_MAC    /* XXX Broken krb5 headers on Mac */
 #undef TARGET_OS_MAC
 #include "zlib.h"
@@ -362,6 +363,9 @@ mm_auth_password(Authctxt *authctxt, char *password)
        mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m);
 
        authenticated = buffer_get_int(&m);
+#ifdef USE_PAM
+       sshpam_set_maxtries_reached(buffer_get_int(&m));
+#endif
 
        buffer_free(&m);
 
@@ -644,6 +648,7 @@ mm_sshpam_query(void *ctx, char **name, char **info,
        debug3("%s: pam_query returned %d", __func__, ret);
        *name = buffer_get_string(&m, NULL);
        *info = buffer_get_string(&m, NULL);
+       sshpam_set_maxtries_reached(buffer_get_int(&m));
        *num = buffer_get_int(&m);
        if (*num > PAM_MAX_NUM_MSG)
                fatal("%s: recieved %u PAM messages, expected <= %u",