Skip to content

Commit

Permalink
Configure how SSSD should access RootDSE.
Browse files Browse the repository at this point in the history
:config:The 'ldap_read_rootdse' option allows you to specify how
SSSD will read RootDSE from the LDAP server. Allowed values are
"anonymous", "authenticated" and "never"

Resolves: #6665
  • Loading branch information
thalman committed Feb 28, 2025
1 parent e2408c2 commit a847109
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/config/SSSDConfig/sssdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ def __init__(self):
'ldap_uri': _('ldap_uri, The URI of the LDAP server'),
'ldap_backup_uri': _('ldap_backup_uri, The URI of the LDAP server'),
'ldap_search_base': _('The default base DN'),
'ldap_read_rootdse': _('How to read rootDSE from LDAP server'),
'ldap_schema': _('The Schema Type in use on the LDAP server, rfc2307'),
'ldap_pwmodify_mode': _('Mode used to change user password'),
'ldap_default_bind_dn': _('The default bind DN'),
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 @@ -686,6 +686,7 @@ option = ldap_purge_cache_offset
option = ldap_pwd_attribute
option = ldap_pwdlockout_dn
option = ldap_pwd_policy
option = ldap_read_rootdse
option = ldap_referrals
option = ldap_rfc2307_fallback_to_local_users
option = ldap_rootdse_last_usn
Expand Down
39 changes: 39 additions & 0 deletions src/man/sssd-ldap.5.xml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,45 @@
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_read_rootdse (string)</term>
<listitem>
<para>
SSSD reads RootDSE to get information about LDAP and
its capabilities. By default, this is done
anonymously. However, this may not be permitted by
the LDAP server. In such cases we can use this option
to influence SSSD behavior.
</para>
<para>
Allowed values are:
<itemizedlist>
<listitem>
<para>
anonymous
</para>
</listitem>
<listitem>
<para>
authenticated
</para>
</listitem>
<listitem>
<para>
never
</para>
</listitem>
</itemizedlist>
Note that when using the "anonymous" option, SSSD
may attempt to read RootDSE after authentication
if anonymous access fails.
</para>
<para>
Default: anonymous
</para>
</listitem>
</varlistentry>

