231 lines
11 KiB
Diff
231 lines
11 KiB
Diff
|
From acd5da528789734411b12fa8b19007b00eea9f2c Mon Sep 17 00:00:00 2001
|
||
|
From: Sumit Bose <sbose@redhat.com>
|
||
|
Date: Fri, 13 Sep 2024 15:45:59 +0200
|
||
|
Subject: [PATCH 13/15] ldap: add 'exop_force' value for ldap_pwmodify_mode
|
||
|
|
||
|
In case the LDAP server allows to run the extended operation to change a
|
||
|
password even if an authenticated bind fails due to missing grace logins
|
||
|
the new option 'exop_force' can be used to run the extended operation to
|
||
|
change the password anyways.
|
||
|
|
||
|
:config: Added `exop_force` value for configuration option
|
||
|
`ldap_pwmodify_mode`. This can be used to force a password change even
|
||
|
if no grace logins are left. Depending on the configuration of the
|
||
|
LDAP server it might be expected that the password change will fail.
|
||
|
|
||
|
(cherry picked from commit 72a7fd0ded236a16b00bb4e26221f7e23b702a53)
|
||
|
|
||
|
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
|
||
|
(cherry picked from commit e3a3f44c4cdcb936b59941636ff576de613366d1)
|
||
|
|
||
|
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
|
||
|
---
|
||
|
src/man/sssd-ldap.5.xml | 11 +++++++++
|
||
|
src/providers/ipa/ipa_auth.c | 3 ++-
|
||
|
src/providers/ldap/ldap_auth.c | 5 +++-
|
||
|
src/providers/ldap/ldap_options.c | 2 ++
|
||
|
src/providers/ldap/sdap.h | 5 ++--
|
||
|
src/providers/ldap/sdap_async.h | 3 ++-
|
||
|
src/providers/ldap/sdap_async_connection.c | 27 +++++++++++++++++-----
|
||
|
7 files changed, 45 insertions(+), 11 deletions(-)
|
||
|
|
||
|
diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml
|
||
|
index 0a814ec35..a9994aade 100644
|
||
|
--- a/src/man/sssd-ldap.5.xml
|
||
|
+++ b/src/man/sssd-ldap.5.xml
|
||
|
@@ -234,6 +234,17 @@
|
||
|
userPassword (not recommended).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
+ <listitem>
|
||
|
+ <para>
|
||
|
+ exop_force - Try Password Modify
|
||
|
+ Extended Operation (RFC 3062) even if
|
||
|
+ there are no grace logins left.
|
||
|
+ Depending on the type and configuration
|
||
|
+ of the LDAP server the password change
|
||
|
+ might fail because an authenticated bind
|
||
|
+ is not possible.
|
||
|
+ </para>
|
||
|
+ </listitem>
|
||
|
</itemizedlist>
|
||
|
</para>
|
||
|
<para>
|
||
|
diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c
|
||
|
index 1d61a1052..b2e5b6f35 100644
|
||
|
--- a/src/providers/ipa/ipa_auth.c
|
||
|
+++ b/src/providers/ipa/ipa_auth.c
|
||
|
@@ -381,7 +381,8 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq)
|
||
|
SDAP_OPT_TIMEOUT);
|
||
|
|
||
|
subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn,
|
||
|
- state->pd->authtok, timeout);
|
||
|
+ state->pd->authtok, timeout,
|
||
|
+ state->auth_ctx->sdap_auth_ctx->opts->pwmodify_mode);
|
||
|
if (subreq == NULL) {
|
||
|
goto done;
|
||
|
}
|
||
|
diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c
|
||
|
index 8ec4d3af5..023ed2277 100644
|
||
|
--- a/src/providers/ldap/ldap_auth.c
|
||
|
+++ b/src/providers/ldap/ldap_auth.c
|
||
|
@@ -896,7 +896,8 @@ static void auth_do_bind(struct tevent_req *req)
|
||
|
NULL, NULL, state->dn,
|
||
|
state->authtok,
|
||
|
dp_opt_get_int(state->ctx->opts->basic,
|
||
|
- SDAP_OPT_TIMEOUT));
|
||
|
+ SDAP_OPT_TIMEOUT),
|
||
|
+ state->ctx->opts->pwmodify_mode);
|
||
|
if (!subreq) {
|
||
|
tevent_req_error(req, ENOMEM);
|
||
|
return;
|
||
|
@@ -1186,6 +1187,7 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx,
|
||
|
|
||
|
switch (opts->pwmodify_mode) {
|
||
|
case SDAP_PWMODIFY_EXOP:
|
||
|
+ case SDAP_PWMODIFY_EXOP_FORCE:
|
||
|
subreq = sdap_exop_modify_passwd_send(state, ev, sh, user_dn,
|
||
|
password, new_password,
|
||
|
timeout);
|
||
|
@@ -1229,6 +1231,7 @@ static void sdap_pam_change_password_done(struct tevent_req *subreq)
|
||
|
|
||
|
switch (state->mode) {
|
||
|
case SDAP_PWMODIFY_EXOP:
|
||
|
+ case SDAP_PWMODIFY_EXOP_FORCE:
|
||
|
ret = sdap_exop_modify_passwd_recv(subreq, state,
|
||
|
&state->user_error_message);
|
||
|
break;
|
||
|
diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c
|
||
|
index 277bcb529..72a95300d 100644
|
||
|
--- a/src/providers/ldap/ldap_options.c
|
||
|
+++ b/src/providers/ldap/ldap_options.c
|
||
|
@@ -294,6 +294,8 @@ int ldap_get_options(TALLOC_CTX *memctx,
|
||
|
opts->pwmodify_mode = SDAP_PWMODIFY_EXOP;
|
||
|
} else if (strcasecmp(pwmodify, "ldap_modify") == 0) {
|
||
|
opts->pwmodify_mode = SDAP_PWMODIFY_LDAP;
|
||
|
+ } else if (strcasecmp(pwmodify, "exop_force") == 0) {
|
||
|
+ opts->pwmodify_mode = SDAP_PWMODIFY_EXOP_FORCE;
|
||
|
} else {
|
||
|
DEBUG(SSSDBG_FATAL_FAILURE, "Unrecognized pwmodify mode: %s\n", pwmodify);
|
||
|
ret = EINVAL;
|
||
|
diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h
|
||
|
index 103d50ed4..cc34c8198 100644
|
||
|
--- a/src/providers/ldap/sdap.h
|
||
|
+++ b/src/providers/ldap/sdap.h
|
||
|
@@ -546,8 +546,9 @@ struct sdap_options {
|
||
|
|
||
|
/* password modify mode */
|
||
|
enum pwmodify_mode {
|
||
|
- SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */
|
||
|
- SDAP_PWMODIFY_LDAP = 2 /* ldap_modify of userPassword */
|
||
|
+ SDAP_PWMODIFY_EXOP = 1, /* pwmodify extended operation */
|
||
|
+ SDAP_PWMODIFY_LDAP = 2, /* ldap_modify of userPassword */
|
||
|
+ SDAP_PWMODIFY_EXOP_FORCE = 3 /* forced pwmodify extended operation */
|
||
|
} pwmodify_mode;
|
||
|
|
||
|
/* The search bases for the domain or its subdomain */
|
||
|
diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h
|
||
|
index a45e057d0..80b403bc3 100644
|
||
|
--- a/src/providers/ldap/sdap_async.h
|
||
|
+++ b/src/providers/ldap/sdap_async.h
|
||
|
@@ -146,7 +146,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
|
||
|
const char *sasl_user,
|
||
|
const char *user_dn,
|
||
|
struct sss_auth_token *authtok,
|
||
|
- int simple_bind_timeout);
|
||
|
+ int simple_bind_timeout,
|
||
|
+ enum pwmodify_mode pwmodify_mode);
|
||
|
|
||
|
errno_t sdap_auth_recv(struct tevent_req *req,
|
||
|
TALLOC_CTX *memctx,
|
||
|
diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
|
||
|
index e8638725c..992a5798c 100644
|
||
|
--- a/src/providers/ldap/sdap_async_connection.c
|
||
|
+++ b/src/providers/ldap/sdap_async_connection.c
|
||
|
@@ -643,6 +643,7 @@ struct simple_bind_state {
|
||
|
struct tevent_context *ev;
|
||
|
struct sdap_handle *sh;
|
||
|
const char *user_dn;
|
||
|
+ enum pwmodify_mode pwmodify_mode;
|
||
|
|
||
|
struct sdap_op *op;
|
||
|
|
||
|
@@ -659,7 +660,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
|
||
|
struct sdap_handle *sh,
|
||
|
int timeout,
|
||
|
const char *user_dn,
|
||
|
- struct berval *pw)
|
||
|
+ struct berval *pw,
|
||
|
+ enum pwmodify_mode pwmodify_mode)
|
||
|
{
|
||
|
struct tevent_req *req;
|
||
|
struct simple_bind_state *state;
|
||
|
@@ -682,6 +684,7 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
|
||
|
state->ev = ev;
|
||
|
state->sh = sh;
|
||
|
state->user_dn = user_dn;
|
||
|
+ state->pwmodify_mode = pwmodify_mode;
|
||
|
|
||
|
ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
|
||
|
0, NULL, 0, &ctrls[0]);
|
||
|
@@ -866,7 +869,12 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
* Grace Authentications". */
|
||
|
DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
"Password expired, grace logins exhausted.\n");
|
||
|
- ret = ERR_AUTH_FAILED;
|
||
|
+ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n");
|
||
|
+ ret = ERR_PASSWORD_EXPIRED;
|
||
|
+ } else {
|
||
|
+ ret = ERR_AUTH_FAILED;
|
||
|
+ }
|
||
|
}
|
||
|
} else if (strcmp(response_controls[c]->ldctl_oid,
|
||
|
LDAP_CONTROL_PWEXPIRED) == 0) {
|
||
|
@@ -879,7 +887,12 @@ static void simple_bind_done(struct sdap_op *op,
|
||
|
if (result == LDAP_INVALID_CREDENTIALS) {
|
||
|
DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
"Password expired, grace logins exhausted.\n");
|
||
|
- ret = ERR_AUTH_FAILED;
|
||
|
+ if (state->pwmodify_mode == SDAP_PWMODIFY_EXOP_FORCE) {
|
||
|
+ DEBUG(SSSDBG_TRACE_LIBS, "Password change forced.\n");
|
||
|
+ ret = ERR_PASSWORD_EXPIRED;
|
||
|
+ } else {
|
||
|
+ ret = ERR_AUTH_FAILED;
|
||
|
+ }
|
||
|
} else {
|
||
|
DEBUG(SSSDBG_TRACE_LIBS,
|
||
|
"Password expired, user must set a new password.\n");
|
||
|
@@ -1358,7 +1371,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
|
||
|
const char *sasl_user,
|
||
|
const char *user_dn,
|
||
|
struct sss_auth_token *authtok,
|
||
|
- int simple_bind_timeout)
|
||
|
+ int simple_bind_timeout,
|
||
|
+ enum pwmodify_mode pwmodify_mode)
|
||
|
{
|
||
|
struct tevent_req *req, *subreq;
|
||
|
struct sdap_auth_state *state;
|
||
|
@@ -1397,7 +1411,7 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
|
||
|
pw.bv_len = pwlen;
|
||
|
|
||
|
state->is_sasl = false;
|
||
|
- subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw);
|
||
|
+ subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw, pwmodify_mode);
|
||
|
if (!subreq) {
|
||
|
tevent_req_error(req, ENOMEM);
|
||
|
return tevent_req_post(req, ev);
|
||
|
@@ -1972,7 +1986,8 @@ static void sdap_cli_auth_step(struct tevent_req *req)
|
||
|
SDAP_SASL_AUTHID),
|
||
|
user_dn, authtok,
|
||
|
dp_opt_get_int(state->opts->basic,
|
||
|
- SDAP_OPT_TIMEOUT));
|
||
|
+ SDAP_OPT_TIMEOUT),
|
||
|
+ state->opts->pwmodify_mode);
|
||
|
talloc_free(authtok);
|
||
|
if (!subreq) {
|
||
|
tevent_req_error(req, ENOMEM);
|
||
|
--
|
||
|
2.46.1
|
||
|
|