summaryrefslogtreecommitdiff
path: root/src/providers/ldap
diff options
context:
space:
mode:
Diffstat (limited to 'src/providers/ldap')
-rw-r--r--src/providers/ldap/ldap_auth.c52
-rw-r--r--src/providers/ldap/sdap.h5
-rw-r--r--src/providers/ldap/sdap_async.h6
-rw-r--r--src/providers/ldap/sdap_async_connection.c53
4 files changed, 103 insertions, 13 deletions
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
index 52287030..8c77e3aa 100644
--- a/src/providers/ldap/ldap_auth.c
+++ b/src/providers/ldap/ldap_auth.c
@@ -7,6 +7,7 @@
Sumit Bose <sbose@redhat.com>
Copyright (C) 2008 Red Hat
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -135,6 +136,39 @@ static errno_t check_pwexpire_shadow(struct spwd *spwd, time_t now,
return EOK;
}
+static errno_t check_pwexpire_ldap(struct pam_data *pd,
+ struct sdap_ppolicy_data *ppolicy,
+ enum sdap_result *result)
+{
+ if (ppolicy->grace > 0 || ppolicy->expire > 0) {
+ uint32_t *data;
+ uint32_t *ptr;
+
+ data = talloc_size(pd, 2* sizeof(uint32_t));
+ if (data == NULL) {
+ DEBUG(1, ("talloc_size failed.\n"));
+ return ENOMEM;
+ }
+
+ ptr = data;
+ if (ppolicy->grace > 0) {
+ *ptr = SSS_PAM_USER_INFO_GRACE_LOGIN;
+ ptr++;
+ *ptr = ppolicy->grace;
+ } else if (ppolicy->expire > 0) {
+ *ptr = SSS_PAM_USER_INFO_EXPIRE_WARN;
+ ptr++;
+ *ptr = ppolicy->expire;
+ }
+
+ pam_add_response(pd, SSS_PAM_USER_INFO, 2* sizeof(uint32_t),
+ (uint8_t*)data);
+ }
+
+ *result = SDAP_AUTH_SUCCESS;
+ return EOK;
+}
+
static errno_t string_to_shadowpw_days(const char *s, long *d)
{
long l;
@@ -569,8 +603,15 @@ static void auth_bind_user_done(struct tevent_req *subreq)
struct auth_state *state = tevent_req_data(req,
struct auth_state);
int ret;
-
- ret = sdap_auth_recv(subreq, &state->result);
+ struct sdap_ppolicy_data *ppolicy;
+
+ ret = sdap_auth_recv(subreq, state, &state->result, &ppolicy);
+ if (ppolicy != NULL) {
+ DEBUG(9,("Found ppolicy data, "
+ "assuming LDAP password policies are active.\n"));
+ state->pw_expire_type = PWEXPIRE_LDAP_PASSWORD_POLICY;
+ state->pw_expire_data = ppolicy;
+ }
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);
@@ -960,6 +1001,13 @@ 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);
+ if (ret != EOK) {
+ DEBUG(1, ("check_pwexpire_ldap failed.\n"));
+ state->pd->pam_status = PAM_SYSTEM_ERR;
+ goto done;
+ }
+ break;
case PWEXPIRE_NONE:
break;
default:
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
index 007185fc..f0e345ec 100644
--- a/src/providers/ldap/sdap.h
+++ b/src/providers/ldap/sdap.h
@@ -85,6 +85,11 @@ struct sdap_service {
char *uri;
};
+struct sdap_ppolicy_data {
+ int grace;
+ int expire;
+};
+
#define SYSDB_SHADOWPW_LASTCHANGE "shadowLastChange"
#define SYSDB_SHADOWPW_MIN "shadowMin"
#define SYSDB_SHADOWPW_MAX "shadowMax"
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
index 3c52d236..888df6b4 100644
--- a/src/providers/ldap/sdap_async.h
+++ b/src/providers/ldap/sdap_async.h
@@ -76,7 +76,11 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *user_dn,
const char *authtok_type,
struct dp_opt_blob authtok);
-int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result);
+
+int sdap_auth_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ enum sdap_result *result,
+ struct sdap_ppolicy_data **ppolicy);
struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx,
struct tevent_context *ev,
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 586733f4..f8c69569 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -4,6 +4,7 @@
Async LDAP Helper routines
Copyright (C) Simo Sorce <ssorce@redhat.com> - 2009
+ Copyright (C) 2010, rhafer@suse.de, Novell Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -278,6 +279,7 @@ struct simple_bind_state {
struct sdap_op *op;
struct sdap_msg *reply;
+ struct sdap_ppolicy_data *ppolicy;
int result;
};
@@ -401,6 +403,7 @@ static void simple_bind_done(struct sdap_op *op,
if (response_controls == NULL) {
DEBUG(5, ("Server returned no controls.\n"));
+ state->ppolicy = NULL;
} else {
for (c = 0; response_controls[c] != NULL; c++) {
DEBUG(9, ("Server returned control [%s].\n",
@@ -420,12 +423,30 @@ static void simple_bind_done(struct sdap_op *op,
DEBUG(7, ("Password Policy Response: expire [%d] grace [%d] "
"error [%s].\n", pp_expire, pp_grace,
ldap_passwordpolicy_err2txt(pp_error)));
-
- if ((state->result == LDAP_SUCCESS &&
- (pp_error == PP_changeAfterReset || pp_grace > 0)) ||
- (state->result == LDAP_INVALID_CREDENTIALS &&
- pp_error == PP_passwordExpired ) ) {
- DEBUG(4, ("User must set a new password.\n"));
+ state->ppolicy = talloc(state, struct sdap_ppolicy_data);
+ if (state->ppolicy == NULL) {
+ DEBUG(1, ("talloc failed.\n"));
+ ret = ENOMEM;
+ goto done;
+ }
+ state->ppolicy->grace = pp_grace;
+ state->ppolicy->expire = pp_expire;
+ if (state->result == LDAP_SUCCESS) {
+ if (pp_error == PP_changeAfterReset) {
+ DEBUG(4, ("Password was reset. "
+ "User must set a new password.\n"));
+ state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
+ } else if (pp_grace > 0) {
+ DEBUG(4, ("Password expired. "
+ "[%d] grace logins remaining.\n", pp_grace));
+ } else if (pp_expire > 0) {
+ DEBUG(4, ("Password will expire in [%d] seconds.\n",
+ pp_expire));
+ }
+ } else if (state->result == LDAP_INVALID_CREDENTIALS &&
+ pp_error == PP_passwordExpired) {
+ DEBUG(4,
+ ("Password expired user must set a new password.\n"));
state->result = LDAP_X_SSSD_PASSWORD_EXPIRED;
}
}
@@ -446,7 +467,10 @@ done:
}
}
-static int simple_bind_recv(struct tevent_req *req, int *ldaperr)
+static int simple_bind_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ int *ldaperr,
+ struct sdap_ppolicy_data **ppolicy)
{
struct simple_bind_state *state = tevent_req_data(req,
struct simple_bind_state);
@@ -455,6 +479,7 @@ static int simple_bind_recv(struct tevent_req *req, int *ldaperr)
TEVENT_REQ_RETURN_ON_ERROR(req);
*ldaperr = state->result;
+ *ppolicy = talloc_steal(memctx, state->ppolicy);
return EOK;
}
@@ -704,6 +729,7 @@ int sdap_kinit_recv(struct tevent_req *req, enum sdap_result *result)
struct sdap_auth_state {
const char *user_dn;
struct berval pw;
+ struct sdap_ppolicy_data *ppolicy;
int result;
bool is_sasl;
@@ -766,8 +792,9 @@ static void sdap_auth_done(struct tevent_req *subreq)
if (state->is_sasl) {
ret = sasl_bind_recv(subreq, &state->result);
+ state->ppolicy = NULL;
} else {
- ret = simple_bind_recv(subreq, &state->result);
+ ret = simple_bind_recv(subreq, state, &state->result, &state->ppolicy);
}
if (ret != EOK) {
tevent_req_error(req, ret);
@@ -777,7 +804,10 @@ static void sdap_auth_done(struct tevent_req *subreq)
tevent_req_done(req);
}
-int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result)
+int sdap_auth_recv(struct tevent_req *req,
+ TALLOC_CTX *memctx,
+ enum sdap_result *result,
+ struct sdap_ppolicy_data **ppolicy)
{
struct sdap_auth_state *state = tevent_req_data(req,
struct sdap_auth_state);
@@ -785,6 +815,9 @@ int sdap_auth_recv(struct tevent_req *req, enum sdap_result *result)
*result = SDAP_ERROR;
TEVENT_REQ_RETURN_ON_ERROR(req);
+ if (ppolicy != NULL) {
+ *ppolicy = talloc_steal(memctx, state->ppolicy);
+ }
switch (state->result) {
case LDAP_SUCCESS:
*result = SDAP_AUTH_SUCCESS;
@@ -1078,7 +1111,7 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
enum sdap_result result;
int ret;
- ret = sdap_auth_recv(subreq, &result);
+ ret = sdap_auth_recv(subreq, NULL, &result, NULL);
talloc_zfree(subreq);
if (ret) {
tevent_req_error(req, ret);