<varlistentry>
<term>ldap_schema (string)</term>
<listitem>
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 @@ -68,6 +68,7 @@ struct dp_option ad_def_ldap_opts[] = {
{ "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_backup_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_read_rootdse", DP_OPT_STRING, { "anonymous" }, NULL_STRING },
{ "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_default_authtok_type", DP_OPT_STRING, NULL_STRING, NULL_STRING},
{ "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
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 @@ -79,6 +79,7 @@ struct dp_option ipa_def_ldap_opts[] = {
{ "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_backup_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_read_rootdse", DP_OPT_STRING, { "anonymous" }, NULL_STRING },
{ "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_default_authtok_type", DP_OPT_STRING, NULL_STRING, NULL_STRING},
{ "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
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 @@ -33,6 +33,7 @@ struct dp_option default_basic_opts[] = {
{ "ldap_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_backup_uri", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_search_base", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_read_rootdse", DP_OPT_STRING, { "anonymous" }, NULL_STRING },
{ "ldap_default_bind_dn", DP_OPT_STRING, NULL_STRING, NULL_STRING },
{ "ldap_default_authtok_type", DP_OPT_STRING, { "password" }, NULL_STRING},
{ "ldap_default_authtok", DP_OPT_BLOB, NULL_BLOB, NULL_BLOB },
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 @@ -140,6 +140,7 @@ enum sdap_basic_opt {
SDAP_URI = 0,
SDAP_BACKUP_URI,
SDAP_SEARCH_BASE,
SDAP_READ_ROOTDSE,
SDAP_DEFAULT_BIND_DN,
SDAP_DEFAULT_AUTHTOK_TYPE,
SDAP_DEFAULT_AUTHTOK,
Expand Down
55 changes: 50 additions & 5 deletions src/providers/ldap/sdap_async_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ struct sdap_rebind_proc_params {
bool use_ppolicy;
};

enum sdap_rootdse_read_opts {
SDAP_ROOTDSE_READ_ANONYMOUS,
SDAP_ROOTDSE_READ_AUTHENTICATED,
SDAP_ROOTDSE_READ_NEVER,
SDAP_ROOTDSE_READ_INVALID,
};

static int sdap_rebind_proc(LDAP *ldap, LDAP_CONST char *url, ber_tag_t request,
ber_int_t msgid, void *params);

Expand Down Expand Up @@ -1496,6 +1503,7 @@ struct sdap_cli_connect_state {
struct be_ctx *be;

bool use_rootdse;
enum sdap_rootdse_read_opts rootdse_access;
struct sysdb_attrs *rootdse;

struct sdap_handle *sh;
Expand Down Expand Up @@ -1525,6 +1533,35 @@ static errno_t sdap_cli_auth_reconnect(struct tevent_req *subreq);
static void sdap_cli_auth_reconnect_done(struct tevent_req *subreq);
static void sdap_cli_rootdse_auth_done(struct tevent_req *subreq);


enum sdap_rootdse_read_opts
decide_rootdse_access(struct dp_option *basic)
{
int i;
char *str;
struct read_rootdse_enum_str {
enum sdap_rootdse_read_opts option_enum;
const char *option_str;
};
static struct read_rootdse_enum_str read_rootdse_enum_str[] = {
{ SDAP_ROOTDSE_READ_ANONYMOUS, "anonymous"},
{ SDAP_ROOTDSE_READ_AUTHENTICATED, "authenticated"},
{ SDAP_ROOTDSE_READ_NEVER, "never"},
{ SDAP_ROOTDSE_READ_INVALID, NULL}
};

str = dp_opt_get_string (basic, SDAP_READ_ROOTDSE);
for (i = 0; read_rootdse_enum_str[i].option_str != NULL; i++) {
if (strcasecmp(read_rootdse_enum_str[i].option_str, str) == 0) {
return read_rootdse_enum_str[i].option_enum;
}
}
DEBUG(SSSDBG_CONF_SETTINGS,
"The ldap_read_rootdse option has an invalid value [%s], "
"using [anonymous]\n", str);
return SDAP_ROOTDSE_READ_ANONYMOUS;
}

static errno_t
decide_tls_usage(enum connect_tls force_tls, struct dp_option *basic,
const char *uri, bool *_use_tls)
Expand Down Expand Up @@ -1579,6 +1616,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
state->srv = NULL;
state->srv_opts = NULL;
state->use_rootdse = !skip_rootdse;
state->rootdse_access = decide_rootdse_access (opts->basic);
state->force_tls = force_tls;
state->do_auth = !skip_auth;

Expand Down Expand Up @@ -1695,15 +1733,19 @@ static void sdap_cli_connect_done(struct tevent_req *subreq)
}
state->retry_attempts = 0;

if (state->use_rootdse) {
if (state->use_rootdse &&
state->rootdse_access == SDAP_ROOTDSE_READ_ANONYMOUS) {

/* fetch the rootDSE this time */
sdap_cli_rootdse_step(req);
return;
}

sasl_mech = dp_opt_get_string(state->opts->basic, SDAP_SASL_MECH);

if (state->do_auth && sasl_mech && state->use_rootdse) {
if (state->do_auth && sasl_mech && state->use_rootdse &&
state->rootdse_access == SDAP_ROOTDSE_READ_ANONYMOUS) {

/* check if server claims to support the configured SASL MECH */
if (!sdap_is_sasl_mech_supported(state->sh, sasl_mech)) {
tevent_req_error(req, ENOTSUP);
Expand Down Expand Up @@ -2097,9 +2139,12 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
return;
}

if (state->use_rootdse && !state->rootdse) {
/* We weren't able to read rootDSE during unauthenticated bind.
* Let's try again now that we are authenticated */
if (state->use_rootdse && !state->rootdse &&
state->rootdse_access != SDAP_ROOTDSE_READ_NEVER) {
/* We did not read rootDSE during unauthenticated bind becase
* it is unaccessible for anonymous user or because
* ldap_read_rootdse is set to "authenticated"
* Let's try to read it now */
subreq = sdap_get_rootdse_send(state, state->ev,
state->opts, state->sh);
if (!subreq) {
Expand Down

0 comments on commit a847109

Please sign in to comment.