@@ -196,22 +196,39 @@ func checkRestricted(l *ldap.Conn, ls *Source, userDN string) bool {
196196}
197197
198198// List all group memberships of a user
199- func (source * Source ) listLdapGroupMemberships (l * ldap.Conn , uid string ) []string {
199+ func (source * Source ) listLdapGroupMemberships (l * ldap.Conn , uid string , applyGroupFilter bool ) []string {
200200 var ldapGroups []string
201- groupFilter := fmt .Sprintf ("(%s=%s)" , source .GroupMemberUID , ldap .EscapeFilter (uid ))
201+ var searchFilter string
202+
203+ groupFilter , ok := source .sanitizedGroupFilter (source .GroupFilter )
204+ if ! ok {
205+ return ldapGroups
206+ }
207+
208+ groupDN , ok := source .sanitizedGroupDN (source .GroupDN )
209+ if ! ok {
210+ return ldapGroups
211+ }
212+
213+ if applyGroupFilter {
214+ searchFilter = fmt .Sprintf ("(&(%s)(%s=%s))" , groupFilter , source .GroupMemberUID , ldap .EscapeFilter (uid ))
215+ } else {
216+ searchFilter = fmt .Sprintf ("(%s=%s)" , source .GroupMemberUID , ldap .EscapeFilter (uid ))
217+ }
218+
202219 result , err := l .Search (ldap .NewSearchRequest (
203- source . GroupDN ,
220+ groupDN ,
204221 ldap .ScopeWholeSubtree ,
205222 ldap .NeverDerefAliases ,
206223 0 ,
207224 0 ,
208225 false ,
209- groupFilter ,
226+ searchFilter ,
210227 []string {},
211228 nil ,
212229 ))
213230 if err != nil {
214- log .Error ("Failed group search using filter[%s]: %v" , groupFilter , err )
231+ log .Error ("Failed group search in LDAP with filter [%s]: %v" , searchFilter , err )
215232 return ldapGroups
216233 }
217234
@@ -238,9 +255,7 @@ func (source *Source) mapLdapGroupsToTeams() map[string]map[string][]string {
238255}
239256
240257// getMappedMemberships : returns the organizations and teams to modify the users membership
241- func (source * Source ) getMappedMemberships (l * ldap.Conn , uid string ) (map [string ][]string , map [string ][]string ) {
242- // get all LDAP group memberships for user
243- usersLdapGroups := source .listLdapGroupMemberships (l , uid )
258+ func (source * Source ) getMappedMemberships (usersLdapGroups []string , uid string ) (map [string ][]string , map [string ][]string ) {
244259 // unmarshall LDAP group team map from configs
245260 ldapGroupsToTeams := source .mapLdapGroupsToTeams ()
246261 membershipsToAdd := map [string ][]string {}
@@ -260,6 +275,14 @@ func (source *Source) getMappedMemberships(l *ldap.Conn, uid string) (map[string
260275 return membershipsToAdd , membershipsToRemove
261276}
262277
278+ func (source * Source ) getUserAttributeListedInGroup (entry * ldap.Entry ) string {
279+ if strings .ToLower (source .UserUID ) == "dn" {
280+ return entry .DN
281+ }
282+
283+ return entry .GetAttributeValue (source .UserUID )
284+ }
285+
263286// SearchEntry : search an LDAP source if an entry (name, passwd) is valid and in the specific filter
264287func (source * Source ) SearchEntry (name , passwd string , directBind bool ) * SearchResult {
265288 // See https://tools.ietf.org/search/rfc4513#section-5.1.2
@@ -375,58 +398,30 @@ func (source *Source) SearchEntry(name, passwd string, directBind bool) *SearchR
375398 firstname := sr .Entries [0 ].GetAttributeValue (source .AttributeName )
376399 surname := sr .Entries [0 ].GetAttributeValue (source .AttributeSurname )
377400 mail := sr .Entries [0 ].GetAttributeValue (source .AttributeMail )
378- uid := sr .Entries [0 ].GetAttributeValue (source .UserUID )
379- if source .UserUID == "dn" || source .UserUID == "DN" {
380- uid = sr .Entries [0 ].DN
381- }
382401
383- // Check group membership
384- if source .GroupsEnabled && source .GroupFilter != "" {
385- groupFilter , ok := source .sanitizedGroupFilter (source .GroupFilter )
386- if ! ok {
387- return nil
388- }
389- groupDN , ok := source .sanitizedGroupDN (source .GroupDN )
390- if ! ok {
391- return nil
392- }
402+ teamsToAdd := make (map [string ][]string )
403+ teamsToRemove := make (map [string ][]string )
393404
394- log .Trace ("Fetching groups '%v' with filter '%s' and base '%s'" , source .GroupMemberUID , groupFilter , groupDN )
395- groupSearch := ldap .NewSearchRequest (
396- groupDN , ldap .ScopeWholeSubtree , ldap .NeverDerefAliases , 0 , 0 , false , groupFilter ,
397- []string {source .GroupMemberUID },
398- nil )
405+ // Check group membership
406+ if source .GroupsEnabled {
407+ userAttributeListedInGroup := source .getUserAttributeListedInGroup (sr .Entries [0 ])
408+ usersLdapGroups := source .listLdapGroupMemberships (l , userAttributeListedInGroup , true )
399409
400- srg , err := l .Search (groupSearch )
401- if err != nil {
402- log .Error ("LDAP group search failed: %v" , err )
403- return nil
404- } else if len (srg .Entries ) < 1 {
405- log .Error ("LDAP group search failed: 0 entries" )
410+ if source .GroupFilter != "" && len (usersLdapGroups ) == 0 {
406411 return nil
407412 }
408413
409- isMember := false
410- Entries:
411- for _ , group := range srg .Entries {
412- for _ , member := range group .GetAttributeValues (source .GroupMemberUID ) {
413- if (source .UserUID == "dn" && member == sr .Entries [0 ].DN ) || member == uid {
414- isMember = true
415- break Entries
416- }
417- }
418- }
419-
420- if ! isMember {
421- log .Error ("LDAP group membership test failed" )
422- return nil
414+ if source .GroupTeamMap != "" || source .GroupTeamMapRemoval {
415+ teamsToAdd , teamsToRemove = source .getMappedMemberships (usersLdapGroups , userAttributeListedInGroup )
423416 }
424417 }
425418
426419 if isAttributeSSHPublicKeySet {
427420 sshPublicKey = sr .Entries [0 ].GetAttributeValues (source .AttributeSSHPublicKey )
428421 }
422+
429423 isAdmin := checkAdmin (l , source , userDN )
424+
430425 var isRestricted bool
431426 if ! isAdmin {
432427 isRestricted = checkRestricted (l , source , userDN )
@@ -436,12 +431,6 @@ func (source *Source) SearchEntry(name, passwd string, directBind bool) *SearchR
436431 Avatar = sr .Entries [0 ].GetRawAttributeValue (source .AttributeAvatar )
437432 }
438433
439- teamsToAdd := make (map [string ][]string )
440- teamsToRemove := make (map [string ][]string )
441- if source .GroupsEnabled && (source .GroupTeamMap != "" || source .GroupTeamMapRemoval ) {
442- teamsToAdd , teamsToRemove = source .getMappedMemberships (l , uid )
443- }
444-
445434 if ! directBind && source .AttributesInBind {
446435 // binds user (checking password) after looking-up attributes in BindDN context
447436 err = bindUser (l , userDN , passwd )
@@ -520,19 +509,29 @@ func (source *Source) SearchEntries() ([]*SearchResult, error) {
520509 return nil , err
521510 }
522511
523- result := make ([]* SearchResult , len (sr .Entries ))
512+ result := make ([]* SearchResult , 0 , len (sr .Entries ))
524513
525- for i , v := range sr .Entries {
514+ for _ , v := range sr .Entries {
526515 teamsToAdd := make (map [string ][]string )
527516 teamsToRemove := make (map [string ][]string )
528- if source .GroupsEnabled && (source .GroupTeamMap != "" || source .GroupTeamMapRemoval ) {
529- userAttributeListedInGroup := v .GetAttributeValue (source .UserUID )
530- if source .UserUID == "dn" || source .UserUID == "DN" {
531- userAttributeListedInGroup = v .DN
517+
518+ if source .GroupsEnabled {
519+ userAttributeListedInGroup := source .getUserAttributeListedInGroup (v )
520+
521+ if source .GroupFilter != "" {
522+ usersLdapGroups := source .listLdapGroupMemberships (l , userAttributeListedInGroup , true )
523+ if len (usersLdapGroups ) == 0 {
524+ continue
525+ }
526+ }
527+
528+ if source .GroupTeamMap != "" || source .GroupTeamMapRemoval {
529+ usersLdapGroups := source .listLdapGroupMemberships (l , userAttributeListedInGroup , false )
530+ teamsToAdd , teamsToRemove = source .getMappedMemberships (usersLdapGroups , userAttributeListedInGroup )
532531 }
533- teamsToAdd , teamsToRemove = source .getMappedMemberships (l , userAttributeListedInGroup )
534532 }
535- result [i ] = & SearchResult {
533+
534+ user := & SearchResult {
536535 Username : v .GetAttributeValue (source .AttributeUsername ),
537536 Name : v .GetAttributeValue (source .AttributeName ),
538537 Surname : v .GetAttributeValue (source .AttributeSurname ),
@@ -541,16 +540,22 @@ func (source *Source) SearchEntries() ([]*SearchResult, error) {
541540 LdapTeamAdd : teamsToAdd ,
542541 LdapTeamRemove : teamsToRemove ,
543542 }
544- if ! result [i ].IsAdmin {
545- result [i ].IsRestricted = checkRestricted (l , source , v .DN )
543+
544+ if ! user .IsAdmin {
545+ user .IsRestricted = checkRestricted (l , source , v .DN )
546546 }
547+
547548 if isAttributeSSHPublicKeySet {
548- result [ i ] .SSHPublicKey = v .GetAttributeValues (source .AttributeSSHPublicKey )
549+ user .SSHPublicKey = v .GetAttributeValues (source .AttributeSSHPublicKey )
549550 }
551+
550552 if isAtributeAvatarSet {
551- result [ i ] .Avatar = v .GetRawAttributeValue (source .AttributeAvatar )
553+ user .Avatar = v .GetRawAttributeValue (source .AttributeAvatar )
552554 }
553- result [i ].LowerName = strings .ToLower (result [i ].Username )
555+
556+ user .LowerName = strings .ToLower (user .Username )
557+
558+ result = append (result , user )
554559 }
555560
556561 return result , nil
0 commit comments