ldap

package
v0.0.0-...-a476982 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 28, 2020 License: MIT Imports: 24 Imported by: 0

README

GoDoc Build Status

Basic LDAP v3 functionality for the GO programming language.

The library implements the following specifications:

Features:

  • Connecting to LDAP server (non-TLS, TLS, STARTTLS)
  • Binding to LDAP server
  • Searching for entries
  • Filter Compile / Decompile
  • Paging Search Results
  • Modify Requests / Responses
  • Add Requests / Responses
  • Delete Requests / Responses
  • Modify DN Requests / Responses

Go Modules:

go get github.com/go-ldap/ldap/v3

As go-ldap was v2+ when Go Modules came out, updating to Go Modules would be considered a breaking change.

To maintain backwards compatability, we ultimately decided to use subfolders (as v3 was already a branch). Whilst this duplicates the code, we can move toward implementing a backwards-compatible versioning system that allows for code reuse. The alternative would be to increment the version number, however we believe that this would confuse users as v3 is in line with LDAPv3 (RFC-4511) https://tools.ietf.org/html/rfc4511

For more info, please visit the pull request that updated to modules. https://github.com/go-ldap/ldap/pull/247

To install with GOMODULE111=off, use go get github.com/go-ldap/ldap https://golang.org/cmd/go/#hdr-Legacy_GOPATH_go_get

As always, we are looking for contributors with great ideas on how to best move forward.

Contributing:

Bug reports and pull requests are welcome!

Before submitting a pull request, please make sure tests and verification scripts pass:

make all

To set up a pre-push hook to run the tests and verify scripts before pushing:

ln -s ../../.githooks/pre-push .git/hooks/pre-push

The Go gopher was designed by Renee French. (http://reneefrench.blogspot.com/) The design is licensed under the Creative Commons 3.0 Attributions license. Read this article for more details: http://blog.golang.org/gopher

Documentation

Overview

Package ldap provides a ldap implementation.

Index

Examples

Constants

View Source
const (
	// MessageQuit causes the processMessages loop to exit
	MessageQuit = 0
	// MessageRequest sends a request to the server
	MessageRequest = 1
	// MessageResponse receives a response from the server
	MessageResponse = 2
	// MessageFinish indicates the client considers a particular message ID to be finished
	MessageFinish = 3
	// MessageTimeout indicates the client-specified timeout for a particular message ID has been reached
	MessageTimeout = 4
)

Variables

View Source
var DefaultTimeout = 60 * time.Second

DefaultTimeout is a package-level variable that sets the timeout value used for the Dial and DialTLS methods.

WARNING: since this is a package-level variable, setting this value from multiple places will probably result in undesired behaviour.

Functions

func BuildExtendedNameValuePacket

func BuildExtendedNameValuePacket(request bool, name ExtendedOp, value *ber.Packet) *ber.Packet

BuildExtendedNameValuePacket builds an extended name and value packet.

func BuildMessagePacket

func BuildMessagePacket(id int64, p *ber.Packet) *ber.Packet

BuildMessagePacket builds a ldap message packet.

func BuildResultPacket

func BuildResultPacket(app ldaputil.Application, result ldaputil.Result, matched, msg string) *ber.Packet

BuildResultPacket builds a ldap result packet.

func GetError

func GetError(p *ber.Packet) error

GetError creates an Error out of a BER packet representing a Result The return is an error object. It can be casted to a Error structure. This function returns nil if resultCode in the Result sequence is success(0).

func IsErrorOf

func IsErrorOf(err error, results ...ldaputil.Result) bool

IsErrorOf returns true if the given error is an LDAP error with any one of the given result codes

func ListenAndServe

func ListenAndServe(ctx context.Context, addr string, h Handler, opts ...func(*net.ListenConfig)) error

ListenAndServe creates a new server for the passed handler, listening and serving on the specified address until the context is closed.

func ListenAndServeTLS

func ListenAndServeTLS(ctx context.Context, addr, certFile, keyFile string, h Handler, opts ...func(*net.ListenConfig)) error

ListenAndServe creates a new server for the passed handler, listening and serving TLS encrypted connections on the specified address until the context is closed.

func Logf

func Logf(ctx context.Context, s string, v ...interface{})

Logf returns the context's log func.

func SessionID

func SessionID(ctx context.Context) string

SessionID returns the context's session id.

func SessionSetValue

func SessionSetValue(ctx context.Context, name string, value interface{})

SessionSetValue sets a named value in the context's session.

func SessionValue

func SessionValue(ctx context.Context, name string) interface{}

SessionValue returns the named value from the context's session.

func WithLogf

func WithLogf(ctx context.Context, logf func(string, ...interface{})) context.Context

WithLogf creates a new context with the specified log func.

Types

type AbandonHandler

type AbandonHandler interface {
	Abandon(context.Context, *AbandonRequest) (*AbandonResponse, error)
}

type AbandonHandlerFunc

type AbandonHandlerFunc func(context.Context, *AbandonRequest) (*AbandonResponse, error)

func (AbandonHandlerFunc) Abandon

type AbandonRequest

type AbandonRequest struct {
	ID int64
}

func ParseAbandonRequest

func ParseAbandonRequest(req *Request) (*AbandonRequest, error)

type AbandonResponse

type AbandonResponse struct{}

func (*AbandonResponse) Encode

Encode satisfies the Encoder interface.

type AddHandler

type AddHandler interface {
	Add(context.Context, *AddRequest) (*AddResponse, error)
}

type AddHandlerFunc

type AddHandlerFunc func(context.Context, *AddRequest) (*AddResponse, error)

func (AddHandlerFunc) Add

type AddRequest

type AddRequest struct{}

func ParseAddRequest

func ParseAddRequest(req *Request) (*AddRequest, error)

type AddResponse

type AddResponse struct{}

func (*AddResponse) Encode

func (res *AddResponse) Encode(_ context.Context, w ResponseWriter) error

Encode satisfies the Encoder interface.

type AuthHandler

AuthHandler is the interface for an auth handler.

func NewSessionAuthHandler

func NewSessionAuthHandler(bind SessionBindFunc, auth SessionAuthFunc, extended SessionExtendedFunc) AuthHandler

NewSessionAuthHandler creates a new session auth handler.

type BindHandler

type BindHandler interface {
	Bind(context.Context, *BindRequest) (*BindResponse, error)
}

type BindHandlerFunc

type BindHandlerFunc func(context.Context, *BindRequest) (*BindResponse, error)

func (BindHandlerFunc) Bind

type BindRequest

type BindRequest struct {
	Username string
	Password string
}

func ParseBindRequest

func ParseBindRequest(req *Request) (*BindRequest, error)

type BindResponse

type BindResponse struct {
	Result    ldaputil.Result
	MatchedDN string
}

func (*BindResponse) Encode

func (res *BindResponse) Encode(ctx context.Context, w ResponseWriter) error

Encode satisfies the Encoder interface.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is an ldap client client.

func Dial

func Dial(network, addr string) (*Client, error)

Dial connects to the given address on the given network using net.Dial and then returns a new Client for the connection. @deprecated Use DialURL instead.

func DialTLS

func DialTLS(network, addr string, config *tls.Config) (*Client, error)

DialTLS connects to the given address on the given network using tls.Dial and then returns a new Client for the connection. @deprecated Use DialURL instead.

func DialURL

func DialURL(addr string, opts ...DialOpt) (*Client, error)

DialURL connects to the given ldap URL. The following schemas are supported: ldap://, ldaps://, ldapi://. On success a new Client for the connection is returned.

func NewClient

func NewClient(conn net.Conn, isTLS bool) *Client

NewClient returns a new Client using conn for network I/O.

func (*Client) Add

func (cl *Client) Add(req *ClientAddRequest) error

Add performs the given AddRequest

func (*Client) Bind

func (cl *Client) Bind(username, password string) error

Bind performs a bind with the given username and password.

It does not allow unauthenticated bind (i.e. empty password). Use the UnauthenticatedBind method for that.

Example

This example demonstrates how to bind a connection to an ldap user allowing access to restricted attributes that user has access to

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	if err = cl.Bind("cn=read-only-admin,dc=example,dc=com", "password"); err != nil {
		log.Fatal(err)
	}
}
Output:

