Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ignoring the ppolicy extension #6904

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/config/SSSDConfig/sssdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ def __init__(self):

'ldap_disable_paging': _('Disable the LDAP paging control'),
'ldap_disable_range_retrieval': _('Disable Active Directory range retrieval'),
'ldap_use_ppolicy': _('Use the ppolicy extension'),

# [provider/ldap/id]
'ldap_search_timeout': _('Length of time to wait for a search request'),
Expand Down
1 change: 1 addition & 0 deletions src/config/cfg_rules.ini
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ option = ldap_tls_cipher_suite
option = ldap_tls_key
option = ldap_tls_reqcert
option = ldap_uri
option = ldap_use_ppolicy
option = ldap_user_ad_account_expires
option = ldap_user_ad_user_account_control
option = ldap_user_authorized_host
Expand Down
1 change: 1 addition & 0 deletions src/config/etc/sssd.api.d/sssd-ldap.conf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ ldap_connection_idle_timeout = int, None, false
ldap_disable_paging = bool, None, false
ldap_disable_range_retrieval = bool, None, false
wildcard_limit = int, None, false
ldap_use_ppolicy = bool, None, false

[provider/ldap/id]
ldap_search_timeout = int, None, false
Expand Down
15 changes: 15 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,21 @@ ldap_access_filter = (employeeType=admin)
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_use_ppolicy (boolean)</term>
<listitem>
<para>
Turns on requesting and relying on the server-side
password policy controls. Disabling this allows
interacting with services which send back invalid
ppolicy extension.
</para>
<para>
Default: true
</para>
</listitem>
</varlistentry>

