diff --git a/internal/service/ldap_service.go b/internal/service/ldap_service.go index b64c1df..d88d180 100644 --- a/internal/service/ldap_service.go +++ b/internal/service/ldap_service.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "fmt" + "slices" "sync" "time" @@ -145,6 +146,36 @@ func (ldap *LdapService) Search(username string) (string, error) { return userDN, nil } +func (ldap *LdapService) GetUserGroups(username string) ([]string, error) { + searchRequest := ldapgo.NewSearchRequest( + ldap.config.BaseDN, + ldapgo.ScopeWholeSubtree, ldapgo.NeverDerefAliases, 0, 0, false, + "(objectclass=groupOfUniqueNames)", + []string{"uniquemember"}, + nil, + ) + + ldap.mutex.Lock() + defer ldap.mutex.Unlock() + + searchResult, err := ldap.conn.Search(searchRequest) + if err != nil { + return []string{}, err + } + + groups := []string{} + + for _, entry := range searchResult.Entries { + memberAttributes := entry.GetAttributeValues("uniquemember") + // no need to escape username here, if it's malicious it won't match anything + if slices.Contains(memberAttributes, fmt.Sprintf(ldap.config.SearchFilter, username)) { + groups = append(groups, entry.DN) + } + } + + return groups, nil +} + func (ldap *LdapService) BindService(rebind bool) error { // Locks must not be used for initial binding attempt if rebind {