Merge pull request #1338 from srenatus/sr/update-go-ldap
update go-ldap, improve errors
This commit is contained in:
commit
4738070951
20 changed files with 699 additions and 336 deletions
|
@ -293,6 +293,9 @@ func (c *ldapConnector) do(ctx context.Context, f func(c *ldap.Conn) error) erro
|
||||||
|
|
||||||
// If bindDN and bindPW are empty this will default to an anonymous bind.
|
// If bindDN and bindPW are empty this will default to an anonymous bind.
|
||||||
if err := conn.Bind(c.BindDN, c.BindPW); err != nil {
|
if err := conn.Bind(c.BindDN, c.BindPW); err != nil {
|
||||||
|
if c.BindDN == "" && c.BindPW == "" {
|
||||||
|
return fmt.Errorf("ldap: initial anonymous bind failed: %v", err)
|
||||||
|
}
|
||||||
return fmt.Errorf("ldap: initial bind for user %q failed: %v", c.BindDN, err)
|
return fmt.Errorf("ldap: initial bind for user %q failed: %v", c.BindDN, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +475,7 @@ func (c *ldapConnector) Login(ctx context.Context, s connector.Scopes, username,
|
||||||
func (c *ldapConnector) Refresh(ctx context.Context, s connector.Scopes, ident connector.Identity) (connector.Identity, error) {
|
func (c *ldapConnector) Refresh(ctx context.Context, s connector.Scopes, ident connector.Identity) (connector.Identity, error) {
|
||||||
var data refreshData
|
var data refreshData
|
||||||
if err := json.Unmarshal(ident.ConnectorData, &data); err != nil {
|
if err := json.Unmarshal(ident.ConnectorData, &data); err != nil {
|
||||||
return ident, fmt.Errorf("ldap: failed to unamrshal internal data: %v", err)
|
return ident, fmt.Errorf("ldap: failed to unmarshal internal data: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var user ldap.Entry
|
var user ldap.Entry
|
||||||
|
|
6
glide.lock
generated
6
glide.lock
generated
|
@ -1,5 +1,5 @@
|
||||||
hash: fe29de07f5c1580c51de0e78796bce522d933602d88a4c397b586bd88ca7ca76
|
hash: e5972bbdf15ad612d99ce8cd34e19537b9eacb5ff53688f339e0da285eb8ec22
|
||||||
updated: 2018-10-24T14:58:32.448481302-07:00
|
updated: 2018-11-12T19:38:56.235070564+01:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/beevik/etree
|
- name: github.com/beevik/etree
|
||||||
version: 4cd0dd976db869f817248477718071a28e978df0
|
version: 4cd0dd976db869f817248477718071a28e978df0
|
||||||
|
@ -180,7 +180,7 @@ imports:
|
||||||
- name: gopkg.in/asn1-ber.v1
|
- name: gopkg.in/asn1-ber.v1
|
||||||
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||||
- name: gopkg.in/ldap.v2
|
- name: gopkg.in/ldap.v2
|
||||||
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
version: bb7a9ca6e4fbc2129e3db588a34bc970ffe811a9
|
||||||
- name: gopkg.in/square/go-jose.v2
|
- name: gopkg.in/square/go-jose.v2
|
||||||
version: 8254d6c783765f38c8675fae4427a1fe73fbd09d
|
version: 8254d6c783765f38c8675fae4427a1fe73fbd09d
|
||||||
subpackages:
|
subpackages:
|
||||||
|
|
|
@ -19,7 +19,7 @@ import:
|
||||||
|
|
||||||
# LDAP dependencies.
|
# LDAP dependencies.
|
||||||
- package: gopkg.in/ldap.v2
|
- package: gopkg.in/ldap.v2
|
||||||
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
version: v2.5.1
|
||||||
- package: gopkg.in/asn1-ber.v1
|
- package: gopkg.in/asn1-ber.v1
|
||||||
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
version: 4e86f4367175e39f69d9358a5f17b4dda270378d
|
||||||
|
|
||||||
|
|
43
vendor/gopkg.in/ldap.v2/LICENSE
generated
vendored
43
vendor/gopkg.in/ldap.v2/LICENSE
generated
vendored
|
@ -1,27 +1,22 @@
|
||||||
Copyright (c) 2012 The Go Authors. All rights reserved.
|
The MIT License (MIT)
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Copyright (c) 2011-2015 Michael Mitton (mmitton@gmail.com)
|
||||||
modification, are permitted provided that the following conditions are
|
Portions copyright (c) 2015-2016 go-ldap Authors
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
notice, this list of conditions and the following disclaimer.
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
* Redistributions in binary form must reproduce the above
|
in the Software without restriction, including without limitation the rights
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
in the documentation and/or other materials provided with the
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
distribution.
|
furnished to do so, subject to the following conditions:
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
The above copyright notice and this permission notice shall be included in all
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
copies or substantial portions of the Software.
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
SOFTWARE.
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
49
vendor/gopkg.in/ldap.v2/add.go
generated
vendored
49
vendor/gopkg.in/ldap.v2/add.go
generated
vendored
|
@ -16,73 +16,78 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Attribute represents an LDAP attribute
|
||||||
type Attribute struct {
|
type Attribute struct {
|
||||||
attrType string
|
// Type is the name of the LDAP attribute
|
||||||
attrVals []string
|
Type string
|
||||||
|
// Vals are the LDAP attribute values
|
||||||
|
Vals []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Attribute) encode() *ber.Packet {
|
func (a *Attribute) encode() *ber.Packet {
|
||||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
|
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")
|
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"))
|
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
|
||||||
}
|
}
|
||||||
seq.AppendChild(set)
|
seq.AppendChild(set)
|
||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddRequest represents an LDAP AddRequest operation
|
||||||
type AddRequest struct {
|
type AddRequest struct {
|
||||||
dn string
|
// DN identifies the entry being added
|
||||||
attributes []Attribute
|
DN string
|
||||||
|
// Attributes list the attributes of the new entry
|
||||||
|
Attributes []Attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AddRequest) encode() *ber.Packet {
|
func (a AddRequest) encode() *ber.Packet {
|
||||||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
|
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")
|
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())
|
attributes.AppendChild(attribute.encode())
|
||||||
}
|
}
|
||||||
request.AppendChild(attributes)
|
request.AppendChild(attributes)
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attribute adds an attribute with the given type and values
|
||||||
func (a *AddRequest) Attribute(attrType string, attrVals []string) {
|
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 {
|
func NewAddRequest(dn string) *AddRequest {
|
||||||
return &AddRequest{
|
return &AddRequest{
|
||||||
dn: dn,
|
DN: dn,
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add performs the given AddRequest
|
||||||
func (l *Conn) Add(addRequest *AddRequest) error {
|
func (l *Conn) Add(addRequest *AddRequest) error {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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())
|
packet.AppendChild(addRequest.encode())
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
if !ok {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||||
}
|
}
|
||||||
packet, err = packetResponse.ReadPacket()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -103,6 +108,6 @@ func (l *Conn) Add(addRequest *AddRequest) error {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Debug.Printf("%d: returning", messageID)
|
l.Debug.Printf("%d: returning", msgCtx.id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
13
vendor/gopkg.in/ldap.v2/atomic_value.go
generated
vendored
Normal file
13
vendor/gopkg.in/ldap.v2/atomic_value.go
generated
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// +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
|
||||||
|
}
|
28
vendor/gopkg.in/ldap.v2/atomic_value_go13.go
generated
vendored
Normal file
28
vendor/gopkg.in/ldap.v2/atomic_value_go13.go
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// +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
|
||||||
|
}
|
42
vendor/gopkg.in/ldap.v2/bind.go
generated
vendored
42
vendor/gopkg.in/ldap.v2/bind.go
generated
vendored
|
@ -10,16 +10,22 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SimpleBindRequest represents a username/password bind operation
|
||||||
type SimpleBindRequest struct {
|
type SimpleBindRequest struct {
|
||||||
|
// Username is the name of the Directory object that the client wishes to bind as
|
||||||
Username string
|
Username string
|
||||||
|
// Password is the credentials to bind with
|
||||||
Password string
|
Password string
|
||||||
|
// Controls are optional controls to send with the bind request
|
||||||
Controls []Control
|
Controls []Control
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SimpleBindResult contains the response from the server
|
||||||
type SimpleBindResult struct {
|
type SimpleBindResult struct {
|
||||||
Controls []Control
|
Controls []Control
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSimpleBindRequest returns a bind request
|
||||||
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
|
func NewSimpleBindRequest(username string, password string, controls []Control) *SimpleBindRequest {
|
||||||
return &SimpleBindRequest{
|
return &SimpleBindRequest{
|
||||||
Username: username,
|
Username: username,
|
||||||
|
@ -39,11 +45,10 @@ func (bindRequest *SimpleBindRequest) encode() *ber.Packet {
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SimpleBind performs the simple bind operation defined in the given request
|
||||||
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
|
func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error) {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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()
|
encodedBindRequest := simpleBindRequest.encode()
|
||||||
packet.AppendChild(encodedBindRequest)
|
packet.AppendChild(encodedBindRequest)
|
||||||
|
|
||||||
|
@ -51,21 +56,18 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
|
||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
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()
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -95,11 +97,10 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind performs a bind with the given username and password
|
||||||
func (l *Conn) Bind(username, password string) error {
|
func (l *Conn) Bind(username, password string) error {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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 := 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.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.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
|
||||||
|
@ -110,21 +111,18 @@ func (l *Conn) Bind(username, password string) error {
|
||||||
ber.PrintPacket(packet)
|
ber.PrintPacket(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
if !ok {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||||
}
|
}
|
||||||
packet, err = packetResponse.ReadPacket()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
18
vendor/gopkg.in/ldap.v2/compare.go
generated
vendored
18
vendor/gopkg.in/ldap.v2/compare.go
generated
vendored
|
@ -33,9 +33,8 @@ import (
|
||||||
// Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise
|
// 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.
|
// false with any error that occurs if any.
|
||||||
func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
|
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 := 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 := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationCompareRequest, nil, "Compare Request")
|
||||||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, dn, "DN"))
|
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)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return false, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
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()
|
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 {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
186
vendor/gopkg.in/ldap.v2/conn.go
generated
vendored
186
vendor/gopkg.in/ldap.v2/conn.go
generated
vendored
|
@ -11,24 +11,34 @@ import (
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// MessageQuit causes the processMessages loop to exit
|
||||||
MessageQuit = 0
|
MessageQuit = 0
|
||||||
|
// MessageRequest sends a request to the server
|
||||||
MessageRequest = 1
|
MessageRequest = 1
|
||||||
|
// MessageResponse receives a response from the server
|
||||||
MessageResponse = 2
|
MessageResponse = 2
|
||||||
|
// MessageFinish indicates the client considers a particular message ID to be finished
|
||||||
MessageFinish = 3
|
MessageFinish = 3
|
||||||
|
// MessageTimeout indicates the client-specified timeout for a particular message ID has been reached
|
||||||
MessageTimeout = 4
|
MessageTimeout = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PacketResponse contains the packet or error encountered reading a response
|
||||||
type PacketResponse struct {
|
type PacketResponse struct {
|
||||||
|
// Packet is the packet read from the server
|
||||||
Packet *ber.Packet
|
Packet *ber.Packet
|
||||||
|
// Error is an error encountered while reading
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadPacket returns the packet or an error
|
||||||
func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) {
|
func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) {
|
||||||
if (pr == nil) || (pr.Packet == nil && pr.Error == nil) {
|
if (pr == nil) || (pr.Packet == nil && pr.Error == nil) {
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
|
return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
|
||||||
|
@ -36,11 +46,31 @@ func (pr *PacketResponse) ReadPacket() (*ber.Packet, error) {
|
||||||
return pr.Packet, pr.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 {
|
type messagePacket struct {
|
||||||
Op int
|
Op int
|
||||||
MessageID int64
|
MessageID int64
|
||||||
Packet *ber.Packet
|
Packet *ber.Packet
|
||||||
Channel chan *PacketResponse
|
Context *messageContext
|
||||||
}
|
}
|
||||||
|
|
||||||
type sendMessageFlags uint
|
type sendMessageFlags uint
|
||||||
|
@ -53,19 +83,18 @@ const (
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
isTLS bool
|
isTLS bool
|
||||||
isClosing bool
|
closing uint32
|
||||||
|
closeErr atomicValue
|
||||||
isStartingTLS bool
|
isStartingTLS bool
|
||||||
Debug debugging
|
Debug debugging
|
||||||
chanConfirm chan bool
|
chanConfirm chan struct{}
|
||||||
chanResults map[int64]chan *PacketResponse
|
messageContexts map[int64]*messageContext
|
||||||
chanMessage chan *messagePacket
|
chanMessage chan *messagePacket
|
||||||
chanMessageID chan int64
|
chanMessageID chan int64
|
||||||
wgSender sync.WaitGroup
|
|
||||||
wgClose sync.WaitGroup
|
wgClose sync.WaitGroup
|
||||||
once sync.Once
|
|
||||||
outstandingRequests uint
|
outstandingRequests uint
|
||||||
messageMutex sync.Mutex
|
messageMutex sync.Mutex
|
||||||
requestTimeout time.Duration
|
requestTimeout int64
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Client = &Conn{}
|
var _ Client = &Conn{}
|
||||||
|
@ -112,27 +141,38 @@ func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
|
||||||
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
func NewConn(conn net.Conn, isTLS bool) *Conn {
|
||||||
return &Conn{
|
return &Conn{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
chanConfirm: make(chan bool),
|
chanConfirm: make(chan struct{}),
|
||||||
chanMessageID: make(chan int64),
|
chanMessageID: make(chan int64),
|
||||||
chanMessage: make(chan *messagePacket, 10),
|
chanMessage: make(chan *messagePacket, 10),
|
||||||
chanResults: map[int64]chan *PacketResponse{},
|
messageContexts: map[int64]*messageContext{},
|
||||||
requestTimeout: 0,
|
requestTimeout: 0,
|
||||||
isTLS: isTLS,
|
isTLS: isTLS,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start initializes goroutines to read responses and process messages
|
||||||
func (l *Conn) Start() {
|
func (l *Conn) Start() {
|
||||||
go l.reader()
|
go l.reader()
|
||||||
go l.processMessages()
|
go l.processMessages()
|
||||||
l.wgClose.Add(1)
|
l.wgClose.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isClosing returns whether or not we're currently closing.
|
||||||
|
func (l *Conn) isClosing() bool {
|
||||||
|
return atomic.LoadUint32(&l.closing) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// setClosing sets the closing value to true
|
||||||
|
func (l *Conn) setClosing() bool {
|
||||||
|
return atomic.CompareAndSwapUint32(&l.closing, 0, 1)
|
||||||
|
}
|
||||||
|
|
||||||
// Close closes the connection.
|
// Close closes the connection.
|
||||||
func (l *Conn) Close() {
|
func (l *Conn) Close() {
|
||||||
l.once.Do(func() {
|
l.messageMutex.Lock()
|
||||||
l.isClosing = true
|
defer l.messageMutex.Unlock()
|
||||||
l.wgSender.Wait()
|
|
||||||
|
|
||||||
|
if l.setClosing() {
|
||||||
l.Debug.Printf("Sending quit message and waiting for confirmation")
|
l.Debug.Printf("Sending quit message and waiting for confirmation")
|
||||||
l.chanMessage <- &messagePacket{Op: MessageQuit}
|
l.chanMessage <- &messagePacket{Op: MessageQuit}
|
||||||
<-l.chanConfirm
|
<-l.chanConfirm
|
||||||
|
@ -140,62 +180,56 @@ func (l *Conn) Close() {
|
||||||
|
|
||||||
l.Debug.Printf("Closing network connection")
|
l.Debug.Printf("Closing network connection")
|
||||||
if err := l.conn.Close(); err != nil {
|
if err := l.conn.Close(); err != nil {
|
||||||
log.Print(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.wgClose.Done()
|
l.wgClose.Done()
|
||||||
})
|
}
|
||||||
l.wgClose.Wait()
|
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) {
|
func (l *Conn) SetTimeout(timeout time.Duration) {
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
l.requestTimeout = timeout
|
atomic.StoreInt64(&l.requestTimeout, int64(timeout))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the next available messageID
|
// Returns the next available messageID
|
||||||
func (l *Conn) nextMessageID() int64 {
|
func (l *Conn) nextMessageID() int64 {
|
||||||
if l.chanMessageID != nil {
|
|
||||||
if messageID, ok := <-l.chanMessageID; ok {
|
if messageID, ok := <-l.chanMessageID; ok {
|
||||||
return messageID
|
return messageID
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
|
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
|
||||||
func (l *Conn) StartTLS(config *tls.Config) error {
|
func (l *Conn) StartTLS(config *tls.Config) error {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
|
|
||||||
if l.isTLS {
|
if l.isTLS {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
|
return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
|
||||||
}
|
}
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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 := 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"))
|
request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command"))
|
||||||
packet.AppendChild(request)
|
packet.AppendChild(request)
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessageWithFlags(packet, startTLS)
|
msgCtx, err := l.sendMessageWithFlags(packet, startTLS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
if !ok {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||||
}
|
}
|
||||||
packet, err = packetResponse.ReadPacket()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -226,45 +260,51 @@ func (l *Conn) StartTLS(config *tls.Config) error {
|
||||||
return nil
|
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)
|
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 {
|
if l.isClosing() {
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
|
return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
|
||||||
}
|
}
|
||||||
l.messageMutex.Lock()
|
l.messageMutex.Lock()
|
||||||
l.Debug.Printf("flags&startTLS = %d", flags&startTLS)
|
l.Debug.Printf("flags&startTLS = %d", flags&startTLS)
|
||||||
if l.isStartingTLS {
|
if l.isStartingTLS {
|
||||||
l.messageMutex.Unlock()
|
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 flags&startTLS != 0 {
|
||||||
if l.outstandingRequests != 0 {
|
if l.outstandingRequests != 0 {
|
||||||
l.messageMutex.Unlock()
|
l.messageMutex.Unlock()
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: cannot StartTLS with outstanding requests"))
|
return nil, NewError(ErrorNetwork, errors.New("ldap: cannot StartTLS with outstanding requests"))
|
||||||
} else {
|
|
||||||
l.isStartingTLS = true
|
|
||||||
}
|
}
|
||||||
|
l.isStartingTLS = true
|
||||||
}
|
}
|
||||||
l.outstandingRequests++
|
l.outstandingRequests++
|
||||||
|
|
||||||
l.messageMutex.Unlock()
|
l.messageMutex.Unlock()
|
||||||
|
|
||||||
out := make(chan *PacketResponse)
|
responses := make(chan *PacketResponse)
|
||||||
|
messageID := packet.Children[0].Value.(int64)
|
||||||
message := &messagePacket{
|
message := &messagePacket{
|
||||||
Op: MessageRequest,
|
Op: MessageRequest,
|
||||||
MessageID: packet.Children[0].Value.(int64),
|
MessageID: messageID,
|
||||||
Packet: packet,
|
Packet: packet,
|
||||||
Channel: out,
|
Context: &messageContext{
|
||||||
|
id: messageID,
|
||||||
|
done: make(chan struct{}),
|
||||||
|
responses: responses,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
l.sendProcessMessage(message)
|
l.sendProcessMessage(message)
|
||||||
return out, nil
|
return message.Context, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Conn) finishMessage(messageID int64) {
|
func (l *Conn) finishMessage(msgCtx *messageContext) {
|
||||||
if l.isClosing {
|
close(msgCtx.done)
|
||||||
|
|
||||||
|
if l.isClosing() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,18 +317,18 @@ func (l *Conn) finishMessage(messageID int64) {
|
||||||
|
|
||||||
message := &messagePacket{
|
message := &messagePacket{
|
||||||
Op: MessageFinish,
|
Op: MessageFinish,
|
||||||
MessageID: messageID,
|
MessageID: msgCtx.id,
|
||||||
}
|
}
|
||||||
l.sendProcessMessage(message)
|
l.sendProcessMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Conn) sendProcessMessage(message *messagePacket) bool {
|
func (l *Conn) sendProcessMessage(message *messagePacket) bool {
|
||||||
if l.isClosing {
|
l.messageMutex.Lock()
|
||||||
|
defer l.messageMutex.Unlock()
|
||||||
|
if l.isClosing() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
l.wgSender.Add(1)
|
|
||||||
l.chanMessage <- message
|
l.chanMessage <- message
|
||||||
l.wgSender.Done()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,13 +337,17 @@ func (l *Conn) processMessages() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("ldap: recovered panic in processMessages: %v", err)
|
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.Load() != nil {
|
||||||
|
msgCtx.sendResponse(&PacketResponse{Error: l.closeErr.Load().(error)})
|
||||||
|
}
|
||||||
l.Debug.Printf("Closing channel for MessageID %d", messageID)
|
l.Debug.Printf("Closing channel for MessageID %d", messageID)
|
||||||
close(channel)
|
close(msgCtx.responses)
|
||||||
delete(l.chanResults, messageID)
|
delete(l.messageContexts, messageID)
|
||||||
}
|
}
|
||||||
close(l.chanMessageID)
|
close(l.chanMessageID)
|
||||||
l.chanConfirm <- true
|
|
||||||
close(l.chanConfirm)
|
close(l.chanConfirm)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -312,11 +356,7 @@ func (l *Conn) processMessages() {
|
||||||
select {
|
select {
|
||||||
case l.chanMessageID <- messageID:
|
case l.chanMessageID <- messageID:
|
||||||
messageID++
|
messageID++
|
||||||
case message, ok := <-l.chanMessage:
|
case message := <-l.chanMessage:
|
||||||
if !ok {
|
|
||||||
l.Debug.Printf("Shutting down - message channel is closed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch message.Op {
|
switch message.Op {
|
||||||
case MessageQuit:
|
case MessageQuit:
|
||||||
l.Debug.Printf("Shutting down - quit message received")
|
l.Debug.Printf("Shutting down - quit message received")
|
||||||
|
@ -324,24 +364,30 @@ func (l *Conn) processMessages() {
|
||||||
case MessageRequest:
|
case MessageRequest:
|
||||||
// Add to message list and write to network
|
// Add to message list and write to network
|
||||||
l.Debug.Printf("Sending message %d", message.MessageID)
|
l.Debug.Printf("Sending message %d", message.MessageID)
|
||||||
l.chanResults[message.MessageID] = message.Channel
|
|
||||||
|
|
||||||
buf := message.Packet.Bytes()
|
buf := message.Packet.Bytes()
|
||||||
_, err := l.conn.Write(buf)
|
_, err := l.conn.Write(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debug.Printf("Error Sending Message: %s", err.Error())
|
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
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only add to messageContexts if we were able to
|
||||||
|
// successfully write the message.
|
||||||
|
l.messageContexts[message.MessageID] = message.Context
|
||||||
|
|
||||||
// Add timeout if defined
|
// Add timeout if defined
|
||||||
if l.requestTimeout > 0 {
|
requestTimeout := time.Duration(atomic.LoadInt64(&l.requestTimeout))
|
||||||
|
if requestTimeout > 0 {
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
log.Printf("ldap: recovered panic in RequestTimeout: %v", err)
|
log.Printf("ldap: recovered panic in RequestTimeout: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
time.Sleep(l.requestTimeout)
|
time.Sleep(requestTimeout)
|
||||||
timeoutMessage := &messagePacket{
|
timeoutMessage := &messagePacket{
|
||||||
Op: MessageTimeout,
|
Op: MessageTimeout,
|
||||||
MessageID: message.MessageID,
|
MessageID: message.MessageID,
|
||||||
|
@ -351,26 +397,26 @@ func (l *Conn) processMessages() {
|
||||||
}
|
}
|
||||||
case MessageResponse:
|
case MessageResponse:
|
||||||
l.Debug.Printf("Receiving message %d", message.MessageID)
|
l.Debug.Printf("Receiving message %d", message.MessageID)
|
||||||
if chanResult, ok := l.chanResults[message.MessageID]; ok {
|
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||||
chanResult <- &PacketResponse{message.Packet, nil}
|
msgCtx.sendResponse(&PacketResponse{message.Packet, nil})
|
||||||
} else {
|
} 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)
|
ber.PrintPacket(message.Packet)
|
||||||
}
|
}
|
||||||
case MessageTimeout:
|
case MessageTimeout:
|
||||||
// Handle the timeout by closing the channel
|
// Handle the timeout by closing the channel
|
||||||
// All reads will return immediately
|
// All reads will return immediately
|
||||||
if chanResult, ok := l.chanResults[message.MessageID]; ok {
|
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||||
chanResult <- &PacketResponse{message.Packet, errors.New("ldap: connection timed out")}
|
|
||||||
l.Debug.Printf("Receiving message timeout for %d", message.MessageID)
|
l.Debug.Printf("Receiving message timeout for %d", message.MessageID)
|
||||||
delete(l.chanResults, message.MessageID)
|
msgCtx.sendResponse(&PacketResponse{message.Packet, errors.New("ldap: connection timed out")})
|
||||||
close(chanResult)
|
delete(l.messageContexts, message.MessageID)
|
||||||
|
close(msgCtx.responses)
|
||||||
}
|
}
|
||||||
case MessageFinish:
|
case MessageFinish:
|
||||||
l.Debug.Printf("Finished message %d", message.MessageID)
|
l.Debug.Printf("Finished message %d", message.MessageID)
|
||||||
if chanResult, ok := l.chanResults[message.MessageID]; ok {
|
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||||
close(chanResult)
|
delete(l.messageContexts, message.MessageID)
|
||||||
delete(l.chanResults, message.MessageID)
|
close(msgCtx.responses)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,7 +442,8 @@ func (l *Conn) reader() {
|
||||||
packet, err := ber.ReadPacket(l.conn)
|
packet, err := ber.ReadPacket(l.conn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// A read error is expected here if we are closing the connection...
|
// 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())
|
l.Debug.Printf("reader error: %s", err.Error())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -419,6 +466,5 @@ func (l *Conn) reader() {
|
||||||
if !l.sendProcessMessage(message) {
|
if !l.sendProcessMessage(message) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
118
vendor/gopkg.in/ldap.v2/control.go
generated
vendored
118
vendor/gopkg.in/ldap.v2/control.go
generated
vendored
|
@ -12,35 +12,48 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ControlTypePaging - https://www.ietf.org/rfc/rfc2696.txt
|
||||||
ControlTypePaging = "1.2.840.113556.1.4.319"
|
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"
|
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"
|
ControlTypeVChuPasswordMustChange = "2.16.840.1.113730.3.4.4"
|
||||||
|
// ControlTypeVChuPasswordWarning - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
|
||||||
ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
|
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"
|
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ControlTypeMap maps controls to text descriptions
|
||||||
var ControlTypeMap = map[string]string{
|
var ControlTypeMap = map[string]string{
|
||||||
ControlTypePaging: "Paging",
|
ControlTypePaging: "Paging",
|
||||||
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
||||||
ControlTypeManageDsaIT: "Manage DSA IT",
|
ControlTypeManageDsaIT: "Manage DSA IT",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Control defines an interface controls provide to encode and describe themselves
|
||||||
type Control interface {
|
type Control interface {
|
||||||
|
// GetControlType returns the OID
|
||||||
GetControlType() string
|
GetControlType() string
|
||||||
|
// Encode returns the ber packet representation
|
||||||
Encode() *ber.Packet
|
Encode() *ber.Packet
|
||||||
|
// String returns a human-readable description
|
||||||
String() string
|
String() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlString implements the Control interface for simple controls
|
||||||
type ControlString struct {
|
type ControlString struct {
|
||||||
ControlType string
|
ControlType string
|
||||||
Criticality bool
|
Criticality bool
|
||||||
ControlValue string
|
ControlValue string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlString) GetControlType() string {
|
func (c *ControlString) GetControlType() string {
|
||||||
return c.ControlType
|
return c.ControlType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlString) Encode() *ber.Packet {
|
func (c *ControlString) Encode() *ber.Packet {
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
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]+")"))
|
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
|
return packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlString) String() string {
|
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)
|
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 {
|
type ControlPaging struct {
|
||||||
|
// PagingSize indicates the page size
|
||||||
PagingSize uint32
|
PagingSize uint32
|
||||||
|
// Cookie is an opaque value returned by the server to track a paging cursor
|
||||||
Cookie []byte
|
Cookie []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlPaging) GetControlType() string {
|
func (c *ControlPaging) GetControlType() string {
|
||||||
return ControlTypePaging
|
return ControlTypePaging
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlPaging) Encode() *ber.Packet {
|
func (c *ControlPaging) Encode() *ber.Packet {
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
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]+")"))
|
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)")
|
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 := 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 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
|
||||||
cookie.Value = c.Cookie
|
cookie.Value = c.Cookie
|
||||||
cookie.Data.Write(c.Cookie)
|
cookie.Data.Write(c.Cookie)
|
||||||
|
@ -81,6 +100,7 @@ func (c *ControlPaging) Encode() *ber.Packet {
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlPaging) String() string {
|
func (c *ControlPaging) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q",
|
"Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q",
|
||||||
|
@ -91,21 +111,29 @@ func (c *ControlPaging) String() string {
|
||||||
c.Cookie)
|
c.Cookie)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetCookie stores the given cookie in the paging control
|
||||||
func (c *ControlPaging) SetCookie(cookie []byte) {
|
func (c *ControlPaging) SetCookie(cookie []byte) {
|
||||||
c.Cookie = cookie
|
c.Cookie = cookie
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlBeheraPasswordPolicy implements the control described in https://tools.ietf.org/html/draft-behera-ldap-password-policy-10
|
||||||
type ControlBeheraPasswordPolicy struct {
|
type ControlBeheraPasswordPolicy struct {
|
||||||
|
// Expire contains the number of seconds before a password will expire
|
||||||
Expire int64
|
Expire int64
|
||||||
|
// Grace indicates the remaining number of times a user will be allowed to authenticate with an expired password
|
||||||
Grace int64
|
Grace int64
|
||||||
|
// Error indicates the error code
|
||||||
Error int8
|
Error int8
|
||||||
|
// ErrorString is a human readable error
|
||||||
ErrorString string
|
ErrorString string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlBeheraPasswordPolicy) GetControlType() string {
|
func (c *ControlBeheraPasswordPolicy) GetControlType() string {
|
||||||
return ControlTypeBeheraPasswordPolicy
|
return ControlTypeBeheraPasswordPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet {
|
func (c *ControlBeheraPasswordPolicy) Encode() *ber.Packet {
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
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]+")"))
|
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
|
return packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlBeheraPasswordPolicy) String() string {
|
func (c *ControlBeheraPasswordPolicy) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Control Type: %s (%q) Criticality: %t Expire: %d Grace: %d Error: %d, ErrorString: %s",
|
"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)
|
c.ErrorString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlVChuPasswordMustChange implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
|
||||||
type ControlVChuPasswordMustChange struct {
|
type ControlVChuPasswordMustChange struct {
|
||||||
|
// MustChange indicates if the password is required to be changed
|
||||||
MustChange bool
|
MustChange bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlVChuPasswordMustChange) GetControlType() string {
|
func (c *ControlVChuPasswordMustChange) GetControlType() string {
|
||||||
return ControlTypeVChuPasswordMustChange
|
return ControlTypeVChuPasswordMustChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlVChuPasswordMustChange) Encode() *ber.Packet {
|
func (c *ControlVChuPasswordMustChange) Encode() *ber.Packet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlVChuPasswordMustChange) String() string {
|
func (c *ControlVChuPasswordMustChange) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Control Type: %s (%q) Criticality: %t MustChange: %b",
|
"Control Type: %s (%q) Criticality: %t MustChange: %v",
|
||||||
ControlTypeMap[ControlTypeVChuPasswordMustChange],
|
ControlTypeMap[ControlTypeVChuPasswordMustChange],
|
||||||
ControlTypeVChuPasswordMustChange,
|
ControlTypeVChuPasswordMustChange,
|
||||||
false,
|
false,
|
||||||
c.MustChange)
|
c.MustChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlVChuPasswordWarning implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00
|
||||||
type ControlVChuPasswordWarning struct {
|
type ControlVChuPasswordWarning struct {
|
||||||
|
// Expire indicates the time in seconds until the password expires
|
||||||
Expire int64
|
Expire int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlVChuPasswordWarning) GetControlType() string {
|
func (c *ControlVChuPasswordWarning) GetControlType() string {
|
||||||
return ControlTypeVChuPasswordWarning
|
return ControlTypeVChuPasswordWarning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlVChuPasswordWarning) Encode() *ber.Packet {
|
func (c *ControlVChuPasswordWarning) Encode() *ber.Packet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlVChuPasswordWarning) String() string {
|
func (c *ControlVChuPasswordWarning) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Control Type: %s (%q) Criticality: %t Expire: %b",
|
"Control Type: %s (%q) Criticality: %t Expire: %b",
|
||||||
|
@ -167,14 +206,18 @@ func (c *ControlVChuPasswordWarning) String() string {
|
||||||
c.Expire)
|
c.Expire)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ControlManageDsaIT implements the control described in https://tools.ietf.org/html/rfc3296
|
||||||
type ControlManageDsaIT struct {
|
type ControlManageDsaIT struct {
|
||||||
|
// Criticality indicates if this control is required
|
||||||
Criticality bool
|
Criticality bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetControlType returns the OID
|
||||||
func (c *ControlManageDsaIT) GetControlType() string {
|
func (c *ControlManageDsaIT) GetControlType() string {
|
||||||
return ControlTypeManageDsaIT
|
return ControlTypeManageDsaIT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encode returns the ber packet representation
|
||||||
func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
||||||
//FIXME
|
//FIXME
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||||
|
@ -185,6 +228,7 @@ func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
||||||
return packet
|
return packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns a human-readable description
|
||||||
func (c *ControlManageDsaIT) String() string {
|
func (c *ControlManageDsaIT) String() string {
|
||||||
return fmt.Sprintf(
|
return fmt.Sprintf(
|
||||||
"Control Type: %s (%q) Criticality: %t",
|
"Control Type: %s (%q) Criticality: %t",
|
||||||
|
@ -193,10 +237,12 @@ func (c *ControlManageDsaIT) String() string {
|
||||||
c.Criticality)
|
c.Criticality)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewControlManageDsaIT returns a ControlManageDsaIT control
|
||||||
func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
|
func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
|
||||||
return &ControlManageDsaIT{Criticality: Criticality}
|
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 {
|
func FindControl(controls []Control, controlType string) Control {
|
||||||
for _, c := range controls {
|
for _, c := range controls {
|
||||||
if c.GetControlType() == controlType {
|
if c.GetControlType() == controlType {
|
||||||
|
@ -206,20 +252,56 @@ func FindControl(controls []Control, controlType string) Control {
|
||||||
return nil
|
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 {
|
func DecodeControl(packet *ber.Packet) Control {
|
||||||
ControlType := packet.Children[0].Value.(string)
|
var (
|
||||||
Criticality := false
|
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] + ")"
|
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
||||||
value := packet.Children[1]
|
ControlType = packet.Children[0].Value.(string)
|
||||||
if len(packet.Children) == 3 {
|
|
||||||
value = packet.Children[2]
|
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"
|
packet.Children[1].Description = "Criticality"
|
||||||
Criticality = packet.Children[1].Value.(bool)
|
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[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 {
|
switch ControlType {
|
||||||
|
case ControlTypeManageDsaIT:
|
||||||
|
return NewControlManageDsaIT(Criticality)
|
||||||
case ControlTypePaging:
|
case ControlTypePaging:
|
||||||
value.Description += " (Paging)"
|
value.Description += " (Paging)"
|
||||||
c := new(ControlPaging)
|
c := new(ControlPaging)
|
||||||
|
@ -252,18 +334,18 @@ func DecodeControl(packet *ber.Packet) Control {
|
||||||
for _, child := range sequence.Children {
|
for _, child := range sequence.Children {
|
||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
//Warning
|
//Warning
|
||||||
child := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
packet := ber.DecodePacket(child.Data.Bytes())
|
packet := ber.DecodePacket(warningPacket.Data.Bytes())
|
||||||
val, ok := packet.Value.(int64)
|
val, ok := packet.Value.(int64)
|
||||||
if ok {
|
if ok {
|
||||||
if child.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
//timeBeforeExpiration
|
//timeBeforeExpiration
|
||||||
c.Expire = val
|
c.Expire = val
|
||||||
child.Value = c.Expire
|
warningPacket.Value = c.Expire
|
||||||
} else if child.Tag == 1 {
|
} else if warningPacket.Tag == 1 {
|
||||||
//graceAuthNsRemaining
|
//graceAuthNsRemaining
|
||||||
c.Grace = val
|
c.Grace = val
|
||||||
child.Value = c.Grace
|
warningPacket.Value = c.Grace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if child.Tag == 1 {
|
} else if child.Tag == 1 {
|
||||||
|
@ -295,14 +377,18 @@ func DecodeControl(packet *ber.Packet) Control {
|
||||||
value.Value = c.Expire
|
value.Value = c.Expire
|
||||||
|
|
||||||
return c
|
return c
|
||||||
}
|
default:
|
||||||
c := new(ControlString)
|
c := new(ControlString)
|
||||||
c.ControlType = ControlType
|
c.ControlType = ControlType
|
||||||
c.Criticality = Criticality
|
c.Criticality = Criticality
|
||||||
|
if value != nil {
|
||||||
c.ControlValue = value.Value.(string)
|
c.ControlValue = value.Value.(string)
|
||||||
|
}
|
||||||
return c
|
return c
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewControlString returns a generic control
|
||||||
func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
|
func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
|
||||||
return &ControlString{
|
return &ControlString{
|
||||||
ControlType: controlType,
|
ControlType: controlType,
|
||||||
|
@ -311,10 +397,12 @@ func NewControlString(controlType string, criticality bool, controlValue string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewControlPaging returns a paging control
|
||||||
func NewControlPaging(pagingSize uint32) *ControlPaging {
|
func NewControlPaging(pagingSize uint32) *ControlPaging {
|
||||||
return &ControlPaging{PagingSize: pagingSize}
|
return &ControlPaging{PagingSize: pagingSize}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewControlBeheraPasswordPolicy returns a ControlBeheraPasswordPolicy
|
||||||
func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy {
|
func NewControlBeheraPasswordPolicy() *ControlBeheraPasswordPolicy {
|
||||||
return &ControlBeheraPasswordPolicy{
|
return &ControlBeheraPasswordPolicy{
|
||||||
Expire: -1,
|
Expire: -1,
|
||||||
|
|
2
vendor/gopkg.in/ldap.v2/debug.go
generated
vendored
2
vendor/gopkg.in/ldap.v2/debug.go
generated
vendored
|
@ -6,7 +6,7 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// debbuging type
|
// debugging type
|
||||||
// - has a Printf method to write the debug output
|
// - has a Printf method to write the debug output
|
||||||
type debugging bool
|
type debugging bool
|
||||||
|
|
||||||
|
|
25
vendor/gopkg.in/ldap.v2/del.go
generated
vendored
25
vendor/gopkg.in/ldap.v2/del.go
generated
vendored
|
@ -12,8 +12,11 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DelRequest implements an LDAP deletion request
|
||||||
type DelRequest struct {
|
type DelRequest struct {
|
||||||
|
// DN is the name of the directory entry to delete
|
||||||
DN string
|
DN string
|
||||||
|
// Controls hold optional controls to send with the request
|
||||||
Controls []Control
|
Controls []Control
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +26,7 @@ func (d DelRequest) encode() *ber.Packet {
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewDelRequest creates a delete request for the given DN and controls
|
||||||
func NewDelRequest(DN string,
|
func NewDelRequest(DN string,
|
||||||
Controls []Control) *DelRequest {
|
Controls []Control) *DelRequest {
|
||||||
return &DelRequest{
|
return &DelRequest{
|
||||||
|
@ -31,10 +35,10 @@ func NewDelRequest(DN string,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Del executes the given delete request
|
||||||
func (l *Conn) Del(delRequest *DelRequest) error {
|
func (l *Conn) Del(delRequest *DelRequest) error {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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())
|
packet.AppendChild(delRequest.encode())
|
||||||
if delRequest.Controls != nil {
|
if delRequest.Controls != nil {
|
||||||
packet.AppendChild(encodeControls(delRequest.Controls))
|
packet.AppendChild(encodeControls(delRequest.Controls))
|
||||||
|
@ -42,22 +46,19 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
if !ok {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||||
}
|
}
|
||||||
packet, err = packetResponse.ReadPacket()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -78,6 +79,6 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Debug.Printf("%d: returning", messageID)
|
l.Debug.Printf("%d: returning", msgCtx.id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
122
vendor/gopkg.in/ldap.v2/dn.go
generated
vendored
122
vendor/gopkg.in/ldap.v2/dn.go
generated
vendored
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
// File contains DN parsing functionallity
|
// File contains DN parsing functionality
|
||||||
//
|
//
|
||||||
// https://tools.ietf.org/html/rfc4514
|
// https://tools.ietf.org/html/rfc4514
|
||||||
//
|
//
|
||||||
|
@ -52,22 +52,28 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ber "gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AttributeTypeAndValue represents an attributeTypeAndValue from https://tools.ietf.org/html/rfc4514
|
||||||
type AttributeTypeAndValue struct {
|
type AttributeTypeAndValue struct {
|
||||||
|
// Type is the attribute type
|
||||||
Type string
|
Type string
|
||||||
|
// Value is the attribute value
|
||||||
Value string
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RelativeDN represents a relativeDistinguishedName from https://tools.ietf.org/html/rfc4514
|
||||||
type RelativeDN struct {
|
type RelativeDN struct {
|
||||||
Attributes []*AttributeTypeAndValue
|
Attributes []*AttributeTypeAndValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DN represents a distinguishedName from https://tools.ietf.org/html/rfc4514
|
||||||
type DN struct {
|
type DN struct {
|
||||||
RDNs []*RelativeDN
|
RDNs []*RelativeDN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseDN returns a distinguishedName or an error
|
||||||
func ParseDN(str string) (*DN, error) {
|
func ParseDN(str string) (*DN, error) {
|
||||||
dn := new(DN)
|
dn := new(DN)
|
||||||
dn.RDNs = make([]*RelativeDN, 0)
|
dn.RDNs = make([]*RelativeDN, 0)
|
||||||
|
@ -77,9 +83,19 @@ func ParseDN(str string) (*DN, error) {
|
||||||
attribute := new(AttributeTypeAndValue)
|
attribute := new(AttributeTypeAndValue)
|
||||||
escaping := false
|
escaping := false
|
||||||
|
|
||||||
|
unescapedTrailingSpaces := 0
|
||||||
|
stringFromBuffer := func() string {
|
||||||
|
s := buffer.String()
|
||||||
|
s = s[0 : len(s)-unescapedTrailingSpaces]
|
||||||
|
buffer.Reset()
|
||||||
|
unescapedTrailingSpaces = 0
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < len(str); i++ {
|
for i := 0; i < len(str); i++ {
|
||||||
char := str[i]
|
char := str[i]
|
||||||
if escaping {
|
if escaping {
|
||||||
|
unescapedTrailingSpaces = 0
|
||||||
escaping = false
|
escaping = false
|
||||||
switch char {
|
switch char {
|
||||||
case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
|
case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
|
||||||
|
@ -94,19 +110,17 @@ func ParseDN(str string) (*DN, error) {
|
||||||
dst := []byte{0}
|
dst := []byte{0}
|
||||||
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
|
n, err := enchex.Decode([]byte(dst), []byte(str[i:i+2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New(
|
return nil, fmt.Errorf("Failed to decode escaped character: %s", err)
|
||||||
fmt.Sprintf("Failed to decode escaped character: %s", err))
|
|
||||||
} else if n != 1 {
|
} else if n != 1 {
|
||||||
return nil, errors.New(
|
return nil, fmt.Errorf("Expected 1 byte when un-escaping, got %d", n)
|
||||||
fmt.Sprintf("Expected 1 byte when un-escaping, got %d", n))
|
|
||||||
}
|
}
|
||||||
buffer.WriteByte(dst[0])
|
buffer.WriteByte(dst[0])
|
||||||
i++
|
i++
|
||||||
} else if char == '\\' {
|
} else if char == '\\' {
|
||||||
|
unescapedTrailingSpaces = 0
|
||||||
escaping = true
|
escaping = true
|
||||||
} else if char == '=' {
|
} else if char == '=' {
|
||||||
attribute.Type = buffer.String()
|
attribute.Type = stringFromBuffer()
|
||||||
buffer.Reset()
|
|
||||||
// Special case: If the first character in the value is # the
|
// Special case: If the first character in the value is # the
|
||||||
// following data is BER encoded so we can just fast forward
|
// following data is BER encoded so we can just fast forward
|
||||||
// and decode.
|
// and decode.
|
||||||
|
@ -119,18 +133,20 @@ func ParseDN(str string) (*DN, error) {
|
||||||
} else {
|
} else {
|
||||||
data = str[i:]
|
data = str[i:]
|
||||||
}
|
}
|
||||||
raw_ber, err := enchex.DecodeString(data)
|
rawBER, err := enchex.DecodeString(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New(
|
return nil, fmt.Errorf("Failed to decode BER encoding: %s", err)
|
||||||
fmt.Sprintf("Failed to decode BER encoding: %s", err))
|
|
||||||
}
|
}
|
||||||
packet := ber.DecodePacket(raw_ber)
|
packet := ber.DecodePacket(rawBER)
|
||||||
buffer.WriteString(packet.Data.String())
|
buffer.WriteString(packet.Data.String())
|
||||||
i += len(data) - 1
|
i += len(data) - 1
|
||||||
}
|
}
|
||||||
} else if char == ',' || char == '+' {
|
} else if char == ',' || char == '+' {
|
||||||
// We're done with this RDN or value, push it
|
// We're done with this RDN or value, push it
|
||||||
attribute.Value = buffer.String()
|
if len(attribute.Type) == 0 {
|
||||||
|
return nil, errors.New("incomplete type, value pair")
|
||||||
|
}
|
||||||
|
attribute.Value = stringFromBuffer()
|
||||||
rdn.Attributes = append(rdn.Attributes, attribute)
|
rdn.Attributes = append(rdn.Attributes, attribute)
|
||||||
attribute = new(AttributeTypeAndValue)
|
attribute = new(AttributeTypeAndValue)
|
||||||
if char == ',' {
|
if char == ',' {
|
||||||
|
@ -138,8 +154,17 @@ func ParseDN(str string) (*DN, error) {
|
||||||
rdn = new(RelativeDN)
|
rdn = new(RelativeDN)
|
||||||
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
||||||
}
|
}
|
||||||
buffer.Reset()
|
} else if char == ' ' && buffer.Len() == 0 {
|
||||||
|
// ignore unescaped leading spaces
|
||||||
|
continue
|
||||||
} else {
|
} else {
|
||||||
|
if char == ' ' {
|
||||||
|
// Track unescaped spaces in case they are trailing and we need to remove them
|
||||||
|
unescapedTrailingSpaces++
|
||||||
|
} else {
|
||||||
|
// Reset if we see a non-space char
|
||||||
|
unescapedTrailingSpaces = 0
|
||||||
|
}
|
||||||
buffer.WriteByte(char)
|
buffer.WriteByte(char)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,9 +172,76 @@ func ParseDN(str string) (*DN, error) {
|
||||||
if len(attribute.Type) == 0 {
|
if len(attribute.Type) == 0 {
|
||||||
return nil, errors.New("DN ended with incomplete type, value pair")
|
return nil, errors.New("DN ended with incomplete type, value pair")
|
||||||
}
|
}
|
||||||
attribute.Value = buffer.String()
|
attribute.Value = stringFromBuffer()
|
||||||
rdn.Attributes = append(rdn.Attributes, attribute)
|
rdn.Attributes = append(rdn.Attributes, attribute)
|
||||||
dn.RDNs = append(dn.RDNs, rdn)
|
dn.RDNs = append(dn.RDNs, rdn)
|
||||||
}
|
}
|
||||||
return dn, nil
|
return dn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the DNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
||||||
|
// Returns true if they have the same number of relative distinguished names
|
||||||
|
// and corresponding relative distinguished names (by position) are the same.
|
||||||
|
func (d *DN) Equal(other *DN) bool {
|
||||||
|
if len(d.RDNs) != len(other.RDNs) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range d.RDNs {
|
||||||
|
if !d.RDNs[i].Equal(other.RDNs[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// AncestorOf returns true if the other DN consists of at least one RDN followed by all the RDNs of the current DN.
|
||||||
|
// "ou=widgets,o=acme.com" is an ancestor of "ou=sprockets,ou=widgets,o=acme.com"
|
||||||
|
// "ou=widgets,o=acme.com" is not an ancestor of "ou=sprockets,ou=widgets,o=foo.com"
|
||||||
|
// "ou=widgets,o=acme.com" is not an ancestor of "ou=widgets,o=acme.com"
|
||||||
|
func (d *DN) AncestorOf(other *DN) bool {
|
||||||
|
if len(d.RDNs) >= len(other.RDNs) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Take the last `len(d.RDNs)` RDNs from the other DN to compare against
|
||||||
|
otherRDNs := other.RDNs[len(other.RDNs)-len(d.RDNs):]
|
||||||
|
for i := range d.RDNs {
|
||||||
|
if !d.RDNs[i].Equal(otherRDNs[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the RelativeDNs are equal as defined by rfc4517 4.2.15 (distinguishedNameMatch).
|
||||||
|
// Relative distinguished names are the same if and only if they have the same number of AttributeTypeAndValues
|
||||||
|
// and each attribute of the first RDN is the same as the attribute of the second RDN with the same attribute type.
|
||||||
|
// The order of attributes is not significant.
|
||||||
|
// Case of attribute types is not significant.
|
||||||
|
func (r *RelativeDN) Equal(other *RelativeDN) bool {
|
||||||
|
if len(r.Attributes) != len(other.Attributes) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return r.hasAllAttributes(other.Attributes) && other.hasAllAttributes(r.Attributes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RelativeDN) hasAllAttributes(attrs []*AttributeTypeAndValue) bool {
|
||||||
|
for _, attr := range attrs {
|
||||||
|
found := false
|
||||||
|
for _, myattr := range r.Attributes {
|
||||||
|
if myattr.Equal(attr) {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal returns true if the AttributeTypeAndValue is equivalent to the specified AttributeTypeAndValue
|
||||||
|
// Case of the attribute type is not significant
|
||||||
|
func (a *AttributeTypeAndValue) Equal(other *AttributeTypeAndValue) bool {
|
||||||
|
return strings.EqualFold(a.Type, other.Type) && a.Value == other.Value
|
||||||
|
}
|
||||||
|
|
13
vendor/gopkg.in/ldap.v2/error.go
generated
vendored
13
vendor/gopkg.in/ldap.v2/error.go
generated
vendored
|
@ -56,6 +56,7 @@ const (
|
||||||
ErrorUnexpectedResponse = 205
|
ErrorUnexpectedResponse = 205
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// LDAPResultCodeMap contains string descriptions for LDAP error codes
|
||||||
var LDAPResultCodeMap = map[uint8]string{
|
var LDAPResultCodeMap = map[uint8]string{
|
||||||
LDAPResultSuccess: "Success",
|
LDAPResultSuccess: "Success",
|
||||||
LDAPResultOperationsError: "Operations Error",
|
LDAPResultOperationsError: "Operations Error",
|
||||||
|
@ -96,6 +97,13 @@ var LDAPResultCodeMap = map[uint8]string{
|
||||||
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
||||||
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
||||||
LDAPResultOther: "Other",
|
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) {
|
func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
||||||
|
@ -115,8 +123,11 @@ func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
||||||
return ErrorNetwork, "Invalid packet format"
|
return ErrorNetwork, "Invalid packet format"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Error holds LDAP error information
|
||||||
type Error struct {
|
type Error struct {
|
||||||
|
// Err is the underlying error
|
||||||
Err error
|
Err error
|
||||||
|
// ResultCode is the LDAP error code
|
||||||
ResultCode uint8
|
ResultCode uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,10 +135,12 @@ func (e *Error) Error() string {
|
||||||
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
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 {
|
func NewError(resultCode uint8, err error) error {
|
||||||
return &Error{ResultCode: resultCode, Err: err}
|
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 {
|
func IsErrorWithCode(err error, desiredResultCode uint8) bool {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return false
|
return false
|
||||||
|
|
75
vendor/gopkg.in/ldap.v2/filter.go
generated
vendored
75
vendor/gopkg.in/ldap.v2/filter.go
generated
vendored
|
@ -15,6 +15,7 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Filter choices
|
||||||
const (
|
const (
|
||||||
FilterAnd = 0
|
FilterAnd = 0
|
||||||
FilterOr = 1
|
FilterOr = 1
|
||||||
|
@ -28,6 +29,7 @@ const (
|
||||||
FilterExtensibleMatch = 9
|
FilterExtensibleMatch = 9
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FilterMap contains human readable descriptions of Filter choices
|
||||||
var FilterMap = map[uint64]string{
|
var FilterMap = map[uint64]string{
|
||||||
FilterAnd: "And",
|
FilterAnd: "And",
|
||||||
FilterOr: "Or",
|
FilterOr: "Or",
|
||||||
|
@ -41,18 +43,21 @@ var FilterMap = map[uint64]string{
|
||||||
FilterExtensibleMatch: "Extensible Match",
|
FilterExtensibleMatch: "Extensible Match",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SubstringFilter options
|
||||||
const (
|
const (
|
||||||
FilterSubstringsInitial = 0
|
FilterSubstringsInitial = 0
|
||||||
FilterSubstringsAny = 1
|
FilterSubstringsAny = 1
|
||||||
FilterSubstringsFinal = 2
|
FilterSubstringsFinal = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FilterSubstringsMap contains human readable descriptions of SubstringFilter choices
|
||||||
var FilterSubstringsMap = map[uint64]string{
|
var FilterSubstringsMap = map[uint64]string{
|
||||||
FilterSubstringsInitial: "Substrings Initial",
|
FilterSubstringsInitial: "Substrings Initial",
|
||||||
FilterSubstringsAny: "Substrings Any",
|
FilterSubstringsAny: "Substrings Any",
|
||||||
FilterSubstringsFinal: "Substrings Final",
|
FilterSubstringsFinal: "Substrings Final",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchingRuleAssertion choices
|
||||||
const (
|
const (
|
||||||
MatchingRuleAssertionMatchingRule = 1
|
MatchingRuleAssertionMatchingRule = 1
|
||||||
MatchingRuleAssertionType = 2
|
MatchingRuleAssertionType = 2
|
||||||
|
@ -60,6 +65,7 @@ const (
|
||||||
MatchingRuleAssertionDNAttributes = 4
|
MatchingRuleAssertionDNAttributes = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// MatchingRuleAssertionMap contains human readable descriptions of MatchingRuleAssertion choices
|
||||||
var MatchingRuleAssertionMap = map[uint64]string{
|
var MatchingRuleAssertionMap = map[uint64]string{
|
||||||
MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
|
MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
|
||||||
MatchingRuleAssertionType: "Matching Rule Assertion Type",
|
MatchingRuleAssertionType: "Matching Rule Assertion Type",
|
||||||
|
@ -67,6 +73,7 @@ var MatchingRuleAssertionMap = map[uint64]string{
|
||||||
MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
|
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) {
|
func CompileFilter(filter string) (*ber.Packet, error) {
|
||||||
if len(filter) == 0 || filter[0] != '(' {
|
if len(filter) == 0 || filter[0] != '(' {
|
||||||
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
|
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
|
||||||
|
@ -75,12 +82,16 @@ func CompileFilter(filter string) (*ber.Packet, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if pos != len(filter) {
|
switch {
|
||||||
|
case pos > len(filter):
|
||||||
|
return nil, NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
|
||||||
|
case pos < len(filter):
|
||||||
return nil, NewError(ErrorFilterCompile, errors.New("ldap: finished compiling filter with extra at end: "+fmt.Sprint(filter[pos:])))
|
return nil, NewError(ErrorFilterCompile, errors.New("ldap: finished compiling filter with extra at end: "+fmt.Sprint(filter[pos:])))
|
||||||
}
|
}
|
||||||
return packet, nil
|
return packet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DecompileFilter converts a packet representation of a filter into a string representation
|
||||||
func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
|
@ -239,11 +250,13 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
packet.AppendChild(child)
|
packet.AppendChild(child)
|
||||||
return packet, newPos, err
|
return packet, newPos, err
|
||||||
default:
|
default:
|
||||||
READING_ATTR := 0
|
const (
|
||||||
READING_EXTENSIBLE_MATCHING_RULE := 1
|
stateReadingAttr = 0
|
||||||
READING_CONDITION := 2
|
stateReadingExtensibleMatchingRule = 1
|
||||||
|
stateReadingCondition = 2
|
||||||
|
)
|
||||||
|
|
||||||
state := READING_ATTR
|
state := stateReadingAttr
|
||||||
|
|
||||||
attribute := ""
|
attribute := ""
|
||||||
extensibleDNAttributes := false
|
extensibleDNAttributes := false
|
||||||
|
@ -261,56 +274,56 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case READING_ATTR:
|
case stateReadingAttr:
|
||||||
switch {
|
switch {
|
||||||
// Extensible rule, with only DN-matching
|
// Extensible rule, with only DN-matching
|
||||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
extensibleDNAttributes = true
|
extensibleDNAttributes = true
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 5
|
newPos += 5
|
||||||
|
|
||||||
// Extensible rule, with DN-matching and a matching OID
|
// Extensible rule, with DN-matching and a matching OID
|
||||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
extensibleDNAttributes = true
|
extensibleDNAttributes = true
|
||||||
state = READING_EXTENSIBLE_MATCHING_RULE
|
state = stateReadingExtensibleMatchingRule
|
||||||
newPos += 4
|
newPos += 4
|
||||||
|
|
||||||
// Extensible rule, with attr only
|
// Extensible rule, with attr only
|
||||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 2
|
newPos += 2
|
||||||
|
|
||||||
// Extensible rule, with no DN attribute matching
|
// Extensible rule, with no DN attribute matching
|
||||||
case currentRune == ':':
|
case currentRune == ':':
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||||
state = READING_EXTENSIBLE_MATCHING_RULE
|
state = stateReadingExtensibleMatchingRule
|
||||||
newPos += 1
|
newPos++
|
||||||
|
|
||||||
// Equality condition
|
// Equality condition
|
||||||
case currentRune == '=':
|
case currentRune == '=':
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 1
|
newPos++
|
||||||
|
|
||||||
// Greater-than or equal
|
// Greater-than or equal
|
||||||
case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
|
case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 2
|
newPos += 2
|
||||||
|
|
||||||
// Less-than or equal
|
// Less-than or equal
|
||||||
case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
|
case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 2
|
newPos += 2
|
||||||
|
|
||||||
// Approx
|
// Approx
|
||||||
case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
|
case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
|
||||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
|
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 2
|
newPos += 2
|
||||||
|
|
||||||
// Still reading the attribute name
|
// Still reading the attribute name
|
||||||
|
@ -319,12 +332,12 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
newPos += currentWidth
|
newPos += currentWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
case READING_EXTENSIBLE_MATCHING_RULE:
|
case stateReadingExtensibleMatchingRule:
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
// Matching rule OID is done
|
// Matching rule OID is done
|
||||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||||
state = READING_CONDITION
|
state = stateReadingCondition
|
||||||
newPos += 2
|
newPos += 2
|
||||||
|
|
||||||
// Still reading the matching rule oid
|
// Still reading the matching rule oid
|
||||||
|
@ -333,7 +346,7 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
newPos += currentWidth
|
newPos += currentWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
case READING_CONDITION:
|
case stateReadingCondition:
|
||||||
// append to the condition
|
// append to the condition
|
||||||
condition += fmt.Sprintf("%c", currentRune)
|
condition += fmt.Sprintf("%c", currentRune)
|
||||||
newPos += currentWidth
|
newPos += currentWidth
|
||||||
|
@ -369,9 +382,9 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the value (only required child)
|
// Add the value (only required child)
|
||||||
encodedString, err := escapedStringToEncodedBytes(condition)
|
encodedString, encodeErr := escapedStringToEncodedBytes(condition)
|
||||||
if err != nil {
|
if encodeErr != nil {
|
||||||
return packet, newPos, err
|
return packet, newPos, encodeErr
|
||||||
}
|
}
|
||||||
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
|
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
|
||||||
|
|
||||||
|
@ -401,17 +414,17 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||||
default:
|
default:
|
||||||
tag = FilterSubstringsAny
|
tag = FilterSubstringsAny
|
||||||
}
|
}
|
||||||
encodedString, err := escapedStringToEncodedBytes(part)
|
encodedString, encodeErr := escapedStringToEncodedBytes(part)
|
||||||
if err != nil {
|
if encodeErr != nil {
|
||||||
return packet, newPos, err
|
return packet, newPos, encodeErr
|
||||||
}
|
}
|
||||||
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
|
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
|
||||||
}
|
}
|
||||||
packet.AppendChild(seq)
|
packet.AppendChild(seq)
|
||||||
default:
|
default:
|
||||||
encodedString, err := escapedStringToEncodedBytes(condition)
|
encodedString, encodeErr := escapedStringToEncodedBytes(condition)
|
||||||
if err != nil {
|
if encodeErr != nil {
|
||||||
return packet, newPos, err
|
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, attribute, "Attribute"))
|
||||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
|
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
|
||||||
|
@ -440,12 +453,12 @@ func escapedStringToEncodedBytes(escapedString string) (string, error) {
|
||||||
if i+2 > len(escapedString) {
|
if i+2 > len(escapedString) {
|
||||||
return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
|
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"))
|
return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
|
||||||
} else {
|
}
|
||||||
buffer.WriteByte(escByte[0])
|
buffer.WriteByte(escByte[0])
|
||||||
i += 2 // +1 from end of loop, so 3 total for \xx.
|
i += 2 // +1 from end of loop, so 3 total for \xx.
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
buffer.WriteRune(currentRune)
|
buffer.WriteRune(currentRune)
|
||||||
}
|
}
|
||||||
|
|
64
vendor/gopkg.in/ldap.v2/ldap.go
generated
vendored
64
vendor/gopkg.in/ldap.v2/ldap.go
generated
vendored
|
@ -9,7 +9,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
ber "gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LDAP Application Codes
|
// LDAP Application Codes
|
||||||
|
@ -36,6 +36,7 @@ const (
|
||||||
ApplicationExtendedResponse = 24
|
ApplicationExtendedResponse = 24
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ApplicationMap contains human readable descriptions of LDAP Application Codes
|
||||||
var ApplicationMap = map[uint8]string{
|
var ApplicationMap = map[uint8]string{
|
||||||
ApplicationBindRequest: "Bind Request",
|
ApplicationBindRequest: "Bind Request",
|
||||||
ApplicationBindResponse: "Bind Response",
|
ApplicationBindResponse: "Bind Response",
|
||||||
|
@ -72,6 +73,7 @@ const (
|
||||||
BeheraPasswordInHistory = 8
|
BeheraPasswordInHistory = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// BeheraPasswordPolicyErrorMap contains human readable descriptions of Behera Password Policy error codes
|
||||||
var BeheraPasswordPolicyErrorMap = map[int8]string{
|
var BeheraPasswordPolicyErrorMap = map[int8]string{
|
||||||
BeheraPasswordExpired: "Password expired",
|
BeheraPasswordExpired: "Password expired",
|
||||||
BeheraAccountLocked: "Account locked",
|
BeheraAccountLocked: "Account locked",
|
||||||
|
@ -151,16 +153,47 @@ func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
||||||
func addControlDescriptions(packet *ber.Packet) {
|
func addControlDescriptions(packet *ber.Packet) {
|
||||||
packet.Description = "Controls"
|
packet.Description = "Controls"
|
||||||
for _, child := range packet.Children {
|
for _, child := range packet.Children {
|
||||||
|
var value *ber.Packet
|
||||||
|
controlType := ""
|
||||||
child.Description = "Control"
|
child.Description = "Control"
|
||||||
child.Children[0].Description = "Control Type (" + ControlTypeMap[child.Children[0].Value.(string)] + ")"
|
switch len(child.Children) {
|
||||||
value := child.Children[1]
|
case 0:
|
||||||
if len(child.Children) == 3 {
|
// at least one child is required for control type
|
||||||
child.Children[1].Description = "Criticality"
|
continue
|
||||||
value = child.Children[2]
|
|
||||||
}
|
|
||||||
value.Description = "Control Value"
|
|
||||||
|
|
||||||
switch child.Children[0].Value.(string) {
|
case 1:
|
||||||
|
// just type, no criticality or value
|
||||||
|
controlType = child.Children[0].Value.(string)
|
||||||
|
child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")"
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
controlType = child.Children[0].Value.(string)
|
||||||
|
child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")"
|
||||||
|
// Children[1] could be criticality or value (both are optional)
|
||||||
|
// duck-type on whether this is a boolean
|
||||||
|
if _, ok := child.Children[1].Value.(bool); ok {
|
||||||
|
child.Children[1].Description = "Criticality"
|
||||||
|
} else {
|
||||||
|
child.Children[1].Description = "Control Value"
|
||||||
|
value = child.Children[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
// criticality and value present
|
||||||
|
controlType = child.Children[0].Value.(string)
|
||||||
|
child.Children[0].Description = "Control Type (" + ControlTypeMap[controlType] + ")"
|
||||||
|
child.Children[1].Description = "Criticality"
|
||||||
|
child.Children[2].Description = "Control Value"
|
||||||
|
value = child.Children[2]
|
||||||
|
|
||||||
|
default:
|
||||||
|
// more than 3 children is invalid
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if value == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch controlType {
|
||||||
case ControlTypePaging:
|
case ControlTypePaging:
|
||||||
value.Description += " (Paging)"
|
value.Description += " (Paging)"
|
||||||
if value.Value != nil {
|
if value.Value != nil {
|
||||||
|
@ -186,18 +219,18 @@ func addControlDescriptions(packet *ber.Packet) {
|
||||||
for _, child := range sequence.Children {
|
for _, child := range sequence.Children {
|
||||||
if child.Tag == 0 {
|
if child.Tag == 0 {
|
||||||
//Warning
|
//Warning
|
||||||
child := child.Children[0]
|
warningPacket := child.Children[0]
|
||||||
packet := ber.DecodePacket(child.Data.Bytes())
|
packet := ber.DecodePacket(warningPacket.Data.Bytes())
|
||||||
val, ok := packet.Value.(int64)
|
val, ok := packet.Value.(int64)
|
||||||
if ok {
|
if ok {
|
||||||
if child.Tag == 0 {
|
if warningPacket.Tag == 0 {
|
||||||
//timeBeforeExpiration
|
//timeBeforeExpiration
|
||||||
value.Description += " (TimeBeforeExpiration)"
|
value.Description += " (TimeBeforeExpiration)"
|
||||||
child.Value = val
|
warningPacket.Value = val
|
||||||
} else if child.Tag == 1 {
|
} else if warningPacket.Tag == 1 {
|
||||||
//graceAuthNsRemaining
|
//graceAuthNsRemaining
|
||||||
value.Description += " (GraceAuthNsRemaining)"
|
value.Description += " (GraceAuthNsRemaining)"
|
||||||
child.Value = val
|
warningPacket.Value = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if child.Tag == 1 {
|
} else if child.Tag == 1 {
|
||||||
|
@ -237,6 +270,7 @@ func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DebugBinaryFile reads and prints packets from the given filename
|
||||||
func DebugBinaryFile(fileName string) error {
|
func DebugBinaryFile(fileName string) error {
|
||||||
file, err := ioutil.ReadFile(fileName)
|
file, err := ioutil.ReadFile(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
66
vendor/gopkg.in/ldap.v2/modify.go
generated
vendored
66
vendor/gopkg.in/ldap.v2/modify.go
generated
vendored
|
@ -36,64 +36,76 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Change operation choices
|
||||||
const (
|
const (
|
||||||
AddAttribute = 0
|
AddAttribute = 0
|
||||||
DeleteAttribute = 1
|
DeleteAttribute = 1
|
||||||
ReplaceAttribute = 2
|
ReplaceAttribute = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PartialAttribute for a ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
|
||||||
type PartialAttribute struct {
|
type PartialAttribute struct {
|
||||||
attrType string
|
// Type is the type of the partial attribute
|
||||||
attrVals []string
|
Type string
|
||||||
|
// Vals are the values of the partial attribute
|
||||||
|
Vals []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PartialAttribute) encode() *ber.Packet {
|
func (p *PartialAttribute) encode() *ber.Packet {
|
||||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
|
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")
|
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"))
|
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
|
||||||
}
|
}
|
||||||
seq.AppendChild(set)
|
seq.AppendChild(set)
|
||||||
return seq
|
return seq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ModifyRequest as defined in https://tools.ietf.org/html/rfc4511
|
||||||
type ModifyRequest struct {
|
type ModifyRequest struct {
|
||||||
dn string
|
// DN is the distinguishedName of the directory entry to modify
|
||||||
addAttributes []PartialAttribute
|
DN string
|
||||||
deleteAttributes []PartialAttribute
|
// AddAttributes contain the attributes to add
|
||||||
replaceAttributes []PartialAttribute
|
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) {
|
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) {
|
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) {
|
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 {
|
func (m ModifyRequest) encode() *ber.Packet {
|
||||||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
|
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")
|
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 := 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(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
|
||||||
change.AppendChild(attribute.encode())
|
change.AppendChild(attribute.encode())
|
||||||
changes.AppendChild(change)
|
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 := 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(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
|
||||||
change.AppendChild(attribute.encode())
|
change.AppendChild(attribute.encode())
|
||||||
changes.AppendChild(change)
|
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 := 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(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
|
||||||
change.AppendChild(attribute.encode())
|
change.AppendChild(attribute.encode())
|
||||||
|
@ -103,38 +115,36 @@ func (m ModifyRequest) encode() *ber.Packet {
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewModifyRequest creates a modify request for the given DN
|
||||||
func NewModifyRequest(
|
func NewModifyRequest(
|
||||||
dn string,
|
dn string,
|
||||||
) *ModifyRequest {
|
) *ModifyRequest {
|
||||||
return &ModifyRequest{
|
return &ModifyRequest{
|
||||||
dn: dn,
|
DN: dn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modify performs the ModifyRequest
|
||||||
func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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())
|
packet.AppendChild(modifyRequest.encode())
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
if !ok {
|
||||||
return NewError(ErrorNetwork, errors.New("ldap: channel closed"))
|
return NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||||
}
|
}
|
||||||
packet, err = packetResponse.ReadPacket()
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -155,6 +165,6 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
||||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Debug.Printf("%d: returning", messageID)
|
l.Debug.Printf("%d: returning", msgCtx.id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
38
vendor/gopkg.in/ldap.v2/passwdmodify.go
generated
vendored
38
vendor/gopkg.in/ldap.v2/passwdmodify.go
generated
vendored
|
@ -16,13 +16,21 @@ const (
|
||||||
passwordModifyOID = "1.3.6.1.4.1.4203.1.11.1"
|
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 {
|
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
|
UserIdentity string
|
||||||
|
// OldPassword, if present, contains the user's current password
|
||||||
OldPassword string
|
OldPassword string
|
||||||
|
// NewPassword, if present, contains the desired password for this user
|
||||||
NewPassword string
|
NewPassword string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PasswordModifyResult holds the server response to a PasswordModifyRequest
|
||||||
type PasswordModifyResult struct {
|
type PasswordModifyResult struct {
|
||||||
|
// GeneratedPassword holds a password generated by the server, if present
|
||||||
GeneratedPassword string
|
GeneratedPassword string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +55,7 @@ func (r *PasswordModifyRequest) encode() (*ber.Packet, error) {
|
||||||
return request, nil
|
return request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new PasswordModifyRequest
|
// NewPasswordModifyRequest creates a new PasswordModifyRequest
|
||||||
//
|
//
|
||||||
// According to the RFC 3602:
|
// According to the RFC 3602:
|
||||||
// userIdentity is a string representing the user associated with the request.
|
// 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) {
|
func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error) {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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()
|
encodedPasswordModifyRequest, err := passwordModifyRequest.encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -86,24 +93,21 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
result := &PasswordModifyResult{}
|
result := &PasswordModifyResult{}
|
||||||
|
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
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()
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -131,10 +135,10 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||||
extendedResponse := packet.Children[1]
|
extendedResponse := packet.Children[1]
|
||||||
for _, child := range extendedResponse.Children {
|
for _, child := range extendedResponse.Children {
|
||||||
if child.Tag == 11 {
|
if child.Tag == 11 {
|
||||||
passwordModifyReponseValue := ber.DecodePacket(child.Data.Bytes())
|
passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
|
||||||
if len(passwordModifyReponseValue.Children) == 1 {
|
if len(passwordModifyResponseValue.Children) == 1 {
|
||||||
if passwordModifyReponseValue.Children[0].Tag == 0 {
|
if passwordModifyResponseValue.Children[0].Tag == 0 {
|
||||||
result.GeneratedPassword = ber.DecodeString(passwordModifyReponseValue.Children[0].Data.Bytes())
|
result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
48
vendor/gopkg.in/ldap.v2/search.go
generated
vendored
48
vendor/gopkg.in/ldap.v2/search.go
generated
vendored
|
@ -68,18 +68,21 @@ import (
|
||||||
"gopkg.in/asn1-ber.v1"
|
"gopkg.in/asn1-ber.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// scope choices
|
||||||
const (
|
const (
|
||||||
ScopeBaseObject = 0
|
ScopeBaseObject = 0
|
||||||
ScopeSingleLevel = 1
|
ScopeSingleLevel = 1
|
||||||
ScopeWholeSubtree = 2
|
ScopeWholeSubtree = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ScopeMap contains human readable descriptions of scope choices
|
||||||
var ScopeMap = map[int]string{
|
var ScopeMap = map[int]string{
|
||||||
ScopeBaseObject: "Base Object",
|
ScopeBaseObject: "Base Object",
|
||||||
ScopeSingleLevel: "Single Level",
|
ScopeSingleLevel: "Single Level",
|
||||||
ScopeWholeSubtree: "Whole Subtree",
|
ScopeWholeSubtree: "Whole Subtree",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// derefAliases
|
||||||
const (
|
const (
|
||||||
NeverDerefAliases = 0
|
NeverDerefAliases = 0
|
||||||
DerefInSearching = 1
|
DerefInSearching = 1
|
||||||
|
@ -87,6 +90,7 @@ const (
|
||||||
DerefAlways = 3
|
DerefAlways = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DerefMap contains human readable descriptions of derefAliases choices
|
||||||
var DerefMap = map[int]string{
|
var DerefMap = map[int]string{
|
||||||
NeverDerefAliases: "NeverDerefAliases",
|
NeverDerefAliases: "NeverDerefAliases",
|
||||||
DerefInSearching: "DerefInSearching",
|
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 {
|
type Entry struct {
|
||||||
|
// DN is the distinguished name of the entry
|
||||||
DN string
|
DN string
|
||||||
|
// Attributes are the returned attributes for the entry
|
||||||
Attributes []*EntryAttribute
|
Attributes []*EntryAttribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttributeValues returns the values for the named attribute, or an empty list
|
||||||
func (e *Entry) GetAttributeValues(attribute string) []string {
|
func (e *Entry) GetAttributeValues(attribute string) []string {
|
||||||
for _, attr := range e.Attributes {
|
for _, attr := range e.Attributes {
|
||||||
if attr.Name == attribute {
|
if attr.Name == attribute {
|
||||||
|
@ -128,6 +136,7 @@ func (e *Entry) GetAttributeValues(attribute string) []string {
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRawAttributeValues returns the byte values for the named attribute, or an empty list
|
||||||
func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
|
func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
|
||||||
for _, attr := range e.Attributes {
|
for _, attr := range e.Attributes {
|
||||||
if attr.Name == attribute {
|
if attr.Name == attribute {
|
||||||
|
@ -137,6 +146,7 @@ func (e *Entry) GetRawAttributeValues(attribute string) [][]byte {
|
||||||
return [][]byte{}
|
return [][]byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAttributeValue returns the first value for the named attribute, or ""
|
||||||
func (e *Entry) GetAttributeValue(attribute string) string {
|
func (e *Entry) GetAttributeValue(attribute string) string {
|
||||||
values := e.GetAttributeValues(attribute)
|
values := e.GetAttributeValues(attribute)
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
|
@ -145,6 +155,7 @@ func (e *Entry) GetAttributeValue(attribute string) string {
|
||||||
return values[0]
|
return values[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRawAttributeValue returns the first value for the named attribute, or an empty slice
|
||||||
func (e *Entry) GetRawAttributeValue(attribute string) []byte {
|
func (e *Entry) GetRawAttributeValue(attribute string) []byte {
|
||||||
values := e.GetRawAttributeValues(attribute)
|
values := e.GetRawAttributeValues(attribute)
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
|
@ -153,6 +164,7 @@ func (e *Entry) GetRawAttributeValue(attribute string) []byte {
|
||||||
return values[0]
|
return values[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print outputs a human-readable description
|
||||||
func (e *Entry) Print() {
|
func (e *Entry) Print() {
|
||||||
fmt.Printf("DN: %s\n", e.DN)
|
fmt.Printf("DN: %s\n", e.DN)
|
||||||
for _, attr := range e.Attributes {
|
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) {
|
func (e *Entry) PrettyPrint(indent int) {
|
||||||
fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
|
fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
|
||||||
for _, attr := range e.Attributes {
|
for _, attr := range e.Attributes {
|
||||||
|
@ -180,38 +193,51 @@ func NewEntryAttribute(name string, values []string) *EntryAttribute {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EntryAttribute holds a single attribute
|
||||||
type EntryAttribute struct {
|
type EntryAttribute struct {
|
||||||
|
// Name is the name of the attribute
|
||||||
Name string
|
Name string
|
||||||
|
// Values contain the string values of the attribute
|
||||||
Values []string
|
Values []string
|
||||||
|
// ByteValues contain the raw values of the attribute
|
||||||
ByteValues [][]byte
|
ByteValues [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print outputs a human-readable description
|
||||||
func (e *EntryAttribute) Print() {
|
func (e *EntryAttribute) Print() {
|
||||||
fmt.Printf("%s: %s\n", e.Name, e.Values)
|
fmt.Printf("%s: %s\n", e.Name, e.Values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrettyPrint outputs a human-readable description with indenting
|
||||||
func (e *EntryAttribute) PrettyPrint(indent int) {
|
func (e *EntryAttribute) PrettyPrint(indent int) {
|
||||||
fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
|
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 {
|
type SearchResult struct {
|
||||||
|
// Entries are the returned entries
|
||||||
Entries []*Entry
|
Entries []*Entry
|
||||||
|
// Referrals are the returned referrals
|
||||||
Referrals []string
|
Referrals []string
|
||||||
|
// Controls are the returned controls
|
||||||
Controls []Control
|
Controls []Control
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print outputs a human-readable description
|
||||||
func (s *SearchResult) Print() {
|
func (s *SearchResult) Print() {
|
||||||
for _, entry := range s.Entries {
|
for _, entry := range s.Entries {
|
||||||
entry.Print()
|
entry.Print()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrettyPrint outputs a human-readable description with indenting
|
||||||
func (s *SearchResult) PrettyPrint(indent int) {
|
func (s *SearchResult) PrettyPrint(indent int) {
|
||||||
for _, entry := range s.Entries {
|
for _, entry := range s.Entries {
|
||||||
entry.PrettyPrint(indent)
|
entry.PrettyPrint(indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchRequest represents a search request to send to the server
|
||||||
type SearchRequest struct {
|
type SearchRequest struct {
|
||||||
BaseDN string
|
BaseDN string
|
||||||
Scope int
|
Scope int
|
||||||
|
@ -247,6 +273,7 @@ func (s *SearchRequest) encode() (*ber.Packet, error) {
|
||||||
return request, nil
|
return request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSearchRequest creates a new search request
|
||||||
func NewSearchRequest(
|
func NewSearchRequest(
|
||||||
BaseDN string,
|
BaseDN string,
|
||||||
Scope, DerefAliases, SizeLimit, TimeLimit int,
|
Scope, DerefAliases, SizeLimit, TimeLimit int,
|
||||||
|
@ -341,10 +368,10 @@ func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32)
|
||||||
return searchResult, nil
|
return searchResult, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search performs the given search request
|
||||||
func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||||
messageID := l.nextMessageID()
|
|
||||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
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
|
// encode search request
|
||||||
encodedSearchRequest, err := searchRequest.encode()
|
encodedSearchRequest, err := searchRequest.encode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -358,14 +385,11 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||||
|
|
||||||
l.Debug.PrintPacket(packet)
|
l.Debug.PrintPacket(packet)
|
||||||
|
|
||||||
channel, err := l.sendMessage(packet)
|
msgCtx, err := l.sendMessage(packet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if channel == nil {
|
defer l.finishMessage(msgCtx)
|
||||||
return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
|
||||||
}
|
|
||||||
defer l.finishMessage(messageID)
|
|
||||||
|
|
||||||
result := &SearchResult{
|
result := &SearchResult{
|
||||||
Entries: make([]*Entry, 0),
|
Entries: make([]*Entry, 0),
|
||||||
|
@ -374,13 +398,13 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||||
|
|
||||||
foundSearchResultDone := false
|
foundSearchResultDone := false
|
||||||
for !foundSearchResultDone {
|
for !foundSearchResultDone {
|
||||||
l.Debug.Printf("%d: waiting for response", messageID)
|
l.Debug.Printf("%d: waiting for response", msgCtx.id)
|
||||||
packetResponse, ok := <-channel
|
packetResponse, ok := <-msgCtx.responses
|
||||||
if !ok {
|
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()
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
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))
|
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
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue