mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
version bump go-ldap to v2.2.1
This commit is contained in:
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
@@ -159,8 +159,8 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-ldap/ldap",
|
||||
"Comment": "v1-19-g83e6542",
|
||||
"Rev": "83e65426fd1c06626e88aa8a085e5bfed0208e29"
|
||||
"Comment": "v2.2.1",
|
||||
"Rev": "07a7330929b9ee80495c88a4439657d89c7dbd87"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/binding",
|
||||
|
||||
5
Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml
generated
vendored
5
Godeps/_workspace/src/github.com/go-ldap/ldap/.travis.yml
generated
vendored
@@ -2,10 +2,13 @@ language: go
|
||||
go:
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
- tip
|
||||
go_import_path: gopkg.in/ldap.v2
|
||||
install:
|
||||
- go get gopkg.in/asn1-ber.v1
|
||||
- go get gopkg.in/ldap.v1
|
||||
- go get gopkg.in/ldap.v2
|
||||
- go get code.google.com/p/go.tools/cmd/cover || go get golang.org/x/tools/cmd/cover
|
||||
- go build -v ./...
|
||||
script:
|
||||
|
||||
41
Godeps/_workspace/src/github.com/go-ldap/ldap/README.md
generated
vendored
41
Godeps/_workspace/src/github.com/go-ldap/ldap/README.md
generated
vendored
@@ -1,8 +1,20 @@
|
||||
[](https://godoc.org/gopkg.in/ldap.v1) [](https://travis-ci.org/go-ldap/ldap)
|
||||
[](https://godoc.org/gopkg.in/ldap.v2)
|
||||
[](https://travis-ci.org/go-ldap/ldap)
|
||||
|
||||
# Basic LDAP v3 functionality for the GO programming language.
|
||||
|
||||
## Required Librarys:
|
||||
## Install
|
||||
|
||||
For the latest version use:
|
||||
|
||||
go get gopkg.in/ldap.v2
|
||||
|
||||
Import the latest version with:
|
||||
|
||||
import "gopkg.in/ldap.v2"
|
||||
|
||||
|
||||
## Required Libraries:
|
||||
|
||||
- gopkg.in/asn1-ber.v1
|
||||
|
||||
@@ -14,6 +26,9 @@
|
||||
- Compiling string filters to LDAP filters
|
||||
- Paging Search Results
|
||||
- Modify Requests / Responses
|
||||
- Add Requests / Responses
|
||||
- Delete Requests / Responses
|
||||
- Better Unicode support
|
||||
|
||||
## Examples:
|
||||
|
||||
@@ -26,23 +41,15 @@
|
||||
|
||||
## TODO:
|
||||
|
||||
- Add Requests / Responses
|
||||
- Delete Requests / Responses
|
||||
- Modify DN Requests / Responses
|
||||
- Compare Requests / Responses
|
||||
- Implement Tests / Benchmarks
|
||||
- [x] Add Requests / Responses
|
||||
- [x] Delete Requests / Responses
|
||||
- [x] Modify DN Requests / Responses
|
||||
- [ ] Compare Requests / Responses
|
||||
- [ ] Implement Tests / Benchmarks
|
||||
|
||||
|
||||
|
||||
---
|
||||
This feature is disabled at the moment, because in some cases the "Search Request Done" packet will be handled before the last "Search Request Entry":
|
||||
|
||||
- Mulitple internal goroutines to handle network traffic
|
||||
Makes library goroutine safe
|
||||
Can perform multiple search requests at the same time and return
|
||||
the results to the proper goroutine. All requests are blocking requests,
|
||||
so the goroutine does not need special handling
|
||||
|
||||
---
|
||||
|
||||
The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/)
|
||||
The design is licensed under the Creative Commons 3.0 Attributions license.
|
||||
Read this article for more details: http://blog.golang.org/gopher
|
||||
|
||||
104
Godeps/_workspace/src/github.com/go-ldap/ldap/add.go
generated
vendored
Normal file
104
Godeps/_workspace/src/github.com/go-ldap/ldap/add.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc4511
|
||||
//
|
||||
// AddRequest ::= [APPLICATION 8] SEQUENCE {
|
||||
// entry LDAPDN,
|
||||
// attributes AttributeList }
|
||||
//
|
||||
// AttributeList ::= SEQUENCE OF attribute Attribute
|
||||
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
|
||||
type Attribute struct {
|
||||
attrType string
|
||||
attrVals []string
|
||||
}
|
||||
|
||||
func (a *Attribute) encode() *ber.Packet {
|
||||
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute")
|
||||
seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.attrType, "Type"))
|
||||
set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
|
||||
for _, value := range a.attrVals {
|
||||
set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
|
||||
}
|
||||
seq.AppendChild(set)
|
||||
return seq
|
||||
}
|
||||
|
||||
type AddRequest struct {
|
||||
dn string
|
||||
attributes []Attribute
|
||||
}
|
||||
|
||||
func (a AddRequest) encode() *ber.Packet {
|
||||
request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationAddRequest, nil, "Add Request")
|
||||
request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, a.dn, "DN"))
|
||||
attributes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
|
||||
for _, attribute := range a.attributes {
|
||||
attributes.AppendChild(attribute.encode())
|
||||
}
|
||||
request.AppendChild(attributes)
|
||||
return request
|
||||
}
|
||||
|
||||
func (a *AddRequest) Attribute(attrType string, attrVals []string) {
|
||||
a.attributes = append(a.attributes, Attribute{attrType: attrType, attrVals: attrVals})
|
||||
}
|
||||
|
||||
func NewAddRequest(dn string) *AddRequest {
|
||||
return &AddRequest{
|
||||
dn: dn,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (l *Conn) Add(addRequest *AddRequest) error {
|
||||
messageID := l.nextMessageID()
|
||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
|
||||
packet.AppendChild(addRequest.encode())
|
||||
|
||||
l.Debug.PrintPacket(packet)
|
||||
|
||||
channel, err := l.sendMessage(packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channel == nil {
|
||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
||||
}
|
||||
defer l.finishMessage(messageID)
|
||||
|
||||
l.Debug.Printf("%d: waiting for response", messageID)
|
||||
packet = <-channel
|
||||
l.Debug.Printf("%d: got response %p", messageID, packet)
|
||||
if packet == nil {
|
||||
return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
|
||||
}
|
||||
|
||||
if l.Debug {
|
||||
if err := addLDAPDescriptions(packet); err != nil {
|
||||
return err
|
||||
}
|
||||
ber.PrintPacket(packet)
|
||||
}
|
||||
|
||||
if packet.Children[1].Tag == ApplicationAddResponse {
|
||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
||||
if resultCode != 0 {
|
||||
return NewError(resultCode, errors.New(resultDescription))
|
||||
}
|
||||
} else {
|
||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||
}
|
||||
|
||||
l.Debug.Printf("%d: returning", messageID)
|
||||
return nil
|
||||
}
|
||||
23
Godeps/_workspace/src/github.com/go-ldap/ldap/client.go
generated
vendored
Normal file
23
Godeps/_workspace/src/github.com/go-ldap/ldap/client.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package ldap
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// Client knows how to interact with an LDAP server
|
||||
type Client interface {
|
||||
Start()
|
||||
StartTLS(config *tls.Config) error
|
||||
Close()
|
||||
|
||||
Bind(username, password string) error
|
||||
SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResult, error)
|
||||
|
||||
Add(addRequest *AddRequest) error
|
||||
Del(delRequest *DelRequest) error
|
||||
Modify(modifyRequest *ModifyRequest) error
|
||||
|
||||
Compare(dn, attribute, value string) (bool, error)
|
||||
PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*PasswordModifyResult, error)
|
||||
|
||||
Search(searchRequest *SearchRequest) (*SearchResult, error)
|
||||
SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error)
|
||||
}
|
||||
9
Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go
generated
vendored
9
Godeps/_workspace/src/github.com/go-ldap/ldap/conn.go
generated
vendored
@@ -8,11 +8,12 @@ import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
"log"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -53,6 +54,8 @@ type Conn struct {
|
||||
messageMutex sync.Mutex
|
||||
}
|
||||
|
||||
var _ Client = &Conn{}
|
||||
|
||||
// DefaultTimeout is a package-level variable that sets the timeout value
|
||||
// used for the Dial and DialTLS methods.
|
||||
//
|
||||
@@ -176,7 +179,7 @@ func (l *Conn) StartTLS(config *tls.Config) error {
|
||||
ber.PrintPacket(packet)
|
||||
}
|
||||
|
||||
if packet.Children[1].Children[0].Value.(int64) == 0 {
|
||||
if resultCode, message := getLDAPResultCode(packet); resultCode == LDAPResultSuccess {
|
||||
conn := tls.Client(l.conn, config)
|
||||
|
||||
if err := conn.Handshake(); err != nil {
|
||||
@@ -186,6 +189,8 @@ func (l *Conn) StartTLS(config *tls.Config) error {
|
||||
|
||||
l.isTLS = true
|
||||
l.conn = conn
|
||||
} else {
|
||||
return NewError(resultCode, fmt.Errorf("ldap: cannot StartTLS (%s)", message))
|
||||
}
|
||||
go l.reader()
|
||||
|
||||
|
||||
32
Godeps/_workspace/src/github.com/go-ldap/ldap/control.go
generated
vendored
32
Godeps/_workspace/src/github.com/go-ldap/ldap/control.go
generated
vendored
@@ -16,11 +16,13 @@ const (
|
||||
ControlTypeBeheraPasswordPolicy = "1.3.6.1.4.1.42.2.27.8.5.1"
|
||||
ControlTypeVChuPasswordMustChange = "2.16.840.1.113730.3.4.4"
|
||||
ControlTypeVChuPasswordWarning = "2.16.840.1.113730.3.4.5"
|
||||
ControlTypeManageDsaIT = "2.16.840.1.113730.3.4.2"
|
||||
)
|
||||
|
||||
var ControlTypeMap = map[string]string{
|
||||
ControlTypePaging: "Paging",
|
||||
ControlTypeBeheraPasswordPolicy: "Password Policy - Behera Draft",
|
||||
ControlTypeManageDsaIT: "Manage DSA IT",
|
||||
}
|
||||
|
||||
type Control interface {
|
||||
@@ -165,6 +167,36 @@ func (c *ControlVChuPasswordWarning) String() string {
|
||||
c.Expire)
|
||||
}
|
||||
|
||||
type ControlManageDsaIT struct {
|
||||
Criticality bool
|
||||
}
|
||||
|
||||
func (c *ControlManageDsaIT) GetControlType() string {
|
||||
return ControlTypeManageDsaIT
|
||||
}
|
||||
|
||||
func (c *ControlManageDsaIT) Encode() *ber.Packet {
|
||||
//FIXME
|
||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypeManageDsaIT, "Control Type ("+ControlTypeMap[ControlTypeManageDsaIT]+")"))
|
||||
if c.Criticality {
|
||||
packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
|
||||
}
|
||||
return packet
|
||||
}
|
||||
|
||||
func (c *ControlManageDsaIT) String() string {
|
||||
return fmt.Sprintf(
|
||||
"Control Type: %s (%q) Criticality: %t",
|
||||
ControlTypeMap[ControlTypeManageDsaIT],
|
||||
ControlTypeManageDsaIT,
|
||||
c.Criticality)
|
||||
}
|
||||
|
||||
func NewControlManageDsaIT(Criticality bool) *ControlManageDsaIT {
|
||||
return &ControlManageDsaIT{Criticality: Criticality}
|
||||
}
|
||||
|
||||
func FindControl(controls []Control, controlType string) Control {
|
||||
for _, c := range controls {
|
||||
if c.GetControlType() == controlType {
|
||||
|
||||
79
Godeps/_workspace/src/github.com/go-ldap/ldap/del.go
generated
vendored
Normal file
79
Godeps/_workspace/src/github.com/go-ldap/ldap/del.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// https://tools.ietf.org/html/rfc4511
|
||||
//
|
||||
// DelRequest ::= [APPLICATION 10] LDAPDN
|
||||
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
|
||||
type DelRequest struct {
|
||||
DN string
|
||||
Controls []Control
|
||||
}
|
||||
|
||||
func (d DelRequest) encode() *ber.Packet {
|
||||
request := ber.Encode(ber.ClassApplication, ber.TypePrimitive, ApplicationDelRequest, d.DN, "Del Request")
|
||||
request.Data.Write([]byte(d.DN))
|
||||
return request
|
||||
}
|
||||
|
||||
func NewDelRequest(DN string,
|
||||
Controls []Control) *DelRequest {
|
||||
return &DelRequest{
|
||||
DN: DN,
|
||||
Controls: Controls,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Conn) Del(delRequest *DelRequest) error {
|
||||
messageID := l.nextMessageID()
|
||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
|
||||
packet.AppendChild(delRequest.encode())
|
||||
if delRequest.Controls != nil {
|
||||
packet.AppendChild(encodeControls(delRequest.Controls))
|
||||
}
|
||||
|
||||
l.Debug.PrintPacket(packet)
|
||||
|
||||
channel, err := l.sendMessage(packet)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channel == nil {
|
||||
return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
|
||||
}
|
||||
defer l.finishMessage(messageID)
|
||||
|
||||
l.Debug.Printf("%d: waiting for response", messageID)
|
||||
packet = <-channel
|
||||
l.Debug.Printf("%d: got response %p", messageID, packet)
|
||||
if packet == nil {
|
||||
return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
|
||||
}
|
||||
|
||||
if l.Debug {
|
||||
if err := addLDAPDescriptions(packet); err != nil {
|
||||
return err
|
||||
}
|
||||
ber.PrintPacket(packet)
|
||||
}
|
||||
|
||||
if packet.Children[1].Tag == ApplicationDelResponse {
|
||||
resultCode, resultDescription := getLDAPResultCode(packet)
|
||||
if resultCode != 0 {
|
||||
return NewError(resultCode, errors.New(resultDescription))
|
||||
}
|
||||
} else {
|
||||
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
|
||||
}
|
||||
|
||||
l.Debug.Printf("%d: returning", messageID)
|
||||
return nil
|
||||
}
|
||||
12
Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go
generated
vendored
12
Godeps/_workspace/src/github.com/go-ldap/ldap/dn.go
generated
vendored
@@ -47,17 +47,17 @@ package ldap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
enchex "encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
enchex "encoding/hex"
|
||||
|
||||
ber "gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
|
||||
type AttributeTypeAndValue struct {
|
||||
Type string
|
||||
Value string
|
||||
Type string
|
||||
Value string
|
||||
}
|
||||
|
||||
type RelativeDN struct {
|
||||
@@ -71,7 +71,7 @@ type DN struct {
|
||||
func ParseDN(str string) (*DN, error) {
|
||||
dn := new(DN)
|
||||
dn.RDNs = make([]*RelativeDN, 0)
|
||||
rdn := new (RelativeDN)
|
||||
rdn := new(RelativeDN)
|
||||
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
|
||||
buffer := bytes.Buffer{}
|
||||
attribute := new(AttributeTypeAndValue)
|
||||
@@ -115,7 +115,7 @@ func ParseDN(str string) (*DN, error) {
|
||||
index := strings.IndexAny(str[i:], ",+")
|
||||
data := str
|
||||
if index > 0 {
|
||||
data = str[i:i+index]
|
||||
data = str[i : i+index]
|
||||
} else {
|
||||
data = str[i:]
|
||||
}
|
||||
@@ -126,7 +126,7 @@ func ParseDN(str string) (*DN, error) {
|
||||
}
|
||||
packet := ber.DecodePacket(raw_ber)
|
||||
buffer.WriteString(packet.Data.String())
|
||||
i += len(data)-1
|
||||
i += len(data) - 1
|
||||
}
|
||||
} else if char == ',' || char == '+' {
|
||||
// We're done with this RDN or value, push it
|
||||
|
||||
66
Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go
generated
vendored
66
Godeps/_workspace/src/github.com/go-ldap/ldap/dn_test.go
generated
vendored
@@ -1,38 +1,40 @@
|
||||
package ldap
|
||||
package ldap_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
func TestSuccessfulDNParsing(t *testing.T) {
|
||||
testcases := map[string]DN {
|
||||
"": DN{[]*RelativeDN{}},
|
||||
"cn=Jim\\2C \\22Hasse Hö\\22 Hansson!,dc=dummy,dc=com": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"cn", "Jim, \"Hasse Hö\" Hansson!"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"dc", "dummy"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"dc", "com"}, }},}},
|
||||
"UID=jsmith,DC=example,DC=net": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"UID", "jsmith"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"DC", "example"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"DC", "net"}, }},}},
|
||||
"OU=Sales+CN=J. Smith,DC=example,DC=net": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{
|
||||
&AttributeTypeAndValue{"OU", "Sales"},
|
||||
&AttributeTypeAndValue{"CN", "J. Smith"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"DC", "example"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"DC", "net"}, }},}},
|
||||
"1.3.6.1.4.1.1466.0=#04024869": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"},}},}},
|
||||
"1.3.6.1.4.1.1466.0=#04024869,DC=net": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"},}},
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"DC", "net"}, }},}},
|
||||
"CN=Lu\\C4\\8Di\\C4\\87": DN{[]*RelativeDN{
|
||||
&RelativeDN{[]*AttributeTypeAndValue{&AttributeTypeAndValue{"CN", "Lučić"},}},}},
|
||||
testcases := map[string]ldap.DN{
|
||||
"": ldap.DN{[]*ldap.RelativeDN{}},
|
||||
"cn=Jim\\2C \\22Hasse Hö\\22 Hansson!,dc=dummy,dc=com": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"cn", "Jim, \"Hasse Hö\" Hansson!"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "dummy"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"dc", "com"}}}}},
|
||||
"UID=jsmith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"UID", "jsmith"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
|
||||
"OU=Sales+CN=J. Smith,DC=example,DC=net": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
|
||||
&ldap.AttributeTypeAndValue{"OU", "Sales"},
|
||||
&ldap.AttributeTypeAndValue{"CN", "J. Smith"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "example"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
|
||||
"1.3.6.1.4.1.1466.0=#04024869": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}}}},
|
||||
"1.3.6.1.4.1.1466.0=#04024869,DC=net": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"1.3.6.1.4.1.1466.0", "Hi"}}},
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
|
||||
"CN=Lu\\C4\\8Di\\C4\\87": ldap.DN{[]*ldap.RelativeDN{
|
||||
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}},
|
||||
}
|
||||
|
||||
for test, answer := range testcases {
|
||||
dn, err := ParseDN(test)
|
||||
dn, err := ldap.ParseDN(test)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
continue
|
||||
@@ -49,16 +51,16 @@ func TestSuccessfulDNParsing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestErrorDNParsing(t *testing.T) {
|
||||
testcases := map[string]string {
|
||||
"*": "DN ended with incomplete type, value pair",
|
||||
"cn=Jim\\0Test": "Failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'",
|
||||
"cn=Jim\\0": "Got corrupted escaped character",
|
||||
testcases := map[string]string{
|
||||
"*": "DN ended with incomplete type, value pair",
|
||||
"cn=Jim\\0Test": "Failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'",
|
||||
"cn=Jim\\0": "Got corrupted escaped character",
|
||||
"DC=example,=net": "DN ended with incomplete type, value pair",
|
||||
"1=#0402486": "Failed to decode BER encoding: encoding/hex: odd length hex string",
|
||||
"1=#0402486": "Failed to decode BER encoding: encoding/hex: odd length hex string",
|
||||
}
|
||||
|
||||
for test, answer := range testcases {
|
||||
_, err := ParseDN(test)
|
||||
_, err := ldap.ParseDN(test)
|
||||
if err == nil {
|
||||
t.Errorf("Expected %s to fail parsing but succeeded\n", test)
|
||||
} else if err.Error() != answer {
|
||||
@@ -66,5 +68,3 @@ func TestErrorDNParsing(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
137
Godeps/_workspace/src/github.com/go-ldap/ldap/error.go
generated
vendored
Normal file
137
Godeps/_workspace/src/github.com/go-ldap/ldap/error.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
|
||||
// LDAP Result Codes
|
||||
const (
|
||||
LDAPResultSuccess = 0
|
||||
LDAPResultOperationsError = 1
|
||||
LDAPResultProtocolError = 2
|
||||
LDAPResultTimeLimitExceeded = 3
|
||||
LDAPResultSizeLimitExceeded = 4
|
||||
LDAPResultCompareFalse = 5
|
||||
LDAPResultCompareTrue = 6
|
||||
LDAPResultAuthMethodNotSupported = 7
|
||||
LDAPResultStrongAuthRequired = 8
|
||||
LDAPResultReferral = 10
|
||||
LDAPResultAdminLimitExceeded = 11
|
||||
LDAPResultUnavailableCriticalExtension = 12
|
||||
LDAPResultConfidentialityRequired = 13
|
||||
LDAPResultSaslBindInProgress = 14
|
||||
LDAPResultNoSuchAttribute = 16
|
||||
LDAPResultUndefinedAttributeType = 17
|
||||
LDAPResultInappropriateMatching = 18
|
||||
LDAPResultConstraintViolation = 19
|
||||
LDAPResultAttributeOrValueExists = 20
|
||||
LDAPResultInvalidAttributeSyntax = 21
|
||||
LDAPResultNoSuchObject = 32
|
||||
LDAPResultAliasProblem = 33
|
||||
LDAPResultInvalidDNSyntax = 34
|
||||
LDAPResultAliasDereferencingProblem = 36
|
||||
LDAPResultInappropriateAuthentication = 48
|
||||
LDAPResultInvalidCredentials = 49
|
||||
LDAPResultInsufficientAccessRights = 50
|
||||
LDAPResultBusy = 51
|
||||
LDAPResultUnavailable = 52
|
||||
LDAPResultUnwillingToPerform = 53
|
||||
LDAPResultLoopDetect = 54
|
||||
LDAPResultNamingViolation = 64
|
||||
LDAPResultObjectClassViolation = 65
|
||||
LDAPResultNotAllowedOnNonLeaf = 66
|
||||
LDAPResultNotAllowedOnRDN = 67
|
||||
LDAPResultEntryAlreadyExists = 68
|
||||
LDAPResultObjectClassModsProhibited = 69
|
||||
LDAPResultAffectsMultipleDSAs = 71
|
||||
LDAPResultOther = 80
|
||||
|
||||
ErrorNetwork = 200
|
||||
ErrorFilterCompile = 201
|
||||
ErrorFilterDecompile = 202
|
||||
ErrorDebugging = 203
|
||||
ErrorUnexpectedMessage = 204
|
||||
ErrorUnexpectedResponse = 205
|
||||
)
|
||||
|
||||
var LDAPResultCodeMap = map[uint8]string{
|
||||
LDAPResultSuccess: "Success",
|
||||
LDAPResultOperationsError: "Operations Error",
|
||||
LDAPResultProtocolError: "Protocol Error",
|
||||
LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
|
||||
LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
|
||||
LDAPResultCompareFalse: "Compare False",
|
||||
LDAPResultCompareTrue: "Compare True",
|
||||
LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
|
||||
LDAPResultStrongAuthRequired: "Strong Auth Required",
|
||||
LDAPResultReferral: "Referral",
|
||||
LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
|
||||
LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
|
||||
LDAPResultConfidentialityRequired: "Confidentiality Required",
|
||||
LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
|
||||
LDAPResultNoSuchAttribute: "No Such Attribute",
|
||||
LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
|
||||
LDAPResultInappropriateMatching: "Inappropriate Matching",
|
||||
LDAPResultConstraintViolation: "Constraint Violation",
|
||||
LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
|
||||
LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
|
||||
LDAPResultNoSuchObject: "No Such Object",
|
||||
LDAPResultAliasProblem: "Alias Problem",
|
||||
LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
|
||||
LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
|
||||
LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
|
||||
LDAPResultInvalidCredentials: "Invalid Credentials",
|
||||
LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
|
||||
LDAPResultBusy: "Busy",
|
||||
LDAPResultUnavailable: "Unavailable",
|
||||
LDAPResultUnwillingToPerform: "Unwilling To Perform",
|
||||
LDAPResultLoopDetect: "Loop Detect",
|
||||
LDAPResultNamingViolation: "Naming Violation",
|
||||
LDAPResultObjectClassViolation: "Object Class Violation",
|
||||
LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
|
||||
LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
|
||||
LDAPResultEntryAlreadyExists: "Entry Already Exists",
|
||||
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
||||
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
||||
LDAPResultOther: "Other",
|
||||
}
|
||||
|
||||
func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
||||
if len(packet.Children) >= 2 {
|
||||
response := packet.Children[1]
|
||||
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
||||
// Children[1].Children[2] is the diagnosticMessage which is guaranteed to exist as seen here: https://tools.ietf.org/html/rfc4511#section-4.1.9
|
||||
return uint8(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
|
||||
}
|
||||
}
|
||||
|
||||
return ErrorNetwork, "Invalid packet format"
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Err error
|
||||
ResultCode uint8
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
||||
}
|
||||
|
||||
func NewError(resultCode uint8, err error) error {
|
||||
return &Error{ResultCode: resultCode, Err: err}
|
||||
}
|
||||
|
||||
func IsErrorWithCode(err error, desiredResultCode uint8) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
serverError, ok := err.(*Error)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return serverError.ResultCode == desiredResultCode
|
||||
}
|
||||
4
Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go
generated
vendored
4
Godeps/_workspace/src/github.com/go-ldap/ldap/example_test.go
generated
vendored
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/go-ldap/ldap"
|
||||
"gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
// ExampleConn_Bind demonstrats how to bind a connection to an ldap user
|
||||
// ExampleConn_Bind demonstrates how to bind a connection to an ldap user
|
||||
// allowing access to restricted attrabutes that user has access to
|
||||
func ExampleConn_Bind() {
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", "ldap.example.com", 389))
|
||||
|
||||
272
Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
generated
vendored
272
Godeps/_workspace/src/github.com/go-ldap/ldap/filter.go
generated
vendored
@@ -5,9 +5,12 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
hexpac "encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
)
|
||||
@@ -50,6 +53,20 @@ var FilterSubstringsMap = map[uint64]string{
|
||||
FilterSubstringsFinal: "Substrings Final",
|
||||
}
|
||||
|
||||
const (
|
||||
MatchingRuleAssertionMatchingRule = 1
|
||||
MatchingRuleAssertionType = 2
|
||||
MatchingRuleAssertionMatchValue = 3
|
||||
MatchingRuleAssertionDNAttributes = 4
|
||||
)
|
||||
|
||||
var MatchingRuleAssertionMap = map[uint64]string{
|
||||
MatchingRuleAssertionMatchingRule: "Matching Rule Assertion Matching Rule",
|
||||
MatchingRuleAssertionType: "Matching Rule Assertion Type",
|
||||
MatchingRuleAssertionMatchValue: "Matching Rule Assertion Match Value",
|
||||
MatchingRuleAssertionDNAttributes: "Matching Rule Assertion DN Attributes",
|
||||
}
|
||||
|
||||
func CompileFilter(filter string) (*ber.Packet, error) {
|
||||
if len(filter) == 0 || filter[0] != '(' {
|
||||
return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
|
||||
@@ -108,7 +125,7 @@ func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
||||
if i == 0 && child.Tag != FilterSubstringsInitial {
|
||||
ret += "*"
|
||||
}
|
||||
ret += ber.DecodeString(child.Data.Bytes())
|
||||
ret += EscapeFilter(ber.DecodeString(child.Data.Bytes()))
|
||||
if child.Tag != FilterSubstringsFinal {
|
||||
ret += "*"
|
||||
}
|
||||
@@ -116,22 +133,53 @@ func DecompileFilter(packet *ber.Packet) (ret string, err error) {
|
||||
case FilterEqualityMatch:
|
||||
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
||||
ret += "="
|
||||
ret += ber.DecodeString(packet.Children[1].Data.Bytes())
|
||||
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
||||
case FilterGreaterOrEqual:
|
||||
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
||||
ret += ">="
|
||||
ret += ber.DecodeString(packet.Children[1].Data.Bytes())
|
||||
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
||||
case FilterLessOrEqual:
|
||||
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
||||
ret += "<="
|
||||
ret += ber.DecodeString(packet.Children[1].Data.Bytes())
|
||||
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
||||
case FilterPresent:
|
||||
ret += ber.DecodeString(packet.Data.Bytes())
|
||||
ret += "=*"
|
||||
case FilterApproxMatch:
|
||||
ret += ber.DecodeString(packet.Children[0].Data.Bytes())
|
||||
ret += "~="
|
||||
ret += ber.DecodeString(packet.Children[1].Data.Bytes())
|
||||
ret += EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes()))
|
||||
case FilterExtensibleMatch:
|
||||
attr := ""
|
||||
dnAttributes := false
|
||||
matchingRule := ""
|
||||
value := ""
|
||||
|
||||
for _, child := range packet.Children {
|
||||
switch child.Tag {
|
||||
case MatchingRuleAssertionMatchingRule:
|
||||
matchingRule = ber.DecodeString(child.Data.Bytes())
|
||||
case MatchingRuleAssertionType:
|
||||
attr = ber.DecodeString(child.Data.Bytes())
|
||||
case MatchingRuleAssertionMatchValue:
|
||||
value = ber.DecodeString(child.Data.Bytes())
|
||||
case MatchingRuleAssertionDNAttributes:
|
||||
dnAttributes = child.Value.(bool)
|
||||
}
|
||||
}
|
||||
|
||||
if len(attr) > 0 {
|
||||
ret += attr
|
||||
}
|
||||
if dnAttributes {
|
||||
ret += ":dn"
|
||||
}
|
||||
if len(matchingRule) > 0 {
|
||||
ret += ":"
|
||||
ret += matchingRule
|
||||
}
|
||||
ret += ":="
|
||||
ret += EscapeFilter(value)
|
||||
}
|
||||
|
||||
ret += ")"
|
||||
@@ -155,58 +203,143 @@ func compileFilterSet(filter string, pos int, parent *ber.Packet) (int, error) {
|
||||
}
|
||||
|
||||
func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||
var packet *ber.Packet
|
||||
var err error
|
||||
var (
|
||||
packet *ber.Packet
|
||||
err error
|
||||
)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
err = NewError(ErrorFilterCompile, errors.New("ldap: error compiling filter"))
|
||||
}
|
||||
}()
|
||||
|
||||
newPos := pos
|
||||
switch filter[pos] {
|
||||
|
||||
currentRune, currentWidth := utf8.DecodeRuneInString(filter[newPos:])
|
||||
|
||||
switch currentRune {
|
||||
case utf8.RuneError:
|
||||
return nil, 0, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
|
||||
case '(':
|
||||
packet, newPos, err = compileFilter(filter, pos+1)
|
||||
packet, newPos, err = compileFilter(filter, pos+currentWidth)
|
||||
newPos++
|
||||
return packet, newPos, err
|
||||
case '&':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterAnd, nil, FilterMap[FilterAnd])
|
||||
newPos, err = compileFilterSet(filter, pos+1, packet)
|
||||
newPos, err = compileFilterSet(filter, pos+currentWidth, packet)
|
||||
return packet, newPos, err
|
||||
case '|':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterOr, nil, FilterMap[FilterOr])
|
||||
newPos, err = compileFilterSet(filter, pos+1, packet)
|
||||
newPos, err = compileFilterSet(filter, pos+currentWidth, packet)
|
||||
return packet, newPos, err
|
||||
case '!':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterNot, nil, FilterMap[FilterNot])
|
||||
var child *ber.Packet
|
||||
child, newPos, err = compileFilter(filter, pos+1)
|
||||
child, newPos, err = compileFilter(filter, pos+currentWidth)
|
||||
packet.AppendChild(child)
|
||||
return packet, newPos, err
|
||||
default:
|
||||
READING_ATTR := 0
|
||||
READING_EXTENSIBLE_MATCHING_RULE := 1
|
||||
READING_CONDITION := 2
|
||||
|
||||
state := READING_ATTR
|
||||
|
||||
attribute := ""
|
||||
extensibleDNAttributes := false
|
||||
extensibleMatchingRule := ""
|
||||
condition := ""
|
||||
for newPos < len(filter) && filter[newPos] != ')' {
|
||||
switch {
|
||||
case packet != nil:
|
||||
condition += fmt.Sprintf("%c", filter[newPos])
|
||||
case filter[newPos] == '=':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
||||
case filter[newPos] == '>' && filter[newPos+1] == '=':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
||||
newPos++
|
||||
case filter[newPos] == '<' && filter[newPos+1] == '=':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
||||
newPos++
|
||||
case filter[newPos] == '~' && filter[newPos+1] == '=':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterLessOrEqual])
|
||||
newPos++
|
||||
case packet == nil:
|
||||
attribute += fmt.Sprintf("%c", filter[newPos])
|
||||
|
||||
for newPos < len(filter) {
|
||||
remainingFilter := filter[newPos:]
|
||||
currentRune, currentWidth = utf8.DecodeRuneInString(remainingFilter)
|
||||
if currentRune == ')' {
|
||||
break
|
||||
}
|
||||
if currentRune == utf8.RuneError {
|
||||
return packet, newPos, NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", newPos))
|
||||
}
|
||||
|
||||
switch state {
|
||||
case READING_ATTR:
|
||||
switch {
|
||||
// Extensible rule, with only DN-matching
|
||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:="):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||
extensibleDNAttributes = true
|
||||
state = READING_CONDITION
|
||||
newPos += 5
|
||||
|
||||
// Extensible rule, with DN-matching and a matching OID
|
||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":dn:"):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||
extensibleDNAttributes = true
|
||||
state = READING_EXTENSIBLE_MATCHING_RULE
|
||||
newPos += 4
|
||||
|
||||
// Extensible rule, with attr only
|
||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||
state = READING_CONDITION
|
||||
newPos += 2
|
||||
|
||||
// Extensible rule, with no DN attribute matching
|
||||
case currentRune == ':':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterExtensibleMatch, nil, FilterMap[FilterExtensibleMatch])
|
||||
state = READING_EXTENSIBLE_MATCHING_RULE
|
||||
newPos += 1
|
||||
|
||||
// Equality condition
|
||||
case currentRune == '=':
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
|
||||
state = READING_CONDITION
|
||||
newPos += 1
|
||||
|
||||
// Greater-than or equal
|
||||
case currentRune == '>' && strings.HasPrefix(remainingFilter, ">="):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
|
||||
state = READING_CONDITION
|
||||
newPos += 2
|
||||
|
||||
// Less-than or equal
|
||||
case currentRune == '<' && strings.HasPrefix(remainingFilter, "<="):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
|
||||
state = READING_CONDITION
|
||||
newPos += 2
|
||||
|
||||
// Approx
|
||||
case currentRune == '~' && strings.HasPrefix(remainingFilter, "~="):
|
||||
packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterApproxMatch])
|
||||
state = READING_CONDITION
|
||||
newPos += 2
|
||||
|
||||
// Still reading the attribute name
|
||||
default:
|
||||
attribute += fmt.Sprintf("%c", currentRune)
|
||||
newPos += currentWidth
|
||||
}
|
||||
|
||||
case READING_EXTENSIBLE_MATCHING_RULE:
|
||||
switch {
|
||||
|
||||
// Matching rule OID is done
|
||||
case currentRune == ':' && strings.HasPrefix(remainingFilter, ":="):
|
||||
state = READING_CONDITION
|
||||
newPos += 2
|
||||
|
||||
// Still reading the matching rule oid
|
||||
default:
|
||||
extensibleMatchingRule += fmt.Sprintf("%c", currentRune)
|
||||
newPos += currentWidth
|
||||
}
|
||||
|
||||
case READING_CONDITION:
|
||||
// append to the condition
|
||||
condition += fmt.Sprintf("%c", currentRune)
|
||||
newPos += currentWidth
|
||||
}
|
||||
newPos++
|
||||
}
|
||||
|
||||
if newPos == len(filter) {
|
||||
err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
|
||||
return packet, newPos, err
|
||||
@@ -217,6 +350,36 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||
}
|
||||
|
||||
switch {
|
||||
case packet.Tag == FilterExtensibleMatch:
|
||||
// MatchingRuleAssertion ::= SEQUENCE {
|
||||
// matchingRule [1] MatchingRuleID OPTIONAL,
|
||||
// type [2] AttributeDescription OPTIONAL,
|
||||
// matchValue [3] AssertionValue,
|
||||
// dnAttributes [4] BOOLEAN DEFAULT FALSE
|
||||
// }
|
||||
|
||||
// Include the matching rule oid, if specified
|
||||
if len(extensibleMatchingRule) > 0 {
|
||||
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchingRule, extensibleMatchingRule, MatchingRuleAssertionMap[MatchingRuleAssertionMatchingRule]))
|
||||
}
|
||||
|
||||
// Include the attribute, if specified
|
||||
if len(attribute) > 0 {
|
||||
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionType, attribute, MatchingRuleAssertionMap[MatchingRuleAssertionType]))
|
||||
}
|
||||
|
||||
// Add the value (only required child)
|
||||
encodedString, err := escapedStringToEncodedBytes(condition)
|
||||
if err != nil {
|
||||
return packet, newPos, err
|
||||
}
|
||||
packet.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionMatchValue, encodedString, MatchingRuleAssertionMap[MatchingRuleAssertionMatchValue]))
|
||||
|
||||
// Defaults to false, so only include in the sequence if true
|
||||
if extensibleDNAttributes {
|
||||
packet.AppendChild(ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, MatchingRuleAssertionDNAttributes, extensibleDNAttributes, MatchingRuleAssertionMap[MatchingRuleAssertionDNAttributes]))
|
||||
}
|
||||
|
||||
case packet.Tag == FilterEqualityMatch && condition == "*":
|
||||
packet = ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterPresent, attribute, FilterMap[FilterPresent])
|
||||
case packet.Tag == FilterEqualityMatch && strings.Contains(condition, "*"):
|
||||
@@ -238,15 +401,56 @@ func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
|
||||
default:
|
||||
tag = FilterSubstringsAny
|
||||
}
|
||||
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, part, FilterSubstringsMap[uint64(tag)]))
|
||||
encodedString, err := escapedStringToEncodedBytes(part)
|
||||
if err != nil {
|
||||
return packet, newPos, err
|
||||
}
|
||||
seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, tag, encodedString, FilterSubstringsMap[uint64(tag)]))
|
||||
}
|
||||
packet.AppendChild(seq)
|
||||
default:
|
||||
encodedString, err := escapedStringToEncodedBytes(condition)
|
||||
if err != nil {
|
||||
return packet, newPos, err
|
||||
}
|
||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
|
||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, condition, "Condition"))
|
||||
packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, encodedString, "Condition"))
|
||||
}
|
||||
|
||||
newPos++
|
||||
newPos += currentWidth
|
||||
return packet, newPos, err
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from "ABC\xx\xx\xx" form to literal bytes for transport
|
||||
func escapedStringToEncodedBytes(escapedString string) (string, error) {
|
||||
var buffer bytes.Buffer
|
||||
i := 0
|
||||
for i < len(escapedString) {
|
||||
currentRune, currentWidth := utf8.DecodeRuneInString(escapedString[i:])
|
||||
if currentRune == utf8.RuneError {
|
||||
return "", NewError(ErrorFilterCompile, fmt.Errorf("ldap: error reading rune at position %d", i))
|
||||
}
|
||||
|
||||
// Check for escaped hex characters and convert them to their literal value for transport.
|
||||
if currentRune == '\\' {
|
||||
// http://tools.ietf.org/search/rfc4515
|
||||
// \ (%x5C) is not a valid character unless it is followed by two HEX characters due to not
|
||||
// being a member of UTF1SUBSET.
|
||||
if i+2 > len(escapedString) {
|
||||
return "", NewError(ErrorFilterCompile, errors.New("ldap: missing characters for escape in filter"))
|
||||
}
|
||||
if escByte, decodeErr := hexpac.DecodeString(escapedString[i+1 : i+3]); decodeErr != nil {
|
||||
return "", NewError(ErrorFilterCompile, errors.New("ldap: invalid characters for escape in filter"))
|
||||
} else {
|
||||
buffer.WriteByte(escByte[0])
|
||||
i += 2 // +1 from end of loop, so 3 total for \xx.
|
||||
}
|
||||
} else {
|
||||
buffer.WriteRune(currentRune)
|
||||
}
|
||||
|
||||
i += currentWidth
|
||||
}
|
||||
return buffer.String(), nil
|
||||
}
|
||||
|
||||
222
Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go
generated
vendored
222
Godeps/_workspace/src/github.com/go-ldap/ldap/filter_test.go
generated
vendored
@@ -1,54 +1,220 @@
|
||||
package ldap
|
||||
package ldap_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
"gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
type compileTest struct {
|
||||
filterStr string
|
||||
filterType int
|
||||
filterStr string
|
||||
|
||||
expectedFilter string
|
||||
expectedType int
|
||||
expectedErr string
|
||||
}
|
||||
|
||||
var testFilters = []compileTest{
|
||||
compileTest{filterStr: "(&(sn=Miller)(givenName=Bob))", filterType: FilterAnd},
|
||||
compileTest{filterStr: "(|(sn=Miller)(givenName=Bob))", filterType: FilterOr},
|
||||
compileTest{filterStr: "(!(sn=Miller))", filterType: FilterNot},
|
||||
compileTest{filterStr: "(sn=Miller)", filterType: FilterEqualityMatch},
|
||||
compileTest{filterStr: "(sn=Mill*)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=*Mill)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=*Mill*)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=*i*le*)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=Mi*l*r)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=Mi*le*)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn=*i*ler)", filterType: FilterSubstrings},
|
||||
compileTest{filterStr: "(sn>=Miller)", filterType: FilterGreaterOrEqual},
|
||||
compileTest{filterStr: "(sn<=Miller)", filterType: FilterLessOrEqual},
|
||||
compileTest{filterStr: "(sn=*)", filterType: FilterPresent},
|
||||
compileTest{filterStr: "(sn~=Miller)", filterType: FilterApproxMatch},
|
||||
compileTest{
|
||||
filterStr: "(&(sn=Miller)(givenName=Bob))",
|
||||
expectedFilter: "(&(sn=Miller)(givenName=Bob))",
|
||||
expectedType: ldap.FilterAnd,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(|(sn=Miller)(givenName=Bob))",
|
||||
expectedFilter: "(|(sn=Miller)(givenName=Bob))",
|
||||
expectedType: ldap.FilterOr,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(!(sn=Miller))",
|
||||
expectedFilter: "(!(sn=Miller))",
|
||||
expectedType: ldap.FilterNot,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=Miller)",
|
||||
expectedFilter: "(sn=Miller)",
|
||||
expectedType: ldap.FilterEqualityMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=Mill*)",
|
||||
expectedFilter: "(sn=Mill*)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=*Mill)",
|
||||
expectedFilter: "(sn=*Mill)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=*Mill*)",
|
||||
expectedFilter: "(sn=*Mill*)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=*i*le*)",
|
||||
expectedFilter: "(sn=*i*le*)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=Mi*l*r)",
|
||||
expectedFilter: "(sn=Mi*l*r)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
// substring filters escape properly
|
||||
compileTest{
|
||||
filterStr: `(sn=Mi*함*r)`,
|
||||
expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
// already escaped substring filters don't get double-escaped
|
||||
compileTest{
|
||||
filterStr: `(sn=Mi*\ed\95\a8*r)`,
|
||||
expectedFilter: `(sn=Mi*\ed\95\a8*r)`,
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=Mi*le*)",
|
||||
expectedFilter: "(sn=Mi*le*)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=*i*ler)",
|
||||
expectedFilter: "(sn=*i*ler)",
|
||||
expectedType: ldap.FilterSubstrings,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn>=Miller)",
|
||||
expectedFilter: "(sn>=Miller)",
|
||||
expectedType: ldap.FilterGreaterOrEqual,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn<=Miller)",
|
||||
expectedFilter: "(sn<=Miller)",
|
||||
expectedType: ldap.FilterLessOrEqual,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn=*)",
|
||||
expectedFilter: "(sn=*)",
|
||||
expectedType: ldap.FilterPresent,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: "(sn~=Miller)",
|
||||
expectedFilter: "(sn~=Miller)",
|
||||
expectedType: ldap.FilterApproxMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
|
||||
expectedFilter: `(objectGUID='\fc\fe\a3\ab\f9\90N\aaGm\d5I~\d12)`,
|
||||
expectedType: ldap.FilterEqualityMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(objectGUID=абвгдеёжзийклмнопрстуфхцчшщъыьэюя)`,
|
||||
expectedFilter: `(objectGUID=\d0\b0\d0\b1\d0\b2\d0\b3\d0\b4\d0\b5\d1\91\d0\b6\d0\b7\d0\b8\d0\b9\d0\ba\d0\bb\d0\bc\d0\bd\d0\be\d0\bf\d1\80\d1\81\d1\82\d1\83\d1\84\d1\85\d1\86\d1\87\d1\88\d1\89\d1\8a\d1\8b\d1\8c\d1\8d\d1\8e\d1\8f)`,
|
||||
expectedType: ldap.FilterEqualityMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(objectGUID=함수목록)`,
|
||||
expectedFilter: `(objectGUID=\ed\95\a8\ec\88\98\eb\aa\a9\eb\a1\9d)`,
|
||||
expectedType: ldap.FilterEqualityMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(objectGUID=`,
|
||||
expectedFilter: ``,
|
||||
expectedType: 0,
|
||||
expectedErr: "unexpected end of filter",
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(objectGUID=함수목록`,
|
||||
expectedFilter: ``,
|
||||
expectedType: 0,
|
||||
expectedErr: "unexpected end of filter",
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(&(objectclass=inetorgperson)(cn=中文))`,
|
||||
expectedFilter: `(&(objectclass=inetorgperson)(cn=\e4\b8\ad\e6\96\87))`,
|
||||
expectedType: 0,
|
||||
},
|
||||
// attr extension
|
||||
compileTest{
|
||||
filterStr: `(memberOf:=foo)`,
|
||||
expectedFilter: `(memberOf:=foo)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
// attr+named matching rule extension
|
||||
compileTest{
|
||||
filterStr: `(memberOf:test:=foo)`,
|
||||
expectedFilter: `(memberOf:test:=foo)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
// attr+oid matching rule extension
|
||||
compileTest{
|
||||
filterStr: `(cn:1.2.3.4.5:=Fred Flintstone)`,
|
||||
expectedFilter: `(cn:1.2.3.4.5:=Fred Flintstone)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
// attr+dn+oid matching rule extension
|
||||
compileTest{
|
||||
filterStr: `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
|
||||
expectedFilter: `(sn:dn:2.4.6.8.10:=Barney Rubble)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
// attr+dn extension
|
||||
compileTest{
|
||||
filterStr: `(o:dn:=Ace Industry)`,
|
||||
expectedFilter: `(o:dn:=Ace Industry)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
// dn extension
|
||||
compileTest{
|
||||
filterStr: `(:dn:2.4.6.8.10:=Dino)`,
|
||||
expectedFilter: `(:dn:2.4.6.8.10:=Dino)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
compileTest{
|
||||
filterStr: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
|
||||
expectedFilter: `(memberOf:1.2.840.113556.1.4.1941:=CN=User1,OU=blah,DC=mydomain,DC=net)`,
|
||||
expectedType: ldap.FilterExtensibleMatch,
|
||||
},
|
||||
|
||||
// compileTest{ filterStr: "()", filterType: FilterExtensibleMatch },
|
||||
}
|
||||
|
||||
var testInvalidFilters = []string{
|
||||
`(objectGUID=\zz)`,
|
||||
`(objectGUID=\a)`,
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
// Test Compiler and Decompiler
|
||||
for _, i := range testFilters {
|
||||
filter, err := CompileFilter(i.filterStr)
|
||||
filter, err := ldap.CompileFilter(i.filterStr)
|
||||
if err != nil {
|
||||
t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
|
||||
} else if filter.Tag != ber.Tag(i.filterType) {
|
||||
t.Errorf("%q Expected %q got %q", i.filterStr, FilterMap[uint64(i.filterType)], FilterMap[uint64(filter.Tag)])
|
||||
if i.expectedErr == "" || !strings.Contains(err.Error(), i.expectedErr) {
|
||||
t.Errorf("Problem compiling '%s' - '%v' (expected error to contain '%v')", i.filterStr, err, i.expectedErr)
|
||||
}
|
||||
} else if filter.Tag != ber.Tag(i.expectedType) {
|
||||
t.Errorf("%q Expected %q got %q", i.filterStr, ldap.FilterMap[uint64(i.expectedType)], ldap.FilterMap[uint64(filter.Tag)])
|
||||
} else {
|
||||
o, err := DecompileFilter(filter)
|
||||
o, err := ldap.DecompileFilter(filter)
|
||||
if err != nil {
|
||||
t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
|
||||
} else if i.filterStr != o {
|
||||
t.Errorf("%q expected, got %q", i.filterStr, o)
|
||||
} else if i.expectedFilter != o {
|
||||
t.Errorf("%q expected, got %q", i.expectedFilter, o)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidFilter(t *testing.T) {
|
||||
for _, filterStr := range testInvalidFilters {
|
||||
if _, err := ldap.CompileFilter(filterStr); err == nil {
|
||||
t.Errorf("Problem compiling %s - expected err", filterStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkFilterCompile(b *testing.B) {
|
||||
b.StopTimer()
|
||||
filters := make([]string, len(testFilters))
|
||||
@@ -61,7 +227,7 @@ func BenchmarkFilterCompile(b *testing.B) {
|
||||
maxIdx := len(filters)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompileFilter(filters[i%maxIdx])
|
||||
ldap.CompileFilter(filters[i%maxIdx])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,12 +237,12 @@ func BenchmarkFilterDecompile(b *testing.B) {
|
||||
|
||||
// Test Compiler and Decompiler
|
||||
for idx, i := range testFilters {
|
||||
filters[idx], _ = CompileFilter(i.filterStr)
|
||||
filters[idx], _ = ldap.CompileFilter(i.filterStr)
|
||||
}
|
||||
|
||||
maxIdx := len(filters)
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
DecompileFilter(filters[i%maxIdx])
|
||||
ldap.DecompileFilter(filters[i%maxIdx])
|
||||
}
|
||||
}
|
||||
|
||||
121
Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go
generated
vendored
121
Godeps/_workspace/src/github.com/go-ldap/ldap/ldap.go
generated
vendored
@@ -6,7 +6,6 @@ package ldap
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
@@ -60,98 +59,6 @@ var ApplicationMap = map[uint8]string{
|
||||
ApplicationExtendedResponse: "Extended Response",
|
||||
}
|
||||
|
||||
// LDAP Result Codes
|
||||
const (
|
||||
LDAPResultSuccess = 0
|
||||
LDAPResultOperationsError = 1
|
||||
LDAPResultProtocolError = 2
|
||||
LDAPResultTimeLimitExceeded = 3
|
||||
LDAPResultSizeLimitExceeded = 4
|
||||
LDAPResultCompareFalse = 5
|
||||
LDAPResultCompareTrue = 6
|
||||
LDAPResultAuthMethodNotSupported = 7
|
||||
LDAPResultStrongAuthRequired = 8
|
||||
LDAPResultReferral = 10
|
||||
LDAPResultAdminLimitExceeded = 11
|
||||
LDAPResultUnavailableCriticalExtension = 12
|
||||
LDAPResultConfidentialityRequired = 13
|
||||
LDAPResultSaslBindInProgress = 14
|
||||
LDAPResultNoSuchAttribute = 16
|
||||
LDAPResultUndefinedAttributeType = 17
|
||||
LDAPResultInappropriateMatching = 18
|
||||
LDAPResultConstraintViolation = 19
|
||||
LDAPResultAttributeOrValueExists = 20
|
||||
LDAPResultInvalidAttributeSyntax = 21
|
||||
LDAPResultNoSuchObject = 32
|
||||
LDAPResultAliasProblem = 33
|
||||
LDAPResultInvalidDNSyntax = 34
|
||||
LDAPResultAliasDereferencingProblem = 36
|
||||
LDAPResultInappropriateAuthentication = 48
|
||||
LDAPResultInvalidCredentials = 49
|
||||
LDAPResultInsufficientAccessRights = 50
|
||||
LDAPResultBusy = 51
|
||||
LDAPResultUnavailable = 52
|
||||
LDAPResultUnwillingToPerform = 53
|
||||
LDAPResultLoopDetect = 54
|
||||
LDAPResultNamingViolation = 64
|
||||
LDAPResultObjectClassViolation = 65
|
||||
LDAPResultNotAllowedOnNonLeaf = 66
|
||||
LDAPResultNotAllowedOnRDN = 67
|
||||
LDAPResultEntryAlreadyExists = 68
|
||||
LDAPResultObjectClassModsProhibited = 69
|
||||
LDAPResultAffectsMultipleDSAs = 71
|
||||
LDAPResultOther = 80
|
||||
|
||||
ErrorNetwork = 200
|
||||
ErrorFilterCompile = 201
|
||||
ErrorFilterDecompile = 202
|
||||
ErrorDebugging = 203
|
||||
ErrorUnexpectedMessage = 204
|
||||
ErrorUnexpectedResponse = 205
|
||||
)
|
||||
|
||||
var LDAPResultCodeMap = map[uint8]string{
|
||||
LDAPResultSuccess: "Success",
|
||||
LDAPResultOperationsError: "Operations Error",
|
||||
LDAPResultProtocolError: "Protocol Error",
|
||||
LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
|
||||
LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
|
||||
LDAPResultCompareFalse: "Compare False",
|
||||
LDAPResultCompareTrue: "Compare True",
|
||||
LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
|
||||
LDAPResultStrongAuthRequired: "Strong Auth Required",
|
||||
LDAPResultReferral: "Referral",
|
||||
LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
|
||||
LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
|
||||
LDAPResultConfidentialityRequired: "Confidentiality Required",
|
||||
LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
|
||||
LDAPResultNoSuchAttribute: "No Such Attribute",
|
||||
LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
|
||||
LDAPResultInappropriateMatching: "Inappropriate Matching",
|
||||
LDAPResultConstraintViolation: "Constraint Violation",
|
||||
LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
|
||||
LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
|
||||
LDAPResultNoSuchObject: "No Such Object",
|
||||
LDAPResultAliasProblem: "Alias Problem",
|
||||
LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
|
||||
LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
|
||||
LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
|
||||
LDAPResultInvalidCredentials: "Invalid Credentials",
|
||||
LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
|
||||
LDAPResultBusy: "Busy",
|
||||
LDAPResultUnavailable: "Unavailable",
|
||||
LDAPResultUnwillingToPerform: "Unwilling To Perform",
|
||||
LDAPResultLoopDetect: "Loop Detect",
|
||||
LDAPResultNamingViolation: "Naming Violation",
|
||||
LDAPResultObjectClassViolation: "Object Class Violation",
|
||||
LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
|
||||
LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
|
||||
LDAPResultEntryAlreadyExists: "Entry Already Exists",
|
||||
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
||||
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
||||
LDAPResultOther: "Other",
|
||||
}
|
||||
|
||||
// Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10)
|
||||
const (
|
||||
BeheraPasswordExpired = 0
|
||||
@@ -318,8 +225,8 @@ func addRequestDescriptions(packet *ber.Packet) {
|
||||
}
|
||||
|
||||
func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
|
||||
resultCode := packet.Children[1].Children[0].Value.(int64)
|
||||
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[uint8(resultCode)] + ")"
|
||||
resultCode, _ := getLDAPResultCode(packet)
|
||||
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
|
||||
packet.Children[1].Children[1].Description = "Matched DN"
|
||||
packet.Children[1].Children[2].Description = "Error Message"
|
||||
if len(packet.Children[1].Children) > 3 {
|
||||
@@ -343,30 +250,6 @@ func DebugBinaryFile(fileName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
Err error
|
||||
ResultCode uint8
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
||||
}
|
||||
|
||||
func NewError(resultCode uint8, err error) error {
|
||||
return &Error{ResultCode: resultCode, Err: err}
|
||||
}
|
||||
|
||||
func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
||||
if len(packet.Children) >= 2 {
|
||||
response := packet.Children[1]
|
||||
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
|
||||
return uint8(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
|
||||
}
|
||||
}
|
||||
|
||||
return ErrorNetwork, "Invalid packet format"
|
||||
}
|
||||
|
||||
var hex = "0123456789abcdef"
|
||||
|
||||
func mustEscape(c byte) bool {
|
||||
|
||||
78
Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go
generated
vendored
78
Godeps/_workspace/src/github.com/go-ldap/ldap/ldap_test.go
generated
vendored
@@ -1,9 +1,11 @@
|
||||
package ldap
|
||||
package ldap_test
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/ldap.v2"
|
||||
)
|
||||
|
||||
var ldapServer = "ldap.itd.umich.edu"
|
||||
@@ -21,7 +23,7 @@ var attributes = []string{
|
||||
|
||||
func TestDial(t *testing.T) {
|
||||
fmt.Printf("TestDial: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
@@ -32,7 +34,7 @@ func TestDial(t *testing.T) {
|
||||
|
||||
func TestDialTLS(t *testing.T) {
|
||||
fmt.Printf("TestDialTLS: starting...\n")
|
||||
l, err := DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
|
||||
l, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
@@ -43,7 +45,7 @@ func TestDialTLS(t *testing.T) {
|
||||
|
||||
func TestStartTLS(t *testing.T) {
|
||||
fmt.Printf("TestStartTLS: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
@@ -58,16 +60,16 @@ func TestStartTLS(t *testing.T) {
|
||||
|
||||
func TestSearch(t *testing.T) {
|
||||
fmt.Printf("TestSearch: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
searchRequest := NewSearchRequest(
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ScopeWholeSubtree, DerefAlways, 0, 0, false,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[0],
|
||||
attributes,
|
||||
nil)
|
||||
@@ -83,16 +85,16 @@ func TestSearch(t *testing.T) {
|
||||
|
||||
func TestSearchStartTLS(t *testing.T) {
|
||||
fmt.Printf("TestSearchStartTLS: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
searchRequest := NewSearchRequest(
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ScopeWholeSubtree, DerefAlways, 0, 0, false,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[0],
|
||||
attributes,
|
||||
nil)
|
||||
@@ -123,7 +125,7 @@ func TestSearchStartTLS(t *testing.T) {
|
||||
|
||||
func TestSearchWithPaging(t *testing.T) {
|
||||
fmt.Printf("TestSearchWithPaging: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
@@ -136,9 +138,9 @@ func TestSearchWithPaging(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
searchRequest := NewSearchRequest(
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ScopeWholeSubtree, DerefAlways, 0, 0, false,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[2],
|
||||
attributes,
|
||||
nil)
|
||||
@@ -149,12 +151,38 @@ func TestSearchWithPaging(t *testing.T) {
|
||||
}
|
||||
|
||||
fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
|
||||
|
||||
searchRequest = ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[2],
|
||||
attributes,
|
||||
[]ldap.Control{ldap.NewControlPaging(5)})
|
||||
sr, err = l.SearchWithPaging(searchRequest, 5)
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
|
||||
|
||||
searchRequest = ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[2],
|
||||
attributes,
|
||||
[]ldap.Control{ldap.NewControlPaging(500)})
|
||||
sr, err = l.SearchWithPaging(searchRequest, 5)
|
||||
if err == nil {
|
||||
t.Errorf("expected an error when paging size in control in search request doesn't match size given in call, got none")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func searchGoroutine(t *testing.T, l *Conn, results chan *SearchResult, i int) {
|
||||
searchRequest := NewSearchRequest(
|
||||
func searchGoroutine(t *testing.T, l *ldap.Conn, results chan *ldap.SearchResult, i int) {
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
baseDN,
|
||||
ScopeWholeSubtree, DerefAlways, 0, 0, false,
|
||||
ldap.ScopeWholeSubtree, ldap.DerefAlways, 0, 0, false,
|
||||
filter[i],
|
||||
attributes,
|
||||
nil)
|
||||
@@ -169,17 +197,17 @@ func searchGoroutine(t *testing.T, l *Conn, results chan *SearchResult, i int) {
|
||||
|
||||
func testMultiGoroutineSearch(t *testing.T, TLS bool, startTLS bool) {
|
||||
fmt.Printf("TestMultiGoroutineSearch: starting...\n")
|
||||
var l *Conn
|
||||
var l *ldap.Conn
|
||||
var err error
|
||||
if TLS {
|
||||
l, err = DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
|
||||
l, err = ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapTLSPort), &tls.Config{InsecureSkipVerify: true})
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
defer l.Close()
|
||||
} else {
|
||||
l, err = Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Errorf(err.Error())
|
||||
return
|
||||
@@ -195,9 +223,9 @@ func testMultiGoroutineSearch(t *testing.T, TLS bool, startTLS bool) {
|
||||
}
|
||||
}
|
||||
|
||||
results := make([]chan *SearchResult, len(filter))
|
||||
results := make([]chan *ldap.SearchResult, len(filter))
|
||||
for i := range filter {
|
||||
results[i] = make(chan *SearchResult)
|
||||
results[i] = make(chan *ldap.SearchResult)
|
||||
go searchGoroutine(t, l, results[i], i)
|
||||
}
|
||||
for i := range filter {
|
||||
@@ -217,17 +245,17 @@ func TestMultiGoroutineSearch(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEscapeFilter(t *testing.T) {
|
||||
if got, want := EscapeFilter("a\x00b(c)d*e\\f"), `a\00b\28c\29d\2ae\5cf`; got != want {
|
||||
if got, want := ldap.EscapeFilter("a\x00b(c)d*e\\f"), `a\00b\28c\29d\2ae\5cf`; got != want {
|
||||
t.Errorf("Got %s, expected %s", want, got)
|
||||
}
|
||||
if got, want := EscapeFilter("Lučić"), `Lu\c4\8di\c4\87`; got != want {
|
||||
if got, want := ldap.EscapeFilter("Lučić"), `Lu\c4\8di\c4\87`; got != want {
|
||||
t.Errorf("Got %s, expected %s", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompare(t *testing.T) {
|
||||
fmt.Printf("TestCompare: starting...\n")
|
||||
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
@@ -243,5 +271,5 @@ func TestCompare(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("TestCompare: -> num of entries = %d\n", sr)
|
||||
fmt.Printf("TestCompare: -> %v\n", sr)
|
||||
}
|
||||
|
||||
61
Godeps/_workspace/src/github.com/go-ldap/ldap/search.go
generated
vendored
61
Godeps/_workspace/src/github.com/go-ldap/ldap/search.go
generated
vendored
@@ -62,6 +62,7 @@ package ldap
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/asn1-ber.v1"
|
||||
@@ -93,6 +94,26 @@ var DerefMap = map[int]string{
|
||||
DerefAlways: "DerefAlways",
|
||||
}
|
||||
|
||||
// NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs.
|
||||
// The map of attributes is accessed in alphabetical order of the keys in order to ensure that, for the
|
||||
// same input map of attributes, the output entry will contain the same order of attributes
|
||||
func NewEntry(dn string, attributes map[string][]string) *Entry {
|
||||
var attributeNames []string
|
||||
for attributeName := range attributes {
|
||||
attributeNames = append(attributeNames, attributeName)
|
||||
}
|
||||
sort.Strings(attributeNames)
|
||||
|
||||
var encodedAttributes []*EntryAttribute
|
||||
for _, attributeName := range attributeNames {
|
||||
encodedAttributes = append(encodedAttributes, NewEntryAttribute(attributeName, attributes[attributeName]))
|
||||
}
|
||||
return &Entry{
|
||||
DN: dn,
|
||||
Attributes: encodedAttributes,
|
||||
}
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
DN string
|
||||
Attributes []*EntryAttribute
|
||||
@@ -146,6 +167,19 @@ func (e *Entry) PrettyPrint(indent int) {
|
||||
}
|
||||
}
|
||||
|
||||
// NewEntryAttribute returns a new EntryAttribute with the desired key-value pair
|
||||
func NewEntryAttribute(name string, values []string) *EntryAttribute {
|
||||
var bytes [][]byte
|
||||
for _, value := range values {
|
||||
bytes = append(bytes, []byte(value))
|
||||
}
|
||||
return &EntryAttribute{
|
||||
Name: name,
|
||||
Values: values,
|
||||
ByteValues: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
type EntryAttribute struct {
|
||||
Name string
|
||||
Values []string
|
||||
@@ -234,13 +268,32 @@ func NewSearchRequest(
|
||||
}
|
||||
}
|
||||
|
||||
// SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the
|
||||
// search request. All paged LDAP query responses will be buffered and the final result will be returned atomically.
|
||||
// The following four cases are possible given the arguments:
|
||||
// - given SearchRequest missing a control of type ControlTypePaging: we will add one with the desired paging size
|
||||
// - given SearchRequest contains a control of type ControlTypePaging that isn't actually a ControlPaging: fail without issuing any queries
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize equal to the size requested: no change to the search request
|
||||
// - given SearchRequest contains a control of type ControlTypePaging with pagingSize not equal to the size requested: fail without issuing any queries
|
||||
// A requested pagingSize of 0 is interpreted as no limit by LDAP servers.
|
||||
func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
|
||||
if searchRequest.Controls == nil {
|
||||
searchRequest.Controls = make([]Control, 0)
|
||||
var pagingControl *ControlPaging
|
||||
|
||||
control := FindControl(searchRequest.Controls, ControlTypePaging)
|
||||
if control == nil {
|
||||
pagingControl = NewControlPaging(pagingSize)
|
||||
searchRequest.Controls = append(searchRequest.Controls, pagingControl)
|
||||
} else {
|
||||
castControl, ok := control.(*ControlPaging)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Expected paging control to be of type *ControlPaging, got %v", control)
|
||||
}
|
||||
if castControl.PagingSize != pagingSize {
|
||||
return nil, fmt.Errorf("Paging size given in search request (%d) conflicts with size given in search call (%d)", castControl.PagingSize, pagingSize)
|
||||
}
|
||||
pagingControl = castControl
|
||||
}
|
||||
|
||||
pagingControl := NewControlPaging(pagingSize)
|
||||
searchRequest.Controls = append(searchRequest.Controls, pagingControl)
|
||||
searchResult := new(SearchResult)
|
||||
for {
|
||||
result, err := l.Search(searchRequest)
|
||||
|
||||
31
Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go
generated
vendored
Normal file
31
Godeps/_workspace/src/github.com/go-ldap/ldap/search_test.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestNewEntry tests that repeated calls to NewEntry return the same value with the same input
|
||||
func TestNewEntry(t *testing.T) {
|
||||
dn := "testDN"
|
||||
attributes := map[string][]string{
|
||||
"alpha": {"value"},
|
||||
"beta": {"value"},
|
||||
"gamma": {"value"},
|
||||
"delta": {"value"},
|
||||
"epsilon": {"value"},
|
||||
}
|
||||
exectedEntry := NewEntry(dn, attributes)
|
||||
|
||||
iteration := 0
|
||||
for {
|
||||
if iteration == 100 {
|
||||
break
|
||||
}
|
||||
testEntry := NewEntry(dn, attributes)
|
||||
if !reflect.DeepEqual(exectedEntry, testEntry) {
|
||||
t.Fatalf("consequent calls to NewEntry did not yield the same result:\n\texpected:\n\t%s\n\tgot:\n\t%s\n", exectedEntry, testEntry)
|
||||
}
|
||||
iteration = iteration + 1
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user