Skip to content

SUBID: add LDAP provider support#8097

Merged
alexey-tikhonov merged 11 commits intoSSSD:masterfrom
alexey-tikhonov:ldap_subid
Dec 2, 2025
Merged

SUBID: add LDAP provider support#8097
alexey-tikhonov merged 11 commits intoSSSD:masterfrom
alexey-tikhonov:ldap_subid

Conversation

@alexey-tikhonov
Copy link
Member

Resolves: #8030

Most patches could be squashed, but I kept them separate to make review easier.

@alexey-tikhonov alexey-tikhonov added the no-backport This should go to target branch only. label Sep 16, 2025
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for subid to the generic LDAP provider, refactoring the existing IPA-specific implementation. The changes are well-structured and cover configuration, documentation, and the core logic. However, I've found a critical security vulnerability in the new implementation where a Distinguished Name (DN) is used in an LDAP filter without proper escaping, which could lead to LDAP injection. Please address this issue.

@alexey-tikhonov
Copy link
Member Author

Steps to test this manually against 389-ds using sssd-ci-containers:

(I) on LDAP container:

(1) extend schema - add a snippet under /etc/dirsrv/slapd-.../schema/:

dn: cn=schema
attributetypes: ( 2.16.840.1.113730.3.8.23.13
  NAME 'subidRangeOwner'
  DESC 'DN of the user who owns the subordinate ID range'
  EQUALITY distinguishedNameMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
  SINGLE-VALUE )
attributetypes: ( 2.16.840.1.113730.3.8.23.7
  NAME 'subUidNumber'
  DESC 'The starting number of the subordinate UID range'
  EQUALITY integerMatch
  ORDERING integerOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  SINGLE-VALUE )
attributetypes: ( 2.16.840.1.113730.3.8.23.8
  NAME 'subUidCount'
  DESC 'The total number of subordinate UIDs in the range'
  EQUALITY integerMatch
  ORDERING integerOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  SINGLE-VALUE )
attributetypes: ( 2.16.840.1.113730.3.8.23.10
  NAME 'subGidNumber'
  DESC 'The starting number of the subordinate GID range'
  EQUALITY integerMatch
  ORDERING integerOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  SINGLE-VALUE )
attributetypes: ( 2.16.840.1.113730.3.8.23.11
  NAME 'subGidCount'
  DESC 'The total number of subordinate GIDs in the range'
  EQUALITY integerMatch
  ORDERING integerOrderingMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  SINGLE-VALUE )
objectclasses: ( 2.16.840.1.113730.3.8.24.4
  NAME 'subordinateId'
  DESC 'Auxiliary object class for managing subordinate ID ranges'
  AUXILIARY
  SUP top
  MUST ( subidRangeOwner $ subUidNumber $ subUidCount $ subGidNumber $ subGidCount ) )
objectClasses: ( 2.16.840.1.113730.3.8.24.5
  NAME 'subordinateIdEntry'
  DESC 'Subordinate uid and gid entry'
  SUP top
  STRUCTURAL
  MUST ( cn $ subidRangeOwner ) )
)

(2) add a container to store subid ranges:

dn: ou=subids,dc=ldap,dc=test
objectClass: top
objectClass: organizationalUnit
ou: subids

(3) assign a range to a user:

dn: cn=range_test11,ou=subids,dc=ldap,dc=test
objectClass: top
objectClass: subordinateIdEntry
objectClass: subordinateId
subidRangeOwner: uid=test11,dc=ldap,dc=test
subUidNumber: 100000
subUidCount: 65536
subGidNumber: 100000
subGidCount: 65536

(II) on the CLIENT container:

(1) install shadow-utils-subid

(2) enable with-subid for the 'sssd' profile

