[GH-ISSUE #1362] [BUG] Unexpected behavior on cn-search #474

Closed
opened 2026-02-27 08:17:28 +03:00 by kerem · 6 comments
Owner

Originally created by @LageTs on GitHub (Dec 10, 2025).
Original GitHub issue: https://github.com/lldap/lldap/issues/1362

Originally assigned to: @Copilot on GitHub.

Describe the bug
I switched from 0.5.0 to 0.6.2 and got errors on my radicale service. Regardless of that I found some behavior that I didn't expect for two ldapsearch requests to my service (changed the dc and UID for privacy but it was identical on command execution, others untouched):

~> ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=*"
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=lagm,dc=tessst> with scope subtree
# filter: cn=*
# requesting: ALL
#

[I've left a few one out here]

# testall, people, tesst.tessst
dn: uid=testall,ou=people,dc=tesst,dc=tessst
cn: TestAll
createtimestamp: 2025-12-10T03:07:27.833947890+00:00
entryuuid: ###UID###
first_name: Test
givenname: Test
last_name: All
mail: mail.test.all@tesst.tessst
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: mailAccount
objectclass: person
sn: All
uid: testall

[I've left a few one out here]

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQsEAA==
pagedresults: estimate=11 cookie=

# numResponses: 12
# numEntries: 11
~> ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=TestAll"
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=tesst,dc=tessst> with scope subtree
# filter: cn=TestAll
# requesting: ALL
#

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQAEAA==
pagedresults: cookie=

# numResponses: 1

To Reproduce
Steps to reproduce the behavior:

  1. have an account to search entries
  2. create Test account
  3. search for Test account by cn
  4. get no results

Expected behavior
I would expect the result to include exactly that one entry that has cn=TestAll, not more, not less than that.

Logs
I couldn't find any logs. Searched for lldap specific logs and in my system log (/var/log/messages)

Additional context
I'm not really sure If I didn't make any false assumptions, please feel free to correct me, if so. LLDAP is installed on alpine-lxc in proxmox as binaries from github.

I noticed this as my radicale instance needs user names to be case sensitive as far as I know. My other services are running fine as they doesn't need this and work with uid requests which return the expected result for case-insensitive searches.

My radicale ldap_filter was like this before. I think this is not relevant:
ldap_filter = (&(cn={0})(|(memberOf=cn=radicale,ou=groups,dc=tesst,dc=tessst)(memberOf=cn=superuser,ou=groups,dc=tesst,dc=tessst)))

Originally created by @LageTs on GitHub (Dec 10, 2025). Original GitHub issue: https://github.com/lldap/lldap/issues/1362 Originally assigned to: @Copilot on GitHub. **Describe the bug** I switched from 0.5.0 to 0.6.2 and got errors on my radicale service. Regardless of that I found some behavior that I didn't expect for two ldapsearch requests to my service (changed the dc and UID for privacy but it was identical on command execution, others untouched): ``` ~> ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=*" # extended LDIF # # LDAPv3 # base <ou=people,dc=lagm,dc=tessst> with scope subtree # filter: cn=* # requesting: ALL # [I've left a few one out here] # testall, people, tesst.tessst dn: uid=testall,ou=people,dc=tesst,dc=tessst cn: TestAll createtimestamp: 2025-12-10T03:07:27.833947890+00:00 entryuuid: ###UID### first_name: Test givenname: Test last_name: All mail: mail.test.all@tesst.tessst objectclass: inetOrgPerson objectclass: posixAccount objectclass: mailAccount objectclass: person sn: All uid: testall [I've left a few one out here] # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQsEAA== pagedresults: estimate=11 cookie= # numResponses: 12 # numEntries: 11 ``` ``` ~> ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=TestAll" # extended LDIF # # LDAPv3 # base <ou=people,dc=tesst,dc=tessst> with scope subtree # filter: cn=TestAll # requesting: ALL # # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQAEAA== pagedresults: cookie= # numResponses: 1 ``` **To Reproduce** Steps to reproduce the behavior: 1. have an account to search entries 2. create Test account 3. search for Test account by cn 4. get no results **Expected behavior** I would expect the result to include exactly that one entry that has cn=TestAll, not more, not less than that. **Logs** I couldn't find any logs. Searched for lldap specific logs and in my system log (/var/log/messages) **Additional context** I'm not really sure If I didn't make any false assumptions, please feel free to correct me, if so. LLDAP is installed on alpine-lxc in proxmox as binaries from github. I noticed this as my radicale instance needs user names to be case sensitive as far as I know. My other services are running fine as they doesn't need this and work with uid requests which return the expected result for case-insensitive searches. My radicale ldap_filter was like this before. I think this is not relevant: ldap_filter = (&(cn={0})(|(memberOf=cn=radicale,ou=groups,dc=tesst,dc=tessst)(memberOf=cn=superuser,ou=groups,dc=tesst,dc=tessst)))
kerem 2026-02-27 08:17:28 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@nitnelave commented on GitHub (Dec 10, 2025):

The LDAP verbose logs would help LLDAP_VERBOSE=true, logs are on standard output for LLDAP.

But the LLDAP protocol is by and large case insensitive. If radicale expects case sensitive usernames, that's not really compatible with LLDAP and there's not much I can do about that.

<!-- gh-comment-id:3635789139 --> @nitnelave commented on GitHub (Dec 10, 2025): The LDAP verbose logs would help `LLDAP_VERBOSE=true`, logs are on standard output for LLDAP. But the LLDAP protocol is by and large case insensitive. If radicale expects case sensitive usernames, that's not really compatible with LLDAP and there's not much I can do about that.
Author
Owner

@LageTs commented on GitHub (Dec 10, 2025):

But than is behavior is still other than expected. If the cn is set to "TestAll" and i search for "cn=TestAll" it still should return that user. Or if I set it to "TestAll" and search for "cn=testall" or even of other way round and it is set to "testall" and i search for "cn=testall" or "cn=TestAll". But only if it is set in lower-case the search returns the user.

So assume the following user:

dn: uid=testall,ou=people,dc=tesst,dc=tessst
cn: Testall
createtimestamp: 2025-12-10T03:07:27.833947890+00:00
entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80
first_name: Test
givenname: Test
last_name: All
mail: mail.test.all@tesst.tessst
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: mailAccount
objectclass: person
sn: All
uid: testall

I get this replys:

ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=Testall"
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=tesst,dc=tessst> with scope subtree
# filter: cn=Testall
# requesting: ALL
#

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQAEAA==
pagedresults: cookie=

# numResponses: 1
ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=testall"
# extended LDIF
#
# LDAPv3
# base <ou=people,dc=tesst,dc=de> with scope subtree
# filter: cn=testall
# requesting: ALL
#

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQAEAA==
pagedresults: cookie=

# numResponses: 1

But if case-insensitive, I would expect both to return the following. If case-sensitive I would expect the first one to return the following, but both don't:

# extended LDIF
#
# LDAPv3
# base <ou=people,dc=tesst,dc=tessst> with scope subtree
# filter: cn=testAll
# requesting: ALL
#

# testall, people, tesst.tessst
dn: uid=testall,ou=people,dc=tesst,dc=tessst
cn: Testall
createtimestamp: 2025-12-10T03:07:27.833947890+00:00
entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80
first_name: Test
givenname: Test
last_name: All
mail: mail.test.all@tesst.tessst
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: mailAccount
objectclass: person
sn: All
uid: testall

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQEEAA==
pagedresults: estimate=1 cookie=

# numResponses: 2
# numEntries: 1

As upper-case-letters a allowed in ldap-cn according to https://datatracker.ietf.org/doc/html/rfc4519#section-2.3

If i set the user to be like this:

# extended LDIF
#
# LDAPv3
# base <ou=people,dc=tesst,dc=tessst> with scope subtree
# filter: cn=testAll
# requesting: ALL
#

# testall, people, tesst.tessst
dn: uid=testall,ou=people,dc=tesst,dc=tessst
cn: testall
createtimestamp: 2025-12-10T03:07:27.833947890+00:00
entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80
first_name: Test
givenname: Test
last_name: All
mail: mail.test.all@tesst.tessst
objectclass: inetOrgPerson
objectclass: posixAccount
objectclass: mailAccount
objectclass: person
sn: All
uid: testall

# search result
search: 2
result: 0 Success
control: 1.2.840.113556.1.4.319 false MAUCAQEEAA==
pagedresults: estimate=1 cookie=

# numResponses: 2
# numEntries: 1

Than the search works like I would it expect as case-sensitive so it returns the user on "cn=testall" but not on "cn=Testall"

In the following the log output of the lldap session with first an search for "cn=*" and than the two commands from above with ldapsearch.

# ./lldap run
Loading configuration from lldap_config.toml
Configuration: Configuration {
    ldap_host: "0.0.0.0",
    ldap_port: 389,
    http_host: "0.0.0.0",
    http_port: 17170,
    jwt_secret: Some(
        ***SECRET***,
    ),
    ldap_base_dn: "dc=tesst,dc=tessst",
    ldap_user_dn: "lldap",
    ldap_user_email: "ldap@tesst.tessst",
    ldap_user_pass: Some(
        ***SECRET***,
    ),
    force_ldap_user_pass_reset: False,
    force_update_private_key: false,
    database_url: "sqlite:///opt/lldap/users.db?mode=rwc",
    ignored_user_attributes: [],
    ignored_group_attributes: [],
    verbose: true,
    key_file: "server_key",
    key_seed: Some(
        ***SECRET***,
    ),
    assets_path: "./app",
    smtp_options: MailOptions {
        enable_password_reset: false,
        from: None,
        reply_to: None,
        server: "localhost",
        port: 587,
        user: "",
        password: ***SECRET***,
        smtp_encryption: Tls,
        ..
    },
    ldaps_options: LdapsOptions {
        enabled: true,
        port: 636,
        cert_file: "/etc/letsencrypt/live/ldap.tesst.tessst/fullchain.pem",
        key_file: "/etc/letsencrypt/live/ldap.tesst.tessst/privkey.pem",
    },
    http_url: "https://ldap.tesst.tessst/",
    ..
}
WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message.
2025-12-10T15:56:17.919742795+00:00  INFO     set_up_server [ 4.49ms | 2.29% / 100.00% ]
2025-12-10T15:56:17.919755546+00:00  INFO     ┝━ i [info]: Starting LLDAP version 0.6.2
2025-12-10T15:56:17.920165038+00:00  DEBUG    ┝━ get_schema_version [ 155µs | 3.44% ]
2025-12-10T15:56:17.920659092+00:00  DEBUG    │  ┕━ 🐛 [debug]:  | return: Some(SchemaVersion(10))
2025-12-10T15:56:17.921142505+00:00  DEBUG    ┝━ list_groups [ 1.60ms | 35.63% ] filters: Some(DisplayName("lldap_admin"))
2025-12-10T15:56:17.922532045+00:00  DEBUG    │  ┕━ 🐛 [debug]:  | return: [Group { id: 1, display_name: "lldap_admin", creation_date: 2025-03-14T01:02:31.476783054, uuid: "###UUID###", users: ["lldap"], attributes: [] }]
2025-12-10T15:56:17.922556666+00:00  DEBUG    ┝━ list_groups [ 534µs | 11.88% ] filters: Some(DisplayName("lldap_password_manager"))
2025-12-10T15:56:17.923176240+00:00  DEBUG    │  ┕━ 🐛 [debug]:  | return: [Group { id: 2, display_name: "lldap_password_manager", creation_date: 2025-03-14T01:02:31.494843627, uuid: "###UUID###", users: [], attributes: [] }]
2025-12-10T15:56:17.923195340+00:00  DEBUG    ┝━ list_groups [ 615µs | 13.68% ] filters: Some(DisplayName("lldap_strict_readonly"))
2025-12-10T15:56:17.923814334+00:00  DEBUG    │  ┕━ 🐛 [debug]:  | return: [Group { id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", users: ["radicale", ###OTHERS###], attributes: [] }]
2025-12-10T15:56:17.925087684+00:00  INFO     ┝━ i [info]: Starting the LDAP server on port 389
2025-12-10T15:56:17.925293655+00:00  INFO     ┝━ i [info]: Starting the LDAPS server on port 636
2025-12-10T15:56:17.923838615+00:00  DEBUG    ┝━ list_users [ 1.38ms | 30.71% ] filters: Some(MemberOf("lldap_admin")) | _get_groups: false
2025-12-10T15:56:17.924956423+00:00  DEBUG    │  ┕━ 🐛 [debug]:  | return: [UserAndGroups { user: User { user_id: "lldap", email: "ldap@tesst.tessst", display_name: Some("Administrator"), creation_date: 2025-03-14T01:02:31.537663854, uuid: "###UUID###", attributes: [] }, groups: Some([GroupDetails { group_id: 1, display_name: "lldap_admin", creation_date: 2025-03-14T01:02:31.476783054, uuid: "###UUID###", attributes: [] }]) }]
2025-12-10T15:56:17.925322435+00:00  DEBUG    ┝━ get_jwt_blacklist [ 106µs | 2.36% ]
2025-12-10T15:56:17.925456826+00:00  INFO     ┕━ i [info]: Starting the API/web server on port 17170
2025-12-10T15:56:17.925567707+00:00  INFO     i [info]: starting 1 workers
2025-12-10T15:56:17.925654078+00:00  INFO     i [info]: Actix runtime found; starting in Actix runtime
2025-12-10T15:56:17.925710348+00:00  INFO     i [info]: starting service: "ldap", workers: 1, listening on: 0.0.0.0:389
2025-12-10T15:56:17.925717508+00:00  INFO     i [info]: starting service: "ldaps", workers: 1, listening on: 0.0.0.0:636
2025-12-10T15:56:17.925763958+00:00  INFO     i [info]: starting service: "http", workers: 1, listening on: 0.0.0.0:17170
2025-12-10T15:56:17.926630395+00:00  INFO     i [info]: DB Cleanup Cron started
2025-12-10T15:56:23.957882765+00:00  DEBUG    🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382
2025-12-10T15:56:23.999908367+00:00  INFO     i [info]: LDAP session start: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b
2025-12-10T15:56:24.000019667+00:00  INFO     LDAP request [ 84.0ms | 0.00% / 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b
2025-12-10T15:56:24.000034028+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] }
2025-12-10T15:56:24.000036378+00:00  DEBUG    ┝━ do_bind [ 84.0ms | 0.00% / 100.00% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst
2025-12-10T15:56:24.000048248+00:00  DEBUG    │  ┝━ bind [ 83.5ms | 0.00% / 99.35% ]
2025-12-10T15:56:24.000062278+00:00  DEBUG    │  │  ┝━ get_password_file_for_user [ 241µs | 0.29% ] user_id: "radicale"
2025-12-10T15:56:24.000273659+00:00  INFO     │  │  ┝━ i [info]: Login attempt for "radicale"
2025-12-10T15:56:24.000275139+00:00  DEBUG    │  │  ┕━ passwords_match [ 83.2ms | 99.07% ] username: radicale
2025-12-10T15:56:24.083516702+00:00  DEBUG    │  ┝━ get_user_groups [ 544µs | 0.65% ] user_id: "radicale"
2025-12-10T15:56:24.083960795+00:00  DEBUG    │  │  ┕━ 🐛 [debug]:  | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }}
2025-12-10T15:56:24.083972185+00:00  DEBUG    │  ┕━ 🐛 [debug]: Success!
2025-12-10T15:56:24.083978475+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None })
2025-12-10T15:56:24.119227217+00:00  INFO     LDAP request [ 1.54ms | 0.00% / 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b
2025-12-10T15:56:24.119233247+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("cn"), attrs: [] }), ctrl: [] }
2025-12-10T15:56:24.120568507+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120612567+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120630417+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120645557+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120672777+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120692808+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", attributes: [LdapPartialAttribute { atype: "cn", vals: ["Radicale Reader"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2025-03-14T01:05:27.516894904+00:00"] }, LdapPartialAttribute { atype: "entryuuid", vals: [###UUID###] }, LdapPartialAttribute { atype: "mail", vals: ["radicale@tesst.tessst"] }, LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "uid", vals: ["radicale"] }] })
2025-12-10T15:56:24.120729218+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=testall,ou=people,dc=tesst,dc=tessst", attributes: [LdapPartialAttribute { atype: "cn", vals: ["Testall"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2025-12-10T03:07:27.833947890+00:00"] }, LdapPartialAttribute { atype: "entryuuid", vals: ["###UUID###"] }, LdapPartialAttribute { atype: "first_name", vals: ["Test"] }, LdapPartialAttribute { atype: "givenname", vals: ["Test"] }, LdapPartialAttribute { atype: "last_name", vals: ["All"] }, LdapPartialAttribute { atype: "mail", vals: ["mail.test.all@tesst.tessst"] }, LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "sn", vals: ["All"] }, LdapPartialAttribute { atype: "uid", vals: ["testall"] }] })
2025-12-10T15:56:24.120747558+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120768968+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120787998+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120821768+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultEntry(###Removed Entry for privacy###)
2025-12-10T15:56:24.120834849+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
2025-12-10T15:56:24.119238537+00:00  DEBUG    ┕━ do_search [ 1.54ms | 0.00% / 100.00% ]
2025-12-10T15:56:24.119239617+00:00  DEBUG       ┕━ do_search [ 1.54ms | 0.00% / 100.00% ]
2025-12-10T15:56:24.119431209+00:00  DEBUG          ┝━ 🐛 [debug]:  | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users
2025-12-10T15:56:24.120489516+00:00  DEBUG          ┝━ expand_attribute_wildcards [ 7.32µs | 0.48% ] ldap_attributes: []
2025-12-10T15:56:24.120497056+00:00  DEBUG          │  ┕━ 🐛 [debug]:  | attributes_out: {AttributeName(CaseInsensitiveString("cn")): "cn", AttributeName(CaseInsensitiveString("createtimestamp")): "createtimestamp", AttributeName(CaseInsensitiveString("entryuuid")): "entryuuid", AttributeName(CaseInsensitiveString("givenname")): "givenname", AttributeName(CaseInsensitiveString("jpegphoto")): "jpegPhoto", AttributeName(CaseInsensitiveString("mail")): "mail", AttributeName(CaseInsensitiveString("objectclass")): "objectclass", AttributeName(CaseInsensitiveString("sn")): "sn", AttributeName(CaseInsensitiveString("uid")): "uid"}
2025-12-10T15:56:24.119432929+00:00  DEBUG          ┕━ get_user_list [ 1.53ms | 0.00% / 99.52% ]
2025-12-10T15:56:24.119435429+00:00  DEBUG             ┝━ 🐛 [debug]:  | filters: True
2025-12-10T15:56:24.119438019+00:00  DEBUG             ┕━ list_users [ 1.53ms | 99.52% ] filters: Some(True) | _get_groups: false
2025-12-10T15:56:24.120484876+00:00  DEBUG                ┕━ 🐛 [debug]:  | return: [UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups { user: User { user_id: "radicale", email: "radicale@tesst.tessst", display_name: Some("Radicale Reader"), creation_date: 2025-03-14T01:05:27.516894904, uuid: "###UUID###", attributes: [] }, groups: Some([GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }]) }, UserAndGroups { user: User { user_id: "testall", email: "mail.test.all@tesst.tessst", display_name: Some("Testall"), creation_date: 2025-12-10T03:07:27.833947890, uuid: "###UUID###", attributes: [Attribute { name: AttributeName(CaseInsensitiveString("first_name")), value: String(Singleton("Test")) }, Attribute { name: AttributeName(CaseInsensitiveString("last_name")), value: String(Singleton("All")) }] }, groups: Some([GroupDetails { group_id: 4, display_name: "radicale", creation_date: 2025-03-14T16:41:41.519585857, uuid: "###UUID###", attributes: [] }]) }, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}]
2025-12-10T15:56:24.189227396+00:00  INFO     LDAP request [ 5.37µs | 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b
2025-12-10T15:56:24.189230676+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] }
2025-12-10T15:56:24.189232826+00:00  DEBUG    ┕━ 🐛 [debug]: Unbind request for radicale
2025-12-10T15:56:24.189247546+00:00  INFO     i [info]: LDAP session end: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b
2025-12-10T15:56:27.414554450+00:00  DEBUG    🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382
2025-12-10T15:56:27.455970245+00:00  INFO     i [info]: LDAP session start: ca61895c-b599-4754-845b-30e8fbb7e82f
2025-12-10T15:56:27.455987215+00:00  INFO     LDAP request [ 85.9ms | 0.06% / 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f
2025-12-10T15:56:27.455994195+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] }
2025-12-10T15:56:27.455996055+00:00  DEBUG    ┝━ do_bind [ 85.9ms | 0.00% / 99.94% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst
2025-12-10T15:56:27.456002305+00:00  DEBUG    │  ┝━ bind [ 85.6ms | 0.09% / 99.64% ]
2025-12-10T15:56:27.456005155+00:00  DEBUG    │  │  ┝━ get_password_file_for_user [ 112µs | 0.13% ] user_id: "radicale"
2025-12-10T15:56:27.456187927+00:00  INFO     │  │  ┝━ i [info]: Login attempt for "radicale"
2025-12-10T15:56:27.456189797+00:00  DEBUG    │  │  ┕━ passwords_match [ 85.4ms | 99.42% ] username: radicale
2025-12-10T15:56:27.541645986+00:00  DEBUG    │  ┝━ get_user_groups [ 252µs | 0.29% ] user_id: "radicale"
2025-12-10T15:56:27.541913778+00:00  DEBUG    │  │  ┕━ 🐛 [debug]:  | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }}
2025-12-10T15:56:27.541919128+00:00  DEBUG    │  ┕━ 🐛 [debug]: Success!
2025-12-10T15:56:27.541926988+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None })
2025-12-10T15:56:27.575749189+00:00  INFO     LDAP request [ 791µs | 6.13% / 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f
2025-12-10T15:56:27.575755149+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("cn", "Testall"), attrs: [] }), ctrl: [] }
2025-12-10T15:56:27.576694266+00:00  DEBUG    ┝━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
2025-12-10T15:56:27.575756819+00:00  DEBUG    ┕━ do_search [ 743µs | 5.25% / 93.87% ]
2025-12-10T15:56:27.575757989+00:00  DEBUG       ┕━ do_search [ 701µs | 0.00% / 88.62% ]
2025-12-10T15:56:27.575970870+00:00  DEBUG          ┝━ 🐛 [debug]:  | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users
2025-12-10T15:56:27.575972280+00:00  DEBUG          ┕━ get_user_list [ 701µs | 0.00% / 88.62% ]
2025-12-10T15:56:27.575975810+00:00  DEBUG             ┝━ 🐛 [debug]:  | filters: Equality(DisplayName, "testall")
2025-12-10T15:56:27.575979211+00:00  DEBUG             ┕━ list_users [ 701µs | 88.62% ] filters: Some(Equality(DisplayName, "testall")) | _get_groups: false
2025-12-10T15:56:27.576685546+00:00  DEBUG                ┕━ 🐛 [debug]:  | return: []
2025-12-10T15:56:27.609787942+00:00  INFO     LDAP request [ 5.31µs | 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f
2025-12-10T15:56:27.609791542+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] }
2025-12-10T15:56:27.609793392+00:00  DEBUG    ┕━ 🐛 [debug]: Unbind request for radicale
2025-12-10T15:56:27.609827312+00:00  INFO     i [info]: LDAP session end: ca61895c-b599-4754-845b-30e8fbb7e82f
2025-12-10T15:56:37.206152474+00:00  DEBUG    🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382
2025-12-10T15:56:37.245469484+00:00  INFO     i [info]: LDAP session start: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6
2025-12-10T15:56:37.245494294+00:00  INFO     LDAP request [ 83.2ms | 0.07% / 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6
2025-12-10T15:56:37.245503144+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] }
2025-12-10T15:56:37.245505735+00:00  DEBUG    ┝━ do_bind [ 83.2ms | 0.00% / 99.93% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst
2025-12-10T15:56:37.245515485+00:00  DEBUG    │  ┝━ bind [ 82.9ms | 0.12% / 99.58% ]
2025-12-10T15:56:37.245518765+00:00  DEBUG    │  │  ┝━ get_password_file_for_user [ 122µs | 0.15% ] user_id: "radicale"
2025-12-10T15:56:37.245737616+00:00  INFO     │  │  ┝━ i [info]: Login attempt for "radicale"
2025-12-10T15:56:37.245739316+00:00  DEBUG    │  │  ┕━ passwords_match [ 82.7ms | 99.30% ] username: radicale
2025-12-10T15:56:37.328407376+00:00  DEBUG    │  ┝━ get_user_groups [ 298µs | 0.36% ] user_id: "radicale"
2025-12-10T15:56:37.328727528+00:00  DEBUG    │  │  ┕━ 🐛 [debug]:  | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }}
2025-12-10T15:56:37.328732948+00:00  DEBUG    │  ┕━ 🐛 [debug]: Success!
2025-12-10T15:56:37.328738898+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None })
2025-12-10T15:56:37.360503825+00:00  INFO     LDAP request [ 751µs | 0.00% / 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6
2025-12-10T15:56:37.360510845+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("cn", "testall"), attrs: [] }), ctrl: [] }
2025-12-10T15:56:37.360512135+00:00  DEBUG    ┝━ do_search [ 751µs | 0.00% / 100.00% ]
2025-12-10T15:56:37.360513245+00:00  DEBUG    │  ┕━ do_search [ 751µs | 35.79% / 100.00% ]
2025-12-10T15:56:37.360707786+00:00  DEBUG    │     ┝━ 🐛 [debug]:  | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users
2025-12-10T15:56:37.360709296+00:00  DEBUG    │     ┕━ get_user_list [ 482µs | 8.89% / 64.21% ]
2025-12-10T15:56:37.360712996+00:00  DEBUG    │        ┝━ 🐛 [debug]:  | filters: Equality(DisplayName, "testall")
2025-12-10T15:56:37.360716456+00:00  DEBUG    │        ┕━ list_users [ 415µs | 55.32% ] filters: Some(Equality(DisplayName, "testall")) | _get_groups: false
2025-12-10T15:56:37.361241790+00:00  DEBUG    │           ┕━ 🐛 [debug]:  | return: []
2025-12-10T15:56:37.361252570+00:00  DEBUG    ┕━ 🐛 [debug]:  | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] })
2025-12-10T15:56:37.392477582+00:00  INFO     LDAP request [ 5.35µs | 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6
2025-12-10T15:56:37.392480942+00:00  DEBUG    ┝━ 🐛 [debug]:  | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] }
2025-12-10T15:56:37.392482832+00:00  DEBUG    ┕━ 🐛 [debug]: Unbind request for radicale
2025-12-10T15:56:37.392496813+00:00  INFO     i [info]: LDAP session end: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6
^C2025-12-10T15:56:52.508526477+00:00  INFO     i [info]: SIGINT received; starting forced shutdown
2025-12-10T15:56:52.508620708+00:00  INFO     i [info]: shutting down idle worker
2025-12-10T15:56:52.508934310+00:00  DEBUG    🐛 [debug]: paused accepting connections on 0.0.0.0:389
2025-12-10T15:56:52.508945930+00:00  DEBUG    🐛 [debug]: paused accepting connections on 0.0.0.0:636
2025-12-10T15:56:52.508954590+00:00  DEBUG    🐛 [debug]: paused accepting connections on 0.0.0.0:17170
2025-12-10T15:56:52.508958990+00:00  INFO     i [info]: accept thread stopped
2025-12-10T15:56:52.810990622+00:00  INFO     i [info]: DB Cleanup stopped
<!-- gh-comment-id:3637945642 --> @LageTs commented on GitHub (Dec 10, 2025): But than is behavior is still other than expected. If the cn is set to "TestAll" and i search for "cn=TestAll" it still should return that user. Or if I set it to "TestAll" and search for "cn=testall" or even of other way round and it is set to "testall" and i search for "cn=testall" or "cn=TestAll". But only if it is set in lower-case the search returns the user. So assume the following user: ```# testall, people, tesst.tessst dn: uid=testall,ou=people,dc=tesst,dc=tessst cn: Testall createtimestamp: 2025-12-10T03:07:27.833947890+00:00 entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80 first_name: Test givenname: Test last_name: All mail: mail.test.all@tesst.tessst objectclass: inetOrgPerson objectclass: posixAccount objectclass: mailAccount objectclass: person sn: All uid: testall ``` I get this replys: ``` ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=Testall" # extended LDIF # # LDAPv3 # base <ou=people,dc=tesst,dc=tessst> with scope subtree # filter: cn=Testall # requesting: ALL # # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQAEAA== pagedresults: cookie= # numResponses: 1 ``` ``` ldapsearch -x -H ldaps://ldap.tesst.tessst:636 -b "ou=people,dc=tesst,dc=tessst" -D "uid=radicale,ou=people,dc=tesst,dc=tessst" -w "###SECRET###" "cn=testall" # extended LDIF # # LDAPv3 # base <ou=people,dc=tesst,dc=de> with scope subtree # filter: cn=testall # requesting: ALL # # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQAEAA== pagedresults: cookie= # numResponses: 1 ``` But if case-insensitive, I would expect both to return the following. If case-sensitive I would expect the first one to return the following, but both don't: ``` # extended LDIF # # LDAPv3 # base <ou=people,dc=tesst,dc=tessst> with scope subtree # filter: cn=testAll # requesting: ALL # # testall, people, tesst.tessst dn: uid=testall,ou=people,dc=tesst,dc=tessst cn: Testall createtimestamp: 2025-12-10T03:07:27.833947890+00:00 entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80 first_name: Test givenname: Test last_name: All mail: mail.test.all@tesst.tessst objectclass: inetOrgPerson objectclass: posixAccount objectclass: mailAccount objectclass: person sn: All uid: testall # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQEEAA== pagedresults: estimate=1 cookie= # numResponses: 2 # numEntries: 1 ``` As upper-case-letters a allowed in ldap-cn according to https://datatracker.ietf.org/doc/html/rfc4519#section-2.3 If i set the user to be like this: ``` # extended LDIF # # LDAPv3 # base <ou=people,dc=tesst,dc=tessst> with scope subtree # filter: cn=testAll # requesting: ALL # # testall, people, tesst.tessst dn: uid=testall,ou=people,dc=tesst,dc=tessst cn: testall createtimestamp: 2025-12-10T03:07:27.833947890+00:00 entryuuid: 4fae4752-060b-36a9-9954-11f63a882d80 first_name: Test givenname: Test last_name: All mail: mail.test.all@tesst.tessst objectclass: inetOrgPerson objectclass: posixAccount objectclass: mailAccount objectclass: person sn: All uid: testall # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.319 false MAUCAQEEAA== pagedresults: estimate=1 cookie= # numResponses: 2 # numEntries: 1 ``` Than the search works like I would it expect as case-sensitive so it returns the user on "cn=testall" but not on "cn=Testall" In the following the log output of the lldap session with first an search for "cn=*" and than the two commands from above with ldapsearch. ``` # ./lldap run Loading configuration from lldap_config.toml Configuration: Configuration { ldap_host: "0.0.0.0", ldap_port: 389, http_host: "0.0.0.0", http_port: 17170, jwt_secret: Some( ***SECRET***, ), ldap_base_dn: "dc=tesst,dc=tessst", ldap_user_dn: "lldap", ldap_user_email: "ldap@tesst.tessst", ldap_user_pass: Some( ***SECRET***, ), force_ldap_user_pass_reset: False, force_update_private_key: false, database_url: "sqlite:///opt/lldap/users.db?mode=rwc", ignored_user_attributes: [], ignored_group_attributes: [], verbose: true, key_file: "server_key", key_seed: Some( ***SECRET***, ), assets_path: "./app", smtp_options: MailOptions { enable_password_reset: false, from: None, reply_to: None, server: "localhost", port: 587, user: "", password: ***SECRET***, smtp_encryption: Tls, .. }, ldaps_options: LdapsOptions { enabled: true, port: 636, cert_file: "/etc/letsencrypt/live/ldap.tesst.tessst/fullchain.pem", key_file: "/etc/letsencrypt/live/ldap.tesst.tessst/privkey.pem", }, http_url: "https://ldap.tesst.tessst/", .. } WARNING: A key_seed was given, we will ignore the key_file and generate one from the seed! Set key_file to an empty string in the config to silence this message. 2025-12-10T15:56:17.919742795+00:00 INFO set_up_server [ 4.49ms | 2.29% / 100.00% ] 2025-12-10T15:56:17.919755546+00:00 INFO ┝━ i [info]: Starting LLDAP version 0.6.2 2025-12-10T15:56:17.920165038+00:00 DEBUG ┝━ get_schema_version [ 155µs | 3.44% ] 2025-12-10T15:56:17.920659092+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: Some(SchemaVersion(10)) 2025-12-10T15:56:17.921142505+00:00 DEBUG ┝━ list_groups [ 1.60ms | 35.63% ] filters: Some(DisplayName("lldap_admin")) 2025-12-10T15:56:17.922532045+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: [Group { id: 1, display_name: "lldap_admin", creation_date: 2025-03-14T01:02:31.476783054, uuid: "###UUID###", users: ["lldap"], attributes: [] }] 2025-12-10T15:56:17.922556666+00:00 DEBUG ┝━ list_groups [ 534µs | 11.88% ] filters: Some(DisplayName("lldap_password_manager")) 2025-12-10T15:56:17.923176240+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: [Group { id: 2, display_name: "lldap_password_manager", creation_date: 2025-03-14T01:02:31.494843627, uuid: "###UUID###", users: [], attributes: [] }] 2025-12-10T15:56:17.923195340+00:00 DEBUG ┝━ list_groups [ 615µs | 13.68% ] filters: Some(DisplayName("lldap_strict_readonly")) 2025-12-10T15:56:17.923814334+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: [Group { id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", users: ["radicale", ###OTHERS###], attributes: [] }] 2025-12-10T15:56:17.925087684+00:00 INFO ┝━ i [info]: Starting the LDAP server on port 389 2025-12-10T15:56:17.925293655+00:00 INFO ┝━ i [info]: Starting the LDAPS server on port 636 2025-12-10T15:56:17.923838615+00:00 DEBUG ┝━ list_users [ 1.38ms | 30.71% ] filters: Some(MemberOf("lldap_admin")) | _get_groups: false 2025-12-10T15:56:17.924956423+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: [UserAndGroups { user: User { user_id: "lldap", email: "ldap@tesst.tessst", display_name: Some("Administrator"), creation_date: 2025-03-14T01:02:31.537663854, uuid: "###UUID###", attributes: [] }, groups: Some([GroupDetails { group_id: 1, display_name: "lldap_admin", creation_date: 2025-03-14T01:02:31.476783054, uuid: "###UUID###", attributes: [] }]) }] 2025-12-10T15:56:17.925322435+00:00 DEBUG ┝━ get_jwt_blacklist [ 106µs | 2.36% ] 2025-12-10T15:56:17.925456826+00:00 INFO ┕━ i [info]: Starting the API/web server on port 17170 2025-12-10T15:56:17.925567707+00:00 INFO i [info]: starting 1 workers 2025-12-10T15:56:17.925654078+00:00 INFO i [info]: Actix runtime found; starting in Actix runtime 2025-12-10T15:56:17.925710348+00:00 INFO i [info]: starting service: "ldap", workers: 1, listening on: 0.0.0.0:389 2025-12-10T15:56:17.925717508+00:00 INFO i [info]: starting service: "ldaps", workers: 1, listening on: 0.0.0.0:636 2025-12-10T15:56:17.925763958+00:00 INFO i [info]: starting service: "http", workers: 1, listening on: 0.0.0.0:17170 2025-12-10T15:56:17.926630395+00:00 INFO i [info]: DB Cleanup Cron started 2025-12-10T15:56:23.957882765+00:00 DEBUG 🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382 2025-12-10T15:56:23.999908367+00:00 INFO i [info]: LDAP session start: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b 2025-12-10T15:56:24.000019667+00:00 INFO LDAP request [ 84.0ms | 0.00% / 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b 2025-12-10T15:56:24.000034028+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] } 2025-12-10T15:56:24.000036378+00:00 DEBUG ┝━ do_bind [ 84.0ms | 0.00% / 100.00% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst 2025-12-10T15:56:24.000048248+00:00 DEBUG │ ┝━ bind [ 83.5ms | 0.00% / 99.35% ] 2025-12-10T15:56:24.000062278+00:00 DEBUG │ │ ┝━ get_password_file_for_user [ 241µs | 0.29% ] user_id: "radicale" 2025-12-10T15:56:24.000273659+00:00 INFO │ │ ┝━ i [info]: Login attempt for "radicale" 2025-12-10T15:56:24.000275139+00:00 DEBUG │ │ ┕━ passwords_match [ 83.2ms | 99.07% ] username: radicale 2025-12-10T15:56:24.083516702+00:00 DEBUG │ ┝━ get_user_groups [ 544µs | 0.65% ] user_id: "radicale" 2025-12-10T15:56:24.083960795+00:00 DEBUG │ │ ┕━ 🐛 [debug]: | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }} 2025-12-10T15:56:24.083972185+00:00 DEBUG │ ┕━ 🐛 [debug]: Success! 2025-12-10T15:56:24.083978475+00:00 DEBUG ┕━ 🐛 [debug]: | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None }) 2025-12-10T15:56:24.119227217+00:00 INFO LDAP request [ 1.54ms | 0.00% / 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b 2025-12-10T15:56:24.119233247+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Present("cn"), attrs: [] }), ctrl: [] } 2025-12-10T15:56:24.120568507+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120612567+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120630417+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120645557+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120672777+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120692808+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", attributes: [LdapPartialAttribute { atype: "cn", vals: ["Radicale Reader"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2025-03-14T01:05:27.516894904+00:00"] }, LdapPartialAttribute { atype: "entryuuid", vals: [###UUID###] }, LdapPartialAttribute { atype: "mail", vals: ["radicale@tesst.tessst"] }, LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "uid", vals: ["radicale"] }] }) 2025-12-10T15:56:24.120729218+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(LdapSearchResultEntry { dn: "uid=testall,ou=people,dc=tesst,dc=tessst", attributes: [LdapPartialAttribute { atype: "cn", vals: ["Testall"] }, LdapPartialAttribute { atype: "createtimestamp", vals: ["2025-12-10T03:07:27.833947890+00:00"] }, LdapPartialAttribute { atype: "entryuuid", vals: ["###UUID###"] }, LdapPartialAttribute { atype: "first_name", vals: ["Test"] }, LdapPartialAttribute { atype: "givenname", vals: ["Test"] }, LdapPartialAttribute { atype: "last_name", vals: ["All"] }, LdapPartialAttribute { atype: "mail", vals: ["mail.test.all@tesst.tessst"] }, LdapPartialAttribute { atype: "objectclass", vals: ["inetOrgPerson", "posixAccount", "mailAccount", "person"] }, LdapPartialAttribute { atype: "sn", vals: ["All"] }, LdapPartialAttribute { atype: "uid", vals: ["testall"] }] }) 2025-12-10T15:56:24.120747558+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120768968+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120787998+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120821768+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultEntry(###Removed Entry for privacy###) 2025-12-10T15:56:24.120834849+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) 2025-12-10T15:56:24.119238537+00:00 DEBUG ┕━ do_search [ 1.54ms | 0.00% / 100.00% ] 2025-12-10T15:56:24.119239617+00:00 DEBUG ┕━ do_search [ 1.54ms | 0.00% / 100.00% ] 2025-12-10T15:56:24.119431209+00:00 DEBUG ┝━ 🐛 [debug]: | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users 2025-12-10T15:56:24.120489516+00:00 DEBUG ┝━ expand_attribute_wildcards [ 7.32µs | 0.48% ] ldap_attributes: [] 2025-12-10T15:56:24.120497056+00:00 DEBUG │ ┕━ 🐛 [debug]: | attributes_out: {AttributeName(CaseInsensitiveString("cn")): "cn", AttributeName(CaseInsensitiveString("createtimestamp")): "createtimestamp", AttributeName(CaseInsensitiveString("entryuuid")): "entryuuid", AttributeName(CaseInsensitiveString("givenname")): "givenname", AttributeName(CaseInsensitiveString("jpegphoto")): "jpegPhoto", AttributeName(CaseInsensitiveString("mail")): "mail", AttributeName(CaseInsensitiveString("objectclass")): "objectclass", AttributeName(CaseInsensitiveString("sn")): "sn", AttributeName(CaseInsensitiveString("uid")): "uid"} 2025-12-10T15:56:24.119432929+00:00 DEBUG ┕━ get_user_list [ 1.53ms | 0.00% / 99.52% ] 2025-12-10T15:56:24.119435429+00:00 DEBUG ┝━ 🐛 [debug]: | filters: True 2025-12-10T15:56:24.119438019+00:00 DEBUG ┕━ list_users [ 1.53ms | 99.52% ] filters: Some(True) | _get_groups: false 2025-12-10T15:56:24.120484876+00:00 DEBUG ┕━ 🐛 [debug]: | return: [UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups { user: User { user_id: "radicale", email: "radicale@tesst.tessst", display_name: Some("Radicale Reader"), creation_date: 2025-03-14T01:05:27.516894904, uuid: "###UUID###", attributes: [] }, groups: Some([GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }]) }, UserAndGroups { user: User { user_id: "testall", email: "mail.test.all@tesst.tessst", display_name: Some("Testall"), creation_date: 2025-12-10T03:07:27.833947890, uuid: "###UUID###", attributes: [Attribute { name: AttributeName(CaseInsensitiveString("first_name")), value: String(Singleton("Test")) }, Attribute { name: AttributeName(CaseInsensitiveString("last_name")), value: String(Singleton("All")) }] }, groups: Some([GroupDetails { group_id: 4, display_name: "radicale", creation_date: 2025-03-14T16:41:41.519585857, uuid: "###UUID###", attributes: [] }]) }, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}, UserAndGroups {(###Removed Entry for privacy###}] 2025-12-10T15:56:24.189227396+00:00 INFO LDAP request [ 5.37µs | 100.00% ] session_id: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b 2025-12-10T15:56:24.189230676+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] } 2025-12-10T15:56:24.189232826+00:00 DEBUG ┕━ 🐛 [debug]: Unbind request for radicale 2025-12-10T15:56:24.189247546+00:00 INFO i [info]: LDAP session end: b1bded9b-b4eb-4aaa-9f7e-6a65cb2e607b 2025-12-10T15:56:27.414554450+00:00 DEBUG 🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382 2025-12-10T15:56:27.455970245+00:00 INFO i [info]: LDAP session start: ca61895c-b599-4754-845b-30e8fbb7e82f 2025-12-10T15:56:27.455987215+00:00 INFO LDAP request [ 85.9ms | 0.06% / 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f 2025-12-10T15:56:27.455994195+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] } 2025-12-10T15:56:27.455996055+00:00 DEBUG ┝━ do_bind [ 85.9ms | 0.00% / 99.94% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst 2025-12-10T15:56:27.456002305+00:00 DEBUG │ ┝━ bind [ 85.6ms | 0.09% / 99.64% ] 2025-12-10T15:56:27.456005155+00:00 DEBUG │ │ ┝━ get_password_file_for_user [ 112µs | 0.13% ] user_id: "radicale" 2025-12-10T15:56:27.456187927+00:00 INFO │ │ ┝━ i [info]: Login attempt for "radicale" 2025-12-10T15:56:27.456189797+00:00 DEBUG │ │ ┕━ passwords_match [ 85.4ms | 99.42% ] username: radicale 2025-12-10T15:56:27.541645986+00:00 DEBUG │ ┝━ get_user_groups [ 252µs | 0.29% ] user_id: "radicale" 2025-12-10T15:56:27.541913778+00:00 DEBUG │ │ ┕━ 🐛 [debug]: | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }} 2025-12-10T15:56:27.541919128+00:00 DEBUG │ ┕━ 🐛 [debug]: Success! 2025-12-10T15:56:27.541926988+00:00 DEBUG ┕━ 🐛 [debug]: | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None }) 2025-12-10T15:56:27.575749189+00:00 INFO LDAP request [ 791µs | 6.13% / 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f 2025-12-10T15:56:27.575755149+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("cn", "Testall"), attrs: [] }), ctrl: [] } 2025-12-10T15:56:27.576694266+00:00 DEBUG ┝━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) 2025-12-10T15:56:27.575756819+00:00 DEBUG ┕━ do_search [ 743µs | 5.25% / 93.87% ] 2025-12-10T15:56:27.575757989+00:00 DEBUG ┕━ do_search [ 701µs | 0.00% / 88.62% ] 2025-12-10T15:56:27.575970870+00:00 DEBUG ┝━ 🐛 [debug]: | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users 2025-12-10T15:56:27.575972280+00:00 DEBUG ┕━ get_user_list [ 701µs | 0.00% / 88.62% ] 2025-12-10T15:56:27.575975810+00:00 DEBUG ┝━ 🐛 [debug]: | filters: Equality(DisplayName, "testall") 2025-12-10T15:56:27.575979211+00:00 DEBUG ┕━ list_users [ 701µs | 88.62% ] filters: Some(Equality(DisplayName, "testall")) | _get_groups: false 2025-12-10T15:56:27.576685546+00:00 DEBUG ┕━ 🐛 [debug]: | return: [] 2025-12-10T15:56:27.609787942+00:00 INFO LDAP request [ 5.31µs | 100.00% ] session_id: ca61895c-b599-4754-845b-30e8fbb7e82f 2025-12-10T15:56:27.609791542+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] } 2025-12-10T15:56:27.609793392+00:00 DEBUG ┕━ 🐛 [debug]: Unbind request for radicale 2025-12-10T15:56:27.609827312+00:00 INFO i [info]: LDAP session end: ca61895c-b599-4754-845b-30e8fbb7e82f 2025-12-10T15:56:37.206152474+00:00 DEBUG 🐛 [debug]: decided upon suite TLS13_AES_256_GCM_SHA384 | log.target: "rustls::server::hs" | log.module_path: "rustls::server::hs" | log.file: "/__w/lldap/lldap/${GITHUB_WORKSPACE}/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.20.9/src/server/hs.rs" | log.line: 382 2025-12-10T15:56:37.245469484+00:00 INFO i [info]: LDAP session start: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6 2025-12-10T15:56:37.245494294+00:00 INFO LDAP request [ 83.2ms | 0.07% / 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6 2025-12-10T15:56:37.245503144+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 1, op: BindRequest(LdapBindRequest { dn: "uid=radicale,ou=people,dc=tesst,dc=tessst", cred: LdapBindCred::Simple }), ctrl: [] } 2025-12-10T15:56:37.245505735+00:00 DEBUG ┝━ do_bind [ 83.2ms | 0.00% / 99.93% ] dn: uid=radicale,ou=people,dc=tesst,dc=tessst 2025-12-10T15:56:37.245515485+00:00 DEBUG │ ┝━ bind [ 82.9ms | 0.12% / 99.58% ] 2025-12-10T15:56:37.245518765+00:00 DEBUG │ │ ┝━ get_password_file_for_user [ 122µs | 0.15% ] user_id: "radicale" 2025-12-10T15:56:37.245737616+00:00 INFO │ │ ┝━ i [info]: Login attempt for "radicale" 2025-12-10T15:56:37.245739316+00:00 DEBUG │ │ ┕━ passwords_match [ 82.7ms | 99.30% ] username: radicale 2025-12-10T15:56:37.328407376+00:00 DEBUG │ ┝━ get_user_groups [ 298µs | 0.36% ] user_id: "radicale" 2025-12-10T15:56:37.328727528+00:00 DEBUG │ │ ┕━ 🐛 [debug]: | return: {GroupDetails { group_id: 3, display_name: "lldap_strict_readonly", creation_date: 2025-03-14T01:02:31.518861775, uuid: "###UUID###", attributes: [] }} 2025-12-10T15:56:37.328732948+00:00 DEBUG │ ┕━ 🐛 [debug]: Success! 2025-12-10T15:56:37.328738898+00:00 DEBUG ┕━ 🐛 [debug]: | response: BindResponse(LdapBindResponse { res: LdapResult { code: Success, matcheddn: "", message: "", referral: [] }, saslcreds: None }) 2025-12-10T15:56:37.360503825+00:00 INFO LDAP request [ 751µs | 0.00% / 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6 2025-12-10T15:56:37.360510845+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 2, op: SearchRequest(LdapSearchRequest { base: "ou=people,dc=tesst,dc=tessst", scope: Subtree, aliases: Never, sizelimit: 0, timelimit: 0, typesonly: false, filter: Equality("cn", "testall"), attrs: [] }), ctrl: [] } 2025-12-10T15:56:37.360512135+00:00 DEBUG ┝━ do_search [ 751µs | 0.00% / 100.00% ] 2025-12-10T15:56:37.360513245+00:00 DEBUG │ ┕━ do_search [ 751µs | 35.79% / 100.00% ] 2025-12-10T15:56:37.360707786+00:00 DEBUG │ ┝━ 🐛 [debug]: | request.base: "ou=people,dc=tesst,dc=tessst" | scope: Users 2025-12-10T15:56:37.360709296+00:00 DEBUG │ ┕━ get_user_list [ 482µs | 8.89% / 64.21% ] 2025-12-10T15:56:37.360712996+00:00 DEBUG │ ┝━ 🐛 [debug]: | filters: Equality(DisplayName, "testall") 2025-12-10T15:56:37.360716456+00:00 DEBUG │ ┕━ list_users [ 415µs | 55.32% ] filters: Some(Equality(DisplayName, "testall")) | _get_groups: false 2025-12-10T15:56:37.361241790+00:00 DEBUG │ ┕━ 🐛 [debug]: | return: [] 2025-12-10T15:56:37.361252570+00:00 DEBUG ┕━ 🐛 [debug]: | response: SearchResultDone(LdapResult { code: Success, matcheddn: "", message: "", referral: [] }) 2025-12-10T15:56:37.392477582+00:00 INFO LDAP request [ 5.35µs | 100.00% ] session_id: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6 2025-12-10T15:56:37.392480942+00:00 DEBUG ┝━ 🐛 [debug]: | msg: LdapMsg { msgid: 3, op: UnbindRequest, ctrl: [] } 2025-12-10T15:56:37.392482832+00:00 DEBUG ┕━ 🐛 [debug]: Unbind request for radicale 2025-12-10T15:56:37.392496813+00:00 INFO i [info]: LDAP session end: 84cdf69a-b926-4cf3-ac26-ba6b3afc6bc6 ^C2025-12-10T15:56:52.508526477+00:00 INFO i [info]: SIGINT received; starting forced shutdown 2025-12-10T15:56:52.508620708+00:00 INFO i [info]: shutting down idle worker 2025-12-10T15:56:52.508934310+00:00 DEBUG 🐛 [debug]: paused accepting connections on 0.0.0.0:389 2025-12-10T15:56:52.508945930+00:00 DEBUG 🐛 [debug]: paused accepting connections on 0.0.0.0:636 2025-12-10T15:56:52.508954590+00:00 DEBUG 🐛 [debug]: paused accepting connections on 0.0.0.0:17170 2025-12-10T15:56:52.508958990+00:00 INFO i [info]: accept thread stopped 2025-12-10T15:56:52.810990622+00:00 INFO i [info]: DB Cleanup stopped ```
Author
Owner

@nitnelave commented on GitHub (Dec 10, 2025):

Oh, sorry, I misunderstood. You're saying that if the filter has an uppercase name, it doesn't match a user with the same casing? Then that's definitely a bug.

<!-- gh-comment-id:3639413048 --> @nitnelave commented on GitHub (Dec 10, 2025): Oh, sorry, I misunderstood. You're saying that if the filter has an uppercase name, it doesn't match a user with the same casing? Then that's definitely a bug.
Author
Owner

@nitnelave commented on GitHub (Dec 10, 2025):

Let's see if Copilot can give a meaningful fix.

<!-- gh-comment-id:3639414357 --> @nitnelave commented on GitHub (Dec 10, 2025): Let's see if Copilot can give a meaningful fix.
Author
Owner

@nitnelave commented on GitHub (Dec 11, 2025):

Sorry, coming back to this issue with a slightly different angle: "cn" (common name) is the display name on LLDAP, are you sure you want to use that to identify users? There are no restrictions on it, including multiple users sharing a display name, or a user taking an admin's display name.

The filter should be done on "uid", not "cn".

It's a separate issue that cn matching doesn't respect the casing well, but that's common with all the "user-defined" attributes (which cn is represented as, even though it's hardcoded). Fixing that would require a bigger architectural change (which would fix other issues around user defined attributes, like date or integer inequalities).

<!-- gh-comment-id:3639502656 --> @nitnelave commented on GitHub (Dec 11, 2025): Sorry, coming back to this issue with a slightly different angle: "cn" (common name) is the display name on LLDAP, are you sure you want to use that to identify users? There are no restrictions on it, including multiple users sharing a display name, or a user taking an admin's display name. The filter should be done on "uid", not "cn". It's a separate issue that cn matching doesn't respect the casing well, but that's common with all the "user-defined" attributes (which cn is represented as, even though it's hardcoded). Fixing that would require a bigger architectural change (which would fix other issues around user defined attributes, like date or integer inequalities).
Author
Owner

@LageTs commented on GitHub (Dec 16, 2025):

I've thought a bit about your comment and read through radicale's documentation again and found something interesting which I will share for documentation reasons:

Since version 3.4.0 there is the new config option ldap_user_attribute = cn with which you can filter by uid and then use the cn as display name. Alternatively one could force lower case user names with lc_username = True

Nevertheless I hope that the unexpected behavior will be fixed in next version.

Thanks for your help!

<!-- gh-comment-id:3658451482 --> @LageTs commented on GitHub (Dec 16, 2025): I've thought a bit about your comment and read through radicale's documentation again and found something interesting which I will share for documentation reasons: Since version 3.4.0 there is the new config option [`ldap_user_attribute = cn`](https://radicale.org/v3.html#ldap_user_attribute) with which you can filter by uid and then use the cn as display name. Alternatively one could force lower case user names with `lc_username = True` Nevertheless I hope that the unexpected behavior will be fixed in next version. Thanks for your help!
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#474
No description provided.