diff options
author | Sumit Bose <sbose@redhat.com> | 2010-12-21 13:30:33 +0100 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2011-01-19 09:53:20 -0500 |
commit | 22f4c1b86dcf5589e63f2ae043dc65a8f72f6f18 (patch) | |
tree | fb69e82eea580199f7919ecf02a83b3339b8dbcc | |
parent | 5352c9b3609bca63814f9f6f03dbbbadf6c6333a (diff) | |
download | sssd-22f4c1b86dcf5589e63f2ae043dc65a8f72f6f18.tar.gz sssd-22f4c1b86dcf5589e63f2ae043dc65a8f72f6f18.tar.xz sssd-22f4c1b86dcf5589e63f2ae043dc65a8f72f6f18.zip |
Add LDAP expire policy based on AD attributes
The second bit of userAccountControl is used to determine if the account
is enabled or disabled. accountExpires is checked to see if the account
is expired.
-rw-r--r-- | src/config/SSSDConfig.py | 2 | ||||
-rw-r--r-- | src/config/etc/sssd.api.d/sssd-ldap.conf | 2 | ||||
-rw-r--r-- | src/man/sssd-ldap.5.xml | 35 | ||||
-rw-r--r-- | src/providers/ipa/ipa_common.c | 4 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.c | 8 | ||||
-rw-r--r-- | src/providers/ldap/ldap_init.c | 3 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 5 | ||||
-rw-r--r-- | src/providers/ldap/sdap_access.c | 85 | ||||
-rw-r--r-- | src/providers/ldap/sdap_access.h | 1 |
9 files changed, 141 insertions, 4 deletions
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index b3861a553..d84509c1b 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -172,6 +172,8 @@ option_strings = { 'ldap_user_krb_last_pwd_change' : _('krbLastPwdChange attribute'), 'ldap_user_krb_password_expiration' : _('krbPasswordExpiration attribute'), 'ldap_pwd_attribute' : _('Attribute indicating that server side password policies are active'), + 'ldap_user_ad_account_expires' : _('accountExpires attribute of AD'), + 'ldap_user_ad_user_account_control' : _('userAccountControl attribute of AD'), 'ldap_group_search_base' : _('Base DN for group lookups'), # not used # 'ldap_group_search_scope' : _('Scope of group lookups'), diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf index 8aaecd5db..064438316 100644 --- a/src/config/etc/sssd.api.d/sssd-ldap.conf +++ b/src/config/etc/sssd.api.d/sssd-ldap.conf @@ -58,6 +58,8 @@ ldap_user_krb_last_pwd_change = str, None, false ldap_user_krb_password_expiration = str, None, false ldap_user_authorized_service = str, None, false ldap_pwd_attribute = str, None, false +ldap_user_ad_account_expires = str, None, false +ldap_user_ad_user_account_control = str, None, false ldap_group_search_base = str, None, false ldap_group_search_scope = str, None, false ldap_group_search_filter = str, None, false diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml index 175ec3568..65c679d61 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -436,6 +436,34 @@ </varlistentry> <varlistentry> + <term>ldap_user_ad_account_expires (string)</term> + <listitem> + <para> + When using ldap_account_expire_policy=ad, this + parameter contains the name of an LDAP attribute + storing the expiration time of the account. + </para> + <para> + Default: accountExpires + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>ldap_user_ad_user_account_control (string)</term> + <listitem> + <para> + When using ldap_account_expire_policy=ad, this + parameter contains the name of an LDAP attribute + storing the user account control bit field. + </para> + <para> + Default: userAccountControl + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>ldap_user_principal (string)</term> <listitem> <para> @@ -1128,6 +1156,13 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com is expired. </para> <para> + <emphasis>ad</emphasis>: use the value of the 32bit + field ldap_user_ad_user_account_control and allow + access if the second bit is not set. If the + attribute is missing access is granted. Also the + expiration time of the account is checked. + </para> + <para> Default: Empty </para> </listitem> diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 4c96babc1..fe1257737 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -115,7 +115,9 @@ struct sdap_attr_map ipa_user_map[] = { { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }, - { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL } + { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }, + { "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL}, + { "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL} }; struct sdap_attr_map ipa_group_map[] = { diff --git a/src/providers/ldap/ldap_common.c b/src/providers/ldap/ldap_common.c index 6daf2c9f5..e98e718b1 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -121,7 +121,9 @@ struct sdap_attr_map rfc2307_user_map[] = { { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }, - { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL } + { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }, + { "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL}, + { "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL} }; struct sdap_attr_map rfc2307_group_map[] = { @@ -161,7 +163,9 @@ struct sdap_attr_map rfc2307bis_user_map[] = { { "ldap_user_krb_last_pwd_change", "krbLastPwdChange", SYSDB_KRBPW_LASTCHANGE, NULL }, { "ldap_user_krb_password_expiration", "krbPasswordExpiration", SYSDB_KRBPW_EXPIRATION, NULL }, { "ldap_pwd_attribute", "pwdAttribute", SYSDB_PWD_ATTRIBUTE, NULL }, - { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL } + { "ldap_user_authorized_service", "authorizedService", SYSDB_AUTHORIZED_SERVICE, NULL }, + { "ldap_user_ad_account_expires", "accountExpires", SYSDB_AD_ACCOUNT_EXPIRES, NULL}, + { "ldap_user_ad_user_account_control", "userAccountControl", SYSDB_AD_USER_ACCOUNT_CONTROL, NULL} }; struct sdap_attr_map rfc2307bis_group_map[] = { diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c index d5dad3607..61f923333 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -345,7 +345,8 @@ int sssm_ldap_access_init(struct be_ctx *bectx, "but no ldap_account_expire_policy configured. " "All domain users will be denied access.\n")); } else { - if (strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_SHADOW) != 0) { + if (strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_SHADOW) != 0 && + strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_AD) != 0) { DEBUG(1, ("Unsupported LDAP account expire policy [%s].\n", dummy)); ret = EINVAL; diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 9ef9b70c7..57f849a16 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -127,6 +127,9 @@ struct sdap_ppolicy_data { #define SYSDB_PWD_ATTRIBUTE "pwdAttribute" +#define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires" +#define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl" + #define SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS "namingContexts" #define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext" @@ -231,6 +234,8 @@ enum sdap_user_attrs { SDAP_AT_KP_EXPIRATION, SDAP_AT_PWD_ATTRIBUTE, SDAP_AT_AUTH_SVC, + SDAP_AT_AD_ACCOUNT_EXPIRES, + SDAP_AT_AD_USER_ACCOUNT_CONTROL, SDAP_OPTS_USER /* attrs counter */ }; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index df433b69e..a3c560d44 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -340,6 +340,84 @@ static errno_t sdap_account_expired_shadow(struct pam_data *pd, return EOK; } +#define UAC_ACCOUNTDISABLE 0x00000002 +#define AD_NEVER_EXP 0x7fffffffffffffffLL +#define AD_TO_UNIX_TIME_CONST 11644473600LL +#define AD_DISABLE_MESSAGE "The user account is disabled on the AD server" +#define AD_EXPIRED_MESSAGE "The user account is expired on the AD server" + +static bool ad_account_expired(uint64_t expiration_time) +{ + time_t now; + int err; + uint64_t nt_now; + + if (expiration_time == 0 || expiration_time == AD_NEVER_EXP) { + return false; + } + + now = time(NULL); + if (now == ((time_t) -1)) { + err = errno; + DEBUG(1, ("time failed [%d][%s].\n", err, strerror(err))); + return true; + } + + /* NT timestamps start at 1601-01-01 and use a 100ns base */ + nt_now = (now + AD_TO_UNIX_TIME_CONST) * 1000 * 1000 * 10; + + if (nt_now > expiration_time) { + return true; + } + + return false; +} + +static errno_t sdap_account_expired_ad(struct pam_data *pd, + struct ldb_message *user_entry, + int *pam_status) +{ + uint32_t uac; + uint64_t expiration_time; + int ret; + + DEBUG(6, ("Performing AD access check for user [%s]\n", pd->user)); + + uac = ldb_msg_find_attr_as_uint(user_entry, SYSDB_AD_USER_ACCOUNT_CONTROL, + 0); + DEBUG(9, ("User account control for user [%s] is [%X].\n", + pd->user, uac)); + + expiration_time = ldb_msg_find_attr_as_uint64(user_entry, + SYSDB_AD_ACCOUNT_EXPIRES, 0); + DEBUG(9, ("Expiration time for user [%s] is [%lld].\n", + pd->user, expiration_time)); + + if (uac & UAC_ACCOUNTDISABLE) { + *pam_status = PAM_PERM_DENIED; + + ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, + sizeof(AD_DISABLE_MESSAGE), + (const uint8_t *) AD_DISABLE_MESSAGE); + if (ret != EOK) { + DEBUG(1, ("pam_add_response failed.\n")); + } + } else if (ad_account_expired(expiration_time)) { + *pam_status = PAM_ACCT_EXPIRED; + + ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, + sizeof(AD_EXPIRED_MESSAGE), + (const uint8_t *) AD_EXPIRED_MESSAGE); + if (ret != EOK) { + DEBUG(1, ("pam_add_response failed.\n")); + } + } else { + *pam_status = PAM_SUCCESS; + } + + return EOK; +} + struct sdap_account_expired_req_ctx { int pam_status; }; @@ -379,6 +457,13 @@ static struct tevent_req *sdap_account_expired_send(TALLOC_CTX *mem_ctx, DEBUG(1, ("sdap_account_expired_shadow failed.\n")); goto done; } + } else if (strcasecmp(expire, LDAP_ACCOUNT_EXPIRE_AD) == 0) { + ret = sdap_account_expired_ad(pd, user_entry, + &state->pam_status); + if (ret != EOK) { + DEBUG(1, ("sdap_account_expired_ad failed.\n")); + goto done; + } } else { DEBUG(1, ("Unsupported LDAP account expire policy [%s]. " "Access denied.\n", expire)); diff --git a/src/providers/ldap/sdap_access.h b/src/providers/ldap/sdap_access.h index 66193a6dd..28c857f61 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -34,6 +34,7 @@ #define LDAP_ACCESS_SERVICE_NAME "authorized_service" #define LDAP_ACCOUNT_EXPIRE_SHADOW "shadow" +#define LDAP_ACCOUNT_EXPIRE_AD "ad" enum ldap_access_rule { LDAP_ACCESS_EMPTY = -1, |