summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/confdb/confdb.c18
-rw-r--r--src/confdb/confdb.h3
-rw-r--r--src/config/etc/sssd.api.conf1
-rw-r--r--src/man/sssd.conf.5.xml35
-rw-r--r--src/providers/krb5/krb5_auth.c31
-rw-r--r--src/providers/ldap/ldap_auth.c42
-rw-r--r--src/responder/pam/pamsrv_cmd.c35
-rw-r--r--src/util/domain_info_utils.c1
-rw-r--r--src/util/sss_krb5.h5
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,