diff options
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); |