[SSSD] [PATCH] Make return values more specific during password change

Sumit Bose sbose at redhat.com
Mon Feb 8 13:56:51 UTC 2010


Hi,

with this patch a user should get a better hint what went wrong if a
password change operation failed.

bye,
Sumit
-------------- next part --------------
From 2addacf0378e3083e6e5b2fd80fdc5e90877a201 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Mon, 8 Feb 2010 11:53:43 +0100
Subject: [PATCH] Make return values more specific during password change

- return PAM_AUTHTOK_ERR instead of PAM_SYSTEM_ERR if the password
  change operation fails
- send a message to the user if the system is offline and the password
  cannot be changed
---
 server/providers/krb5/krb5_child.c |    1 +
 server/providers/ldap/ldap_auth.c  |    8 ++-
 server/responder/pam/pamsrv_cmd.c  |   92 +++++++++++++++++++++--------------
 sss_client/pam_sss.c               |   24 +++++++++
 sss_client/sss_cli.h               |    3 +-
 5 files changed, 87 insertions(+), 41 deletions(-)

diff --git a/server/providers/krb5/krb5_child.c b/server/providers/krb5/krb5_child.c
index 08e16b4..b730326 100644
--- a/server/providers/krb5/krb5_child.c
+++ b/server/providers/krb5/krb5_child.c
@@ -579,6 +579,7 @@ static errno_t changepw_child(int fd, struct krb5_req *kr)
                       result_string.length, result_string.data));
         }
 
+        pam_status = PAM_AUTHTOK_ERR;
         goto sendresponse;
     }
 
diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c
index fbb4e53..1d1346c 100644
--- a/server/providers/ldap/ldap_auth.c
+++ b/server/providers/ldap/ldap_auth.c
@@ -772,7 +772,7 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
         if (pw_expire_type == PWEXPIRE_SHADOW) {
 /* TODO: implement async ldap modify request */
             DEBUG(1, ("Changing shadow password attributes not implemented.\n"));
-            state->pd->pam_status = PAM_SYSTEM_ERR;
+            state->pd->pam_status = PAM_MODULE_UNKNOWN;
             goto done;
         } else {
             subreq = sdap_exop_modify_passwd_send(state,
@@ -791,7 +791,9 @@ static void sdap_auth4chpass_done(struct tevent_req *req)
             return;
         }
         break;
-
+    case SDAP_AUTH_FAILED:
+        state->pd->pam_status = PAM_AUTH_ERR;
+        break;
     default:
         state->pd->pam_status = PAM_SYSTEM_ERR;
     }
@@ -821,7 +823,7 @@ static void sdap_pam_chpass_done(struct tevent_req *req)
         dp_err = DP_ERR_OK;
         break;
     default:
-        state->pd->pam_status = PAM_SYSTEM_ERR;
+        state->pd->pam_status = PAM_AUTHTOK_ERR;
     }
 
 done:
diff --git a/server/responder/pam/pamsrv_cmd.c b/server/responder/pam/pamsrv_cmd.c
index 3172a97..69e492c 100644
--- a/server/responder/pam/pamsrv_cmd.c
+++ b/server/responder/pam/pamsrv_cmd.c
@@ -484,50 +484,68 @@ static void pam_reply(struct pam_auth_req *preq)
     struct tevent_req *req;
     struct sysdb_ctx *sysdb;
     struct pam_ctx *pctx;
+    uint32_t user_info_type;
 
     pd = preq->pd;
 
     DEBUG(4, ("pam_reply get called.\n"));
 
-    if ((pd->cmd == SSS_PAM_AUTHENTICATE) &&
-        (preq->domain != NULL) &&
-        (preq->domain->cache_credentials == true) &&
-        (pd->offline_auth == false)) {
+    if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
+        switch(pd->cmd) {
+            case SSS_PAM_AUTHENTICATE:
+                if ((preq->domain != NULL) &&
+                    (preq->domain->cache_credentials == true) &&
+                    (pd->offline_auth == false)) {
 
-        if (pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
-            /* do auth with offline credentials */
-            pd->offline_auth = true;
+                    /* do auth with offline credentials */
+                    pd->offline_auth = true;
 
-            ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
-                                          preq->domain, &sysdb);
-            if (ret != EOK) {
-                DEBUG(0, ("Fatal: Sysdb CTX not found for this domain!\n"));
-                goto done;
-            }
-
-            pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);
-
-            req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb,
-                                        preq->domain, pd->user, pd->authtok,
-                                        pd->authtok_size, pctx->rctx->cdb);
-            if (req == NULL) {
-                DEBUG(1, ("Failed to setup offline auth"));
-                /* this error is not fatal, continue */
-            } else {
-                tevent_req_set_callback(req, pam_cache_auth_done, preq);
-                return;
-            }
-        }
-    }
+                    ret = sysdb_get_ctx_from_list(preq->cctx->rctx->db_list,
+                                                  preq->domain, &sysdb);
+                    if (ret != EOK) {
+                        DEBUG(0, ("Fatal: Sysdb CTX not found for "
+                                  "domain [%s]!\n", preq->domain->name));
+                        goto done;
+                    }
 
