[GH-ISSUE #255] ldapsearch query does not respect scope #93

Closed
opened 2026-02-27 08:15:12 +03:00 by kerem · 2 comments
Owner

Originally created by @ikaruswill on GitHub (Jul 14, 2022).
Original GitHub issue: https://github.com/lldap/lldap/issues/255

Context

I was just debugging the problem described in https://github.com/nitnelave/lldap/issues/254 and I came across this one when tinkering with the search scope.

Problem

When varying scope for ldapsearch between base and one we'd expect the search to be on the base object itself, and one subtree down. However, varying scope seems to have no effect when search is performed against an LLDAP server.

Here I perform search for a objectClass=person that is a memberOf cn=admins group with a search base of ou=people. I set the scope to be base so the search will only search the object ou=people,dc=example,dc=com, which itself is not an objectClass=person so should return 0 results. Only if scope is set to one will the search look at direct descendants. (Scope docs)

Against LLDAP:

bash-5.1# ldapsearch -H ldap://lldap:389 -LLL -D "uid=admin,ou=people,dc=example,dc=com" -w '<password>' -s "Base" -b "ou=people,dc=example,dc=com" '(&(objectClass=person)(memberof=cn=admins,ou=groups,dc=example,dc=com))'
dn: uid=ikaruswill,ou=people,dc=example,dc=com
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: mailAccount
objectclass: person
dn: uid=ikaruswill,ou=people,dc=example,dc=com
uid: ikaruswill
mail: will@example.com
givenname: Will
sn: Ho
cn: Will Ho
createtimestamp: 2022-07-13T00:02:21.017041305+00:00

Against OpenLDAP (no results):

bash-5.1# ldapsearch -H ldap://openldap:389 -LLL -D "cn=admin,dc=example,dc=com" -w '<password>' -s "Base" -b "ou=people,dc=example,dc=com" '(&(objectClass=person)(memberof=cn=admins,ou=groups,dc=example,dc=com))'
bash-5.1#

Relevant logs:

2022-07-14T00:44:31.321810145+00:00 INFO     LDAP session [ 248ms | 0.10% / 100.00% ]
2022-07-14T00:44:31.321893272+00:00 INFO     ┝━ LDAP request [ 247ms | 0.09% / 99.55% ]
2022-07-14T00:44:31.321918939+00:00 DEBUG    │  ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=admin,ou=people,dc=example,dc=com", cred: Simple("********") }), ctrl: [] }
2022-07-14T00:44:31.321924481+00:00 DEBUG    │  ┝━ do_bind [ 247ms | 0.02% / 99.45% ]
2022-07-14T00:44:31.321930897+00:00 DEBUG    │  │  ┝━ 🐛 [debug]: DN: uid=admin,ou=people,dc=example,dc=com
2022-07-14T00:44:31.321944023+00:00 DEBUG    │  │  ┝━ bind [ 246ms | 0.18% / 99.30% ]
2022-07-14T00:44:31.322371033+00:00 DEBUG    │  │  │  ┕━ passwords_match [ 246ms | 99.12% ]
2022-07-14T00:44:31.568146167+00:00 DEBUG    │  │  ┝━ get_user_groups [ 331µs | 0.13% ]
2022-07-14T00:44:31.568161917+00:00 DEBUG    │  │  │  ┝━ 🐛 [debug]:  | user_id: UserId("admin")
2022-07-14T00:44:31.568230169+00:00 DEBUG    │  │  │  ┝━ 🐛 [debug]:  | query: SELECT "groups"."group_id", "display_name", "creation_date", "uuid" FROM "groups" INNER JOIN "memberships" ON "groups"."group_id" = "memberships"."group_id" WHERE "user_id" = ?
2022-07-14T00:44:31.568903934+00:00 DEBUG    │  │  │  ┕━ 🐛 [debug]:  | return: {GroupDetails { group_id: GroupId(1), display_name: "lldap_admin", creation_date: 2022-07-12T23:48:25.516387433Z, uuid: Uuid("<UUID>") }}
2022-07-14T00:44:31.568922893+00:00 DEBUG    │  │  ┕━ 🐛 [debug]: Success!
2022-07-14T00:44:31.568940977+00:00 DEBUG    │  ┕━ 🐛 [debug]:  | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None })
2022-07-14T00:44:31.569602784+00:00 INFO     ┝━ LDAP request [ 858µs | 0.14% / 0.35% ]
2022-07-14T00:44:31.569637785+00:00 DEBUG    │  ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=example,dc=com", scope: Base, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: And([Equality("objectClass", "person"), Equality("memberof", "cn=admins,ou=groups,dc=example,dc=com")]), attrs: [] }), ctrl: [] }
2022-07-14T00:44:31.569643035+00:00 DEBUG    │  ┝━ do_search [ 508µs | 0.01% / 0.21% ]
2022-07-14T00:44:31.569661410+00:00 DEBUG    │  │  ┝━ 🐛 [debug]:  | request.base: "ou=people,dc=example,dc=com" | scope: Users
2022-07-14T00:44:31.569665202+00:00 DEBUG    │  │  ┕━ get_user_list [ 473µs | 0.04% / 0.19% ]
2022-07-14T00:44:31.569675994+00:00 DEBUG    │  │     ┝━ 🐛 [debug]:  | ldap_filter: And([Equality("objectClass", "person"), Equality("memberof", "cn=admins,ou=groups,dc=example,dc=com")])
2022-07-14T00:44:31.569693495+00:00 DEBUG    │  │     ┝━ 🐛 [debug]:  | parsed_filters: And([And([]), MemberOf("admins")])
2022-07-14T00:44:31.569696411+00:00 DEBUG    │  │     ┝━ expand_attribute_wildcards [ 22.8µs | 0.01% ]
2022-07-14T00:44:31.569716537+00:00 DEBUG    │  │     │  ┕━ 🐛 [debug]:  | ldap_attributes: [] | resolved_attributes: ["objectclass", "dn", "uid", "mail", "givenname", "sn", "cn", "createtimestamp"]
2022-07-14T00:44:31.569730537+00:00 DEBUG    │  │     ┕━ list_users [ 353µs | 0.14% ]
2022-07-14T00:44:31.569738121+00:00 DEBUG    │  │        ┝━ 🐛 [debug]:  | filters: Some(And([And([]), MemberOf("admins")])) | get_groups: false
2022-07-14T00:44:31.569841665+00:00 DEBUG    │  │        ┝━ 🐛 [debug]:  | query: SELECT "users"."user_id", "email", "users"."display_name", "first_name", "last_name", "avatar", "users"."creation_date", "users"."uuid" FROM "users" LEFT JOIN "memberships" ON "users"."user_id" = "memberships"."user_id" LEFT JOIN "groups" ON "memberships"."group_id" = "groups"."group_id" WHERE ? AND ("groups"."display_name" = ?) ORDER BY "users"."user_id" ASC
2022-07-14T00:44:31.571347866+00:00 DEBUG    │  │        ┕━ 🐛 [debug]:  | return: [UserAndGroups { user: User { user_id: UserId("ikaruswill"), email: "will@example.com", display_name: "Will Ho", first_name: "Will", last_name: "Ho", creation_date: 2022-07-13T00:02:21.017041305Z, uuid: Uuid("<UUID>") }, groups: None }]
2022-07-14T00:44:31.571442077+00:00 DEBUG    │  ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=ikaruswill,ou=people,dc=example,dc=com", attributes: [LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "dn", vals: ["uid=ikaruswill,ou=people,dc=example,dc=com"] }, LdapPartialAttribute { atype: "uid", vals: ["ikaruswill"] }, LdapPartialAttribute { atype: "mail", vals: ["will@example.com"] }, LdapPartialAttribute { atype: "givenname", vals: ["Will"] }, LdapPartialAttribute { atype: "sn", vals: ["Ho"] }, LdapPartialAttribute { atype: "cn", vals: ["Will Ho"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2022-07-13T00:02:21.017041305+00:00"] }] })
2022-07-14T00:44:31.571631956+00:00 DEBUG    │  ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
2022-07-14T00:44:31.573040447+00:00 INFO     ┕━ LDAP request [ 26.8µs | 0.01% ]
2022-07-14T00:44:31.573062323+00:00 DEBUG       ┕━ 🐛 [debug]:  | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] }
Originally created by @ikaruswill on GitHub (Jul 14, 2022). Original GitHub issue: https://github.com/lldap/lldap/issues/255 ## Context I was just debugging the problem described in https://github.com/nitnelave/lldap/issues/254 and I came across this one when tinkering with the search scope. ## Problem When varying scope for `ldapsearch` between `base` and `one` we'd expect the search to be on the base object itself, and one subtree down. However, varying scope seems to have no effect when search is performed against an LLDAP server. Here I perform search for a `objectClass=person` that is a `memberOf` `cn=admins` group with a search base of `ou=people`. I set the scope to be `base` so the search will only search the object `ou=people,dc=example,dc=com`, which itself is not an `objectClass=person` so should return 0 results. Only if scope is set to `one` will the search look at direct descendants. ([Scope docs](https://ldapwiki.com/wiki/LDAP%20Search%20Scopes)) Against LLDAP: ``` bash-5.1# ldapsearch -H ldap://lldap:389 -LLL -D "uid=admin,ou=people,dc=example,dc=com" -w '<password>' -s "Base" -b "ou=people,dc=example,dc=com" '(&(objectClass=person)(memberof=cn=admins,ou=groups,dc=example,dc=com))' dn: uid=ikaruswill,ou=people,dc=example,dc=com objectclass: inetOrgPerson objectclass: posixAccount objectclass: mailAccount objectclass: person dn: uid=ikaruswill,ou=people,dc=example,dc=com uid: ikaruswill mail: will@example.com givenname: Will sn: Ho cn: Will Ho createtimestamp: 2022-07-13T00:02:21.017041305+00:00 ``` Against OpenLDAP (no results): ``` bash-5.1# ldapsearch -H ldap://openldap:389 -LLL -D "cn=admin,dc=example,dc=com" -w '<password>' -s "Base" -b "ou=people,dc=example,dc=com" '(&(objectClass=person)(memberof=cn=admins,ou=groups,dc=example,dc=com))' bash-5.1# ``` Relevant logs: ``` 2022-07-14T00:44:31.321810145+00:00 INFO LDAP session [ 248ms | 0.10% / 100.00% ] 2022-07-14T00:44:31.321893272+00:00 INFO ┝━ LDAP request [ 247ms | 0.09% / 99.55% ] 2022-07-14T00:44:31.321918939+00:00 DEBUG │ ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=admin,ou=people,dc=example,dc=com", cred: Simple("********") }), ctrl: [] } 2022-07-14T00:44:31.321924481+00:00 DEBUG │ ┝━ do_bind [ 247ms | 0.02% / 99.45% ] 2022-07-14T00:44:31.321930897+00:00 DEBUG │ │ ┝━ 🐛 [debug]: DN: uid=admin,ou=people,dc=example,dc=com 2022-07-14T00:44:31.321944023+00:00 DEBUG │ │ ┝━ bind [ 246ms | 0.18% / 99.30% ] 2022-07-14T00:44:31.322371033+00:00 DEBUG │ │ │ ┕━ passwords_match [ 246ms | 99.12% ] 2022-07-14T00:44:31.568146167+00:00 DEBUG │ │ ┝━ get_user_groups [ 331µs | 0.13% ] 2022-07-14T00:44:31.568161917+00:00 DEBUG │ │ │ ┝━ 🐛 [debug]: | user_id: UserId("admin") 2022-07-14T00:44:31.568230169+00:00 DEBUG │ │ │ ┝━ 🐛 [debug]: | query: SELECT "groups"."group_id", "display_name", "creation_date", "uuid" FROM "groups" INNER JOIN "memberships" ON "groups"."group_id" = "memberships"."group_id" WHERE "user_id" = ? 2022-07-14T00:44:31.568903934+00:00 DEBUG │ │ │ ┕━ 🐛 [debug]: | return: {GroupDetails { group_id: GroupId(1), display_name: "lldap_admin", creation_date: 2022-07-12T23:48:25.516387433Z, uuid: Uuid("<UUID>") }} 2022-07-14T00:44:31.568922893+00:00 DEBUG │ │ ┕━ 🐛 [debug]: Success! 2022-07-14T00:44:31.568940977+00:00 DEBUG │ ┕━ 🐛 [debug]: | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None }) 2022-07-14T00:44:31.569602784+00:00 INFO ┝━ LDAP request [ 858µs | 0.14% / 0.35% ] 2022-07-14T00:44:31.569637785+00:00 DEBUG │ ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=example,dc=com", scope: Base, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: And([Equality("objectClass", "person"), Equality("memberof", "cn=admins,ou=groups,dc=example,dc=com")]), attrs: [] }), ctrl: [] } 2022-07-14T00:44:31.569643035+00:00 DEBUG │ ┝━ do_search [ 508µs | 0.01% / 0.21% ] 2022-07-14T00:44:31.569661410+00:00 DEBUG │ │ ┝━ 🐛 [debug]: | request.base: "ou=people,dc=example,dc=com" | scope: Users 2022-07-14T00:44:31.569665202+00:00 DEBUG │ │ ┕━ get_user_list [ 473µs | 0.04% / 0.19% ] 2022-07-14T00:44:31.569675994+00:00 DEBUG │ │ ┝━ 🐛 [debug]: | ldap_filter: And([Equality("objectClass", "person"), Equality("memberof", "cn=admins,ou=groups,dc=example,dc=com")]) 2022-07-14T00:44:31.569693495+00:00 DEBUG │ │ ┝━ 🐛 [debug]: | parsed_filters: And([And([]), MemberOf("admins")]) 2022-07-14T00:44:31.569696411+00:00 DEBUG │ │ ┝━ expand_attribute_wildcards [ 22.8µs | 0.01% ] 2022-07-14T00:44:31.569716537+00:00 DEBUG │ │ │ ┕━ 🐛 [debug]: | ldap_attributes: [] | resolved_attributes: ["objectclass", "dn", "uid", "mail", "givenname", "sn", "cn", "createtimestamp"] 2022-07-14T00:44:31.569730537+00:00 DEBUG │ │ ┕━ list_users [ 353µs | 0.14% ] 2022-07-14T00:44:31.569738121+00:00 DEBUG │ │ ┝━ 🐛 [debug]: | filters: Some(And([And([]), MemberOf("admins")])) | get_groups: false 2022-07-14T00:44:31.569841665+00:00 DEBUG │ │ ┝━ 🐛 [debug]: | query: SELECT "users"."user_id", "email", "users"."display_name", "first_name", "last_name", "avatar", "users"."creation_date", "users"."uuid" FROM "users" LEFT JOIN "memberships" ON "users"."user_id" = "memberships"."user_id" LEFT JOIN "groups" ON "memberships"."group_id" = "groups"."group_id" WHERE ? AND ("groups"."display_name" = ?) ORDER BY "users"."user_id" ASC 2022-07-14T00:44:31.571347866+00:00 DEBUG │ │ ┕━ 🐛 [debug]: | return: [UserAndGroups { user: User { user_id: UserId("ikaruswill"), email: "will@example.com", display_name: "Will Ho", first_name: "Will", last_name: "Ho", creation_date: 2022-07-13T00:02:21.017041305Z, uuid: Uuid("<UUID>") }, groups: None }] 2022-07-14T00:44:31.571442077+00:00 DEBUG │ ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=ikaruswill,ou=people,dc=example,dc=com", attributes: [LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "dn", vals: ["uid=ikaruswill,ou=people,dc=example,dc=com"] }, LdapPartialAttribute { atype: "uid", vals: ["ikaruswill"] }, LdapPartialAttribute { atype: "mail", vals: ["will@example.com"] }, LdapPartialAttribute { atype: "givenname", vals: ["Will"] }, LdapPartialAttribute { atype: "sn", vals: ["Ho"] }, LdapPartialAttribute { atype: "cn", vals: ["Will Ho"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2022-07-13T00:02:21.017041305+00:00"] }] }) 2022-07-14T00:44:31.571631956+00:00 DEBUG │ ┕━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) 2022-07-14T00:44:31.573040447+00:00 INFO ┕━ LDAP request [ 26.8µs | 0.01% ] 2022-07-14T00:44:31.573062323+00:00 DEBUG ┕━ 🐛 [debug]: | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] } ```
kerem 2026-02-27 08:15:12 +03:00
Author
Owner

@nitnelave commented on GitHub (Jul 14, 2022):

Yeah, the logic around scope is simplified, since we don't have objects at different levels. Are you actually running into issues because of that?

<!-- gh-comment-id:1184013846 --> @nitnelave commented on GitHub (Jul 14, 2022): Yeah, the logic around scope is simplified, since we don't have objects at different levels. Are you actually running into issues because of that?
Author
Owner

@ikaruswill commented on GitHub (Jul 14, 2022):

I see. At the moment not really. Only the dn issue is causing problems with Home assistant LDAP script. Thought I'd flag it out here for awareness!

<!-- gh-comment-id:1184036642 --> @ikaruswill commented on GitHub (Jul 14, 2022): I see. At the moment not really. Only the dn issue is causing problems with Home assistant LDAP script. Thought I'd flag it out here for awareness!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/lldap-lldap#93
No description provided.