aboutsummaryrefslogtreecommitdiff
path: root/pkg/auth/ldap/ldap.go
diff options
context:
space:
mode:
authoraboron <aboron@users.noreply.github.com>2017-05-29 22:33:50 -0400
committer无闻 <u@gogs.io>2017-05-29 22:33:50 -0400
commitdbb7e5464b6a9cad430b2f36b52e7674211f51cf (patch)
tree8f201849432a65d3a58e04ef2c92b7eedfbf7a24 /pkg/auth/ldap/ldap.go
parent11ad64f6cbdc489a49247604fe697dffaa090ac2 (diff)
ldap: add check for group membership (#4398)
* Add standard LDAP group membership checking. * Fix formatting, typo, grammer, and syntax errors * Debugging done. Gave up on locale file edits.
Diffstat (limited to 'pkg/auth/ldap/ldap.go')
-rw-r--r--pkg/auth/ldap/ldap.go75
1 files changed, 72 insertions, 3 deletions
diff --git a/pkg/auth/ldap/ldap.go b/pkg/auth/ldap/ldap.go
index 78cd66a4..25fddeb7 100644
--- a/pkg/auth/ldap/ldap.go
+++ b/pkg/auth/ldap/ldap.go
@@ -42,6 +42,11 @@ type Source struct {
AttributesInBind bool // fetch attributes in bind context (not user)
Filter string // Query filter to validate entry
AdminFilter string // Query filter to check if user is admin
+ GroupsEnabled bool // if the group checking is enabled
+ GroupDN string // Group Search Base
+ GroupFilter string // Group Name Filter
+ GroupMemberUid string // Group Attribute containing array of UserUID
+ UserUID string // User Attribute listed in Group
Enabled bool // if this source is disabled
}
@@ -67,6 +72,28 @@ func (ls *Source) sanitizedUserDN(username string) (string, bool) {
return fmt.Sprintf(ls.UserDN, username), true
}
+func (ls *Source) sanitizedGroupFilter(group string) (string, bool) {
+ // See http://tools.ietf.org/search/rfc4515
+ badCharacters := "\x00*\\"
+ if strings.ContainsAny(group, badCharacters) {
+ log.Trace("Group filter invalid query characters: %s", group)
+ return "", false
+ }
+
+ return group, true
+}
+
+func (ls *Source) sanitizedGroupDN(groupDn string) (string, bool) {
+ // See http://tools.ietf.org/search/rfc4514: "special characters"
+ badCharacters := "\x00()*\\'\"#+;<>"
+ if strings.ContainsAny(groupDn, badCharacters) || strings.HasPrefix(groupDn, " ") || strings.HasSuffix(groupDn, " ") {
+ log.Trace("Group DN contains invalid query characters: %s", groupDn)
+ return "", false
+ }
+
+ return groupDn, true
+}
+
func (ls *Source) findUserDN(l *ldap.Conn, name string) (string, bool) {
log.Trace("Search for LDAP user: %s", name)
if ls.BindDN != "" && ls.BindPassword != "" {
@@ -194,15 +221,15 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
return "", "", "", "", false, false
}
- log.Trace("Fetching attributes '%v', '%v', '%v', '%v' with filter '%s' and base '%s'", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, userFilter, userDN)
+ log.Trace("Fetching attributes '%v', '%v', '%v', '%v', '%v' with filter '%s' and base '%s'", ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.UserUID, userFilter, userDN)
search := ldap.NewSearchRequest(
userDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, userFilter,
- []string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail},
+ []string{ls.AttributeUsername, ls.AttributeName, ls.AttributeSurname, ls.AttributeMail, ls.UserUID},
nil)
sr, err := l.Search(search)
if err != nil {
- log.Error(4, "LDAP search failed: %v", err)
+ log.Error(4, "LDAP user search failed: %v", err)
return "", "", "", "", false, false
} else if len(sr.Entries) < 1 {
if directBind {
@@ -218,6 +245,48 @@ func (ls *Source) SearchEntry(name, passwd string, directBind bool) (string, str
firstname := sr.Entries[0].GetAttributeValue(ls.AttributeName)
surname := sr.Entries[0].GetAttributeValue(ls.AttributeSurname)
mail := sr.Entries[0].GetAttributeValue(ls.AttributeMail)
+ uid := sr.Entries[0].GetAttributeValue(ls.UserUID)
+
+ // Check group membership
+ if ls.GroupsEnabled {
+ groupFilter, ok := ls.sanitizedGroupFilter(ls.GroupFilter)
+ if !ok {
+ return "", "", "", "", false, false
+ }
+ groupDN, ok := ls.sanitizedGroupDN(ls.GroupDN)
+ if !ok {
+ return "", "", "", "", false, false
+ }
+
+ log.Trace("Fetching groups '%v' with filter '%s' and base '%s'", ls.GroupMemberUid, groupFilter, groupDN)
+ groupSearch := ldap.NewSearchRequest(
+ groupDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, groupFilter,
+ []string{ls.GroupMemberUid},
+ nil)
+
+ srg, err := l.Search(groupSearch)
+ if err != nil {
+ log.Error(4, "LDAP group search failed: %v", err)
+ return "", "", "", "", false, false
+ } else if len(sr.Entries) < 1 {
+ log.Error(4, "LDAP group search failed: 0 entries")
+ return "", "", "", "", false, false
+ }
+
+ isMember := false
+ for _,group := range srg.Entries {
+ for _,member := range group.GetAttributeValues(ls.GroupMemberUid) {
+ if member == uid {
+ isMember = true
+ }
+ }
+ }
+
+ if !isMember {
+ log.Error(4, "LDAP group membership test failed")
+ return "", "", "", "", false, false
+ }
+ }
isAdmin := false
if len(ls.AdminFilter) > 0 {