[SSSD] [PATCH] KRB5: Do not attemtp to get a TGT after a password change using OTP

Jakub Hrozek jhrozek at redhat.com
Tue Mar 18 19:09:45 UTC 2014


On Tue, Mar 18, 2014 at 06:20:41PM +0100, Jakub Hrozek wrote:
> On Tue, Mar 18, 2014 at 01:14:45PM -0400, Nathaniel McCallum wrote:
> > The patch looks okay to me. There is however, a spelling error in the commit message: "attemtp".
> 
> Nice catch. A new patch (which only differs in the commit message) is
> attached.

One more respin -- this time, if there was no ccache with this user's
principal after the chpass, we print a warning message telling the user
to log out and back in. Would you prefer if the message was printed
every time an OTP password is changed even though the user might posses
a valid TGT?

If you'd like me to build you a test package for easier testing.
-------------- next part --------------
>From 41f59df54a5cd2627e6237d110f9c318eb299d38 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 18 Mar 2014 16:48:11 +0100
Subject: [PATCH] KRB5: Do not attempt to get a TGT after a password change
 using OTP

https://fedorahosted.org/sssd/ticket/2271

The current krb5_child code attempts to get a TGT for the convenience of
the user using the new password after a password change operation.
However, an OTP should never be used twice, which means we can't perform
the kinit operation after chpass is finished. Instead, we only print a
DEBUG information instructing the user to kinit manually.
---
 src/providers/krb5/krb5_auth.c  | 21 ++++++++++++++++++---
 src/providers/krb5/krb5_child.c | 14 ++++++++++++++
 src/sss_client/pam_sss.c        | 19 +++++++++++++++++++
 src/sss_client/sss_cli.h        |  3 +++
 4 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 661084ad3963ab98dd2941e18b8fa9046ace1144..f539d5068ec29f7b06f734a3417864b43122b1b7 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -827,6 +827,7 @@ static void krb5_auth_done(struct tevent_req *subreq)
     char *renew_interval_str;
     time_t renew_interval_time = 0;
     bool use_enterprise_principal;
+    uint32_t user_info_type;
 
     ret = handle_child_recv(subreq, pd, &buf, &len);
     talloc_zfree(subreq);
