On (01/03/16 17:45), Lukas Slebodnik wrote:
>On (31/01/16 11:53), Simo Sorce wrote:
>>Expired != Disabled
>>this change is intentional.
>>
>Yes, but explain it to Active directory :-)
>
>Attached is patch with workaround/hack
>regression with expired AD users.
>
ENOPATCH

LS
>From a2feac9bb5f6fde16d992a7e0b30cccb103a7000 Mon Sep 17 00:00:00 2001
From: Lukas Slebodnik <lsleb...@redhat.com>
Date: Tue, 1 Mar 2016 15:13:45 +0100
Subject: [PATCH] KRB5: Discern between expired & disabled AD user

Active directory return krb5 error code KRB5KDC_ERR_CLIENT_REVOKED
"-1765328366/Clients credentials have been revoked" for expired and
disabled user. This is difference between AD and IPA
https://fedorahosted.org/sssd/ticket/2924.

Therefore we need to distinguish between these two states.
We can use AD attribute userAccountControl[1] and override
ERR_ACCOUNT_LOCKED returned from krb5_child to ERR_ACCOUNT_EXPIRED
for expired AD user.

[1] https://msdn.microsoft.com/en-us/library/ms680832%28v=vs.85%29.aspx

Related to:
https://fedorahosted.org/sssd/ticket/2924
---
 src/providers/krb5/krb5_auth.c | 53 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c
index 
f69245efdbac2e771e09c35706cd96552de8375d..bf689a947eabec3e1f1b0a21bd308a2d6aa01dda
 100644
--- a/src/providers/krb5/krb5_auth.c
+++ b/src/providers/krb5/krb5_auth.c
@@ -33,6 +33,7 @@
 #include <security/pam_modules.h>
 
 #include "util/util.h"
+#include "util/strtonum.h"
 #include "util/find_uid.h"
 #include "util/auth_utils.h"
 #include "db/sysdb.h"
@@ -787,6 +788,10 @@ done:
     }
 }
 
+static void ad_discern_expired_disabled_user(struct krb5_auth_state *state,
+                                             const char *user,
+                                             int32_t *_msg_status);
+
 static void krb5_auth_done(struct tevent_req *subreq)
 {
     struct tevent_req *req = tevent_req_callback_data(subreq, struct 
tevent_req);
@@ -911,6 +916,8 @@ static void krb5_auth_done(struct tevent_req *subreq)
         }
     }
 
+    ad_discern_expired_disabled_user(state, pd->user, &res->msg_status);
+
     /* If the child request failed, but did not return an offline error code,
      * return with the status */
     switch (res->msg_status) {
@@ -1150,6 +1157,52 @@ done:
 
 }
 
+static void ad_discern_expired_disabled_user(struct krb5_auth_state *state,
+                                             const char *user,
+                                             int32_t *_msg_status)
+{
+    int ret;
+    /* https://msdn.microsoft.com/en-us/library/ms680832%28v=vs.85%29.aspx */
+    const int UAC_ACCOUNTDISABLE = 0x00000002;
+    int32_t msg_status = *_msg_status;
+    struct ldb_result *res = NULL;
+    const char *attrs[] = { SYSDB_AD_USER_ACCOUNT_CONTROL, NULL };
+
+    /* Active directory return krb5 error code KRB5KDC_ERR_CLIENT_REVOKED
+     * "-1765328366/Clients credentials have been revoked" for expired and
+     * disabled user. This is difference between AD and IPA
+     * https://fedorahosted.org/sssd/ticket/2924.
+     *
+     * Therefore we need to distinguish between these two states.
+     * We can use AD attribute userAccountControl and override
+     * ERR_ACCOUNT_LOCKED returned from krb5_child to ERR_ACCOUNT_EXPIRED
+     * for expired user.
+     */
+    if (msg_status == ERR_ACCOUNT_LOCKED) {
+        ret = sysdb_get_user_attr_with_views(state, state->domain, user, attrs,
+                                             &res);
+        if (ret == EOK && res->count == 1) {
+            const char *uac_str;
+            uac_str = ldb_msg_find_attr_as_string(res->msgs[0],
+                                                  
SYSDB_AD_USER_ACCOUNT_CONTROL,
+                                                  NULL);
+            if (uac_str != NULL) {
+                uint32_t uac;
+                char *endptr;
+                errno_t error;
+
+                uac = strtouint32(uac_str, &endptr, 10);
+                error = errno;
+                if (error == 0 && (uac & UAC_ACCOUNTDISABLE) == 0) {
+                    *_msg_status = ERR_ACCOUNT_EXPIRED;
+                }
+            }
+        }
+
+        talloc_zfree(res);
+    }
+}
+
 int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err)
 {
     struct krb5_auth_state *state = tevent_req_data(req, struct 
krb5_auth_state);
-- 
2.7.2

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://lists.fedorahosted.org/admin/lists/sssd-devel@lists.fedorahosted.org

Reply via email to