44 "errors"
55 "fmt"
66
7- "gopkg.in/asn1-ber.v1"
7+ ber "gopkg.in/asn1-ber.v1"
88)
99
1010// SimpleBindRequest represents a username/password bind operation
@@ -35,13 +35,18 @@ func NewSimpleBindRequest(username string, password string, controls []Control)
3535 }
3636}
3737
38- func (bindRequest * SimpleBindRequest ) encode () * ber.Packet {
39- request := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindRequest , nil , "Bind Request" )
40- request .AppendChild (ber .NewInteger (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , 3 , "Version" ))
41- request .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , bindRequest .Username , "User Name" ))
42- request .AppendChild (ber .NewString (ber .ClassContext , ber .TypePrimitive , 0 , bindRequest .Password , "Password" ))
38+ func (req * SimpleBindRequest ) appendTo ( envelope * ber.Packet ) error {
39+ pkt := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindRequest , nil , "Bind Request" )
40+ pkt .AppendChild (ber .NewInteger (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , 3 , "Version" ))
41+ pkt .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , req .Username , "User Name" ))
42+ pkt .AppendChild (ber .NewString (ber .ClassContext , ber .TypePrimitive , 0 , req .Password , "Password" ))
4343
44- return request
44+ envelope .AppendChild (pkt )
45+ if len (req .Controls ) > 0 {
46+ envelope .AppendChild (encodeControls (req .Controls ))
47+ }
48+
49+ return nil
4550}
4651
4752// SimpleBind performs the simple bind operation defined in the given request
@@ -50,41 +55,17 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
5055 return nil , NewError (ErrorEmptyPassword , errors .New ("ldap: empty password not allowed by the client" ))
5156 }
5257
53- packet := ber .Encode (ber .ClassUniversal , ber .TypeConstructed , ber .TagSequence , nil , "LDAP Request" )
54- packet .AppendChild (ber .NewInteger (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , l .nextMessageID (), "MessageID" ))
55- encodedBindRequest := simpleBindRequest .encode ()
56- packet .AppendChild (encodedBindRequest )
57- if len (simpleBindRequest .Controls ) > 0 {
58- packet .AppendChild (encodeControls (simpleBindRequest .Controls ))
59- }
60-
61- if l .Debug {
62- ber .PrintPacket (packet )
63- }
64-
65- msgCtx , err := l .sendMessage (packet )
58+ msgCtx , err := l .doRequest (simpleBindRequest )
6659 if err != nil {
6760 return nil , err
6861 }
6962 defer l .finishMessage (msgCtx )
7063
71- packetResponse , ok := <- msgCtx .responses
72- if ! ok {
73- return nil , NewError (ErrorNetwork , errors .New ("ldap: response channel closed" ))
74- }
75- packet , err = packetResponse .ReadPacket ()
76- l .Debug .Printf ("%d: got response %p" , msgCtx .id , packet )
64+ packet , err := l .readPacket (msgCtx )
7765 if err != nil {
7866 return nil , err
7967 }
8068
81- if l .Debug {
82- if err = addLDAPDescriptions (packet ); err != nil {
83- return nil , err
84- }
85- ber .PrintPacket (packet )
86- }
87-
8869 result := & SimpleBindResult {
8970 Controls : make ([]Control , 0 ),
9071 }
@@ -133,3 +114,39 @@ func (l *Conn) UnauthenticatedBind(username string) error {
133114 _ , err := l .SimpleBind (req )
134115 return err
135116}
117+
118+ var externalBindRequest = requestFunc (func (envelope * ber.Packet ) error {
119+ pkt := ber .Encode (ber .ClassApplication , ber .TypeConstructed , ApplicationBindRequest , nil , "Bind Request" )
120+ pkt .AppendChild (ber .NewInteger (ber .ClassUniversal , ber .TypePrimitive , ber .TagInteger , 3 , "Version" ))
121+ pkt .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "User Name" ))
122+
123+ saslAuth := ber .Encode (ber .ClassContext , ber .TypeConstructed , 3 , "" , "authentication" )
124+ saslAuth .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "EXTERNAL" , "SASL Mech" ))
125+ saslAuth .AppendChild (ber .NewString (ber .ClassUniversal , ber .TypePrimitive , ber .TagOctetString , "" , "SASL Cred" ))
126+
127+ pkt .AppendChild (saslAuth )
128+
129+ envelope .AppendChild (pkt )
130+
131+ return nil
132+ })
133+
134+ // ExternalBind performs SASL/EXTERNAL authentication.
135+ //
136+ // Use ldap.DialURL("ldapi://") to connect to the Unix socket before ExternalBind.
137+ //
138+ // See https://tools.ietf.org/html/rfc4422#appendix-A
139+ func (l * Conn ) ExternalBind () error {
140+ msgCtx , err := l .doRequest (externalBindRequest )
141+ if err != nil {
142+ return err
143+ }
144+ defer l .finishMessage (msgCtx )
145+
146+ packet , err := l .readPacket (msgCtx )
147+ if err != nil {
148+ return err
149+ }
150+
151+ return GetLDAPError (packet )
152+ }
0 commit comments