Skip to content

Commit

Permalink
ldap: add 'exop_force' value for ldap_pwmodify_mode
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sumit-bose committed Oct 15, 2024
1 parent 0e8e694 commit 72a7fd0
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 11 deletions.
11 changes: 11 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
3 changes: 2 additions & 1 deletion src/providers/ipa/ipa_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,8 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq)
SDAP_USE_PPOLICY);

subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn,
state->pd->authtok, timeout, use_ppolicy);
state->pd->authtok, timeout, use_ppolicy,
state->auth_ctx->sdap_auth_ctx->opts->pwmodify_mode);
if (subreq == NULL) {
goto done;
}
Expand Down
5 changes: 4 additions & 1 deletion src/providers/ldap/ldap_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,8 @@ static void auth_do_bind(struct tevent_req *req)
subreq = sdap_auth_send(state, state->ev, state->sh,
NULL, NULL, state->dn,
state->authtok,
timeout, use_ppolicy);
timeout, use_ppolicy,
state->ctx->opts->pwmodify_mode);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
Expand Down Expand Up @@ -1208,6 +1209,7 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx,

switch (opts->pwmodify_mode) {
case SDAP_PWMODIFY_EXOP:
case SDAP_PWMODIFY_EXOP_FORCE:
use_ppolicy = dp_opt_get_bool(opts->basic, SDAP_USE_PPOLICY);
subreq = sdap_exop_modify_passwd_send(state, ev, sh, user_dn,
password, new_password,
Expand Down Expand Up @@ -1252,6 +1254,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;
Expand Down
2 changes: 2 additions & 0 deletions src/providers/ldap/ldap_options.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions src/providers/ldap/sdap.h
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,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 */
Expand Down
3 changes: 2 additions & 1 deletion src/providers/ldap/sdap_async.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *user_dn,
struct sss_auth_token *authtok,
int simple_bind_timeout,
bool use_ppolicy);
bool use_ppolicy,
enum pwmodify_mode pwmodify_mode);

errno_t sdap_auth_recv(struct tevent_req *req,
TALLOC_CTX *memctx,
Expand Down
27 changes: 21 additions & 6 deletions src/providers/ldap/sdap_async_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,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;

Expand All @@ -663,7 +664,8 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
int timeout,
const char *user_dn,
struct berval *pw,
bool use_ppolicy)
bool use_ppolicy,
enum pwmodify_mode pwmodify_mode)
{
struct tevent_req *req;
struct simple_bind_state *state;
Expand All @@ -686,6 +688,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;

if (use_ppolicy) {
ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
Expand Down Expand Up @@ -872,7 +875,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) {
Expand All @@ -885,7 +893,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");
Expand Down Expand Up @@ -1365,7 +1378,8 @@ struct tevent_req *sdap_auth_send(TALLOC_CTX *memctx,
const char *user_dn,
struct sss_auth_token *authtok,
int simple_bind_timeout,
bool use_ppolicy)
bool use_ppolicy,
enum pwmodify_mode pwmodify_mode)
{
struct tevent_req *req, *subreq;
struct sdap_auth_state *state;
Expand Down Expand Up @@ -1404,7 +1418,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, use_ppolicy);
subreq = simple_bind_send(state, ev, sh, simple_bind_timeout, user_dn, &pw, use_ppolicy, pwmodify_mode);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return tevent_req_post(req, ev);
Expand Down Expand Up @@ -1981,7 +1995,8 @@ static void sdap_cli_auth_step(struct tevent_req *req)
dp_opt_get_int(state->opts->basic,
SDAP_OPT_TIMEOUT),
dp_opt_get_bool(state->opts->basic,
SDAP_USE_PPOLICY));
SDAP_USE_PPOLICY),
state->opts->pwmodify_mode);
talloc_free(authtok);
if (!subreq) {
tevent_req_error(req, ENOMEM);
Expand Down

0 comments on commit 72a7fd0

Please sign in to comment.