mirror of
https://github.com/netauth/ldap.git
synced 2026-11-03 11:43:44 -06:00
112 lines
3.8 KiB
Go
112 lines
3.8 KiB
Go
package ldap
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/ps78674/goldap/message"
|
|
ldap "github.com/ps78674/ldapserver"
|
|
)
|
|
|
|
// The goldap message types have unexported fields with no exported
|
|
// constructors, so test messages are built by hand-encoding the DER
|
|
// for the requests we care about and running them through the real
|
|
// decoder.
|
|
|
|
func berElement(tag byte, body ...[]byte) []byte {
|
|
length := 0
|
|
for _, b := range body {
|
|
length += len(b)
|
|
}
|
|
out := []byte{tag, byte(length)}
|
|
for _, b := range body {
|
|
out = append(out, b...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func berInteger(v byte) []byte { return berElement(0x02, []byte{v}) }
|
|
|
|
func berOctetString(s string) []byte { return berElement(0x04, []byte(s)) }
|
|
|
|
// berBindRequest encodes an LDAPMessage containing a simple
|
|
// BindRequest for the given DN and password.
|
|
func berBindRequest(dn, password string) []byte {
|
|
bind := berElement(0x60, // [APPLICATION 0] constructed
|
|
berInteger(3),
|
|
berOctetString(dn),
|
|
berElement(0x80, []byte(password)), // [0] simple, primitive
|
|
)
|
|
return berElement(0x30, berInteger(1), bind)
|
|
}
|
|
|
|
// berSearchRequest encodes an LDAPMessage containing a SearchRequest
|
|
// with an attribute-present filter on uid and no attribute selection.
|
|
func berSearchRequest(baseDN string) []byte {
|
|
search := berElement(0x63, // [APPLICATION 3] constructed
|
|
berOctetString(baseDN), // baseObject
|
|
berElement(0x0a, []byte{2}), // scope: wholeSubtree
|
|
berElement(0x0a, []byte{0}), // derefAliases: never
|
|
berInteger(0), // sizeLimit
|
|
berInteger(0), // timeLimit
|
|
berElement(0x01, []byte{0x00}), // typesOnly: false
|
|
berElement(0x87, []byte("uid")), // filter: (uid=*)
|
|
berElement(0x30), // attributes: empty selection
|
|
)
|
|
return berElement(0x30, berInteger(2), search)
|
|
}
|
|
|
|
// berEqualityFilter encodes an equalityMatch [3]
|
|
// AttributeValueAssertion filter and decodes it through the real BER
|
|
// reader. The filter types have unexported fields and no exported
|
|
// constructors, so this is the only way to build one for a test.
|
|
func berEqualityFilter(t *testing.T, attr, value string) message.Filter {
|
|
t.Helper()
|
|
return berDecodeFilter(t, berElement(0xa3, berOctetString(attr), berOctetString(value)))
|
|
}
|
|
|
|
// berPresentFilter encodes a present [7] AttributeDescription filter.
|
|
func berPresentFilter(t *testing.T, attr string) message.Filter {
|
|
t.Helper()
|
|
return berDecodeFilter(t, berElement(0x87, []byte(attr)))
|
|
}
|
|
|
|
// berOrFilter encodes an OR [1] of already-encoded filter elements.
|
|
func berOrFilter(t *testing.T, filters ...[]byte) message.Filter {
|
|
t.Helper()
|
|
return berDecodeFilter(t, berElement(0xa1, filters...))
|
|
}
|
|
|
|
// berRawEquality returns the encoded bytes of an equality match so it
|
|
// can be composed into a nested filter.
|
|
func berRawEquality(attr, value string) []byte {
|
|
return berElement(0xa3, berOctetString(attr), berOctetString(value))
|
|
}
|
|
|
|
// berDecodeFilter wraps a raw filter element in a minimal search
|
|
// request, decodes it and returns the parsed filter.
|
|
func berDecodeFilter(t *testing.T, filterElement []byte) message.Filter {
|
|
t.Helper()
|
|
search := berElement(0x63,
|
|
berOctetString(""), // baseObject
|
|
berElement(0x0a, []byte{2}), // scope wholeSubtree
|
|
berElement(0x0a, []byte{0}), // derefAliases never
|
|
berInteger(0), // sizeLimit
|
|
berInteger(0), // timeLimit
|
|
berElement(0x01, []byte{0}), // typesOnly false
|
|
filterElement, // filter
|
|
berElement(0x30), // empty attribute selection
|
|
)
|
|
m := mustDecode(t, berElement(0x30, berInteger(1), search))
|
|
r := m.GetSearchRequest()
|
|
return r.Filter()
|
|
}
|
|
|
|
func mustDecode(t *testing.T, raw []byte) *ldap.Message {
|
|
t.Helper()
|
|
m, err := message.ReadLDAPMessage(message.NewBytes(0, raw))
|
|
if err != nil {
|
|
t.Fatalf("decoding test message: %s", err)
|
|
}
|
|
return &ldap.Message{LDAPMessage: &m, Done: make(chan bool, 2)}
|
|
}
|