@@ -22,6 +22,48 @@ import (
2222
2323type predicate func (entry Entry ) bool
2424
25+ func guidFromBytes (b []byte ) string {
26+ return fmt .Sprintf ("%08x-%04x-%04x-%02x%02x-%x" ,
27+ binary .LittleEndian .Uint32 (b [0 :4 ]),
28+ binary .LittleEndian .Uint16 (b [4 :6 ]),
29+ binary .LittleEndian .Uint16 (b [6 :8 ]),
30+ b [8 ], b [9 ],
31+ b [10 :16 ],
32+ )
33+ }
34+
35+ func updateBaseDnForGuidIfNeeded (msg * ldap.SearchRequest , e * Entry ) {
36+ binGuid , ok := e .Attributes ["objectGUID" ]
37+ if ! ok || len (binGuid ) == 0 {
38+ return
39+ }
40+ msgGuid := msg .BaseDN [6 : len (msg .BaseDN )- 1 ]
41+ if guidFromBytes ([]byte (binGuid [0 ])) != msgGuid {
42+ return
43+ }
44+ log .Infof ("Attributes: %+v" , guidFromBytes ([]byte (e .Attributes ["objectGUID" ][0 ])))
45+ msg .BaseDN = e .Dn
46+ }
47+
48+ var matchingRules = map [string ]string {
49+ "1.3.6.1.4.1.1466.115.121.1.38" : "objectIdentifierMatch" ,
50+ "1.3.6.1.4.1.1466.115.121.1.15" : "caseIgnoreMatch" ,
51+ "1.3.6.1.4.1.1466.115.121.1.26" : "caseExactMatch" ,
52+ "1.3.6.1.4.1.1466.115.121.1.7" : "booleanMatch" ,
53+ "1.3.6.1.4.1.1466.115.121.1.27" : "integerMatch" ,
54+ "1.3.6.1.4.1.1466.115.121.1.12" : "distinguishedNameMatch" ,
55+ "1.3.6.1.4.1.1466.115.121.1.24" : "generalizedTimeMatch" ,
56+ "1.3.6.1.4.1.1466.115.121.1.5" : "octetStringMatch" ,
57+ }
58+
59+ func inferMatchingRule (syntaxOID string ) string {
60+ if v , ok := matchingRules [syntaxOID ]; ok {
61+ return v
62+ }
63+ return "caseExactMatch"
64+ }
65+
66+
2567func (d * Directory ) serveSearch (rw ldap.ResponseWriter , r * ldap.Request ) {
2668 msg := r .Message .(* ldap.SearchRequest )
2769 m , doMonitor := monitor .LdapFromContext (r .Context )
@@ -69,6 +111,10 @@ func (d *Directory) serveSearch(rw ldap.ResponseWriter, r *ldap.Request) {
69111
70112 switch msg .Scope {
71113 case ldap .ScopeBaseObject :
114+ // handle Active Directory extended DN (see MS-ADTS for details)
115+ if strings .HasPrefix (msg .BaseDN , "<GUID=" ) {
116+ updateBaseDnForGuidIfNeeded (msg , & e )
117+ }
72118 if e .Dn != msg .BaseDN {
73119 continue
74120 }
@@ -80,6 +126,10 @@ func (d *Directory) serveSearch(rw ldap.ResponseWriter, r *ldap.Request) {
80126 if dn := strings .Join (parts [1 :], "," ); dn != msg .BaseDN {
81127 continue
82128 }
129+ case ldap .ScopeWholeSubtree :
130+ if ! strings .HasSuffix (strings .ToLower (e .Dn ), strings .ToLower (msg .BaseDN )) {
131+ continue
132+ }
83133 }
84134 if d .skip (& e , msg .BaseDN ) {
85135 continue
@@ -343,6 +393,9 @@ func (p *parser) equal(name, value string) (predicate, error) {
343393 if p .s != nil {
344394 t , ok := p .s .AttributeTypes [name ]
345395 if ok {
396+ if t .Equality == "" {
397+ t .Equality = inferMatchingRule (t .Syntax )
398+ }
346399 switch t .Equality {
347400 case "caseIgnoreMatch" , "2.5.13.2" :
348401 f = func (s string ) bool {
0 commit comments