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.
  • Loading branch information
sumit-bose committed Sep 23, 2024
1 parent 67ba42c commit b36e10d
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 11 deletions.
7 changes: 7 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,13 @@
userPassword (not recommended).
</para>
</listitem>
<listitem>
<para>
exop_force - Try Password Modify
Extended Operation (RFC 3062) even if
there are no grace logins left.
</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 changed 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 changed 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 b36e10d

Please sign in to comment.