Example (VerifyLogin)

This example shows how a typical application can verify a login attempt

package main

import (
	"crypto/tls"
	"fmt"
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	// The username and password we want to check
	username := "someuser"
	password := "userpassword"
	bindusername := "readonly"
	bindpassword := "password"
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	// Reconnect with TLS
	if err = cl.StartTLS(&tls.Config{InsecureSkipVerify: true}); err != nil {
		log.Fatal(err)
	}
	// First bind with a read only user
	if err = cl.Bind(bindusername, bindpassword); err != nil {
		log.Fatal(err)
	}
	// Search for the given username
	req := ldap.NewClientSearchRequest(
		"dc=example,dc=com",
		ldap.ScopeWholeSubtree, ldap.DerefAliasesNever, 0, 0, false,
		fmt.Sprintf("(&(objectClass=organizationalPerson)(uid=%s))", username),
		[]string{"dn"},
	)
	res, err := cl.Search(req)
	if err != nil {
		log.Fatal(err)
	}
	if len(res.Entries) != 1 {
		log.Fatal("User does not exist or too many entries returned")
	}
	userdn := res.Entries[0].DN
	// Bind as the user to verify their password
	if err = cl.Bind(userdn, password); err != nil {
		log.Fatal(err)
	}
	// Rebind as the read only user for any further queries
	if err = cl.Bind(bindusername, bindpassword); err != nil {
		log.Fatal(err)
	}
}
Output:

func (*Client) Close

func (cl *Client) Close()

Close closes the connection.

func (*Client) Compare

func (cl *Client) Compare(dn, attribute, value string) (bool, error)

Compare checks to see if the attribute of the dn matches value. Returns true if it does otherwise false with any error that occurs if any.

Example

This example demonstrates how to compare an attribute with a value

package main

import (
	"fmt"
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	matched, err := cl.Compare("cn=user,dc=example,dc=com", "uid", "someuserid")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(matched)
}
Output:

func (*Client) Del

func (cl *Client) Del(req *ClientDeleteRequest) error

Del executes the given delete request

func (*Client) DigestMD5Bind

func (cl *Client) DigestMD5Bind(req *ClientDigestMD5BindRequest) (*DigestMD5BindResult, error)

DigestMD5Bind performs the digest-md5 bind operation defined in the given request

func (*Client) Do

func (cl *Client) Do(req ClientRequest) (*MessageContext, error)

func (*Client) ExternalBind

func (cl *Client) ExternalBind() error

ExternalBind performs SASL/EXTERNAL authentication.

Use ldap.DialURL("ldapi://") to connect to the Unix socket before ExternalBind.

See https://tools.ietf.org/html/rfc4422#appendix-A

Example

This example demonstrates how to use EXTERNAL SASL with TLS client certificates.

package main

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	ldapCert := "/path/to/cert.pem"
	ldapKey := "/path/to/key.pem"
	ldapCAchain := "/path/to/ca_chain.pem"
	// Load client cert and key
	cert, err := tls.LoadX509KeyPair(ldapCert, ldapKey)
	if err != nil {
		log.Fatal(err)
	}
	// Load CA chain
	caCert, err := ioutil.ReadFile(ldapCAchain)
	if err != nil {
		log.Fatal(err)
	}
	caCertPool := x509.NewCertPool()
	caCertPool.AppendCertsFromPEM(caCert)
	// Setup TLS with ldap client cert
	tlsConfig := &tls.Config{
		Certificates:       []tls.Certificate{cert},
		RootCAs:            caCertPool,
		InsecureSkipVerify: true,
	}
	// connect to ldap server
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	// reconnect using tls
	if err = cl.StartTLS(tlsConfig); err != nil {
		log.Fatal(err)
	}
	// sasl external bind
	if err = cl.ExternalBind(); err != nil {
		log.Fatal(err)
	}
	// Conduct ldap queries
}
Output:

func (*Client) FinishMessage

func (cl *Client) FinishMessage(msgCtx *MessageContext)

func (*Client) IsClosing

func (cl *Client) IsClosing() bool

IsClosing returns whether or not we're currently closing.

func (*Client) MD5Bind

func (cl *Client) MD5Bind(host, username, password string) error

MD5Bind performs a digest-md5 bind with the given host, username and password.

func (*Client) Modify

func (cl *Client) Modify(req *ClientModifyRequest) error

Modify performs the ModifyRequest

Example
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	// Add a description, and replace the mail attributes
	req := ldap.NewModifyRequest("cn=user,dc=example,dc=com", nil)
	req.Add("description", []string{"An example user"})
	req.Replace("mail", []string{"user@example.org"})
	if err = cl.Modify(req); err != nil {
		log.Fatal(err)
	}
}
Output:

func (*Client) ModifyDN

func (cl *Client) ModifyDN(req *ClientModifyDNRequest) error

ModifyDN renames the given DN and optionally move to another base (when the "newSup" argument to NewModifyDNRequest() is not "").

Example (MoveOnly)

