aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2021-07-07 01:49:33 +0200
committerQuentin Dufour <quentin@deuxfleurs.fr>2021-09-16 13:09:26 +0200
commit563fc272a36c8be317fbe95c8308ca2dfa29c3aa (patch)
tree0b6f9a6a15516e7234fc928ecbebbd32d3154074
parentaa912b5ceb24cb8772709171ea9589b0771bbe54 (diff)
downloadbottin-563fc272a36c8be317fbe95c8308ca2dfa29c3aa.tar.gz
bottin-563fc272a36c8be317fbe95c8308ca2dfa29c3aa.zip
Vendor goldap, fix ASN.1 BER integer and length encoding
- Add tests for goldap to prevent regressions - Disable reconnection for our functional tests
-rw-r--r--.drone.yml26
-rw-r--r--.gitignore1
-rw-r--r--go.mod2
-rw-r--r--go.sum12
-rw-r--r--goldap/abandon_request.go25
-rw-r--r--goldap/add_request.go53
-rw-r--r--goldap/add_response.go28
-rw-r--r--goldap/asn1.go761
-rw-r--r--goldap/asn1_test.go54
-rw-r--r--goldap/assertion_value.go44
-rw-r--r--goldap/attribute.go40
-rw-r--r--goldap/attribute_description.go50
-rw-r--r--goldap/attribute_list.go43
-rw-r--r--goldap/attribute_selection.go46
-rw-r--r--goldap/attribute_value.go24
-rw-r--r--goldap/attribute_value_assertion.go77
-rw-r--r--goldap/authentication_choice.go37
-rw-r--r--goldap/bind_request.go93
-rw-r--r--goldap/bind_response.go56
-rw-r--r--goldap/boolean.go62
-rw-r--r--goldap/bytes.go199
-rw-r--r--goldap/bytes_test.go172
-rw-r--r--goldap/compare_request.go53
-rw-r--r--goldap/compare_response.go29
-rw-r--r--goldap/control.go94
-rw-r--r--goldap/controls.go44
-rw-r--r--goldap/del_request.go24
-rw-r--r--goldap/del_response.go29
-rw-r--r--goldap/dn.go60
-rw-r--r--goldap/enumerated.go34
-rw-r--r--goldap/error.go9
-rw-r--r--goldap/extended_request.go69
-rw-r--r--goldap/extended_response.go85
-rw-r--r--goldap/filter.go70
-rw-r--r--goldap/filter_and.go54
-rw-r--r--goldap/filter_approx_match.go34
-rw-r--r--goldap/filter_equality_match.go34
-rw-r--r--goldap/filter_extensible_match.go28
-rw-r--r--goldap/filter_greater_or_equal.go34
-rw-r--r--goldap/filter_less_or_equal.go34
-rw-r--r--goldap/filter_not.go40
-rw-r--r--goldap/filter_or.go52
-rw-r--r--goldap/filter_present.go28
-rw-r--r--goldap/filter_substring.go187
-rw-r--r--goldap/integer.go53
-rw-r--r--goldap/intermediate_response.go89
-rw-r--r--goldap/matching_rule_assertion.go117
-rw-r--r--goldap/matching_rule_id.go29
-rw-r--r--goldap/message.go139
-rw-r--r--goldap/message_id.go46
-rw-r--r--goldap/message_test.go76
-rw-r--r--goldap/modify_dn_request.go87
-rw-r--r--goldap/modify_dn_response.go28
-rw-r--r--goldap/modify_request.go89
-rw-r--r--goldap/modify_request_change.go43
-rw-r--r--goldap/modify_response.go36
-rw-r--r--goldap/octetstring.go44
-rw-r--r--goldap/oid.go50
-rw-r--r--goldap/partial_attribute.go76
-rw-r--r--goldap/partial_attribute_list.go53
-rw-r--r--goldap/protocol_op.go63
-rw-r--r--goldap/read.go18
-rw-r--r--goldap/read_error_test.go3146
-rw-r--r--goldap/read_test.go2936
-rw-r--r--goldap/referral.go50
-rw-r--r--goldap/relative_ldap_dn.go15
-rw-r--r--goldap/result.go282
-rw-r--r--goldap/sasl_credentials.go63
-rw-r--r--goldap/search_request.go246
-rw-r--r--goldap/search_result_done.go31
-rw-r--r--goldap/search_result_entry.go58
-rw-r--r--goldap/search_result_reference.go53
-rw-r--r--goldap/size_test.go85
-rw-r--r--goldap/string.go38
-rw-r--r--goldap/struct.go739
-rw-r--r--goldap/struct_methods.go7
-rw-r--r--goldap/unbind_request.go38
-rw-r--r--goldap/uri.go32
-rw-r--r--goldap/write.go6
-rw-r--r--goldap/write_test.go19
-rw-r--r--ldapserver/client.go8
-rw-r--r--ldapserver/constants.go2
-rw-r--r--ldapserver/message.go2
-rw-r--r--ldapserver/packet.go3
-rw-r--r--ldapserver/responsemessage.go2
-rw-r--r--ldapserver/route.go2
-rw-r--r--main.go19
-rw-r--r--read.go2
-rw-r--r--test/bottin_test.go160
-rw-r--r--test/config.json.test13
-rw-r--r--test/create.go281
-rw-r--r--test/functionTest.go173
-rw-r--r--test/go.mod8
-rw-r--r--test/go.sum26
-rw-r--r--test/handler.go141
-rw-r--r--test/request.go59
-rwxr-xr-xtest/runner.sh16
-rw-r--r--write.go2
98 files changed, 12902 insertions, 27 deletions
diff --git a/.drone.yml b/.drone.yml
index 9eea880..c7fb744 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -1,13 +1,25 @@
---
-pipeline:
- build:
- image: golang:stretch
- commands:
- - go get -d -v
- - go build -v
+kind: pipeline
+name: bottin
+
+steps:
+- name: build
+ image: golang:stretch
+ commands:
+ - go get -d -v
+ - go build -v
+ - cd test
+ - go test -i -c -o test
+
+- name: test_bottin
+ image: consul:latest
+ environment:
+ BOTTIN_DEFAULT_ADMIN_PW: priZ4Cg0x5NkSyiIN/MpvWw4ZEy8f8s1
+ commands:
+ - ash test/runner.sh
---
kind: signature
-hmac: 8f49fdf0e4abb0790827eed7cac8eedd5e11705d1fa01954a84929933eb7b254
+hmac: ff246a04c3df8a2f39c8b446dea920622d61950e6caaac886931bdb05d0706ed
...
diff --git a/.gitignore b/.gitignore
index d739b6f..2a2f53c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
bottin
bottin.static
config.json
+test/test
diff --git a/go.mod b/go.mod
index 75156e0..11a9d2c 100644
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,6 @@ go 1.13
require (
github.com/google/uuid v1.1.1
github.com/hashicorp/consul/api v1.3.0
- github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3
github.com/sirupsen/logrus v1.4.2
+ golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 // indirect
)
diff --git a/go.sum b/go.sum
index c2db0e1..a46b500 100644
--- a/go.sum
+++ b/go.sum
@@ -44,8 +44,6 @@ github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3 h1:wIONC+HMNRqmWBjuMxhatuSzHaljStc4gjDeKycxy0A=
-github.com/lor00x/goldap v0.0.0-20180618054307-a546dffdd1a3/go.mod h1:37YR9jabpiIxsb8X9VCIx8qFOjTDIIrIHHODa8C4gz0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
@@ -77,14 +75,20 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/goldap/abandon_request.go b/goldap/abandon_request.go
new file mode 100644
index 0000000..519641c
--- /dev/null
+++ b/goldap/abandon_request.go
@@ -0,0 +1,25 @@
+package message
+
+import "fmt"
+
+//
+// AbandonRequest ::= [APPLICATION 16] MessageID
+
+func readAbandonRequest(bytes *Bytes) (ret AbandonRequest, err error) {
+ var mes MessageID
+ mes, err = readTaggedMessageID(bytes, classApplication, TagAbandonRequest)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAbandonRequest:\n%s", err.Error())}
+ return
+ }
+ ret = AbandonRequest(mes)
+ return
+}
+
+func (abandon AbandonRequest) size() int {
+ return MessageID(abandon).sizeTagged(TagAbandonRequest)
+}
+
+func (abandon AbandonRequest) write(bytes *Bytes) int {
+ return MessageID(abandon).writeTagged(bytes, classApplication, TagAbandonRequest)
+}
diff --git a/goldap/add_request.go b/goldap/add_request.go
new file mode 100644
index 0000000..1ba4094
--- /dev/null
+++ b/goldap/add_request.go
@@ -0,0 +1,53 @@
+package message
+
+import "fmt"
+
+//
+// AddRequest ::= [APPLICATION 8] SEQUENCE {
+// entry LDAPDN,
+// attributes AttributeList }
+
+func (add *AddRequest) Entry() LDAPDN {
+ return add.entry
+}
+
+func (add *AddRequest) Attributes() AttributeList {
+ return add.attributes
+}
+
+func readAddRequest(bytes *Bytes) (ret AddRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagAddRequest, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAddRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (add *AddRequest) readComponents(bytes *Bytes) (err error) {
+ add.entry, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ add.attributes, err = readAttributeList(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (add AddRequest) size() (size int) {
+ size += add.entry.size()
+ size += add.attributes.size()
+ size += sizeTagAndLength(TagAddRequest, size)
+ return
+}
+
+func (add AddRequest) write(bytes *Bytes) (size int) {
+ size += add.attributes.write(bytes)
+ size += add.entry.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagAddRequest, size)
+ return
+}
diff --git a/goldap/add_response.go b/goldap/add_response.go
new file mode 100644
index 0000000..ab7298d
--- /dev/null
+++ b/goldap/add_response.go
@@ -0,0 +1,28 @@
+package message
+
+import "fmt"
+
+//
+// AddResponse ::= [APPLICATION 9] LDAPResult
+
+func (l *AddResponse) SetResultCode(code int) {
+ l.resultCode = ENUMERATED(code)
+}
+
+func readAddResponse(bytes *Bytes) (ret AddResponse, err error) {
+ var res LDAPResult
+ res, err = readTaggedLDAPResult(bytes, classApplication, TagAddResponse)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAddResponse:\n%s", err.Error())}
+ return
+ }
+ ret = AddResponse(res)
+ return
+}
+
+func (a AddResponse) size() int {
+ return LDAPResult(a).sizeTagged(TagAddResponse)
+}
+func (a AddResponse) write(bytes *Bytes) int {
+ return LDAPResult(a).writeTagged(bytes, classApplication, TagAddResponse)
+}
diff --git a/goldap/asn1.go b/goldap/asn1.go
new file mode 100644
index 0000000..3e7dc76
--- /dev/null
+++ b/goldap/asn1.go
@@ -0,0 +1,761 @@
+package message
+
+// Below code is largely inspired from the standard golang library encoding/asn
+// If put BEGIN / END tags in the comments to give the original library name
+import (
+ // "errors"
+ "fmt"
+ "math/big"
+ // "strconv"
+ // "time"
+)
+
+//
+// BEGIN: encoding/asn1/common.go
+//
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+const (
+ tagBoolean = 1
+ tagInteger = 2
+ // tagBitString = 3
+ tagOctetString = 4
+ // tagOID = 6
+ tagEnum = 10
+ // tagUTF8String = 12
+ tagSequence = 16
+ tagSet = 17
+ // tagPrintableString = 19
+ // tagT61String = 20
+ // tagIA5String = 22
+ // tagUTCTime = 23
+ // tagGeneralizedTime = 24
+ tagGeneralString = 27
+)
+
+var tagNames = map[int]string{
+ tagBoolean: "BOOLEAN",
+ tagInteger: "INTEGER",
+ tagOctetString: "OCTET STRING",
+ tagEnum: "ENUM",
+ tagSequence: "SEQUENCE",
+ tagSet: "SET",
+}
+
+const (
+ classUniversal = 0
+ classApplication = 1
+ classContextSpecific = 2
+ // classPrivate = 3
+)
+
+var classNames = map[int]string{
+ classUniversal: "UNIVERSAL",
+ classApplication: "APPLICATION",
+ classContextSpecific: "CONTEXT SPECIFIC",
+}
+
+const (
+ isCompound = true
+ isNotCompound = false
+)
+
+var compoundNames = map[bool]string{
+ isCompound: "COMPOUND",
+ isNotCompound: "NOT COMPOUND",
+}
+
+type TagAndLength struct {
+ Class, Tag, Length int
+ IsCompound bool
+}
+
+//
+// END: encoding/asn1/common.go
+//
+
+func (t *TagAndLength) Expect(class int, tag int, isCompound bool) (err error) {
+ err = t.ExpectClass(class)
+ if err != nil {
+ return LdapError{fmt.Sprintf("Expect: %s.", err)}
+ }
+ err = t.ExpectTag(tag)
+ if err != nil {
+ return LdapError{fmt.Sprintf("Expect: %s.", err)}
+ }
+ err = t.ExpectCompound(isCompound)
+ if err != nil {
+ return LdapError{fmt.Sprintf("Expect: %s.", err)}
+ }
+ return
+}
+func (t *TagAndLength) ExpectClass(class int) (err error) {
+ if class != t.Class {
+ err = SyntaxError{fmt.Sprintf("ExpectClass: wrong tag class: got %d (%s), expected %d (%s)", t.Class, classNames[t.Class], class, classNames[class])}
+ }
+ return
+}
+func (t *TagAndLength) ExpectTag(tag int) (err error) {
+ if tag != t.Tag {
+ err = SyntaxError{fmt.Sprintf("ExpectTag: wrong tag value: got %d (%s), expected %d (%s)", t.Tag, tagNames[t.Tag], tag, tagNames[tag])}
+ }
+ return
+}
+func (t *TagAndLength) ExpectCompound(isCompound bool) (err error) {
+ if isCompound != t.IsCompound {
+ err = SyntaxError{fmt.Sprintf("ExpectCompound: wrong tag compound: got %t (%s), expected %t (%s)", t.IsCompound, compoundNames[t.IsCompound], isCompound, compoundNames[isCompound])}
+ }
+ return
+}
+
+func ParseTagAndLength(bytes []byte, initOffset int) (ret TagAndLength, offset int, err error) {
+ ret, offset, err = parseTagAndLength(bytes, initOffset)
+ return
+}
+
+//
+// BEGIN encoding/asn1/asn1.go
+//
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package asn1 implements parsing of DER-encoded ASN.1 data structures,
+// as defined in ITU-T Rec X.690.
+//
+// See also ``A Layman's Guide to a Subset of ASN.1, BER, and DER,''
+// http://luca.ntop.org/Teaching/Appunti/asn1.html.
+// package asn1
+
+// ASN.1 is a syntax for specifying abstract objects and BER, DER, PER, XER etc
+// are different encoding formats for those objects. Here, we'll be dealing
+// with DER, the Distinguished Encoding Rules. DER is used in X.509 because
+// it's fast to parse and, unlike BER, has a unique encoding for every object.
+// When calculating hashes over objects, it's important that the resulting
+// bytes be the same at both ends and DER removes this margin of error.
+//
+// ASN.1 is very complex and this package doesn't attempt to implement
+// everything by any means.
+
+//import (
+// "fmt"
+// "math/big"
+// "reflect"
+// "strconv"
+// "time"
+//)
+
+// A StructuralError suggests that the ASN.1 data is valid, but the Go type
+// which is receiving it doesn't match.
+type StructuralError struct {
+ Msg string
+}
+
+func (e StructuralError) Error() string { return "asn1: structure error: " + e.Msg }
+
+// A SyntaxError suggests that the ASN.1 data is invalid.
+type SyntaxError struct {
+ Msg string
+}
+
+func (e SyntaxError) Error() string { return "asn1: syntax error: " + e.Msg }
+
+// We start by dealing with each of the primitive types in turn.
+
+// BOOLEAN
+
+func parseBool(bytes []byte) (ret bool, err error) {
+ if len(bytes) > 1 {
+ err = SyntaxError{"invalid boolean: should be encoded on one byte only"}
+ return
+ } else if len(bytes) == 0 {
+ err = SyntaxError{"invalid boolean: no data to read"}
+ }
+
+ // DER demands that "If the encoding represents the boolean value TRUE,
+ // its single contents octet shall have all eight bits set to one."
+ // Thus only 0 and 255 are valid encoded values.
+ switch bytes[0] {
+ case 0:
+ ret = false
+ case 0xff:
+ ret = true
+ default:
+ err = SyntaxError{"invalid boolean: should be 0x00 of 0xFF"}
+ }
+
+ return
+}
+
+func sizeBool(b bool) int {
+ return 1
+}
+
+func writeBool(bytes *Bytes, b bool) int {
+ if b == false {
+ return bytes.writeBytes([]byte{0x00})
+ } else {
+ return bytes.writeBytes([]byte{0xff})
+ }
+}
+
+// INTEGER
+
+// parseInt64 treats the given bytes as a big-endian, signed integer and
+// returns the result.
+func parseInt64(bytes []byte) (ret int64, err error) {
+ if len(bytes) > 8 {
+ // We'll overflow an int64 in this case.
+ err = StructuralError{"integer too large"}
+ return
+ }
+ for bytesRead := 0; bytesRead < len(bytes); bytesRead++ {
+ ret <<= 8
+ ret |= int64(bytes[bytesRead])
+ }
+
+ // Shift up and down in order to sign extend the result.
+ ret <<= 64 - uint8(len(bytes))*8
+ ret >>= 64 - uint8(len(bytes))*8
+ return
+}
+
+func sizeInt64(i int64) (size int) {
+ n := 1
+
+ for i > 127 {
+ n++
+ i >>= 8
+ }
+
+ for i < -128 {
+ n++
+ i >>= 8
+ }
+
+ return n
+}
+
+func writeInt64(bytes *Bytes, i int64) (size int) {
+ n := sizeInt64(i)
+ buf := [8]byte{}
+
+ for j := 0; j < n; j++ {
+ b := i >> uint((n-1-j)*8)
+ buf[j] = byte(b)
+ }
+ bytes.writeBytes(buf[:n])
+
+ return n
+}
+
+// parseInt treats the given bytes as a big-endian, signed integer and returns
+// the result.
+func parseInt32(bytes []byte) (int32, error) {
+ ret64, err := parseInt64(bytes)
+ if err != nil {
+ return 0, err
+ }
+ if ret64 != int64(int32(ret64)) {
+ return 0, StructuralError{"integer too large"}
+ }
+ return int32(ret64), nil
+}
+
+func sizeInt32(i int32) int {
+ return sizeInt64(int64(i))
+}
+
+func writeInt32(bytes *Bytes, i int32) int {
+ return writeInt64(bytes, int64(i))
+}
+
+var bigOne = big.NewInt(1)
+
+// // parseBigInt treats the given bytes as a big-endian, signed integer and returns
+// // the result.
+// func parseBigInt(bytes []byte) *big.Int {
+// ret := new(big.Int)
+// if len(bytes) > 0 && bytes[0]&0x80 == 0x80 {
+// // This is a negative number.
+// notBytes := make([]byte, len(bytes))
+// for i := range notBytes {
+// notBytes[i] = ^bytes[i]
+// }
+// ret.SetBytes(notBytes)
+// ret.Add(ret, bigOne)
+// ret.Neg(ret)
+// return ret
+// }
+// ret.SetBytes(bytes)
+// return ret
+// }
+
+// // BIT STRING
+
+// // BitString is the structure to use when you want an ASN.1 BIT STRING type. A
+// // bit string is padded up to the nearest byte in memory and the number of
+// // valid bits is recorded. Padding bits will be zero.
+// type BitString struct {
+// Bytes []byte // bits packed into bytes.
+// BitLength int // length in bits.
+// }
+
+// // At returns the bit at the given index. If the index is out of range it
+// // returns false.
+// func (b BitString) At(i int) int {
+// if i < 0 || i >= b.BitLength {
+// return 0
+// }
+// x := i / 8
+// y := 7 - uint(i%8)
+// return int(b.Bytes[x]>>y) & 1
+// }
+
+// // RightAlign returns a slice where the padding bits are at the beginning. The
+// // slice may share memory with the BitString.
+// func (b BitString) RightAlign() []byte {
+// shift := uint(8 - (b.BitLength % 8))
+// if shift == 8 || len(b.Bytes) == 0 {
+// return b.Bytes
+// }
+
+// a := make([]byte, len(b.Bytes))
+// a[0] = b.Bytes[0] >> shift
+// for i := 1; i < len(b.Bytes); i++ {
+// a[i] = b.Bytes[i-1] << (8 - shift)
+// a[i] |= b.Bytes[i] >> shift
+// }
+
+// return a
+// }
+
+// // parseBitString parses an ASN.1 bit string from the given byte slice and returns it.
+// func parseBitString(bytes []byte) (ret BitString, err error) {
+// if len(bytes) == 0 {
+// err = SyntaxError{"zero length BIT STRING"}
+// return
+// }
+// paddingBits := int(bytes[0])
+// if paddingBits > 7 ||
+// len(bytes) == 1 && paddingBits > 0 ||
+// bytes[len(bytes)-1]&((1<<bytes[0])-1) != 0 {
+// err = SyntaxError{"invalid padding bits in BIT STRING"}
+// return
+// }
+// ret.BitLength = (len(bytes)-1)*8 - paddingBits
+// ret.Bytes = bytes[1:]
+// return
+// }
+
+// OBJECT IDENTIFIER
+
+// An ObjectIdentifier represents an ASN.1 OBJECT IDENTIFIER.
+// type ObjectIdentifier []int
+
+// // Equal reports whether oi and other represent the same identifier.
+// func (oi ObjectIdentifier) Equal(other ObjectIdentifier) bool {
+// if len(oi) != len(other) {
+// return false
+// }
+// for i := 0; i < len(oi); i++ {
+// if oi[i] != other[i] {
+// return false
+// }
+// }
+
+// return true
+// }
+
+// func (oi ObjectIdentifier) String() string {
+// var s string
+
+// for i, v := range oi {
+// if i > 0 {
+// s += "."
+// }
+// s += strconv.Itoa(v)
+// }
+
+// return s
+// }
+
+// // parseObjectIdentifier parses an OBJECT IDENTIFIER from the given bytes and
+// // returns it. An object identifier is a sequence of variable length integers
+// // that are assigned in a hierarchy.
+// func parseObjectIdentifier(bytes []byte) (s []int, err error) {
+// if len(bytes) == 0 {
+// err = SyntaxError{"zero length OBJECT IDENTIFIER"}
+// return
+// }
+
+// // In the worst case, we get two elements from the first byte (which is
+// // encoded differently) and then every varint is a single byte long.
+// s = make([]int, len(bytes)+1)
+
+// // The first varint is 40*value1 + value2:
+// // According to this packing, value1 can take the values 0, 1 and 2 only.
+// // When value1 = 0 or value1 = 1, then value2 is <= 39. When value1 = 2,
+// // then there are no restrictions on value2.
+// v, offset, err := parseBase128Int(bytes, 0)
+// if err != nil {
+// return
+// }
+// if v < 80 {
+// s[0] = v / 40
+// s[1] = v % 40
+// } else {
+// s[0] = 2
+// s[1] = v - 80
+// }
+
+// i := 2
+// for ; offset < len(bytes); i++ {
+// v, offset, err = parseBase128Int(bytes, offset)
+// if err != nil {
+// return
+// }
+// s[i] = v
+// }
+// s = s[0:i]
+// return
+// }
+
+// ENUMERATED
+
+// An Enumerated is represented as a plain int.
+type Enumerated int
+
+// FLAG
+
+// A Flag accepts any data and is set to true if present.
+type Flag bool
+
+// parseBase128Int parses a base-128 encoded int from the given offset in the
+// given byte slice. It returns the value and the new offset.
+func parseBase128Int(bytes []byte, initOffset int) (ret, offset int, err error) {
+ offset = initOffset
+ for shifted := 0; offset < len(bytes); shifted++ {
+ if shifted > 4 {
+ err = StructuralError{"base 128 integer too large"}
+ return
+ }
+ ret <<= 7
+ b := bytes[offset]
+ ret |= int(b & 0x7f)
+ offset++
+ if b&0x80 == 0 {
+ return
+ }
+ }
+ err = SyntaxError{"truncated base 128 integer"}
+ return
+}
+
+func sizeBase128Int(value int) (size int) {
+ for i := value; i > 0; i >>= 7 {
+ size++
+ }
+ return
+}
+
+// Write start as the end of the slice and goes back
+// We assume we have enough size
+func writeBase128Int(bytes *Bytes, value int) (size int) {
+ for ; value > 0 || size == 0; value >>= 7 { // Write at least one byte even if the value is 0
+ // Get the 7 lowest bits
+ b := byte(value) & 0x7f
+ if value < 128 {
+ b |= 0x80
+ }
+ bytes.writeBytes([]byte{b})
+ size++
+ }
+ return
+}
+
+// // UTCTime
+
+// func parseUTCTime(bytes []byte) (ret time.Time, err error) {
+// s := string(bytes)
+// ret, err = time.Parse("0601021504Z0700", s)
+// if err != nil {
+// ret, err = time.Parse("060102150405Z0700", s)
+// }
+// if err == nil && ret.Year() >= 2050 {
+// // UTCTime only encodes times prior to 2050. See https://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
+// ret = ret.AddDate(-100, 0, 0)
+// }
+
+// return
+// }
+
+// // parseGeneralizedTime parses the GeneralizedTime from the given byte slice
+// // and returns the resulting time.
+// func parseGeneralizedTime(bytes []byte) (ret time.Time, err error) {
+// return time.Parse("20060102150405Z0700", string(bytes))
+// }
+
+// // PrintableString
+
+// // parsePrintableString parses a ASN.1 PrintableString from the given byte
+// // array and returns it.
+// func parsePrintableString(bytes []byte) (ret string, err error) {
+// for _, b := range bytes {
+// if !isPrintable(b) {
+// err = SyntaxError{"PrintableString contains invalid character"}
+// return
+// }
+// }
+// ret = string(bytes)
+// return
+// }
+
+// // isPrintable returns true iff the given b is in the ASN.1 PrintableString set.
+// func isPrintable(b byte) bool {
+// return 'a' <= b && b <= 'z' ||
+// 'A' <= b && b <= 'Z' ||
+// '0' <= b && b <= '9' ||
+// '\'' <= b && b <= ')' ||
+// '+' <= b && b <= '/' ||
+// b == ' ' ||
+// b == ':' ||
+// b == '=' ||
+// b == '?' ||
+// // This is technically not allowed in a PrintableString.
+// // However, x509 certificates with wildcard strings don't
+// // always use the correct string type so we permit it.
+// b == '*'
+// }
+
+// // IA5String
+
+// // parseIA5String parses a ASN.1 IA5String (ASCII string) from the given
+// // byte slice and returns it.
+// func parseIA5String(bytes []byte) (ret string, err error) {
+// for _, b := range bytes {
+// if b >= 0x80 {
+// err = SyntaxError{"IA5String contains invalid character"}
+// return
+// }
+// }
+// ret = string(bytes)
+// return
+// }
+
+// // T61String
+
+// // parseT61String parses a ASN.1 T61String (8-bit clean string) from the given
+// // byte slice and returns it.
+// func parseT61String(bytes []byte) (ret string, err error) {
+// return string(bytes), nil
+// }
+
+// UTF8String
+
+// parseUTF8String parses a ASN.1 UTF8String (raw UTF-8) from the given byte
+// array and returns it.
+// func parseUTF8String(bytes []byte) (ret string, err error) {
+// return string(bytes), nil
+// }
+// func sizeUTF8String(s string) int {
+// return len(s)
+// }
+// func writeUTF8String(bytes *Bytes, s string) int {
+// return bytes.writeString(s)
+// }
+
+// Octet string
+func parseOctetString(bytes []byte) (ret []byte, err error) {
+ return bytes, nil
+}
+func sizeOctetString(s []byte) int {
+ return len(s)
+}
+func writeOctetString(bytes *Bytes, s []byte) int {
+ return bytes.writeBytes(s)
+}
+
+// A RawValue represents an undecoded ASN.1 object.
+type RawValue struct {
+ Class, Tag int
+ IsCompound bool
+ Bytes []byte
+ FullBytes []byte // includes the tag and length
+}
+
+// RawContent is used to signal that the undecoded, DER data needs to be
+// preserved for a struct. To use it, the first field of the struct must have
+// this type. It's an error for any of the other fields to have this type.
+type RawContent []byte
+
+// Tagging
+
+// parseTagAndLength parses an ASN.1 tag and length pair from the given offset
+// into a byte slice. It returns the parsed data and the new offset. SET and
+// SET OF (tag 17) are mapped to SEQUENCE and SEQUENCE OF (tag 16) since we
+// don't distinguish between ordered and unordered objects in this code.
+func parseTagAndLength(bytes []byte, initOffset int) (ret TagAndLength, offset int, err error) {
+ offset = initOffset
+ b := bytes[offset]
+ offset++
+ ret.Class = int(b >> 6)
+ ret.IsCompound = b&0x20 == 0x20
+ ret.Tag = int(b & 0x1f)
+
+ // If the bottom five bits are set, then the tag number is actually base 128
+ // encoded afterwards
+ if ret.Tag == 0x1f {
+ ret.Tag, offset, err = parseBase128Int(bytes, offset)
+ if err != nil {
+ return
+ }
+ }
+ if offset >= len(bytes) {
+ err = SyntaxError{"truncated tag or length"}
+ return
+ }
+ b = bytes[offset]
+ offset++
+ if b&0x80 == 0 {
+ // The length is encoded in the bottom 7 bits.
+ ret.Length = int(b & 0x7f)
+ } else {
+ // Bottom 7 bits give the number of length bytes to follow.
+ numBytes := int(b & 0x7f)
+ if numBytes == 0 {
+ err = SyntaxError{"indefinite length found (not DER)"}
+ return
+ }
+ ret.Length = 0
+ for i := 0; i < numBytes; i++ {
+ if offset >= len(bytes) {
+ err = SyntaxError{"truncated tag or length"}
+ return
+ }
+ b = bytes[offset]
+ offset++
+ if ret.Length >= 1<<23 {
+ // We can't shift ret.length up without
+ // overflowing.
+ err = StructuralError{"length too large"}
+ return
+ }
+ ret.Length <<= 8
+ ret.Length |= int(b)
+ if ret.Length == 0 {
+ // DER requires that lengths be minimal.
+ err = StructuralError{"superfluous leading zeros in length"}
+ return
+ }
+ }
+ }
+
+ return
+}
+
+// func writeTagAndLength(out *forkableWriter, t tagAndLength) (err error) {
+// b := uint8(t.class) << 6
+// if t.isCompound {
+// b |= 0x20
+// }
+// if t.tag >= 31 {
+// b |= 0x1f
+// err = out.WriteByte(b)
+// if err != nil {
+// return
+// }
+// err = marshalBase128Int(out, int64(t.tag))
+// if err != nil {
+// return
+// }
+// } else {
+// b |= uint8(t.tag)
+// err = out.WriteByte(b)
+// if err != nil {
+// return
+// }
+// }
+
+// if t.length >= 128 {
+// l := lengthLength(t.length)
+// err = out.WriteByte(0x80 | byte(l))
+// if err != nil {
+// return
+// }
+// err = marshalLength(out, t.length)
+// if err != nil {
+// return
+// }
+// } else {
+// err = out.WriteByte(byte(t.length))
+// if err != nil {
+// return
+// }
+// }
+
+// return nil
+// }
+
+func sizeTagAndLength(tag int, length int) (size int) {
+ // Compute the size of the tag
+ size = 1
+ if tag >= 31 {
+ // Long-form identifier if the tag is greater than 30
+ // http://en.wikipedia.org/wiki/X.690#Identifier_tags_greater_than_30
+ size += sizeBase128Int(tag)
+ }
+ // Compute the size of the length using the definite form
+ // http://en.wikipedia.org/wiki/X.690#The_definite_form
+ size += 1
+ if length >= 128 {
+ size += 1
+ for length > 255 {
+ size++
+ length >>= 8
+ }
+ }
+ return
+}
+
+func writeTagAndLength(bytes *Bytes, t TagAndLength) (size int) {
+ // We are writing backward, so write the length bytes first
+ if t.Length < 0 {
+ panic("Can't have a negative length")
+
+ } else if t.Length >= 128 {
+ //lengthBytes := writeInt64(bytes, int64(t.Length))
+ lengthBytes := 0
+ val := t.Length
+ for val > 0 {
+ lengthBytes++
+ bytes.writeBytes([]byte{byte(val & 0xff)})
+ val >>= 8
+ }
+ bytes.writeBytes([]byte{byte(0x80 | byte(lengthBytes))})
+ size += lengthBytes + 1
+
+ } else if t.Length < 128 {
+ size += bytes.writeBytes([]byte{byte(t.Length)})
+ }
+ // Then write the tag
+ b := uint8(t.Class) << 6
+ if t.IsCompound {
+ b |= 0x20
+ }
+ if t.Tag >= 31 {
+ b |= 0x1f
+ size += writeBase128Int(bytes, t.Tag)
+ } else {
+ b |= uint8(t.Tag)
+ }
+ size += bytes.writeBytes([]byte{byte(b)})
+ return
+}
+
+//
+// END encoding/asn1/asn1.go
+//
diff --git a/goldap/asn1_test.go b/goldap/asn1_test.go
new file mode 100644
index 0000000..eb11d29
--- /dev/null
+++ b/goldap/asn1_test.go
@@ -0,0 +1,54 @@
+package message
+
+import (
+ "testing"
+ "bytes"
+)
+
+func TestSizeInt64(t *testing.T) {
+ s := sizeInt64(0)
+ if s != 1 {
+ t.Errorf("computed size is %d, expected 1", s)
+ }
+
+ s = sizeInt64(127)
+ if s != 1 {
+ t.Errorf("computed size is %d, expected 1", s)
+ }
+
+ s = sizeInt64(128)
+ if s != 2 {
+ t.Errorf("computed size is %d, expected 2", s)
+ }
+
+ s = sizeInt64(50000)
+ if s != 3 {
+ t.Errorf("computed size is %d, expected 3", s)
+ }
+
+ s = sizeInt64(-12345)
+ if s != 2 {
+ t.Errorf("computed size is %d, expected 2", s)
+ }
+}
+
+func TestWriteInt64(t *testing.T) {
+ vtests := []int64{0, 127, 128, 50000, -12345}
+ expsize := []int{1, 1, 2, 3, 2}
+ expresult := [][]byte{{0x00}, {0x7F}, {0x00, 0x80}, {0x00, 0xc3, 0x50}, {0xcf, 0xc7}}
+
+ for idx, v := range vtests {
+ fs := sizeInt64(v)
+ b := NewBytes(fs, make([]byte, fs))
+ t.Log("computing", v)
+ s := writeInt64(b, v)
+ if s != expsize[idx] {
+ t.Errorf("computed size is %d, expected %d", s, expsize[idx])
+ }
+ if !bytes.Equal(b.Bytes(), expresult[idx]) {
+ t.Errorf("wrong computed bytes, got %v, expected %v", b.Bytes(), expresult[idx])
+ }
+ a, e := parseInt64(b.Bytes())
+ t.Log("parse", a, e)
+ }
+}
diff --git a/goldap/assertion_value.go b/goldap/assertion_value.go
new file mode 100644
index 0000000..89706a0
--- /dev/null
+++ b/goldap/assertion_value.go
@@ -0,0 +1,44 @@
+package message
+
+import "fmt"
+
+//
+// AssertionValue ::= OCTET STRING
+
+func readAssertionValue(bytes *Bytes) (assertionvalue AssertionValue, err error) {
+ var octetstring OCTETSTRING
+ octetstring, err = readOCTETSTRING(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAssertionValue:\n%s", err.Error())}
+ return
+ }
+ assertionvalue = AssertionValue(octetstring)
+ return
+}
+
+func readTaggedAssertionValue(bytes *Bytes, class int, tag int) (assertionvalue AssertionValue, err error) {
+ var octetstring OCTETSTRING
+ octetstring, err = readTaggedOCTETSTRING(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedAssertionValue:\n%s", err.Error())}
+ return
+ }
+ assertionvalue = AssertionValue(octetstring)
+ return
+}
+
+func (assertion AssertionValue) size() int {
+ return OCTETSTRING(assertion).size()
+}
+
+func (assertion AssertionValue) sizeTagged(tag int) int {
+ return OCTETSTRING(assertion).sizeTagged(tag)
+}
+
+func (assertion AssertionValue) write(bytes *Bytes) int {
+ return OCTETSTRING(assertion).write(bytes)
+}
+
+func (assertion AssertionValue) writeTagged(bytes *Bytes, class int, tag int) int {
+ return OCTETSTRING(assertion).writeTagged(bytes, class, tag)
+}
diff --git a/goldap/attribute.go b/goldap/attribute.go
new file mode 100644
index 0000000..d76b311
--- /dev/null
+++ b/goldap/attribute.go
@@ -0,0 +1,40 @@
+package message
+
+import "fmt"
+
+//
+// Attribute ::= PartialAttribute(WITH COMPONENTS {
+// ...,
+// vals (SIZE(1..MAX))})
+
+func (attribute *Attribute) Type_() AttributeDescription {
+ return attribute.type_
+}
+
+func (attribute *Attribute) Vals() []AttributeValue {
+ return attribute.vals
+}
+
+func readAttribute(bytes *Bytes) (ret Attribute, err error) {
+ var par PartialAttribute
+ par, err = readPartialAttribute(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttribute:\n%s", err.Error())}
+ return
+ }
+ if len(par.vals) == 0 {
+ err = LdapError{"readAttribute: expecting at least one value"}
+ return
+ }
+ ret = Attribute(par)
+ return
+
+}
+
+func (attribute Attribute) size() (size int) {
+ return PartialAttribute(attribute).size()
+}
+
+func (attribute Attribute) write(bytes *Bytes) (size int) {
+ return PartialAttribute(attribute).write(bytes)
+}
diff --git a/goldap/attribute_description.go b/goldap/attribute_description.go
new file mode 100644
index 0000000..04bb03d
--- /dev/null
+++ b/goldap/attribute_description.go
@@ -0,0 +1,50 @@
+package message
+
+import "fmt"
+
+//
+// AttributeDescription ::= LDAPString
+// -- Constrained to <attributedescription>
+// -- [RFC4512]
+
+func (description AttributeDescription) Pointer() *AttributeDescription { return &description }
+
+func readAttributeDescription(bytes *Bytes) (ret AttributeDescription, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readLDAPString(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttributeDescription:\n%s", err.Error())}
+ return
+ }
+ // @TODO: check RFC4512
+ ret = AttributeDescription(ldapstring)
+ return
+}
+
+func readTaggedAttributeDescription(bytes *Bytes, class int, tag int) (ret AttributeDescription, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readTaggedLDAPString(bytes, class, tag)
+ // @TODO: check RFC4512
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedAttributeDescription:\n%s", err.Error())}
+ return
+ }
+ ret = AttributeDescription(ldapstring)
+ return
+}
+
+func (description AttributeDescription) size() int {
+ return LDAPString(description).size()
+}
+
+func (description AttributeDescription) sizeTagged(tag int) int {
+ return LDAPString(description).sizeTagged(tag)
+}
+
+func (description AttributeDescription) write(bytes *Bytes) int {
+ return LDAPString(description).write(bytes)
+}
+
+func (description AttributeDescription) writeTagged(bytes *Bytes, class int, tag int) int {
+ return LDAPString(description).writeTagged(bytes, class, tag)
+}
diff --git a/goldap/attribute_list.go b/goldap/attribute_list.go
new file mode 100644
index 0000000..bcf753c
--- /dev/null
+++ b/goldap/attribute_list.go
@@ -0,0 +1,43 @@
+package message
+
+import "fmt"
+
+//
+// AttributeList ::= SEQUENCE OF attribute Attribute
+
+func readAttributeList(bytes *Bytes) (ret AttributeList, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttributeList:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (list *AttributeList) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var attr Attribute
+ attr, err = readAttribute(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *list = append(*list, attr)
+ }
+ return
+}
+
+func (list AttributeList) size() (size int) {
+ for _, att := range list {
+ size += att.size()
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+
+func (list AttributeList) write(bytes *Bytes) (size int) {
+ for i := len(list) - 1; i >= 0; i-- {
+ size += list[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
diff --git a/goldap/attribute_selection.go b/goldap/attribute_selection.go
new file mode 100644
index 0000000..f092606
--- /dev/null
+++ b/goldap/attribute_selection.go
@@ -0,0 +1,46 @@
+package message
+
+import "fmt"
+
+//
+// AttributeSelection ::= SEQUENCE OF selector LDAPString
+// -- The LDAPString is constrained to
+// -- <attributeSelector> in Section 4.5.1.8
+
+func readAttributeSelection(bytes *Bytes) (attributeSelection AttributeSelection, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, attributeSelection.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttributeSelection:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (selection *AttributeSelection) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var ldapstring LDAPString
+ ldapstring, err = readLDAPString(bytes)
+ // @TOTO: check <attributeSelector> in Section 4.5.1.8
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *selection = append(*selection, ldapstring)
+ }
+ return
+}
+
+func (selection AttributeSelection) write(bytes *Bytes) (size int) {
+ for i := len(selection) - 1; i >= 0; i-- {
+ size += selection[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+
+func (selection AttributeSelection) size() (size int) {
+ for _, selector := range selection {
+ size += selector.size()
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
diff --git a/goldap/attribute_value.go b/goldap/attribute_value.go
new file mode 100644
index 0000000..34fea97
--- /dev/null
+++ b/goldap/attribute_value.go
@@ -0,0 +1,24 @@
+package message
+
+import "fmt"
+
+//
+// AttributeValue ::= OCTET STRING
+
+func readAttributeValue(bytes *Bytes) (ret AttributeValue, err error) {
+ octetstring, err := readOCTETSTRING(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttributeValue:\n%s", err.Error())}
+ return
+ }
+ ret = AttributeValue(octetstring)
+ return
+}
+
+func (value AttributeValue) write(bytes *Bytes) int {
+ return OCTETSTRING(value).write(bytes)
+}
+
+func (value AttributeValue) size() int {
+ return OCTETSTRING(value).size()
+}
diff --git a/goldap/attribute_value_assertion.go b/goldap/attribute_value_assertion.go
new file mode 100644
index 0000000..bb00cbd
--- /dev/null
+++ b/goldap/attribute_value_assertion.go
@@ -0,0 +1,77 @@
+package message
+
+import "fmt"
+
+//
+// AttributeValueAssertion ::= SEQUENCE {
+// attributeDesc AttributeDescription,
+// assertionValue AssertionValue }
+
+func (assertion *AttributeValueAssertion) AttributeDesc() AttributeDescription {
+ return assertion.attributeDesc
+}
+
+func (assertion *AttributeValueAssertion) AssertionValue() AssertionValue {
+ return assertion.assertionValue
+}
+
+func readAttributeValueAssertion(bytes *Bytes) (ret AttributeValueAssertion, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAttributeValueAssertion:\n%s", err.Error())}
+ return
+ }
+ return
+
+}
+
+func readTaggedAttributeValueAssertion(bytes *Bytes, class int, tag int) (ret AttributeValueAssertion, err error) {
+ err = bytes.ReadSubBytes(class, tag, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedAttributeValueAssertion:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (assertion *AttributeValueAssertion) readComponents(bytes *Bytes) (err error) {
+ assertion.attributeDesc, err = readAttributeDescription(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ assertion.assertionValue, err = readAssertionValue(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (assertion AttributeValueAssertion) write(bytes *Bytes) (size int) {
+ size += assertion.assertionValue.write(bytes)
+ size += assertion.attributeDesc.write(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+
+func (assertion AttributeValueAssertion) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ size += assertion.assertionValue.write(bytes)
+ size += assertion.attributeDesc.write(bytes)
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+func (assertion AttributeValueAssertion) size() (size int) {
+ size += assertion.attributeDesc.size()
+ size += assertion.assertionValue.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+
+func (assertion AttributeValueAssertion) sizeTagged(tag int) (size int) {
+ size += assertion.attributeDesc.size()
+ size += assertion.assertionValue.size()
+ size += sizeTagAndLength(tag, size)
+ return
+}
diff --git a/goldap/authentication_choice.go b/goldap/authentication_choice.go
new file mode 100644
index 0000000..804d84d
--- /dev/null
+++ b/goldap/authentication_choice.go
@@ -0,0 +1,37 @@
+package message
+
+import "fmt"
+
+//
+// AuthenticationChoice ::= CHOICE {
+// simple [0] OCTET STRING,
+// -- 1 and 2 reserved
+// sasl [3] SaslCredentials,
+// ... }
+
+func readAuthenticationChoice(bytes *Bytes) (ret AuthenticationChoice, err error) {
+ tagAndLength, err := bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAuthenticationChoice:\n%s", err.Error())}
+ return
+ }
+ err = tagAndLength.ExpectClass(classContextSpecific)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAuthenticationChoice:\n%s", err.Error())}
+ return
+ }
+ switch tagAndLength.Tag {
+ case TagAuthenticationChoiceSimple:
+ ret, err = readTaggedOCTETSTRING(bytes, classContextSpecific, TagAuthenticationChoiceSimple)
+ case TagAuthenticationChoiceSaslCredentials:
+ ret, err = readSaslCredentials(bytes)
+ default:
+ err = LdapError{fmt.Sprintf("readAuthenticationChoice: invalid tag value %d for AuthenticationChoice", tagAndLength.Tag)}
+ return
+ }
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readAuthenticationChoice:\n%s", err.Error())}
+ return
+ }
+ return
+}
diff --git a/goldap/bind_request.go b/goldap/bind_request.go
new file mode 100644
index 0000000..d00a3ef
--- /dev/null
+++ b/goldap/bind_request.go
@@ -0,0 +1,93 @@
+package message
+
+import "fmt"
+
+// BindRequest ::= [APPLICATION 0] SEQUENCE {
+// version INTEGER (1 .. 127),
+// name LDAPDN,
+// authentication AuthenticationChoice }
+
+func (request *BindRequest) Name() LDAPDN {
+ return request.name
+}
+
+func (request *BindRequest) Authentication() AuthenticationChoice {
+ return request.authentication
+}
+
+func (request *BindRequest) AuthenticationSimple() OCTETSTRING {
+ return request.Authentication().(OCTETSTRING)
+}
+
+func (request *BindRequest) AuthenticationChoice() string {
+ switch request.Authentication().(type) {
+ case OCTETSTRING:
+ return "simple"
+ case SaslCredentials:
+ return "sasl"
+ }
+ return ""
+}
+
+func readBindRequest(bytes *Bytes) (bindrequest BindRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagBindRequest, bindrequest.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readBindRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (request *BindRequest) readComponents(bytes *Bytes) (err error) {
+ request.version, err = readINTEGER(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if !(request.version >= BindRequestVersionMin && request.version <= BindRequestVersionMax) {
+ err = LdapError{fmt.Sprintf("readComponents: invalid version %d, must be between %d and %d", request.version, BindRequestVersionMin, BindRequestVersionMax)}
+ return
+ }
+ request.name, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ request.authentication, err = readAuthenticationChoice(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (request BindRequest) write(bytes *Bytes) (size int) {
+ switch request.authentication.(type) {
+ case OCTETSTRING:
+ size += request.authentication.(OCTETSTRING).writeTagged(bytes, classContextSpecific, TagAuthenticationChoiceSimple)
+ case SaslCredentials:
+ size += request.authentication.(SaslCredentials).writeTagged(bytes, classContextSpecific, TagAuthenticationChoiceSaslCredentials)
+ default:
+ panic(fmt.Sprintf("Unknown authentication choice: %#v", request.authentication))
+ }
+ size += request.name.write(bytes)
+ size += request.version.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagBindRequest, size)
+ return
+}
+
+func (request BindRequest) size() (size int) {
+ size += request.version.size()
+ size += request.name.size()
+ switch request.authentication.(type) {
+ case OCTETSTRING:
+ size += request.authentication.(OCTETSTRING).sizeTagged(TagAuthenticationChoiceSimple)
+ case SaslCredentials:
+ size += request.authentication.(SaslCredentials).sizeTagged(TagAuthenticationChoiceSaslCredentials)
+ default:
+ panic(fmt.Sprintf("Unknown authentication choice: %#v", request.authentication))
+ }
+
+ size += sizeTagAndLength(TagBindRequest, size)
+ return
+}
diff --git a/goldap/bind_response.go b/goldap/bind_response.go
new file mode 100644
index 0000000..2d9db30
--- /dev/null
+++ b/goldap/bind_response.go
@@ -0,0 +1,56 @@
+package message
+
+import "fmt"
+
+// BindResponse ::= [APPLICATION 1] SEQUENCE {
+// COMPONENTS OF LDAPResult,
+// serverSaslCreds [7] OCTET STRING OPTIONAL }
+
+func readBindResponse(bytes *Bytes) (bindresponse BindResponse, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagBindResponse, bindresponse.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readBindResponse:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (response *BindResponse) readComponents(bytes *Bytes) (err error) {
+ response.LDAPResult.readComponents(bytes)
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagBindResponseServerSaslCreds {
+ var serverSaslCreds OCTETSTRING
+ serverSaslCreds, err = readTaggedOCTETSTRING(bytes, classContextSpecific, TagBindResponseServerSaslCreds)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ response.serverSaslCreds = serverSaslCreds.Pointer()
+ }
+ }
+ return
+}
+
+func (response BindResponse) write(bytes *Bytes) (size int) {
+ if response.serverSaslCreds != nil {
+ size += response.serverSaslCreds.writeTagged(bytes, classContextSpecific, TagBindResponseServerSaslCreds)
+ }
+ size += response.LDAPResult.writeComponents(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagBindResponse, size)
+ return
+}
+
+func (response BindResponse) size() (size int) {
+ if response.serverSaslCreds != nil {
+ size += response.serverSaslCreds.sizeTagged(TagBindResponseServerSaslCreds)
+ }
+ size += response.LDAPResult.sizeComponents()
+ size += sizeTagAndLength(TagBindResponse, size)
+ return
+}
diff --git a/goldap/boolean.go b/goldap/boolean.go
new file mode 100644
index 0000000..7e3b254
--- /dev/null
+++ b/goldap/boolean.go
@@ -0,0 +1,62 @@
+package message
+
+import "fmt"
+
+func readBOOLEAN(bytes *Bytes) (ret BOOLEAN, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(classUniversal, tagBoolean, tagBoolean)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readBOOLEAN:\n%s", err.Error())}
+ return
+ }
+ ret = BOOLEAN(value.(bool))
+ return
+}
+
+func (boolean BOOLEAN) write(bytes *Bytes) int {
+ return bytes.WritePrimitiveSubBytes(classUniversal, tagBoolean, boolean)
+}
+
+func (boolean BOOLEAN) writeTagged(bytes *Bytes, class int, tag int) int {
+ return bytes.WritePrimitiveSubBytes(class, tag, boolean)
+}
+
+func readTaggedBOOLEAN(bytes *Bytes, class int, tag int) (ret BOOLEAN, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(class, tag, tagBoolean)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedBOOLEAN:\n%s", err.Error())}
+ return
+ }
+ ret = BOOLEAN(value.(bool))
+ return
+}
+
+func SizePrimitiveSubBytes(tag int, value interface{}) (size int) {
+ switch value.(type) {
+ case BOOLEAN:
+ size = sizeBool(bool(value.(BOOLEAN)))
+ case INTEGER:
+ size = sizeInt32(int32(value.(INTEGER)))
+ case ENUMERATED:
+ size = sizeInt32(int32(value.(ENUMERATED)))
+ case OCTETSTRING:
+ size = sizeOctetString([]byte(string(value.(OCTETSTRING))))
+ default:
+ panic(fmt.Sprintf("SizePrimitiveSubBytes: invalid value type %v", value))
+ }
+ size += sizeTagAndLength(tag, size)
+ return
+}
+
+func (boolean BOOLEAN) size() int {
+ return SizePrimitiveSubBytes(tagBoolean, boolean)
+}
+
+func (boolean BOOLEAN) sizeTagged(tag int) int {
+ return SizePrimitiveSubBytes(tag, boolean)
+}
+
+func (boolean BOOLEAN) Bool() bool {
+ return bool(boolean)
+}
diff --git a/goldap/bytes.go b/goldap/bytes.go
new file mode 100644
index 0000000..92c63a2
--- /dev/null
+++ b/goldap/bytes.go
@@ -0,0 +1,199 @@
+package message
+
+import (
+ "fmt"
+)
+
+type Bytes struct {
+ offset int
+ bytes []byte
+}
+
+func (bytes *Bytes) getBytes() []byte {
+ return bytes.bytes
+}
+func NewBytes(offset int, bytes []byte) (ret *Bytes) {
+ return &Bytes{offset: offset, bytes: bytes}
+}
+
+func (bytes Bytes) Debug() {
+ fmt.Printf("Offset: %d, Bytes: %+v\n", bytes.offset, bytes.bytes)
+}
+
+// Return a string with the hex dump of the bytes around the current offset
+// The current offset byte is put in brackets
+// Example: 0x01, [0x02], 0x03
+func (bytes *Bytes) DumpCurrentBytes() (ret string) {
+ var strings [3]string
+ for i := -1; i <= 1; i++ {
+ if bytes.offset+i >= 0 && bytes.offset+i < len(bytes.bytes) {
+ strings[i+1] = fmt.Sprintf("%#x", bytes.bytes[bytes.offset+i])
+ }
+ }
+ ret = fmt.Sprintf("%s, [%s], %s", strings[0], strings[1], strings[2])
+ return
+}
+
+func (bytes *Bytes) HasMoreData() bool {
+ return bytes.offset < len(bytes.bytes)
+}
+
+func (bytes *Bytes) ParseTagAndLength() (ret TagAndLength, err error) {
+ var offset int
+ ret, offset, err = ParseTagAndLength(bytes.bytes, bytes.offset)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("ParseTagAndLength: %s", err.Error())}
+ return
+ } else {
+ bytes.offset = offset
+ }
+ return
+}
+
+func (bytes *Bytes) ReadSubBytes(class int, tag int, callback func(bytes *Bytes) error) (err error) {
+ // Check tag
+ tagAndLength, err := bytes.ParseTagAndLength()
+ if err != nil {
+ return LdapError{fmt.Sprintf("ReadSubBytes:\n%s", err.Error())}
+ }
+ err = tagAndLength.Expect(class, tag, isCompound)
+ if err != nil {
+ return LdapError{fmt.Sprintf("ReadSubBytes:\n%s", err.Error())}
+ }
+
+ start := bytes.offset
+ end := bytes.offset + tagAndLength.Length
+
+ // Check we got enough bytes to process
+ if end > len(bytes.bytes) {
+ return LdapError{fmt.Sprintf("ReadSubBytes: data truncated: expecting %d bytes at offset %d", tagAndLength.Length, bytes.offset)}
+ }
+ // Process sub-bytes
+ subBytes := Bytes{offset: 0, bytes: bytes.bytes[start:end]}
+ err = callback(&subBytes)
+ if err != nil {
+ bytes.offset += subBytes.offset
+ err = LdapError{fmt.Sprintf("ReadSubBytes:\n%s", err.Error())}
+ return
+ }
+ // Check we got no more bytes to process
+ if subBytes.HasMoreData() {
+ return LdapError{fmt.Sprintf("ReadSubBytes: data too long: %d more bytes to read at offset %d", end-bytes.offset, bytes.offset)}
+ }
+ // Move offset
+ bytes.offset = end
+ return
+}
+
+func SizeSubBytes(tag int, callback func() int) (size int) {
+ size = callback()
+ size += sizeTagAndLength(tag, size)
+ return
+}
+
+func (bytes *Bytes) WritePrimitiveSubBytes(class int, tag int, value interface{}) (size int) {
+ switch value.(type) {
+ case BOOLEAN:
+ size = writeBool(bytes, bool(value.(BOOLEAN)))
+ case INTEGER:
+ size = writeInt32(bytes, int32(value.(INTEGER)))
+ case ENUMERATED:
+ size = writeInt32(bytes, int32(value.(ENUMERATED)))
+ case OCTETSTRING:
+ size = writeOctetString(bytes, []byte(string(value.(OCTETSTRING))))
+ default:
+ panic(fmt.Sprintf("WritePrimitiveSubBytes: invalid value type %v", value))
+ }
+ size += bytes.WriteTagAndLength(class, isNotCompound, tag, size)
+ return
+}
+
+func (bytes *Bytes) WriteTagAndLength(class int, compound bool, tag int, length int) int {
+ return writeTagAndLength(bytes, TagAndLength{Class: class, IsCompound: compound, Tag: tag, Length: length})
+}
+
+func (bytes *Bytes) writeString(s string) (size int) {
+ size = len(s)
+ start := bytes.offset - size
+ if start < 0 {
+ panic("Not enough space for string")
+ }
+ copy(bytes.bytes[start:], s)
+ bytes.offset = start
+ return
+}
+
+func (bytes *Bytes) writeBytes(b []byte) (size int) {
+ size = len(b)
+ start := bytes.offset - size
+ if start < 0 {
+ panic("Not enough space for bytes")
+ }
+ copy(bytes.bytes[start:], b)
+ bytes.offset = start
+ return
+}
+
+//
+// Parse tag, length and read the a primitive value
+// Supported types are:
+// - boolean
+// - integer (parsed as int32)
+// - enumerated (parsed as int32)
+// - UTF8 string
+// - Octet string
+//
+// Parameters:
+// - class: the expected class value(classUniversal, classApplication, classContextSpecific)
+// - tag: the expected tag value
+// - typeTag: the real primitive type to parse (tagBoolean, tagInteger, tagEnym, tagUTF8String, tagOctetString)
+//
+func (bytes *Bytes) ReadPrimitiveSubBytes(class int, tag int, typeTag int) (value interface{}, err error) {
+ // Check tag
+ tagAndLength, err := bytes.ParseTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes:\n%s", err.Error())}
+ return
+ }
+ err = tagAndLength.Expect(class, tag, isNotCompound)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes:\n%s", err.Error())}
+ return
+ }
+
+ start := bytes.offset
+ end := bytes.offset + tagAndLength.Length
+
+ // Check we got enough bytes to process
+ if end > len(bytes.bytes) {
+ // err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes: data truncated: expecting %d bytes at offset %d but only %d bytes are remaining (start: %d, length: %d, end: %d, len(b): %d, bytes: %#+v)", tagAndLength.Length, *b.offset, len(b.bytes)-start, start, tagAndLength.Length, end, len(b.bytes), b.bytes)}
+ err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes: data truncated: expecting %d bytes at offset %d but only %d bytes are remaining", tagAndLength.Length, bytes.offset, len(bytes.bytes)-start)}
+ return
+ }
+ // Process sub-bytes
+ subBytes := bytes.bytes[start:end]
+ switch typeTag {
+ case tagBoolean:
+ value, err = parseBool(subBytes)
+ case tagInteger:
+ value, err = parseInt32(subBytes)
+ case tagEnum:
+ value, err = parseInt32(subBytes)
+ case tagOctetString:
+ value, err = parseOctetString(subBytes)
+ default:
+ err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes: invalid type tag value %d", typeTag)}
+ return
+ }
+ if err != nil {
+ err = LdapError{fmt.Sprintf("ReadPrimitiveSubBytes:\n%s", err.Error())}
+ return
+ }
+ // Move offset
+ bytes.offset = end
+ return
+}
+
+func (bytes *Bytes) Bytes() []byte {
+ return bytes.bytes
+}
diff --git a/goldap/bytes_test.go b/goldap/bytes_test.go
new file mode 100644
index 0000000..c56489d
--- /dev/null
+++ b/goldap/bytes_test.go
@@ -0,0 +1,172 @@
+package message
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestReadPrimitiveSubBytesTestData(t *testing.T) {
+ for i, test := range PrimitiveSubBytesTestData() {
+ value, err := test.bytes.ReadPrimitiveSubBytes(test.class, test.tag, test.typeTag)
+ if err != nil {
+ t.Errorf("#%d failed: %s", i+1, err)
+ } else if !reflect.DeepEqual(test.value, value) {
+ t.Errorf("#%d: Wrong value %#v, got %#v", i+1, test.value, value)
+ } else if test.offset != test.bytes.offset {
+ t.Errorf("#%d: Wrong Offset, value %#v, got %#v", i+1, test.offset, test.bytes.offset)
+ }
+ }
+}
+
+func TestSizePrimitiveSubBytesTestData(t *testing.T) {
+ for i, test := range PrimitiveSubBytesTestData() {
+ value, err := test.bytes.ReadPrimitiveSubBytes(test.class, test.tag, test.typeTag)
+ if err != nil {
+ t.Errorf("#%d failed: %s", i+1, err)
+ } else if !reflect.DeepEqual(test.value, value) {
+ t.Errorf("#%d: Wrong value %#v, got %#v", i+1, test.value, value)
+ } else if test.offset != test.bytes.offset {
+ t.Errorf("#%d: Wrong Offset, value %#v, got %#v", i+1, test.offset, test.bytes.offset)
+ }
+ }
+}
+
+func NewInt(value int) (ret *int) {
+ ret = &value
+ return
+}
+
+type PrimitiveSubBytesTestSingleData struct {
+ bytes Bytes // Input
+ class int // Expected class
+ tag int // Expected tag
+ typeTag int // Expected type
+ value interface{} // Expected output
+ offset int // Expected offset after processing
+}
+
+func PrimitiveSubBytesTestData() []PrimitiveSubBytesTestSingleData {
+
+ return []PrimitiveSubBytesTestSingleData{
+ // Test 1
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x02, 0x01, 0x09},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x09),
+ offset: 3,
+ },
+ // Test 2
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x02, 0x02, 0x09, 0x87},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x0987),
+ offset: 4,
+ },
+ // Test 3
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x02, 0x03, 0x09, 0x87, 0x65},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x098765),
+ offset: 5,
+ },
+ // Test 4
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x02, 0x04, 0x09, 0x87, 0x65, 0x43},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x09876543),
+ offset: 6,
+ },
+ // Test 5
+ {
+ bytes: Bytes{
+ offset: 2,
+ bytes: []byte{0x30, 0x03, 0x02, 0x01, 0x0f},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x0f),
+ offset: 5,
+ },
+ // Test 6
+ {
+ bytes: Bytes{
+ offset: 2,
+ bytes: []byte{0x30, 0x16, 0x02, 0x01, 0x0f, 0x60, 0x11, 0x02, 0x01, 0x03, 0x04, 0x00, 0xa3, 0x0a, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x0f),
+ offset: 5,
+ },
+ // Test 7
+ {
+ bytes: Bytes{
+ offset: 2,
+ bytes: []byte{0x30, 0x19, 0x02, 0x04, 0x7f, 0xff, 0xff, 0xff, 0x60, 0x11, 0x02, 0x01, 0x03, 0x04, 0x00, 0xa3, 0x0a, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35},
+ },
+ class: classUniversal,
+ tag: tagInteger,
+ typeTag: tagInteger,
+ value: int32(0x07fffffff),
+ offset: 8,
+ },
+ // Test 8
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35},
+ },
+ class: classUniversal,
+ tag: tagOctetString,
+ typeTag: tagOctetString,
+ value: []byte("CRAM-MD5"),
+ offset: 10,
+ },
+ // Test 9
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{0x04, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c},
+ },
+ class: classUniversal,
+ tag: tagOctetString,
+ typeTag: tagOctetString,
+ value: []byte("Hello, 世界"),
+ offset: 15,
+ },
+ // Test 10
+ {
+ bytes: Bytes{
+ offset: 10,
+ bytes: []byte{0x30, 0x1d, 0x02, 0x01, 0x05, 0x60, 0x18, 0x02, 0x01, 0x03, 0x04, 0x07, 0x6d, 0x79, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x80, 0x0a, 0x6d, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64},
+ },
+ class: classUniversal,
+ tag: tagOctetString,
+ typeTag: tagOctetString,
+ value: []byte("myLogin"),
+ offset: 19,
+ },
+ }
+}
diff --git a/goldap/compare_request.go b/goldap/compare_request.go
new file mode 100644
index 0000000..dfbc346
--- /dev/null
+++ b/goldap/compare_request.go
@@ -0,0 +1,53 @@
+package message
+
+import "fmt"
+
+//
+// CompareRequest ::= [APPLICATION 14] SEQUENCE {
+// entry LDAPDN,
+// ava AttributeValueAssertion }
+
+func (request *CompareRequest) Entry() LDAPDN {
+ return request.entry
+}
+
+func (request *CompareRequest) Ava() *AttributeValueAssertion {
+ return &request.ava
+}
+
+func readCompareRequest(bytes *Bytes) (ret CompareRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagCompareRequest, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readCompareRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (request *CompareRequest) readComponents(bytes *Bytes) (err error) {
+ request.entry, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ request.ava, err = readAttributeValueAssertion(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (request CompareRequest) write(bytes *Bytes) (size int) {
+ size += request.ava.write(bytes)
+ size += request.entry.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagCompareRequest, size)
+ return
+}
+
+func (request CompareRequest) size() (size int) {
+ size += request.entry.size()
+ size += request.ava.size()
+ size += sizeTagAndLength(TagCompareRequest, size)
+ return
+}
diff --git a/goldap/compare_response.go b/goldap/compare_response.go
new file mode 100644
index 0000000..92083fc
--- /dev/null
+++ b/goldap/compare_response.go
@@ -0,0 +1,29 @@
+package message
+
+import "fmt"
+
+//
+// CompareResponse ::= [APPLICATION 15] LDAPResult
+
+func (response *CompareResponse) SetResultCode(code int) {
+ response.resultCode = ENUMERATED(code)
+}
+
+func readCompareResponse(bytes *Bytes) (ret CompareResponse, err error) {
+ var res LDAPResult
+ res, err = readTaggedLDAPResult(bytes, classApplication, TagCompareResponse)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readCompareResponse:\n%s", err.Error())}
+ return
+ }
+ ret = CompareResponse(res)
+ return
+}
+
+func (response CompareResponse) write(bytes *Bytes) int {
+ return LDAPResult(response).writeTagged(bytes, classApplication, TagCompareResponse)
+}
+
+func (response CompareResponse) size() int {
+ return LDAPResult(response).sizeTagged(TagCompareResponse)
+}
diff --git a/goldap/control.go b/goldap/control.go
new file mode 100644
index 0000000..3f94b67
--- /dev/null
+++ b/goldap/control.go
@@ -0,0 +1,94 @@
+package message
+
+import (
+ "errors"
+ "fmt"
+)
+
+//
+// Control ::= SEQUENCE {
+// controlType LDAPOID,
+// criticality BOOLEAN DEFAULT FALSE,
+// controlValue OCTET STRING OPTIONAL }
+
+func (control *Control) ControlType() LDAPOID {
+ return control.controlType
+}
+
+func (control *Control) Criticality() BOOLEAN {
+ return control.criticality
+}
+
+func (control *Control) ControlValue() *OCTETSTRING {
+ return control.controlValue
+}
+
+func readControl(bytes *Bytes) (control Control, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, control.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readControl:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (control *Control) readComponents(bytes *Bytes) (err error) {
+ control.controlType, err = readLDAPOID(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == tagBoolean {
+ control.criticality, err = readBOOLEAN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if control.criticality == false {
+ err = errors.New(fmt.Sprintf("readComponents: criticality default value FALSE should not be specified"))
+ return
+ }
+ }
+ }
+ if bytes.HasMoreData() {
+ var octetstring OCTETSTRING
+ octetstring, err = readOCTETSTRING(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ control.controlValue = octetstring.Pointer()
+ }
+ return
+}
+
+func (control Control) write(bytes *Bytes) (size int) {
+ if control.controlValue != nil {
+ size += control.controlValue.write(bytes)
+ }
+ if control.criticality != BOOLEAN(false) {
+ size += control.criticality.write(bytes)
+ }
+ size += control.controlType.write(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+
+func (control Control) size() (size int) {
+ if control.controlValue != nil {
+ size += control.controlValue.size()
+ }
+ if control.criticality != BOOLEAN(false) {
+ size += control.criticality.size()
+ }
+ size += control.controlType.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
diff --git a/goldap/controls.go b/goldap/controls.go
new file mode 100644
index 0000000..da3ddaf
--- /dev/null
+++ b/goldap/controls.go
@@ -0,0 +1,44 @@
+package message
+
+import "fmt"
+
+//
+// Controls ::= SEQUENCE OF control Control
+
+func readTaggedControls(bytes *Bytes, class int, tag int) (controls Controls, err error) {
+ err = bytes.ReadSubBytes(class, tag, controls.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedControls:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (controls *Controls) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var control Control
+ control, err = readControl(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *controls = append(*controls, control)
+ }
+ return
+}
+func (controls Controls) Pointer() *Controls { return &controls }
+
+func (controls Controls) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ for i := len(controls) - 1; i >= 0; i-- {
+ size += controls[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+func (controls Controls) sizeTagged(tag int) (size int) {
+ for _, control := range controls {
+ size += control.size()
+ }
+ size += sizeTagAndLength(tag, size)
+ return
+}
diff --git a/goldap/del_request.go b/goldap/del_request.go
new file mode 100644
index 0000000..ab24225
--- /dev/null
+++ b/goldap/del_request.go
@@ -0,0 +1,24 @@
+package message
+
+import "fmt"
+
+//
+// DelRequest ::= [APPLICATION 10] LDAPDN
+func readDelRequest(bytes *Bytes) (ret DelRequest, err error) {
+ var res LDAPDN
+ res, err = readTaggedLDAPDN(bytes, classApplication, TagDelRequest)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readDelRequest:\n%s", err.Error())}
+ return
+ }
+ ret = DelRequest(res)
+ return
+}
+
+func (del DelRequest) write(bytes *Bytes) int {
+ return LDAPDN(del).writeTagged(bytes, classApplication, TagDelRequest)
+}
+
+func (del DelRequest) size() int {
+ return LDAPDN(del).sizeTagged(TagDelRequest)
+}
diff --git a/goldap/del_response.go b/goldap/del_response.go
new file mode 100644
index 0000000..f2e14a7
--- /dev/null
+++ b/goldap/del_response.go
@@ -0,0 +1,29 @@
+package message
+
+import "fmt"
+
+//
+// DelResponse ::= [APPLICATION 11] LDAPResult
+
+func (del *DelResponse) SetResultCode(code int) {
+ del.resultCode = ENUMERATED(code)
+}
+
+func readDelResponse(bytes *Bytes) (ret DelResponse, err error) {
+ var res LDAPResult
+ res, err = readTaggedLDAPResult(bytes, classApplication, TagDelResponse)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readDelResponse:\n%s", err.Error())}
+ return
+ }
+ ret = DelResponse(res)
+ return
+}
+
+func (del DelResponse) write(bytes *Bytes) int {
+ return LDAPResult(del).writeTagged(bytes, classApplication, TagDelResponse)
+}
+
+func (del DelResponse) size() int {
+ return LDAPResult(del).sizeTagged(TagDelResponse)
+}
diff --git a/goldap/dn.go b/goldap/dn.go
new file mode 100644
index 0000000..c622fd8
--- /dev/null
+++ b/goldap/dn.go
@@ -0,0 +1,60 @@
+package message
+
+import "fmt"
+
+//
+// LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
+// -- [RFC4514]
+
+func readLDAPDN(bytes *Bytes) (ret LDAPDN, err error) {
+ var str LDAPString
+ str, err = readLDAPString(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readLDAPDN:\n%s", err.Error())}
+ return
+ }
+ ret = LDAPDN(str)
+ return
+}
+
+func readTaggedLDAPDN(bytes *Bytes, class int, tag int) (ret LDAPDN, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readTaggedLDAPString(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedLDAPDN:\n%s", err.Error())}
+ return
+ }
+ // @TODO: check RFC4514
+ ret = LDAPDN(ldapstring)
+ return
+}
+
+func (l LDAPDN) Pointer() *LDAPDN { return &l }
+
+func readRelativeLDAPDN(bytes *Bytes) (ret RelativeLDAPDN, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readLDAPString(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readRelativeLDAPDN:\n%s", err.Error())}
+ return
+ }
+ // @TODO: check RFC4514
+ ret = RelativeLDAPDN(ldapstring)
+ return
+}
+
+func (l LDAPDN) write(bytes *Bytes) int {
+ return LDAPString(l).write(bytes)
+}
+
+func (l LDAPDN) writeTagged(bytes *Bytes, class int, tag int) int {
+ return LDAPString(l).writeTagged(bytes, class, tag)
+}
+
+func (l LDAPDN) size() int {
+ return LDAPString(l).size()
+}
+
+func (l LDAPDN) sizeTagged(tag int) int {
+ return LDAPString(l).sizeTagged(tag)
+}
diff --git a/goldap/enumerated.go b/goldap/enumerated.go
new file mode 100644
index 0000000..6454688
--- /dev/null
+++ b/goldap/enumerated.go
@@ -0,0 +1,34 @@
+package message
+
+import "fmt"
+
+func (enum ENUMERATED) Int() int {
+ return int(enum)
+}
+
+func readENUMERATED(bytes *Bytes, allowedValues map[ENUMERATED]string) (ret ENUMERATED, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(classUniversal, tagEnum, tagEnum)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readENUMERATED:\n%s", err.Error())}
+ return
+ }
+ ret = ENUMERATED(value.(int32))
+ if _, ok := allowedValues[ret]; !ok {
+ err = LdapError{fmt.Sprintf("readENUMERATED: Invalid ENUMERATED VALUE %d", ret)}
+ return
+ }
+ return
+}
+
+func (enum ENUMERATED) write(bytes *Bytes) int {
+ return bytes.WritePrimitiveSubBytes(classUniversal, tagEnum, enum)
+}
+
+func (enum ENUMERATED) writeTagged(bytes *Bytes, class int, tag int) int {
+ return bytes.WritePrimitiveSubBytes(class, tag, enum)
+}
+
+func (enum ENUMERATED) size() int {
+ return SizePrimitiveSubBytes(tagEnum, enum)
+}
diff --git a/goldap/error.go b/goldap/error.go
new file mode 100644
index 0000000..7b5e1c6
--- /dev/null
+++ b/goldap/error.go
@@ -0,0 +1,9 @@
+package message
+
+type LdapError struct {
+ Msg string
+}
+
+func (err LdapError) Error() string {
+ return err.Msg
+}
diff --git a/goldap/extended_request.go b/goldap/extended_request.go
new file mode 100644
index 0000000..983ebf9
--- /dev/null
+++ b/goldap/extended_request.go
@@ -0,0 +1,69 @@
+package message
+
+import "fmt"
+
+//
+// ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+// requestName [0] LDAPOID,
+// requestValue [1] OCTET STRING OPTIONAL }
+
+func (extended *ExtendedRequest) RequestName() LDAPOID {
+ return extended.requestName
+}
+
+func (extended *ExtendedRequest) RequestValue() *OCTETSTRING {
+ return extended.requestValue
+}
+
+func readExtendedRequest(bytes *Bytes) (ret ExtendedRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagExtendedRequest, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readExtendedRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (extended *ExtendedRequest) readComponents(bytes *Bytes) (err error) {
+ extended.requestName, err = readTaggedLDAPOID(bytes, classContextSpecific, TagExtendedRequestName)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagExtendedRequestValue {
+ var requestValue OCTETSTRING
+ requestValue, err = readTaggedOCTETSTRING(bytes, classContextSpecific, TagExtendedRequestValue)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ extended.requestValue = requestValue.Pointer()
+ }
+ }
+ return
+}
+
+func (extended ExtendedRequest) write(bytes *Bytes) (size int) {
+ if extended.requestValue != nil {
+ size += extended.requestValue.writeTagged(bytes, classContextSpecific, TagExtendedRequestValue)
+ }
+ size += extended.requestName.writeTagged(bytes, classContextSpecific, TagExtendedRequestName)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagExtendedRequest, size)
+ return
+}
+
+func (extended ExtendedRequest) size() (size int) {
+ size += extended.requestName.sizeTagged(TagExtendedRequestName)
+ if extended.requestValue != nil {
+ size += extended.requestValue.sizeTagged(TagExtendedRequestValue)
+ }
+ size += sizeTagAndLength(TagExtendedRequest, size)
+ return
+}
diff --git a/goldap/extended_response.go b/goldap/extended_response.go
new file mode 100644
index 0000000..4e41b0e
--- /dev/null
+++ b/goldap/extended_response.go
@@ -0,0 +1,85 @@
+package message
+
+import "fmt"
+
+//
+// ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+// COMPONENTS OF LDAPResult,
+// responseName [10] LDAPOID OPTIONAL,
+// responseValue [11] OCTET STRING OPTIONAL }
+
+func (extended *ExtendedResponse) SetResponseName(name LDAPOID) {
+ extended.responseName = &name
+}
+
+func readExtendedResponse(bytes *Bytes) (ret ExtendedResponse, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagExtendedResponse, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readExtendedResponse:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+func (extended *ExtendedResponse) readComponents(bytes *Bytes) (err error) {
+ extended.LDAPResult.readComponents(bytes)
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagExtendedResponseName {
+ var oid LDAPOID
+ oid, err = readTaggedLDAPOID(bytes, classContextSpecific, TagExtendedResponseName)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ extended.responseName = oid.Pointer()
+ }
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagExtendedResponseValue {
+ var responseValue OCTETSTRING
+ responseValue, err = readTaggedOCTETSTRING(bytes, classContextSpecific, TagExtendedResponseValue)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ extended.responseValue = responseValue.Pointer()
+ }
+ }
+ return
+}
+
+func (extended ExtendedResponse) write(bytes *Bytes) (size int) {
+ if extended.responseValue != nil {
+ size += extended.responseValue.writeTagged(bytes, classContextSpecific, TagExtendedResponseValue)
+ }
+ if extended.responseName != nil {
+ size += extended.responseName.writeTagged(bytes, classContextSpecific, TagExtendedResponseName)
+ }
+ size += extended.LDAPResult.writeComponents(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagExtendedResponse, size)
+ return
+}
+
+func (extended ExtendedResponse) size() (size int) {
+ size += extended.LDAPResult.sizeComponents()
+ if extended.responseName != nil {
+ size += extended.responseName.sizeTagged(TagExtendedResponseName)
+ }
+ if extended.responseValue != nil {
+ size += extended.responseValue.sizeTagged(TagExtendedResponseValue)
+ }
+ size += sizeTagAndLength(TagExtendedResponse, size)
+ return
+}
diff --git a/goldap/filter.go b/goldap/filter.go
new file mode 100644
index 0000000..ba045ad
--- /dev/null
+++ b/goldap/filter.go
@@ -0,0 +1,70 @@
+package message
+
+import "fmt"
+
+//
+// Filter ::= CHOICE {
+// and [0] SET SIZE (1..MAX) OF filter Filter,
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+// not [2] Filter,
+// equalityMatch [3] AttributeValueAssertion,
+//
+//
+//
+//Sermersheim Standards Track [Page 57]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// substrings [4] SubstringFilter,
+// greaterOrEqual [5] AttributeValueAssertion,
+// lessOrEqual [6] AttributeValueAssertion,
+// present [7] AttributeDescription,
+// approxMatch [8] AttributeValueAssertion,
+// extensibleMatch [9] MatchingRuleAssertion,
+// ... }
+
+func readFilter(bytes *Bytes) (filter Filter, err error) {
+ var tagAndLength TagAndLength
+ tagAndLength, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilter:\n%s", err.Error())}
+ return
+ }
+ err = tagAndLength.ExpectClass(classContextSpecific)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilter:\n%s", err.Error())}
+ return
+ }
+ switch tagAndLength.Tag {
+ case TagFilterAnd:
+ filter, err = readFilterAnd(bytes)
+ case TagFilterOr:
+ filter, err = readFilterOr(bytes)
+ case TagFilterNot:
+ filter, err = readFilterNot(bytes)
+ case TagFilterEqualityMatch:
+ filter, err = readFilterEqualityMatch(bytes)
+ case TagFilterSubstrings:
+ filter, err = readFilterSubstrings(bytes)
+ case TagFilterGreaterOrEqual:
+ filter, err = readFilterGreaterOrEqual(bytes)
+ case TagFilterLessOrEqual:
+ filter, err = readFilterLessOrEqual(bytes)
+ case TagFilterPresent:
+ filter, err = readFilterPresent(bytes)
+ case TagFilterApproxMatch:
+ filter, err = readFilterApproxMatch(bytes)
+ case TagFilterExtensibleMatch:
+ filter, err = readFilterExtensibleMatch(bytes)
+ default:
+ err = LdapError{fmt.Sprintf("readFilter: invalid tag value %d for filter", tagAndLength.Tag)}
+ return
+ }
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilter:\n%s", err.Error())}
+ return
+ }
+ return
+}
diff --git a/goldap/filter_and.go b/goldap/filter_and.go
new file mode 100644
index 0000000..981284d
--- /dev/null
+++ b/goldap/filter_and.go
@@ -0,0 +1,54 @@
+package message
+
+import "fmt"
+
+// and [0] SET SIZE (1..MAX) OF filter Filter,
+
+func (filterAnd FilterAnd) getFilterTag() int {
+ return TagFilterAnd
+}
+
+func (filterAnd FilterAnd) size() (size int) {
+ for _, filter := range filterAnd {
+ size += filter.size()
+ }
+ size += sizeTagAndLength(TagFilterAnd, size)
+ return
+}
+
+func (filterAnd *FilterAnd) readComponents(bytes *Bytes) (err error) {
+ count := 0
+ for bytes.HasMoreData() {
+ count++
+ var filter Filter
+ filter, err = readFilter(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents (filter %d):\n%s", count, err.Error())}
+ return
+ }
+ *filterAnd = append(*filterAnd, filter)
+ }
+ if len(*filterAnd) == 0 {
+ err = LdapError{"readComponents: expecting at least one Filter"}
+ return
+ }
+ return
+}
+
+func (filterAnd FilterAnd) write(bytes *Bytes) (size int) {
+
+ for i := len(filterAnd) - 1; i >= 0; i-- {
+ size += filterAnd[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classContextSpecific, isCompound, TagFilterAnd, size)
+ return
+}
+
+func readFilterAnd(bytes *Bytes) (filterand FilterAnd, err error) {
+ err = bytes.ReadSubBytes(classContextSpecific, TagFilterAnd, filterand.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterAnd:\n%s", err.Error())}
+ return
+ }
+ return
+}
diff --git a/goldap/filter_approx_match.go b/goldap/filter_approx_match.go
new file mode 100644
index 0000000..65a802f
--- /dev/null
+++ b/goldap/filter_approx_match.go
@@ -0,0 +1,34 @@
+package message
+
+import "fmt"
+
+// approxMatch [8] AttributeValueAssertion,
+func readFilterApproxMatch(bytes *Bytes) (ret FilterApproxMatch, err error) {
+ var attributevalueassertion AttributeValueAssertion
+ attributevalueassertion, err = readTaggedAttributeValueAssertion(bytes, classContextSpecific, TagFilterApproxMatch)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterApproxMatch:\n%s", err.Error())}
+ return
+ }
+ ret = FilterApproxMatch(attributevalueassertion)
+ return
+}
+
+// approxMatch [8] AttributeValueAssertion,
+func (f FilterApproxMatch) write(bytes *Bytes) int {
+ return AttributeValueAssertion(f).writeTagged(bytes, classContextSpecific, TagFilterApproxMatch)
+}
+func (filterAnd FilterApproxMatch) getFilterTag() int {
+ return TagFilterApproxMatch
+}
+
+// approxMatch [8] AttributeValueAssertion,
+func (f FilterApproxMatch) size() int {
+ return AttributeValueAssertion(f).sizeTagged(TagFilterApproxMatch)
+}
+func (a *FilterApproxMatch) AttributeDesc() AttributeDescription {
+ return a.attributeDesc
+}
+func (a *FilterApproxMatch) AssertionValue() AssertionValue {
+ return a.assertionValue
+}
diff --git a/goldap/filter_equality_match.go b/goldap/filter_equality_match.go
new file mode 100644
index 0000000..19912ff
--- /dev/null
+++ b/goldap/filter_equality_match.go
@@ -0,0 +1,34 @@
+package message
+
+import "fmt"
+
+// equalityMatch [3] AttributeValueAssertion,
+func readFilterEqualityMatch(bytes *Bytes) (ret FilterEqualityMatch, err error) {
+ var attributevalueassertion AttributeValueAssertion
+ attributevalueassertion, err = readTaggedAttributeValueAssertion(bytes, classContextSpecific, TagFilterEqualityMatch)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterEqualityMatch:\n%s", err.Error())}
+ return
+ }
+ ret = FilterEqualityMatch(attributevalueassertion)
+ return
+}
+
+// equalityMatch [3] AttributeValueAssertion,
+func (f FilterEqualityMatch) write(bytes *Bytes) int {
+ return AttributeValueAssertion(f).writeTagged(bytes, classContextSpecific, TagFilterEqualityMatch)
+}
+func (filter FilterEqualityMatch) getFilterTag() int {
+ return TagFilterEqualityMatch
+}
+
+// equalityMatch [3] AttributeValueAssertion,
+func (f FilterEqualityMatch) size() int {
+ return AttributeValueAssertion(f).sizeTagged(TagFilterEqualityMatch)
+}
+func (a *FilterEqualityMatch) AttributeDesc() AttributeDescription {
+ return a.attributeDesc
+}
+func (a *FilterEqualityMatch) AssertionValue() AssertionValue {
+ return a.assertionValue
+}
diff --git a/goldap/filter_extensible_match.go b/goldap/filter_extensible_match.go
new file mode 100644
index 0000000..8c09c7f
--- /dev/null
+++ b/goldap/filter_extensible_match.go
@@ -0,0 +1,28 @@
+package message
+
+import "fmt"
+
+// extensibleMatch [9] MatchingRuleAssertion,
+func readFilterExtensibleMatch(bytes *Bytes) (filterextensiblematch FilterExtensibleMatch, err error) {
+ var matchingruleassertion MatchingRuleAssertion
+ matchingruleassertion, err = readTaggedMatchingRuleAssertion(bytes, classContextSpecific, TagFilterExtensibleMatch)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterExtensibleMatch:\n%s", err.Error())}
+ return
+ }
+ filterextensiblematch = FilterExtensibleMatch(matchingruleassertion)
+ return
+}
+
+// extensibleMatch [9] MatchingRuleAssertion,
+func (f FilterExtensibleMatch) write(bytes *Bytes) int {
+ return MatchingRuleAssertion(f).writeTagged(bytes, classContextSpecific, TagFilterExtensibleMatch)
+}
+func (filterAnd FilterExtensibleMatch) getFilterTag() int {
+ return TagFilterExtensibleMatch
+}
+
+// extensibleMatch [9] MatchingRuleAssertion,
+func (f FilterExtensibleMatch) size() int {
+ return MatchingRuleAssertion(f).sizeTagged(TagFilterExtensibleMatch)
+}
diff --git a/goldap/filter_greater_or_equal.go b/goldap/filter_greater_or_equal.go
new file mode 100644
index 0000000..450eefc
--- /dev/null
+++ b/goldap/filter_greater_or_equal.go
@@ -0,0 +1,34 @@
+package message
+
+import "fmt"
+
+// greaterOrEqual [5] AttributeValueAssertion,
+func readFilterGreaterOrEqual(bytes *Bytes) (ret FilterGreaterOrEqual, err error) {
+ var attributevalueassertion AttributeValueAssertion
+ attributevalueassertion, err = readTaggedAttributeValueAssertion(bytes, classContextSpecific, TagFilterGreaterOrEqual)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterGreaterOrEqual:\n%s", err.Error())}
+ return
+ }
+ ret = FilterGreaterOrEqual(attributevalueassertion)
+ return
+}
+
+// greaterOrEqual [5] AttributeValueAssertion,
+func (filter FilterGreaterOrEqual) write(bytes *Bytes) int {
+ return AttributeValueAssertion(filter).writeTagged(bytes, classContextSpecific, TagFilterGreaterOrEqual)
+}
+func (filter FilterGreaterOrEqual) getFilterTag() int {
+ return TagFilterGreaterOrEqual
+}
+
+// greaterOrEqual [5] AttributeValueAssertion,
+func (filter FilterGreaterOrEqual) size() int {
+ return AttributeValueAssertion(filter).sizeTagged(TagFilterGreaterOrEqual)
+}
+func (filter *FilterGreaterOrEqual) AttributeDesc() AttributeDescription {
+ return filter.attributeDesc
+}
+func (filter *FilterGreaterOrEqual) AssertionValue() AssertionValue {
+ return filter.assertionValue
+}
diff --git a/goldap/filter_less_or_equal.go b/goldap/filter_less_or_equal.go
new file mode 100644
index 0000000..0d22ae2
--- /dev/null
+++ b/goldap/filter_less_or_equal.go
@@ -0,0 +1,34 @@
+package message
+
+import "fmt"
+
+// lessOrEqual [6] AttributeValueAssertion,
+func readFilterLessOrEqual(bytes *Bytes) (ret FilterLessOrEqual, err error) {
+ var attributevalueassertion AttributeValueAssertion
+ attributevalueassertion, err = readTaggedAttributeValueAssertion(bytes, classContextSpecific, TagFilterLessOrEqual)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterLessOrEqual:\n%s", err.Error())}
+ return
+ }
+ ret = FilterLessOrEqual(attributevalueassertion)
+ return
+}
+
+// lessOrEqual [6] AttributeValueAssertion,
+func (f FilterLessOrEqual) write(bytes *Bytes) int {
+ return AttributeValueAssertion(f).writeTagged(bytes, classContextSpecific, TagFilterLessOrEqual)
+}
+func (filterAnd FilterLessOrEqual) getFilterTag() int {
+ return TagFilterLessOrEqual
+}
+
+// lessOrEqual [6] AttributeValueAssertion,
+func (f FilterLessOrEqual) size() int {
+ return AttributeValueAssertion(f).sizeTagged(TagFilterLessOrEqual)
+}
+func (a *FilterLessOrEqual) AttributeDesc() AttributeDescription {
+ return a.attributeDesc
+}
+func (a *FilterLessOrEqual) AssertionValue() AssertionValue {
+ return a.assertionValue
+}
diff --git a/goldap/filter_not.go b/goldap/filter_not.go
new file mode 100644
index 0000000..35726ac
--- /dev/null
+++ b/goldap/filter_not.go
@@ -0,0 +1,40 @@
+package message
+
+import "fmt"
+
+func (filterNot FilterNot) getFilterTag() int {
+ return TagFilterNot
+}
+
+// not [2] Filter,
+func (filterNot FilterNot) size() (size int) {
+ size = filterNot.Filter.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+
+func (filterNot *FilterNot) readComponents(bytes *Bytes) (err error) {
+ filterNot.Filter, err = readFilter(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+// not [2] Filter,
+func (filterNot FilterNot) write(bytes *Bytes) (size int) {
+ size = filterNot.Filter.write(bytes)
+ size += bytes.WriteTagAndLength(classContextSpecific, isCompound, TagFilterNot, size)
+ return
+}
+
+// not [2] Filter,
+func readFilterNot(bytes *Bytes) (filternot FilterNot, err error) {
+ err = bytes.ReadSubBytes(classContextSpecific, TagFilterNot, filternot.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterNot:\n%s", err.Error())}
+ return
+ }
+ return
+}
diff --git a/goldap/filter_or.go b/goldap/filter_or.go
new file mode 100644
index 0000000..9e5dc38
--- /dev/null
+++ b/goldap/filter_or.go
@@ -0,0 +1,52 @@
+package message
+
+import "fmt"
+
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+func readFilterOr(bytes *Bytes) (filteror FilterOr, err error) {
+ err = bytes.ReadSubBytes(classContextSpecific, TagFilterOr, filteror.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterOr:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (filteror *FilterOr) readComponents(bytes *Bytes) (err error) {
+ count := 0
+ for bytes.HasMoreData() {
+ count++
+ var filter Filter
+ filter, err = readFilter(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents (filter %d): %s", count, err.Error())}
+ return
+ }
+ *filteror = append(*filteror, filter)
+ }
+ if len(*filteror) == 0 {
+ err = LdapError{"readComponents: expecting at least one Filter"}
+ return
+ }
+ return
+}
+
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+func (f FilterOr) write(bytes *Bytes) (size int) {
+ for i := len(f) - 1; i >= 0; i-- {
+ size += f[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classContextSpecific, isCompound, TagFilterOr, size)
+ return
+}
+func (filter FilterOr) getFilterTag() int {
+ return TagFilterOr
+}
+
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+func (f FilterOr) size() (size int) {
+ for _, filter := range f {
+ size += filter.size()
+ }
+ size += sizeTagAndLength(TagFilterOr, size)
+ return
+}
diff --git a/goldap/filter_present.go b/goldap/filter_present.go
new file mode 100644
index 0000000..686b83a
--- /dev/null
+++ b/goldap/filter_present.go
@@ -0,0 +1,28 @@
+package message
+
+import "fmt"
+
+// present [7] AttributeDescription,
+func readFilterPresent(bytes *Bytes) (ret FilterPresent, err error) {
+ var attributedescription AttributeDescription
+ attributedescription, err = readTaggedAttributeDescription(bytes, classContextSpecific, TagFilterPresent)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterPresent:\n%s", err.Error())}
+ return
+ }
+ ret = FilterPresent(attributedescription)
+ return
+}
+
+// present [7] AttributeDescription,
+func (f FilterPresent) write(bytes *Bytes) int {
+ return AttributeDescription(f).writeTagged(bytes, classContextSpecific, TagFilterPresent)
+}
+func (filterAnd FilterPresent) getFilterTag() int {
+ return TagFilterPresent
+}
+
+// present [7] AttributeDescription,
+func (f FilterPresent) size() int {
+ return AttributeDescription(f).sizeTagged(TagFilterPresent)
+}
diff --git a/goldap/filter_substring.go b/goldap/filter_substring.go
new file mode 100644
index 0000000..8667420
--- /dev/null
+++ b/goldap/filter_substring.go
@@ -0,0 +1,187 @@
+package message
+
+import "fmt"
+
+// substrings [4] SubstringFilter,
+func readFilterSubstrings(bytes *Bytes) (filtersubstrings FilterSubstrings, err error) {
+ var substringfilter SubstringFilter
+ substringfilter, err = readTaggedSubstringFilter(bytes, classContextSpecific, TagFilterSubstrings)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readFilterSubstrings:\n%s", err.Error())}
+ return
+ }
+ filtersubstrings = FilterSubstrings(substringfilter)
+ return
+}
+
+//
+// SubstringFilter ::= SEQUENCE {
+// type AttributeDescription,
+// substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+// initial [0] AssertionValue, -- can occur at most once
+// any [1] AssertionValue,
+// final [2] AssertionValue } -- can occur at most once
+// }
+func readTaggedSubstringFilter(bytes *Bytes, class int, tag int) (substringfilter SubstringFilter, err error) {
+ err = bytes.ReadSubBytes(class, tag, substringfilter.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedSubstringFilter:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (substringfilter *SubstringFilter) readComponents(bytes *Bytes) (err error) {
+ substringfilter.type_, err = readAttributeDescription(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ err = substringfilter.readSubstrings(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (substringfilter *SubstringFilter) readSubstrings(bytes *Bytes) (err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, substringfilter.readSubstringsComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSubstrings:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (substringfilter *SubstringFilter) readSubstringsComponents(bytes *Bytes) (err error) {
+ var foundInitial = 0
+ var foundFinal = 0
+ var tagAndLength TagAndLength
+ for bytes.HasMoreData() {
+ tagAndLength, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSubstringsComponents:\n%s", err.Error())}
+ return
+ }
+ var assertionvalue AssertionValue
+ switch tagAndLength.Tag {
+ case TagSubstringInitial:
+ foundInitial++
+ if foundInitial > 1 {
+ err = LdapError{"readSubstringsComponents: initial can occur at most once"}
+ return
+ }
+ assertionvalue, err = readTaggedAssertionValue(bytes, classContextSpecific, TagSubstringInitial)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSubstringsComponents:\n%s", err.Error())}
+ return
+ }
+ substringfilter.substrings = append(substringfilter.substrings, SubstringInitial(assertionvalue))
+ case TagSubstringAny:
+ assertionvalue, err = readTaggedAssertionValue(bytes, classContextSpecific, TagSubstringAny)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSubstringsComponents:\n%s", err.Error())}
+ return
+ }
+ substringfilter.substrings = append(substringfilter.substrings, SubstringAny(assertionvalue))
+ case TagSubstringFinal:
+ foundFinal++
+ if foundFinal > 1 {
+ err = LdapError{"readSubstringsComponents: final can occur at most once"}
+ return
+ }
+ assertionvalue, err = readTaggedAssertionValue(bytes, classContextSpecific, TagSubstringFinal)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSubstringsComponents:\n%s", err.Error())}
+ return
+ }
+ substringfilter.substrings = append(substringfilter.substrings, SubstringFinal(assertionvalue))
+ default:
+ err = LdapError{fmt.Sprintf("readSubstringsComponents: invalid tag %d", tagAndLength.Tag)}
+ return
+ }
+ }
+ if len(substringfilter.substrings) == 0 {
+ err = LdapError{"readSubstringsComponents: expecting at least one substring"}
+ return
+ }
+ return
+}
+
+// substrings [4] SubstringFilter,
+func (f FilterSubstrings) write(bytes *Bytes) int {
+ return SubstringFilter(f).writeTagged(bytes, classContextSpecific, TagFilterSubstrings)
+}
+func (s SubstringFilter) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ for i := len(s.substrings) - 1; i >= 0; i-- {
+ substring := s.substrings[i]
+ switch substring.(type) {
+ case SubstringInitial:
+ size += AssertionValue(substring.(SubstringInitial)).writeTagged(bytes, classContextSpecific, TagSubstringInitial)
+ case SubstringAny:
+ size += AssertionValue(substring.(SubstringAny)).writeTagged(bytes, classContextSpecific, TagSubstringAny)
+ case SubstringFinal:
+ size += AssertionValue(substring.(SubstringFinal)).writeTagged(bytes, classContextSpecific, TagSubstringFinal)
+ default:
+ panic("Unknown type for SubstringFilter substring")
+ }
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ size += s.type_.write(bytes)
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+//
+// SubstringFilter ::= SEQUENCE {
+// type AttributeDescription,
+// substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+// initial [0] AssertionValue, -- can occur at most once
+// any [1] AssertionValue,
+// final [2] AssertionValue } -- can occur at most once
+// }
+func (s SubstringFilter) write(bytes *Bytes) (size int) {
+ return s.writeTagged(bytes, classUniversal, tagSequence)
+}
+func (filter FilterSubstrings) getFilterTag() int {
+ return TagFilterSubstrings
+}
+
+// substrings [4] SubstringFilter,
+func (f FilterSubstrings) size() int {
+ return SubstringFilter(f).sizeTagged(TagFilterSubstrings)
+}
+
+//
+// SubstringFilter ::= SEQUENCE {
+// type AttributeDescription,
+// substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+// initial [0] AssertionValue, -- can occur at most once
+// any [1] AssertionValue,
+// final [2] AssertionValue } -- can occur at most once
+// }
+func (s SubstringFilter) size() (size int) {
+ return s.sizeTagged(tagSequence)
+}
+func (s SubstringFilter) sizeTagged(tag int) (size int) {
+ for _, substring := range s.substrings {
+ switch substring.(type) {
+ case SubstringInitial:
+ size += AssertionValue(substring.(SubstringInitial)).sizeTagged(TagSubstringInitial)
+ case SubstringAny:
+ size += AssertionValue(substring.(SubstringAny)).sizeTagged(TagSubstringAny)
+ case SubstringFinal:
+ size += AssertionValue(substring.(SubstringFinal)).sizeTagged(TagSubstringFinal)
+ default:
+ panic("Unknown type for SubstringFilter substring")
+ }
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ size += s.type_.size()
+ size += sizeTagAndLength(tag, size)
+ return
+}
+func (s *FilterSubstrings) Type_() AttributeDescription {
+ return s.type_
+}
+func (s *FilterSubstrings) Substrings() []Substring {
+ return s.substrings
+}
diff --git a/goldap/integer.go b/goldap/integer.go
new file mode 100644
index 0000000..79e4248
--- /dev/null
+++ b/goldap/integer.go
@@ -0,0 +1,53 @@
+package message
+
+import "fmt"
+
+func readINTEGER(bytes *Bytes) (ret INTEGER, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(classUniversal, tagInteger, tagInteger)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readINTEGER:\n%s", err.Error())}
+ return
+ }
+ ret = INTEGER(value.(int32))
+ return
+}
+func readTaggedINTEGER(bytes *Bytes, class int, tag int) (ret INTEGER, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(class, tag, tagInteger)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedINTEGER:\n%s", err.Error())}
+ return
+ }
+ ret = INTEGER(value.(int32))
+ return
+}
+func readTaggedPositiveINTEGER(bytes *Bytes, class int, tag int) (ret INTEGER, err error) {
+ ret, err = readTaggedINTEGER(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedPositiveINTEGER:\n%s", err.Error())}
+ return
+ }
+ if !(ret >= 0 && ret <= maxInt) {
+ err = LdapError{fmt.Sprintf("readTaggedPositiveINTEGER: Invalid INTEGER value %d ! Expected value between 0 and %d", ret, maxInt)}
+ }
+ return
+}
+func readPositiveINTEGER(bytes *Bytes) (ret INTEGER, err error) {
+ return readTaggedPositiveINTEGER(bytes, classUniversal, tagInteger)
+}
+func (i INTEGER) write(bytes *Bytes) int {
+ return bytes.WritePrimitiveSubBytes(classUniversal, tagInteger, i)
+}
+func (i INTEGER) writeTagged(bytes *Bytes, class int, tag int) int {
+ return bytes.WritePrimitiveSubBytes(class, tag, i)
+}
+func (i INTEGER) size() int {
+ return SizePrimitiveSubBytes(tagInteger, i)
+}
+func (i INTEGER) sizeTagged(tag int) int {
+ return SizePrimitiveSubBytes(tag, i)
+}
+func (l INTEGER) Int() int {
+ return int(l)
+}
diff --git a/goldap/intermediate_response.go b/goldap/intermediate_response.go
new file mode 100644
index 0000000..90bf188
--- /dev/null
+++ b/goldap/intermediate_response.go
@@ -0,0 +1,89 @@
+package message
+
+import "fmt"
+
+//
+// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+// responseName [0] LDAPOID OPTIONAL,
+// responseValue [1] OCTET STRING OPTIONAL }
+func readIntermediateResponse(bytes *Bytes) (ret IntermediateResponse, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagIntermediateResponse, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readIntermediateResponse:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (bytes *Bytes) PreviewTagAndLength() (tagAndLength TagAndLength, err error) {
+ previousOffset := bytes.offset // Save offset
+ tagAndLength, err = bytes.ParseTagAndLength()
+ bytes.offset = previousOffset // Restore offset
+ return
+}
+func (res *IntermediateResponse) readComponents(bytes *Bytes) (err error) {
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagIntermediateResponseName {
+ var oid LDAPOID
+ oid, err = readTaggedLDAPOID(bytes, classContextSpecific, TagIntermediateResponseName)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ res.responseName = oid.Pointer()
+ }
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagIntermediateResponseValue {
+ var str OCTETSTRING
+ str, err = readTaggedOCTETSTRING(bytes, classContextSpecific, TagIntermediateResponseValue)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ res.responseValue = str.Pointer()
+ }
+ }
+ return
+}
+
+//
+// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+// responseName [0] LDAPOID OPTIONAL,
+// responseValue [1] OCTET STRING OPTIONAL }
+func (i IntermediateResponse) write(bytes *Bytes) (size int) {
+ if i.responseValue != nil {
+ size += i.responseValue.writeTagged(bytes, classContextSpecific, TagIntermediateResponseValue)
+ }
+ if i.responseName != nil {
+ size += i.responseName.writeTagged(bytes, classContextSpecific, TagIntermediateResponseName)
+ }
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagIntermediateResponse, size)
+ return
+}
+
+//
+// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+// responseName [0] LDAPOID OPTIONAL,
+// responseValue [1] OCTET STRING OPTIONAL }
+func (i IntermediateResponse) size() (size int) {
+ if i.responseName != nil {
+ size += i.responseName.sizeTagged(TagIntermediateResponseName)
+ }
+ if i.responseValue != nil {
+ size += i.responseValue.sizeTagged(TagIntermediateResponseValue)
+ }
+ size += sizeTagAndLength(TagIntermediateResponse, size)
+ return
+}
diff --git a/goldap/matching_rule_assertion.go b/goldap/matching_rule_assertion.go
new file mode 100644
index 0000000..e137852
--- /dev/null
+++ b/goldap/matching_rule_assertion.go
@@ -0,0 +1,117 @@
+package message
+
+import "fmt"
+
+//
+// MatchingRuleAssertion ::= SEQUENCE {
+// matchingRule [1] MatchingRuleId OPTIONAL,
+// type [2] AttributeDescription OPTIONAL,
+// matchValue [3] AssertionValue,
+// dnAttributes [4] BOOLEAN DEFAULT FALSE }
+func readTaggedMatchingRuleAssertion(bytes *Bytes, class int, tag int) (ret MatchingRuleAssertion, err error) {
+ err = bytes.ReadSubBytes(class, tag, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedMatchingRuleAssertion:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (matchingruleassertion *MatchingRuleAssertion) readComponents(bytes *Bytes) (err error) {
+ err = matchingruleassertion.readMatchingRule(bytes)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readComponents: %s", err.Error())}
+ }
+ err = matchingruleassertion.readType(bytes)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readComponents: %s", err.Error())}
+ }
+ matchingruleassertion.matchValue, err = readTaggedAssertionValue(bytes, classContextSpecific, TagMatchingRuleAssertionMatchValue)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readComponents: %s", err.Error())}
+ }
+ matchingruleassertion.dnAttributes, err = readTaggedBOOLEAN(bytes, classContextSpecific, TagMatchingRuleAssertionDnAttributes)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readComponents: %s", err.Error())}
+ }
+ return
+}
+func (matchingruleassertion *MatchingRuleAssertion) readMatchingRule(bytes *Bytes) (err error) {
+ var tagAndLength TagAndLength
+ tagAndLength, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ return LdapError{fmt.Sprintf("readMatchingRule: %s", err.Error())}
+ }
+ if tagAndLength.Tag == TagMatchingRuleAssertionMatchingRule {
+ var matchingRule MatchingRuleId
+ matchingRule, err = readTaggedMatchingRuleId(bytes, classContextSpecific, TagMatchingRuleAssertionMatchingRule)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readMatchingRule: %s", err.Error())}
+ }
+ matchingruleassertion.matchingRule = matchingRule.Pointer()
+ }
+ return
+}
+func (matchingruleassertion *MatchingRuleAssertion) readType(bytes *Bytes) (err error) {
+ var tagAndLength TagAndLength
+ tagAndLength, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ return LdapError{fmt.Sprintf("readType: %s", err.Error())}
+ }
+ if tagAndLength.Tag == TagMatchingRuleAssertionType {
+ var attributedescription AttributeDescription
+ attributedescription, err = readTaggedAttributeDescription(bytes, classContextSpecific, TagMatchingRuleAssertionType)
+ if err != nil {
+ return LdapError{fmt.Sprintf("readType: %s", err.Error())}
+ }
+ matchingruleassertion.type_ = &attributedescription
+ }
+ return
+}
+func (m MatchingRuleAssertion) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ if m.dnAttributes != BOOLEAN(false) {
+ size += m.dnAttributes.writeTagged(bytes, classContextSpecific, TagMatchingRuleAssertionDnAttributes)
+ }
+ size += m.matchValue.writeTagged(bytes, classContextSpecific, TagMatchingRuleAssertionMatchValue)
+ if m.type_ != nil {
+ size += m.type_.writeTagged(bytes, classContextSpecific, TagMatchingRuleAssertionType)
+ }
+ if m.matchingRule != nil {
+ size += m.matchingRule.writeTagged(bytes, classContextSpecific, TagMatchingRuleAssertionMatchingRule)
+ }
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+//
+// MatchingRuleAssertion ::= SEQUENCE {
+// matchingRule [1] MatchingRuleId OPTIONAL,
+// type [2] AttributeDescription OPTIONAL,
+// matchValue [3] AssertionValue,
+// dnAttributes [4] BOOLEAN DEFAULT FALSE }
+func (m MatchingRuleAssertion) write(bytes *Bytes) (size int) {
+ return m.writeTagged(bytes, classUniversal, tagSequence)
+}
+
+//
+// MatchingRuleAssertion ::= SEQUENCE {
+// matchingRule [1] MatchingRuleId OPTIONAL,
+// type [2] AttributeDescription OPTIONAL,
+// matchValue [3] AssertionValue,
+// dnAttributes [4] BOOLEAN DEFAULT FALSE }
+func (m MatchingRuleAssertion) size() (size int) {
+ return m.sizeTagged(tagSequence)
+}
+func (m MatchingRuleAssertion) sizeTagged(tag int) (size int) {
+ if m.matchingRule != nil {
+ size += m.matchingRule.sizeTagged(TagMatchingRuleAssertionMatchingRule)
+ }
+ if m.type_ != nil {
+ size += m.type_.sizeTagged(TagMatchingRuleAssertionType)
+ }
+ size += m.matchValue.sizeTagged(TagMatchingRuleAssertionMatchValue)
+ if m.dnAttributes != BOOLEAN(false) {
+ size += m.dnAttributes.sizeTagged(TagMatchingRuleAssertionDnAttributes)
+ }
+ size += sizeTagAndLength(tag, size)
+ return
+}
diff --git a/goldap/matching_rule_id.go b/goldap/matching_rule_id.go
new file mode 100644
index 0000000..77417c2
--- /dev/null
+++ b/goldap/matching_rule_id.go
@@ -0,0 +1,29 @@
+package message
+
+import "fmt"
+
+//
+// MatchingRuleId ::= LDAPString
+func readTaggedMatchingRuleId(bytes *Bytes, class int, tag int) (matchingruleid MatchingRuleId, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readTaggedLDAPString(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedMatchingRuleId:\n%s", err.Error())}
+ return
+ }
+ matchingruleid = MatchingRuleId(ldapstring)
+ return
+}
+func (m MatchingRuleId) Pointer() *MatchingRuleId { return &m }
+
+//
+// MatchingRuleId ::= LDAPString
+func (m MatchingRuleId) writeTagged(bytes *Bytes, class int, tag int) int {
+ return LDAPString(m).writeTagged(bytes, class, tag)
+}
+
+//
+// MatchingRuleId ::= LDAPString
+func (m MatchingRuleId) sizeTagged(tag int) int {
+ return LDAPString(m).sizeTagged(tag)
+}
diff --git a/goldap/message.go b/goldap/message.go
new file mode 100644
index 0000000..a227d16
--- /dev/null
+++ b/goldap/message.go
@@ -0,0 +1,139 @@
+package message
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// This appendix is normative.
+//
+// Lightweight-Directory-Access-Protocol-V3 {1 3 6 1 1 18}
+// -- Copyright (C) The Internet Society (2006). This version of
+// -- this ASN.1 module is part of RFC 4511; see the RFC itself
+// -- for full legal notices.
+// DEFINITIONS
+// IMPLICIT TAGS
+// EXTENSIBILITY IMPLIED ::=
+//
+// BEGIN
+//
+// LDAPMessage ::= SEQUENCE {
+// messageID MessageID,
+// protocolOp CHOICE {
+// bindRequest BindRequest,
+// bindResponse BindResponse,
+// unbindRequest UnbindRequest,
+// searchRequest SearchRequest,
+// searchResEntry SearchResultEntry,
+// searchResDone SearchResultDone,
+// searchResRef SearchResultReference,
+// modifyRequest ModifyRequest,
+// modifyResponse ModifyResponse,
+// addRequest AddRequest,
+// addResponse AddResponse,
+// delRequest DelRequest,
+// delResponse DelResponse,
+// modDNRequest ModifyDNRequest,
+// modDNResponse ModifyDNResponse,
+// compareRequest CompareRequest,
+// compareResponse CompareResponse,
+// abandonRequest AbandonRequest,
+// extendedReq ExtendedRequest,
+// extendedResp ExtendedResponse,
+// ...,
+// intermediateResponse IntermediateResponse },
+// controls [0] Controls OPTIONAL }
+//
+
+func NewLDAPMessage() *LDAPMessage { return &LDAPMessage{} }
+
+func (message *LDAPMessage) readComponents(bytes *Bytes) (err error) {
+ message.messageID, err = readMessageID(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ message.protocolOp, err = readProtocolOp(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagLDAPMessageControls {
+ var controls Controls
+ controls, err = readTaggedControls(bytes, classContextSpecific, TagLDAPMessageControls)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ message.controls = controls.Pointer()
+ }
+ }
+ return
+}
+
+func (m *LDAPMessage) Write() (bytes *Bytes, err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = LdapError{fmt.Sprintf("Error in LDAPMessage.Write: %s", e)}
+ }
+ }()
+ // Compute the needed size
+ totalSize := m.size()
+ // Initialize the structure
+ bytes = &Bytes{
+ bytes: make([]byte, totalSize),
+ offset: totalSize,
+ }
+
+ // Go !
+ size := 0
+ if m.controls != nil {
+ size += m.controls.writeTagged(bytes, classContextSpecific, TagLDAPMessageControls)
+ }
+ size += m.protocolOp.write(bytes)
+ size += m.messageID.write(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ // Check
+ if size != totalSize || bytes.offset != 0 {
+ err = LdapError{fmt.Sprintf("Something went wrong while writing the message ! Size is %d instead of %d, final offset is %d instead of 0", size, totalSize, bytes.offset)}
+ }
+ return
+}
+func (m *LDAPMessage) size() (size int) {
+ size += m.messageID.size()
+ size += m.protocolOp.size()
+ if m.controls != nil {
+ size += m.controls.sizeTagged(TagLDAPMessageControls)
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (l *LDAPMessage) MessageID() MessageID {
+ return l.messageID
+}
+func (l *LDAPMessage) SetMessageID(ID int) {
+ l.messageID = MessageID(ID)
+}
+func (l *LDAPMessage) Controls() *Controls {
+ return l.controls
+}
+func (l *LDAPMessage) ProtocolOp() ProtocolOp {
+ return l.protocolOp
+}
+func (l *LDAPMessage) ProtocolOpName() string {
+ return reflect.TypeOf(l.ProtocolOp()).Name()
+}
+func (l *LDAPMessage) ProtocolOpType() int {
+ switch l.protocolOp.(type) {
+ case BindRequest:
+ return TagBindRequest
+ }
+ return 0
+}
diff --git a/goldap/message_id.go b/goldap/message_id.go
new file mode 100644
index 0000000..05c7157
--- /dev/null
+++ b/goldap/message_id.go
@@ -0,0 +1,46 @@
+package message
+
+import "fmt"
+
+func readTaggedMessageID(bytes *Bytes, class int, tag int) (ret MessageID, err error) {
+ var integer INTEGER
+ integer, err = readTaggedPositiveINTEGER(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedMessageID:\n%s", err.Error())}
+ return
+ }
+ return MessageID(integer), err
+}
+
+// MessageID ::= INTEGER (0 .. maxInt)
+//
+// maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
+//
+func readMessageID(bytes *Bytes) (ret MessageID, err error) {
+ return readTaggedMessageID(bytes, classUniversal, tagInteger)
+}
+
+// MessageID ::= INTEGER (0 .. maxInt)
+//
+// maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
+//
+func (m MessageID) write(bytes *Bytes) int {
+ return INTEGER(m).write(bytes)
+}
+func (m MessageID) writeTagged(bytes *Bytes, class int, tag int) int {
+ return INTEGER(m).writeTagged(bytes, class, tag)
+}
+
+// MessageID ::= INTEGER (0 .. maxInt)
+//
+// maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
+//
+func (m MessageID) size() int {
+ return INTEGER(m).size()
+}
+func (m MessageID) sizeTagged(tag int) int {
+ return INTEGER(m).sizeTagged(tag)
+}
+func (l MessageID) Int() int {
+ return int(l)
+}
diff --git a/goldap/message_test.go b/goldap/message_test.go
new file mode 100644
index 0000000..9d10d98
--- /dev/null
+++ b/goldap/message_test.go
@@ -0,0 +1,76 @@
+package message
+
+import (
+ "testing"
+ "fmt"
+)
+
+func toHex(b []byte) (r string) {
+ r = "[ "
+ for _, e := range b {
+ r += fmt.Sprintf("0x%x ", e)
+ }
+ return r + "]"
+}
+
+func TestMessageID(t *testing.T) {
+ m := NewLDAPMessageWithProtocolOp(UnbindRequest{})
+ m.SetMessageID(128)
+ buf, err := m.Write()
+ if err != nil {
+ t.Errorf("marshalling failed with %v", err)
+ }
+ t.Logf("%v", toHex(buf.Bytes()))
+
+ ret, err := ReadLDAPMessage(NewBytes(0, buf.Bytes()))
+ if err != nil {
+ t.Errorf("unmarshalling failed with %v", err)
+ }
+ if _, ok := ret.ProtocolOp().(UnbindRequest); !ok {
+ t.Errorf("should be an unbind request")
+ }
+ if ret.MessageID() != 128 {
+ t.Errorf("Expect message id 128, got %d", ret.MessageID())
+ }
+ t.Log("Done, marshal/unmarshall worked")
+}
+
+func TestSearchEntry(t *testing.T) {
+ m := NewLDAPMessageWithProtocolOp(SearchResultEntry{
+ objectName:"cn=êige€nbgtz,ou=users,dc=deuxfleurs,dc=fr",
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_:"displayname",
+ vals:[]AttributeValue{"êiGe€NBgTZ"},
+ },
+ PartialAttribute{
+ type_:"objectclass",
+ vals:[]AttributeValue{"inetOrgPerson"},
+ },
+ PartialAttribute{
+ type_:"objectclass",
+ vals:[]AttributeValue{"organizationalPerson"},
+ },
+ PartialAttribute{
+ type_:"objectclass",
+ vals:[]AttributeValue{"person"},
+ },
+ PartialAttribute{
+ type_:"objectclass",
+ vals:[]AttributeValue{"top"},
+ },
+ PartialAttribute{
+ type_:"structuralobjectclass",
+ vals:[]AttributeValue{"inetOrgPerson"},
+ },
+ },
+ })
+ m.SetMessageID(24)
+ buf, err := m.Write()
+ if err != nil {
+ t.Errorf("marshalling failed with %v", err)
+ }
+ if buf.Bytes()[0] != 0x30 {
+ t.Logf("Malformed message: %v", toHex(buf.Bytes()))
+ }
+}
diff --git a/goldap/modify_dn_request.go b/goldap/modify_dn_request.go
new file mode 100644
index 0000000..8c4ab75
--- /dev/null
+++ b/goldap/modify_dn_request.go
@@ -0,0 +1,87 @@
+package message
+
+import "fmt"
+
+//
+// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+// entry LDAPDN,
+// newrdn RelativeLDAPDN,
+// deleteoldrdn BOOLEAN,
+// newSuperior [0] LDAPDN OPTIONAL }
+func readModifyDNRequest(bytes *Bytes) (ret ModifyDNRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagModifyDNRequest, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readModifyDNRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (req *ModifyDNRequest) readComponents(bytes *Bytes) (err error) {
+ req.entry, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ req.newrdn, err = readRelativeLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ req.deleteoldrdn, err = readBOOLEAN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagModifyDNRequestNewSuperior {
+ var ldapdn LDAPDN
+ ldapdn, err = readTaggedLDAPDN(bytes, classContextSpecific, TagModifyDNRequestNewSuperior)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ req.newSuperior = ldapdn.Pointer()
+ }
+ }
+ return
+}
+
+//
+// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+// entry LDAPDN,
+// newrdn RelativeLDAPDN,
+// deleteoldrdn BOOLEAN,
+// newSuperior [0] LDAPDN OPTIONAL }
+func (m ModifyDNRequest) write(bytes *Bytes) (size int) {
+ if m.newSuperior != nil {
+ size += m.newSuperior.writeTagged(bytes, classContextSpecific, TagModifyDNRequestNewSuperior)
+ }
+ size += m.deleteoldrdn.write(bytes)
+ size += m.newrdn.write(bytes)
+ size += m.entry.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagModifyDNRequest, size)
+ return
+}
+
+//
+// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+// entry LDAPDN,
+// newrdn RelativeLDAPDN,
+// deleteoldrdn BOOLEAN,
+// newSuperior [0] LDAPDN OPTIONAL }
+func (m ModifyDNRequest) size() (size int) {
+ size += m.entry.size()
+ size += m.newrdn.size()
+ size += m.deleteoldrdn.size()
+ if m.newSuperior != nil {
+ size += m.newSuperior.sizeTagged(TagModifyDNRequestNewSuperior)
+ }
+ size += sizeTagAndLength(TagModifyDNRequest, size)
+ return
+}
diff --git a/goldap/modify_dn_response.go b/goldap/modify_dn_response.go
new file mode 100644
index 0000000..9282aba
--- /dev/null
+++ b/goldap/modify_dn_response.go
@@ -0,0 +1,28 @@
+package message
+
+import "fmt"
+
+//
+// ModifyDNResponse ::= [APPLICATION 13] LDAPResult
+func readModifyDNResponse(bytes *Bytes) (ret ModifyDNResponse, err error) {
+ var res LDAPResult
+ res, err = readTaggedLDAPResult(bytes, classApplication, TagModifyDNResponse)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readModifyDNResponse:\n%s", err.Error())}
+ return
+ }
+ ret = ModifyDNResponse(res)
+ return
+}
+
+//
+// ModifyDNResponse ::= [APPLICATION 13] LDAPResult
+func (m ModifyDNResponse) write(bytes *Bytes) int {
+ return LDAPResult(m).writeTagged(bytes, classApplication, TagModifyDNResponse)
+}
+
+//
+// ModifyDNResponse ::= [APPLICATION 13] LDAPResult
+func (m ModifyDNResponse) size() int {
+ return LDAPResult(m).sizeTagged(TagModifyDNResponse)
+}
diff --git a/goldap/modify_request.go b/goldap/modify_request.go
new file mode 100644
index 0000000..c66c00d
--- /dev/null
+++ b/goldap/modify_request.go
@@ -0,0 +1,89 @@
+package message
+
+import "fmt"
+
+//
+// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+// object LDAPDN,
+// changes SEQUENCE OF change SEQUENCE {
+// operation ENUMERATED {
+// add (0),
+// delete (1),
+// replace (2),
+// ... },
+// modification PartialAttribute } }
+func readModifyRequest(bytes *Bytes) (ret ModifyRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagModifyRequest, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readModifyRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (m *ModifyRequest) readComponents(bytes *Bytes) (err error) {
+ m.object, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, m.readChanges)
+ return
+}
+func (m *ModifyRequest) readChanges(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var c ModifyRequestChange
+ c, err = readModifyRequestChange(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readChanges:\n%s", err.Error())}
+ return
+ }
+ m.changes = append(m.changes, c)
+ }
+ return
+}
+
+//
+// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+// object LDAPDN,
+// changes SEQUENCE OF change SEQUENCE {
+// operation ENUMERATED {
+// add (0),
+// delete (1),
+// replace (2),
+// ... },
+// modification PartialAttribute } }
+func (m ModifyRequest) write(bytes *Bytes) (size int) {
+ for i := len(m.changes) - 1; i >= 0; i-- {
+ size += m.changes[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ size += m.object.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagModifyRequest, size)
+ return
+}
+
+//
+// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+// object LDAPDN,
+// changes SEQUENCE OF change SEQUENCE {
+// operation ENUMERATED {
+// add (0),
+// delete (1),
+// replace (2),
+// ... },
+// modification PartialAttribute } }
+func (m ModifyRequest) size() (size int) {
+ for _, change := range m.changes {
+ size += change.size()
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ size += m.object.size()
+ size += sizeTagAndLength(TagModifyRequest, size)
+ return
+}
+func (m *ModifyRequest) Object() LDAPDN {
+ return m.object
+}
+func (m *ModifyRequest) Changes() []ModifyRequestChange {
+ return m.changes
+}
diff --git a/goldap/modify_request_change.go b/goldap/modify_request_change.go
new file mode 100644
index 0000000..e3728c1
--- /dev/null
+++ b/goldap/modify_request_change.go
@@ -0,0 +1,43 @@
+package message
+
+import "fmt"
+
+func readModifyRequestChange(bytes *Bytes) (ret ModifyRequestChange, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readModifyRequestChange:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (m *ModifyRequestChange) readComponents(bytes *Bytes) (err error) {
+ m.operation, err = readENUMERATED(bytes, EnumeratedModifyRequestChangeOperation)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ m.modification, err = readPartialAttribute(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (m ModifyRequestChange) write(bytes *Bytes) (size int) {
+ size += m.modification.write(bytes)
+ size += m.operation.write(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+func (m ModifyRequestChange) size() (size int) {
+ size += m.operation.size()
+ size += m.modification.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (m *ModifyRequestChange) Operation() ENUMERATED {
+ return m.operation
+}
+func (m *ModifyRequestChange) Modification() *PartialAttribute {
+ return &m.modification
+}
diff --git a/goldap/modify_response.go b/goldap/modify_response.go
new file mode 100644
index 0000000..2a214d2
--- /dev/null
+++ b/goldap/modify_response.go
@@ -0,0 +1,36 @@
+package message
+
+import "fmt"
+
+//
+// ModifyResponse ::= [APPLICATION 7] LDAPResult
+func readModifyResponse(bytes *Bytes) (ret ModifyResponse, err error) {
+ var res LDAPResult
+ res, err = readTaggedLDAPResult(bytes, classApplication, TagModifyResponse)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readModifyResponse:\n%s", err.Error())}
+ return
+ }
+ ret = ModifyResponse(res)
+ return
+}
+func (l LDAPResult) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ size += l.writeComponents(bytes)
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+//
+// ModifyResponse ::= [APPLICATION 7] LDAPResult
+func (m ModifyResponse) write(bytes *Bytes) int {
+ return LDAPResult(m).writeTagged(bytes, classApplication, TagModifyResponse)
+}
+
+//
+// ModifyResponse ::= [APPLICATION 7] LDAPResult
+func (m ModifyResponse) size() int {
+ return LDAPResult(m).sizeTagged(TagModifyResponse)
+}
+func (l *ModifyResponse) SetResultCode(code int) {
+ l.resultCode = ENUMERATED(code)
+}
diff --git a/goldap/octetstring.go b/goldap/octetstring.go
new file mode 100644
index 0000000..719f838
--- /dev/null
+++ b/goldap/octetstring.go
@@ -0,0 +1,44 @@
+package message
+
+import "fmt"
+
+func readOCTETSTRING(bytes *Bytes) (ret OCTETSTRING, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(classUniversal, tagOctetString, tagOctetString)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readOCTETSTRING:\n%s", err.Error())}
+ return
+ }
+ ret = OCTETSTRING(value.([]byte))
+ return
+}
+
+func readTaggedOCTETSTRING(bytes *Bytes, class int, tag int) (ret OCTETSTRING, err error) {
+ var value interface{}
+ value, err = bytes.ReadPrimitiveSubBytes(class, tag, tagOctetString)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedOCTETSTRING:\n%s", err.Error())}
+ return
+ }
+ ret = OCTETSTRING(value.([]byte))
+ return
+}
+func (o OCTETSTRING) Pointer() *OCTETSTRING { return &o }
+func (o OCTETSTRING) write(bytes *Bytes) int {
+ return bytes.WritePrimitiveSubBytes(classUniversal, tagOctetString, o)
+}
+func (o OCTETSTRING) writeTagged(bytes *Bytes, class int, tag int) int {
+ return bytes.WritePrimitiveSubBytes(class, tag, o)
+}
+func (o OCTETSTRING) size() int {
+ return SizePrimitiveSubBytes(tagOctetString, o)
+}
+func (o OCTETSTRING) sizeTagged(tag int) int {
+ return SizePrimitiveSubBytes(tag, o)
+}
+func (l OCTETSTRING) String() string {
+ return string(l)
+}
+func (l OCTETSTRING) Bytes() []byte {
+ return []byte(l)
+}
diff --git a/goldap/oid.go b/goldap/oid.go
new file mode 100644
index 0000000..b2c5c81
--- /dev/null
+++ b/goldap/oid.go
@@ -0,0 +1,50 @@
+package message
+
+import "fmt"
+
+//
+//
+// LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+// -- [RFC4512]
+
+func (l LDAPOID) String() string {
+ return string(l)
+}
+
+func (l LDAPOID) Bytes() []byte {
+ return []byte(l)
+}
+
+func (l LDAPOID) Pointer() *LDAPOID { return &l }
+
+func readTaggedLDAPOID(bytes *Bytes, class int, tag int) (ret LDAPOID, err error) {
+ var octetstring OCTETSTRING
+ octetstring, err = readTaggedOCTETSTRING(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedLDAPOID:\n%s", err.Error())}
+ return
+ }
+ // @TODO: check RFC4512 for <numericoid>
+ ret = LDAPOID(octetstring)
+ return
+}
+
+func readLDAPOID(bytes *Bytes) (ret LDAPOID, err error) {
+ return readTaggedLDAPOID(bytes, classUniversal, tagOctetString)
+}
+
+func (l LDAPOID) write(bytes *Bytes) int {
+ return OCTETSTRING(l).write(bytes)
+}
+
+func (l LDAPOID) writeTagged(bytes *Bytes, class int, tag int) int {
+ return OCTETSTRING(l).writeTagged(bytes, class, tag)
+}
+
+func (l LDAPOID) size() int {
+ return OCTETSTRING(l).size()
+}
+
+func (l LDAPOID) sizeTagged(tag int) int {
+ return OCTETSTRING(l).sizeTagged(tag)
+}
diff --git a/goldap/partial_attribute.go b/goldap/partial_attribute.go
new file mode 100644
index 0000000..4cd0215
--- /dev/null
+++ b/goldap/partial_attribute.go
@@ -0,0 +1,76 @@
+package message
+
+import "fmt"
+
+//
+// PartialAttribute ::= SEQUENCE {
+// type AttributeDescription,
+// vals SET OF value AttributeValue }
+func readPartialAttribute(bytes *Bytes) (ret PartialAttribute, err error) {
+ ret = PartialAttribute{vals: make([]AttributeValue, 0, 10)}
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readPartialAttribute:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (partialattribute *PartialAttribute) readComponents(bytes *Bytes) (err error) {
+ partialattribute.type_, err = readAttributeDescription(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ err = bytes.ReadSubBytes(classUniversal, tagSet, partialattribute.readValsComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (partialattribute *PartialAttribute) readValsComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var attributevalue AttributeValue
+ attributevalue, err = readAttributeValue(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readValsComponents:\n%s", err.Error())}
+ return
+ }
+ partialattribute.vals = append(partialattribute.vals, attributevalue)
+ }
+ return
+}
+
+//
+// PartialAttribute ::= SEQUENCE {
+// type AttributeDescription,
+// vals SET OF value AttributeValue }
+func (p PartialAttribute) write(bytes *Bytes) (size int) {
+ for i := len(p.vals) - 1; i >= 0; i-- {
+ size += p.vals[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSet, size)
+ size += p.type_.write(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+
+//
+// PartialAttribute ::= SEQUENCE {
+// type AttributeDescription,
+// vals SET OF value AttributeValue }
+func (p PartialAttribute) size() (size int) {
+ for _, value := range p.vals {
+ size += value.size()
+ }
+ size += sizeTagAndLength(tagSet, size)
+ size += p.type_.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (p *PartialAttribute) Type_() AttributeDescription {
+ return p.type_
+}
+func (p *PartialAttribute) Vals() []AttributeValue {
+ return p.vals
+}
diff --git a/goldap/partial_attribute_list.go b/goldap/partial_attribute_list.go
new file mode 100644
index 0000000..f55d4f9
--- /dev/null
+++ b/goldap/partial_attribute_list.go
@@ -0,0 +1,53 @@
+package message
+
+import "fmt"
+
+//
+// PartialAttributeList ::= SEQUENCE OF
+// partialAttribute PartialAttribute
+func readPartialAttributeList(bytes *Bytes) (ret PartialAttributeList, err error) {
+ ret = PartialAttributeList(make([]PartialAttribute, 0, 10))
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readPartialAttributeList:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (partialattributelist *PartialAttributeList) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var partialattribute PartialAttribute
+ partialattribute, err = readPartialAttribute(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *partialattributelist = append(*partialattributelist, partialattribute)
+ }
+ return
+}
+
+//
+// PartialAttributeList ::= SEQUENCE OF
+// partialAttribute PartialAttribute
+func (p PartialAttributeList) write(bytes *Bytes) (size int) {
+ for i := len(p) - 1; i >= 0; i-- {
+ size += p[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+
+//
+// PartialAttributeList ::= SEQUENCE OF
+// partialAttribute PartialAttribute
+func (p PartialAttributeList) size() (size int) {
+ for _, att := range p {
+ size += att.size()
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (p *PartialAttributeList) add(a PartialAttribute) {
+ *p = append(*p, a)
+}
diff --git a/goldap/protocol_op.go b/goldap/protocol_op.go
new file mode 100644
index 0000000..0ea3881
--- /dev/null
+++ b/goldap/protocol_op.go
@@ -0,0 +1,63 @@
+package message
+
+import "fmt"
+
+func readProtocolOp(bytes *Bytes) (ret ProtocolOp, err error) {
+ tagAndLength, err := bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readProtocolOp:\n%s", err.Error())}
+ return
+ }
+ switch tagAndLength.Tag {
+ case TagBindRequest:
+ ret, err = readBindRequest(bytes)
+ case TagBindResponse:
+ ret, err = readBindResponse(bytes)
+ case TagUnbindRequest:
+ ret, err = readUnbindRequest(bytes)
+ case TagSearchRequest:
+ ret, err = readSearchRequest(bytes)
+ case TagSearchResultEntry:
+ ret, err = readSearchResultEntry(bytes)
+ case TagSearchResultDone:
+ ret, err = readSearchResultDone(bytes)
+ case TagSearchResultReference:
+ ret, err = readSearchResultReference(bytes)
+ case TagModifyRequest:
+ ret, err = readModifyRequest(bytes)
+ case TagModifyResponse:
+ ret, err = readModifyResponse(bytes)
+ case TagAddRequest:
+ ret, err = readAddRequest(bytes)
+ case TagAddResponse:
+ ret, err = readAddResponse(bytes)
+ case TagDelRequest:
+ ret, err = readDelRequest(bytes)
+ case TagDelResponse:
+ ret, err = readDelResponse(bytes)
+ case TagModifyDNRequest:
+ ret, err = readModifyDNRequest(bytes)
+ case TagModifyDNResponse:
+ ret, err = readModifyDNResponse(bytes)
+ case TagCompareRequest:
+ ret, err = readCompareRequest(bytes)
+ case TagCompareResponse:
+ ret, err = readCompareResponse(bytes)
+ case TagAbandonRequest:
+ ret, err = readAbandonRequest(bytes)
+ case TagExtendedRequest:
+ ret, err = readExtendedRequest(bytes)
+ case TagExtendedResponse:
+ ret, err = readExtendedResponse(bytes)
+ case TagIntermediateResponse:
+ ret, err = readIntermediateResponse(bytes)
+ default:
+ err = LdapError{fmt.Sprintf("readProtocolOp: invalid tag value %d for protocolOp", tagAndLength.Tag)}
+ return
+ }
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readProtocolOp:\n%s", err.Error())}
+ return
+ }
+ return
+}
diff --git a/goldap/read.go b/goldap/read.go
new file mode 100644
index 0000000..4ed9deb
--- /dev/null
+++ b/goldap/read.go
@@ -0,0 +1,18 @@
+package message
+
+import (
+ "fmt"
+)
+
+func ReadLDAPMessage(bytes *Bytes) (message LDAPMessage, err error) {
+ err = bytes.ReadSubBytes(classUniversal, tagSequence, message.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("ReadLDAPMessage:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+//
+// END
+//
diff --git a/goldap/read_error_test.go b/goldap/read_error_test.go
new file mode 100644
index 0000000..d2d3878
--- /dev/null
+++ b/goldap/read_error_test.go
@@ -0,0 +1,3146 @@
+package message
+
+import (
+ "strings"
+ "testing"
+)
+
+type LDAPMessageErrorTestData struct {
+ label string
+ bytes Bytes
+ err string
+}
+
+func TestReadLDAPMessageError(t *testing.T) {
+ for i, test := range getLDAPMessageErrorTestData() {
+ message, err := ReadLDAPMessage(&test.bytes)
+ if err == nil {
+ t.Errorf("#%d: %s\nEXPECTED ERROR MESSAGE:\n%s\nGOT A LDAP STRUCT INSTEAD:\n%#+v", i, test.label, test.err, message)
+ } else if !strings.Contains(err.Error(), test.err) {
+ t.Errorf("#%d: %s\nGOT:\n%s\nEXPECTED:\n%s", i+1, test.label, err.Error(), test.err)
+ }
+ }
+}
+
+func getLDAPMessageErrorTestData() (ret []LDAPMessageErrorTestData) {
+ return []LDAPMessageErrorTestData{
+ // Request 1: client => bind request
+ // Wrong authentication tag
+ {
+ label: "Client => bind request, wrong authentication tag",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x07,
+ // version INTEGER (1 .. 127),
+ 0x02, 0x01, 0x03,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x81, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readBindRequest:
+ReadSubBytes:
+readComponents:
+readAuthenticationChoice: invalid tag value 1 for AuthenticationChoice`,
+ },
+
+ // Request 2: client => bind request
+ // Wrong version (too small)
+ {
+ label: "Client => bind request, wrong version (too small)",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x07,
+ // version INTEGER (1 .. 127),
+ 0x02, 0x01, 0x00,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x81, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readBindRequest:
+ReadSubBytes:
+readComponents: invalid version 0, must be between 1 and 127`,
+ },
+
+ // Request 3: client => bind request
+ // Wrong version (too large)
+ {
+ label: "Client => bind request, wrong wrong version (too large)",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0d,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x08,
+ // version INTEGER (1 .. 127),
+ 0x02, 0x02, 0x00, 0xff,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x81, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readBindRequest:
+ReadSubBytes:
+readComponents: invalid version 255, must be between 1 and 127`,
+ },
+
+ // Request 4: client => bind request
+ // Invalid type for version
+ {
+ label: "Client => bind request, invalid type for version",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0d,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x08,
+ // version INTEGER (1 .. 127),
+ 0x04, 0x02, 0x30, 0x30,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x81, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readBindRequest:
+ReadSubBytes:
+readComponents:
+readINTEGER:
+ReadPrimitiveSubBytes:
+Expect: asn1: syntax error: ExpectTag: wrong tag value: got 4 (OCTET STRING), expected 2 (INTEGER).`,
+ },
+
+ // Request 5: client SearchRequest with FilterExtensibleMatch
+ // Error: invalid tag and length for the extensible filter dnAttribute boolean
+ {
+ label: "Client SearchRequest with FilterExtensibleMatch, invalid tag and length for the extensible filter dnAttribute boolean",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3074020131636f04166f753d636f6e73756d6572732c6f753d73797374656d0a01020a0103020203e8020100010100a936811474656c6570686f6e654e756d6265724d61746368820f74656c6570686f6e654e756d626572830a30313233343536373839
+ // 8401ff300d040b6f626a656374436c617373
+ 0x30, 0x74, 0x02, 0x01, 0x31, 0x63, 0x6f, 0x04, 0x16, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa9, 0x36, 0x81, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x82, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x83, 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ // dnAttributes [4] BOOLEAN DEFAULT FALSE
+ 0x84, 0x40, 0xff, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readSearchRequest:
+ReadSubBytes:
+readComponents:
+readFilter:
+readFilterExtensibleMatch:
+readTaggedMatchingRuleAssertion:
+ReadSubBytes:
+readComponents: readTaggedBOOLEAN:
+ReadPrimitiveSubBytes: data truncated: expecting 64 bytes at offset 53 but only 1 bytes are remaining`,
+ },
+
+ // Request 6: SERVER SearchResultDone with Controls
+ // Error: invalid boolean for the criticality of controls
+ {
+ label: "server SearchResultDone with Controls, invalid boolean 0x0f for the criticality of controls",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303402012465070a010004000400a02630240416312e322e3834302e3131333535362e312e342e3331390101ff040730050201000400
+ 0x30, 0x34, 0x02, 0x01, 0x24, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0xa0, 0x26, 0x30, 0x24, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39,
+ // Bad boolean here: 0x0f is not a 0x00 of 0xFF
+ 0x01, 0x01, 0x0f,
+ 0x04, 0x07, 0x30, 0x05, 0x02, 0x01, 0x00, 0x04, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readTaggedControls:
+ReadSubBytes:
+readComponents:
+readControl:
+ReadSubBytes:
+readComponents:
+readBOOLEAN:
+ReadPrimitiveSubBytes:
+asn1: syntax error: invalid boolean: should be 0x00 of 0xFF`,
+ },
+
+ // An abandon request with invalid negative abandon message ID
+ {
+ label: "client AbandonRequest, invalid negative abandon message ID : 0x9f = -97",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x06,
+ 0x02, 0x01, 0x0a, // messageID
+ 0x50, 0x01, 0x9f, // Abandon request [APPLICATION 16] MessageID = 0x9f = -97 (invalid !)
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readAbandonRequest:
+readTaggedMessageID:
+readTaggedPositiveINTEGER: Invalid INTEGER value -97 ! Expected value between 0 and 2147483647`,
+ },
+
+ // An abandon request with an invalid too large abandon message ID
+ {
+ label: "client AbandonRequest, invalid too large abandon message ID",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x0d,
+ 0x02, 0x01, 0x0a, // messageID
+ 0x50, 0x08, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Abandon request [APPLICATION 16] MessageID = 0x0f ff ff ff ff ff ff ff
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readAbandonRequest:
+readTaggedMessageID:
+readTaggedPositiveINTEGER:
+readTaggedINTEGER:
+ReadPrimitiveSubBytes:
+asn1: structure error: integer too large`,
+ },
+
+ {
+ label: "server SearchResultDone, invalid too large result code",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010b65070a010004000400
+ 0x30, 0x13, 0x02, 0x01, 0x0b, 0x65, 0x0e,
+ 0x0a, 0x08, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readSearchResultDone:
+readTaggedLDAPResult:
+ReadSubBytes:
+readComponents:
+readENUMERATED:
+ReadPrimitiveSubBytes:
+asn1: structure error: integer too large`,
+ },
+
+ {
+ label: "server SearchResultDone, invalid result code",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010b65070a010004000400
+ 0x30, 0x0d, 0x02, 0x01, 0x0b, 0x65, 0x08,
+ 0x0a, 0x02, 0x0f, 0xff,
+ 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readSearchResultDone:
+readTaggedLDAPResult:
+ReadSubBytes:
+readComponents:
+readENUMERATED: Invalid ENUMERATED VALUE 4095`,
+ },
+
+ {
+ label: "client delRequest, invalid length for the protocolOp",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30400201274a3b636e3d4120636f6d706c657820706572736f6e5c2c207665727920636f6d706c657820212c6f753d636f6e73756d6572732c6f753d73797374656d
+ 0x30, 0x40, 0x02, 0x01, 0x27,
+ 0x4a, 0x3c, 0x63, 0x6e, 0x3d, 0x41, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5c, 0x2c, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x21, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+readDelRequest:
+readTaggedLDAPDN:
+readTaggedLDAPString:
+readTaggedOCTETSTRING:
+ReadPrimitiveSubBytes: data truncated: expecting 60 bytes at offset 5 but only 59 bytes are remaining`,
+ },
+
+ {
+ label: "client searchRequest with controls, invalid length for the control value",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819c020124633704096f753d73797374656d0a01020a0103020203e8020100010100870b6f626a656374436c617373300d040b6f626a656374436c617373a05e301e0417312e332e362e312e342e312e343230332e312e31302e3104030101ff30190417322e31362e3834302e312e3131333733302e332e342e3230210416312e322e3834302e3131333535362e312e342e333139040730050201030400
+ 0x30, 0x81, 0x9c, 0x02, 0x01, 0x24, 0x63, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0xa0, 0x5e, 0x30, 0x1e, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x03, 0x01, 0x01, 0xff, 0x30, 0x19, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x30, 0x21, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39,
+ // controlValue: OCTETSTRING
+ 0x04,
+ 0x08, // Wrong length here
+ 0x30, 0x05, 0x02, 0x01, 0x03, 0x04, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readTaggedControls:
+ReadSubBytes:
+readComponents:
+readControl:
+ReadSubBytes:
+readComponents:
+readOCTETSTRING:
+ReadPrimitiveSubBytes: data truncated: expecting 8 bytes at offset 26 but only 7 bytes are remaining`,
+ },
+
+ {
+ label: "client AbandonRequest, invalid type for the MessageID",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x06,
+ 0x04, 0x01, 0x0a, // messageID
+ 0x50, 0x01, 0x05, // Abandon request [APPLICATION 16] MessageID = 0x05
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readTaggedMessageID:
+readTaggedPositiveINTEGER:
+readTaggedINTEGER:
+ReadPrimitiveSubBytes:
+Expect: asn1: syntax error: ExpectTag: wrong tag value: got 4 (OCTET STRING), expected 2 (INTEGER).`,
+ },
+
+ {
+ label: "client searchRequest with controls, invalid length for the controls",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819c020124633704096f753d73797374656d0a01020a0103020203e8020100010100870b6f626a656374436c617373300d040b6f626a656374436c617373a05e301e0417312e332e362e312e342e312e343230332e312e31302e3104030101ff30190417322e31362e3834302e312e3131333733302e332e342e3230210416312e322e3834302e3131333535362e312e342e333139040730050201030400
+ 0x30, 0x81, 0x9c, 0x02, 0x01, 0x24, 0x63, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0xa0, 0x82, 0x00, 0x5e, // invalid length: not in DER format
+ 0x30, 0x1e, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x03, 0x01, 0x01, 0xff, 0x30, 0x19, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x30, 0x21, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x04, 0x07, 0x30, 0x05, 0x02, 0x01, 0x03, 0x04, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+ParseTagAndLength: asn1: structure error: superfluous leading zeros in length`,
+ },
+
+ {
+ label: "client BindRequest, invalid length for the ProtocolOp",
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0e,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x82, 0x00, 0x07, // Invalid length here
+ // version INTEGER (1 .. 127),
+ 0x02, 0x01, 0x03,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x80, 0x00,
+ },
+ },
+ err: `ReadLDAPMessage:
+ReadSubBytes:
+readComponents:
+readProtocolOp:
+ParseTagAndLength: asn1: structure error: superfluous leading zeros in length`,
+ },
+
+ // // Request 2: server => bind response
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010161070a010004000400
+ // 0x30, 0x0c,
+ // 0x02, 0x01, 0x01,
+ // // BindResponse ::= [APPLICATION 1] SEQUENCE {
+ // // COMPONENTS OF LDAPResult,
+ // 0x61, 0x07,
+ // // LDAPResult ::= SEQUENCE {
+ // // resultCode ENUMERATED {
+ // // success (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // matchedDN LDAPDN,
+ // 0x04, 0x00,
+ // // diagnosticMessage LDAPString,
+ // 0x04, 0x00,
+ // // referral [3] Referral OPTIONAL }
+ // // serverSaslCreds [7] OCTET STRING OPTIONAL }
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x01)),
+ // protocolOp: BindResponse{
+ // LDAPResult: LDAPResult{
+ // resultCode: 0,
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // },
+ // },
+ // },
+ // },
+
+ // // Request 3: client => search request
+ // // select "subschemaSubentry" from entries where "objectClass" is present
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3038020102633304000a01000a0103020100020100010100870b6f626a656374436c61737330130411737562736368656d61537562656e747279
+ // 0x30, 0x38,
+ // 0x02, 0x01, 0x02,
+ // // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ // 0x63, 0x33,
+ // // baseObject LDAPDN,
+ // 0x04, 0x00,
+ // // scope ENUMERATED {
+ // // baseObject (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // derefAliases ENUMERATED {
+ // // derefAlways (3) },
+ // 0x0a, 0x01, 0x03,
+ // // sizeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // timeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // typesOnly BOOLEAN,
+ // 0x01, 0x01, 0x00,
+ // // filter Filter,
+ // // Filter ::= CHOICE {
+ // // present [7] AttributeDescription,
+ // // ... }
+ // // AttributeDescription ::= LDAPString
+ // // -- Constrained to <attributedescription>
+ // // -- [RFC4512]
+ // 0x87, 0x0b,
+ // // "objectClass"
+ // 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // // attributes AttributeSelection }
+ // // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // // -- The LDAPString is constrained to
+ // // -- <attributeSelector> in Section 4.5.1.8
+ // 0x30, 0x13,
+ // 0x04, 0x11,
+ // // "subschemaSubentry"
+ // 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x02)),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN(""),
+ // scope: SearchRequestScopeBaseObject,
+ // derefAliases: SearchRequetDerefAliasesDerefAlways,
+ // sizeLimit: 0,
+ // timeLimit: 0,
+ // typesOnly: false,
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection([]LDAPString{"subschemaSubentry"}),
+ // },
+ // },
+ // },
+
+ // // Request 4: server => search result entry
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 302b02010264260400302230200411737562736368656d61537562656e747279310b0409636e3d736368656d61
+ // 0x30, 0x2b,
+ // 0x02, 0x01, 0x02,
+ // // SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+ // 0x64, 0x26,
+ // // objectName LDAPDN,
+ // 0x04, 0x00,
+ // // attributes PartialAttributeList }
+ // // PartialAttributeList ::= SEQUENCE OF
+ // // partialAttribute PartialAttribute
+ // 0x30, 0x22,
+ // // PartialAttribute ::= SEQUENCE {
+ // 0x30, 0x20,
+ // // type AttributeDescription,
+ // 0x04, 0x11,
+ // // "subschemaSubentry"
+ // 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ // // vals SET OF value AttributeValue }
+ // // AttributeValue ::= OCTET STRING
+ // 0x31, 0x0b,
+ // 0x04, 0x09,
+ // // "cn=schema"
+ // 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x02)),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN(""),
+ // attributes: PartialAttributeList(
+ // []PartialAttribute{
+ // PartialAttribute{
+ // type_: AttributeDescription("subschemaSubentry"),
+ // vals: []AttributeValue{AttributeValue("cn=schema")},
+ // },
+ // },
+ // ),
+ // },
+ // },
+ // },
+
+ // // Request 5: server => search result done
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010265070a010004000400
+ // 0x30, 0x0c,
+ // 0x02, 0x01, 0x02,
+ // // SearchResultDone ::= [APPLICATION 5] LDAPResult
+ // // LDAPResult ::= SEQUENCE {
+ // 0x65, 0x07,
+ // // resultCode ENUMERATED {
+ // // success (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // matchedDN LDAPDN,
+ // 0x04, 0x00,
+ // // diagnosticMessage LDAPString,
+ // 0x04, 0x00,
+ // // referral [3] Referral OPTIONAL }
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x02)),
+ // protocolOp: SearchResultDone(LDAPResult{
+ // resultCode: ResultCodeSuccess,
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // }),
+ // },
+ // },
+
+ // // Request 6: client => search request
+ // // select
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 305d02010363580409636e3d736368656d610a01000a0103020100020100010100a318040b6f626a656374436c6173730409737562736368656d613022040f63726561746554696d657374616d70040f6d6f6469667954696d657374616d70
+ // 0x30, 0x5d,
+ // 0x02, 0x01, 0x03,
+ // // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ // 0x63, 0x58,
+ // // baseObject LDAPDN,
+ // // "cn=schema"
+ // 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // // scope ENUMERATED {
+ // // baseObject (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // derefAliases ENUMERATED {
+ // // derefAlways (3) },
+ // 0x0a, 0x01, 0x03,
+ // // sizeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // timeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // typesOnly BOOLEAN,
+ // 0x01, 0x01, 0x00,
+ // // filter Filter,
+ // // Filter ::= CHOICE {
+ // // equalityMatch [3] AttributeValueAssertion,
+ // // AttributeValueAssertion ::= SEQUENCE {
+ // 0xa3, 0x18,
+ // // attributeDesc AttributeDescription,
+ // // "objectClass"
+ // 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // // assertionValue AssertionValue }
+ // // "subschema"
+ // 0x04, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // // attributes AttributeSelection }
+ // // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // // -- The LDAPString is constrained to
+ // // -- <attributeSelector> in Section 4.5.1.8
+ // 0x30, 0x22,
+ // // "createTimestamp"
+ // 0x04, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // // "modifyTimestamp"
+ // 0x04, 0x0f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x03)),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("cn=schema"),
+ // scope: SearchRequestScopeBaseObject,
+ // derefAliases: SearchRequetDerefAliasesDerefAlways,
+ // sizeLimit: 0,
+ // timeLimit: 0,
+ // typesOnly: false,
+ // filter: FilterEqualityMatch(
+ // AttributeValueAssertion{
+ // attributeDesc: AttributeDescription("objectClass"),
+ // assertionValue: AssertionValue("subschema"),
+ // }),
+ // attributes: AttributeSelection([]LDAPString{"createTimestamp", "modifyTimestamp"}),
+ // },
+ // },
+ // },
+
+ // // Request 7: server => search result entry
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 305e02010364590409636e3d736368656d61304c3024040f6d6f6469667954696d657374616d703111040f32303039303831383032323733335a3024040f63726561746554696d657374616d703111040f32303039303831383032323733335a
+ // 0x30, 0x5e,
+ // 0x02, 0x01, 0x03,
+ // // SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+ // 0x64, 0x59,
+ // // objectName LDAPDN,
+ // // "cn=schema"
+ // 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // // attributes PartialAttributeList }
+ // // PartialAttributeList ::= SEQUENCE OF
+ // // partialAttribute PartialAttribute
+ // 0x30, 0x4c,
+ // // PartialAttribute ::= SEQUENCE {
+ // 0x30, 0x24,
+ // // type AttributeDescription,
+ // // "modifyTimestamp"
+ // 0x04, 0x0f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // // vals SET OF value AttributeValue }
+ // 0x31, 0x11,
+ // // "20090818022733Z"
+ // 0x04, 0x0f, 0x32, 0x30, 0x30, 0x39, 0x30, 0x38, 0x31, 0x38, 0x30, 0x32, 0x32, 0x37, 0x33, 0x33, 0x5a,
+ // // PartialAttribute ::= SEQUENCE {
+ // 0x30, 0x24,
+ // // type AttributeDescription,
+ // // "createTimestamp"
+ // 0x04, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // // vals SET OF value AttributeValue }
+ // 0x31, 0x11,
+ // // "20090818022733Z"
+ // 0x04, 0x0f, 0x32, 0x30, 0x30, 0x39, 0x30, 0x38, 0x31, 0x38, 0x30, 0x32, 0x32, 0x37, 0x33, 0x33, 0x5a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x03)),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("cn=schema"),
+ // attributes: PartialAttributeList(
+ // []PartialAttribute{
+ // PartialAttribute{
+ // type_: AttributeDescription("modifyTimestamp"),
+ // vals: []AttributeValue{AttributeValue("20090818022733Z")},
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("createTimestamp"),
+ // vals: []AttributeValue{AttributeValue("20090818022733Z")},
+ // },
+ // },
+ // ),
+ // },
+ // },
+ // },
+
+ // // Request 8
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010365070a010004000400
+ // 0x30, 0x0c,
+ // 0x02, 0x01, 0x03,
+ // // SearchResultDone ::= [APPLICATION 5] LDAPResult
+ // // LDAPResult ::= SEQUENCE {
+ // 0x65, 0x07,
+ // // resultCode ENUMERATED {
+ // // success (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // matchedDN LDAPDN,
+ // 0x04, 0x00,
+ // // diagnosticMessage LDAPString,
+ // 0x04, 0x00,
+ // // referral [3] Referral OPTIONAL }
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x03)),
+ // protocolOp: SearchResultDone(LDAPResult{
+ // resultCode: ResultCodeSuccess,
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // }),
+ // },
+ // },
+
+ // // Request 9: client => search request
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081dd0201046381d704000a01000a0100020100020100010100870b6f626a656374436c6173733081b6040e6e616d696e67436f6e74657874730411737562736368656d61537562656e7472790414737570706f727465644c44415056657273696f6e0417737570706f727465645341534c4d656368616e69736d730412737570706f72746564457874656e73696f6e0410737570706f72746564436f6e74726f6c0411737570706f727465644665617475726573040a76656e646f724e616d65040d76656e646f7256657273696f6e04012b040b6f626a656374436c617373
+ // 0x30, 0x81, 0xdd,
+ // 0x02, 0x01, 0x04,
+ // // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ // 0x63, 0x81, 0xd7,
+ // // baseObject LDAPDN,
+ // 0x04, 0x00,
+ // // scope ENUMERATED {
+ // // baseObject (0),
+ // // ... },
+ // 0x0a, 0x01, 0x00,
+ // // derefAliases ENUMERATED {
+ // // neverDerefAliases (0) },
+ // 0x0a, 0x01, 0x00,
+ // // sizeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // timeLimit INTEGER (0 .. maxInt),
+ // 0x02, 0x01, 0x00,
+ // // typesOnly BOOLEAN,
+ // 0x01, 0x01, 0x00,
+ // // filter Filter,
+ // // Filter ::= CHOICE {
+ // // present [7] AttributeDescription,
+ // // "objetClass"
+ // 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // // attributes AttributeSelection }
+ // // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // // -- The LDAPString is constrained to
+ // // -- <attributeSelector> in Section 4.5.1.8
+ // 0x30, 0x81, 0xb6,
+ // // namingContexts
+ // 0x04, 0x0e, 0x6e, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73,
+ // // subschemaSubentry
+ // 0x04, 0x11, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ // // supportedLDAPVersion
+ // 0x04, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4c, 0x44, 0x41, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ // // supportedSASLMechanisms
+ // 0x04, 0x17, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x41, 0x53, 0x4c, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73,
+ // // supportedExtension
+ // 0x04, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+ // // supportedControl
+ // 0x04, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
+ // // supportedFeatures
+ // 0x04, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
+ // // vendorName
+ // 0x04, 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+ // // vendorVersion
+ // 0x04, 0x0d, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ // // +
+ // 0x04, 0x01, 0x2b,
+ // // objectClass
+ // 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x04)),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN(""),
+ // scope: SearchRequestScopeBaseObject,
+ // derefAliases: SearchRequetDerefAliasesNeverDerefAliases,
+ // sizeLimit: 0,
+ // timeLimit: 0,
+ // typesOnly: false,
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection([]LDAPString{
+ // "namingContexts",
+ // "subschemaSubentry",
+ // "supportedLDAPVersion",
+ // "supportedSASLMechanisms",
+ // "supportedExtension",
+ // "supportedControl",
+ // "supportedFeatures",
+ // "vendorName",
+ // "vendorVersion",
+ // "+",
+ // "objectClass",
+ // }),
+ // },
+ // },
+ // },
+
+ // // Request 10
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308203850201046482037e040030820378302a040a76656e646f724e616d65311c041a41706163686520536f66747761726520466f756e646174696f6e301c040d76656e646f7256657273696f6e310b0409322e302e302d4d31343026040b6f626a656374436c61737331170403746f700410657874656e7369626c654f626a65637430200411737562736368656d61537562656e747279310b0409636e3d736368656d61301b0414737570706f727465644c44415056657273696f6e31030401333082012e0410737570706f72746564436f6e74726f6c318201180417322e31362e3834302e312e3131333733302e332e342e330417312e332e362e312e342e312e343230332e312e31302e310417322e31362e3834302e312e3131333733302e332e342e320418312e332e362e312e342e312e343230332e312e392e312e340419312e332e362e312e342e312e34322e322e32372e382e352e310418312e332e362e312e342e312e343230332e312e392e312e310418312e332e362e312e342e312e343230332e312e392e312e330418312e332e362e312e342e312e343230332e312e392e312e320417312e332e362e312e342e312e31383036302e302e302e310417322e31362e3834302e312e3131333733302e332e342e370416312e322e3834302e3131333535362e312e342e3331393081910412737570706f72746564457874656e73696f6e317b0416312e332e362e312e342e312e313436362e32303033360416312e332e362e312e342e312e313436362e32303033370417312e332e362e312e342e312e31383036302e302e312e350417312e332e362e312e342e312e31383036302e302e312e330417312e332e362e312e342e312e343230332e312e31312e3130530417737570706f727465645341534c4d656368616e69736d73313804044e544c4d0406475353415049040a4753532d53504e45474f04084352414d2d4d4435040653494d504c45040a4449474553542d4d443530330409656e747279555549443126042466323930343235632d383237322d346536322d386136372d3932623036663338646266353046040e6e616d696e67436f6e7465787473313404096f753d73797374656d041164633d6578616d706c652c64633d636f6d04096f753d736368656d6104096f753d636f6e666967302d0411737570706f72746564466561747572657331180416312e332e362e312e342e312e343230332e312e352e31
+ // 0x30, 0x82, 0x03, 0x85, 0x02, 0x01, 0x04, 0x64, 0x82, 0x03, 0x7e, 0x04, 0x00, 0x30, 0x82, 0x03, 0x78, 0x30, 0x2a, 0x04, 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x31, 0x1c, 0x04, 0x1a, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x1c, 0x04, 0x0d, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x0b, 0x04, 0x09, 0x32, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x4d, 0x31, 0x34, 0x30, 0x26, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x17, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x30, 0x20, 0x04, 0x11, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x31, 0x0b, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x1b, 0x04, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4c, 0x44, 0x41, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x03, 0x04, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2e, 0x04, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x31, 0x82, 0x01, 0x18, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x33, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x34, 0x04, 0x19, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x2e, 0x32, 0x2e, 0x32, 0x37, 0x2e, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x31, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x33, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x32, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x37, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x30, 0x81, 0x91, 0x04, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x7b, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x36, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x35, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x33, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x31, 0x30, 0x53, 0x04, 0x17, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x41, 0x53, 0x4c, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x31, 0x38, 0x04, 0x04, 0x4e, 0x54, 0x4c, 0x4d, 0x04, 0x06, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x04, 0x0a, 0x47, 0x53, 0x53, 0x2d, 0x53, 0x50, 0x4e, 0x45, 0x47, 0x4f, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35, 0x04, 0x06, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x04, 0x0a, 0x44, 0x49, 0x47, 0x45, 0x53, 0x54, 0x2d, 0x4d, 0x44, 0x35, 0x30, 0x33, 0x04, 0x09, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x55, 0x49, 0x44, 0x31, 0x26, 0x04, 0x24, 0x66, 0x32, 0x39, 0x30, 0x34, 0x32, 0x35, 0x63, 0x2d, 0x38, 0x32, 0x37, 0x32, 0x2d, 0x34, 0x65, 0x36, 0x32, 0x2d, 0x38, 0x61, 0x36, 0x37, 0x2d, 0x39, 0x32, 0x62, 0x30, 0x36, 0x66, 0x33, 0x38, 0x64, 0x62, 0x66, 0x35, 0x30, 0x46, 0x04, 0x0e, 0x6e, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x31, 0x34, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2d, 0x04, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x31, 0x18, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x35, 0x2e, 0x31,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(4),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN(""),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("vendorName"),
+ // vals: []AttributeValue{
+ // AttributeValue("Apache Software Foundation"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("vendorVersion"),
+ // vals: []AttributeValue{
+ // AttributeValue("2.0.0-M14"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("objectClass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("extensibleObject"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("subschemaSubentry"),
+ // vals: []AttributeValue{
+ // AttributeValue("cn=schema"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("supportedLDAPVersion"),
+ // vals: []AttributeValue{
+ // AttributeValue("3"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("supportedControl"),
+ // vals: []AttributeValue{
+ // AttributeValue("2.16.840.1.113730.3.4.3"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.10.1"),
+ // AttributeValue("2.16.840.1.113730.3.4.2"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.9.1.4"),
+ // AttributeValue("1.3.6.1.4.1.42.2.27.8.5.1"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.9.1.1"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.9.1.3"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.9.1.2"),
+ // AttributeValue("1.3.6.1.4.1.18060.0.0.1"),
+ // AttributeValue("2.16.840.1.113730.3.4.7"),
+ // AttributeValue("1.2.840.113556.1.4.319"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("supportedExtension"),
+ // vals: []AttributeValue{
+ // AttributeValue("1.3.6.1.4.1.1466.20036"),
+ // AttributeValue("1.3.6.1.4.1.1466.20037"),
+ // AttributeValue("1.3.6.1.4.1.18060.0.1.5"),
+ // AttributeValue("1.3.6.1.4.1.18060.0.1.3"),
+ // AttributeValue("1.3.6.1.4.1.4203.1.11.1"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("supportedSASLMechanisms"),
+ // vals: []AttributeValue{
+ // AttributeValue("NTLM"),
+ // AttributeValue("GSSAPI"),
+ // AttributeValue("GSS-SPNEGO"),
+ // AttributeValue("CRAM-MD5"),
+ // AttributeValue("SIMPLE"),
+ // AttributeValue("DIGEST-MD5"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("entryUUID"),
+ // vals: []AttributeValue{
+ // AttributeValue("f290425c-8272-4e62-8a67-92b06f38dbf5"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("namingContexts"),
+ // vals: []AttributeValue{
+ // AttributeValue("ou=system"),
+ // AttributeValue("dc=example,dc=com"),
+ // AttributeValue("ou=schema"),
+ // AttributeValue("ou=config"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("supportedFeatures"),
+ // vals: []AttributeValue{
+ // AttributeValue("1.3.6.1.4.1.4203.1.5.1"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 11
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010465070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x04, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(4),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 12
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3028020105632304000a01000a0100020100020100010100870b6f626a656374436c617373300304012a
+ // 0x30, 0x28, 0x02, 0x01, 0x05, 0x63, 0x23, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(5),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN(""),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(0),
+ // sizeLimit: INTEGER(0),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("*"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 13
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3031020105642c040030283026040b6f626a656374436c61737331170403746f700410657874656e7369626c654f626a656374
+ // 0x30, 0x31, 0x02, 0x01, 0x05, 0x64, 0x2c, 0x04, 0x00, 0x30, 0x28, 0x30, 0x26, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x17, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(5),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN(""),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectClass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("extensibleObject"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 14
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010565070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x05, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(5),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 15
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304c020106634704096f753d736368656d610a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x4c, 0x02, 0x01, 0x06, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(6),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=schema"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 16
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303c020106643704096f753d736368656d61302a3028040b6f626a656374636c617373311904126f7267616e697a6174696f6e616c556e69740403746f70
+ // 0x30, 0x3c, 0x02, 0x01, 0x06, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(6),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=schema"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("organizationalUnit"),
+ // AttributeValue("top"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 17
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010665070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x06, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(6),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 18
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304c020107634704096f753d636f6e6669670a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x4c, 0x02, 0x01, 0x07, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(7),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=config"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 19
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303c020107643704096f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x3c, 0x02, 0x01, 0x07, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(7),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 20
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010765070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x07, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(7),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 21
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304c020108634704096f753d73797374656d0a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x4c, 0x02, 0x01, 0x08, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(8),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=system"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 22
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303c020108643704096f753d73797374656d302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x3c, 0x02, 0x01, 0x08, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(8),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=system"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 23
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010865070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x08, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(8),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 24
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304c02010963470409636e3d736368656d610a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x4c, 0x02, 0x01, 0x09, 0x63, 0x47, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(9),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("cn=schema"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 25
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304e02010964490409636e3d736368656d61303c303a040b6f626a656374436c617373312b0403746f700409737562736368656d610408737562656e747279040f617061636865537562736368656d61
+ // 0x30, 0x4e, 0x02, 0x01, 0x09, 0x64, 0x49, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x3c, 0x30, 0x3a, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x2b, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x04, 0x08, 0x73, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x04, 0x0f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(9),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("cn=schema"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectClass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("subschema"),
+ // AttributeValue("subentry"),
+ // AttributeValue("apacheSubschema"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 26
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010965070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x09, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(9),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 27
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 305402010a634f041164633d6578616d706c652c64633d636f6d0a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x54, 0x02, 0x01, 0x0a, 0x63, 0x4f, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(10),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("dc=example,dc=com"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 28
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303802010a6433041164633d6578616d706c652c64633d636f6d301e301c040b6f626a656374636c617373310d0406646f6d61696e0403746f70
+ // 0x30, 0x38, 0x02, 0x01, 0x0a, 0x64, 0x33, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(10),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("dc=example,dc=com"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("domain"),
+ // AttributeValue("top"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 29
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010a65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0a, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(10),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 30
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304d02010b634804096f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x4d, 0x02, 0x01, 0x0b, 0x63, 0x48, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(11),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=config"),
+ // scope: ENUMERATED(1),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 31
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306702010b646204286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730363034040b6f626a656374636c61737331250403746f7004146164732d6469726563746f72795365727669636504086164732d62617365
+ // 0x30, 0x67, 0x02, 0x01, 0x0b, 0x64, 0x62, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x36, 0x30, 0x34, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x25, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(11),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("ads-directoryService"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 32
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010b65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0b, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(11),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 33
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303102010c632c04096f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ // 0x30, 0x31, 0x02, 0x01, 0x0c, 0x63, 0x2c, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(12),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=config"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(0),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("*"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 34
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 304c02010c644704096f753d636f6e666967303a300e04026f7531080406636f6e6669673028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x4c, 0x02, 0x01, 0x0c, 0x64, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x3a, 0x30, 0x0e, 0x04, 0x02, 0x6f, 0x75, 0x31, 0x08, 0x04, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(12),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("ou"),
+ // vals: []AttributeValue{
+ // AttributeValue("config"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 35
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010c65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0c, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(12),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 36
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306c02010d636704286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x6c, 0x02, 0x01, 0x0d, 0x63, 0x67, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(1),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 37
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 307b02010d647604456164732d6a6f75726e616c49643d64656661756c744a6f75726e616c2c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302d302b040b6f626a656374636c617373311c0403746f70040b6164732d6a6f75726e616c04086164732d62617365
+ // 0x30, 0x7b, 0x02, 0x01, 0x0d, 0x64, 0x76, 0x04, 0x45, 0x61, 0x64, 0x73, 0x2d, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2d, 0x30, 0x2b, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x1c, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-journalId=defaultJournal,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("ads-journal"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 38
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306b02010d646604386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x6b, 0x02, 0x01, 0x0d, 0x64, 0x66, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 39
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306902010d646404366f753d706172746974696f6e732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x69, 0x02, 0x01, 0x0d, 0x64, 0x64, 0x04, 0x36, 0x6f, 0x75, 0x3d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=partitions,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 40
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30818102010d647c04496164732d6368616e67654c6f6749643d64656661756c744368616e67654c6f672c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302f302d040b6f626a656374636c617373311e0403746f7004086164732d62617365040d6164732d6368616e67654c6f67
+ // 0x30, 0x81, 0x81, 0x02, 0x01, 0x0d, 0x64, 0x7c, 0x04, 0x49, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2f, 0x30, 0x2d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x1e, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x04, 0x0d, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-changeLogId=defaultChangeLog,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // AttributeValue("ads-changeLog"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 41
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306602010d646104336f753d736572766572732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x66, 0x02, 0x01, 0x0d, 0x64, 0x61, 0x04, 0x33, 0x6f, 0x75, 0x3d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=servers,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 42
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010d65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0d, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 43
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 305002010e634b04286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ // 0x30, 0x50, 0x02, 0x01, 0x0e, 0x63, 0x4b, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(14),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(0),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("*"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 44
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3082017c02010e6482017504286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730820147302304166164732d6469726563746f72797365727669636569643109040764656661756c74302104166164732d647373796e63706572696f646d696c6c69733107040531353030303024041a6164732d6473616c6c6f77616e6f6e796d6f757361636365737331060404545255453016040f6164732d64737265706c696361696431030401313025041a6164732d6473616363657373636f6e74726f6c656e61626c65643107040546414c5345301f04146164732d647370617373776f726468696464656e3107040546414c5345302a041f6164732d647364656e6f726d616c697a656f706174747273656e61626c65643107040546414c53453015040b6164732d656e61626c656431060404545255453034040b6f626a656374636c61737331250403746f7004146164732d6469726563746f72795365727669636504086164732d62617365
+ // 0x30, 0x82, 0x01, 0x7c, 0x02, 0x01, 0x0e, 0x64, 0x82, 0x01, 0x75, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x82, 0x01, 0x47, 0x30, 0x23, 0x04, 0x16, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x69, 0x64, 0x31, 0x09, 0x04, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x30, 0x21, 0x04, 0x16, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x73, 0x79, 0x6e, 0x63, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x31, 0x07, 0x04, 0x05, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x24, 0x04, 0x1a, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x16, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x69, 0x64, 0x31, 0x03, 0x04, 0x01, 0x31, 0x30, 0x25, 0x04, 0x1a, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x1f, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x2a, 0x04, 0x1f, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x6f, 0x70, 0x61, 0x74, 0x74, 0x72, 0x73, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x15, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x34, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x25, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(14),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-directoryserviceid"),
+ // vals: []AttributeValue{
+ // AttributeValue("default"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dssyncperiodmillis"),
+ // vals: []AttributeValue{
+ // AttributeValue("15000"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dsallowanonymousaccess"),
+ // vals: []AttributeValue{
+ // AttributeValue("TRUE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dsreplicaid"),
+ // vals: []AttributeValue{
+ // AttributeValue("1"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dsaccesscontrolenabled"),
+ // vals: []AttributeValue{
+ // AttributeValue("FALSE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dspasswordhidden"),
+ // vals: []AttributeValue{
+ // AttributeValue("FALSE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-dsdenormalizeopattrsenabled"),
+ // vals: []AttributeValue{
+ // AttributeValue("FALSE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-enabled"),
+ // vals: []AttributeValue{
+ // AttributeValue("TRUE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("ads-directoryService"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 45
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010e65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0e, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(14),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 46
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 306002010f635b04386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ // 0x30, 0x60, 0x02, 0x01, 0x0f, 0x63, 0x5b, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(15),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(0),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("*"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 47
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30818102010f647c04386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673040301404026f75310e040c696e746572636570746f72733028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ // 0x30, 0x81, 0x81, 0x02, 0x01, 0x0f, 0x64, 0x7c, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x40, 0x30, 0x14, 0x04, 0x02, 0x6f, 0x75, 0x31, 0x0e, 0x04, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(15),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("ou"),
+ // vals: []AttributeValue{
+ // AttributeValue("interceptors"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("organizationalUnit"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 48
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02010f65070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x0f, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(15),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 49
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 307c020110637704386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x7c, 0x02, 0x01, 0x10, 0x63, 0x77, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(1),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 50
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30819a020110648194045f6164732d696e746572636570746f7249643d657863657074696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x9a, 0x02, 0x01, 0x10, 0x64, 0x81, 0x94, 0x04, 0x5f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=exceptionInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 51
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308196020110648190045b6164732d696e746572636570746f7249643d6576656e74496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x96, 0x02, 0x01, 0x10, 0x64, 0x81, 0x90, 0x04, 0x5b, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=eventInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 52
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a502011064819f046a6164732d696e746572636570746f7249643d6f7065726174696f6e616c417474726962757465496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa5, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9f, 0x04, 0x6a, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=operationalAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 53
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081be0201106481b804646164732d696e746572636570746f7249643d61757468656e7469636174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673050304e040b6f626a656374636c617373313f040f6164732d696e746572636570746f720403746f7004086164732d62617365041d6164732d61757468656e7469636174696f6e496e746572636570746f72
+ // 0x30, 0x81, 0xbe, 0x02, 0x01, 0x10, 0x64, 0x81, 0xb8, 0x04, 0x64, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x50, 0x30, 0x4e, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x3f, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x04, 0x1d, 0x61, 0x64, 0x73, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // AttributeValue("ads-authenticationInterceptor"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 54
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a202011064819c04676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa2, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9c, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 55
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a002011064819a04656164732d696e746572636570746f7249643d70617373776f726448617368696e67496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa0, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9a, 0x04, 0x65, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=passwordHashingInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 56
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308197020110648191045c6164732d696e746572636570746f7249643d736368656d61496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x97, 0x02, 0x01, 0x10, 0x64, 0x81, 0x91, 0x04, 0x5c, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=schemaInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 57
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a402011064819e04696164732d696e746572636570746f7249643d61646d696e697374726174697665506f696e74496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa4, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9e, 0x04, 0x69, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=administrativePointInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 58
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308199020110648193045e6164732d696e746572636570746f7249643d726566657272616c496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x99, 0x02, 0x01, 0x10, 0x64, 0x81, 0x93, 0x04, 0x5e, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=referralInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 59
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30819e02011064819804636164732d696e746572636570746f7249643d6b657944657269766174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x9e, 0x02, 0x01, 0x10, 0x64, 0x81, 0x98, 0x04, 0x63, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=keyDerivationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 60
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30819e02011064819804636164732d696e746572636570746f7249643d6e6f726d616c697a6174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x9e, 0x02, 0x01, 0x10, 0x64, 0x81, 0x98, 0x04, 0x63, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=normalizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 61
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308199020110648193045e6164732d696e746572636570746f7249643d737562656e747279496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x99, 0x02, 0x01, 0x10, 0x64, 0x81, 0x93, 0x04, 0x5e, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x73, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=subentryInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 62
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a502011064819f046a6164732d696e746572636570746f7249643d64656661756c74417574686f72697a6174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa5, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9f, 0x04, 0x6a, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=defaultAuthorizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 63
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 308198020110648192045d6164732d696e746572636570746f7249643d74726967676572496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0x98, 0x02, 0x01, 0x10, 0x64, 0x81, 0x92, 0x04, 0x5d, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=triggerInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 64
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081a402011064819e04696164732d696e746572636570746f7249643d636f6c6c656374697665417474726962757465496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ // 0x30, 0x81, 0xa4, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9e, 0x04, 0x69, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=collectiveAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 65
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011065070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x10, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(16),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 66
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30819002011163818a04676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ // 0x30, 0x81, 0x90, 0x02, 0x01, 0x11, 0x63, 0x81, 0x8a, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(17),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(0),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(0),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("*"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 67
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3082018d0201116482018604676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730820119302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d626173653015040b6164732d656e61626c65643106040454525545306004186164732d696e746572636570746f72636c6173736e616d65314404426f72672e6170616368652e6469726563746f72792e7365727665722e636f72652e617574687a2e416369417574686f72697a6174696f6e496e746572636570746f72301b04146164732d696e746572636570746f726f726465723103040134305004116164732d696e746572636570746f726964313b041b616369417574686f72697a6174696f6e496e746572636570746f72041c616369417574686f72697a6174696f6e496e746572636570746f7232
+ // 0x30, 0x82, 0x01, 0x8d, 0x02, 0x01, 0x11, 0x64, 0x82, 0x01, 0x86, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x82, 0x01, 0x19, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x30, 0x15, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x60, 0x04, 0x18, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x44, 0x04, 0x42, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x2e, 0x41, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x30, 0x1b, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x31, 0x03, 0x04, 0x01, 0x34, 0x30, 0x50, 0x04, 0x11, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x69, 0x64, 0x31, 0x3b, 0x04, 0x1b, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x1c, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(17),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectclass"),
+ // vals: []AttributeValue{
+ // AttributeValue("ads-interceptor"),
+ // AttributeValue("top"),
+ // AttributeValue("ads-base"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-enabled"),
+ // vals: []AttributeValue{
+ // AttributeValue("TRUE"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-interceptorclassname"),
+ // vals: []AttributeValue{
+ // AttributeValue("org.apache.directory.server.core.authz.AciAuthorizationInterceptor"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-interceptororder"),
+ // vals: []AttributeValue{
+ // AttributeValue("4"),
+ // },
+ // },
+ // PartialAttribute{
+ // type_: AttributeDescription("ads-interceptorid"),
+ // vals: []AttributeValue{
+ // AttributeValue("aciAuthorizationInterceptor"),
+ // AttributeValue("aciAuthorizationInterceptor2"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 68
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011165070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x11, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(17),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 69
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081ac0201126381a604676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ // 0x30, 0x81, 0xac, 0x02, 0x01, 0x12, 0x63, 0x81, 0xa6, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(18),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ // scope: ENUMERATED(1),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("hasSubordinates"),
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 70
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011265070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x12, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(18),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 71
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30050201134200
+ // 0x30, 0x05, 0x02, 0x01, 0x13, 0x42, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(19),
+ // protocolOp: UnbindRequest{},
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 72: CLIENT AddRequest
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3081b60201156881b0044a636e3d723030582b636f6d6d6f6e4e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d3062301c040b6465736372697074696f6e310d040b4120746573742075736572300c0402736e310604047230307830160402636e311004047230305804085468652072303058301c040b6f626a656374436c617373310d0406706572736f6e0403746f70
+ // 0x30, 0x81, 0xb6, 0x02, 0x01, 0x15, 0x68, 0x81, 0xb0, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x62, 0x30, 0x1c, 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x04, 0x0b, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x30, 0x0c, 0x04, 0x02, 0x73, 0x6e, 0x31, 0x06, 0x04, 0x04, 0x72, 0x30, 0x30, 0x78, 0x30, 0x16, 0x04, 0x02, 0x63, 0x6e, 0x31, 0x10, 0x04, 0x04, 0x72, 0x30, 0x30, 0x58, 0x04, 0x08, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x06, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(21),
+ // protocolOp: AddRequest{
+ // entry: LDAPDN("cn=r00X+commonName=The r00X+description=A test user,ou=consumers,ou=system"),
+ // attributes: AttributeList{
+ // Attribute{
+ // type_: AttributeDescription("description"),
+ // vals: []AttributeValue{
+ // AttributeValue("A test user"),
+ // },
+ // },
+ // Attribute{
+ // type_: AttributeDescription("sn"),
+ // vals: []AttributeValue{
+ // AttributeValue("r00x"),
+ // },
+ // },
+ // Attribute{
+ // type_: AttributeDescription("cn"),
+ // vals: []AttributeValue{
+ // AttributeValue("r00X"),
+ // AttributeValue("The r00X"),
+ // },
+ // },
+ // Attribute{
+ // type_: AttributeDescription("objectClass"),
+ // vals: []AttributeValue{
+ // AttributeValue("person"),
+ // AttributeValue("top"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 73: SERVER AddResponse
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011569070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x15, 0x69, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(21),
+ // protocolOp: AddResponse{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 74: CLIENT ModifyRequest
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30790201196674044a636e3d723030582b636f6d6d6f6e6e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d302630240a0100301f040f74656c6570686f6e654e756d626572310c040a30313233343536373839
+ // 0x30, 0x79, 0x02, 0x01, 0x19, 0x66, 0x74, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x26, 0x30, 0x24, 0x0a, 0x01, 0x00, 0x30, 0x1f, 0x04, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x31, 0x0c, 0x04, 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(25),
+ // protocolOp: ModifyRequest{
+ // object: LDAPDN("cn=r00X+commonname=The r00X+description=A test user,ou=consumers,ou=system"),
+ // changes: []ModifyRequestChange{
+ // ModifyRequestChange{
+ // operation: ENUMERATED(0),
+ // modification: PartialAttribute{
+ // type_: AttributeDescription("telephoneNumber"),
+ // vals: []AttributeValue{
+ // AttributeValue("0123456789"),
+ // },
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 75: SERVER ModifyResponse
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011967070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x19, 0x67, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(25),
+ // protocolOp: ModifyResponse{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 76: CLIENT ModifyDNrequest
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 307502011b6c70044a636e3d723030582b636f6d6d6f6e6e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d0407636e3d723030580101ff80166f753d636f6e73756d6572732c6f753d73797374656d
+ // 0x30, 0x75, 0x02, 0x01, 0x1b, 0x6c, 0x70, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x04, 0x07, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x01, 0x01, 0xff, 0x80, 0x16, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(27),
+ // protocolOp: ModifyDNRequest{
+ // entry: LDAPDN("cn=r00X+commonname=The r00X+description=A test user,ou=consumers,ou=system"),
+ // newrdn: RelativeLDAPDN("cn=r00X"),
+ // deleteoldrdn: BOOLEAN(true),
+ // newSuperior: LDAPDN("ou=consumers,ou=system").Pointer(),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 77: SERVER ModifyDNResponse
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02011b6d070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x1b, 0x6d, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(27),
+ // protocolOp: ModifyDNResponse{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 78: CLIENT
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 303b020121633604096f753d73797374656d0a01020a0103020203e8020100010100a30a0402636e040472303058300d040b6f626a656374436c617373
+ // 0x30, 0x3b, 0x02, 0x01, 0x21, 0x63, 0x36, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa3, 0x0a, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x04, 0x72, 0x30, 0x30, 0x58, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(33),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=system"),
+ // scope: ENUMERATED(2),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterEqualityMatch{
+ // attributeDesc: AttributeDescription("cn"),
+ // assertionValue: AssertionValue("r00X"),
+ // },
+ // attributes: AttributeSelection{
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 79: SERVER
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30450201216440041e636e3d723030582c6f753d636f6e73756d6572732c6f753d73797374656d301e301c040b6f626a656374436c617373310d0403746f700406706572736f6e
+ // 0x30, 0x45, 0x02, 0x01, 0x21, 0x64, 0x40, 0x04, 0x1e, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x1e, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x06, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(33),
+ // protocolOp: SearchResultEntry{
+ // objectName: LDAPDN("cn=r00X,ou=consumers,ou=system"),
+ // attributes: PartialAttributeList{
+ // PartialAttribute{
+ // type_: AttributeDescription("objectClass"),
+ // vals: []AttributeValue{
+ // AttributeValue("top"),
+ // AttributeValue("person"),
+ // },
+ // },
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 80: SERVER
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c02012165070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x21, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(33),
+ // protocolOp: SearchResultDone{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 81: CLIENT SearchRequest with controls
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30819c020124633704096f753d73797374656d0a01020a0103020203e8020100010100870b6f626a656374436c617373300d040b6f626a656374436c617373a05e301e0417312e332e362e312e342e312e343230332e312e31302e3104030101ff30190417322e31362e3834302e312e3131333733302e332e342e3230210416312e322e3834302e3131333535362e312e342e333139040730050201030400
+ // 0x30, 0x81, 0x9c, 0x02, 0x01, 0x24, 0x63, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0xa0, 0x5e, 0x30, 0x1e, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x03, 0x01, 0x01, 0xff, 0x30, 0x19, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x30, 0x21, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x04, 0x07, 0x30, 0x05, 0x02, 0x01, 0x03, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(36),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=system"),
+ // scope: ENUMERATED(2),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterPresent("objectClass"),
+ // attributes: AttributeSelection{
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: &Controls{
+ // Control{
+ // controlType: LDAPOID("1.3.6.1.4.1.4203.1.10.1"),
+ // criticality: BOOLEAN(false),
+ // controlValue: OCTETSTRING("\x01\x01\xff").Pointer(),
+ // },
+ // Control{
+ // controlType: LDAPOID("2.16.840.1.113730.3.4.2"),
+ // criticality: BOOLEAN(false),
+ // controlValue: (*OCTETSTRING)(nil),
+ // },
+ // Control{
+ // controlType: LDAPOID("1.2.840.113556.1.4.319"),
+ // criticality: BOOLEAN(false),
+ // controlValue: OCTETSTRING("0\x05\x02\x01\x03\x04\x00").Pointer(),
+ // },
+ // },
+ // },
+ // },
+
+ // // (|
+ // // (&
+ // // (cn=r00x)
+ // // (telephoneNumber=*)
+ // // )
+ // // (cn~=The)
+ // // (&
+ // // (!(description=Toto))
+ // // (ou=co*f*g*r*on)
+ // // )
+ // // )
+ // // Request 83: CLIENT
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30818e02010d63818804096f753d73797374656d0a01020a0103020203e8020100010100a15ca01da30a0402636e040472303078870f74656c6570686f6e654e756d626572a8090402636e0403546865a030a215a313040b6465736372697074696f6e0404546f746fa41704026f7530118002636f81016681016781017282026f6e300d040b6f626a656374436c617373
+ // 0x30, 0x81, 0x8e, 0x02, 0x01, 0x0d, 0x63, 0x81, 0x88, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa1, 0x5c, 0xa0, 0x1d, 0xa3, 0x0a, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x04, 0x72, 0x30, 0x30, 0x78, 0x87, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xa8, 0x09, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x03, 0x54, 0x68, 0x65, 0xa0, 0x30, 0xa2, 0x15, 0xa3, 0x13, 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x04, 0x04, 0x54, 0x6f, 0x74, 0x6f, 0xa4, 0x17, 0x04, 0x02, 0x6f, 0x75, 0x30, 0x11, 0x80, 0x02, 0x63, 0x6f, 0x81, 0x01, 0x66, 0x81, 0x01, 0x67, 0x81, 0x01, 0x72, 0x82, 0x02, 0x6f, 0x6e, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(13),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=system"),
+ // scope: ENUMERATED(2),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterOr{
+ // FilterAnd{
+ // FilterEqualityMatch{
+ // attributeDesc: AttributeDescription("cn"),
+ // assertionValue: AssertionValue("r00x"),
+ // },
+ // FilterPresent("telephoneNumber"),
+ // },
+ // FilterApproxMatch{
+ // attributeDesc: AttributeDescription("cn"),
+ // assertionValue: AssertionValue("The"),
+ // },
+ // FilterAnd{
+ // FilterNot{
+ // Filter: FilterEqualityMatch{
+ // attributeDesc: AttributeDescription("description"),
+ // assertionValue: AssertionValue("Toto"),
+ // },
+ // },
+ // FilterSubstrings{
+ // type_: AttributeDescription("ou"),
+ // substrings: []Substring{
+ // SubstringInitial("co"),
+ // SubstringAny("f"),
+ // SubstringAny("g"),
+ // SubstringAny("r"),
+ // SubstringFinal("on"),
+ // },
+ // },
+ // },
+ // },
+ // attributes: AttributeSelection{
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 84: CLIENT SearchRequest with FilterGreaterOrEqual and FilterLessOrEqual
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3072020119636d04000a01020a0103020203e8020100010100a04aa523041e6164732d636867507764506f6c69637950617373776f72644c656e677468040133a623041e6164732d636867507764506f6c69637950617373776f72644c656e677468040135300d040b6f626a656374436c617373
+ // 0x30, 0x72, 0x02, 0x01, 0x19, 0x63, 0x6d, 0x04, 0x00, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x4a, 0xa5, 0x23, 0x04, 0x1e, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x67, 0x50, 0x77, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x04, 0x01, 0x33, 0xa6, 0x23, 0x04, 0x1e, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x67, 0x50, 0x77, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x04, 0x01, 0x35, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(25),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN(""),
+ // scope: ENUMERATED(2),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterAnd{
+ // FilterGreaterOrEqual{
+ // attributeDesc: AttributeDescription("ads-chgPwdPolicyPasswordLength"),
+ // assertionValue: AssertionValue("3"),
+ // },
+ // FilterLessOrEqual{
+ // attributeDesc: AttributeDescription("ads-chgPwdPolicyPasswordLength"),
+ // assertionValue: AssertionValue("5"),
+ // },
+ // },
+ // attributes: AttributeSelection{
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 85: CLIENT SearchRequest with FilterExtensibleMatch
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 3074020131636f04166f753d636f6e73756d6572732c6f753d73797374656d0a01020a0103020203e8020100010100a936811474656c6570686f6e654e756d6265724d61746368820f74656c6570686f6e654e756d626572830a303132333435363738398401ff300d040b6f626a656374436c617373
+ // 0x30, 0x74, 0x02, 0x01, 0x31, 0x63, 0x6f, 0x04, 0x16, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa9, 0x36, 0x81, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x82, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x83, 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x84, 0x01, 0xff, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(49),
+ // protocolOp: SearchRequest{
+ // baseObject: LDAPDN("ou=consumers,ou=system"),
+ // scope: ENUMERATED(2),
+ // derefAliases: ENUMERATED(3),
+ // sizeLimit: INTEGER(1000),
+ // timeLimit: INTEGER(0),
+ // typesOnly: BOOLEAN(false),
+ // filter: FilterExtensibleMatch{
+ // matchingRule: MatchingRuleId("telephoneNumberMatch").Pointer(),
+ // type_: AttributeDescription("telephoneNumber").Pointer(),
+ // matchValue: AssertionValue("0123456789"),
+ // dnAttributes: BOOLEAN(true),
+ // },
+ // attributes: AttributeSelection{
+ // LDAPString("objectClass"),
+ // },
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 86: CLIENT
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 30400201274a3b636e3d4120636f6d706c657820706572736f6e5c2c207665727920636f6d706c657820212c6f753d636f6e73756d6572732c6f753d73797374656d
+ // 0x30, 0x40, 0x02, 0x01, 0x27, 0x4a, 0x3b, 0x63, 0x6e, 0x3d, 0x41, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5c, 0x2c, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x21, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(39),
+ // protocolOp: DelRequest("cn=A complex person\\, very complex !,ou=consumers,ou=system"),
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 87: SERVER
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 300c0201276b070a010004000400
+ // 0x30, 0x0c, 0x02, 0x01, 0x27, 0x6b, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(39),
+ // protocolOp: DelResponse{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 88: CLIENT ExtendedRequest: Start TLS (OID 1.3.6.1.4.1.1466.20037)
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 301d02010177188016312e332e362e312e342e312e313436362e3230303337
+ // 0x30, 0x1d, 0x02, 0x01, 0x01, 0x77, 0x18, 0x80, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(1),
+ // protocolOp: ExtendedRequest{
+ // requestName: LDAPOID("1.3.6.1.4.1.1466.20037"),
+ // requestValue: (*OCTETSTRING)(nil),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // Request 89: SERVER ExtendedResponse: Start TLS (OID 1.3.6.1.4.1.1466.20037)
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // // 302602010178210a0100040004008a16312e332e362e312e342e312e313436362e32303033378b00
+ // 0x30, 0x26, 0x02, 0x01, 0x01, 0x78, 0x21, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0x8a, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37, 0x8b, 0x00,
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(1),
+ // protocolOp: ExtendedResponse{
+ // LDAPResult: LDAPResult{
+ // resultCode: ENUMERATED(0),
+ // matchedDN: LDAPDN(""),
+ // diagnosticMessage: LDAPString(""),
+ // referral: (*Referral)(nil),
+ // },
+ // responseName: LDAPOID("1.3.6.1.4.1.1466.20037").Pointer(),
+ // responseValue: OCTETSTRING("").Pointer(),
+ // },
+ // controls: (*Controls)(nil),
+ // },
+ // },
+
+ // // A bind request with a simple login / password authentication
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // 0x30, 0x1d,
+ // 0x02, 0x01, 0x01, // messageID
+ // 0x60, 0x18, // Application, tag 0 => this is a Bind request
+ // 0x02, 0x01, 0x03, // Version 3
+ // 0x04, 0x07, 0x6d, 0x79, 0x4c, 0x6f, 0x67, 0x69, 0x6e, // login = myLogin
+ // 0x80, 0x0a, 0x6d, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, // simple authentication: myPassword
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x01)),
+ // protocolOp: BindRequest{
+ // version: 0x03,
+ // name: LDAPDN("myLogin"),
+ // authentication: OCTETSTRING([]byte("myPassword")),
+ // },
+ // },
+ // },
+ // // A bind request with SASL (CRAM-MD5)
+ // {
+ // bytes: Bytes{
+ // offset: 0,
+ // bytes: []byte{
+ // 0x30, 0x16,
+ // 0x02, 0x01, 0x01, // messageID
+ // 0x60, 0x11,
+ // 0x02, 0x01, 0x03, // version 3
+ // 0x04, 0x00, // no login
+ // 0xa3, 0x0a, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35, // SASL mechanism "CRAM-MD5", no credentials
+ // },
+ // },
+ // out: LDAPMessage{
+ // messageID: MessageID(int(0x01)),
+ // protocolOp: BindRequest{
+ // version: 0x03,
+ // name: LDAPDN(""),
+ // authentication: SaslCredentials{
+ // mechanism: LDAPString("CRAM-MD5"),
+ // },
+ // },
+ // },
+ // },
+ }
+}
diff --git a/goldap/read_test.go b/goldap/read_test.go
new file mode 100644
index 0000000..bc25fcc
--- /dev/null
+++ b/goldap/read_test.go
@@ -0,0 +1,2936 @@
+package message
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestReadLDAPMessage(t *testing.T) {
+ for i, test := range getLDAPMessageTestData() {
+ message, err := ReadLDAPMessage(&test.bytes)
+ if err != nil {
+ t.Errorf("#%d failed reading bytes at offset %d (%s): %s", i, test.bytes.offset, test.bytes.DumpCurrentBytes(), err)
+ } else if !reflect.DeepEqual(message, test.out) {
+ t.Errorf("#%d:\nGOT:\n%#+v\nEXPECTED:\n%#+v", i, message, test.out)
+ }
+ }
+}
+
+type LDAPMessageTestData struct {
+ bytes Bytes
+ out LDAPMessage
+}
+
+func getLDAPMessageTestData() (ret []LDAPMessageTestData) {
+ return []LDAPMessageTestData{
+ // Request 1: client => bind request
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c020101600702010304008000
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x01,
+ // BindRequest ::= [APPLICATION 0] SEQUENCE {
+ 0x60, 0x07,
+ // version INTEGER (1 .. 127),
+ 0x02, 0x01, 0x03,
+ // name LDAPDN,
+ 0x04, 0x00,
+ // authentication AuthenticationChoice }
+ // AuthenticationChoice ::= CHOICE {
+ // simple [0] OCTET STRING,
+ 0x80, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(1),
+ protocolOp: BindRequest{
+ version: INTEGER(3),
+ name: LDAPDN(""),
+ authentication: OCTETSTRING(""),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 2: server => bind response
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010161070a010004000400
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x01,
+ // BindResponse ::= [APPLICATION 1] SEQUENCE {
+ // COMPONENTS OF LDAPResult,
+ 0x61, 0x07,
+ // LDAPResult ::= SEQUENCE {
+ // resultCode ENUMERATED {
+ // success (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // matchedDN LDAPDN,
+ 0x04, 0x00,
+ // diagnosticMessage LDAPString,
+ 0x04, 0x00,
+ // referral [3] Referral OPTIONAL }
+ // serverSaslCreds [7] OCTET STRING OPTIONAL }
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x01)),
+ protocolOp: BindResponse{
+ LDAPResult: LDAPResult{
+ resultCode: 0,
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ },
+ },
+ },
+ },
+
+ // Request 3: client => search request
+ // select "subschemaSubentry" from entries where "objectClass" is present
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3038020102633304000a01000a0103020100020100010100870b6f626a656374436c61737330130411737562736368656d61537562656e747279
+ 0x30, 0x38,
+ 0x02, 0x01, 0x02,
+ // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ 0x63, 0x33,
+ // baseObject LDAPDN,
+ 0x04, 0x00,
+ // scope ENUMERATED {
+ // baseObject (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // derefAliases ENUMERATED {
+ // derefAlways (3) },
+ 0x0a, 0x01, 0x03,
+ // sizeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // timeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // typesOnly BOOLEAN,
+ 0x01, 0x01, 0x00,
+ // filter Filter,
+ // Filter ::= CHOICE {
+ // present [7] AttributeDescription,
+ // ... }
+ // AttributeDescription ::= LDAPString
+ // -- Constrained to <attributedescription>
+ // -- [RFC4512]
+ 0x87, 0x0b,
+ // "objectClass"
+ 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // attributes AttributeSelection }
+ // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // -- The LDAPString is constrained to
+ // -- <attributeSelector> in Section 4.5.1.8
+ 0x30, 0x13,
+ 0x04, 0x11,
+ // "subschemaSubentry"
+ 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x02)),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN(""),
+ scope: SearchRequestScopeBaseObject,
+ derefAliases: SearchRequetDerefAliasesDerefAlways,
+ sizeLimit: 0,
+ timeLimit: 0,
+ typesOnly: false,
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection([]LDAPString{"subschemaSubentry"}),
+ },
+ },
+ },
+
+ // Request 4: server => search result entry
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 302b02010264260400302230200411737562736368656d61537562656e747279310b0409636e3d736368656d61
+ 0x30, 0x2b,
+ 0x02, 0x01, 0x02,
+ // SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+ 0x64, 0x26,
+ // objectName LDAPDN,
+ 0x04, 0x00,
+ // attributes PartialAttributeList }
+ // PartialAttributeList ::= SEQUENCE OF
+ // partialAttribute PartialAttribute
+ 0x30, 0x22,
+ // PartialAttribute ::= SEQUENCE {
+ 0x30, 0x20,
+ // type AttributeDescription,
+ 0x04, 0x11,
+ // "subschemaSubentry"
+ 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ // vals SET OF value AttributeValue }
+ // AttributeValue ::= OCTET STRING
+ 0x31, 0x0b,
+ 0x04, 0x09,
+ // "cn=schema"
+ 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x02)),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN(""),
+ attributes: PartialAttributeList(
+ []PartialAttribute{
+ {
+ type_: AttributeDescription("subschemaSubentry"),
+ vals: []AttributeValue{AttributeValue("cn=schema")},
+ },
+ },
+ ),
+ },
+ },
+ },
+
+ // Request 5: server => search result done
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010265070a010004000400
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x02,
+ // SearchResultDone ::= [APPLICATION 5] LDAPResult
+ // LDAPResult ::= SEQUENCE {
+ 0x65, 0x07,
+ // resultCode ENUMERATED {
+ // success (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // matchedDN LDAPDN,
+ 0x04, 0x00,
+ // diagnosticMessage LDAPString,
+ 0x04, 0x00,
+ // referral [3] Referral OPTIONAL }
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x02)),
+ protocolOp: SearchResultDone(LDAPResult{
+ resultCode: ResultCodeSuccess,
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ }),
+ },
+ },
+
+ // Request 6: client => search request
+ // select
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 305d02010363580409636e3d736368656d610a01000a0103020100020100010100a318040b6f626a656374436c6173730409737562736368656d613022040f63726561746554696d657374616d70040f6d6f6469667954696d657374616d70
+ 0x30, 0x5d,
+ 0x02, 0x01, 0x03,
+ // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ 0x63, 0x58,
+ // baseObject LDAPDN,
+ // "cn=schema"
+ 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // scope ENUMERATED {
+ // baseObject (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // derefAliases ENUMERATED {
+ // derefAlways (3) },
+ 0x0a, 0x01, 0x03,
+ // sizeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // timeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // typesOnly BOOLEAN,
+ 0x01, 0x01, 0x00,
+ // filter Filter,
+ // Filter ::= CHOICE {
+ // equalityMatch [3] AttributeValueAssertion,
+ // AttributeValueAssertion ::= SEQUENCE {
+ 0xa3, 0x18,
+ // attributeDesc AttributeDescription,
+ // "objectClass"
+ 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // assertionValue AssertionValue }
+ // "subschema"
+ 0x04, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // attributes AttributeSelection }
+ // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // -- The LDAPString is constrained to
+ // -- <attributeSelector> in Section 4.5.1.8
+ 0x30, 0x22,
+ // "createTimestamp"
+ 0x04, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // "modifyTimestamp"
+ 0x04, 0x0f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x03)),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("cn=schema"),
+ scope: SearchRequestScopeBaseObject,
+ derefAliases: SearchRequetDerefAliasesDerefAlways,
+ sizeLimit: 0,
+ timeLimit: 0,
+ typesOnly: false,
+ filter: FilterEqualityMatch(
+ AttributeValueAssertion{
+ attributeDesc: AttributeDescription("objectClass"),
+ assertionValue: AssertionValue("subschema"),
+ }),
+ attributes: AttributeSelection([]LDAPString{"createTimestamp", "modifyTimestamp"}),
+ },
+ },
+ },
+
+ // Request 7: server => search result entry
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 305e02010364590409636e3d736368656d61304c3024040f6d6f6469667954696d657374616d703111040f32303039303831383032323733335a3024040f63726561746554696d657374616d703111040f32303039303831383032323733335a
+ 0x30, 0x5e,
+ 0x02, 0x01, 0x03,
+ // SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+ 0x64, 0x59,
+ // objectName LDAPDN,
+ // "cn=schema"
+ 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ // attributes PartialAttributeList }
+ // PartialAttributeList ::= SEQUENCE OF
+ // partialAttribute PartialAttribute
+ 0x30, 0x4c,
+ // PartialAttribute ::= SEQUENCE {
+ 0x30, 0x24,
+ // type AttributeDescription,
+ // "modifyTimestamp"
+ 0x04, 0x0f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // vals SET OF value AttributeValue }
+ 0x31, 0x11,
+ // "20090818022733Z"
+ 0x04, 0x0f, 0x32, 0x30, 0x30, 0x39, 0x30, 0x38, 0x31, 0x38, 0x30, 0x32, 0x32, 0x37, 0x33, 0x33, 0x5a,
+ // PartialAttribute ::= SEQUENCE {
+ 0x30, 0x24,
+ // type AttributeDescription,
+ // "createTimestamp"
+ 0x04, 0x0f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+ // vals SET OF value AttributeValue }
+ 0x31, 0x11,
+ // "20090818022733Z"
+ 0x04, 0x0f, 0x32, 0x30, 0x30, 0x39, 0x30, 0x38, 0x31, 0x38, 0x30, 0x32, 0x32, 0x37, 0x33, 0x33, 0x5a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x03)),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("cn=schema"),
+ attributes: PartialAttributeList(
+ []PartialAttribute{
+ {
+ type_: AttributeDescription("modifyTimestamp"),
+ vals: []AttributeValue{AttributeValue("20090818022733Z")},
+ },
+ {
+ type_: AttributeDescription("createTimestamp"),
+ vals: []AttributeValue{AttributeValue("20090818022733Z")},
+ },
+ },
+ ),
+ },
+ },
+ },
+
+ // Request 8
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010365070a010004000400
+ 0x30, 0x0c,
+ 0x02, 0x01, 0x03,
+ // SearchResultDone ::= [APPLICATION 5] LDAPResult
+ // LDAPResult ::= SEQUENCE {
+ 0x65, 0x07,
+ // resultCode ENUMERATED {
+ // success (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // matchedDN LDAPDN,
+ 0x04, 0x00,
+ // diagnosticMessage LDAPString,
+ 0x04, 0x00,
+ // referral [3] Referral OPTIONAL }
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x03)),
+ protocolOp: SearchResultDone(LDAPResult{
+ resultCode: ResultCodeSuccess,
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ }),
+ },
+ },
+
+ // Request 9: client => search request
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081dd0201046381d704000a01000a0100020100020100010100870b6f626a656374436c6173733081b6040e6e616d696e67436f6e74657874730411737562736368656d61537562656e7472790414737570706f727465644c44415056657273696f6e0417737570706f727465645341534c4d656368616e69736d730412737570706f72746564457874656e73696f6e0410737570706f72746564436f6e74726f6c0411737570706f727465644665617475726573040a76656e646f724e616d65040d76656e646f7256657273696f6e04012b040b6f626a656374436c617373
+ 0x30, 0x81, 0xdd,
+ 0x02, 0x01, 0x04,
+ // SearchRequest ::= [APPLICATION 3] SEQUENCE {
+ 0x63, 0x81, 0xd7,
+ // baseObject LDAPDN,
+ 0x04, 0x00,
+ // scope ENUMERATED {
+ // baseObject (0),
+ // ... },
+ 0x0a, 0x01, 0x00,
+ // derefAliases ENUMERATED {
+ // neverDerefAliases (0) },
+ 0x0a, 0x01, 0x00,
+ // sizeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // timeLimit INTEGER (0 .. maxInt),
+ 0x02, 0x01, 0x00,
+ // typesOnly BOOLEAN,
+ 0x01, 0x01, 0x00,
+ // filter Filter,
+ // Filter ::= CHOICE {
+ // present [7] AttributeDescription,
+ // "objetClass"
+ 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ // attributes AttributeSelection }
+ // AttributeSelection ::= SEQUENCE OF selector LDAPString
+ // -- The LDAPString is constrained to
+ // -- <attributeSelector> in Section 4.5.1.8
+ 0x30, 0x81, 0xb6,
+ // namingContexts
+ 0x04, 0x0e, 0x6e, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73,
+ // subschemaSubentry
+ 0x04, 0x11, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79,
+ // supportedLDAPVersion
+ 0x04, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4c, 0x44, 0x41, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ // supportedSASLMechanisms
+ 0x04, 0x17, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x41, 0x53, 0x4c, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73,
+ // supportedExtension
+ 0x04, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
+ // supportedControl
+ 0x04, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
+ // supportedFeatures
+ 0x04, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73,
+ // vendorName
+ 0x04, 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65,
+ // vendorVersion
+ 0x04, 0x0d, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
+ // +
+ 0x04, 0x01, 0x2b,
+ // objectClass
+ 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x04)),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN(""),
+ scope: SearchRequestScopeBaseObject,
+ derefAliases: SearchRequetDerefAliasesNeverDerefAliases,
+ sizeLimit: 0,
+ timeLimit: 0,
+ typesOnly: false,
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection([]LDAPString{
+ "namingContexts",
+ "subschemaSubentry",
+ "supportedLDAPVersion",
+ "supportedSASLMechanisms",
+ "supportedExtension",
+ "supportedControl",
+ "supportedFeatures",
+ "vendorName",
+ "vendorVersion",
+ "+",
+ "objectClass",
+ }),
+ },
+ },
+ },
+
+ // Request 10
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308203850201046482037e040030820378302a040a76656e646f724e616d65311c041a41706163686520536f66747761726520466f756e646174696f6e301c040d76656e646f7256657273696f6e310b0409322e302e302d4d31343026040b6f626a656374436c61737331170403746f700410657874656e7369626c654f626a65637430200411737562736368656d61537562656e747279310b0409636e3d736368656d61301b0414737570706f727465644c44415056657273696f6e31030401333082012e0410737570706f72746564436f6e74726f6c318201180417322e31362e3834302e312e3131333733302e332e342e330417312e332e362e312e342e312e343230332e312e31302e310417322e31362e3834302e312e3131333733302e332e342e320418312e332e362e312e342e312e343230332e312e392e312e340419312e332e362e312e342e312e34322e322e32372e382e352e310418312e332e362e312e342e312e343230332e312e392e312e310418312e332e362e312e342e312e343230332e312e392e312e330418312e332e362e312e342e312e343230332e312e392e312e320417312e332e362e312e342e312e31383036302e302e302e310417322e31362e3834302e312e3131333733302e332e342e370416312e322e3834302e3131333535362e312e342e3331393081910412737570706f72746564457874656e73696f6e317b0416312e332e362e312e342e312e313436362e32303033360416312e332e362e312e342e312e313436362e32303033370417312e332e362e312e342e312e31383036302e302e312e350417312e332e362e312e342e312e31383036302e302e312e330417312e332e362e312e342e312e343230332e312e31312e3130530417737570706f727465645341534c4d656368616e69736d73313804044e544c4d0406475353415049040a4753532d53504e45474f04084352414d2d4d4435040653494d504c45040a4449474553542d4d443530330409656e747279555549443126042466323930343235632d383237322d346536322d386136372d3932623036663338646266353046040e6e616d696e67436f6e7465787473313404096f753d73797374656d041164633d6578616d706c652c64633d636f6d04096f753d736368656d6104096f753d636f6e666967302d0411737570706f72746564466561747572657331180416312e332e362e312e342e312e343230332e312e352e31
+ 0x30, 0x82, 0x03, 0x85, 0x02, 0x01, 0x04, 0x64, 0x82, 0x03, 0x7e, 0x04, 0x00, 0x30, 0x82, 0x03, 0x78, 0x30, 0x2a, 0x04, 0x0a, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x31, 0x1c, 0x04, 0x1a, 0x41, 0x70, 0x61, 0x63, 0x68, 0x65, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x1c, 0x04, 0x0d, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x0b, 0x04, 0x09, 0x32, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x4d, 0x31, 0x34, 0x30, 0x26, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x17, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x30, 0x20, 0x04, 0x11, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x53, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x31, 0x0b, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x1b, 0x04, 0x14, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4c, 0x44, 0x41, 0x50, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x03, 0x04, 0x01, 0x33, 0x30, 0x82, 0x01, 0x2e, 0x04, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x31, 0x82, 0x01, 0x18, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x33, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x34, 0x04, 0x19, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x2e, 0x32, 0x2e, 0x32, 0x37, 0x2e, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x31, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x33, 0x04, 0x18, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x39, 0x2e, 0x31, 0x2e, 0x32, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x37, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x30, 0x81, 0x91, 0x04, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x31, 0x7b, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x36, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x35, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x38, 0x30, 0x36, 0x30, 0x2e, 0x30, 0x2e, 0x31, 0x2e, 0x33, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x2e, 0x31, 0x30, 0x53, 0x04, 0x17, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x53, 0x41, 0x53, 0x4c, 0x4d, 0x65, 0x63, 0x68, 0x61, 0x6e, 0x69, 0x73, 0x6d, 0x73, 0x31, 0x38, 0x04, 0x04, 0x4e, 0x54, 0x4c, 0x4d, 0x04, 0x06, 0x47, 0x53, 0x53, 0x41, 0x50, 0x49, 0x04, 0x0a, 0x47, 0x53, 0x53, 0x2d, 0x53, 0x50, 0x4e, 0x45, 0x47, 0x4f, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35, 0x04, 0x06, 0x53, 0x49, 0x4d, 0x50, 0x4c, 0x45, 0x04, 0x0a, 0x44, 0x49, 0x47, 0x45, 0x53, 0x54, 0x2d, 0x4d, 0x44, 0x35, 0x30, 0x33, 0x04, 0x09, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x55, 0x55, 0x49, 0x44, 0x31, 0x26, 0x04, 0x24, 0x66, 0x32, 0x39, 0x30, 0x34, 0x32, 0x35, 0x63, 0x2d, 0x38, 0x32, 0x37, 0x32, 0x2d, 0x34, 0x65, 0x36, 0x32, 0x2d, 0x38, 0x61, 0x36, 0x37, 0x2d, 0x39, 0x32, 0x62, 0x30, 0x36, 0x66, 0x33, 0x38, 0x64, 0x62, 0x66, 0x35, 0x30, 0x46, 0x04, 0x0e, 0x6e, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x73, 0x31, 0x34, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2d, 0x04, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x31, 0x18, 0x04, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x35, 0x2e, 0x31,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(4),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN(""),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("vendorName"),
+ vals: []AttributeValue{
+ AttributeValue("Apache Software Foundation"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("vendorVersion"),
+ vals: []AttributeValue{
+ AttributeValue("2.0.0-M14"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("objectClass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("extensibleObject"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("subschemaSubentry"),
+ vals: []AttributeValue{
+ AttributeValue("cn=schema"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("supportedLDAPVersion"),
+ vals: []AttributeValue{
+ AttributeValue("3"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("supportedControl"),
+ vals: []AttributeValue{
+ AttributeValue("2.16.840.1.113730.3.4.3"),
+ AttributeValue("1.3.6.1.4.1.4203.1.10.1"),
+ AttributeValue("2.16.840.1.113730.3.4.2"),
+ AttributeValue("1.3.6.1.4.1.4203.1.9.1.4"),
+ AttributeValue("1.3.6.1.4.1.42.2.27.8.5.1"),
+ AttributeValue("1.3.6.1.4.1.4203.1.9.1.1"),
+ AttributeValue("1.3.6.1.4.1.4203.1.9.1.3"),
+ AttributeValue("1.3.6.1.4.1.4203.1.9.1.2"),
+ AttributeValue("1.3.6.1.4.1.18060.0.0.1"),
+ AttributeValue("2.16.840.1.113730.3.4.7"),
+ AttributeValue("1.2.840.113556.1.4.319"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("supportedExtension"),
+ vals: []AttributeValue{
+ AttributeValue("1.3.6.1.4.1.1466.20036"),
+ AttributeValue("1.3.6.1.4.1.1466.20037"),
+ AttributeValue("1.3.6.1.4.1.18060.0.1.5"),
+ AttributeValue("1.3.6.1.4.1.18060.0.1.3"),
+ AttributeValue("1.3.6.1.4.1.4203.1.11.1"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("supportedSASLMechanisms"),
+ vals: []AttributeValue{
+ AttributeValue("NTLM"),
+ AttributeValue("GSSAPI"),
+ AttributeValue("GSS-SPNEGO"),
+ AttributeValue("CRAM-MD5"),
+ AttributeValue("SIMPLE"),
+ AttributeValue("DIGEST-MD5"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("entryUUID"),
+ vals: []AttributeValue{
+ AttributeValue("f290425c-8272-4e62-8a67-92b06f38dbf5"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("namingContexts"),
+ vals: []AttributeValue{
+ AttributeValue("ou=system"),
+ AttributeValue("dc=example,dc=com"),
+ AttributeValue("ou=schema"),
+ AttributeValue("ou=config"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("supportedFeatures"),
+ vals: []AttributeValue{
+ AttributeValue("1.3.6.1.4.1.4203.1.5.1"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 11
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010465070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x04, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(4),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 12
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3028020105632304000a01000a0100020100020100010100870b6f626a656374436c617373300304012a
+ 0x30, 0x28, 0x02, 0x01, 0x05, 0x63, 0x23, 0x04, 0x00, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x00, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(5),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN(""),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(0),
+ sizeLimit: INTEGER(0),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("*"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 13
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3031020105642c040030283026040b6f626a656374436c61737331170403746f700410657874656e7369626c654f626a656374
+ 0x30, 0x31, 0x02, 0x01, 0x05, 0x64, 0x2c, 0x04, 0x00, 0x30, 0x28, 0x30, 0x26, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x17, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x10, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(5),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN(""),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectClass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("extensibleObject"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 14
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010565070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x05, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(5),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 15
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c020106634704096f753d736368656d610a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x4c, 0x02, 0x01, 0x06, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(6),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=schema"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 16
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303c020106643704096f753d736368656d61302a3028040b6f626a656374636c617373311904126f7267616e697a6174696f6e616c556e69740403746f70
+ 0x30, 0x3c, 0x02, 0x01, 0x06, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(6),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=schema"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("organizationalUnit"),
+ AttributeValue("top"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 17
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010665070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x06, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(6),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 18
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c020107634704096f753d636f6e6669670a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x4c, 0x02, 0x01, 0x07, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(7),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=config"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 19
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303c020107643704096f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x3c, 0x02, 0x01, 0x07, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(7),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 20
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010765070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x07, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(7),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 21
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c020108634704096f753d73797374656d0a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x4c, 0x02, 0x01, 0x08, 0x63, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(8),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=system"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 22
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303c020108643704096f753d73797374656d302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x3c, 0x02, 0x01, 0x08, 0x64, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(8),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=system"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 23
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010865070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x08, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(8),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 24
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c02010963470409636e3d736368656d610a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x4c, 0x02, 0x01, 0x09, 0x63, 0x47, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(9),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("cn=schema"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 25
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304e02010964490409636e3d736368656d61303c303a040b6f626a656374436c617373312b0403746f700409737562736368656d610408737562656e747279040f617061636865537562736368656d61
+ 0x30, 0x4e, 0x02, 0x01, 0x09, 0x64, 0x49, 0x04, 0x09, 0x63, 0x6e, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x30, 0x3c, 0x30, 0x3a, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x2b, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x09, 0x73, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x04, 0x08, 0x73, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x04, 0x0f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(9),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("cn=schema"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectClass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("subschema"),
+ AttributeValue("subentry"),
+ AttributeValue("apacheSubschema"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 26
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010965070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x09, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(9),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 27
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 305402010a634f041164633d6578616d706c652c64633d636f6d0a01000a0103020101020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x54, 0x02, 0x01, 0x0a, 0x63, 0x4f, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(10),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("dc=example,dc=com"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 28
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303802010a6433041164633d6578616d706c652c64633d636f6d301e301c040b6f626a656374636c617373310d0406646f6d61696e0403746f70
+ 0x30, 0x38, 0x02, 0x01, 0x0a, 0x64, 0x33, 0x04, 0x11, 0x64, 0x63, 0x3d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2c, 0x64, 0x63, 0x3d, 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(10),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("dc=example,dc=com"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("domain"),
+ AttributeValue("top"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 29
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010a65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0a, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(10),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 30
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304d02010b634804096f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x4d, 0x02, 0x01, 0x0b, 0x63, 0x48, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(11),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=config"),
+ scope: ENUMERATED(1),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 31
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306702010b646204286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730363034040b6f626a656374636c61737331250403746f7004146164732d6469726563746f72795365727669636504086164732d62617365
+ 0x30, 0x67, 0x02, 0x01, 0x0b, 0x64, 0x62, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x36, 0x30, 0x34, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x25, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(11),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("ads-directoryService"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 32
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010b65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0b, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(11),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 33
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303102010c632c04096f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ 0x30, 0x31, 0x02, 0x01, 0x0c, 0x63, 0x2c, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(12),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=config"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(0),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("*"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 34
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c02010c644704096f753d636f6e666967303a300e04026f7531080406636f6e6669673028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x4c, 0x02, 0x01, 0x0c, 0x64, 0x47, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x3a, 0x30, 0x0e, 0x04, 0x02, 0x6f, 0x75, 0x31, 0x08, 0x04, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(12),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("ou"),
+ vals: []AttributeValue{
+ AttributeValue("config"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 35
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010c65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0c, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(12),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 36
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306c02010d636704286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x6c, 0x02, 0x01, 0x0d, 0x63, 0x67, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(1),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 37
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 307b02010d647604456164732d6a6f75726e616c49643d64656661756c744a6f75726e616c2c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302d302b040b6f626a656374636c617373311c0403746f70040b6164732d6a6f75726e616c04086164732d62617365
+ 0x30, 0x7b, 0x02, 0x01, 0x0d, 0x64, 0x76, 0x04, 0x45, 0x61, 0x64, 0x73, 0x2d, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2d, 0x30, 0x2b, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x1c, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x6a, 0x6f, 0x75, 0x72, 0x6e, 0x61, 0x6c, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-journalId=defaultJournal,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("ads-journal"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 38
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306b02010d646604386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x6b, 0x02, 0x01, 0x0d, 0x64, 0x66, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 39
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306902010d646404366f753d706172746974696f6e732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x69, 0x02, 0x01, 0x0d, 0x64, 0x64, 0x04, 0x36, 0x6f, 0x75, 0x3d, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=partitions,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 40
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30818102010d647c04496164732d6368616e67654c6f6749643d64656661756c744368616e67654c6f672c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302f302d040b6f626a656374636c617373311e0403746f7004086164732d62617365040d6164732d6368616e67654c6f67
+ 0x30, 0x81, 0x81, 0x02, 0x01, 0x0d, 0x64, 0x7c, 0x04, 0x49, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2f, 0x30, 0x2d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x1e, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x04, 0x0d, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-changeLogId=defaultChangeLog,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ AttributeValue("ads-changeLog"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 41
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306602010d646104336f753d736572766572732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e666967302a3028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x66, 0x02, 0x01, 0x0d, 0x64, 0x61, 0x04, 0x33, 0x6f, 0x75, 0x3d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x2a, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=servers,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 42
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010d65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0d, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 43
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 305002010e634b04286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ 0x30, 0x50, 0x02, 0x01, 0x0e, 0x63, 0x4b, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(14),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(0),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("*"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 44
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3082017c02010e6482017504286164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730820147302304166164732d6469726563746f72797365727669636569643109040764656661756c74302104166164732d647373796e63706572696f646d696c6c69733107040531353030303024041a6164732d6473616c6c6f77616e6f6e796d6f757361636365737331060404545255453016040f6164732d64737265706c696361696431030401313025041a6164732d6473616363657373636f6e74726f6c656e61626c65643107040546414c5345301f04146164732d647370617373776f726468696464656e3107040546414c5345302a041f6164732d647364656e6f726d616c697a656f706174747273656e61626c65643107040546414c53453015040b6164732d656e61626c656431060404545255453034040b6f626a656374636c61737331250403746f7004146164732d6469726563746f72795365727669636504086164732d62617365
+ 0x30, 0x82, 0x01, 0x7c, 0x02, 0x01, 0x0e, 0x64, 0x82, 0x01, 0x75, 0x04, 0x28, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x82, 0x01, 0x47, 0x30, 0x23, 0x04, 0x16, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x69, 0x64, 0x31, 0x09, 0x04, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x30, 0x21, 0x04, 0x16, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x73, 0x79, 0x6e, 0x63, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x6d, 0x69, 0x6c, 0x6c, 0x69, 0x73, 0x31, 0x07, 0x04, 0x05, 0x31, 0x35, 0x30, 0x30, 0x30, 0x30, 0x24, 0x04, 0x1a, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x61, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75, 0x73, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x16, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x69, 0x64, 0x31, 0x03, 0x04, 0x01, 0x31, 0x30, 0x25, 0x04, 0x1a, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x1f, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x2a, 0x04, 0x1f, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x73, 0x64, 0x65, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x6f, 0x70, 0x61, 0x74, 0x74, 0x72, 0x73, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x07, 0x04, 0x05, 0x46, 0x41, 0x4c, 0x53, 0x45, 0x30, 0x15, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x34, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x25, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(14),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("ads-directoryserviceid"),
+ vals: []AttributeValue{
+ AttributeValue("default"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dssyncperiodmillis"),
+ vals: []AttributeValue{
+ AttributeValue("15000"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dsallowanonymousaccess"),
+ vals: []AttributeValue{
+ AttributeValue("TRUE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dsreplicaid"),
+ vals: []AttributeValue{
+ AttributeValue("1"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dsaccesscontrolenabled"),
+ vals: []AttributeValue{
+ AttributeValue("FALSE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dspasswordhidden"),
+ vals: []AttributeValue{
+ AttributeValue("FALSE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-dsdenormalizeopattrsenabled"),
+ vals: []AttributeValue{
+ AttributeValue("FALSE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-enabled"),
+ vals: []AttributeValue{
+ AttributeValue("TRUE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("ads-directoryService"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 45
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010e65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0e, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(14),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 46
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 306002010f635b04386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ 0x30, 0x60, 0x02, 0x01, 0x0f, 0x63, 0x5b, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(15),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(0),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("*"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 47
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30818102010f647c04386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673040301404026f75310e040c696e746572636570746f72733028040b6f626a656374636c61737331190403746f7004126f7267616e697a6174696f6e616c556e6974
+ 0x30, 0x81, 0x81, 0x02, 0x01, 0x0f, 0x64, 0x7c, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x40, 0x30, 0x14, 0x04, 0x02, 0x6f, 0x75, 0x31, 0x0e, 0x04, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x30, 0x28, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x19, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x12, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x74,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(15),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("ou"),
+ vals: []AttributeValue{
+ AttributeValue("interceptors"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("organizationalUnit"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 48
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02010f65070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x0f, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(15),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 49
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 307c020110637704386f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x7c, 0x02, 0x01, 0x10, 0x63, 0x77, 0x04, 0x38, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(1),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 50
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819a020110648194045f6164732d696e746572636570746f7249643d657863657074696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x9a, 0x02, 0x01, 0x10, 0x64, 0x81, 0x94, 0x04, 0x5f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=exceptionInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 51
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308196020110648190045b6164732d696e746572636570746f7249643d6576656e74496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x96, 0x02, 0x01, 0x10, 0x64, 0x81, 0x90, 0x04, 0x5b, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=eventInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 52
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a502011064819f046a6164732d696e746572636570746f7249643d6f7065726174696f6e616c417474726962757465496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa5, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9f, 0x04, 0x6a, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=operationalAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 53
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081be0201106481b804646164732d696e746572636570746f7249643d61757468656e7469636174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673050304e040b6f626a656374636c617373313f040f6164732d696e746572636570746f720403746f7004086164732d62617365041d6164732d61757468656e7469636174696f6e496e746572636570746f72
+ 0x30, 0x81, 0xbe, 0x02, 0x01, 0x10, 0x64, 0x81, 0xb8, 0x04, 0x64, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x50, 0x30, 0x4e, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x3f, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x04, 0x1d, 0x61, 0x64, 0x73, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=authenticationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ AttributeValue("ads-authenticationInterceptor"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 54
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a202011064819c04676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa2, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9c, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 55
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a002011064819a04656164732d696e746572636570746f7249643d70617373776f726448617368696e67496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa0, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9a, 0x04, 0x65, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x48, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=passwordHashingInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 56
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308197020110648191045c6164732d696e746572636570746f7249643d736368656d61496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x97, 0x02, 0x01, 0x10, 0x64, 0x81, 0x91, 0x04, 0x5c, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=schemaInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 57
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a402011064819e04696164732d696e746572636570746f7249643d61646d696e697374726174697665506f696e74496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa4, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9e, 0x04, 0x69, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=administrativePointInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 58
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308199020110648193045e6164732d696e746572636570746f7249643d726566657272616c496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x99, 0x02, 0x01, 0x10, 0x64, 0x81, 0x93, 0x04, 0x5e, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x61, 0x6c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=referralInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 59
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819e02011064819804636164732d696e746572636570746f7249643d6b657944657269766174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x9e, 0x02, 0x01, 0x10, 0x64, 0x81, 0x98, 0x04, 0x63, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6b, 0x65, 0x79, 0x44, 0x65, 0x72, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=keyDerivationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 60
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819e02011064819804636164732d696e746572636570746f7249643d6e6f726d616c697a6174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x9e, 0x02, 0x01, 0x10, 0x64, 0x81, 0x98, 0x04, 0x63, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=normalizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 61
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308199020110648193045e6164732d696e746572636570746f7249643d737562656e747279496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x99, 0x02, 0x01, 0x10, 0x64, 0x81, 0x93, 0x04, 0x5e, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x73, 0x75, 0x62, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=subentryInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 62
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a502011064819f046a6164732d696e746572636570746f7249643d64656661756c74417574686f72697a6174696f6e496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa5, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9f, 0x04, 0x6a, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=defaultAuthorizationInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 63
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 308198020110648192045d6164732d696e746572636570746f7249643d74726967676572496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0x98, 0x02, 0x01, 0x10, 0x64, 0x81, 0x92, 0x04, 0x5d, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=triggerInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 64
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081a402011064819e04696164732d696e746572636570746f7249643d636f6c6c656374697665417474726962757465496e746572636570746f722c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669673031302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d62617365
+ 0x30, 0x81, 0xa4, 0x02, 0x01, 0x10, 0x64, 0x81, 0x9e, 0x04, 0x69, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x31, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=collectiveAttributeInterceptor,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 65
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011065070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x10, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(16),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 66
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819002011163818a04676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01000a0103020100020100010100870b6f626a656374436c617373300304012a
+ 0x30, 0x81, 0x90, 0x02, 0x01, 0x11, 0x63, 0x81, 0x8a, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x00, 0x0a, 0x01, 0x03, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x03, 0x04, 0x01, 0x2a,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(17),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(0),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(0),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("*"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 67
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3082018d0201116482018604676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e66696730820119302f040b6f626a656374636c6173733120040f6164732d696e746572636570746f720403746f7004086164732d626173653015040b6164732d656e61626c65643106040454525545306004186164732d696e746572636570746f72636c6173736e616d65314404426f72672e6170616368652e6469726563746f72792e7365727665722e636f72652e617574687a2e416369417574686f72697a6174696f6e496e746572636570746f72301b04146164732d696e746572636570746f726f726465723103040134305004116164732d696e746572636570746f726964313b041b616369417574686f72697a6174696f6e496e746572636570746f72041c616369417574686f72697a6174696f6e496e746572636570746f7232
+ 0x30, 0x82, 0x01, 0x8d, 0x02, 0x01, 0x11, 0x64, 0x82, 0x01, 0x86, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x30, 0x82, 0x01, 0x19, 0x30, 0x2f, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x20, 0x04, 0x0f, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x08, 0x61, 0x64, 0x73, 0x2d, 0x62, 0x61, 0x73, 0x65, 0x30, 0x15, 0x04, 0x0b, 0x61, 0x64, 0x73, 0x2d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x31, 0x06, 0x04, 0x04, 0x54, 0x52, 0x55, 0x45, 0x30, 0x60, 0x04, 0x18, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x31, 0x44, 0x04, 0x42, 0x6f, 0x72, 0x67, 0x2e, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x7a, 0x2e, 0x41, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x30, 0x1b, 0x04, 0x14, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x31, 0x03, 0x04, 0x01, 0x34, 0x30, 0x50, 0x04, 0x11, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x69, 0x64, 0x31, 0x3b, 0x04, 0x1b, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x04, 0x1c, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(17),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectclass"),
+ vals: []AttributeValue{
+ AttributeValue("ads-interceptor"),
+ AttributeValue("top"),
+ AttributeValue("ads-base"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-enabled"),
+ vals: []AttributeValue{
+ AttributeValue("TRUE"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-interceptorclassname"),
+ vals: []AttributeValue{
+ AttributeValue("org.apache.directory.server.core.authz.AciAuthorizationInterceptor"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-interceptororder"),
+ vals: []AttributeValue{
+ AttributeValue("4"),
+ },
+ },
+ PartialAttribute{
+ type_: AttributeDescription("ads-interceptorid"),
+ vals: []AttributeValue{
+ AttributeValue("aciAuthorizationInterceptor"),
+ AttributeValue("aciAuthorizationInterceptor2"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 68
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011165070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x11, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(17),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 69
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081ac0201126381a604676164732d696e746572636570746f7249643d616369417574686f72697a6174696f6e496e746572636570746f72322c6f753d696e746572636570746f72732c6164732d6469726563746f72795365727669636549643d64656661756c742c6f753d636f6e6669670a01010a0103020203e8020100010100870b6f626a656374436c617373301e040f6861735375626f7264696e61746573040b6f626a656374436c617373
+ 0x30, 0x81, 0xac, 0x02, 0x01, 0x12, 0x63, 0x81, 0xa6, 0x04, 0x67, 0x61, 0x64, 0x73, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x3d, 0x61, 0x63, 0x69, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x32, 0x2c, 0x6f, 0x75, 0x3d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x63, 0x65, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x2c, 0x61, 0x64, 0x73, 0x2d, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x3d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x0a, 0x01, 0x01, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x1e, 0x04, 0x0f, 0x68, 0x61, 0x73, 0x53, 0x75, 0x62, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(18),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ads-interceptorId=aciAuthorizationInterceptor2,ou=interceptors,ads-directoryServiceId=default,ou=config"),
+ scope: ENUMERATED(1),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("hasSubordinates"),
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 70
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011265070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x12, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(18),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 71
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30050201134200
+ 0x30, 0x05, 0x02, 0x01, 0x13, 0x42, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(19),
+ protocolOp: UnbindRequest{},
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 72: CLIENT AddRequest
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3081b60201156881b0044a636e3d723030582b636f6d6d6f6e4e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d3062301c040b6465736372697074696f6e310d040b4120746573742075736572300c0402736e310604047230307830160402636e311004047230305804085468652072303058301c040b6f626a656374436c617373310d0406706572736f6e0403746f70
+ 0x30, 0x81, 0xb6, 0x02, 0x01, 0x15, 0x68, 0x81, 0xb0, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x62, 0x30, 0x1c, 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0d, 0x04, 0x0b, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x30, 0x0c, 0x04, 0x02, 0x73, 0x6e, 0x31, 0x06, 0x04, 0x04, 0x72, 0x30, 0x30, 0x78, 0x30, 0x16, 0x04, 0x02, 0x63, 0x6e, 0x31, 0x10, 0x04, 0x04, 0x72, 0x30, 0x30, 0x58, 0x04, 0x08, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x06, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x04, 0x03, 0x74, 0x6f, 0x70,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(21),
+ protocolOp: AddRequest{
+ entry: LDAPDN("cn=r00X+commonName=The r00X+description=A test user,ou=consumers,ou=system"),
+ attributes: AttributeList{
+ Attribute{
+ type_: AttributeDescription("description"),
+ vals: []AttributeValue{
+ AttributeValue("A test user"),
+ },
+ },
+ Attribute{
+ type_: AttributeDescription("sn"),
+ vals: []AttributeValue{
+ AttributeValue("r00x"),
+ },
+ },
+ Attribute{
+ type_: AttributeDescription("cn"),
+ vals: []AttributeValue{
+ AttributeValue("r00X"),
+ AttributeValue("The r00X"),
+ },
+ },
+ Attribute{
+ type_: AttributeDescription("objectClass"),
+ vals: []AttributeValue{
+ AttributeValue("person"),
+ AttributeValue("top"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 73: SERVER AddResponse
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011569070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x15, 0x69, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(21),
+ protocolOp: AddResponse{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 74: CLIENT ModifyRequest
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30790201196674044a636e3d723030582b636f6d6d6f6e6e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d302630240a0100301f040f74656c6570686f6e654e756d626572310c040a30313233343536373839
+ 0x30, 0x79, 0x02, 0x01, 0x19, 0x66, 0x74, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x26, 0x30, 0x24, 0x0a, 0x01, 0x00, 0x30, 0x1f, 0x04, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x31, 0x0c, 0x04, 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(25),
+ protocolOp: ModifyRequest{
+ object: LDAPDN("cn=r00X+commonname=The r00X+description=A test user,ou=consumers,ou=system"),
+ changes: []ModifyRequestChange{
+ {
+ operation: ENUMERATED(0),
+ modification: PartialAttribute{
+ type_: AttributeDescription("telephoneNumber"),
+ vals: []AttributeValue{
+ AttributeValue("0123456789"),
+ },
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 75: SERVER ModifyResponse
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011967070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x19, 0x67, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(25),
+ protocolOp: ModifyResponse{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 76: CLIENT ModifyDNrequest
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 307502011b6c70044a636e3d723030582b636f6d6d6f6e6e616d653d54686520723030582b6465736372697074696f6e3d41207465737420757365722c6f753d636f6e73756d6572732c6f753d73797374656d0407636e3d723030580101ff80166f753d636f6e73756d6572732c6f753d73797374656d
+ 0x30, 0x75, 0x02, 0x01, 0x1b, 0x6c, 0x70, 0x04, 0x4a, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x54, 0x68, 0x65, 0x20, 0x72, 0x30, 0x30, 0x58, 0x2b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x04, 0x07, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x01, 0x01, 0xff, 0x80, 0x16, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(27),
+ protocolOp: ModifyDNRequest{
+ entry: LDAPDN("cn=r00X+commonname=The r00X+description=A test user,ou=consumers,ou=system"),
+ newrdn: RelativeLDAPDN("cn=r00X"),
+ deleteoldrdn: BOOLEAN(true),
+ newSuperior: LDAPDN("ou=consumers,ou=system").Pointer(),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 77: SERVER ModifyDNResponse
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02011b6d070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x1b, 0x6d, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(27),
+ protocolOp: ModifyDNResponse{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 78: CLIENT
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303b020121633604096f753d73797374656d0a01020a0103020203e8020100010100a30a0402636e040472303058300d040b6f626a656374436c617373
+ 0x30, 0x3b, 0x02, 0x01, 0x21, 0x63, 0x36, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa3, 0x0a, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x04, 0x72, 0x30, 0x30, 0x58, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(33),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=system"),
+ scope: ENUMERATED(2),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterEqualityMatch{
+ attributeDesc: AttributeDescription("cn"),
+ assertionValue: AssertionValue("r00X"),
+ },
+ attributes: AttributeSelection{
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 79: SERVER
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30450201216440041e636e3d723030582c6f753d636f6e73756d6572732c6f753d73797374656d301e301c040b6f626a656374436c617373310d0403746f700406706572736f6e
+ 0x30, 0x45, 0x02, 0x01, 0x21, 0x64, 0x40, 0x04, 0x1e, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x1e, 0x30, 0x1c, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x31, 0x0d, 0x04, 0x03, 0x74, 0x6f, 0x70, 0x04, 0x06, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(33),
+ protocolOp: SearchResultEntry{
+ objectName: LDAPDN("cn=r00X,ou=consumers,ou=system"),
+ attributes: PartialAttributeList{
+ PartialAttribute{
+ type_: AttributeDescription("objectClass"),
+ vals: []AttributeValue{
+ AttributeValue("top"),
+ AttributeValue("person"),
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 80: SERVER
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c02012165070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x21, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(33),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 81: CLIENT SearchRequest with controls
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30819c020124633704096f753d73797374656d0a01020a0103020203e8020100010100870b6f626a656374436c617373300d040b6f626a656374436c617373a05e301e0417312e332e362e312e342e312e343230332e312e31302e3104030101ff30190417322e31362e3834302e312e3131333733302e332e342e3230210416312e322e3834302e3131333535362e312e342e333139040730050201030400
+ 0x30, 0x81, 0x9c, 0x02, 0x01, 0x24, 0x63, 0x37, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x87, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73, 0xa0, 0x5e, 0x30, 0x1e, 0x04, 0x17, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x34, 0x32, 0x30, 0x33, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x2e, 0x31, 0x04, 0x03, 0x01, 0x01, 0xff, 0x30, 0x19, 0x04, 0x17, 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x31, 0x33, 0x37, 0x33, 0x30, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x30, 0x21, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x04, 0x07, 0x30, 0x05, 0x02, 0x01, 0x03, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(36),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=system"),
+ scope: ENUMERATED(2),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterPresent("objectClass"),
+ attributes: AttributeSelection{
+ LDAPString("objectClass"),
+ },
+ },
+ controls: &Controls{
+ Control{
+ controlType: LDAPOID("1.3.6.1.4.1.4203.1.10.1"),
+ criticality: BOOLEAN(false),
+ controlValue: OCTETSTRING("\x01\x01\xff").Pointer(),
+ },
+ Control{
+ controlType: LDAPOID("2.16.840.1.113730.3.4.2"),
+ criticality: BOOLEAN(false),
+ controlValue: (*OCTETSTRING)(nil),
+ },
+ Control{
+ controlType: LDAPOID("1.2.840.113556.1.4.319"),
+ criticality: BOOLEAN(false),
+ controlValue: OCTETSTRING("0\x05\x02\x01\x03\x04\x00").Pointer(),
+ },
+ },
+ },
+ },
+
+ // Request 82: SERVER SearchResultDone with Controls
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 303402012465070a010004000400a02630240416312e322e3834302e3131333535362e312e342e3331390101ff040730050201000400
+ 0x30, 0x34, 0x02, 0x01, 0x24, 0x65, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00, 0xa0, 0x26, 0x30, 0x24, 0x04, 0x16, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x31, 0x33, 0x35, 0x35, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x33, 0x31, 0x39, 0x01, 0x01, 0xff, 0x04, 0x07, 0x30, 0x05, 0x02, 0x01, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(36),
+ protocolOp: SearchResultDone{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: &Controls{
+ Control{
+ controlType: LDAPOID("1.2.840.113556.1.4.319"),
+ criticality: BOOLEAN(true),
+ controlValue: OCTETSTRING("0\x05\x02\x01\x00\x04\x00").Pointer(),
+ },
+ },
+ },
+ },
+
+ // (|
+ // (&
+ // (cn=r00x)
+ // (telephoneNumber=*)
+ // )
+ // (cn~=The)
+ // (&
+ // (!(description=Toto))
+ // (ou=co*f*g*r*on)
+ // )
+ // )
+ // Request 83: CLIENT
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30818e02010d63818804096f753d73797374656d0a01020a0103020203e8020100010100a15ca01da30a0402636e040472303078870f74656c6570686f6e654e756d626572a8090402636e0403546865a030a215a313040b6465736372697074696f6e0404546f746fa41704026f7530118002636f81016681016781017282026f6e300d040b6f626a656374436c617373
+ // 0x30, 0x81, 0x8e, 0x02, 0x01, 0x0d, 0x63, 0x81, 0x88, 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa1, 0x5c, 0xa0, 0x1d, 0xa3, 0x0a, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x04, 0x72, 0x30, 0x30, 0x78, 0x87, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0xa8, 0x09, 0x04, 0x02, 0x63, 0x6e, 0x04, 0x03, 0x54, 0x68, 0x65, 0xa0, 0x30, 0xa2, 0x15, 0xa3, 0x13, 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x04, 0x04, 0x54, 0x6f, 0x74, 0x6f, 0xa4, 0x17, 0x04, 0x02, 0x6f, 0x75, 0x30, 0x11, 0x80, 0x02, 0x63, 0x6f, 0x81, 0x01, 0x66, 0x81, 0x01, 0x67, 0x81, 0x01, 0x72, 0x82, 0x02, 0x6f, 0x6e, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ 0x30, 0x81, 0x8e,
+ // messageID
+ 0x02, 0x01, 0x0d,
+ // protocolOp
+ 0x63, 0x81, 0x88,
+ // baseObject
+ 0x04, 0x09, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ // scope
+ 0x0a, 0x01, 0x02,
+ // derefAliases
+ 0x0a, 0x01, 0x03,
+ // sizeLimit
+ 0x02, 0x02, 0x03, 0xe8,
+ // timeLimit
+ 0x02, 0x01, 0x00,
+ // typesOnly
+ 0x01, 0x01, 0x00,
+ // filter
+ // filterOr [1]
+ 0xa1, 0x5c,
+ // filterAnd [0]
+ 0xa0, 0x1d,
+ // filterEqualityMatch [3]
+ 0xa3, 0x0a,
+ // cn
+ 0x04, 0x02, 0x63, 0x6e,
+ // r00x
+ 0x04, 0x04, 0x72, 0x30, 0x30, 0x78,
+ // filterPresent [7]
+ // telephoneNumber
+ 0x87, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+ // filterApproxMatch
+ 0xa8, 0x09,
+ // cn
+ 0x04, 0x02, 0x63, 0x6e,
+ // the
+ 0x04, 0x03, 0x54, 0x68, 0x65,
+ // filterAnd [0]
+ 0xa0, 0x30,
+ // filterNot [2]
+ 0xa2, 0x15,
+ // FilterEqualityMatch [3]
+ 0xa3, 0x13,
+ // description
+ 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ // Toto
+ 0x04, 0x04, 0x54, 0x6f, 0x74, 0x6f,
+ // filterSubstrings
+ 0xa4, 0x17,
+ // type = ou
+ 0x04, 0x02, 0x6f, 0x75,
+ // substrings
+ 0x30, 0x11,
+ // substringInitial = co
+ 0x80, 0x02, 0x63, 0x6f,
+ // substringAny = f
+ 0x81, 0x01, 0x66,
+ // substringAny = g
+ 0x81, 0x01, 0x67,
+ // substringAny = r
+ 0x81, 0x01, 0x72,
+ // substringFinal = on
+ 0x82, 0x02, 0x6f, 0x6e,
+ // attributes
+ 0x30, 0x0d,
+ // AttributeSelection = objectClass
+ 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(13),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=system"),
+ scope: ENUMERATED(2),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterOr{
+ FilterAnd{
+ FilterEqualityMatch{
+ attributeDesc: AttributeDescription("cn"),
+ assertionValue: AssertionValue("r00x"),
+ },
+ FilterPresent("telephoneNumber"),
+ },
+ FilterApproxMatch{
+ attributeDesc: AttributeDescription("cn"),
+ assertionValue: AssertionValue("The"),
+ },
+ FilterAnd{
+ FilterNot{
+ Filter: FilterEqualityMatch{
+ attributeDesc: AttributeDescription("description"),
+ assertionValue: AssertionValue("Toto"),
+ },
+ },
+ FilterSubstrings{
+ type_: AttributeDescription("ou"),
+ substrings: []Substring{
+ SubstringInitial("co"),
+ SubstringAny("f"),
+ SubstringAny("g"),
+ SubstringAny("r"),
+ SubstringFinal("on"),
+ },
+ },
+ },
+ },
+ attributes: AttributeSelection{
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 84: CLIENT SearchRequest with FilterGreaterOrEqual and FilterLessOrEqual
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3072020119636d04000a01020a0103020203e8020100010100a04aa523041e6164732d636867507764506f6c69637950617373776f72644c656e677468040133a623041e6164732d636867507764506f6c69637950617373776f72644c656e677468040135300d040b6f626a656374436c617373
+ 0x30, 0x72, 0x02, 0x01, 0x19, 0x63, 0x6d, 0x04, 0x00, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x4a, 0xa5, 0x23, 0x04, 0x1e, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x67, 0x50, 0x77, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x04, 0x01, 0x33, 0xa6, 0x23, 0x04, 0x1e, 0x61, 0x64, 0x73, 0x2d, 0x63, 0x68, 0x67, 0x50, 0x77, 0x64, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x04, 0x01, 0x35, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(25),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN(""),
+ scope: ENUMERATED(2),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterAnd{
+ FilterGreaterOrEqual{
+ attributeDesc: AttributeDescription("ads-chgPwdPolicyPasswordLength"),
+ assertionValue: AssertionValue("3"),
+ },
+ FilterLessOrEqual{
+ attributeDesc: AttributeDescription("ads-chgPwdPolicyPasswordLength"),
+ assertionValue: AssertionValue("5"),
+ },
+ },
+ attributes: AttributeSelection{
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 85: CLIENT SearchRequest with FilterExtensibleMatch
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 3074020131636f04166f753d636f6e73756d6572732c6f753d73797374656d0a01020a0103020203e8020100010100a936811474656c6570686f6e654e756d6265724d61746368820f74656c6570686f6e654e756d626572830a303132333435363738398401ff300d040b6f626a656374436c617373
+ 0x30, 0x74, 0x02, 0x01, 0x31, 0x63, 0x6f, 0x04, 0x16, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x0a, 0x01, 0x02, 0x0a, 0x01, 0x03, 0x02, 0x02, 0x03, 0xe8, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0xa9, 0x36, 0x81, 0x14, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x82, 0x0f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x83, 0x0a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x84, 0x01, 0xff, 0x30, 0x0d, 0x04, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x43, 0x6c, 0x61, 0x73, 0x73,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(49),
+ protocolOp: SearchRequest{
+ baseObject: LDAPDN("ou=consumers,ou=system"),
+ scope: ENUMERATED(2),
+ derefAliases: ENUMERATED(3),
+ sizeLimit: INTEGER(1000),
+ timeLimit: INTEGER(0),
+ typesOnly: BOOLEAN(false),
+ filter: FilterExtensibleMatch{
+ matchingRule: MatchingRuleId("telephoneNumberMatch").Pointer(),
+ type_: AttributeDescription("telephoneNumber").Pointer(),
+ matchValue: AssertionValue("0123456789"),
+ dnAttributes: BOOLEAN(true),
+ },
+ attributes: AttributeSelection{
+ LDAPString("objectClass"),
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 86: CLIENT
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 30400201274a3b636e3d4120636f6d706c657820706572736f6e5c2c207665727920636f6d706c657820212c6f753d636f6e73756d6572732c6f753d73797374656d
+ 0x30, 0x40, 0x02, 0x01, 0x27, 0x4a, 0x3b, 0x63, 0x6e, 0x3d, 0x41, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x70, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x5c, 0x2c, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x78, 0x20, 0x21, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(39),
+ protocolOp: DelRequest("cn=A complex person\\, very complex !,ou=consumers,ou=system"),
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 87: SERVER
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 300c0201276b070a010004000400
+ 0x30, 0x0c, 0x02, 0x01, 0x27, 0x6b, 0x07, 0x0a, 0x01, 0x00, 0x04, 0x00, 0x04, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(39),
+ protocolOp: DelResponse{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 88: CLIENT ExtendedRequest: Start TLS (OID 1.3.6.1.4.1.1466.20037)
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 301d02010177188016312e332e362e312e342e312e313436362e3230303337
+ 0x30, 0x1d, 0x02, 0x01, 0x01, 0x77, 0x18, 0x80, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(1),
+ protocolOp: ExtendedRequest{
+ requestName: LDAPOID("1.3.6.1.4.1.1466.20037"),
+ requestValue: (*OCTETSTRING)(nil),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 89: SERVER ExtendedResponse: Start TLS (OID 1.3.6.1.4.1.1466.20037)
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 302602010178210a0100040004008a16312e332e362e312e342e312e313436362e32303033378b00
+ 0x30, 0x26,
+ 0x02, 0x01, 0x01,
+ 0x78, 0x21, 0x0a,
+ 0x01, 0x00,
+ 0x04, 0x00,
+ 0x04, 0x00,
+ 0x8a, 0x16, 0x31, 0x2e, 0x33, 0x2e, 0x36, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e, 0x31, 0x34, 0x36, 0x36, 0x2e, 0x32, 0x30, 0x30, 0x33, 0x37,
+ 0x8b, 0x00,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(1),
+ protocolOp: ExtendedResponse{
+ LDAPResult: LDAPResult{
+ resultCode: ENUMERATED(0),
+ matchedDN: LDAPDN(""),
+ diagnosticMessage: LDAPString(""),
+ referral: (*Referral)(nil),
+ },
+ responseName: LDAPOID("1.3.6.1.4.1.1466.20037").Pointer(),
+ responseValue: OCTETSTRING("").Pointer(),
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+
+ // Request 90: A bind request with a simple login / password authentication
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x1d,
+ 0x02, 0x01, 0x01, // messageID
+ 0x60, 0x18, // Application, tag 0 => this is a Bind request
+ 0x02, 0x01, 0x03, // Version 3
+ 0x04, 0x07, 0x6d, 0x79, 0x4c, 0x6f, 0x67, 0x69, 0x6e, // login = myLogin
+ 0x80, 0x0a, 0x6d, 0x79, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, // simple authentication: myPassword
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x01)),
+ protocolOp: BindRequest{
+ version: 0x03,
+ name: LDAPDN("myLogin"),
+ authentication: OCTETSTRING([]byte("myPassword")),
+ },
+ },
+ },
+ // Request 91: A bind request with SASL (CRAM-MD5)
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x16,
+ 0x02, 0x01, 0x01, // messageID
+ 0x60, 0x11,
+ 0x02, 0x01, 0x03, // version 3
+ 0x04, 0x00, // no login
+ 0xa3, 0x0a, 0x04, 0x08, 0x43, 0x52, 0x41, 0x4d, 0x2d, 0x4d, 0x44, 0x35, // SASL mechanism "CRAM-MD5", no credentials
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x01)),
+ protocolOp: BindRequest{
+ version: 0x03,
+ name: LDAPDN(""),
+ authentication: SaslCredentials{
+ mechanism: LDAPString("CRAM-MD5"),
+ },
+ },
+ },
+ },
+ // Request 92: An abandon request
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ 0x30, 0x06,
+ 0x02, 0x01, 0x0a, // messageID
+ 0x50, 0x01, 0x05, // Abandon request [APPLICATION 16] MessageID = 0x05
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(int(0x0a)),
+ protocolOp: AbandonRequest(0x05),
+ controls: (*Controls)(nil),
+ },
+ },
+ // Request 93: CLIENT
+ {
+ bytes: Bytes{
+ offset: 0,
+ bytes: []byte{
+ // 304c0201156647041e636e3d723030582c6f753d636f6e73756d6572732c6f753d73797374656d302530230a0102301e040b6465736372697074696f6e310f040d48656c6c6f2c20e4b896e7958c
+ 0x30, 0x4c, 0x02, 0x01, 0x15, 0x66, 0x47, 0x04, 0x1e, 0x63, 0x6e, 0x3d, 0x72, 0x30, 0x30, 0x58, 0x2c, 0x6f, 0x75, 0x3d, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x2c, 0x6f, 0x75, 0x3d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x30, 0x25, 0x30, 0x23, 0x0a, 0x01, 0x02, 0x30, 0x1e, 0x04, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0f, 0x04, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0xe4, 0xb8, 0x96, 0xe7, 0x95, 0x8c,
+ },
+ },
+ out: LDAPMessage{
+ messageID: MessageID(21),
+ protocolOp: ModifyRequest{
+ object: LDAPDN("cn=r00X,ou=consumers,ou=system"),
+ changes: []ModifyRequestChange{
+ {
+ operation: ENUMERATED(2),
+ modification: PartialAttribute{
+ type_: AttributeDescription("description"),
+ vals: []AttributeValue{
+ AttributeValue("Hello, 世界"),
+ },
+ },
+ },
+ },
+ },
+ controls: (*Controls)(nil),
+ },
+ },
+ }
+}
diff --git a/goldap/referral.go b/goldap/referral.go
new file mode 100644
index 0000000..8a04d85
--- /dev/null
+++ b/goldap/referral.go
@@ -0,0 +1,50 @@
+package message
+
+import "fmt"
+
+//
+// Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+func readTaggedReferral(bytes *Bytes, class int, tag int) (referral Referral, err error) {
+ err = bytes.ReadSubBytes(class, tag, referral.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedReferral:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (referral *Referral) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var uri URI
+ uri, err = readURI(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *referral = append(*referral, uri)
+ }
+ if len(*referral) == 0 {
+ return LdapError{"readComponents: expecting at least one URI"}
+ }
+ return
+}
+func (referral Referral) Pointer() *Referral { return &referral }
+
+//
+// Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+func (r Referral) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ for i := len(r) - 1; i >= 0; i-- {
+ size += r[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+//
+// Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+func (r Referral) sizeTagged(tag int) (size int) {
+ for _, uri := range r {
+ size += uri.size()
+ }
+ size += sizeTagAndLength(tag, size)
+ return
+}
diff --git a/goldap/relative_ldap_dn.go b/goldap/relative_ldap_dn.go
new file mode 100644
index 0000000..00bc73c
--- /dev/null
+++ b/goldap/relative_ldap_dn.go
@@ -0,0 +1,15 @@
+package message
+
+//
+// RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+// -- [RFC4514]
+func (r RelativeLDAPDN) write(bytes *Bytes) int {
+ return LDAPString(r).write(bytes)
+}
+
+//
+// RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+// -- [RFC4514]
+func (r RelativeLDAPDN) size() int {
+ return LDAPString(r).size()
+}
diff --git a/goldap/result.go b/goldap/result.go
new file mode 100644
index 0000000..8a2c7ae
--- /dev/null
+++ b/goldap/result.go
@@ -0,0 +1,282 @@
+package message
+
+import "fmt"
+
+//
+// LDAPResult ::= SEQUENCE {
+// resultCode ENUMERATED {
+// success (0),
+// operationsError (1),
+// protocolError (2),
+// timeLimitExceeded (3),
+// sizeLimitExceeded (4),
+// compareFalse (5),
+// compareTrue (6),
+// authMethodNotSupported (7),
+// strongerAuthRequired (8),
+// -- 9 reserved --
+// referral (10),
+// adminLimitExceeded (11),
+// unavailableCriticalExtension (12),
+// confidentialityRequired (13),
+// saslBindInProgress (14),
+//
+//
+//
+//Sermersheim Standards Track [Page 55]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// noSuchAttribute (16),
+// undefinedAttributeType (17),
+// inappropriateMatching (18),
+// constraintViolation (19),
+// attributeOrValueExists (20),
+// invalidAttributeSyntax (21),
+// -- 22-31 unused --
+// noSuchObject (32),
+// aliasProblem (33),
+// invalidDNSyntax (34),
+// -- 35 reserved for undefined isLeaf --
+// aliasDereferencingProblem (36),
+// -- 37-47 unused --
+// inappropriateAuthentication (48),
+// invalidCredentials (49),
+// insufficientAccessRights (50),
+// busy (51),
+// unavailable (52),
+// unwillingToPerform (53),
+// loopDetect (54),
+// -- 55-63 unused --
+// namingViolation (64),
+// objectClassViolation (65),
+// notAllowedOnNonLeaf (66),
+// notAllowedOnRDN (67),
+// entryAlreadyExists (68),
+// objectClassModsProhibited (69),
+// -- 70 reserved for CLDAP --
+// affectsMultipleDSAs (71),
+// -- 72-79 unused --
+// other (80),
+// ... },
+// matchedDN LDAPDN,
+// diagnosticMessage LDAPString,
+// referral [3] Referral OPTIONAL }
+func readTaggedLDAPResult(bytes *Bytes, class int, tag int) (ret LDAPResult, err error) {
+ err = bytes.ReadSubBytes(class, tag, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedLDAPResult:\n%s", err.Error())}
+ }
+ return
+}
+func readLDAPResult(bytes *Bytes) (ldapresult LDAPResult, err error) {
+ return readTaggedLDAPResult(bytes, classUniversal, tagSequence)
+}
+func (ldapresult *LDAPResult) readComponents(bytes *Bytes) (err error) {
+ ldapresult.resultCode, err = readENUMERATED(bytes, EnumeratedLDAPResultCode)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ ldapresult.matchedDN, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ ldapresult.diagnosticMessage, err = readLDAPString(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var tag TagAndLength
+ tag, err = bytes.PreviewTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if tag.Tag == TagLDAPResultReferral {
+ var referral Referral
+ referral, err = readTaggedReferral(bytes, classContextSpecific, TagLDAPResultReferral)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ ldapresult.referral = referral.Pointer()
+ }
+ }
+ return
+}
+
+//
+// LDAPResult ::= SEQUENCE {
+// resultCode ENUMERATED {
+// success (0),
+// operationsError (1),
+// protocolError (2),
+// timeLimitExceeded (3),
+// sizeLimitExceeded (4),
+// compareFalse (5),
+// compareTrue (6),
+// authMethodNotSupported (7),
+// strongerAuthRequired (8),
+// -- 9 reserved --
+// referral (10),
+// adminLimitExceeded (11),
+// unavailableCriticalExtension (12),
+// confidentialityRequired (13),
+// saslBindInProgress (14),
+//
+//
+//
+//Sermersheim Standards Track [Page 55]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// noSuchAttribute (16),
+// undefinedAttributeType (17),
+// inappropriateMatching (18),
+// constraintViolation (19),
+// attributeOrValueExists (20),
+// invalidAttributeSyntax (21),
+// -- 22-31 unused --
+// noSuchObject (32),
+// aliasProblem (33),
+// invalidDNSyntax (34),
+// -- 35 reserved for undefined isLeaf --
+// aliasDereferencingProblem (36),
+// -- 37-47 unused --
+// inappropriateAuthentication (48),
+// invalidCredentials (49),
+// insufficientAccessRights (50),
+// busy (51),
+// unavailable (52),
+// unwillingToPerform (53),
+// loopDetect (54),
+// -- 55-63 unused --
+// namingViolation (64),
+// objectClassViolation (65),
+// notAllowedOnNonLeaf (66),
+// notAllowedOnRDN (67),
+// entryAlreadyExists (68),
+// objectClassModsProhibited (69),
+// -- 70 reserved for CLDAP --
+// affectsMultipleDSAs (71),
+// -- 72-79 unused --
+// other (80),
+// ... },
+// matchedDN LDAPDN,
+// diagnosticMessage LDAPString,
+// referral [3] Referral OPTIONAL }
+func (l LDAPResult) write(bytes *Bytes) (size int) {
+ size += l.writeComponents(bytes)
+ size += bytes.WriteTagAndLength(classUniversal, isCompound, tagSequence, size)
+ return
+}
+func (l LDAPResult) writeComponents(bytes *Bytes) (size int) {
+ if l.referral != nil {
+ size += l.referral.writeTagged(bytes, classContextSpecific, TagLDAPResultReferral)
+ }
+ size += l.diagnosticMessage.write(bytes)
+ size += l.matchedDN.write(bytes)
+ size += l.resultCode.write(bytes)
+ return
+}
+
+//
+// LDAPResult ::= SEQUENCE {
+// resultCode ENUMERATED {
+// success (0),
+// operationsError (1),
+// protocolError (2),
+// timeLimitExceeded (3),
+// sizeLimitExceeded (4),
+// compareFalse (5),
+// compareTrue (6),
+// authMethodNotSupported (7),
+// strongerAuthRequired (8),
+// -- 9 reserved --
+// referral (10),
+// adminLimitExceeded (11),
+// unavailableCriticalExtension (12),
+// confidentialityRequired (13),
+// saslBindInProgress (14),
+//
+//
+//
+//Sermersheim Standards Track [Page 55]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// noSuchAttribute (16),
+// undefinedAttributeType (17),
+// inappropriateMatching (18),
+// constraintViolation (19),
+// attributeOrValueExists (20),
+// invalidAttributeSyntax (21),
+// -- 22-31 unused --
+// noSuchObject (32),
+// aliasProblem (33),
+// invalidDNSyntax (34),
+// -- 35 reserved for undefined isLeaf --
+// aliasDereferencingProblem (36),
+// -- 37-47 unused --
+// inappropriateAuthentication (48),
+// invalidCredentials (49),
+// insufficientAccessRights (50),
+// busy (51),
+// unavailable (52),
+// unwillingToPerform (53),
+// loopDetect (54),
+// -- 55-63 unused --
+// namingViolation (64),
+// objectClassViolation (65),
+// notAllowedOnNonLeaf (66),
+// notAllowedOnRDN (67),
+// entryAlreadyExists (68),
+// objectClassModsProhibited (69),
+// -- 70 reserved for CLDAP --
+// affectsMultipleDSAs (71),
+// -- 72-79 unused --
+// other (80),
+// ... },
+// matchedDN LDAPDN,
+// diagnosticMessage LDAPString,
+// referral [3] Referral OPTIONAL }
+func (l LDAPResult) size() (size int) {
+ size += l.sizeComponents()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (l LDAPResult) sizeTagged(tag int) (size int) {
+ size += l.sizeComponents()
+ size += sizeTagAndLength(tag, size)
+ return
+}
+func (l LDAPResult) sizeComponents() (size int) {
+ if l.referral != nil {
+ size += l.referral.sizeTagged(TagLDAPResultReferral)
+ }
+ size += l.diagnosticMessage.size()
+ size += l.matchedDN.size()
+ size += l.resultCode.size()
+ return
+}
+func (l *LDAPResult) SetResultCode(code int) {
+ l.resultCode = ENUMERATED(code)
+}
+func (l *LDAPResult) SeMatchedDN(code string) {
+ l.matchedDN = LDAPDN(code)
+}
+func (l *LDAPResult) SetDiagnosticMessage(code string) {
+ l.diagnosticMessage = LDAPString(code)
+}
+func (l *LDAPResult) SetReferral(r *Referral) {
+ l.referral = r
+}
diff --git a/goldap/sasl_credentials.go b/goldap/sasl_credentials.go
new file mode 100644
index 0000000..1a56b3c
--- /dev/null
+++ b/goldap/sasl_credentials.go
@@ -0,0 +1,63 @@
+package message
+
+import "fmt"
+
+//
+// SaslCredentials ::= SEQUENCE {
+// mechanism LDAPString,
+// credentials OCTET STRING OPTIONAL }
+//
+func readSaslCredentials(bytes *Bytes) (authentication SaslCredentials, err error) {
+ authentication = SaslCredentials{}
+ err = bytes.ReadSubBytes(classContextSpecific, TagAuthenticationChoiceSaslCredentials, authentication.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSaslCredentials:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (authentication *SaslCredentials) readComponents(bytes *Bytes) (err error) {
+ authentication.mechanism, err = readLDAPString(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ if bytes.HasMoreData() {
+ var credentials OCTETSTRING
+ credentials, err = readOCTETSTRING(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ authentication.credentials = credentials.Pointer()
+ }
+ return
+}
+
+//
+// SaslCredentials ::= SEQUENCE {
+// mechanism LDAPString,
+// credentials OCTET STRING OPTIONAL }
+//
+func (s SaslCredentials) writeTagged(bytes *Bytes, class int, tag int) (size int) {
+ if s.credentials != nil {
+ size += s.credentials.write(bytes)
+ }
+ size += s.mechanism.write(bytes)
+ size += bytes.WriteTagAndLength(class, isCompound, tag, size)
+ return
+}
+
+//
+// SaslCredentials ::= SEQUENCE {
+// mechanism LDAPString,
+// credentials OCTET STRING OPTIONAL }
+//
+func (s SaslCredentials) sizeTagged(tag int) (size int) {
+ if s.credentials != nil {
+ size += s.credentials.size()
+ }
+ size += s.mechanism.size()
+ size += sizeTagAndLength(tag, size)
+ return
+}
diff --git a/goldap/search_request.go b/goldap/search_request.go
new file mode 100644
index 0000000..9d84f23
--- /dev/null
+++ b/goldap/search_request.go
@@ -0,0 +1,246 @@
+package message
+
+import (
+ "errors"
+ "fmt"
+)
+
+//
+// SearchRequest ::= [APPLICATION 3] SEQUENCE {
+// baseObject LDAPDN,
+// scope ENUMERATED {
+// baseObject (0),
+// singleLevel (1),
+// wholeSubtree (2),
+// ... },
+// derefAliases ENUMERATED {
+// neverDerefAliases (0),
+// derefInSearching (1),
+// derefFindingBaseObj (2),
+// derefAlways (3) },
+// sizeLimit INTEGER (0 .. maxInt),
+// timeLimit INTEGER (0 .. maxInt),
+// typesOnly BOOLEAN,
+// filter Filter,
+// attributes AttributeSelection }
+func readSearchRequest(bytes *Bytes) (searchrequest SearchRequest, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagSearchRequest, searchrequest.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSearchRequest:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (searchrequest *SearchRequest) readComponents(bytes *Bytes) (err error) {
+ searchrequest.baseObject, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.scope, err = readENUMERATED(bytes, EnumeratedSearchRequestScope)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.derefAliases, err = readENUMERATED(bytes, EnumeratedSearchRequestDerefAliases)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.sizeLimit, err = readPositiveINTEGER(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.timeLimit, err = readPositiveINTEGER(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.typesOnly, err = readBOOLEAN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.filter, err = readFilter(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchrequest.attributes, err = readAttributeSelection(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+//
+// SearchRequest ::= [APPLICATION 3] SEQUENCE {
+// baseObject LDAPDN,
+// scope ENUMERATED {
+// baseObject (0),
+// singleLevel (1),
+// wholeSubtree (2),
+// ... },
+// derefAliases ENUMERATED {
+// neverDerefAliases (0),
+// derefInSearching (1),
+// derefFindingBaseObj (2),
+// derefAlways (3) },
+// sizeLimit INTEGER (0 .. maxInt),
+// timeLimit INTEGER (0 .. maxInt),
+// typesOnly BOOLEAN,
+// filter Filter,
+// attributes AttributeSelection }
+func (s SearchRequest) write(bytes *Bytes) (size int) {
+ size += s.attributes.write(bytes)
+ size += s.filter.write(bytes)
+ size += s.typesOnly.write(bytes)
+ size += s.timeLimit.write(bytes)
+ size += s.sizeLimit.write(bytes)
+ size += s.derefAliases.write(bytes)
+ size += s.scope.write(bytes)
+ size += s.baseObject.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagSearchRequest, size)
+ return
+}
+
+//
+// SearchRequest ::= [APPLICATION 3] SEQUENCE {
+// baseObject LDAPDN,
+// scope ENUMERATED {
+// baseObject (0),
+// singleLevel (1),
+// wholeSubtree (2),
+// ... },
+// derefAliases ENUMERATED {
+// neverDerefAliases (0),
+// derefInSearching (1),
+// derefFindingBaseObj (2),
+// derefAlways (3) },
+// sizeLimit INTEGER (0 .. maxInt),
+// timeLimit INTEGER (0 .. maxInt),
+// typesOnly BOOLEAN,
+// filter Filter,
+// attributes AttributeSelection }
+func (s SearchRequest) size() (size int) {
+ size += s.baseObject.size()
+ size += s.scope.size()
+ size += s.derefAliases.size()
+ size += s.sizeLimit.size()
+ size += s.timeLimit.size()
+ size += s.typesOnly.size()
+ size += s.filter.size()
+ size += s.attributes.size()
+ size += sizeTagAndLength(TagSearchRequest, size)
+ return
+}
+func (s *SearchRequest) BaseObject() LDAPDN {
+ return s.baseObject
+}
+func (s *SearchRequest) Scope() ENUMERATED {
+ return s.scope
+}
+func (s *SearchRequest) DerefAliases() ENUMERATED {
+ return s.derefAliases
+}
+func (s *SearchRequest) SizeLimit() INTEGER {
+ return s.sizeLimit
+}
+func (s *SearchRequest) TimeLimit() INTEGER {
+ return s.timeLimit
+}
+func (s *SearchRequest) TypesOnly() BOOLEAN {
+ return s.typesOnly
+}
+func (s *SearchRequest) Attributes() AttributeSelection {
+ return s.attributes
+}
+func (s *SearchRequest) Filter() Filter {
+ return s.filter
+}
+func (s *SearchRequest) FilterString() string {
+ str, _ := s.decompileFilter(s.Filter())
+ return str
+}
+func (s *SearchRequest) decompileFilter(packet Filter) (ret string, err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = errors.New("error decompiling filter")
+ }
+ }()
+
+ ret = "("
+ err = nil
+ childStr := ""
+
+ switch f := packet.(type) {
+ case FilterAnd:
+ ret += "&"
+ for _, child := range f {
+ childStr, err = s.decompileFilter(child)
+ if err != nil {
+ return
+ }
+ ret += childStr
+ }
+ case FilterOr:
+ ret += "|"
+ for _, child := range f {
+ childStr, err = s.decompileFilter(child)
+ if err != nil {
+ return
+ }
+ ret += childStr
+ }
+ case FilterNot:
+ ret += "!"
+ childStr, err = s.decompileFilter(f.Filter)
+ if err != nil {
+ return
+ }
+ ret += childStr
+
+ case FilterSubstrings:
+ ret += string(f.Type_())
+ ret += "="
+ for _, fs := range f.Substrings() {
+ switch fsv := fs.(type) {
+ case SubstringInitial:
+ ret += string(fsv) + "*"
+ case SubstringAny:
+ ret += "*" + string(fsv) + "*"
+ case SubstringFinal:
+ ret += "*" + string(fsv)
+ }
+ }
+ case FilterEqualityMatch:
+ ret += string(f.AttributeDesc())
+ ret += "="
+ ret += string(f.AssertionValue())
+ case FilterGreaterOrEqual:
+ ret += string(f.AttributeDesc())
+ ret += ">="
+ ret += string(f.AssertionValue())
+ case FilterLessOrEqual:
+ ret += string(f.AttributeDesc())
+ ret += "<="
+ ret += string(f.AssertionValue())
+ case FilterPresent:
+ // if 0 == len(packet.Children) {
+ // ret += ber.DecodeString(packet.Data.Bytes())
+ // } else {
+ // ret += ber.DecodeString(packet.Children[0].Data.Bytes())
+ // }
+ ret += string(f)
+ ret += "=*"
+ case FilterApproxMatch:
+ ret += string(f.AttributeDesc())
+ ret += "~="
+ ret += string(f.AssertionValue())
+ }
+
+ ret += ")"
+ return
+}
diff --git a/goldap/search_result_done.go b/goldap/search_result_done.go
new file mode 100644
index 0000000..9666aef
--- /dev/null
+++ b/goldap/search_result_done.go
@@ -0,0 +1,31 @@
+package message
+
+import "fmt"
+
+//
+// SearchResultDone ::= [APPLICATION 5] LDAPResult
+func readSearchResultDone(bytes *Bytes) (ret SearchResultDone, err error) {
+ var ldapresult LDAPResult
+ ldapresult, err = readTaggedLDAPResult(bytes, classApplication, TagSearchResultDone)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSearchResultDone:\n%s", err.Error())}
+ return
+ }
+ ret = SearchResultDone(ldapresult)
+ return
+}
+
+//
+// SearchResultDone ::= [APPLICATION 5] LDAPResult
+func (s SearchResultDone) write(bytes *Bytes) int {
+ return LDAPResult(s).writeTagged(bytes, classApplication, TagSearchResultDone)
+}
+
+//
+// SearchResultDone ::= [APPLICATION 5] LDAPResult
+func (s SearchResultDone) size() int {
+ return LDAPResult(s).sizeTagged(TagSearchResultDone)
+}
+func (l *SearchResultDone) SetResultCode(code int) {
+ l.resultCode = ENUMERATED(code)
+}
diff --git a/goldap/search_result_entry.go b/goldap/search_result_entry.go
new file mode 100644
index 0000000..05d8e10
--- /dev/null
+++ b/goldap/search_result_entry.go
@@ -0,0 +1,58 @@
+package message
+
+import "fmt"
+
+//
+// SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+// objectName LDAPDN,
+// attributes PartialAttributeList }
+func readSearchResultEntry(bytes *Bytes) (searchresultentry SearchResultEntry, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagSearchResultEntry, searchresultentry.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSearchResultEntry:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (searchresultentry *SearchResultEntry) readComponents(bytes *Bytes) (err error) {
+ searchresultentry.objectName, err = readLDAPDN(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ searchresultentry.attributes, err = readPartialAttributeList(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ return
+}
+
+//
+// SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+// objectName LDAPDN,
+// attributes PartialAttributeList }
+func (s SearchResultEntry) write(bytes *Bytes) (size int) {
+ size += s.attributes.write(bytes)
+ size += s.objectName.write(bytes)
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagSearchResultEntry, size)
+ return
+}
+
+//
+// SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+// objectName LDAPDN,
+// attributes PartialAttributeList }
+func (s SearchResultEntry) size() (size int) {
+ size += s.objectName.size()
+ size += s.attributes.size()
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
+func (s *SearchResultEntry) SetObjectName(on string) {
+ s.objectName = LDAPDN(on)
+}
+func (s *SearchResultEntry) AddAttribute(name AttributeDescription, values ...AttributeValue) {
+ var ea = PartialAttribute{type_: name, vals: values}
+ s.attributes.add(ea)
+}
diff --git a/goldap/search_result_reference.go b/goldap/search_result_reference.go
new file mode 100644
index 0000000..20c14d5
--- /dev/null
+++ b/goldap/search_result_reference.go
@@ -0,0 +1,53 @@
+package message
+
+import "fmt"
+
+//
+// SearchResultReference ::= [APPLICATION 19] SEQUENCE
+// SIZE (1..MAX) OF uri URI
+func readSearchResultReference(bytes *Bytes) (ret SearchResultReference, err error) {
+ err = bytes.ReadSubBytes(classApplication, TagSearchResultReference, ret.readComponents)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readSearchResultReference:\n%s", err.Error())}
+ return
+ }
+ return
+}
+func (s *SearchResultReference) readComponents(bytes *Bytes) (err error) {
+ for bytes.HasMoreData() {
+ var uri URI
+ uri, err = readURI(bytes)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readComponents:\n%s", err.Error())}
+ return
+ }
+ *s = append(*s, uri)
+ }
+ if len(*s) == 0 {
+ err = LdapError{"readComponents: expecting at least one URI"}
+ return
+ }
+ return
+}
+
+//
+// SearchResultReference ::= [APPLICATION 19] SEQUENCE
+// SIZE (1..MAX) OF uri URI
+func (s SearchResultReference) write(bytes *Bytes) (size int) {
+ for i := len(s) - 1; i >= 0; i-- {
+ size += s[i].write(bytes)
+ }
+ size += bytes.WriteTagAndLength(classApplication, isCompound, TagSearchResultReference, size)
+ return
+}
+
+//
+// SearchResultReference ::= [APPLICATION 19] SEQUENCE
+// SIZE (1..MAX) OF uri URI
+func (s SearchResultReference) size() (size int) {
+ for _, uri := range s {
+ size += uri.size()
+ }
+ size += sizeTagAndLength(tagSequence, size)
+ return
+}
diff --git a/goldap/size_test.go b/goldap/size_test.go
new file mode 100644
index 0000000..eef6e53
--- /dev/null
+++ b/goldap/size_test.go
@@ -0,0 +1,85 @@
+package message
+
+import (
+ "testing"
+)
+
+func TestSizeLDAPMessage(t *testing.T) {
+
+ var testData = getLDAPMessageTestData()
+ for i, test := range testData {
+ message, err := ReadLDAPMessage(&test.bytes)
+ if err != nil {
+ t.Errorf("#%d error at offset %d (%s): %s", i, test.bytes.offset, test.bytes.DumpCurrentBytes(), err)
+ }
+ size := message.size()
+ expected := len(test.bytes.bytes)
+ if size != expected {
+ t.Errorf("#%d: wrong size, GOT: %d, EXPECTED: %d", i, size, expected)
+ }
+ }
+}
+
+type tagAndLengthTestData struct {
+ tag int
+ length int
+ expectedSize int
+}
+
+func getSizeTagAndLengthTestData() (ret []tagAndLengthTestData) {
+ return []tagAndLengthTestData{
+ // Length between 0 and 127 are encoded on one byte
+ {
+ tag: tagSequence,
+ length: 0,
+ expectedSize: 2,
+ },
+ {
+ tag: tagSequence,
+ length: 127,
+ expectedSize: 2,
+ },
+ // Length between 128 and 255 are encoded on two bytes
+ {
+ tag: tagSequence,
+ length: 128,
+ expectedSize: 3,
+ },
+ {
+ tag: tagSequence,
+ length: 255,
+ expectedSize: 3,
+ },
+ // Length between 256 (2^8) and 65535 (2^16-1) are encoded on three bytes
+ {
+ tag: tagSequence,
+ length: 256,
+ expectedSize: 4,
+ },
+ {
+ tag: tagSequence,
+ length: 65535,
+ expectedSize: 4,
+ },
+ // Length between 65536 (2^16) and 16777215 (2^24-1) are encoded on four bytes
+ {
+ tag: tagSequence,
+ length: 65536,
+ expectedSize: 5,
+ },
+ {
+ tag: tagSequence,
+ length: 16777215,
+ expectedSize: 5,
+ },
+ }
+}
+func TestSizeTagAndLength(t *testing.T) {
+ for i, test := range getSizeTagAndLengthTestData() {
+ size := sizeTagAndLength(test.tag, test.length)
+ if test.expectedSize != size {
+ t.Errorf("#%d: wrong size, GOT: %d, EXPECTED: %d", i, size, test.expectedSize)
+ }
+ }
+
+}
diff --git a/goldap/string.go b/goldap/string.go
new file mode 100644
index 0000000..d2949ac
--- /dev/null
+++ b/goldap/string.go
@@ -0,0 +1,38 @@
+package message
+
+import "fmt"
+
+func readTaggedLDAPString(bytes *Bytes, class int, tag int) (ldapstring LDAPString, err error) {
+ var octetstring OCTETSTRING
+ octetstring, err = readTaggedOCTETSTRING(bytes, class, tag)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readTaggedLDAPString:\n%s", err.Error())}
+ return
+ }
+ ldapstring = LDAPString(octetstring)
+ return
+}
+
+// LDAPString ::= OCTET STRING -- UTF-8 encoded,
+// -- [ISO10646] characters
+func readLDAPString(bytes *Bytes) (ldapstring LDAPString, err error) {
+ return readTaggedLDAPString(bytes, classUniversal, tagOctetString)
+}
+
+// LDAPString ::= OCTET STRING -- UTF-8 encoded,
+// -- [ISO10646] characters
+func (s LDAPString) write(bytes *Bytes) int {
+ return OCTETSTRING(s).write(bytes)
+}
+func (s LDAPString) writeTagged(bytes *Bytes, class int, tag int) int {
+ return OCTETSTRING(s).writeTagged(bytes, class, tag)
+}
+
+// LDAPString ::= OCTET STRING -- UTF-8 encoded,
+// -- [ISO10646] characters
+func (s LDAPString) size() int {
+ return OCTETSTRING(s).size()
+}
+func (s LDAPString) sizeTagged(tag int) int {
+ return OCTETSTRING(s).sizeTagged(tag)
+}
diff --git a/goldap/struct.go b/goldap/struct.go
new file mode 100644
index 0000000..ae751e2
--- /dev/null
+++ b/goldap/struct.go
@@ -0,0 +1,739 @@
+package message
+
+type OCTETSTRING string
+type INTEGER int32 // In this RFC the max INTEGER value is 2^31 - 1, so int32 is enough
+type BOOLEAN bool
+type ENUMERATED int32
+
+// This appendix is normative.
+//
+// Lightweight-Directory-Access-Protocol-V3 {1 3 6 1 1 18}
+// -- Copyright (C) The Internet Society (2006). This version of
+// -- this ASN.1 module is part of RFC 4511; see the RFC itself
+// -- for full legal notices.
+// DEFINITIONS
+// IMPLICIT TAGS
+// EXTENSIBILITY IMPLIED ::=
+//
+// BEGIN
+//
+// LDAPMessage ::= SEQUENCE {
+// messageID MessageID,
+// protocolOp CHOICE {
+// bindRequest BindRequest,
+// bindResponse BindResponse,
+// unbindRequest UnbindRequest,
+// searchRequest SearchRequest,
+// searchResEntry SearchResultEntry,
+// searchResDone SearchResultDone,
+// searchResRef SearchResultReference,
+// modifyRequest ModifyRequest,
+// modifyResponse ModifyResponse,
+// addRequest AddRequest,
+// addResponse AddResponse,
+// delRequest DelRequest,
+// delResponse DelResponse,
+// modDNRequest ModifyDNRequest,
+// modDNResponse ModifyDNResponse,
+// compareRequest CompareRequest,
+// compareResponse CompareResponse,
+// abandonRequest AbandonRequest,
+// extendedReq ExtendedRequest,
+// extendedResp ExtendedResponse,
+// ...,
+// intermediateResponse IntermediateResponse },
+// controls [0] Controls OPTIONAL }
+//
+type LDAPMessage struct {
+ messageID MessageID
+ protocolOp ProtocolOp
+ controls *Controls
+}
+
+const TagLDAPMessageControls = 0
+
+type ProtocolOp interface {
+ size() int
+ write(*Bytes) int
+}
+
+// MessageID ::= INTEGER (0 .. maxInt)
+//
+type MessageID INTEGER
+
+// maxInt INTEGER ::= 2147483647 -- (2^^31 - 1) --
+const maxInt = INTEGER(2147483647)
+
+//
+// LDAPString ::= OCTET STRING -- UTF-8 encoded,
+// -- [ISO10646] characters
+type LDAPString OCTETSTRING
+
+//
+//
+//
+//
+//Sermersheim Standards Track [Page 54]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// LDAPOID ::= OCTET STRING -- Constrained to <numericoid>
+// -- [RFC4512]
+type LDAPOID OCTETSTRING
+
+//
+// LDAPDN ::= LDAPString -- Constrained to <distinguishedName>
+// -- [RFC4514]
+type LDAPDN LDAPString
+
+//
+// RelativeLDAPDN ::= LDAPString -- Constrained to <name-component>
+// -- [RFC4514]
+type RelativeLDAPDN LDAPString
+
+//
+// AttributeDescription ::= LDAPString
+// -- Constrained to <attributedescription>
+// -- [RFC4512]
+type AttributeDescription LDAPString
+
+//
+// AttributeValue ::= OCTET STRING
+type AttributeValue OCTETSTRING
+
+//
+// AttributeValueAssertion ::= SEQUENCE {
+// attributeDesc AttributeDescription,
+// assertionValue AssertionValue }
+type AttributeValueAssertion struct {
+ attributeDesc AttributeDescription
+ assertionValue AssertionValue
+}
+
+//
+// AssertionValue ::= OCTET STRING
+type AssertionValue OCTETSTRING
+
+//
+// PartialAttribute ::= SEQUENCE {
+// type AttributeDescription,
+// vals SET OF value AttributeValue }
+type PartialAttribute struct {
+ type_ AttributeDescription
+ vals []AttributeValue
+}
+
+//
+// Attribute ::= PartialAttribute(WITH COMPONENTS {
+// ...,
+// vals (SIZE(1..MAX))})
+type Attribute PartialAttribute
+
+//
+// MatchingRuleId ::= LDAPString
+type MatchingRuleId LDAPString
+
+//
+// LDAPResult ::= SEQUENCE {
+// resultCode ENUMERATED {
+// success (0),
+// operationsError (1),
+// protocolError (2),
+// timeLimitExceeded (3),
+// sizeLimitExceeded (4),
+// compareFalse (5),
+// compareTrue (6),
+// authMethodNotSupported (7),
+// strongerAuthRequired (8),
+// -- 9 reserved --
+// referral (10),
+// adminLimitExceeded (11),
+// unavailableCriticalExtension (12),
+// confidentialityRequired (13),
+// saslBindInProgress (14),
+//
+//
+//
+//Sermersheim Standards Track [Page 55]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// noSuchAttribute (16),
+// undefinedAttributeType (17),
+// inappropriateMatching (18),
+// constraintViolation (19),
+// attributeOrValueExists (20),
+// invalidAttributeSyntax (21),
+// -- 22-31 unused --
+// noSuchObject (32),
+// aliasProblem (33),
+// invalidDNSyntax (34),
+// -- 35 reserved for undefined isLeaf --
+// aliasDereferencingProblem (36),
+// -- 37-47 unused --
+// inappropriateAuthentication (48),
+// invalidCredentials (49),
+// insufficientAccessRights (50),
+// busy (51),
+// unavailable (52),
+// unwillingToPerform (53),
+// loopDetect (54),
+// -- 55-63 unused --
+// namingViolation (64),
+// objectClassViolation (65),
+// notAllowedOnNonLeaf (66),
+// notAllowedOnRDN (67),
+// entryAlreadyExists (68),
+// objectClassModsProhibited (69),
+// -- 70 reserved for CLDAP --
+// affectsMultipleDSAs (71),
+// -- 72-79 unused --
+// other (80),
+// ... },
+// matchedDN LDAPDN,
+// diagnosticMessage LDAPString,
+// referral [3] Referral OPTIONAL }
+//
+type LDAPResult struct {
+ resultCode ENUMERATED
+ matchedDN LDAPDN
+ diagnosticMessage LDAPString
+ referral *Referral
+}
+
+const TagLDAPResultReferral = 3
+
+const ResultCodeSuccess = 0
+const ResultCodeOperationsError = 1
+const ResultCodeProtocolError = 2
+const ResultCodeTimeLimitExceeded = 3
+const ResultCodeSizeLimitExceeded = 4
+const ResultCodeCompareFalse = 5
+const ResultCodeCompareTrue = 6
+const ResultCodeAuthMethodNotSupported = 7
+const ResultCodeStrongerAuthRequired = 8
+const ResultCodeReferral = 10
+const ResultCodeAdminLimitExceeded = 11
+const ResultCodeUnavailableCriticalExtension = 12
+const ResultCodeConfidentialityRequired = 13
+const ResultCodeSaslBindInProgress = 14
+const ResultCodeNoSuchAttribute = 16
+const ResultCodeUndefinedAttributeType = 17
+const ResultCodeInappropriateMatching = 18
+const ResultCodeConstraintViolation = 19
+const ResultCodeAttributeOrValueExists = 20
+const ResultCodeInvalidAttributeSyntax = 21
+const ResultCodeNoSuchObject = 32
+const ResultCodeAliasProblem = 33
+const ResultCodeInvalidDNSyntax = 34
+const ResultCodeAliasDereferencingProblem = 36
+const ResultCodeInappropriateAuthentication = 48
+const ResultCodeInvalidCredentials = 49
+const ResultCodeInsufficientAccessRights = 50
+const ResultCodeBusy = 51
+const ResultCodeUnavailable = 52
+const ResultCodeUnwillingToPerform = 53
+const ResultCodeLoopDetect = 54
+const ResultCodeNamingViolation = 64
+const ResultCodeObjectClassViolation = 65
+const ResultCodeNotAllowedOnNonLeaf = 66
+const ResultCodeNotAllowedOnRDN = 67
+const ResultCodeEntryAlreadyExists = 68
+const ResultCodeObjectClassModsProhibited = 69
+const ResultCodeAffectsMultipleDSAs = 71
+const ResultCodeOther = 80
+
+var EnumeratedLDAPResultCode = map[ENUMERATED]string{
+ ResultCodeSuccess: "success",
+ ResultCodeOperationsError: "operationsError",
+ ResultCodeProtocolError: "protocolError",
+ ResultCodeTimeLimitExceeded: "timeLimitExceeded",
+ ResultCodeSizeLimitExceeded: "sizeLimitExceeded",
+ ResultCodeCompareFalse: "compareFalse",
+ ResultCodeCompareTrue: "compareTrue",
+ ResultCodeAuthMethodNotSupported: "authMethodNotSupported",
+ ResultCodeStrongerAuthRequired: "strongerAuthRequired",
+ // -- 9 reserved --
+ ResultCodeReferral: "referral",
+ ResultCodeAdminLimitExceeded: "adminLimitExceeded",
+ ResultCodeUnavailableCriticalExtension: "unavailableCriticalExtension",
+ ResultCodeConfidentialityRequired: "confidentialityRequired",
+ ResultCodeSaslBindInProgress: "saslBindInProgress",
+ ResultCodeNoSuchAttribute: "noSuchAttribute",
+ ResultCodeUndefinedAttributeType: "undefinedAttributeType",
+ ResultCodeInappropriateMatching: "inappropriateMatching",
+ ResultCodeConstraintViolation: "constraintViolation",
+ ResultCodeAttributeOrValueExists: "attributeOrValueExists",
+ ResultCodeInvalidAttributeSyntax: "invalidAttributeSyntax",
+ // -- 22-31 unused --
+ ResultCodeNoSuchObject: "noSuchObject",
+ ResultCodeAliasProblem: "aliasProblem",
+ ResultCodeInvalidDNSyntax: "invalidDNSyntax",
+ // -- 35 reserved for undefined isLeaf --
+ ResultCodeAliasDereferencingProblem: "aliasDereferencingProblem",
+ // -- 37-47 unused --
+ ResultCodeInappropriateAuthentication: "inappropriateAuthentication",
+ ResultCodeInvalidCredentials: "invalidCredentials",
+ ResultCodeInsufficientAccessRights: "insufficientAccessRights",
+ ResultCodeBusy: "busy",
+ ResultCodeUnavailable: "unavailable",
+ ResultCodeUnwillingToPerform: "unwillingToPerform",
+ ResultCodeLoopDetect: "loopDetect",
+ // -- 55-63 unused --
+ ResultCodeNamingViolation: "namingViolation",
+ ResultCodeObjectClassViolation: "objectClassViolation",
+ ResultCodeNotAllowedOnNonLeaf: "notAllowedOnNonLeaf",
+ ResultCodeNotAllowedOnRDN: "notAllowedOnRDN",
+ ResultCodeEntryAlreadyExists: "entryAlreadyExists",
+ ResultCodeObjectClassModsProhibited: "objectClassModsProhibited",
+ // -- 70 reserved for CLDAP --
+ ResultCodeAffectsMultipleDSAs: "affectsMultipleDSAs",
+ // -- 72-79 unused --
+ ResultCodeOther: "other",
+}
+
+// Referral ::= SEQUENCE SIZE (1..MAX) OF uri URI
+type Referral []URI
+
+//
+// URI ::= LDAPString -- limited to characters permitted in
+// -- URIs
+type URI LDAPString
+
+//
+// Controls ::= SEQUENCE OF control Control
+type Controls []Control
+
+//
+// Control ::= SEQUENCE {
+// controlType LDAPOID,
+// criticality BOOLEAN DEFAULT FALSE,
+// controlValue OCTET STRING OPTIONAL }
+type Control struct {
+ controlType LDAPOID
+ criticality BOOLEAN
+ controlValue *OCTETSTRING
+}
+
+//
+//
+//
+//
+//Sermersheim Standards Track [Page 56]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// BindRequest ::= [APPLICATION 0] SEQUENCE {
+// version INTEGER (1 .. 127),
+// name LDAPDN,
+// authentication AuthenticationChoice }
+const TagBindRequest = 0
+const BindRequestVersionMin = 1
+const BindRequestVersionMax = 127
+
+type BindRequest struct {
+ version INTEGER
+ name LDAPDN
+ authentication AuthenticationChoice
+}
+
+//
+// AuthenticationChoice ::= CHOICE {
+// simple [0] OCTET STRING,
+// -- 1 and 2 reserved
+// sasl [3] SaslCredentials,
+// ... }
+const TagAuthenticationChoiceSimple = 0
+const TagAuthenticationChoiceSaslCredentials = 3
+
+type AuthenticationChoice interface {
+ sizeTagged(int) int
+}
+
+//
+// SaslCredentials ::= SEQUENCE {
+// mechanism LDAPString,
+// credentials OCTET STRING OPTIONAL }
+type SaslCredentials struct {
+ mechanism LDAPString
+ credentials *OCTETSTRING
+}
+
+//
+// BindResponse ::= [APPLICATION 1] SEQUENCE {
+// COMPONENTS OF LDAPResult,
+// serverSaslCreds [7] OCTET STRING OPTIONAL }
+const TagBindResponse = 1
+const TagBindResponseServerSaslCreds = 7
+
+type BindResponse struct {
+ LDAPResult
+ serverSaslCreds *OCTETSTRING
+}
+
+//
+// UnbindRequest ::= [APPLICATION 2] NULL
+const TagUnbindRequest = 2
+
+type UnbindRequest struct {
+}
+
+//
+// SearchRequest ::= [APPLICATION 3] SEQUENCE {
+// baseObject LDAPDN,
+// scope ENUMERATED {
+// baseObject (0),
+// singleLevel (1),
+// wholeSubtree (2),
+// ... },
+// derefAliases ENUMERATED {
+// neverDerefAliases (0),
+// derefInSearching (1),
+// derefFindingBaseObj (2),
+// derefAlways (3) },
+// sizeLimit INTEGER (0 .. maxInt),
+// timeLimit INTEGER (0 .. maxInt),
+// typesOnly BOOLEAN,
+// filter Filter,
+// attributes AttributeSelection }
+const TagSearchRequest = 3
+
+type SearchRequest struct {
+ baseObject LDAPDN
+ scope ENUMERATED
+ derefAliases ENUMERATED
+ sizeLimit INTEGER
+ timeLimit INTEGER
+ typesOnly BOOLEAN
+ filter Filter
+ attributes AttributeSelection
+}
+
+const SearchRequestScopeBaseObject = 0
+const SearchRequestSingleLevel = 1
+const SearchRequestHomeSubtree = 2
+
+var EnumeratedSearchRequestScope = map[ENUMERATED]string{
+ SearchRequestScopeBaseObject: "baseObject",
+ SearchRequestSingleLevel: "singleLevel",
+ SearchRequestHomeSubtree: "homeSubtree",
+}
+
+const SearchRequetDerefAliasesNeverDerefAliases = 0
+const SearchRequetDerefAliasesDerefInSearching = 1
+const SearchRequetDerefAliasesDerefFindingBaseObj = 2
+const SearchRequetDerefAliasesDerefAlways = 3
+
+var EnumeratedSearchRequestDerefAliases = map[ENUMERATED]string{
+ SearchRequetDerefAliasesNeverDerefAliases: "neverDerefAliases",
+ SearchRequetDerefAliasesDerefInSearching: "derefInSearching",
+ SearchRequetDerefAliasesDerefFindingBaseObj: "derefFindingBaseObj",
+ SearchRequetDerefAliasesDerefAlways: "derefAlways",
+}
+
+//
+// AttributeSelection ::= SEQUENCE OF selector LDAPString
+// -- The LDAPString is constrained to
+// -- <attributeSelector> in Section 4.5.1.8
+type AttributeSelection []LDAPString
+
+//
+// Filter ::= CHOICE {
+// and [0] SET SIZE (1..MAX) OF filter Filter,
+// or [1] SET SIZE (1..MAX) OF filter Filter,
+// not [2] Filter,
+// equalityMatch [3] AttributeValueAssertion,
+//
+//
+//
+//Sermersheim Standards Track [Page 57]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// substrings [4] SubstringFilter,
+// greaterOrEqual [5] AttributeValueAssertion,
+// lessOrEqual [6] AttributeValueAssertion,
+// present [7] AttributeDescription,
+// approxMatch [8] AttributeValueAssertion,
+// extensibleMatch [9] MatchingRuleAssertion,
+// ... }
+const TagFilterAnd = 0
+const TagFilterOr = 1
+const TagFilterNot = 2
+const TagFilterEqualityMatch = 3
+const TagFilterSubstrings = 4
+const TagFilterGreaterOrEqual = 5
+const TagFilterLessOrEqual = 6
+const TagFilterPresent = 7
+const TagFilterApproxMatch = 8
+const TagFilterExtensibleMatch = 9
+
+type Filter interface {
+ size() int
+ write(*Bytes) int
+ getFilterTag() int
+}
+type FilterAnd []Filter
+type FilterOr []Filter
+type FilterNot struct {
+ Filter
+}
+type FilterEqualityMatch AttributeValueAssertion
+type FilterSubstrings SubstringFilter
+type FilterGreaterOrEqual AttributeValueAssertion
+type FilterLessOrEqual AttributeValueAssertion
+type FilterPresent AttributeDescription
+type FilterApproxMatch AttributeValueAssertion
+type FilterExtensibleMatch MatchingRuleAssertion
+
+//
+// SubstringFilter ::= SEQUENCE {
+// type AttributeDescription,
+// substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
+// initial [0] AssertionValue, -- can occur at most once
+// any [1] AssertionValue,
+// final [2] AssertionValue } -- can occur at most once
+// }
+type SubstringFilter struct {
+ type_ AttributeDescription
+ substrings []Substring
+}
+
+type Substring interface{}
+
+const TagSubstringInitial = 0
+const TagSubstringAny = 1
+const TagSubstringFinal = 2
+
+type SubstringInitial AssertionValue
+type SubstringAny AssertionValue
+type SubstringFinal AssertionValue
+
+//
+// MatchingRuleAssertion ::= SEQUENCE {
+// matchingRule [1] MatchingRuleId OPTIONAL,
+// type [2] AttributeDescription OPTIONAL,
+// matchValue [3] AssertionValue,
+// dnAttributes [4] BOOLEAN DEFAULT FALSE }
+type MatchingRuleAssertion struct {
+ matchingRule *MatchingRuleId
+ type_ *AttributeDescription
+ matchValue AssertionValue
+ dnAttributes BOOLEAN
+}
+
+const TagMatchingRuleAssertionMatchingRule = 1
+const TagMatchingRuleAssertionType = 2
+const TagMatchingRuleAssertionMatchValue = 3
+const TagMatchingRuleAssertionDnAttributes = 4
+
+//
+// SearchResultEntry ::= [APPLICATION 4] SEQUENCE {
+// objectName LDAPDN,
+// attributes PartialAttributeList }
+const TagSearchResultEntry = 4
+
+type SearchResultEntry struct {
+ objectName LDAPDN
+ attributes PartialAttributeList
+}
+
+//
+// PartialAttributeList ::= SEQUENCE OF
+// partialAttribute PartialAttribute
+type PartialAttributeList []PartialAttribute
+
+//
+// SearchResultReference ::= [APPLICATION 19] SEQUENCE
+// SIZE (1..MAX) OF uri URI
+const TagSearchResultReference = 19
+
+type SearchResultReference []URI
+
+//
+// SearchResultDone ::= [APPLICATION 5] LDAPResult
+const TagSearchResultDone = 5
+
+type SearchResultDone LDAPResult
+
+//
+// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
+// object LDAPDN,
+// changes SEQUENCE OF change SEQUENCE {
+// operation ENUMERATED {
+// add (0),
+// delete (1),
+// replace (2),
+// ... },
+// modification PartialAttribute } }
+const TagModifyRequest = 6
+
+type ModifyRequest struct {
+ object LDAPDN
+ changes []ModifyRequestChange
+}
+type ModifyRequestChange struct {
+ operation ENUMERATED
+ modification PartialAttribute
+}
+
+const ModifyRequestChangeOperationAdd = 0
+const ModifyRequestChangeOperationDelete = 1
+const ModifyRequestChangeOperationReplace = 2
+
+var EnumeratedModifyRequestChangeOperation = map[ENUMERATED]string{
+ ModifyRequestChangeOperationAdd: "add",
+ ModifyRequestChangeOperationDelete: "delete",
+ ModifyRequestChangeOperationReplace: "replace",
+}
+
+//
+// ModifyResponse ::= [APPLICATION 7] LDAPResult
+const TagModifyResponse = 7
+
+type ModifyResponse LDAPResult
+
+//
+//
+//
+//
+//
+//
+//Sermersheim Standards Track [Page 58]
+//
+//
+//RFC 4511 LDAPv3 June 2006
+//
+//
+// AddRequest ::= [APPLICATION 8] SEQUENCE {
+// entry LDAPDN,
+// attributes AttributeList }
+const TagAddRequest = 8
+
+type AddRequest struct {
+ entry LDAPDN
+ attributes AttributeList
+}
+
+//
+// AttributeList ::= SEQUENCE OF attribute Attribute
+type AttributeList []Attribute
+
+//
+// AddResponse ::= [APPLICATION 9] LDAPResult
+const TagAddResponse = 9
+
+type AddResponse LDAPResult
+
+//
+// DelRequest ::= [APPLICATION 10] LDAPDN
+const TagDelRequest = 10
+
+type DelRequest LDAPDN
+
+//
+// DelResponse ::= [APPLICATION 11] LDAPResult
+const TagDelResponse = 11
+
+type DelResponse LDAPResult
+
+//
+// ModifyDNRequest ::= [APPLICATION 12] SEQUENCE {
+// entry LDAPDN,
+// newrdn RelativeLDAPDN,
+// deleteoldrdn BOOLEAN,
+// newSuperior [0] LDAPDN OPTIONAL }
+const TagModifyDNRequest = 12
+
+type ModifyDNRequest struct {
+ entry LDAPDN
+ newrdn RelativeLDAPDN
+ deleteoldrdn BOOLEAN
+ newSuperior *LDAPDN
+}
+
+const TagModifyDNRequestNewSuperior = 0
+
+//
+// ModifyDNResponse ::= [APPLICATION 13] LDAPResult
+const TagModifyDNResponse = 13
+
+type ModifyDNResponse LDAPResult
+
+//
+// CompareRequest ::= [APPLICATION 14] SEQUENCE {
+// entry LDAPDN,
+// ava AttributeValueAssertion }
+const TagCompareRequest = 14
+
+type CompareRequest struct {
+ entry LDAPDN
+ ava AttributeValueAssertion
+}
+
+// CompareResponse ::= [APPLICATION 15] LDAPResult
+const TagCompareResponse = 15
+
+type CompareResponse LDAPResult
+
+//
+// AbandonRequest ::= [APPLICATION 16] MessageID
+const TagAbandonRequest = 16
+
+type AbandonRequest MessageID
+
+//
+// ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
+// requestName [0] LDAPOID,
+// requestValue [1] OCTET STRING OPTIONAL }
+const TagExtendedRequest = 23
+
+type ExtendedRequest struct {
+ requestName LDAPOID
+ requestValue *OCTETSTRING
+}
+
+const TagExtendedRequestName = 0
+const TagExtendedRequestValue = 1
+
+//
+// ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
+// COMPONENTS OF LDAPResult,
+// responseName [10] LDAPOID OPTIONAL,
+// responseValue [11] OCTET STRING OPTIONAL }
+const TagExtendedResponse = 24
+
+type ExtendedResponse struct {
+ LDAPResult
+ responseName *LDAPOID
+ responseValue *OCTETSTRING
+}
+
+const TagExtendedResponseName = 10
+const TagExtendedResponseValue = 11
+
+//
+// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
+// responseName [0] LDAPOID OPTIONAL,
+// responseValue [1] OCTET STRING OPTIONAL }
+const TagIntermediateResponse = 25
+
+type IntermediateResponse struct {
+ responseName *LDAPOID
+ responseValue *OCTETSTRING
+}
+
+const TagIntermediateResponseName = 0
+const TagIntermediateResponseValue = 1
+
+//
+// END
+//
diff --git a/goldap/struct_methods.go b/goldap/struct_methods.go
new file mode 100644
index 0000000..a43cb63
--- /dev/null
+++ b/goldap/struct_methods.go
@@ -0,0 +1,7 @@
+package message
+
+func NewLDAPMessageWithProtocolOp(po ProtocolOp) *LDAPMessage {
+ m := NewLDAPMessage()
+ m.protocolOp = po
+ return m
+}
diff --git a/goldap/unbind_request.go b/goldap/unbind_request.go
new file mode 100644
index 0000000..57f49e5
--- /dev/null
+++ b/goldap/unbind_request.go
@@ -0,0 +1,38 @@
+package message
+
+import "fmt"
+
+//
+// UnbindRequest ::= [APPLICATION 2] NULL
+func readUnbindRequest(bytes *Bytes) (unbindrequest UnbindRequest, err error) {
+ var tagAndLength TagAndLength
+ tagAndLength, err = bytes.ParseTagAndLength()
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readUnbindRequest:\n%s", err.Error())}
+ return
+ }
+ err = tagAndLength.Expect(classApplication, TagUnbindRequest, isNotCompound)
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readUnbindRequest:\n%s", err.Error())}
+ return
+ }
+ if tagAndLength.Length != 0 {
+ err = LdapError{"readUnbindRequest: expecting NULL"}
+ return
+ }
+ return
+}
+
+//
+// UnbindRequest ::= [APPLICATION 2] NULL
+func (u UnbindRequest) write(bytes *Bytes) (size int) {
+ size += bytes.WriteTagAndLength(classApplication, isNotCompound, TagUnbindRequest, 0)
+ return
+}
+
+//
+// UnbindRequest ::= [APPLICATION 2] NULL
+func (u UnbindRequest) size() (size int) {
+ size = sizeTagAndLength(TagUnbindRequest, 0)
+ return
+}
diff --git a/goldap/uri.go b/goldap/uri.go
new file mode 100644
index 0000000..b57874a
--- /dev/null
+++ b/goldap/uri.go
@@ -0,0 +1,32 @@
+package message
+
+import "fmt"
+
+//
+// URI ::= LDAPString -- limited to characters permitted in
+// -- URIs
+func readURI(bytes *Bytes) (uri URI, err error) {
+ var ldapstring LDAPString
+ ldapstring, err = readLDAPString(bytes)
+ // @TODO: check permitted chars in URI
+ if err != nil {
+ err = LdapError{fmt.Sprintf("readURI:\n%s", err.Error())}
+ return
+ }
+ uri = URI(ldapstring)
+ return
+}
+
+//
+// URI ::= LDAPString -- limited to characters permitted in
+// -- URIs
+func (u URI) write(bytes *Bytes) int {
+ return LDAPString(u).write(bytes)
+}
+
+//
+// URI ::= LDAPString -- limited to characters permitted in
+// -- URIs
+func (u URI) size() int {
+ return LDAPString(u).size()
+}
diff --git a/goldap/write.go b/goldap/write.go
new file mode 100644
index 0000000..970cb02
--- /dev/null
+++ b/goldap/write.go
@@ -0,0 +1,6 @@
+package message
+
+type Writable interface {
+ write(bytes *Bytes) int
+ writeTagged(bytes *Bytes, class int, tag int) int
+}
diff --git a/goldap/write_test.go b/goldap/write_test.go
new file mode 100644
index 0000000..7c82bd7
--- /dev/null
+++ b/goldap/write_test.go
@@ -0,0 +1,19 @@
+package message
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestWriteLDAPMessage(t *testing.T) {
+
+ var testData = getLDAPMessageTestData()
+ for i, test := range testData {
+ bytes, err := test.out.Write()
+ if err != nil {
+ t.Errorf("#%d error at offset %d (%s): %s\nEXPECTED BYTES: %#v\nWRITTEN BYTES: %#v\n", i, test.bytes.offset, test.bytes.DumpCurrentBytes(), err, test.bytes.getBytes(), bytes.getBytes())
+ } else if !reflect.DeepEqual(bytes.getBytes(), test.bytes.getBytes()) {
+ t.Errorf("#%d:\nGOT:\n%#+v\nEXPECTED:\n%#+v", i, bytes.getBytes(), test.bytes.getBytes())
+ }
+ }
+}
diff --git a/ldapserver/client.go b/ldapserver/client.go
index 91a5980..3674ba4 100644
--- a/ldapserver/client.go
+++ b/ldapserver/client.go
@@ -6,7 +6,7 @@ import (
"sync"
"time"
- ldap "github.com/lor00x/goldap/message"
+ ldap "bottin/goldap"
)
type UserState interface{}
@@ -206,10 +206,14 @@ func (c *client) close() {
}
func (c *client) writeMessage(m *ldap.LDAPMessage) {
- data, _ := m.Write()
+ data, err := m.Write()
+ if err != nil {
+ Logger.Errorf("bottin: unable to marshal response message: %v", err)
+ }
//Logger.Printf(">>> %d - %s - hex=%x", c.Numero, m.ProtocolOpName(), data.Bytes())
Logger.Tracef(">>> [%d] %#v", c.Numero, m)
+ Logger.Tracef("%v", data.Bytes())
c.bw.Write(data.Bytes())
c.bw.Flush()
diff --git a/ldapserver/constants.go b/ldapserver/constants.go
index de6d229..a04ca43 100644
--- a/ldapserver/constants.go
+++ b/ldapserver/constants.go
@@ -1,6 +1,6 @@
package ldapserver
-import ldap "github.com/lor00x/goldap/message"
+import ldap "bottin/goldap"
// LDAP Application Codes
const (
diff --git a/ldapserver/message.go b/ldapserver/message.go
index f6e609f..7033e06 100644
--- a/ldapserver/message.go
+++ b/ldapserver/message.go
@@ -3,7 +3,7 @@ package ldapserver
import (
"fmt"
- ldap "github.com/lor00x/goldap/message"
+ ldap "bottin/goldap"
)
type Message struct {
diff --git a/ldapserver/packet.go b/ldapserver/packet.go
index 77b4926..a60a44a 100644
--- a/ldapserver/packet.go
+++ b/ldapserver/packet.go
@@ -5,7 +5,7 @@ import (
"errors"
"fmt"
- ldap "github.com/lor00x/goldap/message"
+ ldap "bottin/goldap"
)
type messagePacket struct {
@@ -141,6 +141,7 @@ func readBytes(conn *bufio.Reader, bytes *[]byte, length int) (b byte, err error
if n != length {
fmt.Errorf("%d bytes read instead of %d", n, length)
} else if err != nil {
+ fmt.Println("ooopsie an error occured here:", err)
return
}
*bytes = append(*bytes, newbytes...)
diff --git a/ldapserver/responsemessage.go b/ldapserver/responsemessage.go
index 23527b9..9dc0406 100644
--- a/ldapserver/responsemessage.go
+++ b/ldapserver/responsemessage.go
@@ -1,6 +1,6 @@
package ldapserver
-import ldap "github.com/lor00x/goldap/message"
+import ldap "bottin/goldap"
func NewBindResponse(resultCode int) ldap.BindResponse {
r := ldap.BindResponse{}
diff --git a/ldapserver/route.go b/ldapserver/route.go
index dfd5240..3ba5618 100644
--- a/ldapserver/route.go
+++ b/ldapserver/route.go
@@ -3,7 +3,7 @@ package ldapserver
import (
"strings"
- ldap "github.com/lor00x/goldap/message"
+ ldap "bottin/goldap"
)
// Constant to LDAP Request protocol Type names
diff --git a/main.go b/main.go
index 13d3da6..4e5abce 100644
--- a/main.go
+++ b/main.go
@@ -13,9 +13,9 @@ import (
"syscall"
ldap "bottin/ldapserver"
+ message "bottin/goldap"
consul "github.com/hashicorp/consul/api"
- message "github.com/lor00x/goldap/message"
log "github.com/sirupsen/logrus"
)
@@ -320,12 +320,19 @@ func (server *Server) init() error {
return err
}
- admin_pass := make([]byte, 8)
- _, err = rand.Read(admin_pass)
- if err != nil {
- return err
+
+ admin_pass_str, environnement_variable_exist := os.LookupEnv("BOTTIN_DEFAULT_ADMIN_PW")
+ if !environnement_variable_exist {
+ admin_pass := make([]byte, 8)
+ _, err = rand.Read(admin_pass)
+ if err != nil {
+ return err
+ }
+ admin_pass_str = base64.RawURLEncoding.EncodeToString(admin_pass)
+ } else {
+ server.logger.Debug("BOTTIN_DEFAULT_ADMIN_PW environment variable is set, using it for admin's password")
}
- admin_pass_str := base64.RawURLEncoding.EncodeToString(admin_pass)
+
admin_pass_hash := SSHAEncode([]byte(admin_pass_str))
admin_dn := "cn=admin," + server.config.Suffix
diff --git a/read.go b/read.go
index 7887c93..06e54b2 100644
--- a/read.go
+++ b/read.go
@@ -6,7 +6,7 @@ import (
ldap "bottin/ldapserver"
- message "github.com/lor00x/goldap/message"
+ message "bottin/goldap"
)
// Generic read utility functions ----------
diff --git a/test/bottin_test.go b/test/bottin_test.go
new file mode 100644
index 0000000..f4ed7fe
--- /dev/null
+++ b/test/bottin_test.go
@@ -0,0 +1,160 @@
+package main
+
+import (
+ "testing"
+)
+
+func TestAddThenDelete(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestConfirmAddAttributes(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Test search_attribute to confirm the Add
+ if ok, err := inst.CompareOurDataWithConsul(); !ok {
+ t.Error(err)
+ }
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+//Modifyrequest Test
+func TestModifyRequest(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Test modify all data (groups and users)
+ err = inst.ModifyRandomAllData()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestModifyRequestAndCheck(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Test modify all data (groups and users)
+ err = inst.ModifyRandomAllData()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Check if the data was modify on Consul
+ if ok, err := inst.CompareOurDataWithConsul(); !ok {
+ t.Error(err)
+ }
+
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestAddUserInGroup(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Add users in group
+ err = inst.AddAllUsersInGroup()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestDeleteGroupsAfterAddedUsers(t *testing.T) {
+ t.Parallel()
+ //SetUp - Create Users and Groups
+ inst, err := Init()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Add users in group
+ err = inst.AddAllUsersInGroup()
+ if err != nil {
+ t.Error(err)
+ }
+
+ //Delete the half groups
+ number := len(inst.dataGroups) / 2
+ err = inst.clean(inst.dataGroups[0:number])
+ if err != nil {
+ t.Error(err)
+ }
+ inst.dataGroups = inst.dataGroups[number:len(inst.dataGroups)]
+
+ //Check all the groups in memberOf exist
+ ok, err := inst.CheckMemberOf()
+ if err != nil {
+ t.Error(err)
+ }
+ if !ok {
+ t.Errorf("Found group in memberOf that isn't in Consul.")
+ }
+
+ //TearDown - Delete all the users and groups created
+ err = inst.Clean()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+//Example of paralellism Test
+func TestPrincipal(t *testing.T) {
+
+ t.Run("A=Add and delete", TestAddThenDelete)
+ t.Run("A=Modify", TestModifyRequest)
+ if !testing.Short() {
+ t.Run("B=Add attributes", TestConfirmAddAttributes)
+ t.Run("B=Modify and check", TestModifyRequestAndCheck)
+ t.Run("C=Add user in group", TestAddUserInGroup)
+ t.Run("C=Delete group", TestDeleteGroupsAfterAddedUsers)
+ }
+
+}
diff --git a/test/config.json.test b/test/config.json.test
new file mode 100644
index 0000000..bc1eeec
--- /dev/null
+++ b/test/config.json.test
@@ -0,0 +1,13 @@
+{
+ "suffix": "dc=deuxfleurs,dc=fr",
+ "bind": "127.0.0.1:1389",
+ "acl": [
+ "ANONYMOUS::bind:*,ou=users,dc=deuxfleurs,dc=fr:",
+ "ANONYMOUS::bind:cn=admin,dc=deuxfleurs,dc=fr:",
+ "*,dc=deuxfleurs,dc=fr::read:*:* !userpassword",
+ "*::read modify:SELF:*",
+ "cn=admin,dc=deuxfleurs,dc=fr::read add modify delete:*:*",
+ "*:cn=admin,ou=groups,dc=deuxfleurs,dc=fr:read add modify delete:*:*"
+ ]
+}
+
diff --git a/test/create.go b/test/create.go
new file mode 100644
index 0000000..4ad8106
--- /dev/null
+++ b/test/create.go
@@ -0,0 +1,281 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+ "sync"
+
+ "github.com/go-ldap/ldap/v3"
+ "github.com/sirupsen/logrus"
+)
+
+//Mux value, this value permits do not have two identicals values in the parallel instances
+type StoreAllCN struct {
+ mu sync.Mutex
+ cn map[string]struct{}
+}
+
+var allNames = StoreAllCN{cn: make(map[string]struct{})}
+
+//Type used for the tests
+type attributes struct {
+ Name string
+ Data []string
+}
+
+type data_DN struct {
+ DN string
+ Attributes []attributes
+}
+
+type instance struct {
+ numberUsers, numberGroups int
+ dataGroups, dataUsers []data_DN
+ logging *ldap.Conn
+}
+
+//Create a new object instance
+//With this instance, we can obtain an isolated container where
+//we have our users and groups. It allows to run tests in parallel.
+func NewInstance(numberUsers, numberGroups int) (*instance, error) {
+ l, err := Connect()
+ if err != nil {
+ return nil, err
+ }
+
+ logging.Level = logrus.InfoLevel
+
+ inst := instance{
+ numberUsers: numberUsers,
+ numberGroups: numberGroups,
+ dataGroups: []data_DN{},
+ dataUsers: []data_DN{},
+ logging: l,
+ }
+
+ err = inst.createOrganizationnalUnit()
+ if ldap.IsErrorWithCode(err, uint16(68)) {
+ logging.Warn("OrganizationnalUnit already created")
+ err = nil
+ }
+ if err != nil {
+ return nil, err
+ }
+
+ err = inst.CreateGroups()
+ if err != nil {
+ return nil, err
+ }
+ err = inst.CreateUsers()
+ if err != nil {
+ return nil, err
+ }
+
+ return &inst, nil
+}
+
+//Part: Created users or groups or OU
+
+func (inst *instance) createOrganizationnalUnit() error {
+ dn := []string{"ou=groups,dc=deuxfleurs,dc=fr", "ou=users,dc=deuxfleurs,dc=fr"}
+ attributes := []map[string][]string{{
+ "description": []string{"OrganizationalUnit qui regroupe tous les groupes"},
+ "objectclass": []string{"organizationalUnit", "top"},
+ "ou": []string{"groups"},
+ "structuralobjectclass": []string{"organizationalUnit"},
+ },
+ {
+ "description": []string{"OrganizationalUnit qui regroupe tous les users"},
+ "objectclass": []string{"organizationalUnit", "top"},
+ "ou": []string{"users"},
+ "structuralobjectclass": []string{"organizationalUnit"},
+ },
+ }
+
+ for index := range dn {
+ err := inst.Add_Request(dn[index], attributes[index])
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+
+}
+
+//Part: Create User or group
+
+func (inst *instance) CreateUsers() (err error) {
+
+ dn := "cn=%s,ou=users,dc=deuxfleurs,dc=fr"
+ attributes := map[string][]string{
+ "displayname": {},
+ "objectclass": {"inetOrgPerson", "organizationalPerson", "person", "top"},
+ "structuralobjectclass": {"inetOrgPerson"},
+ }
+
+ du, err := inst.create(dn, []string{"displayname"}, inst.numberUsers, attributes, inst.dataUsers)
+ if err == nil {
+ inst.dataUsers = du
+ }
+ return err
+}
+
+func (inst *instance) CreateGroups() error {
+ dn := "cn=%s,ou=groups,dc=deuxfleurs,dc=fr"
+ attributes := map[string][]string{
+ "description": {},
+ "objectclass": {"groupOfNames", "top"},
+ "structuralobjectclass": {"groupOfNames"},
+ }
+
+ dg, err := inst.create(dn, []string{"description"}, inst.numberGroups, attributes, inst.dataGroups)
+ if err == nil {
+ inst.dataGroups = dg
+ }
+
+ return err
+}
+
+//Hard Function: She does:
+//- generate an unique name
+//- store the Data of each AddRequest in instance struct
+//- send AddRequest to Bottin
+func (inst *instance) create(dn string, unique_attr []string, number int, attributes map[string][]string, data []data_DN) ([]data_DN, error) {
+ for i := 0; i < number; i++ {
+ name := inst.GenerateName()
+
+ datDn := data_DN{DN: fmt.Sprintf(dn, name)}
+
+ for _, value := range unique_attr {
+ attributes[value] = []string{name}
+ }
+
+ datDn.Attributes = MapAttToStruct(attributes)
+ data = append(data, datDn)
+
+ err := inst.Add_Request(fmt.Sprintf(dn, name), attributes)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return data, nil
+}
+
+//Part: clean
+
+func (inst *instance) Clean() error {
+ err := inst.CleanGroups()
+ if err != nil {
+ return err
+ }
+ err = inst.CleanUsers()
+ return err
+}
+
+func (inst *instance) CleanUsers() error {
+ err := inst.clean(inst.dataUsers)
+ if err != nil {
+ return err
+ }
+ inst.dataUsers = []data_DN{}
+ return err
+}
+
+func (inst *instance) CleanGroups() error {
+ err := inst.clean(inst.dataGroups)
+ if err != nil {
+ return err
+ }
+ inst.dataGroups = []data_DN{}
+ return err
+}
+
+func (inst *instance) clean(stock []data_DN) error {
+ logging.Debugf("Delete %d elements.", len(stock))
+ for _, value := range stock {
+ err := inst.Delete_Request(value.DN)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+//Part: Verify if a data_Dn is a group or an user
+func (inst *instance) VerifyUser(user data_DN) (bool, error) {
+ dn := "ou=users,dc=deuxfleurs,dc=fr"
+ cn := strings.Split(user.DN, ",")[0]
+ filter := fmt.Sprintf("(%s)", cn)
+
+ res, err := inst.Search_Request(dn, filter, []string{"cn"})
+
+ return len(res.Entries) == 1, err
+}
+
+func (inst *instance) VerifyGroup(group data_DN) (bool, error) {
+ dn := "ou=groups,dc=deuxfleurs,dc=fr"
+ cn := strings.Split(group.DN, ",")[0]
+ filter := fmt.Sprintf("(%s)", cn)
+
+ res, err := inst.Search_Request(dn, filter, []string{"cn"})
+
+ return len(res.Entries) == 1, err
+}
+
+//Part: Add user in a group
+func (inst *instance) AddUserInGroup(user, group data_DN) error {
+
+ err := inst.Modify_Request(group.DN, nil, nil, map[string][]string{
+ "member": {user.DN},
+ })
+ return err
+}
+
+func (inst *instance) AddUserSliceInGroup(users_cn []string, group_dn string) error {
+
+ err := inst.Modify_Request(group_dn, nil, nil, map[string][]string{
+ "member": users_cn,
+ })
+ return err
+}
+
+//Part: modify, add, delete data_DN struct
+
+func AddAtt(name string, data []string, dat data_DN) data_DN {
+ dat.Attributes = append(dat.Attributes, attributes{
+ Name: name,
+ Data: data,
+ })
+
+ logging.Debug(fmt.Sprintf("Attributes %s add from %s.", name, dat.DN))
+ return dat
+}
+
+func DelAtt(name string, dat data_DN) data_DN {
+ for index, value := range dat.Attributes {
+ if value.Name == name {
+ dat.Attributes[index] = dat.Attributes[len(dat.Attributes)-1]
+ //tmp := dat.Attributes[:len(dat.Attributes)-1]
+ dat.Attributes = []attributes{}
+ logging.Debugf("Attributes %s delete from %s.", name, dat.DN)
+ return dat
+ }
+ }
+ logging.Debugf("Can't delete attribute %s from %s.", name, dat.DN)
+ return dat
+}
+
+func ReplaceAtt(name string, data []string, dat data_DN) data_DN {
+ for index, value := range dat.Attributes {
+ if value.Name == name {
+ dat.Attributes[index] = attributes{
+ Name: name,
+ Data: data,
+ }
+ logging.Debugf("Replace attributes %s from %s succesful..", name, dat.DN)
+ return dat
+ }
+ }
+ logging.Debugf("Can't replace attributes %s from %s.", name, dat.DN)
+ return dat
+}
diff --git a/test/functionTest.go b/test/functionTest.go
new file mode 100644
index 0000000..e8d95ab
--- /dev/null
+++ b/test/functionTest.go
@@ -0,0 +1,173 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/go-ldap/ldap/v3"
+)
+
+const default_users, default_groups = 1000, 1000
+
+func Init() (*instance, error) {
+ inst, err := NewInstance(default_users, default_groups)
+ return inst, err
+}
+
+//Part to compare our datas
+func (inst *instance) CompareOurDataWithConsul() (bool, error) {
+ if ok, err := inst.VerifyOurData(inst.dataUsers); !ok {
+ return false, err
+ }
+ if ok, err := inst.VerifyOurData(inst.dataGroups); !ok {
+ return false, err
+ }
+ return true, nil
+}
+
+func (inst *instance) VerifyOurData(tabData []data_DN) (bool, error) {
+ for _, value := range tabData {
+ names := getNamesAtt(value)
+ cn := strings.Split(value.DN, ",")[0]
+ res, err := inst.Search_Request(value.DN, fmt.Sprintf("(&(%s))", cn), names)
+ if err != nil {
+ return false, err
+ }
+ if len(res.Entries) != 1 {
+ return false, fmt.Errorf("expected 1 entry, but found %d entry/ies", len(res.Entries))
+ }
+ if !Compare(value, res.Entries[0]) {
+ return false, fmt.Errorf("no match with the DN: %s", value.DN)
+ }
+ }
+ return true, nil
+}
+
+func Compare(dat data_DN, ent *ldap.Entry) bool {
+ for _, value := range dat.Attributes {
+ logging.Debugf("Attributes from %s is now: %s.", dat.DN, dat.Attributes)
+ entVal := GetAttributeValuesBottin(ent, value.Name)
+ logging.Debugf("Values of the Entry: attributName: %s, Values: %s.", value.Name, entVal)
+ if !CompareSliceString(entVal, value.Data) {
+ logging.Debugf("Values expected: %s, values found: %s.", value.Data, entVal)
+ return false
+ }
+ }
+ return true
+}
+
+//Part modify datas
+func (inst *instance) ModifyRandomAllData() error {
+ dg, err := inst.ModifyRandom(inst.dataGroups, []string{"description"})
+ if err != nil {
+ return err
+ } else {
+ inst.dataGroups = dg
+ }
+
+ dg, err = inst.ModifyRandom(inst.dataUsers, []string{"displayname"})
+ if err != nil {
+ return err
+ } else {
+ inst.dataUsers = dg
+ }
+ return nil
+}
+
+//Function which modify random way the attributes in attName of a data_DN's slice, it can delete, replace and delete
+//The function modify also in the dat object
+func (inst *instance) ModifyRandom(dat []data_DN, attName []string) ([]data_DN, error) {
+ for index, value := range dat {
+ del := make(map[string][]string)
+ add := make(map[string][]string)
+ replace := make(map[string][]string)
+
+ for _, att := range attName {
+
+ switch selNumber := R.Intn(3); selNumber {
+ case 0:
+ del[att] = []string{}
+ value = DelAtt(att, value)
+ logging.Debug(fmt.Sprintf("Delete the attribute %s of the DN %s.", att, value.DN))
+ case 1:
+ name := inst.GenerateName()
+ value = AddAtt(name, []string{name}, value)
+ add[name] = []string{name}
+ logging.Debug(fmt.Sprintf("Add the attribute %s with value %s of the DN %s.", name, name, value.DN))
+ case 2:
+ name := inst.GenerateName()
+ value = ReplaceAtt(att, []string{name}, value)
+ replace[att] = []string{name}
+ logging.Debug(fmt.Sprintf("Replace the attribute %s with value %s of the DN %s.", att, name, value.DN))
+ }
+
+ }
+
+ err := inst.Modify_Request(value.DN, add, del, replace)
+ if err != nil {
+ return dat, err
+ }
+ dat[index] = value
+ }
+ return dat, nil
+}
+
+//Add all users in a random group
+func (inst *instance) AddAllUsersInGroup() error {
+ for _, value := range inst.dataGroups {
+ valueRand := (len(inst.dataUsers) + 1) / 30
+ if valueRand == 0 {
+ valueRand = 1
+ }
+ numberOfMembers := R.Intn(valueRand) + 1
+ logging.Debugf("%s will be have %d members.", value.DN, numberOfMembers)
+
+ groupMemory := make(map[int]struct{})
+ users_cn := []string{}
+
+ for i := 0; i < numberOfMembers; i++ {
+ selectGroup := R.Intn(len(inst.dataUsers))
+ for _, ok := groupMemory[selectGroup]; ok; _, ok = groupMemory[selectGroup] {
+ selectGroup = R.Intn(len(inst.dataUsers))
+
+ logging.Debugf("Search an other member. The value is %d , and we have %d members available.", selectGroup, len(inst.dataUsers))
+ }
+ groupMemory[selectGroup] = struct{}{}
+
+ users_cn = append(users_cn, inst.dataGroups[selectGroup].DN)
+
+ }
+ err := inst.AddUserSliceInGroup(users_cn, value.DN)
+ if err != nil {
+ return err
+ }
+
+ }
+ return nil
+}
+
+//Check if the groups in memberOf exist in Consul
+func (inst *instance) CheckMemberOf() (bool, error) {
+ for _, value := range inst.dataUsers {
+ cn := strings.Split(value.DN, ",")[0]
+ res, err := inst.Search_Request(value.DN, fmt.Sprintf("(&(%s))", cn), []string{"memberOf"})
+ if err != nil {
+ return false, err
+ }
+ if len(res.Entries) != 1 {
+ return false, fmt.Errorf("expected 1 entry, but found %d entry/ies", len(res.Entries))
+ }
+ attValues := GetAttributeValuesBottin(res.Entries[0], "memberOf")
+ for _, dnGroup := range attValues {
+ logging.Debugf("Verify if the group %s exist...", dnGroup)
+ ok, err := inst.VerifyGroup(data_DN{DN: dnGroup})
+ if err != nil {
+ return false, err
+ }
+ if !ok {
+ return false, fmt.Errorf("don't found the group: %s", dnGroup)
+ }
+ }
+ }
+ return true, nil
+}
diff --git a/test/go.mod b/test/go.mod
new file mode 100644
index 0000000..74ed1ce
--- /dev/null
+++ b/test/go.mod
@@ -0,0 +1,8 @@
+module bottin/integration
+
+go 1.14
+
+require (
+ github.com/go-ldap/ldap/v3 v3.3.0
+ github.com/sirupsen/logrus v1.4.2
+)
diff --git a/test/go.sum b/test/go.sum
new file mode 100644
index 0000000..9c882d3
--- /dev/null
+++ b/test/go.sum
@@ -0,0 +1,26 @@
+github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c h1:/IBSNwUN8+eKzUzbJPqhK839ygXJ82sde8x3ogr6R28=
+github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
+github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
+github.com/go-ldap/ldap/v3 v3.3.0 h1:lwx+SJpgOHd8tG6SumBQZXCmNX51zM8B1cfxJ5gv4tQ=
+github.com/go-ldap/ldap/v3 v3.3.0/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
+golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/test/handler.go b/test/handler.go
new file mode 100644
index 0000000..fdee34f
--- /dev/null
+++ b/test/handler.go
@@ -0,0 +1,141 @@
+package main
+
+import (
+ "fmt"
+ "math/rand"
+ "os"
+
+ ldap "github.com/go-ldap/ldap/v3"
+ "github.com/sirupsen/logrus"
+)
+
+const maxlength_generateName, minlength_generateName = 25, 3
+
+const bindusername = "cn=admin,dc=deuxfleurs,dc=fr"
+const adresse = "127.0.0.1"
+const port = 1389
+
+var logging = logrus.New()
+
+const seed = 654258
+
+var R = rand.New(rand.NewSource(seed))
+
+var bindpassword = "sf7yO52NCuE"
+
+//Handler just to facilite the print error
+func PrintError(LDAPError error) {
+ if LDAPError != nil {
+ logging.Fatal(LDAPError)
+ }
+}
+
+//Generate an unique name, which store in all_names
+func (inst *instance) GenerateName() (name string) {
+ alphabet := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
+ "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
+ "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "é", "è", "ê", "ë", "à", "@", "â", "ä", "û", "ü", "ù", "$", "£", "%", "ø", "€"}
+ length := R.Intn(maxlength_generateName) + minlength_generateName
+
+ //Check if this name not exist already
+ //Lock thhis variable because she is hared with other goroutine
+ allNames.mu.Lock()
+ for only_one := true; only_one; _, only_one = allNames.cn[name] {
+ //Create the name
+ for i := 0; i < length; i++ {
+ name += alphabet[R.Intn(len(alphabet))]
+ }
+
+ }
+ //Add the new name in the map to store this one
+ allNames.cn[name] = struct{}{}
+ allNames.mu.Unlock()
+ logging.Debug(fmt.Sprintf("Name generated: %s.", name))
+ return
+}
+
+//Handler to around the bug with MessageId
+func (inst *instance) Reconnect() (err error) {
+ inst.logging.Close()
+ inst.logging, err = ldap.Dial("tcp", fmt.Sprintf("%s:%d", adresse, port))
+ if err != nil {
+ return
+ }
+ err = inst.logging.Bind(bindusername, bindpassword)
+ //logging.Debug("Reconnect succesful")
+ return
+}
+
+//Transform attributes in map format to the struct attributes
+func MapAttToStruct(att map[string][]string) []attributes {
+ resultat := []attributes{}
+ for key, value := range att {
+ logging.Debug(fmt.Sprintf("Transform: key: %s, values: %s to attributes struct.\n", key, value))
+ resultat = append(resultat, attributes{
+ Name: key,
+ Data: value,
+ })
+ }
+ return resultat
+}
+
+func Connect() (*ldap.Conn, error) {
+
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", adresse, port))
+ if err != nil {
+ return nil, err
+ }
+
+ if key, ok := os.LookupEnv("BOTTIN_DEFAULT_ADMIN_PW"); ok {
+ bindpassword = key
+ }
+ //l.Debug.Enable(true)
+ err = l.Bind(bindusername, bindpassword)
+ logging.Debug("Connection succesful")
+ return l, err
+}
+
+//Handler to get only attributes names
+func getNamesAtt(dat data_DN) []string {
+ resultat := []string{}
+ for _, values := range dat.Attributes {
+ resultat = append(resultat, values.Name)
+ }
+ return resultat
+}
+
+//Handler to compare slice string
+func CompareSliceString(string1, string2 []string) bool {
+ if len(string1) != len(string2) {
+ return false
+ } else {
+ for index := range string1 {
+ if string1[index] != string2[index] {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+//Handler to remove an element in slice string
+func DeleteElementSliceString(s string, sSlice []string) []string {
+
+ for index, value := range sSlice {
+ if value == s {
+ sSlice[index] = sSlice[len(sSlice)-1]
+ return sSlice[:len(sSlice)-1]
+ }
+ }
+ return sSlice
+}
+
+//Get attributes entry values bottin bug
+func GetAttributeValuesBottin(ent *ldap.Entry, name string) (res []string) {
+ for _, val := range ent.Attributes {
+ if val.Name == name {
+ res = append(res, val.Values...)
+ }
+ }
+ return
+}
diff --git a/test/request.go b/test/request.go
new file mode 100644
index 0000000..adde22e
--- /dev/null
+++ b/test/request.go
@@ -0,0 +1,59 @@
+package main
+
+import (
+ ldap "github.com/go-ldap/ldap/v3"
+)
+
+func (inst *instance) Add_Request(dn string, attributes map[string][]string) error {
+ //Create the AddRequest
+ req := ldap.NewAddRequest(dn, nil)
+ for key, value := range attributes {
+ req.Attribute(key, value)
+ }
+
+ //Send the request
+ err := inst.logging.Add(req)
+ return err
+
+}
+
+//Use enum to select Replace,Delete,Modify
+func (inst *instance) Modify_Request(dn string, add_attributes, delete_attributes, replace_attributes map[string][]string) error {
+ modifyReq := ldap.NewModifyRequest(dn, nil)
+
+ for key, value := range add_attributes {
+ modifyReq.Add(key, value)
+ }
+
+ for key, value := range delete_attributes {
+ modifyReq.Delete(key, value)
+ }
+
+ for key, value := range replace_attributes {
+ modifyReq.Replace(key, value)
+ }
+
+ err := inst.logging.Modify(modifyReq)
+ return err
+}
+
+func (inst *instance) Delete_Request(dn string) error {
+ del := ldap.NewDelRequest(dn, nil)
+
+ err := inst.logging.Del(del)
+ return err
+}
+
+func (inst *instance) Search_Request(dn, filter string, name_attributes []string) (*ldap.SearchResult, error) {
+ searchReq := ldap.NewSearchRequest(
+ dn,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
+ filter,
+ name_attributes,
+ nil,
+ )
+
+ res, err := inst.logging.Search(searchReq)
+ logging.Debugf("Search Request made with: dn: %s, filter: %s, attributes: %s. \n", dn, filter, name_attributes)
+ return res, err
+}
diff --git a/test/runner.sh b/test/runner.sh
new file mode 100755
index 0000000..04e42be
--- /dev/null
+++ b/test/runner.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+set -ex
+
+echo $BOTTIN_DEFAULT_ADMIN_PW
+consul agent -dev > /dev/null 2>&1 &
+sleep 2
+cp test/config.json.test config.json
+./bottin > /tmp/bottin.log 2>&1 &
+sleep 1
+./test/test -test.v -test.failfast -test.short -test.run TestPrincipal
+./test/test -test.v -test.failfast -test.run TestPrincipal/B=
+
+jobs
+kill %2
+kill %1
diff --git a/write.go b/write.go
index 482f971..2dd42c6 100644
--- a/write.go
+++ b/write.go
@@ -8,7 +8,7 @@ import (
ldap "bottin/ldapserver"
consul "github.com/hashicorp/consul/api"
- message "github.com/lor00x/goldap/message"
+ message "bottin/goldap"
)
// Generic item modification function --------