diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/config/SSSDConfig.py | 3 | ||||
| -rw-r--r-- | src/config/etc/sssd.api.d/sssd-ldap.conf | 3 | ||||
| -rw-r--r-- | src/man/sssd-ldap.5.xml | 50 | ||||
| -rw-r--r-- | src/providers/ipa/ipa_common.c | 5 | ||||
| -rw-r--r-- | src/providers/ldap/ldap_common.c | 10 | ||||
| -rw-r--r-- | src/providers/ldap/ldap_init.c | 1 | ||||
| -rw-r--r-- | src/providers/ldap/sdap.h | 6 | ||||
| -rw-r--r-- | src/providers/ldap/sdap_access.c | 177 | ||||
| -rw-r--r-- | src/providers/ldap/sdap_access.h | 1 | 
9 files changed, 253 insertions, 3 deletions
diff --git a/src/config/SSSDConfig.py b/src/config/SSSDConfig.py index 2af4892b..16d3d357 100644 --- a/src/config/SSSDConfig.py +++ b/src/config/SSSDConfig.py @@ -190,6 +190,9 @@ option_strings = {      'ldap_user_ad_account_expires' : _('accountExpires attribute of AD'),      'ldap_user_ad_user_account_control' : _('userAccountControl 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'), +    'ldap_user_nds_login_allowed_time_map' : _('loginAllowedTimeMap attribute of NDS'),      '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 ce9ec513..18321cad 100644 --- a/src/config/etc/sssd.api.d/sssd-ldap.conf +++ b/src/config/etc/sssd.api.d/sssd-ldap.conf @@ -67,6 +67,9 @@ ldap_pwd_attribute = str, None, false  ldap_user_ad_account_expires = str, None, false  ldap_user_ad_user_account_control = 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 +ldap_user_nds_login_allowed_time_map = 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 e554cac4..7c364abe 100644 --- a/src/man/sssd-ldap.5.xml +++ b/src/man/sssd-ldap.5.xml @@ -493,6 +493,47 @@                  </varlistentry>                  <varlistentry> +                    <term>ldap_user_nds_login_disabled (string)</term> +                    <listitem> +                        <para> +                            When using ldap_account_expire_policy=nds, this +                            attribute determines if access is allowed or not. +                        </para> +                        <para> +                            Default: loginDisabled +                        </para> +                    </listitem> +                </varlistentry> + +                <varlistentry> +                    <term>ldap_user_nds_login_expiration_time (string)</term> +                    <listitem> +                        <para> +                            When using ldap_account_expire_policy=nds, this +                            attribute determines until which date access is +                            granted. +                        </para> +                        <para> +                            Default: loginDisabled +                        </para> +                    </listitem> +                </varlistentry> + +                <varlistentry> +                    <term>ldap_user_nds_login_allowed_time_map (string)</term> +                    <listitem> +                        <para> +                            When using ldap_account_expire_policy=nds, this +                            attribute determines the hours of a day in a week +                            when access is granted. +                        </para> +                        <para> +                            Default: loginAllowedTimeMap +                        </para> +                    </listitem> +                </varlistentry> + +                <varlistentry>                      <term>ldap_user_principal (string)</term>                      <listitem>                          <para> @@ -1296,6 +1337,15 @@ ldap_access_filter = memberOf=cn=allowedusers,ou=Groups,dc=example,dc=com                              access is allowed or not.                          </para>                          <para> +                            <emphasis>nds</emphasis>: the values of +                            ldap_user_nds_login_allowed_time_map, +                            ldap_user_nds_login_disabled and +                            ldap_user_nds_login_expiration_time are used to +                            check if access is allowed. If both attributes are +                            missing access is granted. +                            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="include/experimental.xml" /> +                        </para> +                        <para>                              Default: Empty                          </para>                      </listitem> diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c index 55a19724..9fbf9baa 100644 --- a/src/providers/ipa/ipa_common.c +++ b/src/providers/ipa/ipa_common.c @@ -134,7 +134,10 @@ struct sdap_attr_map ipa_user_map[] = {      { "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_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, -    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL } +    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, +    { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, +    { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL }, +    { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, 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 5b75cf28..b28a348f 100644 --- a/src/providers/ldap/ldap_common.c +++ b/src/providers/ldap/ldap_common.c @@ -135,7 +135,10 @@ struct sdap_attr_map rfc2307_user_map[] = {      { "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_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, -    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL } +    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, +    { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, +    { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL }, +    { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, NULL }  };  struct sdap_attr_map rfc2307_group_map[] = { @@ -179,7 +182,10 @@ struct sdap_attr_map rfc2307bis_user_map[] = {      { "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_ns_account_lock", "nsAccountLock", SYSDB_NS_ACCOUNT_LOCK, NULL}, -    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL } +    { "ldap_user_authorized_host", "host", SYSDB_AUTHORIZED_HOST, NULL }, +    { "ldap_user_nds_login_disabled", "loginDisabled", SYSDB_NDS_LOGIN_DISABLED, NULL }, +    { "ldap_user_nds_login_expiration_time", "loginExpirationTime", SYSDB_NDS_LOGIN_EXPIRATION_TIME, NULL }, +    { "ldap_user_nds_login_allowed_time_map", "loginAllowedTimeMap", SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP, 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 62588b77..c00c0a9d 100644 --- a/src/providers/ldap/ldap_init.c +++ b/src/providers/ldap/ldap_init.c @@ -347,6 +347,7 @@ int sssm_ldap_access_init(struct be_ctx *bectx,              } else {                  if (strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_SHADOW) != 0 &&                      strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_AD) != 0 && +                    strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_NDS) != 0 &&                      strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_RHDS) != 0 &&                      strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_IPA) != 0 &&                      strcasecmp(dummy, LDAP_ACCOUNT_EXPIRE_389DS) != 0) { diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 9184090e..baac956b 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -123,6 +123,9 @@ struct sdap_ppolicy_data {  #define SYSDB_AD_ACCOUNT_EXPIRES "adAccountExpires"  #define SYSDB_AD_USER_ACCOUNT_CONTROL "adUserAccountControl" +#define SYSDB_NDS_LOGIN_DISABLED "ndsLoginDisabled" +#define SYSDB_NDS_LOGIN_EXPIRATION_TIME "ndsLoginExpirationTime" +#define SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP "ndsLoginAllowedTimeMap"  #define SDAP_ROOTDSE_ATTR_NAMING_CONTEXTS "namingContexts"  #define SDAP_ROOTDSE_ATTR_DEFAULT_NAMING_CONTEXT "defaultNamingContext" @@ -239,6 +242,9 @@ enum sdap_user_attrs {      SDAP_AT_AD_USER_ACCOUNT_CONTROL,      SDAP_AT_NS_ACCOUNT_LOCK,      SDAP_AT_AUTHORIZED_HOST, +    SDAP_AT_NDS_LOGIN_DISABLED, +    SDAP_AT_NDS_LOGIN_EXPIRATION_TIME, +    SDAP_AT_NDS_LOGIN_ALLOWED_TIME_MAP,      SDAP_OPTS_USER /* attrs counter */  }; diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c index 9b598bc5..9bb2f2ef 100644 --- a/src/providers/ldap/sdap_access.c +++ b/src/providers/ldap/sdap_access.c @@ -22,6 +22,9 @@      along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ +#define _XOPEN_SOURCE 500 /* for strptime() */ +#include <time.h> +#undef _XOPEN_SOURCE  #include <sys/param.h>  #include <security/pam_modules.h>  #include <talloc.h> @@ -470,6 +473,174 @@ static errno_t sdap_account_expired_rhds(struct pam_data *pd,      return EOK;  } +#define NDS_DISABLE_MSG "The user account is disabled on the server" +#define NDS_EXPIRED_MSG "The user account is expired" +#define NDS_TIME_MAP_MSG "The user account is not allowed at this time" + +static bool nds_check_expired(const char *exp_time_str) +{ +    char *end; +    struct tm tm; +    time_t expire_time; +    time_t now; + +    if (exp_time_str == NULL) { +        DEBUG(9, ("ndsLoginExpirationTime is not set, access granted.\n")); +        return false; +    } + +    memset(&tm, 0, sizeof(tm)); + +    end = strptime(exp_time_str, "%Y%m%d%H%M%SZ", &tm); +    if (end == NULL) { +        DEBUG(1, ("NDS expire date [%s] invalid.\n", exp_time_str)); +        return true; +    } +    if (*end != '\0') { +        DEBUG(1, ("NDS expire date [%s] contains extra characters.\n", +                  exp_time_str)); +        return true; +    } + +    expire_time = mktime(&tm); +    if (expire_time == -1) { +        DEBUG(1, ("mktime failed to convert [%s].\n", exp_time_str)); +        return true; +    } + +    tzset(); +    expire_time -= timezone; +    now = time(NULL); +    DEBUG(9, ("Time info: tzname[0] [%s] tzname[1] [%s] timezone [%d] " +              "daylight [%d] now [%d] expire_time [%d].\n", tzname[0], +              tzname[1], timezone, daylight, now, expire_time)); + +    if (difftime(now, expire_time) > 0.0) { +        DEBUG(4, ("NDS account expired.\n")); +        return true; +    } + +    return false; +} + +/* There is no real documentation of the byte string value of + * loginAllowedTimeMap, but some good example code in + * http://http://developer.novell.com/documentation/samplecode/extjndi_sample/CheckBind.java.html + */ +static bool nds_check_time_map(const struct ldb_val *time_map) +{ +    time_t now; +    struct tm *tm_now; +    size_t map_index; +    div_t q; +    uint8_t mask = 0; + +    if (time_map == NULL) { +        DEBUG(9, ("loginAllowedTimeMap is missing, access granted.\n")); +        return false; +    } + +    if (time_map->length != 42) { +        DEBUG(4, ("Allowed time map has the wrong size, " +                  "got [%d], expected 42.\n", time_map->length)); +        return true; +    } + +    now = time(NULL); +    tm_now = gmtime(&now); + +    map_index = tm_now->tm_wday * 48 + tm_now->tm_hour * 2 + +                (tm_now->tm_min < 30 ? 0 : 1); + +    if (map_index > 335) { +        DEBUG(1, ("Unexpected index value [%d] for time map.\n", index)); +        return true; +    } + +    q = div(map_index, 8); + +    if (q.quot > 41 || q.quot < 0 || q.rem > 7 || q.rem < 0) { +        DEBUG(1, ("Unexpected result of div(), [%d][%d][%d].\n", +                  index, q.quot, q.rem)); +        return true; +    } + +    if (q.rem > 0) { +        mask = 1 << q.rem; +    } + +    if (time_map->data[q.quot] & mask) { +        DEBUG(4, ("Access allowed by time map.\n")); +        return false; +    } + +    return true; +} + +static errno_t sdap_account_expired_nds(struct pam_data *pd, +                                         struct ldb_message *user_entry, +                                         int *pam_status) +{ +    bool locked = true; +    int ret; +    const char *exp_time_str; +    const struct ldb_val *time_map; + +    DEBUG(6, ("Performing NDS access check for user [%s]\n", pd->user)); + +    locked = ldb_msg_find_attr_as_bool(user_entry, SYSDB_NDS_LOGIN_DISABLED, +                                       false); +    DEBUG(9, ("Account for user [%s] is%s disabled.\n", pd->user, +              locked ? "" : " not")); + +    if (locked) { +        ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, +                               sizeof(NDS_DISABLE_MSG), +                               (const uint8_t *) NDS_DISABLE_MSG); +        if (ret != EOK) { +            DEBUG(1, ("pam_add_response failed.\n")); +        } +    } else { +        exp_time_str = ldb_msg_find_attr_as_string(user_entry, +                                                SYSDB_NDS_LOGIN_EXPIRATION_TIME, +                                                NULL); +        locked = nds_check_expired(exp_time_str); + +        DEBUG(9, ("Account for user [%s] is%s expired.\n", pd->user, +                  locked ? "" : " not")); + +        if (locked) { +            ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, +                                   sizeof(NDS_EXPIRED_MSG), +                                   (const uint8_t *) NDS_EXPIRED_MSG); +            if (ret != EOK) { +                DEBUG(1, ("pam_add_response failed.\n")); +            } +        } else { +            time_map = ldb_msg_find_ldb_val(user_entry, +                                            SYSDB_NDS_LOGIN_ALLOWED_TIME_MAP); + +            locked = nds_check_time_map(time_map); + +            DEBUG(9, ("Account for user [%s] is%s locked at this time.\n", +                      pd->user, locked ? "" : " not")); + +            if (locked) { +                ret = pam_add_response(pd, SSS_PAM_SYSTEM_INFO, +                                       sizeof(NDS_TIME_MAP_MSG), +                                       (const uint8_t *) NDS_TIME_MAP_MSG); +                if (ret != EOK) { +                    DEBUG(1, ("pam_add_response failed.\n")); +                } +            } +        } +    } + +    *pam_status = locked ? PAM_PERM_DENIED : PAM_SUCCESS; + +    return EOK; +} +  struct sdap_account_expired_req_ctx {      int pam_status;  }; @@ -525,6 +696,12 @@ static struct tevent_req *sdap_account_expired_send(TALLOC_CTX *mem_ctx,                  DEBUG(1, ("sdap_account_expired_rhds failed.\n"));                  goto done;              } +        } else if (strcasecmp(expire, LDAP_ACCOUNT_EXPIRE_NDS) == 0) { +            ret = sdap_account_expired_nds(pd, user_entry, &state->pam_status); +            if (ret != EOK) { +                DEBUG(1, ("sdap_account_expired_nds 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 d78fdb1e..6263e25d 100644 --- a/src/providers/ldap/sdap_access.h +++ b/src/providers/ldap/sdap_access.h @@ -39,6 +39,7 @@  #define LDAP_ACCOUNT_EXPIRE_RHDS "rhds"  #define LDAP_ACCOUNT_EXPIRE_IPA "ipa"  #define LDAP_ACCOUNT_EXPIRE_389DS "389ds" +#define LDAP_ACCOUNT_EXPIRE_NDS "nds"  enum ldap_access_rule {      LDAP_ACCESS_EMPTY = -1,  | 