This example shows how to move an entry to a new base without renaming the RDN

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.org:389")
	if err != nil {
		log.Fatalf("Failed to connect: %s", err)
	}
	defer cl.Close()
	_, err = cl.SimpleBind(&ldap.ClientSimpleBindRequest{
		Username: "uid=someone,ou=people,dc=example,dc=org",
		Password: "MySecretPass",
	})
	if err != nil {
		log.Fatalf("Failed to bind: %s", err)
	}
	// move to ou=users,dc=example,dc=org -> uid=user,ou=users,dc=example,dc=org
	req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=user", true, "ou=users,dc=example,dc=org")
	if err = cl.ModifyDN(req); err != nil {
		log.Fatalf("Failed to call ModifyDN(): %s", err)
	}
}
Output:

Example (RenameAndMove)

This example shows how to rename an entry and moving it to a new base

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.org:389")
	if err != nil {
		log.Fatalf("Failed to connect: %s", err)
	}
	defer cl.Close()
	_, err = cl.SimpleBind(&ldap.ClientSimpleBindRequest{
		Username: "uid=someone,ou=people,dc=example,dc=org",
		Password: "MySecretPass",
	})
	if err != nil {
		log.Fatalf("Failed to bind: %s", err)
	}
	// rename to uid=new,ou=people,dc=example,dc=org and move to ou=users,dc=example,dc=org ->
	// uid=new,ou=users,dc=example,dc=org
	req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=new", true, "ou=users,dc=example,dc=org")
	if err = cl.ModifyDN(req); err != nil {
		log.Fatalf("Failed to call ModifyDN(): %s", err)
	}
}
Output:

Example (RenameNoMove)

This example shows how to rename an entry without moving it

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.org:389")
	if err != nil {
		log.Fatalf("Failed to connect: %s", err)
	}
	defer cl.Close()
	_, err = cl.SimpleBind(&ldap.ClientSimpleBindRequest{
		Username: "uid=someone,ou=people,dc=example,dc=org",
		Password: "MySecretPass",
	})
	if err != nil {
		log.Fatalf("Failed to bind: %s", err)
	}
	// just rename to uid=new,ou=people,dc=example,dc=org:
	req := ldap.NewModifyDNRequest("uid=user,ou=people,dc=example,dc=org", "uid=new", true, "")
	if err = cl.ModifyDN(req); err != nil {
		log.Fatalf("Failed to call ModifyDN(): %s", err)
	}
}
Output:

func (*Client) NTLMBind

func (cl *Client) NTLMBind(domain, username, password string) error

NTLMBind performs an NTLMSSP Bind with the given domain, username and password

func (*Client) NTLMBindWithHash

func (cl *Client) NTLMBindWithHash(domain, username, hash string) error

NTLMBindWithHash performs an NTLM Bind with an NTLM hash instead of plaintext password (pass-the-hash)

func (*Client) NTLMChallengeBind

func (cl *Client) NTLMChallengeBind(req *ClientNTLMBindRequest) (*NTLMBindResult, error)

NTLMChallengeBind performs the NTLMSSP bind operation defined in the given request

func (*Client) PasswordModify

func (cl *Client) PasswordModify(req *ClientPasswordModifyRequest) (*PasswordModifyResult, error)

PasswordModify performs the modification request

Example
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	if err = cl.Bind("cn=admin,dc=example,dc=com", "password"); err != nil {
		log.Fatal(err)
	}
	req := ldap.NewPasswordModifyRequest("cn=user,dc=example,dc=com", "", "NewPassword")
	if _, err = cl.PasswordModify(req); err != nil {
		log.Fatalf("Password could not be changed: %v", err)
	}
}
Output:

Example (GeneratedPassword)
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	if err = cl.Bind("cn=user,dc=example,dc=com", "password"); err != nil {
		log.Fatal(err)
	}
	req := ldap.NewPasswordModifyRequest("", "OldPassword", "")
	res, err := cl.PasswordModify(req)
	if err != nil {
		log.Fatalf("Password could not be changed: %v", err)
	}
	log.Printf("Generated password: %s", res.GeneratedPassword)
}
Output:

Example (SetNewPassword)
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	if err = cl.Bind("cn=user,dc=example,dc=com", "password"); err != nil {
		log.Fatal(err)
	}
	req := ldap.NewPasswordModifyRequest("", "OldPassword", "NewPassword")
	if _, err = cl.PasswordModify(req); err != nil {
		log.Fatalf("Password could not be changed: %v", err)
	}
}
Output:

func (*Client) ReadPacket

func (cl *Client) ReadPacket(msgCtx *MessageContext) (*ber.Packet, error)

func (*Client) Search

func (cl *Client) Search(req *ClientSearchRequest) (*SearchResult, error)

Search performs the given search request

Example

This example demonstrates how to use the search interface

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	req := ldap.NewClientSearchRequest(
		"dc=example,dc=com", // The base dn to search
		ldap.ScopeWholeSubtree, ldap.DerefAliasesNever, 0, 0, false,
		"(&(objectClass=organizationalPerson))", // The filter to apply
		[]string{"dn", "cn"},                    // A list attributes to retrieve
	)
	res, err := cl.Search(req)
	if err != nil {
		log.Fatal(err)
	}
	for _, entry := range res.Entries {
		log.Printf("%s: %v", entry.DN, entry.GetAttributeValue("cn"))
	}
}
Output:

Example (ControlManualPaging)

This example demonstrates how to use Paging to manually execute a paginated search request instead of using SearchWithPaging.

package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
	"github.com/userhive/asn1/ldap/control"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	var pageSize uint32 = 32
	base := "dc=example,dc=com"
	filter := "(objectClass=group)"
	paging := control.NewPaging(pageSize)
	attributes := []string{}
	for {
		req := ldap.NewClientSearchRequest(
			base,
			ldap.ScopeWholeSubtree,
			ldap.DerefAliasesAlways,
			0,
			0,
			false,
			filter,
			attributes,
			paging,
		)
		res, err := cl.Search(req)
		if err != nil {
			log.Fatalf("Failed to execute search request: %s", err.Error())
		}
		// [do something with the response entries]
		// In order to prepare the next request, we check if the response
		// contains another Paging object and a not-empty cookie and
		// copy that cookie into our pagingControl object:
		updatedControl := control.Find(res.Controls, control.ControlPaging.String())
		if ctrl, ok := updatedControl.(*control.Paging); ctrl != nil && ok && len(ctrl.Cookie) != 0 {
			paging.SetCookie(ctrl.Cookie)
			continue
		}
		// If no new paging information is available or the cookie is empty, we
		// are done with the pagination.
		break
	}
}
Output:

func (*Client) SearchWithPaging

func (cl *Client) SearchWithPaging(req *ClientSearchRequest, pagingSize uint32) (*SearchResult, error)

SearchWithPaging accepts a search request and desired page size in order to execute LDAP queries to fulfill the search request. All paged LDAP query responses will be buffered and the final result will be returned atomically.

