diff options
author | Ralf Haferkamp <rhafer@suse.de> | 2010-03-12 10:54:40 +0100 |
---|---|---|
committer | Stephen Gallagher <sgallagh@redhat.com> | 2010-03-22 08:47:12 -0400 |
commit | dfc511c1226786cebbda35990bb7149dea5577b5 (patch) | |
tree | 78697c85743a0b30a222b523192ed8754f713b3d /src/providers/ldap | |
parent | 369975ab6d7c45916e0e2739eb5449879c32b6f8 (diff) | |
download | sssd-dfc511c1226786cebbda35990bb7149dea5577b5.tar.gz sssd-dfc511c1226786cebbda35990bb7149dea5577b5.tar.bz2 sssd-dfc511c1226786cebbda35990bb7149dea5577b5.zip |
Improvements for LDAP Password Policy support
Display warnings about remaining grace logins and password
expiration to the user, when LDAP Password Policies are used.
Improved detection if LDAP Password policies are supported by
LDAP Server.
Diffstat (limited to 'src/providers/ldap')
-rw-r--r-- | src/providers/ldap/ldap_auth.c | 52 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 5 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 6 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_connection.c | 53 |
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); |