@@ -1076,9 +1077,23 @@ static void krb5_auth_done(struct tevent_req *subreq)
 
     ret = sss_krb5_check_ccache_princ(kr->uid, kr->gid, kr->ccname, kr->upn);
     if (ret) {
-        DEBUG(SSSDBG_CRIT_FAILURE,
-                "No ccache for %s in %s?\n", kr->upn, kr->ccname);
-        goto done;
+        if (res->otp == true && pd->cmd == SSS_PAM_CHAUTHTOK) {
+            DEBUG(SSSDBG_IMPORTANT_INFO,
+                  "Password change succeeded but currently "
+                  "post-chpass kinit is not implemented\n");
+
+            user_info_type = SSS_PAM_USER_INFO_OTP_CHPASS;
+            ret = pam_add_response(pd, SSS_PAM_USER_INFO, sizeof(uint32_t),
+                                   (const uint8_t *) &user_info_type);
+            if (ret != EOK) {
+                DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n");
+                /* Not fatal */
+            }
+        } else {
+            DEBUG(SSSDBG_CRIT_FAILURE,
+                  "No ccache for %s in %s?\n", kr->upn, kr->ccname);
+            goto done;
+        }
     }
 
     if (kr->old_ccname) {
diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c
index 1bff0e99b586e0b1a54a660320f91cdab275fbe1..a36ecae4da8c4791018923a6a35f9aff6c6577c8 100644
--- a/src/providers/krb5/krb5_child.c
+++ b/src/providers/krb5/krb5_child.c
@@ -45,6 +45,7 @@ struct krb5_req {
     krb5_principal princ;
     char* name;
     krb5_creds *creds;
+    bool otp;
     krb5_get_init_creds_opt *options;
 
     struct pam_data *pd;
@@ -287,6 +288,8 @@ static krb5_error_code answer_otp(krb5_context ctx,
         goto done;
     }
 
+    kr->otp = true;
+
     /* Validate our assumptions about the contents of authtok. */
     ret = sss_authtok_get_password(kr->pd->authtok, &pwd, &len);
     if (ret != EOK)
@@ -612,6 +615,8 @@ static errno_t k5c_send_data(struct krb5_req *kr, int fd, errno_t error)
     size_t len;
     int ret;
 
+    DEBUG(SSSDBG_FUNC_DATA, "Received error %d\n", error);
+
     ret = pack_response_packet(kr, error, kr->pd->resp_list, &buf, &len);
     if (ret != EOK) {
         DEBUG(SSSDBG_CRIT_FAILURE, "pack_response_packet failed.\n");
@@ -1022,6 +1027,8 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim)
     uint8_t *msg;
 
     DEBUG(SSSDBG_TRACE_LIBS, "Password change operation\n");
+    DEBUG(SSSDBG_TRACE_INTERNAL,
+          "chpass is%s using OTP\n", kr->otp ? "" : " not");
 
     ret = sss_authtok_get_password(kr->pd->authtok, &password, NULL);
     if (ret != EOK) {
@@ -1046,6 +1053,8 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim)
                                         prompter, kr, 0,
                                         SSSD_KRB5_CHANGEPW_PRINCIPAL,
                                         kr->options);
+    DEBUG(SSSDBG_TRACE_INTERNAL,
+          "chpass is%s using OTP\n", kr->otp ? "" : " not");
     if (kerr != 0) {
         ret = pack_user_info_chpass_error(kr->pd, "Old password not accepted.",
                                           &msg_len, &msg);
@@ -1145,6 +1154,11 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim)
 
     krb5_free_cred_contents(kr->ctx, kr->creds);
 
+    if (kr->otp == true) {
+        sss_authtok_set_empty(kr->pd->newauthtok);
+        return map_krb5_error(kerr);
+    }
+
     kerr = get_and_save_tgt(kr, newpassword);
 
     sss_authtok_set_empty(kr->pd->newauthtok);
diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c
index 32558fac9b18e5f62b8968f6fbfbada6c9b3f504..ddf4ded7cc509408dc022c8384e87176cf005e23 100644
--- a/src/sss_client/pam_sss.c
+++ b/src/sss_client/pam_sss.c
@@ -763,6 +763,22 @@ static int user_info_offline_chpass(pam_handle_t *pamh)
     return PAM_SUCCESS;
 }
 
+static int user_info_otp_chpass(pam_handle_t *pamh)
+{
+    int ret;
+
+    ret = do_pam_conversation(pamh, PAM_TEXT_INFO,
+                              _("After changing the OTP password, you need to "
+                                "log out and back in order to acquire a ticket"),
+                              NULL, NULL);
+    if (ret != PAM_SUCCESS) {
+        D(("do_pam_conversation failed."));
+        return PAM_SYSTEM_ERR;
+    }
+
+    return PAM_SUCCESS;
+}
+
 static int user_info_chpass_error(pam_handle_t *pamh, size_t buflen,
                                   uint8_t *buf)
 {
@@ -848,6 +864,9 @@ static int eval_user_info_response(pam_handle_t *pamh, size_t buflen,
         case SSS_PAM_USER_INFO_OFFLINE_CHPASS:
             ret = user_info_offline_chpass(pamh);
             break;
+        case SSS_PAM_USER_INFO_OTP_CHPASS:
+            ret = user_info_otp_chpass(pamh);
+            break;
         case SSS_PAM_USER_INFO_CHPASS_ERROR:
             ret = user_info_chpass_error(pamh, buflen, buf);
             break;
diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h
index 285a2979addb0c0677527b76b3b6755f2f173815..16a08e1869bb81ede2c1db87f1fb6d0a51087847 100644
--- a/src/sss_client/sss_cli.h
+++ b/src/sss_client/sss_cli.h
@@ -451,6 +451,9 @@ enum user_info_type {
                                        * possible to change the password while
                                        * the system is offline. This message
                                        * is generated by the PAM responder. */
+    SSS_PAM_USER_INFO_OTP_CHPASS,   /**< Tell the user that he needs to kinit
+                                      * or login and logout to get a TGT after
+                                      * an OTP password change */
     SSS_PAM_USER_INFO_CHPASS_ERROR, /**< Tell the user that a password change
                                      * failed and optionally give a reason.
                                      * @param Size of the message as unsigned
-- 
1.8.5.3



More information about the sssd-devel mailing list