The following four cases are possible given the arguments:

  • given SearchRequest missing a control of type control.ControlPaging: we will add one with the desired paging size
  • given SearchRequest contains a control of type control.ControlPaging that isn't actually a Paging: fail without issuing any queries
  • given SearchRequest contains a control of type control.ControlPaging with pagingSize equal to the size requested: no change to the search request
  • given SearchRequest contains a control of type control.ControlPaging with pagingSize not equal to the size requested: fail without issuing any queries

A requested pagingSize of 0 is interpreted as no limit by LDAP servers.

func (*Client) SendMessage

func (cl *Client) SendMessage(p *ber.Packet) (*MessageContext, error)

func (*Client) SendMessageWithFlags

func (cl *Client) SendMessageWithFlags(p *ber.Packet, flags SendMessageFlags) (*MessageContext, error)

func (*Client) SetTimeout

func (cl *Client) SetTimeout(timeout time.Duration)

SetTimeout sets the time after a request is sent that a MessageTimeout triggers

func (*Client) SimpleBind

func (cl *Client) SimpleBind(req *ClientSimpleBindRequest) (*SimpleBindResult, error)

SimpleBind performs the simple bind operation defined in the given request

Example (ControlBeheraPasswordPolicy)
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
	"github.com/userhive/asn1/ldap/control"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	controls := []control.Control{
		control.NewBeheraPasswordPolicy(),
	}
	req := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", controls...)
	res, err := cl.SimpleBind(req)
	if err != nil {
		log.Fatal(err)
	}
	ppolicyControl := control.Find(res.Controls, control.ControlBeheraPasswordPolicy.String())
	var ppolicy *control.BeheraPasswordPolicy
	if ppolicyControl != nil {
		ppolicy = ppolicyControl.(*control.BeheraPasswordPolicy)
	} else {
		log.Printf("ppolicyControl response not available.")
	}
	if ppolicy != nil {
		if ppolicy.Expire >= 0 {
			log.Printf("Password expires in %d seconds", ppolicy.Expire)
		} else if ppolicy.Grace >= 0 {
			log.Printf("Password expired, %d grace logins remain", ppolicy.Grace)
		}
	}
}
Output:

Example (ControlVChuPasswordPolicy)
package main

import (
	"log"

	"github.com/userhive/asn1/ldap"
	"github.com/userhive/asn1/ldap/control"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	req := ldap.NewSimpleBindRequest("cn=admin,dc=example,dc=com", "password", nil)
	res, err := cl.SimpleBind(req)
	passwordMustChangeControl := control.Find(res.Controls, control.ControlVChuPasswordMustChange.String())
	var passwordMustChange *control.VChuPasswordMustChange
	if passwordMustChangeControl != nil {
		passwordMustChange = passwordMustChangeControl.(*control.VChuPasswordMustChange)
	}
	if passwordMustChange != nil && passwordMustChange.MustChange {
		log.Printf("Password Must be changed.")
	}
	passwordWarningControl := control.Find(res.Controls, control.ControlVChuPasswordWarning.String())
	var passwordWarning *control.VChuPasswordWarning
	if passwordWarningControl != nil {
		passwordWarning = passwordWarningControl.(*control.VChuPasswordWarning)
	} else {
		log.Printf("ppolicyControl response not available.")
	}
	if err != nil {
		log.Fatal(err)
	}
	if passwordWarning != nil {
		if passwordWarning.Expire >= 0 {
			log.Printf("Password expires in %d seconds", passwordWarning.Expire)
		}
	}
}
Output:

func (*Client) Start

func (cl *Client) Start()

Start initializes goroutines to read responses and process messages

func (*Client) StartTLS

func (cl *Client) StartTLS(config *tls.Config) error

StartTLS sends the command to start a TLS session and then creates a new TLS Client

Example

This example demonstrates how to start a TLS connection

package main

import (
	"crypto/tls"
	"log"

	"github.com/userhive/asn1/ldap"
)

func main() {
	cl, err := ldap.DialURL("ldap://ldap.example.com:389")
	if err != nil {
		log.Fatal(err)
	}
	defer cl.Close()
	// Reconnect with TLS
	if err = cl.StartTLS(&tls.Config{InsecureSkipVerify: true}); err != nil {
		log.Fatal(err)
	}
	// Operations via l are now encrypted
}
Output:

func (*Client) TLSConnectionState

func (cl *Client) TLSConnectionState() (state tls.ConnectionState, ok bool)

TLSConnectionState returns the client's TLS connection state. The return values are their zero values if StartTLS did not succeed.

func (*Client) UnauthenticatedBind

func (cl *Client) UnauthenticatedBind(username string) error

UnauthenticatedBind performs an unauthenticated bind.

A username may be provided for trace (e.g. logging) purpose only, but it is normally not authenticated or otherwise validated by the LDAP server.

See https://tools.ietf.org/html/rfc4513#section-5.1.2 . See https://tools.ietf.org/html/rfc4513#section-6.3.1 .

type ClientAddRequest

type ClientAddRequest struct {
	// DN identifies the entry being added
	DN string
	// Attributes list the attributes of the new entry
	Attributes []ldaputil.Attribute
	// Controls hold optional controls to send with the request
	Controls []control.Control
}

AddRequest represents an LDAP AddRequest operation

func NewAddRequest

func NewAddRequest(dn string, controls ...control.Control) *ClientAddRequest

NewAddRequest returns an AddRequest for the given DN, with no attributes

func (*ClientAddRequest) AppendTo

func (req *ClientAddRequest) AppendTo(envelope *ber.Packet) error

func (*ClientAddRequest) Attribute

func (req *ClientAddRequest) Attribute(attrType string, attrVals []string)

Attribute adds an attribute with the given type and values

type ClientCompareRequest

type ClientCompareRequest struct {
	DN        string
	Attribute string
	Value     string
}

CompareRequest represents an LDAP CompareRequest operation.

func (*ClientCompareRequest) AppendTo

func (req *ClientCompareRequest) AppendTo(envelope *ber.Packet) error

type ClientDeleteRequest

type ClientDeleteRequest struct {
	// DN is the name of the directory entry to delete
	DN string
	// Controls hold optional controls to send with the request
	Controls []control.Control
}

DeleteRequest implements an LDAP deletion request

func NewDeleteRequest

func NewDeleteRequest(dn string, controls ...control.Control) *ClientDeleteRequest

NewDeleteRequest creates a delete request for the given DN and controls

func (*ClientDeleteRequest) AppendTo

func (req *ClientDeleteRequest) AppendTo(envelope *ber.Packet) error

type ClientDigestMD5BindRequest

type ClientDigestMD5BindRequest struct {
	Host string
	// Username is the name of the Directory object that the client wishes to bind as
	Username string
	// Password is the credentials to bind with
	Password string
	// Controls are optional controls to send with the bind request
	Controls []control.Control
}

