1 package ldap
2
3 import (
4 "context"
5 "errors"
6 "fmt"
7 "reflect"
8 "sort"
9 "strconv"
10 "strings"
11 "time"
12
13 ber "github.com/go-asn1-ber/asn1-ber"
14 )
15
16
17 const (
18 ScopeBaseObject = 0
19 ScopeSingleLevel = 1
20 ScopeWholeSubtree = 2
21 )
22
23
24 var ScopeMap = map[int]string{
25 ScopeBaseObject: "Base Object",
26 ScopeSingleLevel: "Single Level",
27 ScopeWholeSubtree: "Whole Subtree",
28 }
29
30
31 const (
32 NeverDerefAliases = 0
33 DerefInSearching = 1
34 DerefFindingBaseObj = 2
35 DerefAlways = 3
36 )
37
38
39 var DerefMap = map[int]string{
40 NeverDerefAliases: "NeverDerefAliases",
41 DerefInSearching: "DerefInSearching",
42 DerefFindingBaseObj: "DerefFindingBaseObj",
43 DerefAlways: "DerefAlways",
44 }
45
46
47
48
49 func NewEntry(dn string, attributes map[string][]string) *Entry {
50 var attributeNames []string
51 for attributeName := range attributes {
52 attributeNames = append(attributeNames, attributeName)
53 }
54 sort.Strings(attributeNames)
55
56 var encodedAttributes []*EntryAttribute
57 for _, attributeName := range attributeNames {
58 encodedAttributes = append(encodedAttributes, NewEntryAttribute(attributeName, attributes[attributeName]))
59 }
60 return &Entry{
61 DN: dn,
62 Attributes: encodedAttributes,
63 }
64 }
65
66
67 type Entry struct {
68
69 DN string
70
71 Attributes []*EntryAttribute
72 }
73
74
75 func (e *Entry) GetAttributeValues(attribute string) []string {
76 for _, attr := range e.Attributes {
77 if attr.Name == attribute {
78 return attr.Values
79 }
80 }
81 return []string{}
82 }
83
84
85
86 func (e *Entry) GetEqualFoldAttributeValues(attribute string) []string {
87 for _, attr := range e.Attributes {
88 if strings.EqualFold(attribute, attr.Name) {
89 return attr.Values
90 }
91 }
92 return []string{}
93 }
94
95
96 func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
97 for _, attr := range e.Attributes {
98 if attr.Name == attribute {
99 return attr.ByteValues
100 }
101 }
102 return [][]byte{}
103 }
104
105
106 func (e *Entry) GetEqualFoldRawAttributeValues(attribute string) [][]byte {
107 for _, attr := range e.Attributes {
108 if strings.EqualFold(attr.Name, attribute) {
109 return attr.ByteValues
110 }
111 }
112 return [][]byte{}
113 }
114
115
116 func (e *Entry) GetAttributeValue(attribute string) string {
117 values := e.GetAttributeValues(attribute)
118 if len(values) == 0 {
119 return ""
120 }
121 return values[0]
122 }
123
124
125
126 func (e *Entry) GetEqualFoldAttributeValue(attribute string) string {
127 values := e.GetEqualFoldAttributeValues(attribute)
128 if len(values) == 0 {
129 return ""
130 }
131 return values[0]
132 }
133
134
135 func (e *Entry) GetRawAttributeValue(attribute string) []byte {
136 values := e.GetRawAttributeValues(attribute)
137 if len(values) == 0 {
138 return []byte{}
139 }
140 return values[0]
141 }
142
143
144 func (e *Entry) GetEqualFoldRawAttributeValue(attribute string) []byte {
145 values := e.GetEqualFoldRawAttributeValues(attribute)
146 if len(values) == 0 {
147 return []byte{}
148 }
149 return values[0]
150 }
151
152
153 func (e *Entry) Print() {
154 fmt.Printf("DN: %s\n", e.DN)
155 for _, attr := range e.Attributes {
156 attr.Print()
157 }
158 }
159
160
161 func (e *Entry) PrettyPrint(indent int) {
162 fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
163 for _, attr := range e.Attributes {
164 attr.PrettyPrint(indent + 2)
165 }
166 }
167
168
169 const decoderTagName = "ldap"
170
171
172
173
174 func readTag(f reflect.StructField) (string, bool) {
175 val, ok := f.Tag.Lookup(decoderTagName)
176 if !ok {
177 return f.Name, false
178 }
179 opts := strings.Split(val, ",")
180 omit := false
181 if len(opts) == 2 {
182 omit = opts[1] == "omitempty"
183 }
184 return opts[0], omit
185 }
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240 func (e *Entry) Unmarshal(i interface{}) (err error) {
241
242 if vo := reflect.ValueOf(i).Kind(); vo != reflect.Ptr {
243 return fmt.Errorf("ldap: cannot use %s, expected pointer to a struct", vo)
244 }
245
246 sv, st := reflect.ValueOf(i).Elem(), reflect.TypeOf(i).Elem()
247
248 if sv.Kind() != reflect.Struct {
249 return fmt.Errorf("ldap: expected pointer to a struct, got %s", sv.Kind())
250 }
251
252 for n := 0; n < st.NumField(); n++ {
253
254 fv, ft := sv.Field(n), st.Field(n)
255
256
257 if ft.PkgPath != "" {
258 continue
259 }
260
261
262 fieldTag, _ := readTag(ft)
263
264
265 if fieldTag == "dn" {
266 fv.SetString(e.DN)
267 continue
268 }
269
270 values := e.GetAttributeValues(fieldTag)
271 if len(values) == 0 {
272 continue
273 }
274
275 switch fv.Interface().(type) {
276 case []string:
277 for _, item := range values {
278 fv.Set(reflect.Append(fv, reflect.ValueOf(item)))
279 }
280 case string:
281 fv.SetString(values[0])
282 case []byte:
283 fv.SetBytes([]byte(values[0]))
284 case int, int64:
285 intVal, err := strconv.ParseInt(values[0], 10, 64)
286 if err != nil {
287 return fmt.Errorf("ldap: could not parse value '%s' into int field", values[0])
288 }
289 fv.SetInt(intVal)
290 case time.Time:
291 t, err := ber.ParseGeneralizedTime([]byte(values[0]))
292 if err != nil {
293 return fmt.Errorf("ldap: could not parse value '%s' into time.Time field", values[0])
294 }
295 fv.Set(reflect.ValueOf(t))
296 case *DN:
297 dn, err := ParseDN(values[0])
298 if err != nil {
299 return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", values[0])
300 }
301 fv.Set(reflect.ValueOf(dn))
302 case []*DN:
303 for _, item := range values {
304 dn, err := ParseDN(item)
305 if err != nil {
306 return fmt.Errorf("ldap: could not parse value '%s' into *ldap.DN field", item)
307 }
308 fv.Set(reflect.Append(fv, reflect.ValueOf(dn)))
309 }
310 default:
311 return fmt.Errorf("ldap: expected field to be of type string, []string, int, int64, []byte, *DN, []*DN or time.Time, got %v", ft.Type)
312 }
313 }
314 return
315 }
316
317
318 func NewEntryAttribute(name string, values []string) *EntryAttribute {
319 var bytes [][]byte
320 for _, value := range values {
321 bytes = append(bytes, []byte(value))
322 }
323 return &EntryAttribute{
324 Name: name,
325 Values: values,
326 ByteValues: bytes,
327 }
328 }
329
330
331 type EntryAttribute struct {
332
333 Name string
334
335 Values []string
336
337 ByteValues [][]byte
338 }
339
340
341 func (e *EntryAttribute) Print() {
342 fmt.Printf("%s: %s\n", e.Name, e.Values)
343 }
344
345
346 func (e *EntryAttribute) PrettyPrint(indent int) {
347 fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
348 }
349
350
351 type SearchResult struct {
352
353 Entries []*Entry
354
355 Referrals []string
356
357 Controls []Control
358 }
359
360
361 func (s *SearchResult) Print() {
362 for _, entry := range s.Entries {
363 entry.Print()
364 }
365 }
366
367
368 func (s *SearchResult) PrettyPrint(indent int) {
369 for _, entry := range s.Entries {
370 entry.PrettyPrint(indent)
371 }
372 }
373
374
375 func (s *SearchResult) appendTo(r *SearchResult) {
376 r.Entries = append(r.Entries, s.Entries...)
377 r.Referrals = append(r.Referrals, s.Referrals...)
378 r.Controls = append(r.Controls, s.Controls...)
379 }
380
381
382 type SearchSingleResult struct {
383
384 Entry *Entry
385
386 Referral string
387
388 Controls []Control
389
390 Error error
391 }
392
393
394 func (s *SearchSingleResult) Print() {
395 s.Entry.Print()
396 }
397
398
399 func (s *SearchSingleResult) PrettyPrint(indent int) {
400 s.Entry.PrettyPrint(indent)
401 }
402
403
404 type SearchRequest struct {
405 BaseDN string
406 Scope int
407 DerefAliases int
408 SizeLimit int
409 TimeLimit int
410 TypesOnly bool
411 Filter string
412 Attributes []string
413 Controls []Control
414 }
415
416 func (req *SearchRequest) appendTo(envelope *ber.Packet) error {
417 pkt := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
418 pkt.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, req.BaseDN, "Base DN"))
419 pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(req.Scope), "Scope"))
420 pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(req.DerefAliases), "Deref Aliases"))
421 pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(req.SizeLimit), "Size Limit"))
422 pkt.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(req.TimeLimit), "Time Limit"))
423 pkt.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, req.TypesOnly, "Types Only"))
424
425 filterPacket, err := CompileFilter(req.Filter)
426 if err != nil {
427 return err
428 }
429 pkt.AppendChild(filterPacket)
430
431 attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
432 for _, attribute := range req.Attributes {
433 attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
434 }
435 pkt.AppendChild(attributesPacket)
436
437 envelope.AppendChild(pkt)
438 if len(req.Controls) > 0 {
439 envelope.AppendChild(encodeControls(req.Controls))
440 }
441
442 return nil
443 }
444
445
446 func NewSearchRequest(
447 BaseDN string,
448 Scope, DerefAliases, SizeLimit, TimeLimit int,
449 TypesOnly bool,
450 Filter string,
451 Attributes []string,
452 Controls []Control,
453 ) *SearchRequest {
454 return &SearchRequest{
455 BaseDN: BaseDN,
456 Scope: Scope,
457 DerefAliases: DerefAliases,
458 SizeLimit: SizeLimit,
459 TimeLimit: TimeLimit,
460 TypesOnly: TypesOnly,
461 Filter: Filter,
462 Attributes: Attributes,
463 Controls: Controls,
464 }
465 }
466
467
468
469
470
471
472
473
474
475
476 func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
477 var pagingControl *ControlPaging
478
479 control := FindControl(searchRequest.Controls, ControlTypePaging)
480 if control == nil {
481 pagingControl = NewControlPaging(pagingSize)
482 searchRequest.Controls = append(searchRequest.Controls, pagingControl)
483 } else {
484 castControl, ok := control.(*ControlPaging)
485 if !ok {
486 return nil, fmt.Errorf("expected paging control to be of type *ControlPaging, got %v", control)
487 }
488 if castControl.PagingSize != pagingSize {
489 return nil, fmt.Errorf("paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
490 }
491 pagingControl = castControl
492 }
493
494 searchResult := new(SearchResult)
495 for {
496 result, err := l.Search(searchRequest)
497 if result != nil {
498 result.appendTo(searchResult)
499 } else {
500 if err == nil {
501
502
503 return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
504 }
505 }
506 if err != nil {
507
508 return searchResult, err
509 }
510
511 l.Debug.Printf("Looking for Paging Control...")
512 pagingResult := FindControl(result.Controls, ControlTypePaging)
513 if pagingResult == nil {
514 pagingControl = nil
515 l.Debug.Printf("Could not find paging control. Breaking...")
516 break
517 }
518
519 cookie := pagingResult.(*ControlPaging).Cookie
520 if len(cookie) == 0 {
521 pagingControl = nil
522 l.Debug.Printf("Could not find cookie. Breaking...")
523 break
524 }
525 pagingControl.SetCookie(cookie)
526 }
527
528 if pagingControl != nil {
529 l.Debug.Printf("Abandoning Paging...")
530 pagingControl.PagingSize = 0
531 if _, err := l.Search(searchRequest); err != nil {
532 return searchResult, err
533 }
534 }
535
536 return searchResult, nil
537 }
538
539
540 func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
541 msgCtx, err := l.doRequest(searchRequest)
542 if err != nil {
543 return nil, err
544 }
545 defer l.finishMessage(msgCtx)
546
547 result := &SearchResult{
548 Entries: make([]*Entry, 0),
549 Referrals: make([]string, 0),
550 Controls: make([]Control, 0),
551 }
552
553 for {
554 packet, err := l.readPacket(msgCtx)
555 if err != nil {
556 return result, err
557 }
558
559 switch packet.Children[1].Tag {
560 case 4:
561 entry := &Entry{
562 DN: packet.Children[1].Children[0].Value.(string),
563 Attributes: unpackAttributes(packet.Children[1].Children[1].Children),
564 }
565 result.Entries = append(result.Entries, entry)
566 case 5:
567 err := GetLDAPError(packet)
568 if err != nil {
569 return result, err
570 }
571 if len(packet.Children) == 3 {
572 for _, child := range packet.Children[2].Children {
573 decodedChild, err := DecodeControl(child)
574 if err != nil {
575 return result, fmt.Errorf("failed to decode child control: %s", err)
576 }
577 result.Controls = append(result.Controls, decodedChild)
578 }
579 }
580 return result, nil
581 case 19:
582 result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
583 }
584 }
585 }
586
587
588
589
590
591 func (l *Conn) SearchAsync(
592 ctx context.Context, searchRequest *SearchRequest, bufferSize int) Response {
593 r := newSearchResponse(l, bufferSize)
594 r.start(ctx, searchRequest)
595 return r
596 }
597
598
599
600
601
602 func (l *Conn) Syncrepl(
603 ctx context.Context, searchRequest *SearchRequest, bufferSize int,
604 mode ControlSyncRequestMode, cookie []byte, reloadHint bool,
605 ) Response {
606 control := NewControlSyncRequest(mode, cookie, reloadHint)
607 searchRequest.Controls = append(searchRequest.Controls, control)
608 r := newSearchResponse(l, bufferSize)
609 r.start(ctx, searchRequest)
610 return r
611 }
612
613
614
615 func unpackAttributes(children []*ber.Packet) []*EntryAttribute {
616 entries := make([]*EntryAttribute, len(children))
617 for i, child := range children {
618 length := len(child.Children[1].Children)
619 entry := &EntryAttribute{
620 Name: child.Children[0].Value.(string),
621
622
623 Values: make([]string, length),
624 ByteValues: make([][]byte, length),
625 }
626
627 for i, value := range child.Children[1].Children {
628 entry.ByteValues[i] = value.ByteValue
629 entry.Values[i] = value.Value.(string)
630 }
631 entries[i] = entry
632 }
633
634 return entries
635 }
636
637
638 func (l *Conn) DirSync(
639 searchRequest *SearchRequest, flags int64, maxAttrCount int64, cookie []byte,
640 ) (*SearchResult, error) {
641 control := FindControl(searchRequest.Controls, ControlTypeDirSync)
642 if control == nil {
643 c := NewRequestControlDirSync(flags, maxAttrCount, cookie)
644 searchRequest.Controls = append(searchRequest.Controls, c)
645 } else {
646 c := control.(*ControlDirSync)
647 if c.Flags != flags {
648 return nil, fmt.Errorf("flags given in search request (%d) conflicts with flags given in search call (%d)", c.Flags, flags)
649 }
650 if c.MaxAttrCount != maxAttrCount {
651 return nil, fmt.Errorf("MaxAttrCnt given in search request (%d) conflicts with maxAttrCount given in search call (%d)", c.MaxAttrCount, maxAttrCount)
652 }
653 }
654 searchResult, err := l.Search(searchRequest)
655 l.Debug.Printf("Looking for result...")
656 if err != nil {
657 return nil, err
658 }
659 if searchResult == nil {
660 return nil, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
661 }
662
663 l.Debug.Printf("Looking for DirSync Control...")
664 resultControl := FindControl(searchResult.Controls, ControlTypeDirSync)
665 if resultControl == nil {
666 l.Debug.Printf("Could not find dirSyncControl control. Breaking...")
667 return searchResult, nil
668 }
669
670 cookie = resultControl.(*ControlDirSync).Cookie
671 if len(cookie) == 0 {
672 l.Debug.Printf("Could not find cookie. Breaking...")
673 return searchResult, nil
674 }
675
676 return searchResult, nil
677 }
678
679
680
681 func (l *Conn) DirSyncAsync(
682 ctx context.Context, searchRequest *SearchRequest, bufferSize int,
683 flags, maxAttrCount int64, cookie []byte,
684 ) Response {
685 control := NewRequestControlDirSync(flags, maxAttrCount, cookie)
686 searchRequest.Controls = append(searchRequest.Controls, control)
687 r := newSearchResponse(l, bufferSize)
688 r.start(ctx, searchRequest)
689 return r
690 }
691
View as plain text