...
1 package ldap
2
3 import (
4 "errors"
5
6 ber "github.com/go-asn1-ber/asn1-ber"
7 )
8
9 var (
10 errRespChanClosed = errors.New("ldap: response channel closed")
11 errCouldNotRetMsg = errors.New("ldap: could not retrieve message")
12
13 ErrNilConnection = errors.New("ldap: conn is nil, expected net.Conn")
14 )
15
16 type request interface {
17 appendTo(*ber.Packet) error
18 }
19
20 type requestFunc func(*ber.Packet) error
21
22 func (f requestFunc) appendTo(p *ber.Packet) error {
23 return f(p)
24 }
25
26 func (l *Conn) doRequest(req request) (*messageContext, error) {
27 if l == nil || l.conn == nil {
28 return nil, ErrNilConnection
29 }
30
31 packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
32 packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
33 if err := req.appendTo(packet); err != nil {
34 return nil, err
35 }
36
37 if l.Debug {
38 l.Debug.PrintPacket(packet)
39 }
40
41 msgCtx, err := l.sendMessage(packet)
42 if err != nil {
43 return nil, err
44 }
45 l.Debug.Printf("%d: returning", msgCtx.id)
46 return msgCtx, nil
47 }
48
49 func (l *Conn) readPacket(msgCtx *messageContext) (*ber.Packet, error) {
50 l.Debug.Printf("%d: waiting for response", msgCtx.id)
51 packetResponse, ok := <-msgCtx.responses
52 if !ok {
53 return nil, NewError(ErrorNetwork, errRespChanClosed)
54 }
55 packet, err := packetResponse.ReadPacket()
56 l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
57 if err != nil {
58 return nil, err
59 }
60
61 if packet == nil {
62 return nil, NewError(ErrorNetwork, errCouldNotRetMsg)
63 }
64
65 if l.Debug {
66 if err = addLDAPDescriptions(packet); err != nil {
67 return nil, err
68 }
69 l.Debug.PrintPacket(packet)
70 }
71 return packet, nil
72 }
73
74 func getReferral(err error, packet *ber.Packet) (referral string) {
75 if !IsErrorWithCode(err, LDAPResultReferral) {
76 return ""
77 }
78
79 if len(packet.Children) < 2 {
80 return ""
81 }
82
83
84
85
86
87
88
89
90 if len(packet.Children[1].Children) == 0 || (packet.Children[1].TagType != ber.TypeConstructed || packet.Children[1].ClassType != ber.ClassApplication) {
91 return ""
92 }
93
94 var ok bool
95
96 for _, child := range packet.Children[1].Children {
97
98
99
100 if (child.Tag != ber.TagBitString && child.Tag != ber.TagPrintableString) || child.TagType != ber.TypeConstructed || child.ClassType != ber.ClassContext {
101 continue
102 }
103
104 if referral, ok = child.Children[0].Value.(string); ok {
105 return referral
106 }
107 }
108
109 return ""
110 }
111
View as plain text