DigestMD5BindRequest represents a digest-md5 bind operation

func (*ClientDigestMD5BindRequest) AppendTo

func (req *ClientDigestMD5BindRequest) AppendTo(envelope *ber.Packet) error

type ClientModifyDNRequest

type ClientModifyDNRequest struct {
	DN           string
	NewRDN       string
	DeleteOldRDN bool
	NewSuperior  string
}

ModifyDNRequest holds the request to modify a DN

func NewModifyDNRequest

func NewModifyDNRequest(dn string, rdn string, delOld bool, newSup string) *ClientModifyDNRequest

NewModifyDNRequest creates a new request which can be passed to ModifyDN().

To move an object in the tree, set the "newSup" to the new parent entry DN. Use an empty string for just changing the object's RDN.

For moving the object without renaming, the "rdn" must be the first RDN of the given DN.

A call like

mdnReq := NewModifyDNRequest("uid=someone,dc=example,dc=org", "uid=newname", true, "")

will setup the request to just rename uid=someone,dc=example,dc=org to uid=newname,dc=example,dc=org.

func (*ClientModifyDNRequest) AppendTo

func (req *ClientModifyDNRequest) AppendTo(envelope *ber.Packet) error

type ClientModifyRequest

type ClientModifyRequest struct {
	// DN is the distinguishedName of the directory entry to modify
	DN string
	// Changes contain the attributes to modify
	Changes []ldaputil.Change
	// Controls hold optional controls to send with the request
	Controls []control.Control
}

ModifyRequest as defined in https://tools.ietf.org/html/rfc4511

func NewModifyRequest

func NewModifyRequest(dn string, controls ...control.Control) *ClientModifyRequest

NewModifyRequest creates a modify request for the given DN

func (*ClientModifyRequest) Add

func (req *ClientModifyRequest) Add(attrType string, attrVals []string)

Add appends the given attribute to the list of changes to be made

func (*ClientModifyRequest) AppendTo

func (req *ClientModifyRequest) AppendTo(envelope *ber.Packet) error

func (*ClientModifyRequest) Delete

func (req *ClientModifyRequest) Delete(attrType string, attrVals []string)

Delete appends the given attribute to the list of changes to be made

func (*ClientModifyRequest) Increment

func (req *ClientModifyRequest) Increment(attrType string, attrVal string)

Increment appends the given attribute to the list of changes to be made

func (*ClientModifyRequest) Replace

func (req *ClientModifyRequest) Replace(attrType string, attrVals []string)

Replace appends the given attribute to the list of changes to be made

type ClientNTLMBindRequest

type ClientNTLMBindRequest struct {
	// Domain is the AD Domain to authenticate too. If not specified, it will be grabbed from the NTLMSSP Challenge
	Domain string
	// Username is the name of the Directory object that the client wishes to bind as
	Username string
	// Password is the credentials to bind with
	Password string
	// Hash is the hex NTLM hash to bind with. Password or hash must be provided
	Hash string
	// Controls are optional controls to send with the bind request
	Controls []control.Control
}

NTLMBind performs an NTLMSSP bind leveraging https://github.com/Azure/go-ntlmssp NTLMBindRequest represents an NTLMSSP bind operation

func (*ClientNTLMBindRequest) AppendTo

func (req *ClientNTLMBindRequest) AppendTo(envelope *ber.Packet) error

type ClientPasswordModifyRequest

type ClientPasswordModifyRequest struct {
	// UserIdentity is an optional string representation of the user associated with the request.
	// This string may or may not be an LDAPDN [RFC2253].
	// If no UserIdentity field is present, the request acts up upon the password of the user currently associated with the LDAP session
	UserIdentity string
	// OldPassword, if present, contains the user's current password
	OldPassword string
	// NewPassword, if present, contains the desired password for this user
	NewPassword string
}

PasswordModifyRequest implements the Password Modify Extended Operation as defined in https://www.ietf.org/rfc/rfc3062.txt

func NewPasswordModifyRequest

func NewPasswordModifyRequest(userIdentity string, oldPassword string, newPassword string) *ClientPasswordModifyRequest

NewPasswordModifyRequest creates a new PasswordModifyRequest