(3) set ldap_subid_ranges_search_base = ou=subids,dc=ldap,dc=test in the LDAP domain section of 'sssd.conf'
(or leave a default if you didn't follow I.2 and created subid range object directly in dc=ldap,dc=test)

Then:

# getsubids test11@ldap.test
0: test11@ldap.test 100000 65536

@SSSD SSSD deleted a comment from gemini-code-assist bot Sep 16, 2025
@alexey-tikhonov alexey-tikhonov added the coverity Trigger a coverity scan label Sep 16, 2025
if (expire > time(NULL)) {
dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL);
if (dn != NULL) {
sss_filter_sanitize(mem_ctx, dn, &result);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Covscan complains here:

Calling sss_filter_sanitize without checking return value (as is done elsewhere 66 out of 67 times).

But when functions fails its output arg is untouched, and thus NULL. Not much to do on top of this.

@justin-stephenson
Copy link
Contributor

Will there be some tests for this functionality?

@alexey-tikhonov
Copy link
Member Author

Will there be some tests for this functionality?

I didn't find a QE owner (yet?) so plan to add a basic test myself.
This will require changes in ci-containers and a test-framework.

@alexey-tikhonov
Copy link
Member Author

(rebased)

Copy link
Contributor

@justin-stephenson justin-stephenson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, steps provided work for me.

[root@client /]# getsubids test11@ldap.test
0: test11@ldap.test 100000 65536

@alexey-tikhonov
Copy link
Member Author

alexey-tikhonov commented Sep 24, 2025

To have it recorded somewhere - current implementation (I guess both with and without patches from this PR) works in a weird way for AD:

[nss] [sss_dp_get_account_send] (0x0400): [CID#8] Creating request for [samba.test][0x10][BE_REQ_SUBID_RANGES][name=test15:-]
[nss] [sbus_dispatch] (0x4000): Dispatching.
[nss] [cache_req_common_process_dp_reply] (0x3f7c0): [CID#8] CR #7: Data Provider Error: 3, 1432158288, The internal name format cannot be parsed

-- nss responder refuses a request immediately. I guess it strictly requires FQDN for AD but not sure why. That's ok since SSSD currently doesn't support subid ranges lookup for AD, but not... neat.

@alexey-tikhonov
Copy link
Member Author

alexey-tikhonov commented Sep 24, 2025

As @justin-stephenson found out, there are at least two other flaws related to subid ranges support both in current "stock" SSSD and in this PR:

(1) lookup by overridden name doesn't work for IPA:

# ipa idoverrideuser-find 'example1'
--------------------------
1 User ID override matched
--------------------------
  Anchor to override: testuser1
  User login: newname1
----------------------------
Number of entries returned 1
----------------------------
# id newname1@ipa.test
uid=1149800005(newname1@ipa.test) gid=1149800005(testuser1@ipa.test) groups=1149800005(testuser1@ipa.test)

# getsubids newname1@ipa.test                                                                                                                            
Error fetching ranges

(2) lookup of a range in trusted IPA domain doesn't work:

[dp_get_account_info_send] (0x0200): Got request for [0x10][BE_REQ_SUBID_RANGES][name=testuser1]
[dp_attach_req] (0x0400): [RID#4] DP Request [Account #4]: REQ_TRACE: New request. [sssd.nss CID #2] Flags [0x0001].
[dp_attach_req] (0x0400): [RID#4] Number of active DP request: 1
[sss_domain_get_state] (0x2000): [RID#4] Domain test is Active
[sss_domain_get_state] (0x2000): [RID#4] Domain samba.test is Active
[sss_domain_get_state] (0x2000): [RID#4] Domain ipa2.test is Active
[sss_domain_get_state] (0x2000): [RID#4] Domain test is Active
[sss_domain_get_state] (0x2000): [RID#4] Domain samba.test is Active
[sss_domain_get_state] (0x2000): [RID#4] Domain ipa2.test is Active
[sdap_id_op_connect_step] (0x4000): [RID#4] reusing cached connection
[sdap_id_conn_data_not_idle] (0x4000): [RID#4] Marking connection as not idle
[sdap_id_op_connect_step] (0x4000): [RID#4] reusing cached connection
[sdap_id_conn_data_not_idle] (0x4000): [RID#4] Marking connection as not idle
[ipa_get_trusted_override_connect_done] (0x0040): [RID#4] dp_id_data_to_override_filter failed.

(note IPA-IPA trust support in IPA isn't yet released, testing was done against copr build of IPA)

#ifdef BUILD_SUBID
if (!ar->extra_value) {
if ((strcasecmp(sdom->dom->provider, "ldap") != 0) &&
(strcasecmp(sdom->dom->provider, "ipa") != 0)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check will not work as expected for a case "IPA-AD trusted subdomain" since "provider" will be "ipa" in this case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now.

@alexey-tikhonov alexey-tikhonov force-pushed the ldap_subid branch 2 times, most recently from b70b621 to f9031c3 Compare October 10, 2025 15:17
@alexey-tikhonov alexey-tikhonov removed the coverity Trigger a coverity scan label Oct 10, 2025
#ifdef BUILD_SUBID
if (!ar->extra_value) {
if (((strcasecmp(sdom->dom->provider, "ldap") != 0) &&
(strcasecmp(sdom->dom->provider, "ipa") != 0))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this ever match? You are comparing the same provider instance to be two different values at the same time.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abbra, not "to be" but "to be not"

(if this is not LDAP and not IPA) or (this is trusted by IPA AD subdomain) => reject

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes. I would have used !string_in_list() instead to be more clear here.

Copy link
Contributor

@sumit-bose sumit-bose left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

thank you for the patches (and your patience). I only have two comments (see inline), originally I had more but since I was going through the patches one by one it turned out that you already addressed most of my comments in later patches.

I ran couple of tests with a plain LDAP server and all went well.

bye,
Sumit

@alexey-tikhonov
Copy link
Member Author

(rebased)

Copy link
Contributor

@sumit-bose sumit-bose left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

all my comments are addressed and tests are still working as expected, ACK.

bye,
Sumit

@sssd-bot
Copy link
Contributor

sssd-bot commented Dec 1, 2025

The pull request was accepted by @alexey-tikhonov with the following PR CI status:


🟢 CodeFactor (success)
🟢 CodeQL (success)
🟢 osh-diff-scan:fedora-rawhide-x86_64:upstream (success)
🟢 rpm-build:centos-stream-10-x86_64:upstream (success)
🟢 rpm-build:fedora-41-x86_64:upstream (success)
🟢 rpm-build:fedora-42-x86_64:upstream (success)
🟢 rpm-build:fedora-43-x86_64:upstream (success)
🟢 rpm-build:fedora-rawhide-x86_64:upstream (success)
🟢 Analyze (target) / cppcheck (success)
🟢 Build / freebsd (success)
🟢 Build / make-distcheck (success)
🟢 ci / intgcheck (centos-10) (success)
🟢 ci / intgcheck (fedora-41) (success)
🟢 ci / intgcheck (fedora-42) (success)
🟢 ci / intgcheck (fedora-43) (success)
🟢 ci / intgcheck (fedora-44) (success)
🟢 ci / prepare (success)
🟢 ci / system (centos-10) (success)
🟢 ci / system (fedora-41) (success)
🟢 ci / system (fedora-42) (success)
🟢 ci / system (fedora-43) (success)
🟢 ci / system (fedora-44) (success)
➖ Coverity scan / coverity (skipped)
🟢 Static code analysis / codeql (success)
🟢 Static code analysis / pre-commit (success)
🟢 Static code analysis / python-system-tests (success)


There are unsuccessful or unfinished checks. Make sure that the failures are not related to this pull request before merging.

Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Proper STRUCTURAL objectClass is 'ipaSubordinateIdEntry'.

Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
in favor of `ldap_subid_ranges_search_base`.

:config:Option `ipa_subid_ranges_search_base` was deprecated in favor
of `ldap_subid_ranges_search_base`.

Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Resolves: SSSD#8030
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
It can be read from rootDSE upon first connection.

Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
related to attributes presence/manipulation.

Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
Reviewed-by: Sumit Bose <sbose@redhat.com>
@alexey-tikhonov alexey-tikhonov merged commit 95994dd into SSSD:master Dec 2, 2025
11 of 16 checks passed
@SSSD SSSD deleted a comment from sssd-bot Dec 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support subuid with generic LDAP provider

5 participants