+                    pctx = talloc_get_type(preq->cctx->rctx->pvt_ctx,
+                                           struct pam_ctx);
+
+                    req = sysdb_cache_auth_send(preq, preq->cctx->ev, sysdb,
+                                                preq->domain, pd->user,
+                                                pd->authtok, pd->authtok_size,
+                                                pctx->rctx->cdb);
+                    if (req == NULL) {
+                        DEBUG(1, ("Failed to setup offline auth"));
+                        /* this error is not fatal, continue */
+                    } else {
+                        tevent_req_set_callback(req, pam_cache_auth_done, preq);
+                        return;
+                    }
+                }
+                break;
+            case SSS_PAM_CHAUTHTOK_PRELIM:
+            case SSS_PAM_CHAUTHTOK:
+                DEBUG(5, ("Password change not possible while offline"));
+                pd->pam_status = PAM_AUTHTOK_ERR;
+                user_info_type = SSS_PAM_USER_INFO_OFFLINE_CHPASS;
+                pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
+                                 (const uint8_t *) &user_info_type);
+                break;
 /* TODO: we need the pam session cookie here to make sure that cached
  * authentication was successful */
-    if ((pd->cmd == SSS_PAM_SETCRED || pd->cmd == SSS_PAM_ACCT_MGMT ||
-         pd->cmd == SSS_PAM_OPEN_SESSION || pd->cmd == SSS_PAM_CLOSE_SESSION) &&
-        pd->pam_status == PAM_AUTHINFO_UNAVAIL) {
-        DEBUG(2, ("Assuming offline authentication "
-                  "setting status for pam call %d to PAM_SUCCESS.\n", pd->cmd));
-        pd->pam_status = PAM_SUCCESS;
+            case SSS_PAM_SETCRED:
+            case SSS_PAM_ACCT_MGMT:
+            case SSS_PAM_OPEN_SESSION:
+            case SSS_PAM_CLOSE_SESSION:
+                DEBUG(2, ("Assuming offline authentication setting status for "
+                          "pam call %d to PAM_SUCCESS.\n", pd->cmd));
+                pd->pam_status = PAM_SUCCESS;
+                break;
+            default:
+                DEBUG(1, ("Unknow PAM call [%d].\n", pd->cmd));
+                pd->pam_status = PAM_MODULE_UNKNOWN;
+        }
     }
 
     cctx = preq->cctx;
diff --git a/sss_client/pam_sss.c b/sss_client/pam_sss.c
index 6e238ec..8c970e4 100644
--- a/sss_client/pam_sss.c
+++ b/sss_client/pam_sss.c
@@ -475,6 +475,27 @@ static int user_info_offline_auth_delayed(pam_handle_t *pamh, size_t buflen,
     return PAM_SUCCESS;
 }
 
+static int user_info_offline_chpass(pam_handle_t *pamh, size_t buflen,
+                                    uint8_t *buf)
+{
+    int ret;
+
+    if (buflen != sizeof(uint32_t)) {
+        D(("User info response data has the wrong size"));
+        return PAM_BUF_ERR;
+    }
+
+    ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
+                              _("System is offline, password change not possible"),
+                              NULL, NULL);
+    if (ret != PAM_SUCCESS) {
+        D(("do_pam_conversation failed."));
+        return PAM_SYSTEM_ERR;
+    }
+
+    return PAM_SUCCESS;
+}
+
 static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
                                    uint8_t *buf)
 {
@@ -495,6 +516,9 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
         case SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED:
             ret = user_info_offline_auth_delayed(pamh, buflen, buf);
             break;
+        case SSS_PAM_USER_INFO_OFFLINE_CHPASS:
+            ret = user_info_offline_chpass(pamh, buflen, buf);
+            break;
         default:
             D(("Unknown user info type [%d]", type));
             ret = PAM_SYSTEM_ERR;
diff --git a/sss_client/sss_cli.h b/sss_client/sss_cli.h
index 9546961..55d5a28 100644
--- a/sss_client/sss_cli.h
+++ b/sss_client/sss_cli.h
@@ -179,7 +179,8 @@ enum response_type {
 
 enum user_info_type {
     SSS_PAM_USER_INFO_OFFLINE_AUTH = 0x01,
-    SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED
+    SSS_PAM_USER_INFO_OFFLINE_AUTH_DELAYED,
+    SSS_PAM_USER_INFO_OFFLINE_CHPASS
 };
 
 enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
-- 
1.6.6



More information about the sssd-devel mailing list