According to the RFC 3602 (https://tools.ietf.org/html/rfc3062): userIdentity is a string representing the user associated with the request. This string may or may not be an LDAPDN (RFC 2253). If userIdentity is empty then the operation will act on the user associated with the session.

oldPassword is the current user's password, it can be empty or it can be needed depending on the session user access rights (usually an administrator can change a user's password without knowing the current one) and the password policy (see pwdSafeModify password policy's attribute)

newPassword is the desired user's password. If empty the server can return an error or generate a new password that will be available in the PasswordModifyResult.GeneratedPassword

func (*ClientPasswordModifyRequest) AppendTo

func (req *ClientPasswordModifyRequest) AppendTo(envelope *ber.Packet) error

type ClientRequest

type ClientRequest interface {
	AppendTo(*ber.Packet) error
}

type ClientRequestFunc

type ClientRequestFunc func(*ber.Packet) error

func (ClientRequestFunc) AppendTo

func (f ClientRequestFunc) AppendTo(p *ber.Packet) error

type ClientSearchRequest

type ClientSearchRequest struct {
	BaseDN       string
	Scope        Scope
	DerefAliases DerefAliases
	SizeLimit    int
	TimeLimit    time.Duration
	TypesOnly    bool
	Filter       string
	Attributes   []string
	Controls     []control.Control
}

SearchRequest represents a search request to send to the server

func NewClientSearchRequest

func NewClientSearchRequest(baseDN string, scope Scope, derefAliases DerefAliases, sizeLimit int, timeLimit time.Duration, typesOnly bool, filter string, attributes []string, controls ...control.Control) *ClientSearchRequest

NewClientSearchRequest creates a new search request

func (*ClientSearchRequest) AppendTo

func (req *ClientSearchRequest) AppendTo(envelope *ber.Packet) error

type ClientSimpleBindRequest

type ClientSimpleBindRequest struct {
	// Username is the name of the Directory object that the client wishes to bind as
	Username string
	// Password is the credentials to bind with
	Password string
	// Controls are optional controls to send with the bind request
	Controls []control.Control
}

SimpleBindRequest represents a username/password bind operation

func NewSimpleBindRequest

func NewSimpleBindRequest(username string, password string, controls ...control.Control) *ClientSimpleBindRequest

NewSimpleBindRequest returns a bind request

func (*ClientSimpleBindRequest) AppendTo

func (req *ClientSimpleBindRequest) AppendTo(envelope *ber.Packet) error

type CompareHandler

type CompareHandler interface {
	Compare(context.Context, *CompareRequest) (*CompareResponse, error)
}

type CompareHandlerFunc

type CompareHandlerFunc func(context.Context, *CompareRequest) (*CompareResponse, error)

func (CompareHandlerFunc) Compare

type CompareRequest

type CompareRequest struct{}

func ParseCompareRequest

func ParseCompareRequest(req *Request) (*CompareRequest, error)

type CompareResponse

type CompareResponse struct{}

func (*CompareResponse) Encode

Encode satisfies the Encoder interface.

type DeleteHandler

type DeleteHandler interface {
	Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
}

type DeleteHandlerFunc

type DeleteHandlerFunc func(context.Context, *DeleteRequest) (*DeleteResponse, error)

func (DeleteHandlerFunc) Delete

type DeleteRequest

type DeleteRequest struct{}

func ParseDeleteRequest

func ParseDeleteRequest(req *Request) (*DeleteRequest, error)

type DeleteResponse

type DeleteResponse struct{}

func (*DeleteResponse) Encode

Encode satisfies the Encoder interface.

type DerefAliases

type DerefAliases int

DerefAliases is the deref aliases enum.

const (
	DerefAliasesNever DerefAliases = iota
	DerefAliasesInSearching
	DerefAliasesFindingBaseObject
	DerefAliasesAlways
)

DerefAliases values.

func (DerefAliases) String

func (i DerefAliases) String() string

type DialContext

type DialContext struct {
	Dialer    *net.Dialer
	TLSConfig *tls.Config
}

DialContext contains necessary parameters to dial the given ldap URL.

func (*DialContext) Dial

func (dc *DialContext) Dial(u *url.URL) (net.Conn, error)

type DialOpt

type DialOpt func(*DialContext)

DialOpt configures DialContext.

func DialWithDialer

func DialWithDialer(d *net.Dialer) DialOpt

DialWithDialer updates net.Dialer in DialContext.

func DialWithTLSConfig

func DialWithTLSConfig(tc *tls.Config) DialOpt

DialWithTLSConfig updates tls.Config in DialContext.

type DigestMD5BindResult

type DigestMD5BindResult struct {
	Controls []control.Control
}

DigestMD5BindResult contains the response from the server

type Encoder

type Encoder interface {
	Encode(context.Context, ResponseWriter) error
}

Encoder is the interface for types that can be directly encoded to a response writer.

type Entry

type Entry struct {
	// DN is the distinguished name of the entry
	DN string
	// Attributes are the returned attributes for the entry
	Attributes []*EntryAttribute
}

Entry represents a single search result entry

func NewEntry

func NewEntry(dn string, attributes map[string][]string) *Entry

NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs. The map of attributes is accessed in alphabetical order of the keys in order to ensure that, for the same input map of attributes, the output entry will contain the same order of attributes

func (*Entry) GetAttributeValue

func (e *Entry) GetAttributeValue(attribute string) string

GetAttributeValue returns the first value for the named attribute, or ""

func (*Entry) GetAttributeValues

func (e *Entry) GetAttributeValues(attribute string) []string

GetAttributeValues returns the values for the named attribute, or an empty list

func (*Entry) GetEqualFoldAttributeValue

func (e *Entry) GetEqualFoldAttributeValue(attribute string) string

GetEqualFoldAttributeValue returns the first value for the named attribute, or "". Attribute comparison is done with strings.EqualFold.

func (*Entry) GetEqualFoldAttributeValues

func (e *Entry) GetEqualFoldAttributeValues(attribute string) []string

GetEqualFoldAttributeValues returns the values for the named attribute, or an empty list. Attribute matching is done with strings.EqualFold.

func (*Entry) GetEqualFoldRawAttributeValue

func (e *Entry) GetEqualFoldRawAttributeValue(attribute string) []byte

GetEqualFoldRawAttributeValue returns the first value for the named attribute, or an empty slice

func (*Entry) GetEqualFoldRawAttributeValues

func (e *Entry) GetEqualFoldRawAttributeValues(attribute string) [][]byte

GetEqualFoldRawAttributeValues returns the byte values for the named attribute, or an empty list

func (*Entry) GetRawAttributeValue

func (e *Entry) GetRawAttributeValue(attribute string) []byte

GetRawAttributeValue returns the first value for the named attribute, or an empty slice

func (*Entry) GetRawAttributeValues

func (e *Entry) GetRawAttributeValues(attribute string) [][]byte

GetRawAttributeValues returns the byte values for the named attribute, or an empty list

func (*Entry) PrettyPrint

func (e *Entry) PrettyPrint(indent int)

PrettyPrint outputs a human-readable description indenting

func (*Entry) Print

func (e *Entry) Print()

Print outputs a human-readable description

type EntryAttribute

type EntryAttribute struct {
	// Name is the name of the attribute
	Name string
	// Values contain the string values of the attribute
	Values []string
	// ByteValues contain the raw values of the attribute
	ByteValues [][]byte
}

EntryAttribute holds a single attribute

func NewEntryAttribute

func NewEntryAttribute(name string, values []string) *EntryAttribute

NewEntryAttribute returns a new EntryAttribute with the desired key-value pair

func (*EntryAttribute) PrettyPrint

func (e *EntryAttribute) PrettyPrint(indent int)

PrettyPrint outputs a human-readable description with indenting

func (*EntryAttribute) Print

func (e *EntryAttribute) Print()

Print outputs a human-readable description

type Error

type Error struct {
	Result  ldaputil.Result
	Matched string
	Message string
}

Error is a ldap error.

func NewError

func NewError(result ldaputil.Result, message string) *Error

NewError creates a new ldap error.

func NewErrorf

func NewErrorf(result ldaputil.Result, message string, v ...interface{}) *Error

NewErrorf creates a new ldap error using fmt.Sprintf.

func (*Error) Error

func (err *Error) Error() string

Error satisfies the error interface.

type ExtendedHandler

type ExtendedHandler interface {
	Extended(context.Context, *ExtendedRequest) (*ExtendedResponse, error)
}

type ExtendedHandlerFunc

type ExtendedHandlerFunc func(context.Context, *ExtendedRequest) (*ExtendedResponse, error)

func NewExtendedPasswordModifyHandler

func NewExtendedPasswordModifyHandler(f ExtendedPasswordModifyHandlerFunc) ExtendedHandlerFunc

NewExtendedPasswordModifyHandler creates a new password modify handler.

func NewExtendedWhoAmIHandler

func NewExtendedWhoAmIHandler(f ExtendedWhoAmIHandlerFunc) ExtendedHandlerFunc

NewExtendedWhoAmIHandler creates a new who am i handler.

Note: see RFC4513 section 5.2.1.8 for format of "authzID" (prefix with dn: or u:).

func (ExtendedHandlerFunc) Extended

type ExtendedOp

type ExtendedOp string

ExtendedOp is an extended operation identifier.

const (
	ExtendedOpPasswordModify ExtendedOp = "1.3.6.1.4.1.4203.1.11.1"
	ExtendedOpCancel         ExtendedOp = "1.3.6.1.4.1.4203.1.11.2"
	ExtendedOpWhoAmI         ExtendedOp = "1.3.6.1.4.1.4203.1.11.3"
)

ExtendedOp values.

func (ExtendedOp) String

func (op ExtendedOp) String() string

String satisfies the fmt.Stringer interface.

type ExtendedOpHandler

type ExtendedOpHandler map[ExtendedOp]ExtendedHandlerFunc

ExtendedOpHandler is an extended op handler.

func (ExtendedOpHandler) Extended

Extended satisfies the ExtendedHandler interface.

type ExtendedPasswordModifyHandlerFunc

type ExtendedPasswordModifyHandlerFunc func(context.Context, string, string, string, string) (ldaputil.Result, error)

ExtendedPasswordModifyHandlerFunc is the password modify handler func type.

type ExtendedRequest

type ExtendedRequest struct {
	Name  ExtendedOp
	Value *ber.Packet
}

func NewExtendedPasswordModifyRequest

func NewExtendedPasswordModifyRequest(id, oldPass, newPass string) (*ExtendedRequest, error)

NewExtendedPasswordModifyRequest creates an extended password modify request.

func NewExtendedWhoAmIRequest

func NewExtendedWhoAmIRequest() (*ExtendedRequest, error)

NewExtendedWhoAmIRequest creates an extended whoami request.

func ParseExtendedRequest

func ParseExtendedRequest(req *Request) (*ExtendedRequest, error)

func (*ExtendedRequest) AppendTo

func (req *ExtendedRequest) AppendTo(p *ber.Packet) error

AppendTo satisfies the Request interface.

func (*ExtendedRequest) BuildPacket

func (req *ExtendedRequest) BuildPacket() *ber.Packet

type ExtendedResponse

type ExtendedResponse struct {
	Result    ldaputil.Result
	MatchedDN string
	Name      ExtendedOp
	Value     *ber.Packet
}

func DoExtendedRequest

func DoExtendedRequest(ctx context.Context, cl *Client, req *ExtendedRequest) (*ExtendedResponse, error)

DoExtendedRequest performs an extended request against the provided context and client.

Note: this is defined primarily for testing purposes, as the client does not provide any direct ability to send extended requests.

func (*ExtendedResponse) BuildPacket

func (res *ExtendedResponse) BuildPacket() *ber.Packet

func (*ExtendedResponse) Encode

func (res *ExtendedResponse) Encode(ctx context.Context, w ResponseWriter) error

Encode satisfies the Encoder interface.

type ExtendedWhoAmIHandlerFunc

type ExtendedWhoAmIHandlerFunc func(context.Context, string) (ldaputil.Result, string, error)

ExtendedWhoAmIHandlerFunc is the who am i handler func type.

type Handler

type Handler interface {
	ServeLDAP(context.Context, ResponseWriter, *Request)
}

Handler is the ldap handler interface.

type HandlerFunc

type HandlerFunc func(context.Context, ResponseWriter, *Request)

HandlerFunc is the ldap handler func type.

func (HandlerFunc) ServeLDAP

func (f HandlerFunc) ServeLDAP(ctx context.Context, res ResponseWriter, req *Request)

ServeLDAP satisfies the Handler interface.

type MessageContext

type MessageContext struct {
	// contains filtered or unexported fields
}

func (*MessageContext) SendResponse

func (msgCtx *MessageContext) SendResponse(res *PacketResponse)

SendResponse should only be called within the processMessages() loop which is also responsible for closing the responses channel.

type ModifyDNHandler

type ModifyDNHandler interface {
	ModifyDN(context.Context, *ModifyDNRequest) (*ModifyDNResponse, error)
}

type ModifyDNHandlerFunc

type ModifyDNHandlerFunc func(context.Context, *ModifyDNRequest) (*ModifyDNResponse, error)

func (ModifyDNHandlerFunc) ModifyDN

type ModifyDNRequest

type ModifyDNRequest struct{}

func ParseModifyDNRequest

func ParseModifyDNRequest(req *Request) (*ModifyDNRequest, error)

type ModifyDNResponse

type ModifyDNResponse struct{}

func (*ModifyDNResponse) Encode

Encode satisfies the Encoder interface.

type ModifyHandler

type ModifyHandler interface {
	Modify(context.Context, *ModifyRequest) (*ModifyResponse, error)
}

type ModifyHandlerFunc

type ModifyHandlerFunc func(context.Context, *ModifyRequest) (*ModifyResponse, error)

func (ModifyHandlerFunc) Modify

type ModifyRequest

type ModifyRequest struct{}

func ParseModifyRequest

func ParseModifyRequest(req *Request) (*ModifyRequest, error)

type ModifyResponse

type ModifyResponse struct{}

func (*ModifyResponse) Encode

Encode satisfies the Encoder interface.

type NTLMBindResult

type NTLMBindResult struct {
	Controls []control.Control
}

NTLMBindResult contains the response from the server

type OpHandler

type OpHandler struct {
	Auth     AuthHandler
	Bind     BindHandler
	Unbind   UnbindHandler
	Search   SearchHandler
	Modify   ModifyHandler
	Add      AddHandler
	Delete   DeleteHandler
	ModifyDN ModifyDNHandler
	Compare  CompareHandler
	Abandon  AbandonHandler
	Extended ExtendedHandler
}

OpHandler is a ldap operation handler.

func (OpHandler) ServeLDAP

func (h OpHandler) ServeLDAP(ctx context.Context, res ResponseWriter, req *Request)

ServeLDAP satisfies the Handler interface.

type PacketResponse

type PacketResponse struct {
	// Packet is the packet read from the server
	Packet *ber.Packet
	// Error is an error encountered while reading
	Error error
}

PacketResponse contains the packet or error encountered reading a response

func (*PacketResponse) ReadPacket

func (pr *PacketResponse) ReadPacket() (*ber.Packet, error)

ReadPacket returns the packet or an error

type PasswordModifyResult

type PasswordModifyResult struct {
	// GeneratedPassword holds a password generated by the server, if present
	GeneratedPassword string
	// Referral are the returned referral
	Referral string
}

PasswordModifyResult holds the server response to a PasswordModifyRequest

type QueryHandler

type QueryHandler interface {
	Query()
}

type Request

type Request struct {
	ConnID     string
	LocalAddr  net.Addr
	RemoteAddr net.Addr
	ID         int64
	Packet     *ber.Packet
}

Request is a ldap request.

func ReadRequest

func ReadRequest(conn net.Conn) (*Request, error)

ReadRequest reads a request from the connection.

type ResponseWriter

type ResponseWriter interface {
	WriteRaw([]byte) error
	WritePacket(*ber.Packet) error
	WriteMessage(*ber.Packet) error
	WriteResult(ldaputil.Application, ldaputil.Result, string, string, ...*ber.Packet) error
	WriteError(ldaputil.Application, error) error
}

ResponseWriter is the ldap response writer interface.

func NewResponseWriter

func NewResponseWriter(w io.Writer, id int64) ResponseWriter

NewResponseWriter creates a new response writer for the writer and message id.

type Scope

type Scope int

Scope is the scope enum.

const (
	ScopeBaseObject Scope = iota
	ScopeSingleLevel
	ScopeWholeSubtree
)

Scope values.

func (Scope) String

func (i Scope) String() string

type SearchEntry

type SearchEntry struct {
}

func (*SearchEntry) Encode

func (v *SearchEntry) Encode(w ResponseWriter) error

type SearchEntryResult

type SearchEntryResult interface {
	Columns() ([]string, error)
	Next() bool
	Scan(...interface{}) error
	Err() error
	Close() error
}

type SearchHandler

type SearchHandler interface {
	Search(context.Context, *SearchRequest) (*SearchResponse, error)
}

func NewSearchQueryHandler

func NewSearchQueryHandler(h QueryHandler) SearchHandler

type SearchHandlerFunc

type SearchHandlerFunc func(context.Context, *SearchRequest) (*SearchResponse, error)

func (SearchHandlerFunc) Search

type SearchRef

type SearchRef struct {
}

func (*SearchRef) Encode

func (v *SearchRef) Encode(w ResponseWriter) error

type SearchRefResult

type SearchRefResult interface {
	Next() bool
	Scan(...interface{}) error
	Err() error
	Close() error
}

type SearchRequest

type SearchRequest struct {
	BaseObject   string
	Scope        Scope
	DerefAliases DerefAliases
	SizeLimit    int64
	TimeLimit    time.Duration
	TypesOnly    bool
	Filter       *ber.Packet
	Attributes   []string
}

func ParseSearchRequest

func ParseSearchRequest(req *Request) (*SearchRequest, error)

type SearchResponse

type SearchResponse struct {
	Result    ldaputil.Result
	MatchedDN string
	Entries   SearchEntryResult
	Refs      SearchRefResult
}

func (*SearchResponse) Encode

func (res *SearchResponse) Encode(ctx context.Context, w ResponseWriter) error

Encode satisfies the Encoder interface.

func (*SearchResponse) WriteDone

func (res *SearchResponse) WriteDone(w ResponseWriter) error

type SearchResult

type SearchResult struct {
	// Entries are the returned entries
	Entries []*Entry
	// Referrals are the returned referrals
	Referrals []string
	// Controls are the returned controls
	Controls []control.Control
}

SearchResult holds the server's response to a search request

func (*SearchResult) PrettyPrint

func (s *SearchResult) PrettyPrint(indent int)

PrettyPrint outputs a human-readable description with indenting

func (*SearchResult) Print

func (s *SearchResult) Print()

Print outputs a human-readable description

type SendMessageFlags

type SendMessageFlags uint

type Server

type Server struct {
	Addr      string
	Handler   Handler
	ErrorLog  *log.Logger
	TLSConfig *tls.Config
	// contains filtered or unexported fields
}

Server is a ldap server.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(ctx context.Context, opts ...func(*net.ListenConfig)) error

ListenAndServe listens and serves ldap connections on the Server's address until the context is closed.

func (*Server) ListenAndServeTLS

func (s *Server) ListenAndServeTLS(ctx context.Context, certFile, keyFile string, opts ...func(*net.ListenConfig)) error

ListenAndServeTLS listens and serves TLS encrypted ldap connections on the Server's address until the context is closed.

func (*Server) Serve

func (s *Server) Serve(ctx context.Context, l net.Listener) error

Serve accepts incoming connections on conn.

func (*Server) ServeTLS

func (s *Server) ServeTLS(ctx context.Context, l net.Listener, certFile, keyFile string) error

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context) error

