From a2feac9bb5f6fde16d992a7e0b30cccb103a7000 Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik 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 #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