sdap: handle missing rootDSE gracefully#8706
Conversation
There was a problem hiding this comment.
Code Review
This pull request ensures that srv_opts is always initialized in sdap_cli_connect_done to prevent potential NULL pointer issues when rootDSE is unavailable or access is disabled. It also adds a talloc_zfree call in sdap_cli_use_rootdse to prevent memory leaks when re-initializing these options. I have no feedback to provide.
-- feels like some words are missing... |
sssd-bot
left a comment
There was a problem hiding this comment.
Review done using Claude Code / claude-opus-4-6
Functional Issues
-
USN map names may be prematurely set on the first (NULL rootdse) call, preventing proper autodetection on the second call.
sdap_get_server_opts_from_rootdsehas side effects on the sharedoptsstructure: when called with a NULLrootdseand no configured USN attributes (the generic LDAP case wheregen_map[SDAP_AT_ENTRY_USN].nameandgen_map[SDAP_AT_LAST_USN].namedefault to NULL), it setsgen_map[SDAP_AT_ENTRY_USN].nameto"modifyTimestamp"and propagates that fallback intouser_map,group_map,service_map,sudorule_map,iphost_map, andipnetwork_map(seesdap.c:1519-1562).When
sdap_cli_use_rootdselater calls the function again with real rootdse data, the autodetect loop (sdap.c:1449-1473) may discover IPA or AD USN attributes and updategen_map, but the per-object-type maps (user_map,group_map, etc.) are skipped because they are already non-NULL from the first call. This leaves the per-object maps using"modifyTimestamp"whilegen_mapuses the proper USN attribute.In practice this only affects generic LDAP providers (not IPA or AD, which pre-set USN defaults in their attribute maps), so the impact is limited. But it is a behavioral regression compared to pre-patch code where the function was called exactly once with the actual rootdse data.
Consider either (a) clearing the per-object-type USN names in
sdap_cli_use_rootdsebefore the second call, or (b) moving the per-object-type map population out ofsdap_get_server_opts_from_rootdseand intosdap_cli_use_rootdseso it only runs once with final data. -
Commit message body has a broken sentence.
"If ldap_read_rootdse = never then srv_opts which is unexpected"is missing a verb — likely should be"then srv_opts is NULL, which is unexpected". Also"the rootDSE is successfully fetch"should be"fetched". While not a code bug, this will appear ingit logpermanently and makes the rationale hard to follow.
Nits & Non-functional Issues
-
Unmatched parenthesis in comment (
src/providers/ldap/sdap_async_connection.c:1658-1659): The comment opens(this can happen ifbut never closes the parenthesis before*/. -
Typo in
:fixes:tag:"enumarete"should be"enumerate". -
No test coverage. The crash described in the
:fixes:tag (ldap_read_rootdse = neverwithenumerate = true) is a concrete scenario that could be covered by a unit or integration test configuring those options and verifying the connection completes without crashing.
Review of Existing Review Comments
The only review is from gemini-code-assist[bot], which summarized the change and stated "I have no feedback to provide." No actionable items were raised.
This seems valid. |
thalman
left a comment
There was a problem hiding this comment.
Code looks good, please fix the commit message, "If ldap_read_rootdse = never then srv_opts which is unexpected." does not make sense.
|
CI failures are not connected with the change. |
If `ldap_read_rootdse = never` then srv_opts is NULL which is unexpected. It can also happen on other path in the connection code, because sdap_cli_use_rootdse() is called only when the rootDSE is successfully fetch. This patch makes sure that srv_opts are always set. :fixes: SSSD no longer crashes if `ldap_read_rootdse = never` and `enumerate = true`
It wasn't, because there was But I refactored it and only create srv_opts with NULL rootdse as a falback in _recv. |
|
Ready for new review. |
What if server didn't return rootDSE upon first connection (and map names are populated with defaults), but - out of a sudden - returns a rootDSE after re-connection? I understand this is quite artificial scenario, but I guess this is what was meant. |
New srv_opts is returned and used. |
|
@pbrezina You're right that The concern is narrower: if (!opts->user_map[SDAP_AT_USER_USN].name) {
opts->user_map[SDAP_AT_USER_USN].name =
talloc_strdup(opts->user_map,
opts->gen_map[SDAP_AT_ENTRY_USN].name);
}
/* same for group_map, service_map, sudorule_map, ... */In the edge case @alexey-tikhonov described (rootDSE unavailable on first connect, available on reconnect):
The result is That said, this is a pre-existing design limitation of |
If
ldap_read_rootdse = neverthen srv_opts which is unexpected. It canalso happen on other path in the connection code, because
sdap_cli_use_rootdse() is called only when the rootDSE is successfully
fetch. This patch makes sure that srv_opts are always set.
:fixes: SSSD no longer crashes if
ldap_read_rootdse = neverandenumarete = true