Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ActiveDirectory's logonHours restrictions #269

Open
wants to merge 1 commit into
base: master
from
Open
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

Add support for ActiveDirectory's logonHours restrictions

  • Loading branch information...
NWilson committed May 11, 2017
commit a1fb09cd1a7dd6df285e27850917e9437d166764
@@ -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'),
@@ -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
@@ -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
@@ -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 */
@@ -565,6 +565,20 @@
</listitem>
</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>
@@ -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 },
@@ -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 },
@@ -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},

This comment has been minimized.

Copy link
@jhrozek

jhrozek May 16, 2017

Contributor

The generic RFC2307 and RFC2307bis maps should default the attribute value to NULL. Only the AD LDAP map should set the attribute value to logonHours.

{ "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 },
@@ -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,
@@ -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;
@@ -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,
@@ -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,
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.