summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/go-ldap
diff options
context:
space:
mode:
authorChristopher Speller <crspeller@gmail.com>2016-09-23 10:17:51 -0400
committerGitHub <noreply@github.com>2016-09-23 10:17:51 -0400
commit2ca0e8f9a0f9863555a26e984cde15efff9ef8f8 (patch)
treedaae1ee67b14a3d0a84424f2a304885d9e75ce2b /vendor/github.com/go-ldap
parent6d62d65b2dc85855aabea036cbd44f6059e19d13 (diff)
downloadchat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.tar.gz
chat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.tar.bz2
chat-2ca0e8f9a0f9863555a26e984cde15efff9ef8f8.zip
Updating golang dependancies (#4075)
Diffstat (limited to 'vendor/github.com/go-ldap')
-rwxr-xr-xvendor/github.com/go-ldap/ldap/.githooks/pre-push6
-rw-r--r--vendor/github.com/go-ldap/ldap/.travis.yml11
-rw-r--r--vendor/github.com/go-ldap/ldap/Makefile42
-rw-r--r--vendor/github.com/go-ldap/ldap/README.md28
-rw-r--r--vendor/github.com/go-ldap/ldap/add.go49
-rw-r--r--vendor/github.com/go-ldap/ldap/bind.go42
-rw-r--r--vendor/github.com/go-ldap/ldap/compare.go18
-rw-r--r--vendor/github.com/go-ldap/ldap/conn.go147
-rw-r--r--vendor/github.com/go-ldap/ldap/conn_test.go295
-rw-r--r--vendor/github.com/go-ldap/ldap/control.go132
-rw-r--r--vendor/github.com/go-ldap/ldap/control_test.go58
-rw-r--r--vendor/github.com/go-ldap/ldap/del.go27
-rw-r--r--vendor/github.com/go-ldap/ldap/dn.go21
-rw-r--r--vendor/github.com/go-ldap/ldap/error.go8
-rw-r--r--vendor/github.com/go-ldap/ldap/error_test.go77
-rw-r--r--vendor/github.com/go-ldap/ldap/filter.go72
-rw-r--r--vendor/github.com/go-ldap/ldap/ldap.go3
-rw-r--r--vendor/github.com/go-ldap/ldap/modify.go66
-rw-r--r--vendor/github.com/go-ldap/ldap/passwdmodify.go34
-rw-r--r--vendor/github.com/go-ldap/ldap/search.go58
20 files changed, 929 insertions, 265 deletions
diff --git a/vendor/github.com/go-ldap/ldap/.githooks/pre-push b/vendor/github.com/go-ldap/ldap/.githooks/pre-push
new file mode 100755
index 000000000..4325ee31c
--- /dev/null
+++ b/vendor/github.com/go-ldap/ldap/.githooks/pre-push
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+# install from the root of the repo with:
+# ln -s ../../.githooks/pre-push .git/hooks/pre-push
+
+make vet fmt lint \ No newline at end of file
diff --git a/vendor/github.com/go-ldap/ldap/.travis.yml b/vendor/github.com/go-ldap/ldap/.travis.yml
index a7a38951b..7e2f641e7 100644
--- a/vendor/github.com/go-ldap/ldap/.travis.yml
+++ b/vendor/github.com/go-ldap/ldap/.travis.yml
@@ -1,15 +1,24 @@
language: go
+env:
+ global:
+ - VET_VERSIONS="1.5 1.6 tip"
+ - LINT_VERSIONS="1.5 1.6 tip"
go:
- 1.2
- 1.3
- 1.4
- 1.5
+ - 1.6
- tip
go_import_path: gopkg.in/ldap.v2
install:
- go get gopkg.in/asn1-ber.v1
- go get gopkg.in/ldap.v2
- go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
+ - go get github.com/golang/lint/golint || true
- go build -v ./...
script:
- - go test -v -cover ./...
+ - make test
+ - make fmt
+ - if [[ "$VET_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make vet; fi
+ - if [[ "$LINT_VERSIONS" == *"$TRAVIS_GO_VERSION"* ]]; then make lint; fi
diff --git a/vendor/github.com/go-ldap/ldap/Makefile b/vendor/github.com/go-ldap/ldap/Makefile
new file mode 100644
index 000000000..c1fc96657
--- /dev/null
+++ b/vendor/github.com/go-ldap/ldap/Makefile
@@ -0,0 +1,42 @@
+.PHONY: default install build test quicktest fmt vet lint
+
+default: fmt vet lint build quicktest
+
+install:
+ go get -t -v ./...
+
+build:
+ go build -v ./...
+
+test:
+ go test -v -cover ./...
+
+quicktest:
+ go test ./...
+
+# Capture output and force failure when there is non-empty output
+fmt:
+ @echo gofmt -l .
+ @OUTPUT=`gofmt -l . 2>&1`; \
+ if [ "$$OUTPUT" ]; then \
+ echo "gofmt must be run on the following files:"; \
+ echo "$$OUTPUT"; \
+ exit 1; \
+ fi
+
+# Only run on go1.5+
+vet:
+ go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult .
+
+# https://github.com/golang/lint
+# go get github.com/golang/lint/golint
+# Capture output and force failure when there is non-empty output
+# Only run on go1.5+
+lint:
+ @echo golint ./...
+ @OUTPUT=`golint ./... 2>&1`; \
+ if [ "$$OUTPUT" ]; then \
+ echo "golint errors:"; \
+ echo "$$OUTPUT"; \
+ exit 1; \
+ fi
diff --git a/vendor/github.com/go-ldap/ldap/README.md b/vendor/github.com/go-ldap/ldap/README.md
index f49b4d6a1..a26ed2d82 100644
--- a/vendor/github.com/go-ldap/ldap/README.md
+++ b/vendor/github.com/go-ldap/ldap/README.md
@@ -13,41 +13,39 @@ Import the latest version with:
import "gopkg.in/ldap.v2"
-
## Required Libraries:
- gopkg.in/asn1-ber.v1
-## Working:
+## Features:
- - Connecting to LDAP server
+ - Connecting to LDAP server (non-TLS, TLS, STARTTLS)
- Binding to LDAP server
- Searching for entries
- - Compiling string filters to LDAP filters
+ - Filter Compile / Decompile
- Paging Search Results
- Modify Requests / Responses
- Add Requests / Responses
- Delete Requests / Responses
- - Better Unicode support
## Examples:
- search
- modify
-## Tests Implemented:
-
- - Filter Compile / Decompile
-
-## TODO:
+## Contributing:
- - [x] Add Requests / Responses
- - [x] Delete Requests / Responses
- - [x] Modify DN Requests / Responses
- - [ ] Compare Requests / Responses
- - [ ] Implement Tests / Benchmarks
+Bug reports and pull requests are welcome!
+Before submitting a pull request, please make sure tests and verification scripts pass:
+```
+make all
+```
+To set up a pre-push hook to run the tests and verify scripts before pushing:
+```
+ln -s ../../.githooks/pre-push .git/hooks/pre-push
+```
---
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
diff --git a/vendor/github.com/go-ldap/ldap/add.go b/vendor/github.com/go-ldap/ldap/add.go
index 61b795e0e..0e5f6cdba 100644
--- a/vendor/github.com/go-ldap/ldap/add.go
+++ b/vendor/github.com/go-ldap/ldap/add.go
@@ -16,73 +16,78 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// Attribute represents an LDAP attribute
type Attribute struct {
- attrType string
- attrVals []string
+ // Type is the name of the LDAP attribute
+ Type string
+ // Vals are the LDAP attribute values
+ Vals []string
}
func (a *Attribute) encode() *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
- seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.attrType, "Type"))
+ seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.Type, "Type"))
set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
- for _, value := range a.attrVals {
+ for _, value := range a.Vals {
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
}
seq.AppendChild(set)
return seq
}
+// AddRequest represents an LDAP AddRequest operation
type AddRequest struct {
- dn string
- attributes []Attribute
+ // DN identifies the entry being added
+ DN string
+ // Attributes list the attributes of the new entry
+ Attributes []Attribute
}
func (a AddRequest) encode() *ber.Packet {
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
- request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.dn, "DN"))
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.DN, "DN"))
attributes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
- for _, attribute := range a.attributes {
+ for _, attribute := range a.Attributes {
attributes.AppendChild(attribute.encode())
}
request.AppendChild(attributes)
return request
}
+// Attribute adds an attribute with the given type and values
func (a *AddRequest) Attribute(attrType string, attrVals []string) {
- a.attributes = append(a.attributes, Attribute{attrType: attrType, attrVals: attrVals})
+ a.Attributes = append(a.Attributes, Attribute{Type: attrType, Vals: attrVals})
}
+// NewAddRequest returns an AddRequest for the given DN, with no attributes
func NewAddRequest(dn string) *AddRequest {
return &AddRequest{
- dn: dn,
+ DN: dn,
}
}
+// Add performs the given AddRequest
func (l *Conn) Add(addRequest *AddRequest) error {
- messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(addRequest.encode())
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
- if channel == nil {
- return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
@@ -103,6 +108,6 @@ func (l *Conn) Add(addRequest *AddRequest) error {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
}
- l.Debug.Printf("%d: returning", messageID)
+ l.Debug.Printf("%d: returning", msgCtx.id)
return nil
}
diff --git a/vendor/github.com/go-ldap/ldap/bind.go b/vendor/github.com/go-ldap/ldap/bind.go
index ae68eb481..26b3cc727 100644
--- a/vendor/github.com/go-ldap/ldap/bind.go
+++ b/vendor/github.com/go-ldap/ldap/bind.go
@@ -10,16 +10,22 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// SimpleBindRequest represents a username/password bind operation
type SimpleBindRequest struct {
+ // Username is the name of the Directory object that the client wishes to bind as
Username string
+ // Password is the credentials to bind with
Password string
+ // Controls are optional controls to send with the bind request
Controls []Control
}
+// SimpleBindResult contains the response from the server
type SimpleBindResult struct {
Controls []Control
}
+// NewSimpleBindRequest returns a bind request
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
return &SimpleBindRequest{
Username: username,
@@ -39,11 +45,10 @@ func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
return request
}
+// SimpleBind performs the simple bind operation defined in the given request
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
- messageID := l.nextMessageID()
-
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
encodedBindRequest := simpleBindRequest.encode()
packet.AppendChild(encodedBindRequest)
@@ -51,21 +56,18 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
ber.PrintPacket(packet)
}
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return nil, err
}
- if channel == nil {
- return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- packetResponse, ok := <-channel
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return nil, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return nil, err
}
@@ -95,11 +97,10 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
return result, nil
}
+// Bind performs a bind with the given username and password
func (l *Conn) Bind(username, password string) error {
- messageID := l.nextMessageID()
-
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
@@ -110,21 +111,18 @@ func (l *Conn) Bind(username, password string) error {
ber.PrintPacket(packet)
}
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
- if channel == nil {
- return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- packetResponse, ok := <-channel
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
diff --git a/vendor/github.com/go-ldap/ldap/compare.go b/vendor/github.com/go-ldap/ldap/compare.go
index dfe728bad..cc6d2af5e 100644
--- a/vendor/github.com/go-ldap/ldap/compare.go
+++ b/vendor/github.com/go-ldap/ldap/compare.go
@@ -33,9 +33,8 @@ import (
// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
// false with any error that occurs if any.
func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
- messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, dn, "DN"))
@@ -48,22 +47,19 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return false, err
}
- if channel == nil {
- return false, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return false, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return false, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return false, err
}
diff --git a/vendor/github.com/go-ldap/ldap/conn.go b/vendor/github.com/go-ldap/ldap/conn.go
index 6aad628be..b5bd99adb 100644
--- a/vendor/github.com/go-ldap/ldap/conn.go
+++ b/vendor/github.com/go-ldap/ldap/conn.go
@@ -17,18 +17,27 @@ import (
)
const (
- MessageQuit = 0
- MessageRequest = 1
+ // MessageQuit causes the processMessages loop to exit
+ MessageQuit = 0
+ // MessageRequest sends a request to the server
+ MessageRequest = 1
+ // MessageResponse receives a response from the server
MessageResponse = 2
- MessageFinish = 3
- MessageTimeout = 4
+ // MessageFinish indicates the client considers a particular message ID to be finished
+ MessageFinish = 3
+ // MessageTimeout indicates the client-specified timeout for a particular message ID has been reached
+ MessageTimeout = 4
)
+// PacketResponse contains the packet or error encountered reading a response
type PacketResponse struct {
+ // Packet is the packet read from the server
Packet *ber.Packet
- Error error
+ // Error is an error encountered while reading
+ Error error
}
+// ReadPacket returns the packet or an error
func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) {
if (pr == nil) || (pr.Packet == nil && pr.Error == nil) {
return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
@@ -36,11 +45,31 @@ func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) {
return pr.Packet, pr.Error
}
+type messageContext struct {
+ id int64
+ // close(done) should only be called from finishMessage()
+ done chan struct{}
+ // close(responses) should only be called from processMessages(), and only sent to from sendResponse()
+ responses chan *PacketResponse
+}
+
+// sendResponse should only be called within the processMessages() loop which
+// is also responsible for closing the responses channel.
+func (msgCtx *messageContext) sendResponse(packet *PacketResponse) {
+ select {
+ case msgCtx.responses <- packet:
+ // Successfully sent packet to message handler.
+ case <-msgCtx.done:
+ // The request handler is done and will not receive more
+ // packets.
+ }
+}
+
type messagePacket struct {
Op int
MessageID int64
Packet *ber.Packet
- Channel chan *PacketResponse
+ Context *messageContext
}
type sendMessageFlags uint
@@ -54,10 +83,11 @@ type Conn struct {
conn net.Conn
isTLS bool
isClosing bool
+ closeErr error
isStartingTLS bool
Debug debugging
chanConfirm chan bool
- chanResults map[int64]chan *PacketResponse
+ messageContexts map[int64]*messageContext
chanMessage chan *messagePacket
chanMessageID chan int64
wgSender sync.WaitGroup
@@ -111,16 +141,17 @@ func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
// NewConn returns a new Conn using conn for network I/O.
func NewConn(conn net.Conn, isTLS bool) *Conn {
return &Conn{
- conn: conn,
- chanConfirm: make(chan bool),
- chanMessageID: make(chan int64),
- chanMessage: make(chan *messagePacket, 10),
- chanResults: map[int64]chan *PacketResponse{},
- requestTimeout: 0,
- isTLS: isTLS,
+ conn: conn,
+ chanConfirm: make(chan bool),
+ chanMessageID: make(chan int64),
+ chanMessage: make(chan *messagePacket, 10),
+ messageContexts: map[int64]*messageContext{},
+ requestTimeout: 0,
+ isTLS: isTLS,
}
}
+// Start initializes goroutines to read responses and process messages
func (l *Conn) Start() {
go l.reader()
go l.processMessages()
@@ -148,7 +179,7 @@ func (l *Conn) Close() {
l.wgClose.Wait()
}
-// Sets the time after a request is sent that a MessageTimeout triggers
+// SetTimeout sets the time after a request is sent that a MessageTimeout triggers
func (l *Conn) SetTimeout(timeout time.Duration) {
if timeout > 0 {
l.requestTimeout = timeout
@@ -167,35 +198,31 @@ func (l *Conn) nextMessageID() int64 {
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
func (l *Conn) StartTLS(config *tls.Config) error {
- messageID := l.nextMessageID()
-
if l.isTLS {
return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
}
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Start TLS")
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command"))
packet.AppendChild(request)
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessageWithFlags(packet, startTLS)
+ msgCtx, err := l.sendMessageWithFlags(packet, startTLS)
if err != nil {
return err
}
- if channel == nil {
- return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
+ defer l.finishMessage(msgCtx)
- l.Debug.Printf("%d: waiting for response", messageID)
- defer l.finishMessage(messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
@@ -226,11 +253,11 @@ func (l *Conn) StartTLS(config *tls.Config) error {
return nil
}
-func (l *Conn) sendMessage(packet *ber.Packet) (chan *PacketResponse, error) {
+func (l *Conn) sendMessage(packet *ber.Packet) (*messageContext, error) {
return l.sendMessageWithFlags(packet, 0)
}
-func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags) (chan *PacketResponse, error) {
+func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags) (*messageContext, error) {
if l.isClosing {
return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
}
@@ -238,32 +265,38 @@ func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags)
l.Debug.Printf("flags&startTLS = %d", flags&startTLS)
if l.isStartingTLS {
l.messageMutex.Unlock()
- return nil, NewError(ErrorNetwork, errors.New("ldap: connection is in startls phase."))
+ return nil, NewError(ErrorNetwork, errors.New("ldap: connection is in startls phase"))
}
if flags&startTLS != 0 {
if l.outstandingRequests != 0 {
l.messageMutex.Unlock()
return nil, NewError(ErrorNetwork, errors.New("ldap: cannot StartTLS with outstanding requests"))
- } else {
- l.isStartingTLS = true
}
+ l.isStartingTLS = true
}
l.outstandingRequests++
l.messageMutex.Unlock()
- out := make(chan *PacketResponse)
+ responses := make(chan *PacketResponse)
+ messageID := packet.Children[0].Value.(int64)
message := &messagePacket{
Op: MessageRequest,
- MessageID: packet.Children[0].Value.(int64),
+ MessageID: messageID,
Packet: packet,
- Channel: out,
+ Context: &messageContext{
+ id: messageID,
+ done: make(chan struct{}),
+ responses: responses,
+ },
}
l.sendProcessMessage(message)
- return out, nil
+ return message.Context, nil
}
-func (l *Conn) finishMessage(messageID int64) {
+func (l *Conn) finishMessage(msgCtx *messageContext) {
+ close(msgCtx.done)
+
if l.isClosing {
return
}
@@ -277,7 +310,7 @@ func (l *Conn) finishMessage(messageID int64) {
message := &messagePacket{
Op: MessageFinish,
- MessageID: messageID,
+ MessageID: msgCtx.id,
}
l.sendProcessMessage(message)
}
@@ -297,10 +330,15 @@ func (l *Conn) processMessages() {
if err := recover(); err != nil {
log.Printf("ldap: recovered panic in processMessages: %v", err)
}
- for messageID, channel := range l.chanResults {
+ for messageID, msgCtx := range l.messageContexts {
+ // If we are closing due to an error, inform anyone who
+ // is waiting about the error.
+ if l.isClosing && l.closeErr != nil {
+ msgCtx.sendResponse(&PacketResponse{Error: l.closeErr})
+ }
l.Debug.Printf("Closing channel for MessageID %d", messageID)
- close(channel)
- delete(l.chanResults, messageID)
+ close(msgCtx.responses)
+ delete(l.messageContexts, messageID)
}
close(l.chanMessageID)
l.chanConfirm <- true
@@ -324,15 +362,20 @@ func (l *Conn) processMessages() {
case MessageRequest:
// Add to message list and write to network
l.Debug.Printf("Sending message %d", message.MessageID)
- l.chanResults[message.MessageID] = message.Channel
buf := message.Packet.Bytes()
_, err := l.conn.Write(buf)
if err != nil {
l.Debug.Printf("Error Sending Message: %s", err.Error())
+ message.Context.sendResponse(&PacketResponse{Error: fmt.Errorf("unable to send request: %s", err)})
+ close(message.Context.responses)
break
}
+ // Only add to messageContexts if we were able to
+ // successfully write the message.
+ l.messageContexts[message.MessageID] = message.Context
+
// Add timeout if defined
if l.requestTimeout > 0 {
go func() {
@@ -351,8 +394,8 @@ func (l *Conn) processMessages() {
}
case MessageResponse:
l.Debug.Printf("Receiving message %d", message.MessageID)
- if chanResult, ok := l.chanResults[message.MessageID]; ok {
- chanResult <- &PacketResponse{message.Packet, nil}
+ if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
+ msgCtx.sendResponse(&PacketResponse{message.Packet, nil})
} else {
log.Printf("Received unexpected message %d, %v", message.MessageID, l.isClosing)
ber.PrintPacket(message.Packet)
@@ -360,17 +403,17 @@ func (l *Conn) processMessages() {
case MessageTimeout:
// Handle the timeout by closing the channel
// All reads will return immediately
- if chanResult, ok := l.chanResults[message.MessageID]; ok {
- chanResult <- &PacketResponse{message.Packet, errors.New("ldap: connection timed out")}
+ if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
l.Debug.Printf("Receiving message timeout for %d", message.MessageID)
- delete(l.chanResults, message.MessageID)
- close(chanResult)
+ msgCtx.sendResponse(&PacketResponse{message.Packet, errors.New("ldap: connection timed out")})
+ delete(l.messageContexts, message.MessageID)
+ close(msgCtx.responses)
}
case MessageFinish:
l.Debug.Printf("Finished message %d", message.MessageID)
- if chanResult, ok := l.chanResults[message.MessageID]; ok {
- close(chanResult)
- delete(l.chanResults, message.MessageID)
+ if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
+ delete(l.messageContexts, message.MessageID)
+ close(msgCtx.responses)
}
}
}
@@ -397,6 +440,7 @@ func (l *Conn) reader() {
if err != nil {
// A read error is expected here if we are closing the connection...
if !l.isClosing {
+ l.closeErr = fmt.Errorf("unable to read LDAP response packet: %s", err)
l.Debug.Printf("reader error: %s", err.Error())
}
return
@@ -419,6 +463,5 @@ func (l *Conn) reader() {
if !l.sendProcessMessage(message) {
return
}
-
}
}
diff --git a/vendor/github.com/go-ldap/ldap/conn_test.go b/vendor/github.com/go-ldap/ldap/conn_test.go
index 8394e5339..10766bbd4 100644
--- a/vendor/github.com/go-ldap/ldap/conn_test.go
+++ b/vendor/github.com/go-ldap/ldap/conn_test.go
@@ -1,9 +1,14 @@
package ldap
import (
+ "bytes"
+ "errors"
+ "io"
"net"
"net/http"
"net/http/httptest"
+ "runtime"
+ "sync"
"testing"
"time"
@@ -27,19 +32,20 @@ func TestUnresponsiveConnection(t *testing.T) {
defer conn.Close()
// Mock a packet
- messageID := conn.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, conn.nextMessageID(), "MessageID"))
bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
packet.AppendChild(bindRequest)
// Send packet and test response
- channel, err := conn.sendMessage(packet)
+ msgCtx, err := conn.sendMessage(packet)
if err != nil {
t.Fatalf("error sending message: %v", err)
}
- packetResponse, ok := <-channel
+ defer conn.finishMessage(msgCtx)
+
+ packetResponse, ok := <-msgCtx.responses
if !ok {
t.Fatalf("no PacketResponse in response channel")
}
@@ -51,3 +57,284 @@ func TestUnresponsiveConnection(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
}
+
+// TestFinishMessage tests that we do not enter deadlock when a goroutine makes
+// a request but does not handle all responses from the server.
+func TestConn(t *testing.T) {
+ ptc := newPacketTranslatorConn()
+ defer ptc.Close()
+
+ conn := NewConn(ptc, false)
+ conn.Start()
+
+ // Test sending 5 different requests in series. Ensure that we can
+ // get a response packet from the underlying connection and also
+ // ensure that we can gracefully ignore unhandled responses.
+ for i := 0; i < 5; i++ {
+ t.Logf("serial request %d", i)
+ // Create a message and make sure we can receive responses.
+ msgCtx := testSendRequest(t, ptc, conn)
+ testReceiveResponse(t, ptc, msgCtx)
+
+ // Send a few unhandled responses and finish the message.
+ testSendUnhandledResponsesAndFinish(t, ptc, conn, msgCtx, 5)
+ t.Logf("serial request %d done", i)
+ }
+
+ // Test sending 5 different requests in parallel.
+ var wg sync.WaitGroup
+ for i := 0; i < 5; i++ {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+ t.Logf("parallel request %d", i)
+ // Create a message and make sure we can receive responses.
+ msgCtx := testSendRequest(t, ptc, conn)
+ testReceiveResponse(t, ptc, msgCtx)
+
+ // Send a few unhandled responses and finish the message.
+ testSendUnhandledResponsesAndFinish(t, ptc, conn, msgCtx, 5)
+ t.Logf("parallel request %d done", i)
+ }(i)
+ }
+ wg.Wait()
+
+ // We cannot run Close() in a defer because t.FailNow() will run it and
+ // it will block if the processMessage Loop is in a deadlock.
+ conn.Close()
+}
+
+func testSendRequest(t *testing.T, ptc *packetTranslatorConn, conn *Conn) (msgCtx *messageContext) {
+ var msgID int64
+ runWithTimeout(t, time.Second, func() {
+ msgID = conn.nextMessageID()
+ })
+
+ requestPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ requestPacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, msgID, "MessageID"))
+
+ var err error
+
+ runWithTimeout(t, time.Second, func() {
+ msgCtx, err = conn.sendMessage(requestPacket)
+ if err != nil {
+ t.Fatalf("unable to send request message: %s", err)
+ }
+ })
+
+ // We should now be able to get this request packet out from the other
+ // side.
+ runWithTimeout(t, time.Second, func() {
+ if _, err = ptc.ReceiveRequest(); err != nil {
+ t.Fatalf("unable to receive request packet: %s", err)
+ }
+ })
+
+ return msgCtx
+}
+
+func testReceiveResponse(t *testing.T, ptc *packetTranslatorConn, msgCtx *messageContext) {
+ // Send a mock response packet.
+ responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response")
+ responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, msgCtx.id, "MessageID"))
+
+ runWithTimeout(t, time.Second, func() {
+ if err := ptc.SendResponse(responsePacket); err != nil {
+ t.Fatalf("unable to send response packet: %s", err)
+ }
+ })
+
+ // We should be able to receive the packet from the connection.
+ runWithTimeout(t, time.Second, func() {
+ if _, ok := <-msgCtx.responses; !ok {
+ t.Fatal("response channel closed")
+ }
+ })
+}
+
+func testSendUnhandledResponsesAndFinish(t *testing.T, ptc *packetTranslatorConn, conn *Conn, msgCtx *messageContext, numResponses int) {
+ // Send a mock response packet.
+ responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response")
+ responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, msgCtx.id, "MessageID"))
+
+ // Send extra responses but do not attempt to receive them on the
+ // client side.
+ for i := 0; i < numResponses; i++ {
+ runWithTimeout(t, time.Second, func() {
+ if err := ptc.SendResponse(responsePacket); err != nil {
+ t.Fatalf("unable to send response packet: %s", err)
+ }
+ })
+ }
+
+ // Finally, attempt to finish this message.
+ runWithTimeout(t, time.Second, func() {
+ conn.finishMessage(msgCtx)
+ })
+}
+
+func runWithTimeout(t *testing.T, timeout time.Duration, f func()) {
+ runtime.Gosched()
+
+ done := make(chan struct{})
+ go func() {
+ f()
+ close(done)
+ }()
+
+ runtime.Gosched()
+
+ select {
+ case <-done: // Success!
+ case <-time.After(timeout):
+ _, file, line, _ := runtime.Caller(1)
+ t.Fatalf("%s:%d timed out", file, line)
+ }
+}
+
+// packetTranslatorConn is a helful type which can be used with various tests
+// in this package. It implements the net.Conn interface to be used as an
+// underlying connection for a *ldap.Conn. Most methods are no-ops but the
+// Read() and Write() methods are able to translate ber-encoded packets for
+// testing LDAP requests and responses.
+//
+// Test cases can simulate an LDAP server sending a response by calling the
+// SendResponse() method with a ber-encoded LDAP response packet. Test cases
+// can simulate an LDAP server receiving a request from a client by calling the
+// ReceiveRequest() method which returns a ber-encoded LDAP request packet.
+type packetTranslatorConn struct {
+ lock sync.Mutex
+ isClosed bool
+
+ responseCond sync.Cond
+ requestCond sync.Cond
+
+ responseBuf bytes.Buffer
+ requestBuf bytes.Buffer
+}
+
+var errPacketTranslatorConnClosed = errors.New("connection closed")
+
+func newPacketTranslatorConn() *packetTranslatorConn {
+ conn := &packetTranslatorConn{}
+ conn.responseCond = sync.Cond{L: &conn.lock}
+ conn.requestCond = sync.Cond{L: &conn.lock}
+
+ return conn
+}
+
+// Read is called by the reader() loop to receive response packets. It will
+// block until there are more packet bytes available or this connection is
+// closed.
+func (c *packetTranslatorConn) Read(b []byte) (n int, err error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ for !c.isClosed {
+ // Attempt to read data from the response buffer. If it fails
+ // with an EOF, wait and try again.
+ n, err = c.responseBuf.Read(b)
+ if err != io.EOF {
+ return n, err
+ }
+
+ c.responseCond.Wait()
+ }
+
+ return 0, errPacketTranslatorConnClosed
+}
+
+// SendResponse writes the given response packet to the response buffer for
+// this conection, signalling any goroutine waiting to read a response.
+func (c *packetTranslatorConn) SendResponse(packet *ber.Packet) error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if c.isClosed {
+ return errPacketTranslatorConnClosed
+ }
+
+ // Signal any goroutine waiting to read a response.
+ defer c.responseCond.Broadcast()
+
+ // Writes to the buffer should always succeed.
+ c.responseBuf.Write(packet.Bytes())
+
+ return nil
+}
+
+// Write is called by the processMessages() loop to send request packets.
+func (c *packetTranslatorConn) Write(b []byte) (n int, err error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if c.isClosed {
+ return 0, errPacketTranslatorConnClosed
+ }
+
+ // Signal any goroutine waiting to read a request.
+ defer c.requestCond.Broadcast()
+
+ // Writes to the buffer should always succeed.
+ return c.requestBuf.Write(b)
+}
+
+// ReceiveRequest attempts to read a request packet from this connection. It
+// will block until it is able to read a full request packet or until this
+// connection is closed.
+func (c *packetTranslatorConn) ReceiveRequest() (*ber.Packet, error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ for !c.isClosed {
+ // Attempt to parse a request packet from the request buffer.
+ // If it fails with an unexpected EOF, wait and try again.
+ requestReader := bytes.NewReader(c.requestBuf.Bytes())
+ packet, err := ber.ReadPacket(requestReader)
+ switch err {
+ case io.EOF, io.ErrUnexpectedEOF:
+ c.requestCond.Wait()
+ case nil:
+ // Advance the request buffer by the number of bytes
+ // read to decode the request packet.
+ c.requestBuf.Next(c.requestBuf.Len() - requestReader.Len())
+ return packet, nil
+ default:
+ return nil, err
+ }
+ }
+
+ return nil, errPacketTranslatorConnClosed
+}
+
+// Close closes this connection causing Read() and Write() calls to fail.
+func (c *packetTranslatorConn) Close() error {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ c.isClosed = true
+ c.responseCond.Broadcast()
+ c.requestCond.Broadcast()
+
+ return nil
+}
+
+func (c *packetTranslatorConn) LocalAddr() net.Addr {
+ return (*net.TCPAddr)(nil)
+}
+
+func (c *packetTranslatorConn) RemoteAddr() net.Addr {
+ return (*net.TCPAddr)(nil)
+}
+
+func (c *packetTranslatorConn) SetDeadline(t time.Time) error {
+ return nil
+}
+
+func (c *packetTranslatorConn) SetReadDeadline(t time.Time) error {
+ return nil
+}
+
+func (c *packetTranslatorConn) SetWriteDeadline(t time.Time) error {
+ return nil
+}
diff --git a/vendor/github.com/go-ldap/ldap/control.go b/vendor/github.com/go-ldap/ldap/control.go
index 4d8298093..5c62118d4 100644
--- a/vendor/github.com/go-ldap/ldap/control.go
+++ b/vendor/github.com/go-ldap/ldap/control.go
@@ -12,35 +12,48 @@ import (
)
const (
- ControlTypePaging = "1.2.840.113556.1.4.319"
- ControlTypeBeheraPasswordPolicy = "1.3.6.1.4.1.42.2.27.8.5.1"
+ // ControlTypePaging - https://www.ietf.org/rfc/rfc2696.txt
+ ControlTypePaging = "1.2.840.113556.1.4.319"
+ // ControlTypeBeheraPasswordPolicy - https://tools.ietf.org/html/draft-behera-ldap-password-policy-10
+ ControlTypeBeheraPasswordPolicy = "1.3.6.1.4.1.42.2.27.8.5.1"
+ // ControlTypeVChuPasswordMustChange - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
ControlTypeVChuPasswordMustChange = "2.16.840.1.113730.3.4.4"
- ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
- ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
+ // ControlTypeVChuPasswordWarning - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
+ ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
+ // ControlTypeManageDsaIT - https://tools.ietf.org/html/rfc3296
+ ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
)
+// ControlTypeMap maps controls to text descriptions
var ControlTypeMap = map[string]string{
ControlTypePaging: "Paging",
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
ControlTypeManageDsaIT: "Manage DSA IT",
}
+// Control defines an interface controls provide to encode and describe themselves
type Control interface {
+ // GetControlType returns the OID
GetControlType() string
+ // Encode returns the ber packet representation
Encode() *ber.Packet
+ // String returns a human-readable description
String() string
}
+// ControlString implements the Control interface for simple controls
type ControlString struct {
ControlType string
Criticality bool
ControlValue string
}
+// GetControlType returns the OID
func (c *ControlString) GetControlType() string {
return c.ControlType
}
+// Encode returns the ber packet representation
func (c *ControlString) Encode() *ber.Packet {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlType, "Control Type ("+ControlTypeMap[c.ControlType]+")"))
@@ -51,26 +64,32 @@ func (c *ControlString) Encode() *ber.Packet {
return packet
}
+// String returns a human-readable description
func (c *ControlString) String() string {
return fmt.Sprintf("Control Type: %s (%q) Criticality: %t Control Value: %s", ControlTypeMap[c.ControlType], c.ControlType, c.Criticality, c.ControlValue)
}
+// ControlPaging implements the paging control described in https://www.ietf.org/rfc/rfc2696.txt
type ControlPaging struct {
+ // PagingSize indicates the page size
PagingSize uint32
- Cookie []byte
+ // Cookie is an opaque value returned by the server to track a paging cursor
+ Cookie []byte
}
+// GetControlType returns the OID
func (c *ControlPaging) GetControlType() string {
return ControlTypePaging
}
+// Encode returns the ber packet representation
func (c *ControlPaging) Encode() *ber.Packet {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypePaging, "Control Type ("+ControlTypeMap[ControlTypePaging]+")"))
p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
- seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(c.PagingSize), "Paging Size"))
+ seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, int64(c.PagingSize), "Paging Size"))
cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
cookie.Value = c.Cookie
cookie.Data.Write(c.Cookie)
@@ -81,6 +100,7 @@ func (c *ControlPaging) Encode() *ber.Packet {
return packet
}
+// String returns a human-readable description
func (c *ControlPaging) String() string {
return fmt.Sprintf(
"Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q",
@@ -91,21 +111,29 @@ func (c *ControlPaging) String() string {
c.Cookie)
}
+// SetCookie stores the given cookie in the paging control
func (c *ControlPaging) SetCookie(cookie []byte) {
c.Cookie = cookie
}
+// ControlBeheraPasswordPolicy implements the control described in https://tools.ietf.org/html/draft-behera-ldap-password-policy-10
type ControlBeheraPasswordPolicy struct {
- Expire int64
- Grace int64
- Error int8
+ // Expire contains the number of seconds before a password will expire
+ Expire int64
+ // Grace indicates the remaining number of times a user will be allowed to authenticate with an expired password
+ Grace int64
+ // Error indicates the error code
+ Error int8
+ // ErrorString is a human readable error
ErrorString string
}
+// GetControlType returns the OID
func (c *ControlBeheraPasswordPolicy) GetControlType() string {
return ControlTypeBeheraPasswordPolicy
}
+// Encode returns the ber packet representation
func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeBeheraPasswordPolicy, "Control Type ("+ControlTypeMap[ControlTypeBeheraPasswordPolicy]+")"))
@@ -113,6 +141,7 @@ func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet {
return packet
}
+// String returns a human-readable description
func (c *ControlBeheraPasswordPolicy) String() string {
return fmt.Sprintf(
"Control Type: %s (%q) Criticality: %t Expire: %d Grace: %d Error: %d, ErrorString: %s",
@@ -125,39 +154,49 @@ func (c *ControlBeheraPasswordPolicy) String() string {
c.ErrorString)
}
+// ControlVChuPasswordMustChange implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
type ControlVChuPasswordMustChange struct {
+ // MustChange indicates if the password is required to be changed
MustChange bool
}
+// GetControlType returns the OID
func (c *ControlVChuPasswordMustChange) GetControlType() string {
return ControlTypeVChuPasswordMustChange
}
+// Encode returns the ber packet representation
func (c *ControlVChuPasswordMustChange) Encode() *ber.Packet {
return nil
}
+// String returns a human-readable description
func (c *ControlVChuPasswordMustChange) String() string {
return fmt.Sprintf(
- "Control Type: %s (%q) Criticality: %t MustChange: %b",
+ "Control Type: %s (%q) Criticality: %t MustChange: %v",
ControlTypeMap[ControlTypeVChuPasswordMustChange],
ControlTypeVChuPasswordMustChange,
false,
c.MustChange)
}
+// ControlVChuPasswordWarning implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
type ControlVChuPasswordWarning struct {
+ // Expire indicates the time in seconds until the password expires
Expire int64
}
+// GetControlType returns the OID
func (c *ControlVChuPasswordWarning) GetControlType() string {
return ControlTypeVChuPasswordWarning
}
+// Encode returns the ber packet representation
func (c *ControlVChuPasswordWarning) Encode() *ber.Packet {
return nil
}
+// String returns a human-readable description
func (c *ControlVChuPasswordWarning) String() string {
return fmt.Sprintf(
"Control Type: %s (%q) Criticality: %t Expire: %b",
@@ -167,14 +206,18 @@ func (c *ControlVChuPasswordWarning) String() string {
c.Expire)
}
+// ControlManageDsaIT implements the control described in https://tools.ietf.org/html/rfc3296
type ControlManageDsaIT struct {
+ // Criticality indicates if this control is required
Criticality bool
}
+// GetControlType returns the OID
func (c *ControlManageDsaIT) GetControlType() string {
return ControlTypeManageDsaIT
}
+// Encode returns the ber packet representation
func (c *ControlManageDsaIT) Encode() *ber.Packet {
//FIXME
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
@@ -185,6 +228,7 @@ func (c *ControlManageDsaIT) Encode() *ber.Packet {
return packet
}
+// String returns a human-readable description
func (c *ControlManageDsaIT) String() string {
return fmt.Sprintf(
"Control Type: %s (%q) Criticality: %t",
@@ -193,10 +237,12 @@ func (c *ControlManageDsaIT) String() string {
c.Criticality)
}
+// NewControlManageDsaIT returns a ControlManageDsaIT control
func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
return &ControlManageDsaIT{Criticality: Criticality}
}
+// FindControl returns the first control of the given type in the list, or nil
func FindControl(controls []Control, controlType string) Control {
for _, c := range controls {
if c.GetControlType() == controlType {
@@ -206,20 +252,56 @@ func FindControl(controls []Control, controlType string) Control {
return nil
}
+// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made
func DecodeControl(packet *ber.Packet) Control {
- ControlType := packet.Children[0].Value.(string)
- Criticality := false
+ var (
+ ControlType = ""
+ Criticality = false
+ value *ber.Packet
+ )
+
+ switch len(packet.Children) {
+ case 0:
+ // at least one child is required for control type
+ return nil
+
+ case 1:
+ // just type, no criticality or value
+ packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
+ ControlType = packet.Children[0].Value.(string)
+
+ case 2:
+ packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
+ ControlType = packet.Children[0].Value.(string)
+
+ // Children[1] could be criticality or value (both are optional)
+ // duck-type on whether this is a boolean
+ if _, ok := packet.Children[1].Value.(bool); ok {
+ packet.Children[1].Description = "Criticality"
+ Criticality = packet.Children[1].Value.(bool)
+ } else {
+ packet.Children[1].Description = "Control Value"
+ value = packet.Children[1]
+ }
+
+ case 3:
+ packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
+ ControlType = packet.Children[0].Value.(string)
- packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
- value := packet.Children[1]
- if len(packet.Children) == 3 {
- value = packet.Children[2]
packet.Children[1].Description = "Criticality"
Criticality = packet.Children[1].Value.(bool)
+
+ packet.Children[2].Description = "Control Value"
+ value = packet.Children[2]
+
+ default:
+ // more than 3 children is invalid
+ return nil
}
- value.Description = "Control Value"
switch ControlType {
+ case ControlTypeManageDsaIT:
+ return NewControlManageDsaIT(Criticality)
case ControlTypePaging:
value.Description += " (Paging)"
c := new(ControlPaging)
@@ -295,14 +377,18 @@ func DecodeControl(packet *ber.Packet) Control {
value.Value = c.Expire
return c
+ default:
+ c := new(ControlString)
+ c.ControlType = ControlType
+ c.Criticality = Criticality
+ if value != nil {
+ c.ControlValue = value.Value.(string)
+ }
+ return c
}
- c := new(ControlString)
- c.ControlType = ControlType
- c.Criticality = Criticality
- c.ControlValue = value.Value.(string)
- return c
}
+// NewControlString returns a generic control
func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
return &ControlString{
ControlType: controlType,
@@ -311,10 +397,12 @@ func NewControlString(controlType string, criticality bool, controlValue string)
}
}
+// NewControlPaging returns a paging control
func NewControlPaging(pagingSize uint32) *ControlPaging {
return &ControlPaging{PagingSize: pagingSize}
}
+// NewControlBeheraPasswordPolicy returns a ControlBeheraPasswordPolicy
func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy {
return &ControlBeheraPasswordPolicy{
Expire: -1,
diff --git a/vendor/github.com/go-ldap/ldap/control_test.go b/vendor/github.com/go-ldap/ldap/control_test.go
new file mode 100644
index 000000000..3fcdab0d7
--- /dev/null
+++ b/vendor/github.com/go-ldap/ldap/control_test.go
@@ -0,0 +1,58 @@
+package ldap
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "runtime"
+ "testing"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+func TestControlPaging(t *testing.T) {
+ runControlTest(t, NewControlPaging(0))
+ runControlTest(t, NewControlPaging(100))
+}
+
+func TestControlManageDsaIT(t *testing.T) {
+ runControlTest(t, NewControlManageDsaIT(true))
+ runControlTest(t, NewControlManageDsaIT(false))
+}
+
+func TestControlString(t *testing.T) {
+ runControlTest(t, NewControlString("x", true, "y"))
+ runControlTest(t, NewControlString("x", true, ""))
+ runControlTest(t, NewControlString("x", false, "y"))
+ runControlTest(t, NewControlString("x", false, ""))
+}
+
+func runControlTest(t *testing.T, originalControl Control) {
+ header := ""
+ if callerpc, _, line, ok := runtime.Caller(1); ok {
+ if caller := runtime.FuncForPC(callerpc); caller != nil {
+ header = fmt.Sprintf("%s:%d: ", caller.Name(), line)
+ }
+ }
+
+ encodedPacket := originalControl.Encode()
+ encodedBytes := encodedPacket.Bytes()
+
+ // Decode directly from the encoded packet (ensures Value is correct)
+ fromPacket := DecodeControl(encodedPacket)
+ if !bytes.Equal(encodedBytes, fromPacket.Encode().Bytes()) {
+ t.Errorf("%sround-trip from encoded packet failed", header)
+ }
+ if reflect.TypeOf(originalControl) != reflect.TypeOf(fromPacket) {
+ t.Errorf("%sgot different type decoding from encoded packet: %T vs %T", header, fromPacket, originalControl)
+ }
+
+ // Decode from the wire bytes (ensures ber-encoding is correct)
+ fromBytes := DecodeControl(ber.DecodePacket(encodedBytes))
+ if !bytes.Equal(encodedBytes, fromBytes.Encode().Bytes()) {
+ t.Errorf("%sround-trip from encoded bytes failed", header)
+ }
+ if reflect.TypeOf(originalControl) != reflect.TypeOf(fromPacket) {
+ t.Errorf("%sgot different type decoding from encoded bytes: %T vs %T", header, fromBytes, originalControl)
+ }
+}
diff --git a/vendor/github.com/go-ldap/ldap/del.go b/vendor/github.com/go-ldap/ldap/del.go
index 5bb5a25d7..4fd63dc3f 100644
--- a/vendor/github.com/go-ldap/ldap/del.go
+++ b/vendor/github.com/go-ldap/ldap/del.go
@@ -12,8 +12,11 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// DelRequest implements an LDAP deletion request
type DelRequest struct {
- DN string
+ // DN is the name of the directory entry to delete
+ DN string
+ // Controls hold optional controls to send with the request
Controls []Control
}
@@ -23,6 +26,7 @@ func (d DelRequest) encode() *ber.Packet {
return request
}
+// NewDelRequest creates a delete request for the given DN and controls
func NewDelRequest(DN string,
Controls []Control) *DelRequest {
return &DelRequest{
@@ -31,10 +35,10 @@ func NewDelRequest(DN string,
}
}
+// Del executes the given delete request
func (l *Conn) Del(delRequest *DelRequest) error {
- messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(delRequest.encode())
if delRequest.Controls != nil {
packet.AppendChild(encodeControls(delRequest.Controls))
@@ -42,22 +46,19 @@ func (l *Conn) Del(delRequest *DelRequest) error {
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
- if channel == nil {
- return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
@@ -78,6 +79,6 @@ func (l *Conn) Del(delRequest *DelRequest) error {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
}
- l.Debug.Printf("%d: returning", messageID)
+ l.Debug.Printf("%d: returning", msgCtx.id)
return nil
}
diff --git a/vendor/github.com/go-ldap/ldap/dn.go b/vendor/github.com/go-ldap/ldap/dn.go
index 5d83c5e9a..cc70c894c 100644
--- a/vendor/github.com/go-ldap/ldap/dn.go
+++ b/vendor/github.com/go-ldap/ldap/dn.go
@@ -55,19 +55,25 @@ import (
ber "gopkg.in/asn1-ber.v1"
)
+// AttributeTypeAndValue represents an attributeTypeAndValue from https://tools.ietf.org/html/rfc4514
type AttributeTypeAndValue struct {
- Type string
+ // Type is the attribute type
+ Type string
+ // Value is the attribute value
Value string
}
+// RelativeDN represents a relativeDistinguishedName from https://tools.ietf.org/html/rfc4514
type RelativeDN struct {
Attributes []*AttributeTypeAndValue
}
+// DN represents a distinguishedName from https://tools.ietf.org/html/rfc4514
type DN struct {
RDNs []*RelativeDN
}
+// ParseDN returns a distinguishedName or an error
func ParseDN(str string) (*DN, error) {
dn := new(DN)
dn.RDNs = make([]*RelativeDN, 0)
@@ -94,11 +100,9 @@ func ParseDN(str string) (*DN, error) {
dst := []byte{0}
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
if err != nil {
- return nil, errors.New(
- fmt.Sprintf("Failed to decode escaped character: %s", err))
+ return nil, fmt.Errorf("Failed to decode escaped character: %s", err)
} else if n != 1 {
- return nil, errors.New(
- fmt.Sprintf("Expected 1 byte when un-escaping, got %d", n))
+ return nil, fmt.Errorf("Expected 1 byte when un-escaping, got %d", n)
}
buffer.WriteByte(dst[0])
i++
@@ -119,12 +123,11 @@ func ParseDN(str string) (*DN, error) {
} else {
data = str[i:]
}
- raw_ber, err := enchex.DecodeString(data)
+ rawBER, err := enchex.DecodeString(data)
if err != nil {
- return nil, errors.New(
- fmt.Sprintf("Failed to decode BER encoding: %s", err))
+ return nil, fmt.Errorf("Failed to decode BER encoding: %s", err)
}
- packet := ber.DecodePacket(raw_ber)
+ packet := ber.DecodePacket(rawBER)
buffer.WriteString(packet.Data.String())
i += len(data) - 1
}
diff --git a/vendor/github.com/go-ldap/ldap/error.go b/vendor/github.com/go-ldap/ldap/error.go
index 97404eb65..ff697873d 100644
--- a/vendor/github.com/go-ldap/ldap/error.go
+++ b/vendor/github.com/go-ldap/ldap/error.go
@@ -56,6 +56,7 @@ const (
ErrorUnexpectedResponse = 205
)
+// LDAPResultCodeMap contains string descriptions for LDAP error codes
var LDAPResultCodeMap = map[uint8]string{
LDAPResultSuccess: "Success",
LDAPResultOperationsError: "Operations Error",
@@ -115,8 +116,11 @@ func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
return ErrorNetwork, "Invalid packet format"
}
+// Error holds LDAP error information
type Error struct {
- Err error
+ // Err is the underlying error
+ Err error
+ // ResultCode is the LDAP error code
ResultCode uint8
}
@@ -124,10 +128,12 @@ func (e *Error) Error() string {
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
}
+// NewError creates an LDAP error with the given code and underlying error
func NewError(resultCode uint8, err error) error {
return &Error{ResultCode: resultCode, Err: err}
}
+// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
func IsErrorWithCode(err error, desiredResultCode uint8) bool {
if err == nil {
return false
diff --git a/vendor/github.com/go-ldap/ldap/error_test.go b/vendor/github.com/go-ldap/ldap/error_test.go
index 4ec720d9f..c010ebe3e 100644
--- a/vendor/github.com/go-ldap/ldap/error_test.go
+++ b/vendor/github.com/go-ldap/ldap/error_test.go
@@ -1,7 +1,11 @@
package ldap
import (
+ "errors"
+ "net"
+ "strings"
"testing"
+ "time"
"gopkg.in/asn1-ber.v1"
)
@@ -16,8 +20,8 @@ func TestNilPacket(t *testing.T) {
// Test for nil result
kids := []*ber.Packet{
- &ber.Packet{}, // Unused
- nil, // Can't be nil
+ {}, // Unused
+ nil, // Can't be nil
}
pack := &ber.Packet{Children: kids}
code, _ = getLDAPResultCode(pack)
@@ -25,5 +29,74 @@ func TestNilPacket(t *testing.T) {
if code != ErrorUnexpectedResponse {
t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code)
}
+}
+
+// TestConnReadErr tests that an unexpected error reading from underlying
+// connection bubbles up to the goroutine which makes a request.
+func TestConnReadErr(t *testing.T) {
+ conn := &signalErrConn{
+ signals: make(chan error),
+ }
+
+ ldapConn := NewConn(conn, false)
+ ldapConn.Start()
+
+ // Make a dummy search request.
+ searchReq := NewSearchRequest("dc=example,dc=com", ScopeWholeSubtree, DerefAlways, 0, 0, false, "(objectClass=*)", nil, nil)
+
+ expectedError := errors.New("this is the error you are looking for")
+
+ // Send the signal after a short amount of time.
+ time.AfterFunc(10*time.Millisecond, func() { conn.signals <- expectedError })
+
+ // This should block until the underlyiny conn gets the error signal
+ // which should bubble up through the reader() goroutine, close the
+ // connection, and
+ _, err := ldapConn.Search(searchReq)
+ if err == nil || !strings.Contains(err.Error(), expectedError.Error()) {
+ t.Errorf("not the expected error: %s", err)
+ }
+}
+
+// signalErrConn is a helful type used with TestConnReadErr. It implements the
+// net.Conn interface to be used as a connection for the test. Most methods are
+// no-ops but the Read() method blocks until it receives a signal which it
+// returns as an error.
+type signalErrConn struct {
+ signals chan error
+}
+
+// Read blocks until an error is sent on the internal signals channel. That
+// error is returned.
+func (c *signalErrConn) Read(b []byte) (n int, err error) {
+ return 0, <-c.signals
+}
+
+func (c *signalErrConn) Write(b []byte) (n int, err error) {
+ return len(b), nil
+}
+
+func (c *signalErrConn) Close() error {
+ close(c.signals)
+ return nil
+}
+
+func (c *signalErrConn) LocalAddr() net.Addr {
+ return (*net.TCPAddr)(nil)
+}
+
+func (c *signalErrConn) RemoteAddr() net.Addr {
+ return (*net.TCPAddr)(nil)
+}
+
+func (c *signalErrConn) SetDeadline(t time.Time) error {
+ return nil
+}
+
+func (c *signalErrConn) SetReadDeadline(t time.Time) error {
+ return nil
+}
+func (c *signalErrConn) SetWriteDeadline(t time.Time) error {
+ return nil
}
diff --git a/vendor/github.com/go-ldap/ldap/filter.go b/vendor/github.com/go-ldap/ldap/filter.go
index 63bcec1e3..7eae310f1 100644
--- a/vendor/github.com/go-ldap/ldap/filter.go
+++ b/vendor/github.com/go-ldap/ldap/filter.go
@@ -15,6 +15,7 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// Filter choices
const (
FilterAnd = 0
FilterOr = 1
@@ -28,6 +29,7 @@ const (
FilterExtensibleMatch = 9
)
+// FilterMap contains human readable descriptions of Filter choices
var FilterMap = map[uint64]string{
FilterAnd: "And",
FilterOr: "Or",
@@ -41,18 +43,21 @@ var FilterMap = map[uint64]string{
FilterExtensibleMatch: "Extensible Match",
}
+// SubstringFilter options
const (
FilterSubstringsInitial = 0
FilterSubstringsAny = 1
FilterSubstringsFinal = 2
)
+// FilterSubstringsMap contains human readable descriptions of SubstringFilter choices
var FilterSubstringsMap = map[uint64]string{
FilterSubstringsInitial: "Substrings Initial",
FilterSubstringsAny: "Substrings Any",
FilterSubstringsFinal: "Substrings Final",
}
+// MatchingRuleAssertion choices
const (
MatchingRuleAssertionMatchingRule = 1
MatchingRuleAssertionType = 2
@@ -60,6 +65,7 @@ const (
MatchingRuleAssertionDNAttributes = 4
)
+// MatchingRuleAssertionMap contains human readable descriptions of MatchingRuleAssertion choices
var MatchingRuleAssertionMap = map[uint64]string{
MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
MatchingRuleAssertionType: "Matching Rule Assertion Type",
@@ -67,6 +73,7 @@ var MatchingRuleAssertionMap = map[uint64]string{
MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
}
+// CompileFilter converts a string representation of a filter into a BER-encoded packet
func CompileFilter(filter string) (*ber.Packet, error) {
if len(filter) == 0 || filter[0] != '(' {
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
@@ -81,6 +88,7 @@ func CompileFilter(filter string) (*ber.Packet, error) {
return packet, nil
}
+// DecompileFilter converts a packet representation of a filter into a string representation
func DecompileFilter(packet *ber.Packet) (ret string, err error) {
defer func() {
if r := recover(); r != nil {
@@ -239,11 +247,13 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
packet.AppendChild(child)
return packet, newPos, err
default:
- READING_ATTR := 0
- READING_EXTENSIBLE_MATCHING_RULE := 1
- READING_CONDITION := 2
+ const (
+ stateReadingAttr = 0
+ stateReadingExtensibleMatchingRule = 1
+ stateReadingCondition = 2
+ )
- state := READING_ATTR
+ state := stateReadingAttr
attribute := ""
extensibleDNAttributes := false
@@ -261,56 +271,56 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
}
switch state {
- case READING_ATTR:
+ case stateReadingAttr:
switch {
// Extensible rule, with only DN-matching
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
extensibleDNAttributes = true
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 5
// Extensible rule, with DN-matching and a matching OID
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
extensibleDNAttributes = true
- state = READING_EXTENSIBLE_MATCHING_RULE
+ state = stateReadingExtensibleMatchingRule
newPos += 4
// Extensible rule, with attr only
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 2
// Extensible rule, with no DN attribute matching
case currentRune == ':':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
- state = READING_EXTENSIBLE_MATCHING_RULE
- newPos += 1
+ state = stateReadingExtensibleMatchingRule
+ newPos++
// Equality condition
case currentRune == '=':
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
- state = READING_CONDITION
- newPos += 1
+ state = stateReadingCondition
+ newPos++
// Greater-than or equal
case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 2
// Less-than or equal
case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 2
// Approx
case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 2
// Still reading the attribute name
@@ -319,12 +329,12 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
newPos += currentWidth
}
- case READING_EXTENSIBLE_MATCHING_RULE:
+ case stateReadingExtensibleMatchingRule:
switch {
// Matching rule OID is done
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
- state = READING_CONDITION
+ state = stateReadingCondition
newPos += 2
// Still reading the matching rule oid
@@ -333,7 +343,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
newPos += currentWidth
}
- case READING_CONDITION:
+ case stateReadingCondition:
// append to the condition
condition += fmt.Sprintf("%c", currentRune)
newPos += currentWidth
@@ -369,9 +379,9 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
}
// Add the value (only required child)
- encodedString, err := escapedStringToEncodedBytes(condition)
- if err != nil {
- return packet, newPos, err
+ encodedString, encodeErr := escapedStringToEncodedBytes(condition)
+ if encodeErr != nil {
+ return packet, newPos, encodeErr
}
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
@@ -401,17 +411,17 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
default:
tag = FilterSubstringsAny
}
- encodedString, err := escapedStringToEncodedBytes(part)
- if err != nil {
- return packet, newPos, err
+ encodedString, encodeErr := escapedStringToEncodedBytes(part)
+ if encodeErr != nil {
+ return packet, newPos, encodeErr
}
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
}
packet.AppendChild(seq)
default:
- encodedString, err := escapedStringToEncodedBytes(condition)
- if err != nil {
- return packet, newPos, err
+ encodedString, encodeErr := escapedStringToEncodedBytes(condition)
+ if encodeErr != nil {
+ return packet, newPos, encodeErr
}
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
@@ -440,12 +450,12 @@ func escapedStringToEncodedBytes(escapedString string) (string, error) {
if i+2 > len(escapedString) {
return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
}
- if escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3]); decodeErr != nil {
+ escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3])
+ if decodeErr != nil {
return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
- } else {
- buffer.WriteByte(escByte[0])
- i += 2 // +1 from end of loop, so 3 total for \xx.
}
+ buffer.WriteByte(escByte[0])
+ i += 2 // +1 from end of loop, so 3 total for \xx.
} else {
buffer.WriteRune(currentRune)
}
diff --git a/vendor/github.com/go-ldap/ldap/ldap.go b/vendor/github.com/go-ldap/ldap/ldap.go
index 1620aaea6..90018be83 100644
--- a/vendor/github.com/go-ldap/ldap/ldap.go
+++ b/vendor/github.com/go-ldap/ldap/ldap.go
@@ -36,6 +36,7 @@ const (
ApplicationExtendedResponse = 24
)
+// ApplicationMap contains human readable descriptions of LDAP Application Codes
var ApplicationMap = map[uint8]string{
ApplicationBindRequest: "Bind Request",
ApplicationBindResponse: "Bind Response",
@@ -72,6 +73,7 @@ const (
BeheraPasswordInHistory = 8
)
+// BeheraPasswordPolicyErrorMap contains human readable descriptions of Behera Password Policy error codes
var BeheraPasswordPolicyErrorMap = map[int8]string{
BeheraPasswordExpired: "Password expired",
BeheraAccountLocked: "Account locked",
@@ -237,6 +239,7 @@ func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
}
}
+// DebugBinaryFile reads and prints packets from the given filename
func DebugBinaryFile(fileName string) error {
file, err := ioutil.ReadFile(fileName)
if err != nil {
diff --git a/vendor/github.com/go-ldap/ldap/modify.go b/vendor/github.com/go-ldap/ldap/modify.go
index 5c042af79..e4ab6cefc 100644
--- a/vendor/github.com/go-ldap/ldap/modify.go
+++ b/vendor/github.com/go-ldap/ldap/modify.go
@@ -36,64 +36,76 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// Change operation choices
const (
AddAttribute = 0
DeleteAttribute = 1
ReplaceAttribute = 2
)
+// PartialAttribute for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
type PartialAttribute struct {
- attrType string
- attrVals []string
+ // Type is the type of the partial attribute
+ Type string
+ // Vals are the values of the partial attribute
+ Vals []string
}
func (p *PartialAttribute) encode() *ber.Packet {
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
- seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.attrType, "Type"))
+ seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.Type, "Type"))
set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
- for _, value := range p.attrVals {
+ for _, value := range p.Vals {
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
}
seq.AppendChild(set)
return seq
}
+// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
type ModifyRequest struct {
- dn string
- addAttributes []PartialAttribute
- deleteAttributes []PartialAttribute
- replaceAttributes []PartialAttribute
+ // DN is the distinguishedName of the directory entry to modify
+ DN string
+ // AddAttributes contain the attributes to add
+ AddAttributes []PartialAttribute
+ // DeleteAttributes contain the attributes to delete
+ DeleteAttributes []PartialAttribute
+ // ReplaceAttributes contain the attributes to replace
+ ReplaceAttributes []PartialAttribute
}
+// Add inserts the given attribute to the list of attributes to add
func (m *ModifyRequest) Add(attrType string, attrVals []string) {
- m.addAttributes = append(m.addAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+ m.AddAttributes = append(m.AddAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
}
+// Delete inserts the given attribute to the list of attributes to delete
func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
- m.deleteAttributes = append(m.deleteAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+ m.DeleteAttributes = append(m.DeleteAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
}
+// Replace inserts the given attribute to the list of attributes to replace
func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
- m.replaceAttributes = append(m.replaceAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
+ m.ReplaceAttributes = append(m.ReplaceAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
}
func (m ModifyRequest) encode() *ber.Packet {
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
- request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.dn, "DN"))
+ request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.DN, "DN"))
changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
- for _, attribute := range m.addAttributes {
+ for _, attribute := range m.AddAttributes {
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
change.AppendChild(attribute.encode())
changes.AppendChild(change)
}
- for _, attribute := range m.deleteAttributes {
+ for _, attribute := range m.DeleteAttributes {
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
change.AppendChild(attribute.encode())
changes.AppendChild(change)
}
- for _, attribute := range m.replaceAttributes {
+ for _, attribute := range m.ReplaceAttributes {
change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
change.AppendChild(attribute.encode())
@@ -103,38 +115,36 @@ func (m ModifyRequest) encode() *ber.Packet {
return request
}
+// NewModifyRequest creates a modify request for the given DN
func NewModifyRequest(
dn string,
) *ModifyRequest {
return &ModifyRequest{
- dn: dn,
+ DN: dn,
}
}
+// Modify performs the ModifyRequest
func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
- messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(modifyRequest.encode())
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return err
}
- if channel == nil {
- return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return err
}
@@ -155,6 +165,6 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
}
- l.Debug.Printf("%d: returning", messageID)
+ l.Debug.Printf("%d: returning", msgCtx.id)
return nil
}
diff --git a/vendor/github.com/go-ldap/ldap/passwdmodify.go b/vendor/github.com/go-ldap/ldap/passwdmodify.go
index 6d5ca975a..26110ccf4 100644
--- a/vendor/github.com/go-ldap/ldap/passwdmodify.go
+++ b/vendor/github.com/go-ldap/ldap/passwdmodify.go
@@ -16,13 +16,21 @@ const (
passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
)
+// PasswordModifyRequest implements the Password Modify Extended Operation as defined in https://www.ietf.org/rfc/rfc3062.txt
type PasswordModifyRequest struct {
+ // UserIdentity is an optional string representation of the user associated with the request.
+ // This string may or may not be an LDAPDN [RFC2253].
+ // If no UserIdentity field is present, the request acts up upon the password of the user currently associated with the LDAP session
UserIdentity string
- OldPassword string
- NewPassword string
+ // OldPassword, if present, contains the user's current password
+ OldPassword string
+ // NewPassword, if present, contains the desired password for this user
+ NewPassword string
}
+// PasswordModifyResult holds the server response to a PasswordModifyRequest
type PasswordModifyResult struct {
+ // GeneratedPassword holds a password generated by the server, if present
GeneratedPassword string
}
@@ -47,7 +55,7 @@ func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
return request, nil
}
-// Create a new PasswordModifyRequest
+// NewPasswordModifyRequest creates a new PasswordModifyRequest
//
// According to the RFC 3602:
// userIdentity is a string representing the user associated with the request.
@@ -72,11 +80,10 @@ func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPasswo
}
}
+// PasswordModify performs the modification request
func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
- messageID := l.nextMessageID()
-
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
encodedPasswordModifyRequest, err := passwordModifyRequest.encode()
if err != nil {
@@ -86,24 +93,21 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return nil, err
}
- if channel == nil {
- return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
result := &PasswordModifyResult{}
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return nil, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return nil, err
}
diff --git a/vendor/github.com/go-ldap/ldap/search.go b/vendor/github.com/go-ldap/ldap/search.go
index 7e9495bdc..2a99894c9 100644
--- a/vendor/github.com/go-ldap/ldap/search.go
+++ b/vendor/github.com/go-ldap/ldap/search.go
@@ -68,18 +68,21 @@ import (
"gopkg.in/asn1-ber.v1"
)
+// scope choices
const (
ScopeBaseObject = 0
ScopeSingleLevel = 1
ScopeWholeSubtree = 2
)
+// ScopeMap contains human readable descriptions of scope choices
var ScopeMap = map[int]string{
ScopeBaseObject: "Base Object",
ScopeSingleLevel: "Single Level",
ScopeWholeSubtree: "Whole Subtree",
}
+// derefAliases
const (
NeverDerefAliases = 0
DerefInSearching = 1
@@ -87,6 +90,7 @@ const (
DerefAlways = 3
)
+// DerefMap contains human readable descriptions of derefAliases choices
var DerefMap = map[int]string{
NeverDerefAliases: "NeverDerefAliases",
DerefInSearching: "DerefInSearching",
@@ -114,11 +118,15 @@ func NewEntry(dn string, attributes map[string][]string) *Entry {
}
}
+// Entry represents a single search result entry
type Entry struct {
- DN string
+ // DN is the distinguished name of the entry
+ DN string
+ // Attributes are the returned attributes for the entry
Attributes []*EntryAttribute
}
+// GetAttributeValues returns the values for the named attribute, or an empty list
func (e *Entry) GetAttributeValues(attribute string) []string {
for _, attr := range e.Attributes {
if attr.Name == attribute {
@@ -128,6 +136,7 @@ func (e *Entry) GetAttributeValues(attribute string) []string {
return []string{}
}
+// GetRawAttributeValues returns the byte values for the named attribute, or an empty list
func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
for _, attr := range e.Attributes {
if attr.Name == attribute {
@@ -137,6 +146,7 @@ func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
return [][]byte{}
}
+// GetAttributeValue returns the first value for the named attribute, or ""
func (e *Entry) GetAttributeValue(attribute string) string {
values := e.GetAttributeValues(attribute)
if len(values) == 0 {
@@ -145,6 +155,7 @@ func (e *Entry) GetAttributeValue(attribute string) string {
return values[0]
}
+// GetRawAttributeValue returns the first value for the named attribute, or an empty slice
func (e *Entry) GetRawAttributeValue(attribute string) []byte {
values := e.GetRawAttributeValues(attribute)
if len(values) == 0 {
@@ -153,6 +164,7 @@ func (e *Entry) GetRawAttributeValue(attribute string) []byte {
return values[0]
}
+// Print outputs a human-readable description
func (e *Entry) Print() {
fmt.Printf("DN: %s\n", e.DN)
for _, attr := range e.Attributes {
@@ -160,6 +172,7 @@ func (e *Entry) Print() {
}
}
+// PrettyPrint outputs a human-readable description indenting
func (e *Entry) PrettyPrint(indent int) {
fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
for _, attr := range e.Attributes {
@@ -180,38 +193,51 @@ func NewEntryAttribute(name string, values []string) *EntryAttribute {
}
}
+// EntryAttribute holds a single attribute
type EntryAttribute struct {
- Name string
- Values []string
+ // Name is the name of the attribute
+ Name string
+ // Values contain the string values of the attribute
+ Values []string
+ // ByteValues contain the raw values of the attribute
ByteValues [][]byte
}
+// Print outputs a human-readable description
func (e *EntryAttribute) Print() {
fmt.Printf("%s: %s\n", e.Name, e.Values)
}
+// PrettyPrint outputs a human-readable description with indenting
func (e *EntryAttribute) PrettyPrint(indent int) {
fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
}
+// SearchResult holds the server's response to a search request
type SearchResult struct {
- Entries []*Entry
+ // Entries are the returned entries
+ Entries []*Entry
+ // Referrals are the returned referrals
Referrals []string
- Controls []Control
+ // Controls are the returned controls
+ Controls []Control
}
+// Print outputs a human-readable description
func (s *SearchResult) Print() {
for _, entry := range s.Entries {
entry.Print()
}
}
+// PrettyPrint outputs a human-readable description with indenting
func (s *SearchResult) PrettyPrint(indent int) {
for _, entry := range s.Entries {
entry.PrettyPrint(indent)
}
}
+// SearchRequest represents a search request to send to the server
type SearchRequest struct {
BaseDN string
Scope int
@@ -247,6 +273,7 @@ func (s *SearchRequest) encode() (*ber.Packet, error) {
return request, nil
}
+// NewSearchRequest creates a new search request
func NewSearchRequest(
BaseDN string,
Scope, DerefAliases, SizeLimit, TimeLimit int,
@@ -341,10 +368,10 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
return searchResult, nil
}
+// Search performs the given search request
func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
- messageID := l.nextMessageID()
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
// encode search request
encodedSearchRequest, err := searchRequest.encode()
if err != nil {
@@ -358,14 +385,11 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
l.Debug.PrintPacket(packet)
- channel, err := l.sendMessage(packet)
+ msgCtx, err := l.sendMessage(packet)
if err != nil {
return nil, err
}
- if channel == nil {
- return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
- }
- defer l.finishMessage(messageID)
+ defer l.finishMessage(msgCtx)
result := &SearchResult{
Entries: make([]*Entry, 0),
@@ -374,13 +398,13 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
foundSearchResultDone := false
for !foundSearchResultDone {
- l.Debug.Printf("%d: waiting for response", messageID)
- packetResponse, ok := <-channel
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
if !ok {
- return nil, NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ return nil, NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
}
packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", messageID, packet)
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
if err != nil {
return nil, err
}
@@ -421,6 +445,6 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
}
}
- l.Debug.Printf("%d: returning", messageID)
+ l.Debug.Printf("%d: returning", msgCtx.id)
return result, nil
}