mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-08-04 11:55:01 -04:00
build(deps): bump github.com/go-ldap/ldap/v3 from 3.4.13 to 3.4.14
Bumps [github.com/go-ldap/ldap/v3](https://github.com/go-ldap/ldap) from 3.4.13 to 3.4.14. - [Release notes](https://github.com/go-ldap/ldap/releases) - [Commits](https://github.com/go-ldap/ldap/compare/v3.4.13...v3.4.14) --- updated-dependencies: - dependency-name: github.com/go-ldap/ldap/v3 dependency-version: 3.4.14 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
committed by
Ralf Haferkamp
parent
7c2cb14a80
commit
b9adb507f8
4
go.mod
4
go.mod
@@ -23,7 +23,7 @@ require (
|
||||
github.com/go-chi/chi/v5 v5.3.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-jose/go-jose/v3 v3.0.5
|
||||
github.com/go-ldap/ldap/v3 v3.4.13
|
||||
github.com/go-ldap/ldap/v3 v3.4.14
|
||||
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3
|
||||
github.com/go-micro/plugins/v4/client/grpc v1.2.1
|
||||
github.com/go-micro/plugins/v4/logger/zerolog v1.2.0
|
||||
@@ -203,7 +203,7 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/gdexlab/go-render v1.0.1 // indirect
|
||||
github.com/go-acme/lego/v4 v4.4.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.9.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.19.1 // indirect
|
||||
|
||||
8
go.sum
8
go.sum
@@ -370,8 +370,8 @@ github.com/go-acme/lego/v4 v4.4.0 h1:uHhU5LpOYQOdp3aDU+XY2bajseu8fuExphTL1Ss6/Fc
|
||||
github.com/go-acme/lego/v4 v4.4.0/go.mod h1:l3+tFUFZb590dWcqhWZegynUthtaHJbG2fevUpoOOE0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.4.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8 h1:H9AZkK22UOmfX8J84ubyaZxKJZ3FMHVwn8swoMML7iQ=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi/v5 v5.3.1 h1:3j4HZLGZQ3JpMCrPJF/Jl3mYJfWLKBfNJ6quurUGCf8=
|
||||
github.com/go-chi/chi/v5 v5.3.1/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto=
|
||||
@@ -402,8 +402,8 @@ github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj
|
||||
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
|
||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-ldap/ldap/v3 v3.1.7/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
|
||||
github.com/go-ldap/ldap/v3 v3.4.13 h1:+x1nG9h+MZN7h/lUi5Q3UZ0fJ1GyDQYbPvbuH38baDQ=
|
||||
github.com/go-ldap/ldap/v3 v3.4.13/go.mod h1:LxsGZV6vbaK0sIvYfsv47rfh4ca0JXokCoKjZxsszv0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.14 h1:D6PYdEgsaVzsXyr6w/yDC06Ria4uUhWm+Rb+er8lfAs=
|
||||
github.com/go-ldap/ldap/v3 v3.4.14/go.mod h1:S4eJUMUNjDkE0ZJtIZdybwyb03sGGLW6gxXT1Hs8VKA=
|
||||
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3 h1:sfz1YppV05y4sYaW7kXZtrocU/+vimnIWt4cxAYh7+o=
|
||||
github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3/go.mod h1:ZXFhGda43Z2TVbfGZefXyMJzsDHhCh0go3bZUcwTx7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
|
||||
33
vendor/github.com/go-asn1-ber/asn1-ber/ber.go
generated
vendored
33
vendor/github.com/go-asn1-ber/asn1-ber/ber.go
generated
vendored
@@ -19,6 +19,10 @@ import (
|
||||
// no limit.
|
||||
var MaxPacketLengthBytes int64 = math.MaxInt32
|
||||
|
||||
// MaxNestingDepth specifies the maximum allowed nesting depth when calling ReadPacket, DecodePacket, or
|
||||
// DecodePacketErr. Set to 0 for no limit.
|
||||
var MaxNestingDepth int = 1000
|
||||
|
||||
type Packet struct {
|
||||
Identifier
|
||||
Value interface{}
|
||||
@@ -218,7 +222,7 @@ func printPacket(out io.Writer, p *Packet, indent int, printBytes bool) {
|
||||
|
||||
// ReadPacket reads a single Packet from the reader.
|
||||
func ReadPacket(reader io.Reader) (*Packet, error) {
|
||||
p, _, err := readPacket(reader)
|
||||
p, _, err := readPacket(reader, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -278,7 +282,7 @@ func int64Length(i int64) (numBytes int) {
|
||||
// DecodePacket decodes the given bytes into a single Packet
|
||||
// If a decode error is encountered, nil is returned.
|
||||
func DecodePacket(data []byte) *Packet {
|
||||
p, _, _ := readPacket(bytes.NewBuffer(data))
|
||||
p, _, _ := readPacket(bytes.NewBuffer(data), 0)
|
||||
|
||||
return p
|
||||
}
|
||||
@@ -286,7 +290,7 @@ func DecodePacket(data []byte) *Packet {
|
||||
// DecodePacketErr decodes the given bytes into a single Packet
|
||||
// If a decode error is encountered, nil is returned.
|
||||
func DecodePacketErr(data []byte) (*Packet, error) {
|
||||
p, _, err := readPacket(bytes.NewBuffer(data))
|
||||
p, _, err := readPacket(bytes.NewBuffer(data), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -294,12 +298,20 @@ func DecodePacketErr(data []byte) (*Packet, error) {
|
||||
}
|
||||
|
||||
// readPacket reads a single Packet from the reader, returning the number of bytes read.
|
||||
func readPacket(reader io.Reader) (*Packet, int, error) {
|
||||
func readPacket(reader io.Reader, depth int) (*Packet, int, error) {
|
||||
if MaxNestingDepth > 0 && depth >= MaxNestingDepth {
|
||||
return nil, 0, fmt.Errorf("nesting depth %d exceeds maximum %d", depth, MaxNestingDepth)
|
||||
}
|
||||
|
||||
identifier, length, read, err := readHeader(reader)
|
||||
if err != nil {
|
||||
return nil, read, err
|
||||
}
|
||||
|
||||
if length != LengthIndefinite && MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes {
|
||||
return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes)
|
||||
}
|
||||
|
||||
p := &Packet{
|
||||
Identifier: identifier,
|
||||
}
|
||||
@@ -326,13 +338,19 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
|
||||
}
|
||||
|
||||
// Read the next packet
|
||||
child, r, err := readPacket(reader)
|
||||
child, r, err := readPacket(reader, depth+1)
|
||||
if err != nil {
|
||||
return nil, read, unexpectedEOF(err)
|
||||
}
|
||||
contentRead += r
|
||||
read += r
|
||||
|
||||
// Enforce the aggregate size limit for constructed packets. Indefinite length declares
|
||||
// no bound up front, so the content bytes are only known as they are read.
|
||||
if MaxPacketLengthBytes > 0 && int64(contentRead) > MaxPacketLengthBytes {
|
||||
return nil, read, fmt.Errorf("length %d greater than maximum %d", contentRead, MaxPacketLengthBytes)
|
||||
}
|
||||
|
||||
// Test is this is the EOC marker for our packet
|
||||
if isEOCPacket(child) {
|
||||
if length == LengthIndefinite {
|
||||
@@ -351,11 +369,6 @@ func readPacket(reader io.Reader) (*Packet, int, error) {
|
||||
return nil, read, errors.New("indefinite length used with primitive type")
|
||||
}
|
||||
|
||||
// Read definite-length content
|
||||
if MaxPacketLengthBytes > 0 && int64(length) > MaxPacketLengthBytes {
|
||||
return nil, read, fmt.Errorf("length %d greater than maximum %d", length, MaxPacketLengthBytes)
|
||||
}
|
||||
|
||||
var content []byte
|
||||
if length > 0 {
|
||||
// Read the content and limit it to the parsed length.
|
||||
|
||||
9
vendor/github.com/go-asn1-ber/asn1-ber/length.go
generated
vendored
9
vendor/github.com/go-asn1-ber/asn1-ber/length.go
generated
vendored
@@ -40,7 +40,7 @@ func readLength(reader io.Reader) (length int, read int, err error) {
|
||||
}
|
||||
|
||||
// Accumulate into a 64-bit variable
|
||||
var length64 int64
|
||||
var length64 uint64
|
||||
for i := 0; i < lengthBytes; i++ {
|
||||
b, err = readByte(reader)
|
||||
if err != nil {
|
||||
@@ -53,13 +53,14 @@ func readLength(reader io.Reader) (length int, read int, err error) {
|
||||
|
||||
// x.600, 8.1.3.5
|
||||
length64 <<= 8
|
||||
length64 |= int64(b)
|
||||
length64 |= uint64(b)
|
||||
}
|
||||
|
||||
// Cast to a platform-specific integer
|
||||
length = int(length64)
|
||||
// Ensure we didn't overflow
|
||||
if int64(length) != length64 {
|
||||
// Ensure we didn't overflow or wrap negative. Length octets are unsigned
|
||||
// (x.600, 8.1.3.5), so a negative result is unrepresentable, not indefinite.
|
||||
if length < 0 || uint64(length) != length64 {
|
||||
return 0, read, errors.New("long-form length overflow")
|
||||
}
|
||||
|
||||
|
||||
3
vendor/github.com/go-ldap/ldap/v3/add.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/add.go
generated
vendored
@@ -83,6 +83,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationAddResponse {
|
||||
err := GetLDAPError(packet)
|
||||
if err != nil {
|
||||
|
||||
77
vendor/github.com/go-ldap/ldap/v3/bind.go
generated
vendored
77
vendor/github.com/go-ldap/ldap/v3/bind.go
generated
vendored
@@ -3,13 +3,13 @@ package ldap
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
enchex "encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
|
||||
@@ -221,12 +221,15 @@ func (l *Conn) DigestMD5Bind(digestMD5BindRequest *DigestMD5BindRequest) (*Diges
|
||||
}
|
||||
|
||||
if len(params) > 0 {
|
||||
resp := computeResponse(
|
||||
resp, err := computeResponse(
|
||||
params,
|
||||
"ldap/"+strings.ToLower(digestMD5BindRequest.Host),
|
||||
digestMD5BindRequest.Username,
|
||||
digestMD5BindRequest.Password,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("compute digest-md5 response: %s", err)
|
||||
}
|
||||
packet = ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
|
||||
packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, l.nextMessageID(), "MessageID"))
|
||||
|
||||
@@ -291,12 +294,22 @@ func parseParams(str string) (map[string]string, error) {
|
||||
m := make(map[string]string)
|
||||
var key, value string
|
||||
var state int
|
||||
var escaped bool
|
||||
for i := 0; i <= len(str); i++ {
|
||||
switch state {
|
||||
case 0: // reading key
|
||||
if i == len(str) {
|
||||
return nil, fmt.Errorf("syntax error on %d", i)
|
||||
}
|
||||
// The digest-challenge is an RFC 2068 #rule (RFC 2831 section 2.1.1),
|
||||
// which permits optional linear whitespace around the comma directive
|
||||
// separators. Directive names are tokens that never contain
|
||||
// whitespace, so skip it here; otherwise a directive following
|
||||
// "..., name" is keyed with a leading space and the lookups in
|
||||
// computeResponse (realm, nonce, authzid) miss it.
|
||||
if str[i] == ' ' || str[i] == '\t' {
|
||||
continue
|
||||
}
|
||||
if str[i] != '=' {
|
||||
key += string(str[i])
|
||||
continue
|
||||
@@ -307,6 +320,14 @@ func parseParams(str string) (map[string]string, error) {
|
||||
m[key] = value
|
||||
break
|
||||
}
|
||||
// Linear whitespace outside a quoted string is not part of the
|
||||
// value: an unquoted value is a token and a quoted value's content
|
||||
// is read in the quoted state below. Skipping it lets a challenge
|
||||
// using the whitespace the #rule allows (e.g. `nonce="n" , qop=auth`)
|
||||
// parse the same as the unspaced form.
|
||||
if str[i] == ' ' || str[i] == '\t' {
|
||||
continue
|
||||
}
|
||||
switch str[i] {
|
||||
case ',':
|
||||
m[key] = value
|
||||
@@ -325,20 +346,34 @@ func parseParams(str string) (map[string]string, error) {
|
||||
if i == len(str) {
|
||||
return nil, fmt.Errorf("syntax error on %d", i)
|
||||
}
|
||||
if str[i] != '"' {
|
||||
switch {
|
||||
case escaped:
|
||||
// RFC 2831 section 7.1 quoted-pair: a backslash escapes the
|
||||
// following character, so the next byte is taken literally
|
||||
// (this is how a server sends a literal " or \ in a realm or
|
||||
// nonce).
|
||||
value += string(str[i])
|
||||
} else {
|
||||
escaped = false
|
||||
case str[i] == '\\':
|
||||
escaped = true
|
||||
case str[i] == '"':
|
||||
state = 1
|
||||
default:
|
||||
value += string(str[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func computeResponse(params map[string]string, uri, username, password string) string {
|
||||
func computeResponse(params map[string]string, uri, username, password string) (string, error) {
|
||||
nc := "00000001"
|
||||
qop := "auth"
|
||||
cnonce := enchex.EncodeToString(randomBytes(16))
|
||||
rb, err := randomBytes(16)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
cnonce := enchex.EncodeToString(rb)
|
||||
x := username + ":" + params["realm"] + ":" + password
|
||||
y := md5Hash([]byte(x))
|
||||
|
||||
@@ -361,14 +396,24 @@ func computeResponse(params map[string]string, uri, username, password string) s
|
||||
resp := enchex.EncodeToString(md5Hash([]byte(kd)))
|
||||
return fmt.Sprintf(
|
||||
`username="%s",realm="%s",nonce="%s",cnonce="%s",nc=00000001,qop=%s,digest-uri="%s",response=%s`,
|
||||
username,
|
||||
params["realm"],
|
||||
params["nonce"],
|
||||
quotedStringEscape(username),
|
||||
quotedStringEscape(params["realm"]),
|
||||
quotedStringEscape(params["nonce"]),
|
||||
cnonce,
|
||||
qop,
|
||||
uri,
|
||||
quotedStringEscape(uri),
|
||||
resp,
|
||||
)
|
||||
), nil
|
||||
}
|
||||
|
||||
// quotedStringEscape escapes the two characters that may not appear unescaped
|
||||
// inside a DIGEST-MD5 quoted string per RFC 2831 section 7.1: the backslash
|
||||
// and the double quote. The backslash is replaced first so the quotes escaped
|
||||
// afterwards are not doubled.
|
||||
func quotedStringEscape(s string) string {
|
||||
s = strings.ReplaceAll(s, `\`, `\\`)
|
||||
s = strings.ReplaceAll(s, `"`, `\"`)
|
||||
return s
|
||||
}
|
||||
|
||||
func md5Hash(b []byte) []byte {
|
||||
@@ -377,12 +422,12 @@ func md5Hash(b []byte) []byte {
|
||||
return hasher.Sum(nil)
|
||||
}
|
||||
|
||||
func randomBytes(len int) []byte {
|
||||
b := make([]byte, len)
|
||||
for i := 0; i < len; i++ {
|
||||
b[i] = byte(rand.Intn(256))
|
||||
func randomBytes(length int) ([]byte, error) {
|
||||
b := make([]byte, length)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b
|
||||
return b, nil
|
||||
}
|
||||
|
||||
var externalBindRequest = requestFunc(func(envelope *ber.Packet) error {
|
||||
|
||||
3
vendor/github.com/go-ldap/ldap/v3/compare.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/compare.go
generated
vendored
@@ -46,6 +46,9 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return false, fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationCompareResponse {
|
||||
err := GetLDAPError(packet)
|
||||
|
||||
|
||||
66
vendor/github.com/go-ldap/ldap/v3/conn.go
generated
vendored
66
vendor/github.com/go-ldap/ldap/v3/conn.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
@@ -112,7 +113,11 @@ type Conn struct {
|
||||
outstandingRequests uint
|
||||
messageMutex sync.Mutex
|
||||
|
||||
err error
|
||||
// errMutex guards err only. It is a leaf lock: processMessages and reader
|
||||
// record errors while another goroutine may hold messageMutex, so err must
|
||||
// not share messageMutex or those writers could deadlock.
|
||||
errMutex sync.Mutex
|
||||
err error
|
||||
}
|
||||
|
||||
var _ Client = &Conn{}
|
||||
@@ -160,10 +165,18 @@ type DialContext struct {
|
||||
|
||||
func (dc *DialContext) dial(u *url.URL) (net.Conn, error) {
|
||||
if u.Scheme == "ldapi" {
|
||||
if u.Path == "" || u.Path == "/" {
|
||||
u.Path = "/var/run/slapd/ldapi"
|
||||
// RFC 4516 (and draft-chu-ldap-ldapi) put the socket path in the
|
||||
// host component, percent-encoded; the path is an optional DN.
|
||||
// parseLDAPURL has already decoded the host. Accept the older
|
||||
// ldapi:///path form too so existing callers keep working.
|
||||
path := u.Host
|
||||
if path == "" {
|
||||
path = u.Path
|
||||
}
|
||||
return dc.dialer.Dial("unix", u.Path)
|
||||
if path == "" || path == "/" {
|
||||
path = "/var/run/slapd/ldapi"
|
||||
}
|
||||
return dc.dialer.Dial("unix", path)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
@@ -222,12 +235,33 @@ func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
// parseLDAPURL parses an LDAP URL. It defers to net/url for the common
|
||||
// ldap/ldaps/cldap schemes, but handles ldapi specially: the spec puts the
|
||||
// unix socket path in the host, percent-encoded with %2F, and net/url rejects
|
||||
// that as invalid. Pull the host out manually and decode it.
|
||||
func parseLDAPURL(addr string) (*url.URL, error) {
|
||||
const ldapi = "ldapi://"
|
||||
if !strings.HasPrefix(addr, ldapi) {
|
||||
return url.Parse(addr)
|
||||
}
|
||||
rest := addr[len(ldapi):]
|
||||
host, path := rest, ""
|
||||
if i := strings.IndexByte(rest, '/'); i >= 0 {
|
||||
host, path = rest[:i], rest[i:]
|
||||
}
|
||||
decodedHost, err := url.PathUnescape(host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ldapi: invalid host %q: %w", host, err)
|
||||
}
|
||||
return &url.URL{Scheme: "ldapi", Host: decodedHost, Path: path}, nil
|
||||
}
|
||||
|
||||
// DialURL connects to the given ldap URL.
|
||||
// The following schemas are supported: ldap://, ldaps://, ldapi://,
|
||||
// and cldap:// (RFC1798, deprecated but used by Active Directory).
|
||||
// On success a new Conn for the connection is returned.
|
||||
func DialURL(addr string, opts ...DialOpt) (*Conn, error) {
|
||||
u, err := url.Parse(addr)
|
||||
u, err := parseLDAPURL(addr)
|
||||
if err != nil {
|
||||
return nil, NewError(ErrorNetwork, err)
|
||||
}
|
||||
@@ -338,11 +372,21 @@ func (l *Conn) nextMessageID() int64 {
|
||||
// GetLastError returns the last recorded error from goroutines like processMessages and reader.
|
||||
// Only the last recorded error will be returned.
|
||||
func (l *Conn) GetLastError() error {
|
||||
l.messageMutex.Lock()
|
||||
defer l.messageMutex.Unlock()
|
||||
l.errMutex.Lock()
|
||||
defer l.errMutex.Unlock()
|
||||
return l.err
|
||||
}
|
||||
|
||||
// setError records the connection's last error. The background goroutines that
|
||||
// call it (processMessages, reader, the per-request timeout helper and the
|
||||
// SearchAsync worker) run concurrently with callers of GetLastError, so the
|
||||
// write must take the mutex the getter reads under.
|
||||
func (l *Conn) setError(err error) {
|
||||
l.errMutex.Lock()
|
||||
defer l.errMutex.Unlock()
|
||||
l.err = err
|
||||
}
|
||||
|
||||
// StartTLS sends the command to start a TLS session and then creates a new TLS Client
|
||||
func (l *Conn) StartTLS(config *tls.Config) error {
|
||||
if l.isTLS {
|
||||
@@ -491,7 +535,7 @@ func (l *Conn) sendProcessMessage(message *messagePacket) bool {
|
||||
func (l *Conn) processMessages() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
l.err = fmt.Errorf("ldap: recovered panic in processMessages: %v", err)
|
||||
l.setError(fmt.Errorf("ldap: recovered panic in processMessages: %v", err))
|
||||
}
|
||||
for messageID, msgCtx := range l.messageContexts {
|
||||
// If we are closing due to an error, inform anyone who
|
||||
@@ -541,7 +585,7 @@ func (l *Conn) processMessages() {
|
||||
timer := time.NewTimer(time.Duration(requestTimeout))
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
l.err = fmt.Errorf("ldap: recovered panic in RequestTimeout: %v", err)
|
||||
l.setError(fmt.Errorf("ldap: recovered panic in RequestTimeout: %v", err))
|
||||
}
|
||||
|
||||
timer.Stop()
|
||||
@@ -563,7 +607,7 @@ func (l *Conn) processMessages() {
|
||||
if msgCtx, ok := l.messageContexts[message.MessageID]; ok {
|
||||
msgCtx.sendResponse(&PacketResponse{message.Packet, nil}, time.Duration(l.getTimeout()))
|
||||
} else {
|
||||
l.err = fmt.Errorf("ldap: received unexpected message %d, %v", message.MessageID, l.IsClosing())
|
||||
l.setError(fmt.Errorf("ldap: received unexpected message %d, %v", message.MessageID, l.IsClosing()))
|
||||
l.Debug.PrintPacket(message.Packet)
|
||||
}
|
||||
case MessageTimeout:
|
||||
@@ -590,7 +634,7 @@ func (l *Conn) reader() {
|
||||
cleanstop := false
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
l.err = fmt.Errorf("ldap: recovered panic in reader: %v", err)
|
||||
l.setError(fmt.Errorf("ldap: recovered panic in reader: %v", err))
|
||||
}
|
||||
if !cleanstop {
|
||||
l.Close()
|
||||
|
||||
111
vendor/github.com/go-ldap/ldap/v3/control.go
generated
vendored
111
vendor/github.com/go-ldap/ldap/v3/control.go
generated
vendored
@@ -565,12 +565,20 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
case 1:
|
||||
// just type, no criticality or value
|
||||
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
||||
ControlType = packet.Children[0].Value.(string)
|
||||
ct, ok := packet.Children[0].Value.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("control type is not a string: %T", packet.Children[0].Value)
|
||||
}
|
||||
ControlType = ct
|
||||
|
||||
case 2:
|
||||
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
||||
if packet.Children[0].Value != nil {
|
||||
ControlType = packet.Children[0].Value.(string)
|
||||
ct, ok := packet.Children[0].Value.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("control type is not a string: %T", packet.Children[0].Value)
|
||||
}
|
||||
ControlType = ct
|
||||
} else if packet.Children[0].Data != nil {
|
||||
ControlType = packet.Children[0].Data.String()
|
||||
} else {
|
||||
@@ -579,9 +587,9 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
|
||||
// Children[1] could be criticality or value (both are optional)
|
||||
// duck-type on whether this is a boolean
|
||||
if _, ok := packet.Children[1].Value.(bool); ok {
|
||||
if crit, ok := packet.Children[1].Value.(bool); ok {
|
||||
packet.Children[1].Description = "Criticality"
|
||||
Criticality = packet.Children[1].Value.(bool)
|
||||
Criticality = crit
|
||||
} else {
|
||||
packet.Children[1].Description = "Control Value"
|
||||
value = packet.Children[1]
|
||||
@@ -589,10 +597,18 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
|
||||
case 3:
|
||||
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
|
||||
ControlType = packet.Children[0].Value.(string)
|
||||
ct, ok := packet.Children[0].Value.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("control type is not a string: %T", packet.Children[0].Value)
|
||||
}
|
||||
ControlType = ct
|
||||
|
||||
packet.Children[1].Description = "Criticality"
|
||||
Criticality = packet.Children[1].Value.(bool)
|
||||
crit, ok := packet.Children[1].Value.(bool)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("criticality is not a bool: %T", packet.Children[1].Value)
|
||||
}
|
||||
Criticality = crit
|
||||
|
||||
packet.Children[2].Description = "Control Value"
|
||||
value = packet.Children[2]
|
||||
@@ -606,6 +622,9 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
case ControlTypeManageDsaIT:
|
||||
return NewControlManageDsaIT(Criticality), nil
|
||||
case ControlTypePaging:
|
||||
if value == nil {
|
||||
return nil, fmt.Errorf("paging control value is missing")
|
||||
}
|
||||
value.Description += " (Paging)"
|
||||
c := new(ControlPaging)
|
||||
if value.Value != nil {
|
||||
@@ -617,11 +636,21 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
value.Value = nil
|
||||
value.AppendChild(valueChildren)
|
||||
}
|
||||
if len(value.Children) == 0 {
|
||||
return nil, fmt.Errorf("paging control value is empty")
|
||||
}
|
||||
value = value.Children[0]
|
||||
value.Description = "Search Control Value"
|
||||
if len(value.Children) < 2 {
|
||||
return nil, fmt.Errorf("paging control value has %d children, expected 2", len(value.Children))
|
||||
}
|
||||
value.Children[0].Description = "Paging Size"
|
||||
value.Children[1].Description = "Cookie"
|
||||
c.PagingSize = uint32(value.Children[0].Value.(int64))
|
||||
pagingSize, ok := value.Children[0].Value.(int64)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("paging size is not an integer: %T", value.Children[0].Value)
|
||||
}
|
||||
c.PagingSize = uint32(pagingSize)
|
||||
c.Cookie = value.Children[1].Data.Bytes()
|
||||
value.Children[1].Value = c.Cookie
|
||||
return c, nil
|
||||
@@ -729,7 +758,16 @@ func DecodeControl(packet *ber.Packet) (Control, error) {
|
||||
c.ControlType = ControlType
|
||||
c.Criticality = Criticality
|
||||
if value != nil {
|
||||
c.ControlValue = value.Value.(string)
|
||||
// A non-conforming or malicious server can send a non-string
|
||||
// (or nil) value here; the previous unchecked cast panicked
|
||||
// the calling goroutine, see #561. Fall back to the raw bytes
|
||||
// when the value isn't a string so we surface an error
|
||||
// instead of crashing.
|
||||
if s, ok := value.Value.(string); ok {
|
||||
c.ControlValue = s
|
||||
} else if value.Data != nil {
|
||||
c.ControlValue = value.Data.String()
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
@@ -921,28 +959,44 @@ func (c *ControlServerSideSorting) GetControlType() string {
|
||||
}
|
||||
|
||||
func NewControlServerSideSorting(value *ber.Packet) (*ControlServerSideSorting, error) {
|
||||
sortKeys := []*SortKey{}
|
||||
val, err := ber.DecodePacketErr(value.Data.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode packet err: %s", err)
|
||||
}
|
||||
|
||||
val := value.Children[1].Children
|
||||
|
||||
if len(val) != 1 {
|
||||
if len(val.Children) == 0 {
|
||||
return nil, fmt.Errorf("no sequence value in packet")
|
||||
}
|
||||
|
||||
sequences := val[0].Children
|
||||
var sortKeys []*SortKey
|
||||
|
||||
for i, sequence := range sequences {
|
||||
sortKey := new(SortKey)
|
||||
|
||||
if len(sequence.Children) < 2 {
|
||||
return nil, fmt.Errorf("attributeType or matchingRule is missing from sequence %d", i)
|
||||
for i, sequence := range val.Children {
|
||||
if len(sequence.Children) < 1 || len(sequence.Children) > 3 {
|
||||
return nil, fmt.Errorf("attributeType is missing from sequence %d", i)
|
||||
}
|
||||
|
||||
sortKey.AttributeType = sequence.Children[0].Value.(string)
|
||||
sortKey.MatchingRule = sequence.Children[1].Value.(string)
|
||||
sortKey := new(SortKey)
|
||||
|
||||
if len(sequence.Children) == 3 {
|
||||
sortKey.Reverse = sequence.Children[2].Value.(bool)
|
||||
for _, child := range sequence.Children {
|
||||
switch {
|
||||
case child.ClassType == ber.ClassUniversal && child.Tag == ber.TagOctetString:
|
||||
// A constructed-form OCTET STRING matches this case but leaves
|
||||
// Value nil; guard the assertion so a malformed attributeType is
|
||||
// rejected below rather than panicking.
|
||||
if attrType, ok := child.Value.(string); ok {
|
||||
sortKey.AttributeType = attrType
|
||||
}
|
||||
|
||||
case child.ClassType == ber.ClassContext && child.Tag == 0:
|
||||
sortKey.MatchingRule = child.Data.String()
|
||||
|
||||
case child.ClassType == ber.ClassContext && child.Tag == 1:
|
||||
b := child.Data.Bytes()
|
||||
sortKey.Reverse = len(b) > 0 && b[0] != 0
|
||||
}
|
||||
}
|
||||
if sortKey.AttributeType == "" {
|
||||
return nil, fmt.Errorf("attributeType is missing from sequence %d", i)
|
||||
}
|
||||
|
||||
sortKeys = append(sortKeys, sortKey)
|
||||
@@ -959,7 +1013,6 @@ func (c *ControlServerSideSorting) Encode() *ber.Packet {
|
||||
packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
|
||||
control := ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.GetControlType(), "Control Type")
|
||||
|
||||
value := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value")
|
||||
seqs := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "SortKeyList")
|
||||
|
||||
for _, f := range c.SortKeys {
|
||||
@@ -968,9 +1021,11 @@ func (c *ControlServerSideSorting) Encode() *ber.Packet {
|
||||
seq.AppendChild(
|
||||
ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, f.AttributeType, "attributeType"),
|
||||
)
|
||||
seq.AppendChild(
|
||||
ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, f.MatchingRule, "orderingRule"),
|
||||
)
|
||||
if f.MatchingRule != "" {
|
||||
seq.AppendChild(
|
||||
ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, f.MatchingRule, "orderingRule"),
|
||||
)
|
||||
}
|
||||
if f.Reverse {
|
||||
seq.AppendChild(
|
||||
ber.NewBoolean(ber.ClassContext, ber.TypePrimitive, 1, f.Reverse, "reverseOrder"),
|
||||
@@ -980,7 +1035,7 @@ func (c *ControlServerSideSorting) Encode() *ber.Packet {
|
||||
seqs.AppendChild(seq)
|
||||
}
|
||||
|
||||
value.AppendChild(seqs)
|
||||
value := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, string(seqs.Bytes()), "Control Value")
|
||||
|
||||
packet.AppendChild(control)
|
||||
packet.AppendChild(value)
|
||||
@@ -1060,6 +1115,8 @@ func NewControlServerSideSortingResult(pkt *ber.Packet) (*ControlServerSideSorti
|
||||
return nil, err
|
||||
}
|
||||
|
||||
control.Result = ControlServerSideSortingCode(codeInt)
|
||||
|
||||
return control, nil
|
||||
}
|
||||
|
||||
|
||||
3
vendor/github.com/go-ldap/ldap/v3/del.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/del.go
generated
vendored
@@ -52,6 +52,9 @@ func (l *Conn) Del(delRequest *DelRequest) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationDelResponse {
|
||||
err := GetLDAPError(packet)
|
||||
if err != nil {
|
||||
|
||||
61
vendor/github.com/go-ldap/ldap/v3/dn.go
generated
vendored
61
vendor/github.com/go-ldap/ldap/v3/dn.go
generated
vendored
@@ -1,14 +1,16 @@
|
||||
package ldap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
ber "github.com/go-asn1-ber/asn1-ber"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
ber "github.com/go-asn1-ber/asn1-ber"
|
||||
)
|
||||
|
||||
// AttributeTypeAndValue represents an attributeTypeAndValue from https://tools.ietf.org/html/rfc4514
|
||||
@@ -94,9 +96,21 @@ func (d *DN) String() string {
|
||||
func stripLeadingAndTrailingSpaces(inVal string) string {
|
||||
noSpaces := strings.Trim(inVal, " ")
|
||||
|
||||
// Re-add the trailing space if it was an escaped space
|
||||
if len(noSpaces) > 0 && noSpaces[len(noSpaces)-1] == '\\' && inVal[len(inVal)-1] == ' ' {
|
||||
noSpaces = noSpaces + " "
|
||||
// Re-add the trailing space only if it was escaped. A trailing space is
|
||||
// escaped when it is preceded by an odd number of backslashes; an even
|
||||
// number leaves the space unescaped (each "\\" is a literal backslash), so
|
||||
// the space is insignificant and stays stripped. Counting only the final
|
||||
// backslash treated "\\ " (a literal backslash plus an insignificant
|
||||
// space) as an escaped space, keeping a spurious trailing space in the
|
||||
// decoded value.
|
||||
if len(noSpaces) > 0 && inVal[len(inVal)-1] == ' ' {
|
||||
backslashes := 0
|
||||
for i := len(noSpaces) - 1; i >= 0 && noSpaces[i] == '\\'; i-- {
|
||||
backslashes++
|
||||
}
|
||||
if backslashes%2 == 1 {
|
||||
noSpaces = noSpaces + " "
|
||||
}
|
||||
}
|
||||
|
||||
return noSpaces
|
||||
@@ -116,6 +130,16 @@ func decodeString(str string) (string, error) {
|
||||
// If the character is not an escape character, just add it to the
|
||||
// builder and continue
|
||||
if char != '\\' {
|
||||
// RFC 4514 section 2.4: these characters must appear escaped
|
||||
// (either as "\X" or as "\XX" hex) when present in an AttributeValue.
|
||||
// Reject the raw form here so that callers don't silently accept
|
||||
// input that violates the grammar.
|
||||
switch char {
|
||||
case '"', ';', '<', '>':
|
||||
return "", fmt.Errorf("got unescaped character: '%s'", string(char))
|
||||
case 0:
|
||||
return "", fmt.Errorf("got unescaped NULL character")
|
||||
}
|
||||
builder.WriteRune(char)
|
||||
continue
|
||||
}
|
||||
@@ -233,10 +257,18 @@ func decodeEncodedString(str string) (string, error) {
|
||||
return "", fmt.Errorf("failed to decode BER encoding: %w", err)
|
||||
}
|
||||
|
||||
packet, err := ber.DecodePacketErr(decoded)
|
||||
// RFC 4514 section 2.4: the value following '#' is the hex encoding of the
|
||||
// BER encoding of a single AttributeValue. Read exactly one element and
|
||||
// reject any leftover octets, otherwise bytes appended after the value are
|
||||
// silently dropped and two different DN strings decode to the same value.
|
||||
reader := bytes.NewBuffer(decoded)
|
||||
packet, err := ber.ReadPacket(reader)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode BER encoding: %w", err)
|
||||
}
|
||||
if reader.Len() != 0 {
|
||||
return "", errors.New("failed to decode BER encoding: trailing bytes after value")
|
||||
}
|
||||
|
||||
return packet.Data.String(), nil
|
||||
}
|
||||
@@ -352,10 +384,19 @@ func (r *RelativeDN) Equal(other *RelativeDN) bool {
|
||||
}
|
||||
|
||||
func (r *RelativeDN) hasAllAttributes(attrs []*AttributeTypeAndValue) bool {
|
||||
// Each candidate attribute must match a distinct attribute of the receiver.
|
||||
// Without consuming matches this is a set containment test, so a multi-valued
|
||||
// RDN that repeats an attributeTypeAndValue would compare equal to one that
|
||||
// repeats a different pair the same number of times.
|
||||
matched := make([]bool, len(r.Attributes))
|
||||
for _, attr := range attrs {
|
||||
found := false
|
||||
for _, myattr := range r.Attributes {
|
||||
for i, myattr := range r.Attributes {
|
||||
if matched[i] {
|
||||
continue
|
||||
}
|
||||
if myattr.Equal(attr) {
|
||||
matched[i] = true
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@@ -415,10 +456,16 @@ func (r *RelativeDN) EqualFold(other *RelativeDN) bool {
|
||||
}
|
||||
|
||||
func (r *RelativeDN) hasAllAttributesFold(attrs []*AttributeTypeAndValue) bool {
|
||||
// See hasAllAttributes: matches are consumed so multiplicity is respected.
|
||||
matched := make([]bool, len(r.Attributes))
|
||||
for _, attr := range attrs {
|
||||
found := false
|
||||
for _, myattr := range r.Attributes {
|
||||
for i, myattr := range r.Attributes {
|
||||
if matched[i] {
|
||||
continue
|
||||
}
|
||||
if myattr.EqualFold(attr) {
|
||||
matched[i] = true
|
||||
found = true
|
||||
break
|
||||
}
|
||||
|
||||
8
vendor/github.com/go-ldap/ldap/v3/extended.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/extended.go
generated
vendored
@@ -89,6 +89,14 @@ func (l *Conn) Extended(er *ExtendedRequest) (*ExtendedResponse, error) {
|
||||
}
|
||||
|
||||
for _, child := range extResp.Children {
|
||||
// responseName [10] and responseValue [11] are context-class and
|
||||
// optional. The preceding resultCode is a universal ENUMERATED whose
|
||||
// tag number (10) is the same as responseName, so a child must be
|
||||
// matched on its class as well, otherwise the resultCode is read as
|
||||
// the responseName whenever the server omits the latter.
|
||||
if child.ClassType != ber.ClassContext {
|
||||
continue
|
||||
}
|
||||
switch child.Tag {
|
||||
case ber.TagEnumerated:
|
||||
response.Name = child.Data.String()
|
||||
|
||||
16
vendor/github.com/go-ldap/ldap/v3/filter.go
generated
vendored
16
vendor/github.com/go-ldap/ldap/v3/filter.go
generated
vendored
@@ -131,7 +131,7 @@ func DecompileFilter(packet *ber.Packet) (_ string, err error) {
|
||||
buf.WriteString(childStr)
|
||||
|
||||
case FilterSubstrings:
|
||||
buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[0].Data.Bytes())))
|
||||
buf.WriteByte('=')
|
||||
for i, child := range packet.Children[1].Children {
|
||||
if i == 0 && child.Tag != FilterSubstringsInitial {
|
||||
@@ -143,22 +143,22 @@ func DecompileFilter(packet *ber.Packet) (_ string, err error) {
|
||||
}
|
||||
}
|
||||
case FilterEqualityMatch:
|
||||
buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[0].Data.Bytes())))
|
||||
buf.WriteByte('=')
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
|
||||
case FilterGreaterOrEqual:
|
||||
buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[0].Data.Bytes())))
|
||||
buf.WriteString(">=")
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
|
||||
case FilterLessOrEqual:
|
||||
buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[0].Data.Bytes())))
|
||||
buf.WriteString("<=")
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
|
||||
case FilterPresent:
|
||||
buf.WriteString(ber.DecodeString(packet.Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Data.Bytes())))
|
||||
buf.WriteString("=*")
|
||||
case FilterApproxMatch:
|
||||
buf.WriteString(ber.DecodeString(packet.Children[0].Data.Bytes()))
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[0].Data.Bytes())))
|
||||
buf.WriteString("~=")
|
||||
buf.WriteString(EscapeFilter(ber.DecodeString(packet.Children[1].Data.Bytes())))
|
||||
case FilterExtensibleMatch:
|
||||
@@ -181,14 +181,14 @@ func DecompileFilter(packet *ber.Packet) (_ string, err error) {
|
||||
}
|
||||
|
||||
if len(attr) > 0 {
|
||||
buf.WriteString(attr)
|
||||
buf.WriteString(EscapeFilter(attr))
|
||||
}
|
||||
if dnAttributes {
|
||||
buf.WriteString(":dn")
|
||||
}
|
||||
if len(matchingRule) > 0 {
|
||||
buf.WriteString(":")
|
||||
buf.WriteString(matchingRule)
|
||||
buf.WriteString(EscapeFilter(matchingRule))
|
||||
}
|
||||
buf.WriteString(":=")
|
||||
buf.WriteString(EscapeFilter(value))
|
||||
|
||||
3
vendor/github.com/go-ldap/ldap/v3/moddn.go
generated
vendored
3
vendor/github.com/go-ldap/ldap/v3/moddn.go
generated
vendored
@@ -89,6 +89,9 @@ func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationModifyDNResponse {
|
||||
err := GetLDAPError(packet)
|
||||
if err != nil {
|
||||
|
||||
7
vendor/github.com/go-ldap/ldap/v3/modify.go
generated
vendored
7
vendor/github.com/go-ldap/ldap/v3/modify.go
generated
vendored
@@ -121,6 +121,9 @@ func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationModifyResponse {
|
||||
err := GetLDAPError(packet)
|
||||
if err != nil {
|
||||
@@ -159,6 +162,10 @@ func (l *Conn) ModifyWithResult(modifyRequest *ModifyRequest) (*ModifyResult, er
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return nil, fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
|
||||
switch packet.Children[1].Tag {
|
||||
case ApplicationModifyResponse:
|
||||
if err = GetLDAPError(packet); err != nil {
|
||||
|
||||
8
vendor/github.com/go-ldap/ldap/v3/passwdmodify.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/passwdmodify.go
generated
vendored
@@ -93,6 +93,9 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||
|
||||
result := &PasswordModifyResult{}
|
||||
|
||||
if len(packet.Children) < 2 {
|
||||
return nil, fmt.Errorf("ldap: malformed response: expected at least 2 children, got %d", len(packet.Children))
|
||||
}
|
||||
if packet.Children[1].Tag == ApplicationExtendedResponse {
|
||||
if err = GetLDAPError(packet); err != nil {
|
||||
result.Referral = getReferral(err, packet)
|
||||
@@ -106,7 +109,10 @@ func (l *Conn) PasswordModify(passwordModifyRequest *PasswordModifyRequest) (*Pa
|
||||
extendedResponse := packet.Children[1]
|
||||
for _, child := range extendedResponse.Children {
|
||||
if child.Tag == ber.TagEmbeddedPDV {
|
||||
passwordModifyResponseValue := ber.DecodePacket(child.Data.Bytes())
|
||||
passwordModifyResponseValue, err := ber.DecodePacketErr(child.Data.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ldap: failed to decode PasswordModifyResponseValue: %s", err)
|
||||
}
|
||||
if len(passwordModifyResponseValue.Children) == 1 {
|
||||
if passwordModifyResponseValue.Children[0].Tag == ber.TagEOC {
|
||||
result.GeneratedPassword = ber.DecodeString(passwordModifyResponseValue.Children[0].Data.Bytes())
|
||||
|
||||
8
vendor/github.com/go-ldap/ldap/v3/request.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/request.go
generated
vendored
@@ -101,6 +101,14 @@ func getReferral(err error, packet *ber.Packet) (referral string) {
|
||||
continue
|
||||
}
|
||||
|
||||
// A Referral is a SEQUENCE SIZE (1..MAX) OF uri, but a non-conforming or
|
||||
// malicious server can send an empty SEQUENCE. Skip it instead of indexing
|
||||
// child.Children[0], which would panic the goroutine that called Modify or
|
||||
// PasswordModify.
|
||||
if len(child.Children) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if referral, ok = child.Children[0].Value.(string); ok {
|
||||
return referral
|
||||
}
|
||||
|
||||
56
vendor/github.com/go-ldap/ldap/v3/response.go
generated
vendored
56
vendor/github.com/go-ldap/ldap/v3/response.go
generated
vendored
@@ -66,12 +66,28 @@ func (r *searchResponse) Next() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// send enqueues a result on the result channel, giving up when ctx is
|
||||
// cancelled so an abandoned consumer cannot block the search goroutine
|
||||
// forever on a full buffer. It reports whether the result was handed off to
|
||||
// the channel; a true return does not mean the consumer received it. The
|
||||
// give-up is best-effort: if ctx is already cancelled but buffer space is
|
||||
// available, the result may still be enqueued. Callers that terminate the
|
||||
// stream regardless of the outcome may ignore the return value.
|
||||
func (r *searchResponse) send(ctx context.Context, res *SearchSingleResult) bool {
|
||||
select {
|
||||
case r.ch <- res:
|
||||
return true
|
||||
case <-ctx.Done():
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest) {
|
||||
go func() {
|
||||
defer func() {
|
||||
close(r.ch)
|
||||
if err := recover(); err != nil {
|
||||
r.conn.err = fmt.Errorf("ldap: recovered panic in searchResponse: %v", err)
|
||||
r.conn.setError(fmt.Errorf("ldap: recovered panic in searchResponse: %v", err))
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -84,14 +100,14 @@ func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest
|
||||
// encode search request
|
||||
err := searchRequest.appendTo(packet)
|
||||
if err != nil {
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
r.conn.Debug.PrintPacket(packet)
|
||||
|
||||
msgCtx, err := r.conn.sendMessage(packet)
|
||||
if err != nil {
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
defer r.conn.finishMessage(msgCtx)
|
||||
@@ -106,19 +122,19 @@ func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest
|
||||
case packetResponse, ok := <-msgCtx.responses:
|
||||
if !ok {
|
||||
err := NewError(ErrorNetwork, errors.New("ldap: response channel closed"))
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
packet, err = packetResponse.ReadPacket()
|
||||
r.conn.Debug.Printf("%d: got response %p", msgCtx.id, packet)
|
||||
if err != nil {
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
|
||||
if r.conn.Debug {
|
||||
if err := addLDAPDescriptions(packet); err != nil {
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
ber.PrintPacket(packet)
|
||||
@@ -133,22 +149,26 @@ func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest
|
||||
},
|
||||
}
|
||||
if len(packet.Children) != 3 {
|
||||
r.ch <- result
|
||||
if !r.send(ctx, result) {
|
||||
return
|
||||
}
|
||||
continue
|
||||
}
|
||||
decoded, err := DecodeControl(packet.Children[2].Children[0])
|
||||
if err != nil {
|
||||
werr := fmt.Errorf("failed to decode search result entry: %w", err)
|
||||
result.Error = werr
|
||||
r.ch <- result
|
||||
r.send(ctx, result)
|
||||
return
|
||||
}
|
||||
result.Controls = append(result.Controls, decoded)
|
||||
r.ch <- result
|
||||
if !r.send(ctx, result) {
|
||||
return
|
||||
}
|
||||
|
||||
case ApplicationSearchResultDone:
|
||||
if err := GetLDAPError(packet); err != nil {
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
if len(packet.Children) == 3 {
|
||||
@@ -157,33 +177,37 @@ func (r *searchResponse) start(ctx context.Context, searchRequest *SearchRequest
|
||||
decodedChild, err := DecodeControl(child)
|
||||
if err != nil {
|
||||
werr := fmt.Errorf("failed to decode child control: %w", err)
|
||||
r.ch <- &SearchSingleResult{Error: werr}
|
||||
r.send(ctx, &SearchSingleResult{Error: werr})
|
||||
return
|
||||
}
|
||||
result.Controls = append(result.Controls, decodedChild)
|
||||
}
|
||||
r.ch <- result
|
||||
r.send(ctx, result)
|
||||
}
|
||||
foundSearchSingleResultDone = true
|
||||
|
||||
case ApplicationSearchResultReference:
|
||||
ref := packet.Children[1].Children[0].Value.(string)
|
||||
r.ch <- &SearchSingleResult{Referral: ref}
|
||||
if !r.send(ctx, &SearchSingleResult{Referral: ref}) {
|
||||
return
|
||||
}
|
||||
|
||||
case ApplicationIntermediateResponse:
|
||||
decoded, err := DecodeControl(packet.Children[1])
|
||||
if err != nil {
|
||||
werr := fmt.Errorf("failed to decode intermediate response: %w", err)
|
||||
r.ch <- &SearchSingleResult{Error: werr}
|
||||
r.send(ctx, &SearchSingleResult{Error: werr})
|
||||
return
|
||||
}
|
||||
result := &SearchSingleResult{}
|
||||
result.Controls = append(result.Controls, decoded)
|
||||
r.ch <- result
|
||||
if !r.send(ctx, result) {
|
||||
return
|
||||
}
|
||||
|
||||
default:
|
||||
err := fmt.Errorf("unknown tag: %d", packet.Children[1].Tag)
|
||||
r.ch <- &SearchSingleResult{Error: err}
|
||||
r.send(ctx, &SearchSingleResult{Error: err})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
8
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/search.go
generated
vendored
@@ -624,7 +624,10 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
|
||||
// SearchAsync performs a search request and returns all search results asynchronously.
|
||||
// This means you get all results until an error happens (or the search successfully finished),
|
||||
// e.g. for size / time limited requests all are received until the limit is reached.
|
||||
// To stop the search, call cancel function of the context.
|
||||
// To stop the search, call the cancel function of the context; Next may
|
||||
// still deliver a few results received before the cancellation took effect.
|
||||
// Cancellation is not reported as an error: Err returns nil, same as a
|
||||
// successfully completed search.
|
||||
func (l *Conn) SearchAsync(
|
||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int) Response {
|
||||
r := newSearchResponse(l, bufferSize)
|
||||
@@ -635,7 +638,8 @@ func (l *Conn) SearchAsync(
|
||||
// Syncrepl is a short name for LDAP Sync Replication engine that works on the
|
||||
// consumer-side. This can perform a persistent search and returns an entry
|
||||
// when the entry is updated on the server side.
|
||||
// To stop the search, call cancel function of the context.
|
||||
// To stop the search, call the cancel function of the context; cancellation
|
||||
// is not reported as an error, Err returns nil.
|
||||
func (l *Conn) Syncrepl(
|
||||
ctx context.Context, searchRequest *SearchRequest, bufferSize int,
|
||||
mode ControlSyncRequestMode, cookie []byte, reloadHint bool,
|
||||
|
||||
9
vendor/github.com/go-ldap/ldap/v3/unbind.go
generated
vendored
9
vendor/github.com/go-ldap/ldap/v3/unbind.go
generated
vendored
@@ -24,11 +24,18 @@ func (l *Conn) Unbind() error {
|
||||
return ErrConnUnbound
|
||||
}
|
||||
|
||||
_, err := l.doRequest(unbindRequest{})
|
||||
msgCtx, err := l.doRequest(unbindRequest{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finish the message context so its done channel is closed. Without
|
||||
// this, a server-initiated disconnect racing with Close can deadlock:
|
||||
// processMessages cleanup tries to deliver closeErr to the orphaned
|
||||
// context via sendResponse, which blocks forever on the unclosed done
|
||||
// channel, preventing chanConfirm from being signalled.
|
||||
l.finishMessage(msgCtx)
|
||||
|
||||
// Sending an unbindRequest will make the connection unusable.
|
||||
// Pending requests will fail with:
|
||||
// LDAP Result Code 200 "Network Error": ldap: response channel closed
|
||||
|
||||
8
vendor/github.com/go-ldap/ldap/v3/whoami.go
generated
vendored
8
vendor/github.com/go-ldap/ldap/v3/whoami.go
generated
vendored
@@ -19,5 +19,11 @@ func (l *Conn) WhoAmI(controls []Control) (*WhoAmIResult, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WhoAmIResult{AuthzID: resp.Value.Data.String()}, nil
|
||||
// responseValue is OPTIONAL (RFC 4532); Extended leaves Value nil when the
|
||||
// server omits it. Guard the dereference and report an empty authzId.
|
||||
result := &WhoAmIResult{}
|
||||
if resp.Value != nil {
|
||||
result.AuthzID = resp.Value.Data.String()
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@@ -451,7 +451,7 @@ github.com/ggwhite/go-masker
|
||||
## explicit; go 1.15
|
||||
github.com/go-acme/lego/v4/acme
|
||||
github.com/go-acme/lego/v4/challenge
|
||||
# github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667
|
||||
# github.com/go-asn1-ber/asn1-ber v1.5.8
|
||||
## explicit; go 1.13
|
||||
github.com/go-asn1-ber/asn1-ber
|
||||
# github.com/go-chi/chi/v5 v5.3.1
|
||||
@@ -539,8 +539,8 @@ github.com/go-jose/go-jose/v4/json
|
||||
## explicit; go 1.17
|
||||
github.com/go-kit/log
|
||||
github.com/go-kit/log/level
|
||||
# github.com/go-ldap/ldap/v3 v3.4.13
|
||||
## explicit; go 1.24.0
|
||||
# github.com/go-ldap/ldap/v3 v3.4.14
|
||||
## explicit; go 1.25.0
|
||||
github.com/go-ldap/ldap/v3
|
||||
# github.com/go-ldap/ldif v0.0.0-20200320164324-fd88d9b715b3
|
||||
## explicit; go 1.14
|
||||
|
||||
Reference in New Issue
Block a user