diff options
author | Jan Zeleny <jzeleny@redhat.com> | 2012-05-01 03:36:37 -0400 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2012-05-04 13:36:42 -0400 |
commit | bf8cce77a35cb0a3cdb0d21fb9c39b7b6372bc11 (patch) | |
tree | ba1da22bd4f400edf1ba50563c80ab290e0987bb /src | |
parent | 9fd2775fe1ced6ff6a9a3ff7db124fcb52dade5d (diff) | |
download | sssd-bf8cce77a35cb0a3cdb0d21fb9c39b7b6372bc11.tar.gz sssd-bf8cce77a35cb0a3cdb0d21fb9c39b7b6372bc11.tar.xz sssd-bf8cce77a35cb0a3cdb0d21fb9c39b7b6372bc11.zip |
Modify behavior of pam_pwd_expiration_warning
New option pwd_expiration_warning is introduced which can be set per
domain and can override the value specified by the original
pam_pwd_expiration_warning.
If the value of expiration warning is set to zero, the filter isn't
apllied at all - if backend server returns the warning, it will be
automatically displayed.
Default value for Kerberos: 7 days
Default value for LDAP: don't apply the filter
Technical note: default value when creating the domain is -1. This is
important so we can distinguish between "no value set" and 0. Without
this possibility it would be impossible to set different values for LDAP
and Kerberos provider.
Diffstat (limited to 'src')
-rw-r--r-- | src/confdb/confdb.c | 18 | ||||
-rw-r--r-- | src/confdb/confdb.h | 3 | ||||
-rw-r--r-- | src/config/etc/sssd.api.conf | 1 | ||||
-rw-r--r-- | src/man/sssd.conf.5.xml | 35 | ||||
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 31 | ||||
-rw-r--r-- | src/providers/ldap/ldap_auth.c | 42 | ||||
-rw-r--r-- | src/responder/pam/pamsrv_cmd.c | 35 | ||||
-rw-r--r-- | src/util/domain_info_utils.c | 1 | ||||
-rw-r--r-- | src/util/sss_krb5.h | 5 |
9 files changed, 119 insertions, 52 deletions
diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c index d938d4f61..427101e9b 100644 --- a/src/confdb/confdb.c +++ b/src/confdb/confdb.c @@ -922,6 +922,24 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, goto done; } + /* Set the PAM warning time, if specified */ + val = ldb_msg_find_attr_as_int(res->msgs[0], + CONFDB_DOMAIN_PWD_EXPIRATION_WARNING, + -1); + if (val > 0) { + /* The value is in days, transform it to seconds */ + val *= 24 * 3600; + } else { + ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, + CONFDB_PAM_PWD_EXPIRATION_WARNING, + -1, &val); + if (ret != EOK) { + DEBUG(1, ("Failed to read PAM expiration warning, not fatal.\n")); + val = -1; + } + } + domain->pwd_expiration_warning = val; + ret = get_entry_as_uint32(res->msgs[0], &domain->override_gid, CONFDB_DOMAIN_OVERRIDE_GID, 0); if (ret != EOK) { diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h index b90db303a..5ec9f721c 100644 --- a/src/confdb/confdb.h +++ b/src/confdb/confdb.h @@ -152,6 +152,7 @@ #define CONFDB_DOMAIN_NETGROUP_CACHE_TIMEOUT "entry_cache_netgroup_timeout" #define CONFDB_DOMAIN_SERVICE_CACHE_TIMEOUT "entry_cache_service_timeout" #define CONFDB_DOMAIN_AUTOFS_CACHE_TIMEOUT "entry_cache_autofs_timeout" +#define CONFDB_DOMAIN_PWD_EXPIRATION_WARNING "pwd_expiration_warning" /* Local Provider */ #define CONFDB_LOCAL_DEFAULT_SHELL "default_shell" @@ -199,6 +200,8 @@ struct sss_domain_info { uint32_t service_timeout; uint32_t autofsmap_timeout; + int pwd_expiration_warning; + struct sysdb_ctx *sysdb; struct sss_domain_info **subdomains; diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf index a7bece99a..a5fdbffb6 100644 --- a/src/config/etc/sssd.api.conf +++ b/src/config/etc/sssd.api.conf @@ -89,6 +89,7 @@ use_fully_qualified_names = bool, None, false entry_cache_timeout = int, None, false lookup_family_order = str, None, false account_cache_expiration = int, None, false +pwd_expiration_warning = int, None, false filter_users = list, str, false filter_groups = list, str, false dns_resolver_timeout = int, None, false diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml index ef7490d94..a7691edcc 100644 --- a/src/man/sssd.conf.5.xml +++ b/src/man/sssd.conf.5.xml @@ -632,7 +632,17 @@ warning. </para> <para> - Default: 7 + If zero is set, then this filter is not applied, + i.e. if the expiration warning was received from + backend server, it will automatically be displayed. + </para> + <para> + This setting can be overridden by setting + <emphasis>pwd_expiration_warning</emphasis> + for a particular domain. + </para> + <para> + Default: 0 </para> </listitem> </varlistentry> @@ -922,6 +932,29 @@ </para> </listitem> </varlistentry> + <varlistentry> + <term>pwd_expiration_warning (integer)</term> + <listitem> + <para> + Display a warning N days before the password expires. + </para> + <para> + If zero is set, then this filter is not applied, + i.e. if the expiration warning was received from + backend server, it will automatically be displayed. + </para> + <para> + Please note that the backend server has to provide + information about the expiration time of the password. + If this information is missing, sssd cannot display a + warning. Also an auth provider has to be configured for + the backend. + </para> + <para> + Default: 7 (Kerberos), 0 (LDAP) + </para> + </listitem> + </varlistentry> <varlistentry> <term>id_provider (string)</term> diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index 0306426cc..986e449fd 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -734,8 +734,16 @@ static void krb5_child_done(struct tevent_req *subreq) int32_t msg_len; int64_t time_data; struct tgt_times tgtt; + int pwd_exp_warning; + uint32_t *expiration; + uint32_t *msg_subtype; + bool skip; memset(&tgtt, 0, sizeof(tgtt)); + pwd_exp_warning = state->be_ctx->domain->pwd_expiration_warning; + if (pwd_exp_warning < 0) { + pwd_exp_warning = KERBEROS_PWEXPIRE_WARNING_TIME; + } ret = handle_child_recv(subreq, pd, &buf, &len); talloc_zfree(subreq); @@ -771,6 +779,7 @@ static void krb5_child_done(struct tevent_req *subreq) SAFEALIGN_COPY_INT32(&msg_status, buf+p, &p); while (p < len) { + skip = false; SAFEALIGN_COPY_INT32(&msg_type, buf+p, &p); SAFEALIGN_COPY_INT32(&msg_len, buf+p, &p); @@ -813,10 +822,24 @@ static void krb5_child_done(struct tevent_req *subreq) tgtt.starttime, tgtt.endtime, tgtt.renew_till)); } - ret = pam_add_response(pd, msg_type, msg_len, &buf[p]); - if (ret != EOK) { - /* This is not a fatal error */ - DEBUG(1, ("pam_add_response failed.\n")); + if (msg_type == SSS_PAM_USER_INFO) { + msg_subtype = (uint32_t *)&buf[p]; + if (*msg_subtype == SSS_PAM_USER_INFO_EXPIRE_WARN) + { + expiration = (uint32_t *)&buf[p+sizeof(uint32_t)]; + if (pwd_exp_warning > 0 && + difftime(pwd_exp_warning, *expiration) < 0.0) { + skip = true; + } + } + } + + if (!skip) { + ret = pam_add_response(pd, msg_type, msg_len, &buf[p]); + if (ret != EOK) { + /* This is not a fatal error */ + DEBUG(1, ("pam_add_response failed.\n")); + } } p += msg_len; diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c index 734249ced..da64f249e 100644 --- a/src/providers/ldap/ldap_auth.c +++ b/src/providers/ldap/ldap_auth.c @@ -47,11 +47,7 @@ #include "providers/ldap/sdap_async.h" #include "providers/ldap/sdap_async_private.h" -/* MIT Kerberos has the same hardcoded warning interval of 7 days. Due to the - * fact that using the expiration time of a Kerberos password with LDAP - * authentication is presumably a rare case a separate config option is not - * necessary. */ -#define KERBEROS_PWEXPIRE_WARNING_TIME (7 * 24 * 60 * 60) +#define LDAP_PWEXPIRE_WARNING_TIME 0 enum pwexpire { PWEXPIRE_NONE = 0, @@ -90,11 +86,13 @@ static errno_t add_expired_warning(struct pam_data *pd, long exp_time) static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, struct pam_data *pd, - enum sdap_result *result) + enum sdap_result *result, + int pwd_exp_warning) { char *end; struct tm tm; time_t expire_time; + int expiration_warning; int ret; memset(&tm, 0, sizeof(tm)); @@ -130,8 +128,14 @@ static errno_t check_pwexpire_kerberos(const char *expire_date, time_t now, } else { *result = SDAP_AUTH_SUCCESS; + if (pwd_exp_warning >= 0) { + expiration_warning = pwd_exp_warning; + } else { + expiration_warning = KERBEROS_PWEXPIRE_WARNING_TIME; + } if (pd != NULL && - difftime(now + KERBEROS_PWEXPIRE_WARNING_TIME, expire_time) > 0.0) { + (difftime(now + expiration_warning, expire_time) > 0.0 || + expiration_warning == 0)) { ret = add_expired_warning(pd, (long) difftime(expire_time, now)); if (ret != EOK) { DEBUG(1, ("add_expired_warning failed.\n")); @@ -202,13 +206,19 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now, static errno_t check_pwexpire_ldap(struct pam_data *pd, struct sdap_ppolicy_data *ppolicy, - enum sdap_result *result) + enum sdap_result *result, + int pwd_exp_warning) { if (ppolicy->grace > 0 || ppolicy->expire > 0) { uint32_t *data; uint32_t *ptr; + time_t now = time(NULL); int ret; + if (pwd_exp_warning < 0) { + pwd_exp_warning = 0; + } + data = talloc_size(pd, 2* sizeof(uint32_t)); if (data == NULL) { DEBUG(1, ("talloc_size failed.\n")); @@ -221,6 +231,10 @@ static errno_t check_pwexpire_ldap(struct pam_data *pd, ptr++; *ptr = ppolicy->grace; } else if (ppolicy->expire > 0) { + if (pwd_exp_warning == 0 || + difftime(now + pwd_exp_warning, ppolicy->expire) > 0.0) { + goto done; + } *ptr = SSS_PAM_USER_INFO_EXPIRE_WARN; ptr++; *ptr = ppolicy->expire; @@ -234,6 +248,7 @@ static errno_t check_pwexpire_ldap(struct pam_data *pd, } } +done: *result = SDAP_AUTH_SUCCESS; return EOK; } @@ -830,8 +845,8 @@ static void sdap_auth4chpass_done(struct tevent_req *req) } break; case PWEXPIRE_KERBEROS: - ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL, - &result); + ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), NULL, &result, + state->breq->domain->pwd_expiration_warning); if (ret != EOK) { DEBUG(1, ("check_pwexpire_kerberos failed.\n")); state->pd->pam_status = PAM_SYSTEM_ERR; @@ -1064,6 +1079,7 @@ static void sdap_pam_auth_done(struct tevent_req *req) tevent_req_callback_data(req, struct sdap_pam_auth_state); enum sdap_result result; enum pwexpire pw_expire_type; + struct be_ctx *be_ctx = state->breq->be_ctx; void *pw_expire_data; int dp_err = DP_ERR_OK; int ret; @@ -1091,7 +1107,8 @@ static void sdap_pam_auth_done(struct tevent_req *req) break; case PWEXPIRE_KERBEROS: ret = check_pwexpire_kerberos(pw_expire_data, time(NULL), - state->pd, &result); + state->pd, &result, + be_ctx->domain->pwd_expiration_warning); if (ret != EOK) { DEBUG(1, ("check_pwexpire_kerberos failed.\n")); state->pd->pam_status = PAM_SYSTEM_ERR; @@ -1099,7 +1116,8 @@ static void sdap_pam_auth_done(struct tevent_req *req) } break; case PWEXPIRE_LDAP_PASSWORD_POLICY: - ret = check_pwexpire_ldap(state->pd, pw_expire_data, &result); + ret = check_pwexpire_ldap(state->pd, pw_expire_data, &result, + be_ctx->domain->pwd_expiration_warning); if (ret != EOK) { DEBUG(1, ("check_pwexpire_ldap failed.\n")); state->pd->pam_status = PAM_SYSTEM_ERR; diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c index c3e027e3c..608a38d4f 100644 --- a/src/responder/pam/pamsrv_cmd.c +++ b/src/responder/pam/pamsrv_cmd.c @@ -42,7 +42,6 @@ enum pam_verbosity { }; #define DEFAULT_PAM_VERBOSITY PAM_VERBOSITY_IMPORTANT -#define DEFAULT_PAM_PWD_EXPIRATION_WARNING 7 static void pam_reply(struct pam_auth_req *preq); @@ -515,16 +514,7 @@ static errno_t filter_responses(struct confdb_ctx *cdb, struct response_data *resp; uint32_t user_info_type; int64_t expire_date; - uint32_t expire_warn; - TALLOC_CTX *tmp_ctx; int pam_verbosity; - int pam_expiration_warning; - - tmp_ctx = talloc_new(NULL); - if (tmp_ctx == NULL) { - DEBUG(1, ("talloc_new failed.\n")); - return ENOMEM; - } ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, CONFDB_PAM_VERBOSITY, DEFAULT_PAM_VERBOSITY, @@ -534,20 +524,7 @@ static errno_t filter_responses(struct confdb_ctx *cdb, pam_verbosity = DEFAULT_PAM_VERBOSITY; } - - ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY, - CONFDB_PAM_PWD_EXPIRATION_WARNING, - DEFAULT_PAM_PWD_EXPIRATION_WARNING, - &pam_expiration_warning); - if (ret != EOK) { - DEBUG(1, ("Failed to read PAM expiration warning, not fatal.\n")); - pam_expiration_warning = DEFAULT_PAM_PWD_EXPIRATION_WARNING; - } - - talloc_free(tmp_ctx); - resp = resp_list; - while(resp != NULL) { if (resp->type == SSS_PAM_USER_INFO) { if (resp->len < sizeof(uint32_t)) { @@ -581,18 +558,6 @@ static errno_t filter_responses(struct confdb_ctx *cdb, } break; - case SSS_PAM_USER_INFO_EXPIRE_WARN: - if (resp->len != 2 * sizeof(uint32_t)) { - DEBUG(1, ("User info expire warning entry is " - "too short.\n")); - return EINVAL; - } - memcpy(&expire_warn, resp->data + sizeof(uint32_t), - sizeof(uint32_t)); - if(expire_warn > pam_expiration_warning * (60 * 60 * 24)) { - resp->do_not_send_to_client = true; - } - break; default: DEBUG(7, ("User info type [%d] not filtered.\n")); } diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c index d9f320d80..45f98d858 100644 --- a/src/util/domain_info_utils.c +++ b/src/util/domain_info_utils.c @@ -77,6 +77,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, /* FIXME: get ranges from the server */ dom->id_min = 0; dom->id_max = 0xffffffff; + dom->pwd_expiration_warning = parent->pwd_expiration_warning; dom->cache_credentials = parent->cache_credentials; dom->case_sensitive = parent->case_sensitive; dom->user_timeout = parent->user_timeout; diff --git a/src/util/sss_krb5.h b/src/util/sss_krb5.h index 50c4b696f..6ad80806c 100644 --- a/src/util/sss_krb5.h +++ b/src/util/sss_krb5.h @@ -34,6 +34,11 @@ #include "util/util.h" +/* MIT Kerberos has the same hardcoded warning interval of 7 days. Due to the + * fact that using the expiration time of a Kerberos password with LDAP + * authentication is presumably a rare case a separate config option is not + * necessary. */ +#define KERBEROS_PWEXPIRE_WARNING_TIME (7 * 24 * 60 * 60) #define KEYTAB_CLEAN_NAME keytab_name ? keytab_name : "default" const char * KRB5_CALLCONV sss_krb5_get_error_message (krb5_context, |