summaryrefslogtreecommitdiffstats
path: root/vendor/gopkg.in
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2019-02-18 12:34:37 +0000
committerGitHub <noreply@github.com>2019-02-18 12:34:37 +0000
commit22770c324dc46412241ec833e608134df8f47245 (patch)
treed3ffad8575860955a56d1ba259145fc5a51a596b /vendor/gopkg.in
parenta380cfd8e03148a05859a7496d235fa14bde4796 (diff)
downloadgitea-22770c324dc46412241ec833e608134df8f47245.tar.gz
gitea-22770c324dc46412241ec833e608134df8f47245.zip
Move to ldap.v3 to fix #5928 (#6105)
Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'vendor/gopkg.in')
-rw-r--r--vendor/gopkg.in/ldap.v2/atomic_value.go13
-rw-r--r--vendor/gopkg.in/ldap.v2/atomic_value_go13.go28
-rw-r--r--vendor/gopkg.in/ldap.v2/error.go155
-rw-r--r--vendor/gopkg.in/ldap.v3/LICENSE (renamed from vendor/gopkg.in/ldap.v2/LICENSE)0
-rw-r--r--vendor/gopkg.in/ldap.v3/add.go (renamed from vendor/gopkg.in/ldap.v2/add.go)16
-rw-r--r--vendor/gopkg.in/ldap.v3/bind.go (renamed from vendor/gopkg.in/ldap.v2/bind.go)104
-rw-r--r--vendor/gopkg.in/ldap.v3/client.go (renamed from vendor/gopkg.in/ldap.v2/client.go)1
-rw-r--r--vendor/gopkg.in/ldap.v3/compare.go (renamed from vendor/gopkg.in/ldap.v2/compare.go)20
-rw-r--r--vendor/gopkg.in/ldap.v3/conn.go (renamed from vendor/gopkg.in/ldap.v2/conn.go)98
-rw-r--r--vendor/gopkg.in/ldap.v3/control.go (renamed from vendor/gopkg.in/ldap.v2/control.go)119
-rw-r--r--vendor/gopkg.in/ldap.v3/debug.go (renamed from vendor/gopkg.in/ldap.v2/debug.go)0
-rw-r--r--vendor/gopkg.in/ldap.v3/del.go (renamed from vendor/gopkg.in/ldap.v2/del.go)8
-rw-r--r--vendor/gopkg.in/ldap.v3/dn.go (renamed from vendor/gopkg.in/ldap.v2/dn.go)30
-rw-r--r--vendor/gopkg.in/ldap.v3/doc.go (renamed from vendor/gopkg.in/ldap.v2/doc.go)0
-rw-r--r--vendor/gopkg.in/ldap.v3/error.go234
-rw-r--r--vendor/gopkg.in/ldap.v3/filter.go (renamed from vendor/gopkg.in/ldap.v2/filter.go)4
-rw-r--r--vendor/gopkg.in/ldap.v3/ldap.go (renamed from vendor/gopkg.in/ldap.v2/ldap.go)86
-rw-r--r--vendor/gopkg.in/ldap.v3/moddn.go104
-rw-r--r--vendor/gopkg.in/ldap.v3/modify.go (renamed from vendor/gopkg.in/ldap.v2/modify.go)77
-rw-r--r--vendor/gopkg.in/ldap.v3/passwdmodify.go (renamed from vendor/gopkg.in/ldap.v2/passwdmodify.go)17
-rw-r--r--vendor/gopkg.in/ldap.v3/search.go (renamed from vendor/gopkg.in/ldap.v2/search.go)22
21 files changed, 712 insertions, 424 deletions
diff --git a/vendor/gopkg.in/ldap.v2/atomic_value.go b/vendor/gopkg.in/ldap.v2/atomic_value.go
deleted file mode 100644
index bccf7573e0..0000000000
--- a/vendor/gopkg.in/ldap.v2/atomic_value.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// +build go1.4
-
-package ldap
-
-import (
- "sync/atomic"
-)
-
-// For compilers that support it, we just use the underlying sync/atomic.Value
-// type.
-type atomicValue struct {
- atomic.Value
-}
diff --git a/vendor/gopkg.in/ldap.v2/atomic_value_go13.go b/vendor/gopkg.in/ldap.v2/atomic_value_go13.go
deleted file mode 100644
index 04920bb260..0000000000
--- a/vendor/gopkg.in/ldap.v2/atomic_value_go13.go
+++ /dev/null
@@ -1,28 +0,0 @@
-// +build !go1.4
-
-package ldap
-
-import (
- "sync"
-)
-
-// This is a helper type that emulates the use of the "sync/atomic.Value"
-// struct that's available in Go 1.4 and up.
-type atomicValue struct {
- value interface{}
- lock sync.RWMutex
-}
-
-func (av *atomicValue) Store(val interface{}) {
- av.lock.Lock()
- av.value = val
- av.lock.Unlock()
-}
-
-func (av *atomicValue) Load() interface{} {
- av.lock.RLock()
- ret := av.value
- av.lock.RUnlock()
-
- return ret
-}
diff --git a/vendor/gopkg.in/ldap.v2/error.go b/vendor/gopkg.in/ldap.v2/error.go
deleted file mode 100644
index 4cccb537fd..0000000000
--- a/vendor/gopkg.in/ldap.v2/error.go
+++ /dev/null
@@ -1,155 +0,0 @@
-package ldap
-
-import (
- "fmt"
-
- "gopkg.in/asn1-ber.v1"
-)
-
-// LDAP Result Codes
-const (
- LDAPResultSuccess = 0
- LDAPResultOperationsError = 1
- LDAPResultProtocolError = 2
- LDAPResultTimeLimitExceeded = 3
- LDAPResultSizeLimitExceeded = 4
- LDAPResultCompareFalse = 5
- LDAPResultCompareTrue = 6
- LDAPResultAuthMethodNotSupported = 7
- LDAPResultStrongAuthRequired = 8
- LDAPResultReferral = 10
- LDAPResultAdminLimitExceeded = 11
- LDAPResultUnavailableCriticalExtension = 12
- LDAPResultConfidentialityRequired = 13
- LDAPResultSaslBindInProgress = 14
- LDAPResultNoSuchAttribute = 16
- LDAPResultUndefinedAttributeType = 17
- LDAPResultInappropriateMatching = 18
- LDAPResultConstraintViolation = 19
- LDAPResultAttributeOrValueExists = 20
- LDAPResultInvalidAttributeSyntax = 21
- LDAPResultNoSuchObject = 32
- LDAPResultAliasProblem = 33
- LDAPResultInvalidDNSyntax = 34
- LDAPResultAliasDereferencingProblem = 36
- LDAPResultInappropriateAuthentication = 48
- LDAPResultInvalidCredentials = 49
- LDAPResultInsufficientAccessRights = 50
- LDAPResultBusy = 51
- LDAPResultUnavailable = 52
- LDAPResultUnwillingToPerform = 53
- LDAPResultLoopDetect = 54
- LDAPResultNamingViolation = 64
- LDAPResultObjectClassViolation = 65
- LDAPResultNotAllowedOnNonLeaf = 66
- LDAPResultNotAllowedOnRDN = 67
- LDAPResultEntryAlreadyExists = 68
- LDAPResultObjectClassModsProhibited = 69
- LDAPResultAffectsMultipleDSAs = 71
- LDAPResultOther = 80
-
- ErrorNetwork = 200
- ErrorFilterCompile = 201
- ErrorFilterDecompile = 202
- ErrorDebugging = 203
- ErrorUnexpectedMessage = 204
- ErrorUnexpectedResponse = 205
-)
-
-// LDAPResultCodeMap contains string descriptions for LDAP error codes
-var LDAPResultCodeMap = map[uint8]string{
- LDAPResultSuccess: "Success",
- LDAPResultOperationsError: "Operations Error",
- LDAPResultProtocolError: "Protocol Error",
- LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
- LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
- LDAPResultCompareFalse: "Compare False",
- LDAPResultCompareTrue: "Compare True",
- LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
- LDAPResultStrongAuthRequired: "Strong Auth Required",
- LDAPResultReferral: "Referral",
- LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
- LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
- LDAPResultConfidentialityRequired: "Confidentiality Required",
- LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
- LDAPResultNoSuchAttribute: "No Such Attribute",
- LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
- LDAPResultInappropriateMatching: "Inappropriate Matching",
- LDAPResultConstraintViolation: "Constraint Violation",
- LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
- LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
- LDAPResultNoSuchObject: "No Such Object",
- LDAPResultAliasProblem: "Alias Problem",
- LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
- LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
- LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
- LDAPResultInvalidCredentials: "Invalid Credentials",
- LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
- LDAPResultBusy: "Busy",
- LDAPResultUnavailable: "Unavailable",
- LDAPResultUnwillingToPerform: "Unwilling To Perform",
- LDAPResultLoopDetect: "Loop Detect",
- LDAPResultNamingViolation: "Naming Violation",
- LDAPResultObjectClassViolation: "Object Class Violation",
- LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
- LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
- LDAPResultEntryAlreadyExists: "Entry Already Exists",
- LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
- LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
- LDAPResultOther: "Other",
-
- ErrorNetwork: "Network Error",
- ErrorFilterCompile: "Filter Compile Error",
- ErrorFilterDecompile: "Filter Decompile Error",
- ErrorDebugging: "Debugging Error",
- ErrorUnexpectedMessage: "Unexpected Message",
- ErrorUnexpectedResponse: "Unexpected Response",
-}
-
-func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
- if packet == nil {
- return ErrorUnexpectedResponse, "Empty packet"
- } else if len(packet.Children) >= 2 {
- response := packet.Children[1]
- if response == nil {
- return ErrorUnexpectedResponse, "Empty response in packet"
- }
- if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
- // Children[1].Children[2] is the diagnosticMessage which is guaranteed to exist as seen here: https://tools.ietf.org/html/rfc4511#section-4.1.9
- return uint8(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
- }
- }
-
- return ErrorNetwork, "Invalid packet format"
-}
-
-// Error holds LDAP error information
-type Error struct {
- // Err is the underlying error
- Err error
- // ResultCode is the LDAP error code
- ResultCode uint8
-}
-
-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
- }
-
- serverError, ok := err.(*Error)
- if !ok {
- return false
- }
-
- return serverError.ResultCode == desiredResultCode
-}
diff --git a/vendor/gopkg.in/ldap.v2/LICENSE b/vendor/gopkg.in/ldap.v3/LICENSE
index 6c0ed4b387..6c0ed4b387 100644
--- a/vendor/gopkg.in/ldap.v2/LICENSE
+++ b/vendor/gopkg.in/ldap.v3/LICENSE
diff --git a/vendor/gopkg.in/ldap.v2/add.go b/vendor/gopkg.in/ldap.v3/add.go
index 0e5f6cdba1..19bce1b75b 100644
--- a/vendor/gopkg.in/ldap.v2/add.go
+++ b/vendor/gopkg.in/ldap.v3/add.go
@@ -41,6 +41,8 @@ type AddRequest struct {
DN string
// Attributes list the attributes of the new entry
Attributes []Attribute
+ // Controls hold optional controls to send with the request
+ Controls []Control
}
func (a AddRequest) encode() *ber.Packet {
@@ -60,9 +62,10 @@ func (a *AddRequest) Attribute(attrType string, attrVals []string) {
}
// NewAddRequest returns an AddRequest for the given DN, with no attributes
-func NewAddRequest(dn string) *AddRequest {
+func NewAddRequest(dn string, controls []Control) *AddRequest {
return &AddRequest{
- DN: dn,
+ DN: dn,
+ Controls: controls,
}
}
@@ -72,6 +75,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(addRequest.encode())
+ if len(addRequest.Controls) > 0 {
+ packet.AppendChild(encodeControls(addRequest.Controls))
+ }
l.Debug.PrintPacket(packet)
@@ -100,9 +106,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
}
if packet.Children[1].Tag == ApplicationAddResponse {
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return NewError(resultCode, errors.New(resultDescription))
+ err := GetLDAPError(packet)
+ if err != nil {
+ return err
}
} else {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
diff --git a/vendor/gopkg.in/ldap.v2/bind.go b/vendor/gopkg.in/ldap.v3/bind.go
index 26b3cc7270..59c3f5ef59 100644
--- a/vendor/gopkg.in/ldap.v2/bind.go
+++ b/vendor/gopkg.in/ldap.v3/bind.go
@@ -1,11 +1,8 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
package ldap
import (
"errors"
+ "fmt"
"gopkg.in/asn1-ber.v1"
)
@@ -18,6 +15,9 @@ type SimpleBindRequest struct {
Password string
// Controls are optional controls to send with the bind request
Controls []Control
+ // AllowEmptyPassword sets whether the client allows binding with an empty password
+ // (normally used for unauthenticated bind).
+ AllowEmptyPassword bool
}
// SimpleBindResult contains the response from the server
@@ -28,9 +28,10 @@ type SimpleBindResult struct {
// NewSimpleBindRequest returns a bind request
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
return &SimpleBindRequest{
- Username: username,
- Password: password,
- Controls: controls,
+ Username: username,
+ Password: password,
+ Controls: controls,
+ AllowEmptyPassword: false,
}
}
@@ -40,17 +41,22 @@ func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, bindRequest.Username, "User Name"))
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, bindRequest.Password, "Password"))
- request.AppendChild(encodeControls(bindRequest.Controls))
-
return request
}
// SimpleBind performs the simple bind operation defined in the given request
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
+ if simpleBindRequest.Password == "" && !simpleBindRequest.AllowEmptyPassword {
+ return nil, NewError(ErrorEmptyPassword, errors.New("ldap: empty password not allowed by the client"))
+ }
+
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
encodedBindRequest := simpleBindRequest.encode()
packet.AppendChild(encodedBindRequest)
+ if len(simpleBindRequest.Controls) > 0 {
+ packet.AppendChild(encodeControls(simpleBindRequest.Controls))
+ }
if l.Debug {
ber.PrintPacket(packet)
@@ -73,7 +79,7 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
}
if l.Debug {
- if err := addLDAPDescriptions(packet); err != nil {
+ if err = addLDAPDescriptions(packet); err != nil {
return nil, err
}
ber.PrintPacket(packet)
@@ -85,59 +91,45 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
if len(packet.Children) == 3 {
for _, child := range packet.Children[2].Children {
- result.Controls = append(result.Controls, DecodeControl(child))
+ decodedChild, decodeErr := DecodeControl(child)
+ if decodeErr != nil {
+ return nil, fmt.Errorf("failed to decode child control: %s", decodeErr)
+ }
+ result.Controls = append(result.Controls, decodedChild)
}
}
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return result, NewError(resultCode, errors.New(resultDescription))
- }
-
- return result, nil
+ err = GetLDAPError(packet)
+ return result, err
}
-// Bind performs a bind with the given username and password
+// Bind performs a bind with the given username and password.
+//
+// It does not allow unauthenticated bind (i.e. empty password). Use the UnauthenticatedBind method
+// for that.
func (l *Conn) Bind(username, password string) error {
- packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
- 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"))
- bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, password, "Password"))
- packet.AppendChild(bindRequest)
-
- if l.Debug {
- ber.PrintPacket(packet)
- }
-
- msgCtx, err := l.sendMessage(packet)
- if err != nil {
- return err
- }
- defer l.finishMessage(msgCtx)
-
- packetResponse, ok := <-msgCtx.responses
- if !ok {
- return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
- }
- packet, err = packetResponse.ReadPacket()
- l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
- if err != nil {
- return err
- }
-
- if l.Debug {
- if err := addLDAPDescriptions(packet); err != nil {
- return err
- }
- ber.PrintPacket(packet)
+ req := &SimpleBindRequest{
+ Username: username,
+ Password: password,
+ AllowEmptyPassword: false,
}
+ _, err := l.SimpleBind(req)
+ return err
+}
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return NewError(resultCode, errors.New(resultDescription))
+// UnauthenticatedBind performs an unauthenticated bind.
+//
+// A username may be provided for trace (e.g. logging) purpose only, but it is normally not
+// authenticated or otherwise validated by the LDAP server.
+//
+// See https://tools.ietf.org/html/rfc4513#section-5.1.2 .
+// See https://tools.ietf.org/html/rfc4513#section-6.3.1 .
+func (l *Conn) UnauthenticatedBind(username string) error {
+ req := &SimpleBindRequest{
+ Username: username,
+ Password: "",
+ AllowEmptyPassword: true,
}
-
- return nil
+ _, err := l.SimpleBind(req)
+ return err
}
diff --git a/vendor/gopkg.in/ldap.v2/client.go b/vendor/gopkg.in/ldap.v3/client.go
index 055b27b5fc..c7f41f6f90 100644
--- a/vendor/gopkg.in/ldap.v2/client.go
+++ b/vendor/gopkg.in/ldap.v3/client.go
@@ -18,6 +18,7 @@ type Client interface {
Add(addRequest *AddRequest) error
Del(delRequest *DelRequest) error
Modify(modifyRequest *ModifyRequest) error
+ ModifyDN(modifyDNRequest *ModifyDNRequest) error
Compare(dn, attribute, value string) (bool, error)
PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
diff --git a/vendor/gopkg.in/ldap.v2/compare.go b/vendor/gopkg.in/ldap.v3/compare.go
index cc6d2af5e5..5b5013cbed 100644
--- a/vendor/gopkg.in/ldap.v2/compare.go
+++ b/vendor/gopkg.in/ldap.v3/compare.go
@@ -1,7 +1,3 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
// File contains Compare functionality
//
// https://tools.ietf.org/html/rfc4511
@@ -41,7 +37,7 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
ava := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "AttributeValueAssertion")
ava.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "AttributeDesc"))
- ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagOctetString, value, "AssertionValue"))
+ ava.AppendChild(ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "AssertionValue"))
request.AppendChild(ava)
packet.AppendChild(request)
@@ -72,14 +68,16 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
}
if packet.Children[1].Tag == ApplicationCompareResponse {
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode == LDAPResultCompareTrue {
+ err := GetLDAPError(packet)
+
+ switch {
+ case IsErrorWithCode(err, LDAPResultCompareTrue):
return true, nil
- } else if resultCode == LDAPResultCompareFalse {
+ case IsErrorWithCode(err, LDAPResultCompareFalse):
return false, nil
- } else {
- return false, NewError(resultCode, errors.New(resultDescription))
+ default:
+ return false, err
}
}
- return false, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag)
+ return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)
}
diff --git a/vendor/gopkg.in/ldap.v2/conn.go b/vendor/gopkg.in/ldap.v3/conn.go
index eb28eb4726..c20471fc20 100644
--- a/vendor/gopkg.in/ldap.v2/conn.go
+++ b/vendor/gopkg.in/ldap.v3/conn.go
@@ -1,7 +1,3 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
package ldap
import (
@@ -10,6 +6,7 @@ import (
"fmt"
"log"
"net"
+ "net/url"
"sync"
"sync/atomic"
"time"
@@ -30,6 +27,13 @@ const (
MessageTimeout = 4
)
+const (
+ // DefaultLdapPort default ldap port for pure TCP connection
+ DefaultLdapPort = "389"
+ // DefaultLdapsPort default ldap port for SSL connection
+ DefaultLdapsPort = "636"
+)
+
// PacketResponse contains the packet or error encountered reading a response
type PacketResponse struct {
// Packet is the packet read from the server
@@ -81,10 +85,13 @@ const (
// Conn represents an LDAP Connection
type Conn struct {
+ // requestTimeout is loaded atomically
+ // so we need to ensure 64-bit alignment on 32-bit platforms.
+ requestTimeout int64
conn net.Conn
isTLS bool
closing uint32
- closeErr atomicValue
+ closeErr atomic.Value
isStartingTLS bool
Debug debugging
chanConfirm chan struct{}
@@ -94,7 +101,6 @@ type Conn struct {
wgClose sync.WaitGroup
outstandingRequests uint
messageMutex sync.Mutex
- requestTimeout int64
}
var _ Client = &Conn{}
@@ -121,22 +127,51 @@ func Dial(network, addr string) (*Conn, error) {
// DialTLS connects to the given address on the given network using tls.Dial
// and then returns a new Conn for the connection.
func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
- dc, err := net.DialTimeout(network, addr, DefaultTimeout)
+ c, err := tls.DialWithDialer(&net.Dialer{Timeout: DefaultTimeout}, network, addr, config)
if err != nil {
return nil, NewError(ErrorNetwork, err)
}
- c := tls.Client(dc, config)
- err = c.Handshake()
- if err != nil {
- // Handshake error, close the established connection before we return an error
- dc.Close()
- return nil, NewError(ErrorNetwork, err)
- }
conn := NewConn(c, true)
conn.Start()
return conn, nil
}
+// DialURL connects to the given ldap URL vie TCP using tls.Dial or net.Dial if ldaps://
+// or ldap:// specified as protocol. On success a new Conn for the connection
+// is returned.
+func DialURL(addr string) (*Conn, error) {
+
+ lurl, err := url.Parse(addr)
+ if err != nil {
+ return nil, NewError(ErrorNetwork, err)
+ }
+
+ host, port, err := net.SplitHostPort(lurl.Host)
+ if err != nil {
+ // we asume that error is due to missing port
+ host = lurl.Host
+ port = ""
+ }
+
+ switch lurl.Scheme {
+ case "ldap":
+ if port == "" {
+ port = DefaultLdapPort
+ }
+ return Dial("tcp", net.JoinHostPort(host, port))
+ case "ldaps":
+ if port == "" {
+ port = DefaultLdapsPort
+ }
+ tlsConf := &tls.Config{
+ ServerName: host,
+ }
+ return DialTLS("tcp", net.JoinHostPort(host, port), tlsConf)
+ }
+
+ return nil, NewError(ErrorNetwork, fmt.Errorf("Unknown scheme '%s'", lurl.Scheme))
+}
+
// NewConn returns a new Conn using conn for network I/O.
func NewConn(conn net.Conn, isTLS bool) *Conn {
return &Conn{
@@ -157,8 +192,8 @@ func (l *Conn) Start() {
l.wgClose.Add(1)
}
-// isClosing returns whether or not we're currently closing.
-func (l *Conn) isClosing() bool {
+// IsClosing returns whether or not we're currently closing.
+func (l *Conn) IsClosing() bool {
return atomic.LoadUint32(&l.closing) == 1
}
@@ -242,30 +277,41 @@ func (l *Conn) StartTLS(config *tls.Config) error {
ber.PrintPacket(packet)
}
- if resultCode, message := getLDAPResultCode(packet); resultCode == LDAPResultSuccess {
+ if err := GetLDAPError(packet); err == nil {
conn := tls.Client(l.conn, config)
- if err := conn.Handshake(); err != nil {
+ if connErr := conn.Handshake(); connErr != nil {
l.Close()
- return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", err))
+ return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", connErr))
}
l.isTLS = true
l.conn = conn
} else {
- return NewError(resultCode, fmt.Errorf("ldap: cannot StartTLS (%s)", message))
+ return err
}
go l.reader()
return nil
}
+// TLSConnectionState returns the client's TLS connection state.
+// The return values are their zero values if StartTLS did
+// not succeed.
+func (l *Conn) TLSConnectionState() (state tls.ConnectionState, ok bool) {
+ tc, ok := l.conn.(*tls.Conn)
+ if !ok {
+ return
+ }
+ return tc.ConnectionState(), true
+}
+
func (l *Conn) sendMessage(packet *ber.Packet) (*messageContext, error) {
return l.sendMessageWithFlags(packet, 0)
}
func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags) (*messageContext, error) {
- if l.isClosing() {
+ if l.IsClosing() {
return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
}
l.messageMutex.Lock()
@@ -304,7 +350,7 @@ func (l *Conn) sendMessageWithFlags(packet *ber.Packet, flags sendMessageFlags)
func (l *Conn) finishMessage(msgCtx *messageContext) {
close(msgCtx.done)
- if l.isClosing() {
+ if l.IsClosing() {
return
}
@@ -325,7 +371,7 @@ func (l *Conn) finishMessage(msgCtx *messageContext) {
func (l *Conn) sendProcessMessage(message *messagePacket) bool {
l.messageMutex.Lock()
defer l.messageMutex.Unlock()
- if l.isClosing() {
+ if l.IsClosing() {
return false
}
l.chanMessage <- message
@@ -340,7 +386,7 @@ func (l *Conn) processMessages() {
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.Load() != nil {
+ if l.IsClosing() && l.closeErr.Load() != nil {
msgCtx.sendResponse(&PacketResponse{Error: l.closeErr.Load().(error)})
}
l.Debug.Printf("Closing channel for MessageID %d", messageID)
@@ -400,7 +446,7 @@ func (l *Conn) processMessages() {
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())
+ log.Printf("Received unexpected message %d, %v", message.MessageID, l.IsClosing())
ber.PrintPacket(message.Packet)
}
case MessageTimeout:
@@ -442,7 +488,7 @@ func (l *Conn) reader() {
packet, err := ber.ReadPacket(l.conn)
if err != nil {
// A read error is expected here if we are closing the connection...
- if !l.isClosing() {
+ if !l.IsClosing() {
l.closeErr.Store(fmt.Errorf("unable to read LDAP response packet: %s", err))
l.Debug.Printf("reader error: %s", err.Error())
}
diff --git a/vendor/gopkg.in/ldap.v2/control.go b/vendor/gopkg.in/ldap.v3/control.go
index 342f325ca6..4439a865d9 100644
--- a/vendor/gopkg.in/ldap.v2/control.go
+++ b/vendor/gopkg.in/ldap.v3/control.go
@@ -1,7 +1,3 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
package ldap
import (
@@ -22,13 +18,20 @@ const (
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"
+
+ // ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
+ ControlTypeMicrosoftNotification = "1.2.840.113556.1.4.528"
+ // ControlTypeMicrosoftShowDeleted - https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx
+ ControlTypeMicrosoftShowDeleted = "1.2.840.113556.1.4.417"
)
// ControlTypeMap maps controls to text descriptions
var ControlTypeMap = map[string]string{
- ControlTypePaging: "Paging",
- ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
- ControlTypeManageDsaIT: "Manage DSA IT",
+ ControlTypePaging: "Paging",
+ ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
+ ControlTypeManageDsaIT: "Manage DSA IT",
+ ControlTypeMicrosoftNotification: "Change Notification - Microsoft",
+ ControlTypeMicrosoftShowDeleted: "Show Deleted Objects - Microsoft",
}
// Control defines an interface controls provide to encode and describe themselves
@@ -242,6 +245,64 @@ func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
return &ControlManageDsaIT{Criticality: Criticality}
}
+// ControlMicrosoftNotification implements the control described in https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx
+type ControlMicrosoftNotification struct{}
+
+// GetControlType returns the OID
+func (c *ControlMicrosoftNotification) GetControlType() string {
+ return ControlTypeMicrosoftNotification
+}
+
+// Encode returns the ber packet representation
+func (c *ControlMicrosoftNotification) Encode() *ber.Packet {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftNotification, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftNotification]+")"))
+
+ return packet
+}
+
+// String returns a human-readable description
+func (c *ControlMicrosoftNotification) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q)",
+ ControlTypeMap[ControlTypeMicrosoftNotification],
+ ControlTypeMicrosoftNotification)
+}
+
+// NewControlMicrosoftNotification returns a ControlMicrosoftNotification control
+func NewControlMicrosoftNotification() *ControlMicrosoftNotification {
+ return &ControlMicrosoftNotification{}
+}
+
+// ControlMicrosoftShowDeleted implements the control described in https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx
+type ControlMicrosoftShowDeleted struct{}
+
+// GetControlType returns the OID
+func (c *ControlMicrosoftShowDeleted) GetControlType() string {
+ return ControlTypeMicrosoftShowDeleted
+}
+
+// Encode returns the ber packet representation
+func (c *ControlMicrosoftShowDeleted) Encode() *ber.Packet {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
+ packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeMicrosoftShowDeleted, "Control Type ("+ControlTypeMap[ControlTypeMicrosoftShowDeleted]+")"))
+
+ return packet
+}
+
+// String returns a human-readable description
+func (c *ControlMicrosoftShowDeleted) String() string {
+ return fmt.Sprintf(
+ "Control Type: %s (%q)",
+ ControlTypeMap[ControlTypeMicrosoftShowDeleted],
+ ControlTypeMicrosoftShowDeleted)
+}
+
+// NewControlMicrosoftShowDeleted returns a ControlMicrosoftShowDeleted control
+func NewControlMicrosoftShowDeleted() *ControlMicrosoftShowDeleted {
+ return &ControlMicrosoftShowDeleted{}
+}
+
// 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 {
@@ -253,7 +314,7 @@ func FindControl(controls []Control, controlType string) Control {
}
// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made
-func DecodeControl(packet *ber.Packet) Control {
+func DecodeControl(packet *ber.Packet) (Control, error) {
var (
ControlType = ""
Criticality = false
@@ -263,7 +324,7 @@ func DecodeControl(packet *ber.Packet) Control {
switch len(packet.Children) {
case 0:
// at least one child is required for control type
- return nil
+ return nil, fmt.Errorf("at least one child is required for control type")
case 1:
// just type, no criticality or value
@@ -296,17 +357,20 @@ func DecodeControl(packet *ber.Packet) Control {
default:
// more than 3 children is invalid
- return nil
+ return nil, fmt.Errorf("more than 3 children is invalid for controls")
}
switch ControlType {
case ControlTypeManageDsaIT:
- return NewControlManageDsaIT(Criticality)
+ return NewControlManageDsaIT(Criticality), nil
case ControlTypePaging:
value.Description += " (Paging)"
c := new(ControlPaging)
if value.Value != nil {
- valueChildren := ber.DecodePacket(value.Data.Bytes())
+ valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode data bytes: %s", err)
+ }
value.Data.Truncate(0)
value.Value = nil
value.AppendChild(valueChildren)
@@ -318,12 +382,15 @@ func DecodeControl(packet *ber.Packet) Control {
c.PagingSize = uint32(value.Children[0].Value.(int64))
c.Cookie = value.Children[1].Data.Bytes()
value.Children[1].Value = c.Cookie
- return c
+ return c, nil
case ControlTypeBeheraPasswordPolicy:
value.Description += " (Password Policy - Behera)"
c := NewControlBeheraPasswordPolicy()
if value.Value != nil {
- valueChildren := ber.DecodePacket(value.Data.Bytes())
+ valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode data bytes: %s", err)
+ }
value.Data.Truncate(0)
value.Value = nil
value.AppendChild(valueChildren)
@@ -335,7 +402,10 @@ func DecodeControl(packet *ber.Packet) Control {
if child.Tag == 0 {
//Warning
warningPacket := child.Children[0]
- packet := ber.DecodePacket(warningPacket.Data.Bytes())
+ packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode data bytes: %s", err)
+ }
val, ok := packet.Value.(int64)
if ok {
if warningPacket.Tag == 0 {
@@ -350,7 +420,10 @@ func DecodeControl(packet *ber.Packet) Control {
}
} else if child.Tag == 1 {
// Error
- packet := ber.DecodePacket(child.Data.Bytes())
+ packet, err := ber.DecodePacketErr(child.Data.Bytes())
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode data bytes: %s", err)
+ }
val, ok := packet.Value.(int8)
if !ok {
// what to do?
@@ -361,22 +434,26 @@ func DecodeControl(packet *ber.Packet) Control {
c.ErrorString = BeheraPasswordPolicyErrorMap[c.Error]
}
}
- return c
+ return c, nil
case ControlTypeVChuPasswordMustChange:
c := &ControlVChuPasswordMustChange{MustChange: true}
- return c
+ return c, nil
case ControlTypeVChuPasswordWarning:
c := &ControlVChuPasswordWarning{Expire: -1}
expireStr := ber.DecodeString(value.Data.Bytes())
expire, err := strconv.ParseInt(expireStr, 10, 64)
if err != nil {
- return nil
+ return nil, fmt.Errorf("failed to parse value as int: %s", err)
}
c.Expire = expire
value.Value = c.Expire
- return c
+ return c, nil
+ case ControlTypeMicrosoftNotification:
+ return NewControlMicrosoftNotification(), nil
+ case ControlTypeMicrosoftShowDeleted:
+ return NewControlMicrosoftShowDeleted(), nil
default:
c := new(ControlString)
c.ControlType = ControlType
@@ -384,7 +461,7 @@ func DecodeControl(packet *ber.Packet) Control {
if value != nil {
c.ControlValue = value.Value.(string)
}
- return c
+ return c, nil
}
}
diff --git a/vendor/gopkg.in/ldap.v2/debug.go b/vendor/gopkg.in/ldap.v3/debug.go
index 7279fc2518..7279fc2518 100644
--- a/vendor/gopkg.in/ldap.v2/debug.go
+++ b/vendor/gopkg.in/ldap.v3/debug.go
diff --git a/vendor/gopkg.in/ldap.v2/del.go b/vendor/gopkg.in/ldap.v3/del.go
index 4fd63dc3f2..6f78beb18e 100644
--- a/vendor/gopkg.in/ldap.v2/del.go
+++ b/vendor/gopkg.in/ldap.v3/del.go
@@ -40,7 +40,7 @@ func (l *Conn) Del(delRequest *DelRequest) error {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(delRequest.encode())
- if delRequest.Controls != nil {
+ if len(delRequest.Controls) > 0 {
packet.AppendChild(encodeControls(delRequest.Controls))
}
@@ -71,9 +71,9 @@ func (l *Conn) Del(delRequest *DelRequest) error {
}
if packet.Children[1].Tag == ApplicationDelResponse {
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return NewError(resultCode, errors.New(resultDescription))
+ err := GetLDAPError(packet)
+ if err != nil {
+ return err
}
} else {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
diff --git a/vendor/gopkg.in/ldap.v2/dn.go b/vendor/gopkg.in/ldap.v3/dn.go
index 34e9023af9..f89e73a9a6 100644
--- a/vendor/gopkg.in/ldap.v2/dn.go
+++ b/vendor/gopkg.in/ldap.v3/dn.go
@@ -1,7 +1,3 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
// File contains DN parsing functionality
//
// https://tools.ietf.org/html/rfc4514
@@ -94,7 +90,8 @@ func ParseDN(str string) (*DN, error) {
for i := 0; i < len(str); i++ {
char := str[i]
- if escaping {
+ switch {
+ case escaping:
unescapedTrailingSpaces = 0
escaping = false
switch char {
@@ -104,22 +101,22 @@ func ParseDN(str string) (*DN, error) {
}
// Not a special character, assume hex encoded octet
if len(str) == i+1 {
- return nil, errors.New("Got corrupted escaped character")
+ return nil, errors.New("got corrupted escaped character")
}
dst := []byte{0}
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
if err != nil {
- return nil, fmt.Errorf("Failed to decode escaped character: %s", err)
+ return nil, fmt.Errorf("failed to decode escaped character: %s", err)
} else if n != 1 {
- return nil, fmt.Errorf("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++
- } else if char == '\\' {
+ case char == '\\':
unescapedTrailingSpaces = 0
escaping = true
- } else if char == '=' {
+ case char == '=':
attribute.Type = stringFromBuffer()
// Special case: If the first character in the value is # the
// following data is BER encoded so we can just fast forward
@@ -135,13 +132,16 @@ func ParseDN(str string) (*DN, error) {
}
rawBER, err := enchex.DecodeString(data)
if err != nil {
- return nil, fmt.Errorf("Failed to decode BER encoding: %s", err)
+ return nil, fmt.Errorf("failed to decode BER encoding: %s", err)
+ }
+ packet, err := ber.DecodePacketErr(rawBER)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode BER packet: %s", err)
}
- packet := ber.DecodePacket(rawBER)
buffer.WriteString(packet.Data.String())
i += len(data) - 1
}
- } else if char == ',' || char == '+' {
+ case char == ',' || char == '+':
// We're done with this RDN or value, push it
if len(attribute.Type) == 0 {
return nil, errors.New("incomplete type, value pair")
@@ -154,10 +154,10 @@ func ParseDN(str string) (*DN, error) {
rdn = new(RelativeDN)
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
}
- } else if char == ' ' && buffer.Len() == 0 {
+ case char == ' ' && buffer.Len() == 0:
// ignore unescaped leading spaces
continue
- } else {
+ default:
if char == ' ' {
// Track unescaped spaces in case they are trailing and we need to remove them
unescapedTrailingSpaces++
diff --git a/vendor/gopkg.in/ldap.v2/doc.go b/vendor/gopkg.in/ldap.v3/doc.go
index f20d39bc99..f20d39bc99 100644
--- a/vendor/gopkg.in/ldap.v2/doc.go
+++ b/vendor/gopkg.in/ldap.v3/doc.go
diff --git a/vendor/gopkg.in/ldap.v3/error.go b/vendor/gopkg.in/ldap.v3/error.go
new file mode 100644
index 0000000000..50ed8ab3fe
--- /dev/null
+++ b/vendor/gopkg.in/ldap.v3/error.go
@@ -0,0 +1,234 @@
+package ldap
+
+import (
+ "fmt"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+// LDAP Result Codes
+const (
+ LDAPResultSuccess = 0
+ LDAPResultOperationsError = 1
+ LDAPResultProtocolError = 2
+ LDAPResultTimeLimitExceeded = 3
+ LDAPResultSizeLimitExceeded = 4
+ LDAPResultCompareFalse = 5
+ LDAPResultCompareTrue = 6
+ LDAPResultAuthMethodNotSupported = 7
+ LDAPResultStrongAuthRequired = 8
+ LDAPResultReferral = 10
+ LDAPResultAdminLimitExceeded = 11
+ LDAPResultUnavailableCriticalExtension = 12
+ LDAPResultConfidentialityRequired = 13
+ LDAPResultSaslBindInProgress = 14
+ LDAPResultNoSuchAttribute = 16
+ LDAPResultUndefinedAttributeType = 17
+ LDAPResultInappropriateMatching = 18
+ LDAPResultConstraintViolation = 19
+ LDAPResultAttributeOrValueExists = 20
+ LDAPResultInvalidAttributeSyntax = 21
+ LDAPResultNoSuchObject = 32
+ LDAPResultAliasProblem = 33
+ LDAPResultInvalidDNSyntax = 34
+ LDAPResultIsLeaf = 35
+ LDAPResultAliasDereferencingProblem = 36
+ LDAPResultInappropriateAuthentication = 48
+ LDAPResultInvalidCredentials = 49
+ LDAPResultInsufficientAccessRights = 50
+ LDAPResultBusy = 51
+ LDAPResultUnavailable = 52
+ LDAPResultUnwillingToPerform = 53
+ LDAPResultLoopDetect = 54
+ LDAPResultSortControlMissing = 60
+ LDAPResultOffsetRangeError = 61
+ LDAPResultNamingViolation = 64
+ LDAPResultObjectClassViolation = 65
+ LDAPResultNotAllowedOnNonLeaf = 66
+ LDAPResultNotAllowedOnRDN = 67
+ LDAPResultEntryAlreadyExists = 68
+ LDAPResultObjectClassModsProhibited = 69
+ LDAPResultResultsTooLarge = 70
+ LDAPResultAffectsMultipleDSAs = 71
+ LDAPResultVirtualListViewErrorOrControlError = 76
+ LDAPResultOther = 80
+ LDAPResultServerDown = 81
+ LDAPResultLocalError = 82
+ LDAPResultEncodingError = 83
+ LDAPResultDecodingError = 84
+ LDAPResultTimeout = 85
+ LDAPResultAuthUnknown = 86
+ LDAPResultFilterError = 87
+ LDAPResultUserCanceled = 88
+ LDAPResultParamError = 89
+ LDAPResultNoMemory = 90
+ LDAPResultConnectError = 91
+ LDAPResultNotSupported = 92
+ LDAPResultControlNotFound = 93
+ LDAPResultNoResultsReturned = 94
+ LDAPResultMoreResultsToReturn = 95
+ LDAPResultClientLoop = 96
+ LDAPResultReferralLimitExceeded = 97
+ LDAPResultInvalidResponse = 100
+ LDAPResultAmbiguousResponse = 101
+ LDAPResultTLSNotSupported = 112
+ LDAPResultIntermediateResponse = 113
+ LDAPResultUnknownType = 114
+ LDAPResultCanceled = 118
+ LDAPResultNoSuchOperation = 119
+ LDAPResultTooLate = 120
+ LDAPResultCannotCancel = 121
+ LDAPResultAssertionFailed = 122
+ LDAPResultAuthorizationDenied = 123
+ LDAPResultSyncRefreshRequired = 4096
+
+ ErrorNetwork = 200
+ ErrorFilterCompile = 201
+ ErrorFilterDecompile = 202
+ ErrorDebugging = 203
+ ErrorUnexpectedMessage = 204
+ ErrorUnexpectedResponse = 205
+ ErrorEmptyPassword = 206
+)
+
+// LDAPResultCodeMap contains string descriptions for LDAP error codes
+var LDAPResultCodeMap = map[uint16]string{
+ LDAPResultSuccess: "Success",
+ LDAPResultOperationsError: "Operations Error",
+ LDAPResultProtocolError: "Protocol Error",
+ LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
+ LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
+ LDAPResultCompareFalse: "Compare False",
+ LDAPResultCompareTrue: "Compare True",
+ LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
+ LDAPResultStrongAuthRequired: "Strong Auth Required",
+ LDAPResultReferral: "Referral",
+ LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
+ LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
+ LDAPResultConfidentialityRequired: "Confidentiality Required",
+ LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
+ LDAPResultNoSuchAttribute: "No Such Attribute",
+ LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
+ LDAPResultInappropriateMatching: "Inappropriate Matching",
+ LDAPResultConstraintViolation: "Constraint Violation",
+ LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
+ LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
+ LDAPResultNoSuchObject: "No Such Object",
+ LDAPResultAliasProblem: "Alias Problem",
+ LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
+ LDAPResultIsLeaf: "Is Leaf",
+ LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
+ LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
+ LDAPResultInvalidCredentials: "Invalid Credentials",
+ LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
+ LDAPResultBusy: "Busy",
+ LDAPResultUnavailable: "Unavailable",
+ LDAPResultUnwillingToPerform: "Unwilling To Perform",
+ LDAPResultLoopDetect: "Loop Detect",
+ LDAPResultSortControlMissing: "Sort Control Missing",
+ LDAPResultOffsetRangeError: "Result Offset Range Error",
+ LDAPResultNamingViolation: "Naming Violation",
+ LDAPResultObjectClassViolation: "Object Class Violation",
+ LDAPResultResultsTooLarge: "Results Too Large",
+ LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
+ LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
+ LDAPResultEntryAlreadyExists: "Entry Already Exists",
+ LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
+ LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
+ LDAPResultVirtualListViewErrorOrControlError: "Failed because of a problem related to the virtual list view",
+ LDAPResultOther: "Other",
+ LDAPResultServerDown: "Cannot establish a connection",
+ LDAPResultLocalError: "An error occurred",
+ LDAPResultEncodingError: "LDAP encountered an error while encoding",
+ LDAPResultDecodingError: "LDAP encountered an error while decoding",
+ LDAPResultTimeout: "LDAP timeout while waiting for a response from the server",
+ LDAPResultAuthUnknown: "The auth method requested in a bind request is unknown",
+ LDAPResultFilterError: "An error occurred while encoding the given search filter",
+ LDAPResultUserCanceled: "The user canceled the operation",
+ LDAPResultParamError: "An invalid parameter was specified",
+ LDAPResultNoMemory: "Out of memory error",
+ LDAPResultConnectError: "A connection to the server could not be established",
+ LDAPResultNotSupported: "An attempt has been made to use a feature not supported LDAP",
+ LDAPResultControlNotFound: "The controls required to perform the requested operation were not found",
+ LDAPResultNoResultsReturned: "No results were returned from the server",
+ LDAPResultMoreResultsToReturn: "There are more results in the chain of results",
+ LDAPResultClientLoop: "A loop has been detected. For example when following referrals",
+ LDAPResultReferralLimitExceeded: "The referral hop limit has been exceeded",
+ LDAPResultCanceled: "Operation was canceled",
+ LDAPResultNoSuchOperation: "Server has no knowledge of the operation requested for cancellation",
+ LDAPResultTooLate: "Too late to cancel the outstanding operation",
+ LDAPResultCannotCancel: "The identified operation does not support cancellation or the cancel operation cannot be performed",
+ LDAPResultAssertionFailed: "An assertion control given in the LDAP operation evaluated to false causing the operation to not be performed",
+ LDAPResultSyncRefreshRequired: "Refresh Required",
+ LDAPResultInvalidResponse: "Invalid Response",
+ LDAPResultAmbiguousResponse: "Ambiguous Response",
+ LDAPResultTLSNotSupported: "Tls Not Supported",
+ LDAPResultIntermediateResponse: "Intermediate Response",
+ LDAPResultUnknownType: "Unknown Type",
+ LDAPResultAuthorizationDenied: "Authorization Denied",
+
+ ErrorNetwork: "Network Error",
+ ErrorFilterCompile: "Filter Compile Error",
+ ErrorFilterDecompile: "Filter Decompile Error",
+ ErrorDebugging: "Debugging Error",
+ ErrorUnexpectedMessage: "Unexpected Message",
+ ErrorUnexpectedResponse: "Unexpected Response",
+ ErrorEmptyPassword: "Empty password not allowed by the client",
+}
+
+// Error holds LDAP error information
+type Error struct {
+ // Err is the underlying error
+ Err error
+ // ResultCode is the LDAP error code
+ ResultCode uint16
+ // MatchedDN is the matchedDN returned if any
+ MatchedDN string
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
+}
+
+// GetLDAPError creates an Error out of a BER packet representing a LDAPResult
+// The return is an error object. It can be casted to a Error structure.
+// This function returns nil if resultCode in the LDAPResult sequence is success(0).
+func GetLDAPError(packet *ber.Packet) error {
+ if packet == nil {
+ return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")}
+ } else if len(packet.Children) >= 2 {
+ response := packet.Children[1]
+ if response == nil {
+ return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
+ }
+ if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
+ resultCode := uint16(response.Children[0].Value.(int64))
+ if resultCode == 0 { // No error
+ return nil
+ }
+ return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
+ Err: fmt.Errorf(response.Children[2].Value.(string))}
+ }
+ }
+
+ return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
+}
+
+// NewError creates an LDAP error with the given code and underlying error
+func NewError(resultCode uint16, 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 uint16) bool {
+ if err == nil {
+ return false
+ }
+
+ serverError, ok := err.(*Error)
+ if !ok {
+ return false
+ }
+
+ return serverError.ResultCode == desiredResultCode
+}
diff --git a/vendor/gopkg.in/ldap.v2/filter.go b/vendor/gopkg.in/ldap.v3/filter.go
index 3858a2865c..4cc4207bec 100644
--- a/vendor/gopkg.in/ldap.v2/filter.go
+++ b/vendor/gopkg.in/ldap.v3/filter.go
@@ -1,7 +1,3 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
package ldap
import (
diff --git a/vendor/gopkg.in/ldap.v2/ldap.go b/vendor/gopkg.in/ldap.v3/ldap.go
index 4969247569..d7666676fe 100644
--- a/vendor/gopkg.in/ldap.v2/ldap.go
+++ b/vendor/gopkg.in/ldap.v3/ldap.go
@@ -1,11 +1,8 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
package ldap
import (
"errors"
+ "fmt"
"io/ioutil"
"os"
@@ -101,13 +98,13 @@ func addLDAPDescriptions(packet *ber.Packet) (err error) {
switch application {
case ApplicationBindRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationBindResponse:
- addDefaultLDAPResponseDescriptions(packet)
+ err = addDefaultLDAPResponseDescriptions(packet)
case ApplicationUnbindRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationSearchRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationSearchResultEntry:
packet.Children[1].Children[0].Description = "Object Name"
packet.Children[1].Children[1].Description = "Attributes"
@@ -120,37 +117,37 @@ func addLDAPDescriptions(packet *ber.Packet) (err error) {
}
}
if len(packet.Children) == 3 {
- addControlDescriptions(packet.Children[2])
+ err = addControlDescriptions(packet.Children[2])
}
case ApplicationSearchResultDone:
- addDefaultLDAPResponseDescriptions(packet)
+ err = addDefaultLDAPResponseDescriptions(packet)
case ApplicationModifyRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationModifyResponse:
case ApplicationAddRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationAddResponse:
case ApplicationDelRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationDelResponse:
case ApplicationModifyDNRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationModifyDNResponse:
case ApplicationCompareRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationCompareResponse:
case ApplicationAbandonRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationSearchResultReference:
case ApplicationExtendedRequest:
- addRequestDescriptions(packet)
+ err = addRequestDescriptions(packet)
case ApplicationExtendedResponse:
}
- return nil
+ return err
}
-func addControlDescriptions(packet *ber.Packet) {
+func addControlDescriptions(packet *ber.Packet) error {
packet.Description = "Controls"
for _, child := range packet.Children {
var value *ber.Packet
@@ -159,7 +156,7 @@ func addControlDescriptions(packet *ber.Packet) {
switch len(child.Children) {
case 0:
// at least one child is required for control type
- continue
+ return fmt.Errorf("at least one child is required for control type")
case 1:
// just type, no criticality or value
@@ -188,8 +185,9 @@ func addControlDescriptions(packet *ber.Packet) {
default:
// more than 3 children is invalid
- continue
+ return fmt.Errorf("more than 3 children for control packet found")
}
+
if value == nil {
continue
}
@@ -197,7 +195,10 @@ func addControlDescriptions(packet *ber.Packet) {
case ControlTypePaging:
value.Description += " (Paging)"
if value.Value != nil {
- valueChildren := ber.DecodePacket(value.Data.Bytes())
+ valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
+ if err != nil {
+ return fmt.Errorf("failed to decode data bytes: %s", err)
+ }
value.Data.Truncate(0)
value.Value = nil
valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
@@ -210,7 +211,10 @@ func addControlDescriptions(packet *ber.Packet) {
case ControlTypeBeheraPasswordPolicy:
value.Description += " (Password Policy - Behera Draft)"
if value.Value != nil {
- valueChildren := ber.DecodePacket(value.Data.Bytes())
+ valueChildren, err := ber.DecodePacketErr(value.Data.Bytes())
+ if err != nil {
+ return fmt.Errorf("failed to decode data bytes: %s", err)
+ }
value.Data.Truncate(0)
value.Value = nil
value.AppendChild(valueChildren)
@@ -220,7 +224,10 @@ func addControlDescriptions(packet *ber.Packet) {
if child.Tag == 0 {
//Warning
warningPacket := child.Children[0]
- packet := ber.DecodePacket(warningPacket.Data.Bytes())
+ packet, err := ber.DecodePacketErr(warningPacket.Data.Bytes())
+ if err != nil {
+ return fmt.Errorf("failed to decode data bytes: %s", err)
+ }
val, ok := packet.Value.(int64)
if ok {
if warningPacket.Tag == 0 {
@@ -235,7 +242,10 @@ func addControlDescriptions(packet *ber.Packet) {
}
} else if child.Tag == 1 {
// Error
- packet := ber.DecodePacket(child.Data.Bytes())
+ packet, err := ber.DecodePacketErr(child.Data.Bytes())
+ if err != nil {
+ return fmt.Errorf("failed to decode data bytes: %s", err)
+ }
val, ok := packet.Value.(int8)
if !ok {
val = -1
@@ -246,28 +256,31 @@ func addControlDescriptions(packet *ber.Packet) {
}
}
}
+ return nil
}
-func addRequestDescriptions(packet *ber.Packet) {
+func addRequestDescriptions(packet *ber.Packet) error {
packet.Description = "LDAP Request"
packet.Children[0].Description = "Message ID"
packet.Children[1].Description = ApplicationMap[uint8(packet.Children[1].Tag)]
if len(packet.Children) == 3 {
- addControlDescriptions(packet.Children[2])
+ return addControlDescriptions(packet.Children[2])
}
+ return nil
}
-func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
- resultCode, _ := getLDAPResultCode(packet)
- packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
- packet.Children[1].Children[1].Description = "Matched DN"
+func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error {
+ err := GetLDAPError(packet)
+ packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[err.(*Error).ResultCode] + ")"
+ packet.Children[1].Children[1].Description = "Matched DN (" + err.(*Error).MatchedDN + ")"
packet.Children[1].Children[2].Description = "Error Message"
if len(packet.Children[1].Children) > 3 {
packet.Children[1].Children[3].Description = "Referral"
}
if len(packet.Children) == 3 {
- addControlDescriptions(packet.Children[2])
+ return addControlDescriptions(packet.Children[2])
}
+ return nil
}
// DebugBinaryFile reads and prints packets from the given filename
@@ -277,8 +290,13 @@ func DebugBinaryFile(fileName string) error {
return NewError(ErrorDebugging, err)
}
ber.PrintBytes(os.Stdout, file, "")
- packet := ber.DecodePacket(file)
- addLDAPDescriptions(packet)
+ packet, err := ber.DecodePacketErr(file)
+ if err != nil {
+ return fmt.Errorf("failed to decode packet: %s", err)
+ }
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
ber.PrintPacket(packet)
return nil
diff --git a/vendor/gopkg.in/ldap.v3/moddn.go b/vendor/gopkg.in/ldap.v3/moddn.go
new file mode 100644
index 0000000000..803279d262
--- /dev/null
+++ b/vendor/gopkg.in/ldap.v3/moddn.go
@@ -0,0 +1,104 @@
+// Package ldap - moddn.go contains ModifyDN functionality
+//
+// https://tools.ietf.org/html/rfc4511
+// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+// entry LDAPDN,
+// newrdn RelativeLDAPDN,
+// deleteoldrdn BOOLEAN,
+// newSuperior [0] LDAPDN OPTIONAL }
+//
+//
+package ldap
+
+import (
+ "errors"
+ "log"
+
+ "gopkg.in/asn1-ber.v1"
+)
+
+// ModifyDNRequest holds the request to modify a DN
+type ModifyDNRequest struct {
+ DN string
+ NewRDN string
+ DeleteOldRDN bool
+ NewSuperior string
+}
+
+// NewModifyDNRequest creates a new request which can be passed to ModifyDN().
+//
+// To move an object in the tree, set the "newSup" to the new parent entry DN. Use an
+// empty string for just changing the object's RDN.
+//
+// For moving the object without renaming, the "rdn" must be the first
+// RDN of the given DN.
+//
+// A call like
+// mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")
+// will setup the request to just rename uid=someone,dc=example,dc=org to
+// uid=newname,dc=example,dc=org.
+func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ModifyDNRequest {
+ return &ModifyDNRequest{
+ DN: dn,
+ NewRDN: rdn,
+ DeleteOldRDN: delOld,
+ NewSuperior: newSup,
+ }
+}
+
+func (m ModifyDNRequest) encode() *ber.Packet {
+ request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyDNRequest, nil, "Modify DN 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.NewRDN, "New RDN"))
+ request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, m.DeleteOldRDN, "Delete old RDN"))
+ if m.NewSuperior != "" {
+ request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, m.NewSuperior, "New Superior"))
+ }
+ return request
+}
+
+// ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument
+// to NewModifyDNRequest() is not "").
+func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
+ packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
+ packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
+ packet.AppendChild(m.encode())
+
+ l.Debug.PrintPacket(packet)
+
+ msgCtx, err := l.sendMessage(packet)
+ if err != nil {
+ return err
+ }
+ defer l.finishMessage(msgCtx)
+
+ l.Debug.Printf("%d: waiting for response", msgCtx.id)
+ packetResponse, ok := <-msgCtx.responses
+ if !ok {
+ return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
+ }
+ packet, err = packetResponse.ReadPacket()
+ l.Debug.Printf("%d: got response %p", msgCtx.id, packet)
+ if err != nil {
+ return err
+ }
+
+ if l.Debug {
+ if err := addLDAPDescriptions(packet); err != nil {
+ return err
+ }
+ ber.PrintPacket(packet)
+ }
+
+ if packet.Children[1].Tag == ApplicationModifyDNResponse {
+ err := GetLDAPError(packet)
+ if err != nil {
+ return err
+ }
+ } else {
+ log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
+ }
+
+ l.Debug.Printf("%d: returning", msgCtx.id)
+ return nil
+}
diff --git a/vendor/gopkg.in/ldap.v2/modify.go b/vendor/gopkg.in/ldap.v3/modify.go
index e4ab6cefc7..d83e6221fd 100644
--- a/vendor/gopkg.in/ldap.v2/modify.go
+++ b/vendor/gopkg.in/ldap.v3/modify.go
@@ -1,7 +1,3 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
// File contains Modify functionality
//
// https://tools.ietf.org/html/rfc4511
@@ -62,54 +58,56 @@ func (p *PartialAttribute) encode() *ber.Packet {
return seq
}
+// Change for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
+type Change struct {
+ // Operation is the type of change to be made
+ Operation uint
+ // Modification is the attribute to be modified
+ Modification PartialAttribute
+}
+
+func (c *Change) encode() *ber.Packet {
+ change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
+ change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(c.Operation), "Operation"))
+ change.AppendChild(c.Modification.encode())
+ return change
+}
+
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
type ModifyRequest struct {
// 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
+ // Changes contain the attributes to modify
+ Changes []Change
+ // Controls hold optional controls to send with the request
+ Controls []Control
}
-// Add inserts the given attribute to the list of attributes to add
+// Add appends the given attribute to the list of changes to be made
func (m *ModifyRequest) Add(attrType string, attrVals []string) {
- m.AddAttributes = append(m.AddAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
+ m.appendChange(AddAttribute, attrType, attrVals)
}
-// Delete inserts the given attribute to the list of attributes to delete
+// Delete appends the given attribute to the list of changes to be made
func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
- m.DeleteAttributes = append(m.DeleteAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
+ m.appendChange(DeleteAttribute, attrType, attrVals)
}
-// Replace inserts the given attribute to the list of attributes to replace
+// Replace appends the given attribute to the list of changes to be made
func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
- m.ReplaceAttributes = append(m.ReplaceAttributes, PartialAttribute{Type: attrType, Vals: attrVals})
+ m.appendChange(ReplaceAttribute, attrType, attrVals)
+}
+
+func (m *ModifyRequest) appendChange(operation uint, attrType string, attrVals []string) {
+ m.Changes = append(m.Changes, Change{operation, 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"))
changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
- 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 {
- 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 {
- 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())
- changes.AppendChild(change)
+ for _, change := range m.Changes {
+ changes.AppendChild(change.encode())
}
request.AppendChild(changes)
return request
@@ -118,9 +116,11 @@ func (m ModifyRequest) encode() *ber.Packet {
// NewModifyRequest creates a modify request for the given DN
func NewModifyRequest(
dn string,
+ controls []Control,
) *ModifyRequest {
return &ModifyRequest{
- DN: dn,
+ DN: dn,
+ Controls: controls,
}
}
@@ -129,6 +129,9 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
packet.AppendChild(modifyRequest.encode())
+ if len(modifyRequest.Controls) > 0 {
+ packet.AppendChild(encodeControls(modifyRequest.Controls))
+ }
l.Debug.PrintPacket(packet)
@@ -157,9 +160,9 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
}
if packet.Children[1].Tag == ApplicationModifyResponse {
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return NewError(resultCode, errors.New(resultDescription))
+ err := GetLDAPError(packet)
+ if err != nil {
+ return err
}
} else {
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
diff --git a/vendor/gopkg.in/ldap.v2/passwdmodify.go b/vendor/gopkg.in/ldap.v3/passwdmodify.go
index 7d8246fd18..06bc21db13 100644
--- a/vendor/gopkg.in/ldap.v2/passwdmodify.go
+++ b/vendor/gopkg.in/ldap.v3/passwdmodify.go
@@ -32,6 +32,8 @@ type PasswordModifyRequest struct {
type PasswordModifyResult struct {
// GeneratedPassword holds a password generated by the server, if present
GeneratedPassword string
+ // Referral are the returned referral
+ Referral string
}
func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
@@ -124,12 +126,19 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
}
if packet.Children[1].Tag == ApplicationExtendedResponse {
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return nil, NewError(resultCode, errors.New(resultDescription))
+ err := GetLDAPError(packet)
+ if err != nil {
+ if IsErrorWithCode(err, LDAPResultReferral) {
+ for _, child := range packet.Children[1].Children {
+ if child.Tag == 3 {
+ result.Referral = child.Children[0].Value.(string)
+ }
+ }
+ }
+ return result, err
}
} else {
- return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("Unexpected Response: %d", packet.Children[1].Tag))
+ return nil, NewError(ErrorUnexpectedResponse, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag))
}
extendedResponse := packet.Children[1]
diff --git a/vendor/gopkg.in/ldap.v2/search.go b/vendor/gopkg.in/ldap.v3/search.go
index 2a99894c94..3aa6dac0c2 100644
--- a/vendor/gopkg.in/ldap.v2/search.go
+++ b/vendor/gopkg.in/ldap.v3/search.go
@@ -1,7 +1,3 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-//
// File contains Search functionality
//
// https://tools.ietf.org/html/rfc4511
@@ -313,10 +309,10 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
} else {
castControl, ok := control.(*ControlPaging)
if !ok {
- return nil, fmt.Errorf("Expected paging control to be of type *ControlPaging, got %v", control)
+ return nil, fmt.Errorf("expected paging control to be of type *ControlPaging, got %v", control)
}
if castControl.PagingSize != pagingSize {
- return nil, fmt.Errorf("Paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
+ return nil, fmt.Errorf("paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
}
pagingControl = castControl
}
@@ -379,7 +375,7 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
}
packet.AppendChild(encodedSearchRequest)
// encode search controls
- if searchRequest.Controls != nil {
+ if len(searchRequest.Controls) > 0 {
packet.AppendChild(encodeControls(searchRequest.Controls))
}
@@ -431,13 +427,17 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
}
result.Entries = append(result.Entries, entry)
case 5:
- resultCode, resultDescription := getLDAPResultCode(packet)
- if resultCode != 0 {
- return result, NewError(resultCode, errors.New(resultDescription))
+ err := GetLDAPError(packet)
+ if err != nil {
+ return nil, err
}
if len(packet.Children) == 3 {
for _, child := range packet.Children[2].Children {
- result.Controls = append(result.Controls, DecodeControl(child))
+ decodedChild, err := DecodeControl(child)
+ if err != nil {
+ return nil, fmt.Errorf("failed to decode child control: %s", err)
+ }
+ result.Controls = append(result.Controls, decodedChild)
}
}
foundSearchResultDone = true