[SSSD] [PATCH] Skip CHAUTHTOK_PRELIM when using OTPs

Jakub Hrozek jhrozek at redhat.com
Mon Dec 1 21:15:43 UTC 2014


Hi,

the attached patch fixes chpass for OTP users for me. I hope looking at
the ipaUserAuthType attribute is acceptable.

The attribute is undocumented on purpose -- I don't see a reason for the
user to set this attribute to a different value and the desription would
just clutter the (already too complex) sssd-ldap man page.

I'm open to adding the attribute to the configAPI, though.
-------------- next part --------------
>From e207f26632a778a56fef8bb4ac51cb8f4730f120 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Thu, 27 Nov 2014 20:29:03 +0100
Subject: [PATCH] Skip CHAUTHTOK_PRELIM when using OTPs

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

When OTPs are used, we can only used each authtoken at most once. When
it comes to Kerberos password changes, this was only working previously
by accident, because the old authtoken was first used to verify the old
password is valid and not expired and then also to acquire a chpass
principal.

This patch looks at the user object in LDAP to check if the user has any
OTPs enabled. If he does, the CHAUTHTOK_PRELIM step is skipped
completely so that the OTP can be used to acquire the chpass ticket
later.
---
 src/db/sysdb.h                 |  2 ++
 src/providers/ad/ad_opts.h     |  1 +
 src/providers/ipa/ipa_opts.h   |  1 +
 src/providers/krb5/krb5_auth.c | 38 +++++++++++++++++++++++++++++++++++---
 src/providers/ldap/ldap_opts.h |  3 +++
 src/providers/ldap/sdap.h      |  1 +
 6 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 5bd7f90acb685bbaff5c98f433c7dce8175c33ca..4fbbb16718a2fc3d444e4c6dba5fca4c1bb3096a 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -127,6 +127,8 @@
 
 #define SYSDB_SSH_PUBKEY "sshPublicKey"
 
+#define SYSDB_AUTH_TYPE "authType"
+
 #define SYSDB_SUBDOMAIN_REALM "realmName"
 #define SYSDB_SUBDOMAIN_FLAT "flatName"
 #define SYSDB_SUBDOMAIN_ID "domainID"
diff --git a/src/providers/ad/ad_opts.h b/src/providers/ad/ad_opts.h
index c3de3d94b1818665a86bba8a2432c699717b6a34..d9405e5020ca724a0f7caa752ac10fb07d8aa397 100644
--- a/src/providers/ad/ad_opts.h
+++ b/src/providers/ad/ad_opts.h
@@ -212,6 +212,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = {
     { "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
     { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
     { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
     SDAP_ATTR_MAP_TERMINATOR
 };
 
diff --git a/src/providers/ipa/ipa_opts.h b/src/providers/ipa/ipa_opts.h
index f77ff1d05b9540155db44d04d4fb3aac9d7b5988..66af648583e552d7edd932f6bb5a2c3bef107e51 100644
--- a/src/providers/ipa/ipa_opts.h
+++ b/src/providers/ipa/ipa_opts.h
@@ -203,6 +203,7 @@ struct sdap_attr_map ipa_user_map[] = {
     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
     { "ldap_user_ssh_public_key", "ipaSshPubKey", SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_user_auth_type", "ipaUserAuthType", SYSDB_AUTH_TYPE, NULL },
     SDAP_ATTR_MAP_TERMINATOR
 };
 
diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index e791aee1c2d83f84ba617db1d5d93948c0e4e2a1..99233f69fb7367b1f0b38b5369ac855bb82c7907 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -311,6 +311,25 @@ static void krb5_auth_store_creds(struct sss_domain_info *domain,
     }
 }
 
+static bool is_otp_enabled(struct ldb_message *user_msg)
+{
+    struct ldb_message_element *el;
+    size_t i;
+
+    el = ldb_msg_find_element(user_msg, SYSDB_AUTH_TYPE);
+    if (el == NULL) {
+        return false;
+    }
+
+    for (i = 0; i < el->num_values; i++) {
+        if (strcmp((const char * )el->values[i].data, "otp") == 0) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 /* krb5_auth request */
 
 struct krb5_auth_state {
@@ -344,8 +363,9 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
     const char *realm;
     struct tevent_req *req;
     struct tevent_req *subreq;
-    int authtok_type;
+    enum sss_authtok_type authtok_type;
     int ret;
+    bool otp;
 
     req = tevent_req_create(mem_ctx, &state, struct krb5_auth_state);
     if (req == NULL) {
@@ -441,7 +461,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    attrs = talloc_array(state, const char *, 7);
+    attrs = talloc_array(state, const char *, 8);
     if (attrs == NULL) {
         ret = ENOMEM;
         goto done;
@@ -453,7 +473,8 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
     attrs[3] = SYSDB_UIDNUM;
     attrs[4] = SYSDB_GIDNUM;
     attrs[5] = SYSDB_CANONICAL_UPN;
-    attrs[6] = NULL;
+    attrs[6] = SYSDB_AUTH_TYPE;
+    attrs[7] = NULL;
 
     ret = krb5_setup(state, pd, krb5_ctx, &state->kr);
     if (ret != EOK) {
@@ -541,6 +562,17 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx,
         break;
     }
 
+    otp = is_otp_enabled(res->msgs[0]);
+    if (pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM && otp == true) {
+        /* To avoid consuming the OTP */
+        DEBUG(SSSDBG_TRACE_FUNC,
+              "Skipping password checks for OTP-enabled user\n");
+        state->pam_status = PAM_SUCCESS;
+        state->dp_err = DP_ERR_OK;
+        ret = EOK;
+        goto done;
+    }
+
     kr->srv = NULL;
     kr->kpasswd_srv = NULL;
 
diff --git a/src/providers/ldap/ldap_opts.h b/src/providers/ldap/ldap_opts.h
index f46381e9fac7b93730ce0767154989f2e3b7ebbf..7c9ed3e01f726f2ba6ecb2a7268867abd3baa37d 100644
--- a/src/providers/ldap/ldap_opts.h
+++ b/src/providers/ldap/ldap_opts.h
@@ -179,6 +179,7 @@ struct sdap_attr_map rfc2307_user_map[] = {
     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
     { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
     SDAP_ATTR_MAP_TERMINATOR
 };
 
@@ -233,6 +234,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = {
     { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
     { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
     { "ldap_user_ssh_public_key", "sshPublicKey", SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
     SDAP_ATTR_MAP_TERMINATOR
 };
 
@@ -287,6 +289,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = {
     { "ldap_user_nds_login_expiration_time", NULL, SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL },
     { "ldap_user_nds_login_allowed_time_map", NULL, SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL },
     { "ldap_user_ssh_public_key", NULL, SYSDB_SSH_PUBKEY, NULL },
+    { "ldap_user_auth_type", NULL, SYSDB_AUTH_TYPE, NULL },
     SDAP_ATTR_MAP_TERMINATOR
 };
 
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index aa10623a58d7d667205b09e744dc2b924ca821ed..921051b41a911a2d1117672a8e9c2697b679f24e 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -280,6 +280,7 @@ enum sdap_user_attrs {
     SDAP_AT_NDS_LOGIN_EXPIRATION_TIME,
     SDAP_AT_NDS_LOGIN_ALLOWED_TIME_MAP,
     SDAP_AT_USER_SSH_PUBLIC_KEY,
+    SDAP_AT_USER_AUTH_TYPE,
 
     SDAP_OPTS_USER /* attrs counter */
 };
-- 
1.9.3



More information about the sssd-devel mailing list