>From 54edfffe7a41216a2267a57bb68525454dbe85e5 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 16 Nov 2009 13:56:57 +0100 Subject: [PATCH] Add ldap_pwd_policy option --- server/config/SSSDConfig.py | 3 + server/config/etc/sssd.api.d/sssd-ldap.conf | 1 + server/man/sssd-ldap.5.xml | 33 ++++++++ server/providers/ldap/ldap_auth.c | 114 ++++++++++++++++---------- server/providers/ldap/ldap_common.c | 18 ++++- server/providers/ldap/ldap_common.h | 4 + server/providers/ldap/sdap.h | 1 + 7 files changed, 129 insertions(+), 45 deletions(-) diff --git a/server/config/SSSDConfig.py b/server/config/SSSDConfig.py index 57d39c7..1cbf1a8 100644 --- a/server/config/SSSDConfig.py +++ b/server/config/SSSDConfig.py @@ -136,6 +136,9 @@ option_strings = { 'ldap_user_member_of' : _('memberOf attribute'), 'ldap_user_modify_timestamp' : _('Modification time attribute'), + # [provider/ldap/auth] + 'ldap_pwd_policy' : _('Policy to evaluate the password expiration'), + # [provider/local/id] 'default_shell' : _('Default shell, /bin/bash'), 'base_directory' : _('Base for home directories'), diff --git a/server/config/etc/sssd.api.d/sssd-ldap.conf b/server/config/etc/sssd.api.d/sssd-ldap.conf index 34aaa65..314f57f 100644 --- a/server/config/etc/sssd.api.d/sssd-ldap.conf +++ b/server/config/etc/sssd.api.d/sssd-ldap.conf @@ -61,6 +61,7 @@ ldap_group_modify_timestamp = str, None ldap_force_upper_case_realm = bool, None [provider/ldap/auth] +ldap_pwd_policy = str, None [provider/ldap/chpass] diff --git a/server/man/sssd-ldap.5.xml b/server/man/sssd-ldap.5.xml index a2aa730..d944392 100644 --- a/server/man/sssd-ldap.5.xml +++ b/server/man/sssd-ldap.5.xml @@ -582,6 +582,39 @@ + + ldap_pwd_policy (string) + + + Select the policy to evaluate the password + expiration on the client side. The following values + are allowed: + + + none No evaluation on the + client side. This option cannot disable server side + password policies. + + + shadow use + shadow + 5 style + attributes to evaluate if the password is expired. + Please note that the current version of sssd cannot + update this attribute during a password change. + + + mit_kerberos use the attributes + used by MIT Kerberos to evaluate if the password is + expired. Use chpass_provider=krb5 to update these + attributes when the password is changed. + + + Default: none + + + + diff --git a/server/providers/ldap/ldap_auth.c b/server/providers/ldap/ldap_auth.c index a9f03a7..1f86fb0 100644 --- a/server/providers/ldap/ldap_auth.c +++ b/server/providers/ldap/ldap_auth.c @@ -34,6 +34,7 @@ #undef _XOPEN_SOURCE #include #include +#include #include #include @@ -168,16 +169,24 @@ static errno_t string_to_shadowpw_days(const char *s, long *d) static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, const struct ldb_message *msg, + struct dp_option *opts, enum pwexpire *type, void **data) { const char *mark; const char *val; struct spwd *spwd; + const char *pwd_policy; int ret; *type = PWEXPIRE_NONE; *data = NULL; + pwd_policy = dp_opt_get_string(opts, SDAP_PWD_POLICY); + if (pwd_policy == NULL) { + DEBUG(1, ("Missing password policy.\n")); + return EINVAL; + } + mark = ldb_msg_find_attr_as_string(msg, SYSDB_PWD_ATTRIBUTE, NULL); if (mark != NULL) { DEBUG(9, ("Found pwdAttribute, " @@ -187,60 +196,73 @@ static errno_t find_password_expiration_attributes(TALLOC_CTX *mem_ctx, return EOK; } - mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL); - if (mark != NULL) { - DEBUG(9, ("Found Kerberos password expiration attributes.\n")) - val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION, - NULL); - if (val != NULL) { - *data = talloc_strdup(mem_ctx, val); - if (*data == NULL) { - DEBUG(1, ("talloc_strdup failed.\n")); - return ENOMEM; - } - *type = PWEXPIRE_KERBEROS; - - return EOK; - } - } + if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) == 0) { + DEBUG(9, ("No password policy requested.\n")); + return EOK; + } else if (strcasecmp(pwd_policy, PWD_POL_OPT_MIT) == 0) { + mark = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_LASTCHANGE, NULL); + if (mark != NULL) { + DEBUG(9, ("Found Kerberos password expiration attributes.\n")) + val = ldb_msg_find_attr_as_string(msg, SYSDB_KRBPW_EXPIRATION, + NULL); + if (val != NULL) { + *data = talloc_strdup(mem_ctx, val); + if (*data == NULL) { + DEBUG(1, ("talloc_strdup failed.\n")); + return ENOMEM; + } + *type = PWEXPIRE_KERBEROS; - mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); - if (mark != NULL) { - DEBUG(9, ("Found shadow password expiration attributes.\n")) - spwd = talloc_zero(mem_ctx, struct spwd); - if (spwd == NULL) { - DEBUG(1, ("talloc failed.\n")); - return ENOMEM; + return EOK; + } + } else { + DEBUG(1, ("No Kerberos password expiration attributes found, " + "but MIT Kerberos password policy was requested.\n")); + return EINVAL; } + } else if (strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) == 0) { + mark = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); + if (mark != NULL) { + DEBUG(9, ("Found shadow password expiration attributes.\n")) + spwd = talloc_zero(mem_ctx, struct spwd); + if (spwd == NULL) { + DEBUG(1, ("talloc failed.\n")); + return ENOMEM; + } - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_lstchg); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_LASTCHANGE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_lstchg); + if (ret != EOK) goto shadow_fail; - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_min); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MIN, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_min); + if (ret != EOK) goto shadow_fail; - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_max); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_MAX, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_max); + if (ret != EOK) goto shadow_fail; - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_warn); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_WARNING, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_warn); + if (ret != EOK) goto shadow_fail; - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_inact); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_INACTIVE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_inact); + if (ret != EOK) goto shadow_fail; - val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL); - ret = string_to_shadowpw_days(val, &spwd->sp_expire); - if (ret != EOK) goto shadow_fail; + val = ldb_msg_find_attr_as_string(msg, SYSDB_SHADOWPW_EXPIRE, NULL); + ret = string_to_shadowpw_days(val, &spwd->sp_expire); + if (ret != EOK) goto shadow_fail; - *data = spwd; - *type = PWEXPIRE_SHADOW; + *data = spwd; + *type = PWEXPIRE_SHADOW; - return EOK; + return EOK; + } else { + DEBUG(1, ("No shadow password attributes found, " + "but shadow password policy was requested.\n")); + return EINVAL; + } } DEBUG(9, ("No password expiration attributes found.\n")); @@ -360,6 +382,7 @@ static void get_user_dn_done(void *pvt, int err, struct ldb_result *res) } ret = find_password_expiration_attributes(state, res->msgs[0], + state->ctx->opts->basic, &state->pw_expire_type, &state->pw_expire_data); if (ret != EOK) { @@ -883,6 +906,9 @@ static void sdap_pam_auth_done(struct tevent_req *req) case SDAP_UNAVAIL: state->pd->pam_status = PAM_AUTHINFO_UNAVAIL; break; + case SDAP_ACCT_EXPIRED: + state->pd->pam_status = PAM_ACCT_EXPIRED; + break; case SDAP_AUTH_PW_EXPIRED: state->pd->pam_status = PAM_AUTHTOK_EXPIRED; break; diff --git a/server/providers/ldap/ldap_common.c b/server/providers/ldap/ldap_common.c index deffb4a..6263810 100644 --- a/server/providers/ldap/ldap_common.c +++ b/server/providers/ldap/ldap_common.c @@ -54,7 +54,8 @@ struct dp_option default_basic_opts[] = { { "ldap_krb5_keytab", DP_OPT_STRING, NULL_STRING, NULL_STRING }, { "ldap_krb5_init_creds", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, /* use the same parm name as the krb5 module so we set it only once */ - { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING } + { "krb5_realm", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "ldap_pwd_policy", DP_OPT_STRING, { "none" } , NULL_STRING } }; struct sdap_attr_map generic_attr_map[] = { @@ -156,6 +157,7 @@ int ldap_get_options(TALLOC_CTX *memctx, struct sdap_attr_map *default_group_map; struct sdap_options *opts; char *schema; + const char *pwd_policy; int ret; opts = talloc_zero(memctx, struct sdap_options); @@ -194,6 +196,20 @@ int ldap_get_options(TALLOC_CTX *memctx, dp_opt_get_string(opts->basic, SDAP_GROUP_SEARCH_BASE))); } + pwd_policy = dp_opt_get_string(opts->basic, SDAP_PWD_POLICY); + if (pwd_policy == NULL) { + DEBUG(1, ("Missing password policy, this may not happen.\n")); + ret = EINVAL; + goto done; + } + if (strcasecmp(pwd_policy, PWD_POL_OPT_NONE) != 0 && + strcasecmp(pwd_policy, PWD_POL_OPT_SHADOW) != 0 && + strcasecmp(pwd_policy, PWD_POL_OPT_MIT) != 0) { + DEBUG(1, ("Unsupported password policy [%s].\n", pwd_policy)); + ret = EINVAL; + goto done; + } + /* schema type */ schema = dp_opt_get_string(opts->basic, SDAP_SCHEMA); if (strcasecmp(schema, "rfc2307") == 0) { diff --git a/server/providers/ldap/ldap_common.h b/server/providers/ldap/ldap_common.h index 96b332c..f02395b 100644 --- a/server/providers/ldap/ldap_common.h +++ b/server/providers/ldap/ldap_common.h @@ -25,6 +25,10 @@ #include "providers/dp_backend.h" #include "providers/ldap/sdap.h" +#define PWD_POL_OPT_NONE "none" +#define PWD_POL_OPT_SHADOW "shadow" +#define PWD_POL_OPT_MIT "mit_kerberos" + struct sdap_id_ctx { struct be_ctx *be; diff --git a/server/providers/ldap/sdap.h b/server/providers/ldap/sdap.h index 8330bd6..9348a2e 100644 --- a/server/providers/ldap/sdap.h +++ b/server/providers/ldap/sdap.h @@ -117,6 +117,7 @@ enum sdap_basic_opt { SDAP_KRB5_KEYTAB, SDAP_KRB5_KINIT, SDAP_KRB5_REALM, + SDAP_PWD_POLICY, SDAP_OPTS_BASIC /* opts counter */ }; -- 1.6.2.5