Skip to content

Commit 498933b

Browse files
committed
support AD style objectSid search
1 parent bfdbd78 commit 498933b

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Simple diffinition of AD domain user
2+
3+
# Root DSE.
4+
dn:
5+
namingContexts: dc=example_domain_name
6+
subschemaSubentry: cn=schema
7+
8+
# Schema definition
9+
dn: cn=schema
10+
objectClass: top
11+
objectClass: subschema
12+
# 'activeDirectoryObjectSidMatch' is a custom logic which allows filtering by (objectSid=S-1-...).
13+
# Such filtering is AD only feature so we should specify that objectSid can be found by either (objectSid=S-1-...) or (objectSid=\00\01\AB...).
14+
# Custom objectClass 'myUser' make it possible to attach 'activeDirectoryObjectSidMatch' to entry.
15+
attributeTypes: ( 1.2.3.4.5.6.7.8 NAME 'objectSid' DESC 'objectSid' EQUALITY activeDirectoryObjectSidMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 )
16+
objectClasses: ( 1.2.3.4.5.6.7.9 NAME 'myUser' SUP top STRUCTURAL MUST ( cn ) MAY ( objectSid ) )
17+
18+
# Example domain
19+
dn: dc=example_domain_name
20+
objectClass: top
21+
objectClass: domain
22+
dc: example_domain_name
23+
24+
# Example user
25+
dn: uid=example_user_name,dc=example_domain_name
26+
objectClass: myUser
27+
objectClass: user
28+
cn: example_user_name
29+
30+
# SID in binary form (Base64 encoded).
31+
# S-1-5-21-1234567890-1234567890-1234567890-1001
32+
objectSid:: AQUAAAAAAAUVAAAA0gKWSdIClknSApZJ6QMAAA==

providers/directory/search.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,12 @@ func (p *parser) equal(name, value string) (predicate, error) {
373373
s = strings.ReplaceAll(v, "-", "")
374374
return v == s
375375
}
376+
case "activeDirectoryObjectSidMatch", "0.0.0.0":
377+
v, _ := sidToBytes(value)
378+
f = func(s string) bool {
379+
b := []byte(s)
380+
return bytes.Equal(b, v) || value == s
381+
}
376382
default:
377383
return nil, fmt.Errorf("unsupported equality type: %v", t)
378384
}
@@ -536,3 +542,46 @@ func levenshtein(a, b string) int {
536542
// Return the final Levenshtein distance
537543
return matrix[len(a)][len(b)]
538544
}
545+
546+
// Converts sddl Sid to []byte
547+
func sidToBytes(sid string) ([]byte, error) {
548+
sid = strings.ReplaceAll(sid, "S-", "")
549+
parts := strings.Split(sid, "-")
550+
551+
if len(parts) < 3 {
552+
return nil, fmt.Errorf("invalid sid string format %v", sid)
553+
}
554+
555+
var result []byte
556+
557+
// Revision
558+
rev, revErr := strconv.ParseUint(parts[0], 10, 32)
559+
if revErr != nil {
560+
return nil, fmt.Errorf("invalid uint value %v at position: %v", parts[0], 0)
561+
}
562+
result = append(result, byte(rev))
563+
564+
// SubAuthorityCount
565+
result = append(result, byte(len(parts)-2))
566+
567+
// IdentifierAuthority
568+
for range 5 {
569+
result = append(result, 0)
570+
}
571+
authId, authIdErr := strconv.ParseUint(parts[1], 10, 32)
572+
if authIdErr != nil {
573+
return nil, fmt.Errorf("invalid uint value %v at position: %v", parts[1], 1)
574+
}
575+
result = append(result, byte(authId))
576+
for i, part := range parts[2:] {
577+
val, valErr := strconv.ParseUint(part, 10, 32)
578+
if valErr != nil {
579+
return nil, fmt.Errorf("invalid uint value %v at position: %v", part, i)
580+
}
581+
b := make([]byte, 4)
582+
binary.LittleEndian.PutUint32(b, uint32(val))
583+
result = append(result, b...)
584+
}
585+
586+
return result, nil
587+
}

0 commit comments

Comments
 (0)