</variablelist>
</para>
</refsect1>
Expand Down
1 change: 1 addition & 0 deletions src/providers/ad/ad_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct dp_option ad_def_ldap_opts[] = {
{ "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
{ "ldap_library_debug_level", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
{ "ldap_use_ppolicy", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
DP_OPTION_TERMINATOR
};

Expand Down
5 changes: 4 additions & 1 deletion src/providers/ipa/ipa_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq)
struct ldb_message *msg;
const char *dn;
int timeout;
bool use_ppolicy;
errno_t ret;

req = tevent_req_callback_data(subreq, struct tevent_req);
Expand Down Expand Up @@ -379,9 +380,11 @@ static void ipa_pam_auth_handler_connect_done(struct tevent_req *subreq)

timeout = dp_opt_get_int(state->auth_ctx->sdap_auth_ctx->opts->basic,
SDAP_OPT_TIMEOUT);
use_ppolicy = dp_opt_get_bool(state->auth_ctx->sdap_auth_ctx->opts->basic,
SDAP_USE_PPOLICY);

subreq = sdap_auth_send(state, state->ev, sh, NULL, NULL, dn,
state->pd->authtok, timeout);
state->pd->authtok, timeout, use_ppolicy);
if (subreq == NULL) {
goto done;
}
Expand Down
1 change: 1 addition & 0 deletions src/providers/ipa/ipa_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ struct dp_option ipa_def_ldap_opts[] = {
{ "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
{ "ldap_library_debug_level", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
{ "ldap_use_ppolicy", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
DP_OPTION_TERMINATOR
};

Expand Down
10 changes: 7 additions & 3 deletions src/providers/ldap/ldap_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,12 +891,14 @@ static void auth_do_bind(struct tevent_req *req)
{
struct auth_state *state = tevent_req_data(req, struct auth_state);
struct tevent_req *subreq;
bool use_ppolicy = dp_opt_get_bool(state->ctx->opts->basic,
SDAP_USE_PPOLICY);
int timeout = dp_opt_get_int(state->ctx->opts->basic, SDAP_OPT_TIMEOUT);

subreq = sdap_auth_send(state, state->ev, state->sh,
NULL, NULL, state->dn,
state->authtok,
dp_opt_get_int(state->ctx->opts->basic,
SDAP_OPT_TIMEOUT));
timeout, use_ppolicy);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return;
Expand Down Expand Up @@ -1160,6 +1162,7 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx,
char *pwd_attr;
int timeout;
errno_t ret;
bool use_ppolicy;

pwd_attr = opts->user_map[SDAP_AT_USER_PWD].name;

Expand All @@ -1186,9 +1189,10 @@ sdap_pam_change_password_send(TALLOC_CTX *mem_ctx,

switch (opts->pwmodify_mode) {
case SDAP_PWMODIFY_EXOP:
use_ppolicy = dp_opt_get_int(opts->basic, SDAP_USE_PPOLICY);
subreq = sdap_exop_modify_passwd_send(state, ev, sh, user_dn,
password, new_password,
timeout);
timeout, use_ppolicy);
break;
case SDAP_PWMODIFY_LDAP:
subreq = sdap_modify_passwd_send(state, ev, sh, timeout, pwd_attr,
Expand Down
1 change: 1 addition & 0 deletions src/providers/ldap/ldap_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct dp_option default_basic_opts[] = {
{ "ldap_pwdlockout_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "wildcard_limit", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER},
{ "ldap_library_debug_level", DP_OPT_NUMBER, NULL_NUMBER, NULL_NUMBER},
{ "ldap_use_ppolicy", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE },
DP_OPTION_TERMINATOR
};

Expand Down
1 change: 1 addition & 0 deletions src/providers/ldap/sdap.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ enum sdap_basic_opt {
SDAP_PWDLOCKOUT_DN,
SDAP_WILDCARD_LIMIT,
SDAP_LIBRARY_DEBUG_LEVEL,
SDAP_USE_PPOLICY,

SDAP_OPTS_BASIC /* opts counter */
};
Expand Down
21 changes: 12 additions & 9 deletions src/providers/ldap/sdap_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,8 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
char *user_dn,
const char *password,
const char *new_password,
int timeout)
int timeout,
bool use_ppolicy)
{
struct tevent_req *req = NULL;
struct sdap_exop_modify_passwd_state *state;
Expand Down Expand Up @@ -652,15 +653,17 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
return NULL;
}

ret = sdap_control_create(state->sh, LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE, "sdap_control_create failed to create "
"Password Policy control.\n");
ret = ERR_INTERNAL;
goto fail;
if (use_ppolicy) {
ret = sdap_control_create(state->sh, LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE, "sdap_control_create failed to create "
"Password Policy control.\n");
ret = ERR_INTERNAL;
goto fail;
}
request_controls = ctrls;
}
request_controls = ctrls;

DEBUG(SSSDBG_CONF_SETTINGS, "Executing extended operation\n");

Expand Down
6 changes: 4 additions & 2 deletions src/providers/ldap/sdap_async.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
bool use_ppolicy);

errno_t sdap_auth_recv(struct tevent_req *req,
TALLOC_CTX *memctx,
Expand All @@ -170,7 +171,8 @@ struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx,
char *user_dn,
const char *password,
const char *new_password,
int timeout);
int timeout,
bool use_ppolicy);
errno_t sdap_exop_modify_passwd_recv(struct tevent_req *req,
TALLOC_CTX *mem_ctx,
char **user_error_msg);
Expand Down
47 changes: 29 additions & 18 deletions src/providers/ldap/sdap_async_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct sdap_rebind_proc_params {
struct sdap_options *opts;
struct sdap_handle *sh;
bool use_start_tls;
bool use_ppolicy;
};

static int sdap_rebind_proc(LDAP *ldap, LDAP_CONST char *url, ber_tag_t request,
Expand Down Expand Up @@ -240,6 +241,8 @@ static void sdap_sys_connect_done(struct tevent_req *subreq)
rebind_proc_params->opts = state->opts;
rebind_proc_params->sh = state->sh;
rebind_proc_params->use_start_tls = state->use_start_tls;
rebind_proc_params->use_ppolicy = dp_opt_get_bool(state->opts->basic,
SDAP_USE_PPOLICY);

lret = ldap_set_rebind_proc(state->sh->ldap, sdap_rebind_proc,
rebind_proc_params);
Expand Down Expand Up @@ -659,7 +662,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,
bool use_ppolicy)
{
struct tevent_req *req;
struct simple_bind_state *state;
Expand All @@ -683,14 +687,16 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx,
state->sh = sh;
state->user_dn = user_dn;

ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_control_create failed to create "
"Password Policy control.\n");
goto fail;
if (use_ppolicy) {
ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_control_create failed to create "
"Password Policy control.\n");
goto fail;
}
request_controls = ctrls;
}
request_controls = ctrls;

