feat: add posixAccount and posixGroup filter logic for more versatile usage in LDAP (#4014)

This commit is contained in:
Xiao Mao
2025-07-29 21:49:39 +08:00
committed by GitHub
parent 0ac69bde53
commit f3af2a26aa
3 changed files with 77 additions and 0 deletions

View File

@@ -19,6 +19,7 @@ import (
"fmt"
"hash/fnv"
"log"
"strings"
"github.com/casdoor/casdoor/conf"
"github.com/casdoor/casdoor/object"
@@ -158,6 +159,38 @@ func handleSearch(w ldap.ResponseWriter, m *ldap.Message) {
default:
}
var isGroupSearch bool = false
filter := r.Filter()
if eq, ok := filter.(message.FilterEqualityMatch); ok && strings.EqualFold(string(eq.AttributeDesc()), "objectClass") && strings.EqualFold(string(eq.AssertionValue()), "posixGroup") {
isGroupSearch = true
}
if isGroupSearch {
groups, code := GetFilteredGroups(m, string(r.BaseObject()), r.FilterString())
if code != ldap.LDAPResultSuccess {
res.SetResultCode(code)
w.Write(res)
return
}
for _, group := range groups {
dn := fmt.Sprintf("cn=%s,%s", group.Name, string(r.BaseObject()))
e := ldap.NewSearchResultEntry(dn)
e.AddAttribute("cn", message.AttributeValue(group.Name))
gidNumberStr := fmt.Sprintf("%v", hash(group.Name))
e.AddAttribute("gidNumber", message.AttributeValue(gidNumberStr))
users := object.GetGroupUsersWithoutError(group.GetId())
for _, user := range users {
e.AddAttribute("memberUid", message.AttributeValue(user.Name))
}
e.AddAttribute("objectClass", "posixGroup")
w.Write(e)
}
w.Write(res)
return
}
users, code := GetFilteredUsers(m)
if code != ldap.LDAPResultSuccess {
res.SetResultCode(code)

View File

@@ -184,6 +184,10 @@ func buildUserFilterCondition(filter interface{}) (builder.Cond, error) {
case message.FilterEqualityMatch:
attr := string(f.AttributeDesc())
if strings.EqualFold(attr, "objectclass") && strings.EqualFold(string(f.AssertionValue()), "posixAccount") {
return builder.Expr("1 = 1"), nil
}
if attr == ldapMemberOfAttr {
var names []string
groupId := string(f.AssertionValue())
@@ -324,6 +328,36 @@ func GetFilteredUsers(m *ldap.Message) (filteredUsers []*object.User, code int)
}
}
func GetFilteredGroups(m *ldap.Message, baseDN string, filterStr string) ([]*object.Group, int) {
name, org, code := getNameAndOrgFromFilter(baseDN, filterStr)
if code != ldap.LDAPResultSuccess {
return nil, code
}
var groups []*object.Group
var err error
if name == "*" {
if m.Client.IsGlobalAdmin && org == "*" {
groups, err = object.GetGlobalGroups()
if err != nil {
panic(err)
}
} else if m.Client.IsGlobalAdmin || org == m.Client.OrgName {
groups, err = object.GetGroups(org)
if err != nil {
panic(err)
}
} else {
return nil, ldap.LDAPResultInsufficientAccessRights
}
} else {
return nil, ldap.LDAPResultNoSuchObject
}
return groups, ldap.LDAPResultSuccess
}
// get user password with hash type prefix
// TODO not handle salt yet
// @return {md5}5f4dcc3b5aa765d61d8327deb882cf99