summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@redhat.com>2010-12-21 13:30:33 +0100
committerStephen Gallagher <sgallagh@redhat.com>2011-01-19 09:53:20 -0500
commit22f4c1b86dcf5589e63f2ae043dc65a8f72f6f18 (patch)
treefb69e82eea580199f7919ecf02a83b3339b8dbcc
parent5352c9b3609bca63814f9f6f03dbbbadf6c6333a (diff)
downloadsssd-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.py2
-rw-r--r--src/config/etc/sssd.api.d/sssd-ldap.conf2
-rw-r--r--src/man/sssd-ldap.5.xml35
-rw-r--r--src/providers/ipa/ipa_common.c4
-rw-r--r--src/providers/ldap/ldap_common.c8
-rw-r--r--src/providers/ldap/ldap_init.c3
-rw-r--r--src/providers/ldap/sdap.h5
-rw-r--r--src/providers/ldap/sdap_access.c85
-rw-r--r--src/providers/ldap/sdap_access.h1
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,