Shutdown gracefully stops the server. It first closes all listeners and then waits for any running handlers to complete.

Shutdown returns after nil all handlers have completed. ctx.Err() is returned if ctx is canceled.

Any Serve methods return ErrShutdown after Shutdown is called.

type ServerError

type ServerError string

ServerError is a server error.

const (
	ErrServerShutdown                   ServerError = "server shutdown"
	ErrNilHandler                       ServerError = "nil handler"
	ErrPacketHasInvalidNumberOfChildren ServerError = "packet has invalid number of children"
	ErrPacketHasInvalidMessageID        ServerError = "packet has invalid message id"
	ErrPacketHasInvalidClass            ServerError = "packet has invalid class"
	ErrRespChanClosed                   ServerError = "response channel closed"
	ErrCouldNotRetrieveMessage          ServerError = "could not retrieve message"
)

Error values.

func (ServerError) Error

func (err ServerError) Error() string

Error satisfies the error interface.

type Session

type Session struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Session is a ldap session.

func NewSession

func NewSession(conn net.Conn) *Session

NewSession creates a new session

type SessionAuthFunc

type SessionAuthFunc func(context.Context, ldaputil.Application, string) (ldaputil.Result, error)

SessionAuthFunc is the session auth func type.

type SessionAuthHandler

