Blob Blame History Raw
From 0479c6f1598602909487c499266fe410085251a5 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Mon, 25 Mar 2019 10:17:17 +0100
Subject: [PATCH] pam_sss: PAM_USER_UNKNOWN if socket is missing

If SSSD used without explicit configuration in the files-only mode and
pam_sss is also used in the PAM configuration, as e.g. in recent Fedora
systems, users handled by other NSS modules might get an 'Access Denied'
when trying to log in.

The culprit is the line like

    account     [default=bad success=ok user_unknown=ignore] pam_sss.so

in the PAM configuration which can only grant access if pam_sss.so
returns PAM_SUCCESS or PAM_USER_UNKNOWN. Even PAM_IGNORE causes a
rejection because of 'default=bad'.

Of the PAM responder is running PAM_USER_UNKNOWN is returned for users
from other NSS modules. With this patch PAM_USER_UNKNOWN is returned as
well during the 'account' step if the PAM responder socket is not
available.

Related to https://pagure.io/SSSD/sssd/issue/3988

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
 src/man/pam_sss.8.xml    |  4 ++++
 src/sss_client/common.c  | 18 ++++++++++++++++++
 src/sss_client/pam_sss.c | 16 +++++++++++++---
 src/sss_client/sss_cli.h |  2 ++
 4 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/src/man/pam_sss.8.xml b/src/man/pam_sss.8.xml
index 86ed0fefe..834d9d268 100644
--- a/src/man/pam_sss.8.xml
+++ b/src/man/pam_sss.8.xml
@@ -256,6 +256,10 @@ auth sufficient pam_sss.so allow_missing_name
         <para>All module types (<option>account</option>, <option>auth</option>,
         <option>password</option> and <option>session</option>) are provided.
         </para>
+        <para>If SSSD's PAM responder is not running, e.g. if the PAM responder
+        socket is not available, pam_sss will return PAM_USER_UNKNOWN when
+        called as <option>account</option> module to avoid issues with users
+        from other sources during access control.</para>
     </refsect1>
 
     <refsect1 id='files'>
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 224f33b55..e2d840540 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -913,8 +913,14 @@ int sss_pam_make_request(enum sss_cli_command cmd,
     /* only root shall use the privileged pipe */
     if (getuid() == 0 && getgid() == 0) {
         socket_name = SSS_PAM_PRIV_SOCKET_NAME;
+        errno = 0;
         statret = stat(socket_name, &stat_buf);
         if (statret != 0) {
+            if (errno == ENOENT) {
+                *errnop = ESSS_NO_SOCKET;
+            } else {
+                *errnop = ESSS_SOCKET_STAT_ERROR;
+            }
             ret = PAM_SERVICE_ERR;
             goto out;
         }
@@ -928,8 +934,14 @@ int sss_pam_make_request(enum sss_cli_command cmd,
         }
     } else {
         socket_name = SSS_PAM_SOCKET_NAME;
+        errno = 0;
         statret = stat(socket_name, &stat_buf);
         if (statret != 0) {
+            if (errno == ENOENT) {
+                *errnop = ESSS_NO_SOCKET;
+            } else {
+                *errnop = ESSS_SOCKET_STAT_ERROR;
+            }
             ret = PAM_SERVICE_ERR;
             goto out;
         }
@@ -1075,6 +1087,12 @@ const char *ssscli_err2string(int err)
         case ESSS_SERVER_NOT_TRUSTED:
             return _("SSSD is not run by root.");
             break;
+        case ESSS_NO_SOCKET:
+            return _("SSSD socket does not exist.");
+            break;
+        case ESSS_SOCKET_STAT_ERROR:
+            return _("Cannot get stat of SSSD socket.");
+            break;
         default:
             m = strerror(err);
             if (m == NULL) {
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 69dc50dfd..9d51aefc6 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -1304,10 +1304,20 @@ static int send_and_receive(pam_handle_t *pamh, struct pam_items *pi,
     }
 
     if (ret != PAM_SUCCESS) {
-        if (errnop != 0) {
-            logger(pamh, LOG_ERR, "Request to sssd failed. %s", ssscli_err2string(errnop));
+        /* If there is no PAM responder socket during the access control step
+         * we assume this is on purpose, i.e. PAM responder is not configured.
+         * PAM_USER_UNKNOWN is returned to the PAM stack to avoid unexpected
+         * denials. */
+        if (errnop == ESSS_NO_SOCKET && task == SSS_PAM_ACCT_MGMT) {
+            pam_status = PAM_USER_UNKNOWN;
+        } else {
+            if (errnop != 0 && errnop != ESSS_NO_SOCKET) {
+                logger(pamh, LOG_ERR, "Request to sssd failed. %s",
+                                      ssscli_err2string(errnop));
+            }
+
+            pam_status = PAM_AUTHINFO_UNAVAIL;
         }
-        pam_status = PAM_AUTHINFO_UNAVAIL;
         goto done;
     }
 
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index af8a43916..31b4e50f7 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -584,6 +584,8 @@ enum sss_cli_error_codes {
     ESSS_BAD_PUB_SOCKET,
     ESSS_BAD_CRED_MSG,
     ESSS_SERVER_NOT_TRUSTED,
+    ESSS_NO_SOCKET,
+    ESSS_SOCKET_STAT_ERROR,
 
     ESS_SSS_CLI_ERROR_MAX
 };
-- 
2.19.1