URL: https://github.com/SSSD/sssd/pull/269 Author: NWilson Title: #269: Add support for ActiveDirectory's logonHours restrictions Action: opened
PR body: """ This is a straightforward patch for denying access to a user when the user is not permitted to access their account due to logonHours restrictions. This matches the default behaviour for domain-joined Windows machines. When outside the logonHours, all types of authentication are denied (password/Kerberos/certificate) - so it is appropriate to put this check inside the PAM "account" rules. """ To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/269/head:pr269 git checkout pr269
From a1fb09cd1a7dd6df285e27850917e9437d166764 Mon Sep 17 00:00:00 2001 From: Nicholas Wilson <nicholas.wil...@realvnc.com> Date: Thu, 11 May 2017 13:38:24 +0100 Subject: [PATCH] Add support for ActiveDirectory's logonHours restrictions --- src/config/SSSDConfig/__init__.py.in | 1 + src/config/cfg_rules.ini | 1 + src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + src/db/sysdb.h | 1 + src/man/sssd-ldap.5.xml | 14 +++++++++ src/providers/ad/ad_opts.c | 1 + src/providers/ipa/ipa_opts.c | 1 + src/providers/ldap/ldap_opts.c | 3 ++ src/providers/ldap/sdap.h | 1 + src/providers/ldap/sdap_access.c | 50 ++++++++++++++++++++++++++++++++ src/responder/nss/nss_cmd.c | 1 + src/responder/nss/nss_protocol_sid.c | 1 + 12 files changed, 76 insertions(+) diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in index 5ca31cf..bd41d7a 100644 --- a/src/config/SSSDConfig/__init__.py.in +++ b/src/config/SSSDConfig/__init__.py.in @@ -347,6 +347,7 @@ option_strings = { '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_user_ad_logon_hours' : _('logonHours attribute of AD'), 'ldap_ns_account_lock' : _('nsAccountLock attribute'), 'ldap_user_nds_login_disabled' : _('loginDisabled attribute of NDS'), 'ldap_user_nds_login_expiration_time' : _('loginExpirationTime attribute of NDS'), diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini index 64cb147..7ae7c26 100644 --- a/src/config/cfg_rules.ini +++ b/src/config/cfg_rules.ini @@ -654,6 +654,7 @@ option = ldap_tls_reqcert option = ldap_uri option = ldap_user_ad_account_expires option = ldap_user_ad_user_account_control +option = ldap_user_ad_logon_hours option = ldap_user_authorized_host option = ldap_user_authorized_service option = ldap_user_auth_type diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf index c2ad346..67ea7cc 100644 --- a/src/config/etc/sssd.api.d/sssd-ldap.conf +++ b/src/config/etc/sssd.api.d/sssd-ldap.conf @@ -79,6 +79,7 @@ ldap_user_authorized_host = 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_user_ad_logon_hours = str, None, false ldap_ns_account_lock = str, None, false ldap_user_nds_login_disabled = str, None, false ldap_user_nds_login_expiration_time = str, None, false diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 62c561b..ff803d6 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -173,6 +173,7 @@ #define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires" #define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl" +#define SYSDB_AD_LOGON_HOURS "adLogonHours" #define SYSDB_DEFAULT_VIEW_NAME "default" #define SYSDB_LOCAL_VIEW_NAME "LOCAL" /* reserved for client-side overrides */ diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml index 739ae15..b0094f4 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -566,6 +566,20 @@ </varlistentry> <varlistentry> + <term>ldap_user_ad_logon_hours (string)</term> + <listitem> + <para> + When using ldap_account_expire_policy=ad, this + parameter contains the name of an LDAP attribute + storing the user's permitted logon hours. + </para> + <para> + Default: logonHours + </para> + </listitem> + </varlistentry> + + <varlistentry> <term>ldap_ns_account_lock (string)</term> <listitem> <para> diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c index fc1dc67..2ebddfc 100644 --- a/src/providers/ad/ad_opts.c +++ b/src/providers/ad/ad_opts.c @@ -211,6 +211,7 @@ struct sdap_attr_map ad_2008r2_user_map[] = { { "ldap_user_authorized_service", NULL, 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}, + { "ldap_user_ad_logon_hours", "logonHours", SYSDB_AD_LOGON_HOURS, NULL}, { "ldap_ns_account_lock", NULL, SYSDB_NS_ACCOUNT_LOCK, NULL}, { "ldap_user_authorized_host", NULL, SYSDB_AUTHORIZED_HOST, NULL }, { "ldap_user_nds_login_disabled", NULL, SYSDB_NDS_LOGIN_DISABLED, NULL }, diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c index f9f3a2a..88b402c 100644 --- a/src/providers/ipa/ipa_opts.c +++ b/src/providers/ipa/ipa_opts.c @@ -196,6 +196,7 @@ struct sdap_attr_map ipa_user_map[] = { { "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}, + { "ldap_user_ad_logon_hours", "logonHours", SYSDB_AD_LOGON_HOURS, NULL}, { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c index c6efe33..01a3687 100644 --- a/src/providers/ldap/ldap_opts.c +++ b/src/providers/ldap/ldap_opts.c @@ -172,6 +172,7 @@ struct sdap_attr_map rfc2307_user_map[] = { { "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}, + { "ldap_user_ad_logon_hours", "logonHours", SYSDB_AD_LOGON_HOURS, NULL}, { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, @@ -230,6 +231,7 @@ struct sdap_attr_map rfc2307bis_user_map[] = { { "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}, + { "ldap_user_ad_logon_hours", "logonHours", SYSDB_AD_LOGON_HOURS, NULL}, { "ldap_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, @@ -288,6 +290,7 @@ struct sdap_attr_map gen_ad2008r2_user_map[] = { { "ldap_user_authorized_service", NULL, 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}, + { "ldap_user_ad_logon_hours", "logonHours", SYSDB_AD_LOGON_HOURS, NULL}, { "ldap_ns_account_lock", NULL, SYSDB_NS_ACCOUNT_LOCK, NULL}, { "ldap_user_authorized_host", NULL, SYSDB_AUTHORIZED_HOST, NULL }, { "ldap_user_nds_login_disabled", NULL, SYSDB_NDS_LOGIN_DISABLED, NULL }, diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index afdc019..2e57ad5 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -277,6 +277,7 @@ enum sdap_user_attrs { SDAP_AT_AUTH_SVC, SDAP_AT_AD_ACCOUNT_EXPIRES, SDAP_AT_AD_USER_ACCOUNT_CONTROL, + SDAP_AT_AD_LOGON_HOURS, SDAP_AT_NS_ACCOUNT_LOCK, SDAP_AT_AUTHORIZED_HOST, SDAP_AT_NDS_LOGIN_DISABLED, diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 6e8af73..475a9f7 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -426,6 +426,8 @@ static errno_t sdap_account_expired_shadow(struct pam_data *pd, #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" +#define AD_OUTSIDE_LOGONHOURS_MESSAGE \ + "Outside of the user's login hours on the AD server" static bool ad_account_expired(uint64_t expiration_time) { @@ -455,11 +457,41 @@ static bool ad_account_expired(uint64_t expiration_time) return false; } +static bool ad_account_outside_logonhours(const uint8_t *data) +{ + time_t now; + struct tm tm; + int hour_of_week, err; + + if (data == NULL) { + return false; + } + + now = time(NULL); + if (now == ((time_t) -1)) { + err = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "time failed [%d][%s].\n", err, strerror(err)); + return true; + } + + if (gmtime_r(&now, &tm) == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "gmtime_r failed.\n"); + return true; + } + + hour_of_week = tm.tm_wday * 24 + tm.tm_hour; + hour_of_week = MAX(0, MIN(hour_of_week, 167)); + + return !(data[hour_of_week / 8] & (1 << (hour_of_week % 8))); +} + static errno_t sdap_account_expired_ad(struct pam_data *pd, struct ldb_message *user_entry) { uint32_t uac; uint64_t expiration_time; + const struct ldb_val *logon_hours; int ret; DEBUG(SSSDBG_TRACE_FUNC, @@ -476,6 +508,13 @@ static errno_t sdap_account_expired_ad(struct pam_data *pd, "Expiration time for user [%s] is [%"PRIu64"].\n", pd->user, expiration_time); + logon_hours = ldb_msg_find_ldb_val(user_entry, SYSDB_AD_LOGON_HOURS); + if (logon_hours != NULL && logon_hours->length != 21) { + logon_hours = NULL; + } + DEBUG(SSSDBG_TRACE_ALL, "Logon hours for user [%s] are %s.\n", + pd->user, logon_hours ? "set" : "unset"); + if (uac & UAC_ACCOUNTDISABLE) { ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, @@ -497,6 +536,17 @@ static errno_t sdap_account_expired_ad(struct pam_data *pd, } return ERR_ACCOUNT_EXPIRED; + + } else if (ad_account_outside_logonhours(logon_hours->data)) { + + ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, + sizeof(AD_OUTSIDE_LOGONHOURS_MESSAGE), + (const uint8_t *) AD_OUTSIDE_LOGONHOURS_MESSAGE); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); + } + + return ERR_ACCESS_DENIED; } return EOK; diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c index a4727c1..c613ab4 100644 --- a/src/responder/nss/nss_cmd.c +++ b/src/responder/nss/nss_cmd.c @@ -984,6 +984,7 @@ static errno_t nss_cmd_getorigbyname(struct cli_ctx *cli_ctx) SYSDB_DEFAULT_OVERRIDE_NAME, SYSDB_AD_ACCOUNT_EXPIRES, SYSDB_AD_USER_ACCOUNT_CONTROL, + SYSDB_AD_LOGON_HOURS, SYSDB_SSH_PUBKEY, SYSDB_USER_CERT, SYSDB_USER_EMAIL, diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c index 61357c2..531c214 100644 --- a/src/responder/nss/nss_protocol_sid.c +++ b/src/responder/nss/nss_protocol_sid.c @@ -233,6 +233,7 @@ nss_protocol_fill_orig(struct nss_ctx *nss_ctx, SYSDB_DEFAULT_OVERRIDE_NAME, SYSDB_AD_ACCOUNT_EXPIRES, SYSDB_AD_USER_ACCOUNT_CONTROL, + SYSDB_AD_LOGON_HOURS, SYSDB_SSH_PUBKEY, SYSDB_USER_CERT, SYSDB_USER_EMAIL,
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org