type SessionAuthHandler struct {
	// contains filtered or unexported fields
}

SessionAuthHandler is a session auth handler.

func (SessionAuthHandler) Auth

Auth satisfies the AuthHandler interface.

func (SessionAuthHandler) Bind

Bind satisfies the AuthHandler interface.

func (SessionAuthHandler) Extended

Extended satisfies the AuthHandler interface.

type SessionBindFunc

type SessionBindFunc func(context.Context, string, string) (ldaputil.Result, error)

SessionBindFunc is the session bind func type.

type SessionExtendedFunc

type SessionExtendedFunc func(context.Context, ExtendedOp, string) (ldaputil.Result, error)

SessionExtendedFunc is the sesssion extended auth func type.

type SimpleBindResult

type SimpleBindResult struct {
	Controls []control.Control
}

SimpleBindResult contains the response from the server

type UnbindHandler

type UnbindHandler interface {
	Unbind(context.Context, *UnbindRequest) (*UnbindResponse, error)
}

type UnbindHandlerFunc

type UnbindHandlerFunc func(context.Context, *UnbindRequest) (*UnbindResponse, error)

func (UnbindHandlerFunc) Unbind

type UnbindRequest

type UnbindRequest struct{}

func ParseUnbindRequest

func ParseUnbindRequest(req *Request) (*UnbindRequest, error)

type UnbindResponse

type UnbindResponse struct{}

func (*UnbindResponse) Encode

Encode satisfies the Encoder interface.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL