Skip to content

bug(ldap): getUserAttributeFilter maps "uid" to UIDNumber (numeric) instead of Username (string) #615

@botox0711

Description

@botox0711

Bug Report

Component: pkg/utils/ldapgetUserAttributeFilter
Affected version: reva v2.43.0 (shipped with OpenCloud v6.1.0)
Priority: High — blocks user authentication with external read-only LDAP


Description

When OpenCloud performs a user lookup via GetUserByClaim with claim "uid",
the function getUserAttributeFilter incorrectly maps the logical attribute
"uid" to i.User.Schema.UIDNumber (a numeric POSIX attribute) instead of
i.User.Schema.Username (the string uid attribute).

This causes LDAP filters like (uidNumber=jdoe) to be generated instead of
the correct (uid=jdoe), resulting in failed user lookups for all users on
external LDAP setups using the standard inetOrgPerson/person schema.


Confirmed via trace log

DBG LDAP Search
  filter=(&(&(objectClass=person)(memberOf=cn=users,ou=groups,dc=example,dc=com))
          (objectclass=inetOrgPerson)(uidNumber=jdoe))
  line=pkg/utils/ldap/identity.go:265
  service=users

DBG GetUserByClaim
  error="error: not found:
         (&(&(objectClass=person)(memberOf=cn=users,ou=groups,dc=example,dc=com))
           (objectclass=inetOrgPerson)(uidNumber=jdoe))"
  line=pkg/user/manager/ldap/ldap.go:156
  service=users

The filter (uidNumber=jdoe) is clearly wrong — uidNumber is a numeric
POSIX attribute and jdoe is a string username. The correct filter must be
(uid=jdoe).


Root Cause

Bug 1 — Wrong attribute mapping in pkg/utils/ldap/ldap.go:

// BUGGY (~line 432)
func (i *Identity) getUserAttributeFilter(attribute, value, tenantID string) (string, error) {
    switch attribute {
    case "uid":
        attribute = i.User.Schema.UIDNumber  // ← WRONG: numeric POSIX attribute
    ...

Should be:

    case "uid":
        attribute = i.User.Schema.Username   // ← CORRECT: string uid attribute

Bug 2 — Wrong value escaping for non-UUID attributes, directly below the switch:

// This treats every attribute value as a UUID — wrong for mail, uid, username
value, err := filterEscapeAttribute(i.User.Schema.ID, i.User.Schema.IDIsOctetString, value)

UUID parsing should only apply for case "userid" when IDIsOctetString is
true. For all other cases plain ldap.EscapeFilter(value) is correct.


Configuration (external read-only LDAP)

OC_LDAP_URI=ldap://192.168.x.x:3890
OC_LDAP_SERVER_WRITE_ENABLED=false
OC_LDAP_USER_BASE_DN=ou=people,dc=example,dc=com
OC_LDAP_USER_OBJECTCLASS=person
OC_LDAP_USER_FILTER='(&(objectClass=person)(memberOf=cn=users,ou=groups,dc=example,dc=com))'
OC_LDAP_USER_SCHEMA_ID=entryuuid
OC_LDAP_DISABLE_USER_MECHANISM=none
# OC_LDAP_USER_SCHEMA_USERNAME not set → defaults to "uid" ✓

This is the standard setup described in the OpenCloud documentation for
connecting an external read-only LDAP server. The bug affects all deployments
using this recommended configuration.


Impact

  • User authentication fails completely for all users
  • No workaround available via environment variables
    (UIDNumber is not configurable via env)
  • Affects any external LDAP with inetOrgPerson/person schema
    where uidNumber is not populated

Missing Test Coverage

getUserAttributeFilter has no unit tests. The existing ldap_test.go only
covers getUserFindFilter. Suggested additions:

{"uid lookup",      "uid",     "jdoe",              "(&...(uid=jdoe)...)"},
{"mail lookup",     "mail",    "jdoe@example.com",  "(&...(mail=jdoe@example.com)...)"},
{"username lookup", "username","jdoe",               "(&...(uid=jdoe)...)"},
{"invalid field",   "invalid", "jdoe",               error},

These tests would have caught both bugs at introduction.


References

/cc @rhafer

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions