Documentation
¶
Overview ¶
Package ldaptest drives an LDAP server over the wire, for the questions a real client cannot express.
⛔ It is NOT a judge, and it is not a client library. A client from the same module as the server can agree with it about a misreading of the protocol and both be wrong -- which is exactly how a substring filter defect went unnoticed for years in the library go-authn/ldap replaces: its own client encoded the filter with the same mistake, so the round trip looked clean. Conformance belongs to OpenLDAP's `ldapsearch`.
What this is for is the questions ldapsearch cannot ask, all of which are about ONE CONNECTION'S STATE:
- two binds and a search on a single socket, because "a refused bind keeps the previous bind's rights" does not exist across two;
- a SASL bind with an arbitrary mechanism, which go-ldap/ldap/v3 offers no way to send;
- a StartTLS upgrade followed by more LDAP on the same connection.
It returns errors rather than taking a *testing.T, so that importing it pulls no test flags into anything, and so it can be used from a fixture that is not a test.
Index ¶
- func Paged(size int, cookie string) ldap.Control
- type Client
- func (c *Client) Bind(dn, password string) (ldap.Result, error)
- func (c *Client) BindSASL(mechanism string, credentials []byte) (SASLStep, error)
- func (c *Client) Close() error
- func (c *Client) Conn() net.Conn
- func (c *Client) Extended(oid string, value []byte) (ldap.Result, error)
- func (c *Client) Read() (*ber.Packet, error)
- func (c *Client) Search(s Search) (SearchResult, error)
- func (c *Client) SetDeadline(t time.Time) error
- func (c *Client) StartTLS(cfg *tls.Config) (ldap.Result, error)
- func (c *Client) WhoAmI() (string, ldap.Result, error)
- type SASLStep
- type Search
- type SearchResult
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
A Client is one connection to a server.
func (*Client) Bind ¶
Bind sends a simple bind.
The password is a string here and not []byte, because a test writes a literal. A SERVER must take it as bytes -- see ldap.BindRequest.
func (*Client) BindSASL ¶
BindSASL sends one step of a SASL bind. Passing nil credentials sends the field ABSENT, which several mechanisms use as their first message.
func (*Client) Read ¶
Read reads one message, for a caller asserting that something arrived -- or, with a deadline, that nothing did.
func (*Client) Search ¶
func (c *Client) Search(s Search) (SearchResult, error)
Search sends one and reads to the searchResDone.
func (*Client) SetDeadline ¶
SetDeadline bounds every exchange, so that a test against a server that stops answering fails rather than hangs.
func (*Client) StartTLS ¶
StartTLS upgrades the connection (RFC 4511 4.14).
The handshake is done here, which means a caller that wants to assert a REFUSAL gets it from the result rather than from a handshake that never happens: the result is returned before the handshake is attempted, and the handshake only runs on success.
type SASLStep ¶
type SASLStep struct {
ldap.Result
// ServerCreds is serverSaslCreds, and Present says whether the field was
// there at all -- RFC 4511 4.2.2 gives an absent field and a zero-length
// one different meanings, and a test that cannot tell them apart cannot
// check either.
ServerCreds []byte
Present bool
}
A SASLStep is what one step of a SASL bind answered.
type Search ¶
type Search struct {
Base string
Scope ldap.Scope
Filter string // RFC 4515; empty means "(objectClass=*)"
// FilterAST is sent instead of Filter when it is set, so that a test can
// send a filter the RFC 4515 parser would never produce -- which is what
// this package is for. A nil one is an error rather than a filter that
// matches everything.
FilterAST ldap.Filter
Attrs []string
SizeLimit int
TypesOnly bool
Controls []ldap.Control
}
A Search is what to ask for. The zero value is a base-scope search of the root DSE with a present filter, which is what discovery looks like.
type SearchResult ¶
type SearchResult struct {
ldap.Result
Entries []*ldap.Entry
// Controls are the response controls on the searchResDone -- where the
// paged-results cookie arrives (RFC 2696).
Controls []ldap.Control
}
A SearchResult is what a search came back with.
func (SearchResult) Cookie ¶ added in v0.2.0
func (r SearchResult) Cookie() (cookie string, ok bool)
Cookie is the paged-results cookie, and ok says whether the control was there at all.
⛔ An EMPTY cookie with the control present means "that was the last page" and is how a sequence ends; an ABSENT control means the server did not page at all. A client that cannot tell them apart either stops early or asks forever.
func (SearchResult) DNs ¶
func (r SearchResult) DNs() []string
DNs is every entry's DN, for a test that only cares which entries came.
func (SearchResult) Values ¶
func (r SearchResult) Values() []string
Values is every attribute value, as "name: value", for a test asserting what an entry published.