summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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,