DEBUG(SSSDBG_CONF_SETTINGS,
"Executing simple bind as: %s\n", state->user_dn);
Expand Down Expand Up @@ -1358,7 +1364,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,
bool use_ppolicy)
{
struct tevent_req *req, *subreq;
struct sdap_auth_state *state;
Expand Down Expand Up @@ -1397,7 +1404,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, use_ppolicy);
if (!subreq) {
tevent_req_error(req, ENOMEM);
return tevent_req_post(req, ev);
Expand Down Expand Up @@ -1972,7 +1979,9 @@ 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),
dp_opt_get_bool(state->opts->basic,
SDAP_USE_PPOLICY));
talloc_free(authtok);
if (!subreq) {
tevent_req_error(req, ENOMEM);
Expand Down Expand Up @@ -2320,15 +2329,17 @@ static int sdap_rebind_proc(LDAP *ldap, LDAP_CONST char *url, ber_tag_t request,
sasl_mech = dp_opt_get_string(p->opts->basic, SDAP_SASL_MECH);

if (sasl_mech == NULL) {
ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE,
"sss_ldap_control_create failed to create "
if (p->use_ppolicy) {
ret = sss_ldap_control_create(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
0, NULL, 0, &ctrls[0]);
if (ret != LDAP_SUCCESS && ret != LDAP_NOT_SUPPORTED) {
DEBUG(SSSDBG_CRIT_FAILURE,
"sss_ldap_control_create failed to create "
"Password Policy control.\n");
goto done;
goto done;
}
request_controls = ctrls;
}
request_controls = ctrls;

user_dn = dp_opt_get_string(p->opts->basic, SDAP_DEFAULT_BIND_DN);
if (user_dn != NULL) {
Expand Down
16 changes: 12 additions & 4 deletions src/tests/system/tests/test_ldap.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
@pytest.mark.importance("critical")
@pytest.mark.authentication
@pytest.mark.parametrize("modify_mode", ["exop", "ldap_modify"])
@pytest.mark.parametrize("use_ppolicy", ["true", "false"])
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__change_password(client: Client, ldap: LDAP, modify_mode: str):
def test_ldap__change_password(client: Client, ldap: LDAP, modify_mode: str, use_ppolicy: str):
"""
:title: Change password with "ldap_pwmodify_mode" set to @modify_mode
:setup:
Expand Down Expand Up @@ -45,6 +46,7 @@ def test_ldap__change_password(client: Client, ldap: LDAP, modify_mode: str):
ldap.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)')

client.sssd.domain["ldap_pwmodify_mode"] = modify_mode
client.sssd.domain["ldap_use_ppolicy"] = use_ppolicy
client.sssd.start()

assert client.auth.ssh.password(user, old_pass), "Authentication with old correct password failed"
Expand All @@ -57,8 +59,9 @@ def test_ldap__change_password(client: Client, ldap: LDAP, modify_mode: str):

@pytest.mark.ticket(bz=[795044, 1695574])
@pytest.mark.parametrize("modify_mode", ["exop", "ldap_modify"])
@pytest.mark.parametrize("use_ppolicy", ["true", "false"])
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__change_password_new_pass_not_match(client: Client, ldap: LDAP, modify_mode: str):
def test_ldap__change_password_new_pass_not_match(client: Client, ldap: LDAP, modify_mode: str, use_ppolicy: str):
"""
:title: Change password with "ldap_pwmodify_mode" set to @modify_mode, but retyped password do not match
:setup:
Expand All @@ -76,6 +79,7 @@ def test_ldap__change_password_new_pass_not_match(client: Client, ldap: LDAP, mo
ldap.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)')

client.sssd.domain["ldap_pwmodify_mode"] = modify_mode
client.sssd.domain["ldap_use_ppolicy"] = use_ppolicy
client.sssd.start()

assert not client.auth.passwd.password(
Expand All @@ -85,8 +89,9 @@ def test_ldap__change_password_new_pass_not_match(client: Client, ldap: LDAP, mo

@pytest.mark.ticket(bz=[795044, 1695574, 1795220])
@pytest.mark.parametrize("modify_mode", ["exop", "ldap_modify"])
@pytest.mark.parametrize("use_ppolicy", ["true", "false"])
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__change_password_lowercase(client: Client, ldap: LDAP, modify_mode: str):
def test_ldap__change_password_lowercase(client: Client, ldap: LDAP, modify_mode: str, use_ppolicy: str):
"""
:title: Change password to lower-case letters, password check fail
:setup:
Expand All @@ -108,6 +113,7 @@ def test_ldap__change_password_lowercase(client: Client, ldap: LDAP, modify_mode
ldap.ldap.modify("cn=config", replace={"passwordCheckSyntax": "on"})

client.sssd.domain["ldap_pwmodify_mode"] = modify_mode
client.sssd.domain["ldap_use_ppolicy"] = use_ppolicy
client.sssd.start()

assert not client.auth.passwd.password(
Expand All @@ -122,8 +128,9 @@ def test_ldap__change_password_lowercase(client: Client, ldap: LDAP, modify_mode

@pytest.mark.ticket(bz=[1695574, 1795220])
@pytest.mark.parametrize("modify_mode", ["exop", "ldap_modify"])
@pytest.mark.parametrize("use_ppolicy", ["true", "false"])
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__change_password_wrong_current(client: Client, ldap: LDAP, modify_mode: str):
def test_ldap__change_password_wrong_current(client: Client, ldap: LDAP, modify_mode: str, use_ppolicy: str):
"""
:title: Password change failed because an incorrect password was used
:setup:
Expand All @@ -141,6 +148,7 @@ def test_ldap__change_password_wrong_current(client: Client, ldap: LDAP, modify_
ldap.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)')

client.sssd.domain["ldap_pwmodify_mode"] = modify_mode
client.sssd.domain["ldap_use_ppolicy"] = use_ppolicy
client.sssd.start()

assert not client.auth.passwd.password("user1", "wrong123", "Newpass123"), "Password change did not fail"
Expand Down