ldapserver

package
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2015 License: GPL-2.0, Apache-2.0 Imports: 9 Imported by: 0

README

GoDoc Build Status

This package is a work in progress.

I'm co-learning golang with R00x. Have a look at his implementation: https://github.com/lor00x/goldap

ldapserver is a helper library for building server software capable of speaking the LDAP protocol. This could be an alternate implementation of LDAP, a custom LDAP proxy or even a completely different backend capable of "masquerading" its API as a LDAP Server.

The package supports

  • All basic LDAP Operations (bind, search, add, compare, modify, delete, extended)
  • SSL
  • StartTLS
  • Unbind request is implemented, but is handled internally to close the connection.
  • Graceful stopping
  • Basic request routing inspired by net/http ServeMux

Default behavior

When no route matches the request, the server will first try to call a special NotFound route, if nothing is specified, it will return an UnwillingToResponse Error code (53)

Feel free to contribute, comment :)

Sample Code

// Listen to 10389 port for LDAP Request
// and route bind request to the handleBind func
package main

import (
	"log"
	"os"
	"os/signal"
	"syscall"

	ldap "github.com/vjeantet/ldapserver"
)

func main() {
	//LDAP handlers routes
	routes := ldap.NewRouteMux()
	routes.Bind(handleBind)

	//Create a new LDAP Server
	server := ldap.NewServer()
	server.Handle(routes)

	// listen on 10389
	go server.ListenAndServe(":10389")

	// When CTRL+C, SIGINT and SIGTERM signal occurs
	// Then stop server gracefully
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
	<-ch
	close(ch)
	server.Stop()
}

func handleBind(w ldap.ResponseWriter, m *ldap.Message) {
	r := m.GetBindRequest()
	res := ldap.NewBindResponse(ldap.LDAPResultSuccess)

	if string(r.GetLogin()) == "myLogin" {
		w.Write(res)
		return
	}

	res.ResultCode = ldap.LDAPResultInvalidCredentials
	w.Write(res)
}

more examples

Look into the "examples" folder

Documentation

Index

Constants

View Source
const (
	FilterSubstringsInitial = 0
	FilterSubstringsAny     = 1
	FilterSubstringsFinal   = 2
)

filter substrings expressions

View Source
const (
	FilterAnd             = 0
	FilterOr              = 1
	FilterNot             = 2
	FilterEqualityMatch   = 3
	FilterSubstrings      = 4
	FilterGreaterOrEqual  = 5
	FilterLessOrEqual     = 6
	FilterPresent         = 7
	FilterApproxMatch     = 8
	FilterExtensibleMatch = 9
)

Filter expressions

View Source
const (
	ApplicationBindRequest           = 0
	ApplicationBindResponse          = 1
	ApplicationUnbindRequest         = 2
	ApplicationSearchRequest         = 3
	ApplicationSearchResultEntry     = 4
	ApplicationSearchResultDone      = 5
	ApplicationModifyRequest         = 6
	ApplicationModifyResponse        = 7
	ApplicationAddRequest            = 8
	ApplicationAddResponse           = 9
	ApplicationDelRequest            = 10
	ApplicationDelResponse           = 11
	ApplicationModifyDNRequest       = 12
	ApplicationModifyDNResponse      = 13
	ApplicationCompareRequest        = 14
	ApplicationCompareResponse       = 15
	ApplicationAbandonRequest        = 16
	ApplicationSearchResultReference = 19
	ApplicationExtendedRequest       = 23
	ApplicationExtendedResponse      = 24
)

LDAP Application Codes

View Source
const (
	LDAPResultSuccess                      = 0
	LDAPResultOperationsError              = 1
	LDAPResultProtocolError                = 2
	LDAPResultTimeLimitExceeded            = 3
	LDAPResultSizeLimitExceeded            = 4
	LDAPResultCompareFalse                 = 5
	LDAPResultCompareTrue                  = 6
	LDAPResultAuthMethodNotSupported       = 7
	LDAPResultStrongAuthRequired           = 8
	LDAPResultReferral                     = 10
	LDAPResultAdminLimitExceeded           = 11
	LDAPResultUnavailableCriticalExtension = 12
	LDAPResultConfidentialityRequired      = 13
	LDAPResultSaslBindInProgress           = 14
	LDAPResultNoSuchAttribute              = 16
	LDAPResultUndefinedAttributeType       = 17
	LDAPResultInappropriateMatching        = 18
	LDAPResultConstraintViolation          = 19
	LDAPResultAttributeOrValueExists       = 20
	LDAPResultInvalidAttributeSyntax       = 21
	LDAPResultNoSuchObject                 = 32
	LDAPResultAliasProblem                 = 33
	LDAPResultInvalidDNSyntax              = 34
	LDAPResultAliasDereferencingProblem    = 36
	LDAPResultInappropriateAuthentication  = 48
	LDAPResultInvalidCredentials           = 49
	LDAPResultInsufficientAccessRights     = 50
	LDAPResultBusy                         = 51
	LDAPResultUnavailable                  = 52
	LDAPResultUnwillingToPerform           = 53
	LDAPResultLoopDetect                   = 54
	LDAPResultNamingViolation              = 64
	LDAPResultObjectClassViolation         = 65
	LDAPResultNotAllowedOnNonLeaf          = 66
	LDAPResultNotAllowedOnRDN              = 67
	LDAPResultEntryAlreadyExists           = 68
	LDAPResultObjectClassModsProhibited    = 69
	LDAPResultAffectsMultipleDSAs          = 71
	LDAPResultOther                        = 80

	ErrorNetwork         = 200
	ErrorFilterCompile   = 201
	ErrorFilterDecompile = 202
	ErrorDebugging       = 203
)

LDAP Result Codes

View Source
const (
	ModifyRequestChangeOperationAdd     = 0
	ModifyRequestChangeOperationDelete  = 1
	ModifyRequestChangeOperationReplace = 2
)

Modify Request Operation code

View Source
const (
	SearchRequestScopeBaseObject = 0
	SearchRequestSingleLevel     = 1
	SearchRequestHomeSubtree     = 2
)

Search scope constant

View Source
const (
	SEARCH   = "SearchRequest"
	BIND     = "BindRequest"
	COMPARE  = "CompareRequest"
	ADD      = "AddRequest"
	MODIFY   = "ModifyRequest"
	DELETE   = "DeleteRequest"
	EXTENDED = "ExtendedRequest"
	ABANDON  = "AbandonRequest"
)

Constant to LDAP Request protocol Type names

Variables

This section is empty.

Functions

func NewResponse

func NewResponse(resultCode int) *ldapResult

Types

type AbandonRequest

type AbandonRequest int

AbandonRequest operation's function is allow a client to request that the server abandon an uncompleted operation. The Abandon Request is defined as follows:

func (*AbandonRequest) GetIDToAbandon

func (r *AbandonRequest) GetIDToAbandon() int

GetIDToAbandon retrieves the message ID of the operation to abandon

type AddRequest

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

AddRequest is a definition of the Add Operation

func (*AddRequest) GetAttributes

func (r *AddRequest) GetAttributes() AttributeList

func (*AddRequest) GetEntryDN

func (r *AddRequest) GetEntryDN() LDAPDN

type AddResponse

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

func NewAddResponse

func NewAddResponse(resultCode int) *AddResponse

func (*AddResponse) SetMessageID

func (e *AddResponse) SetMessageID(ID int)

type AssertionValue

type AssertionValue OCTETSTRING

AssertionValue ::= OCTET STRING

type Attribute

type Attribute PartialAttribute
Attribute ::= PartialAttribute(WITH COMPONENTS {
     ...,
     vals (SIZE(1..MAX))})

func (*Attribute) GetDescription

func (p *Attribute) GetDescription() AttributeDescription

func (*Attribute) GetValues

func (p *Attribute) GetValues() []AttributeValue

type AttributeDescription

type AttributeDescription LDAPString

AttributeDescription ::= LDAPString

-- Constrained to <attributedescription>
-- [RFC4512]

type AttributeList

type AttributeList []Attribute

AttributeList ::= SEQUENCE OF attribute Attribute

type AttributeValue

type AttributeValue OCTETSTRING

AttributeValue ::= OCTET STRING

type AttributeValueAssertion

type AttributeValueAssertion struct {
	// contains filtered or unexported fields
}
AttributeValueAssertion ::= SEQUENCE {
     attributeDesc   AttributeDescription,
     assertionValue  AssertionValue }

func (*AttributeValueAssertion) GetName

func (a *AttributeValueAssertion) GetName() string

func (*AttributeValueAssertion) GetValue

func (a *AttributeValueAssertion) GetValue() string

type BindRequest

type BindRequest struct {
	Version  int
	Login    []byte
	Password []byte
}

BindRequest struct

func (*BindRequest) GetLogin

func (r *BindRequest) GetLogin() []byte

func (*BindRequest) GetPassword

func (r *BindRequest) GetPassword() []byte

type BindResponse

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

BindResponse consists simply of an indication from the server of the status of the client's request for authentication

func NewBindResponse

func NewBindResponse(resultCode int) *BindResponse

func (*BindResponse) Bytes

func (r *BindResponse) Bytes() []byte

func (*BindResponse) SetMessageID

func (e *BindResponse) SetMessageID(ID int)

type CompareRequest

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

func (*CompareRequest) GetAttributeValueAssertion

func (r *CompareRequest) GetAttributeValueAssertion() *AttributeValueAssertion

func (*CompareRequest) GetEntry

func (r *CompareRequest) GetEntry() LDAPDN

type CompareResponse

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

func NewCompareResponse

func NewCompareResponse(resultCode int) *CompareResponse

func (*CompareResponse) SetMessageID

func (e *CompareResponse) SetMessageID(ID int)

type DeleteRequest

type DeleteRequest LDAPDN

DeleteRequest is a definition of the Delete Operation

func (*DeleteRequest) GetEntryDN

func (r *DeleteRequest) GetEntryDN() LDAPDN

GetEntryDN returns the entry's DN to delete

type DeleteResponse

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

func NewDeleteResponse

func NewDeleteResponse(resultCode int) *DeleteResponse

func (*DeleteResponse) SetMessageID

func (e *DeleteResponse) SetMessageID(ID int)

type ExtendedRequest

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

ExtendedRequest operation allows additional operations to be defined for services not already available in the protocol The Extended operation allows clients to send request with predefined syntaxes and semantics. These may be defined in RFCs or be private to particular implementations.

func (*ExtendedRequest) GetResponseName

func (r *ExtendedRequest) GetResponseName() LDAPOID

func (*ExtendedRequest) GetResponseValue

func (r *ExtendedRequest) GetResponseValue() []byte

type ExtendedResponse

type ExtendedResponse struct {
	ResponseName  LDAPOID
	ResponseValue string
	// contains filtered or unexported fields
}

ExtendedResponse operation allows additional operations to be defined for services not already available in the protocol, like the disconnection notification sent by the server before it stops serving The Extended operation allows clients to receive responses with predefined syntaxes and semantics. These may be defined in RFCs or be private to particular implementations.

func NewExtendedResponse

func NewExtendedResponse(resultCode int) *ExtendedResponse

func (*ExtendedResponse) SetMessageID

func (e *ExtendedResponse) SetMessageID(ID int)

type Handler

type Handler interface {
	ServeLDAP(w ResponseWriter, r *Message)
}

Handler interface used to serve a LDAP Request message

type HandlerFunc

type HandlerFunc func(ResponseWriter, *Message)

HandlerFunc type is an adapter to allow the use of ordinary functions as LDAP handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.

type LDAPDN

type LDAPDN string

LDAPDN is defined to be the representation of a Distinguished Name (DN) after encoding according to the specification

type LDAPOID

type LDAPOID string

LDAPOID is a notational convenience to indicate that the permitted value of this string is a (UTF-8 encoded) dotted-decimal representation of an OBJECT IDENTIFIER. Although an LDAPOID is

const (
	NoticeOfDisconnection   LDAPOID = "1.3.6.1.4.1.1466.2003"
	NoticeOfCancel          LDAPOID = "1.3.6.1.1.8"
	NoticeOfStartTLS        LDAPOID = "1.3.6.1.4.1.1466.20037"
	NoticeOfWhoAmI          LDAPOID = "1.3.6.1.4.1.4203.1.11.3"
	NoticeOfGetConnectionID LDAPOID = "1.3.6.1.4.1.26027.1.6.2"
	NoticeOfPasswordModify  LDAPOID = "1.3.6.1.4.1.4203.1.11.1"
)

Extended operation responseName and requestName

type LDAPString

type LDAPString string

respectively, and have the same single octet UTF-8 encoding. Other Unicode characters have a multiple octet UTF-8 encoding.

type Message

type Message struct {
	Client    *client
	MessageID int

	Controls []interface{}
	Done     chan bool
	// contains filtered or unexported fields
}

func (*Message) Abandon

func (m *Message) Abandon()

Abandon close the Done channel, to notify handler's user function to stop any running process

func (*Message) GetAbandonRequest

func (m *Message) GetAbandonRequest() AbandonRequest

func (*Message) GetAddRequest

func (m *Message) GetAddRequest() AddRequest

func (*Message) GetBindRequest

func (m *Message) GetBindRequest() BindRequest

func (*Message) GetCompareRequest

func (m *Message) GetCompareRequest() CompareRequest

func (*Message) GetDeleteRequest

func (m *Message) GetDeleteRequest() DeleteRequest

func (*Message) GetDoneChannel

func (m *Message) GetDoneChannel() chan bool

GetDoneChannel return a channel, which indicate the the request should be aborted quickly, because the client abandonned the request, the server qui quitting, ...

func (*Message) GetExtendedRequest

func (m *Message) GetExtendedRequest() ExtendedRequest

func (*Message) GetModifyRequest

func (m *Message) GetModifyRequest() ModifyRequest

func (*Message) GetProtocolOp

func (m *Message) GetProtocolOp() ProtocolOp

func (*Message) GetSearchRequest

func (m *Message) GetSearchRequest() SearchRequest

func (*Message) String

func (m *Message) String() string

type ModifyRequest

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

func (*ModifyRequest) GetChanges

func (r *ModifyRequest) GetChanges() []modifyRequestChange

func (*ModifyRequest) GetObject

func (r *ModifyRequest) GetObject() LDAPDN

type ModifyResponse

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

func NewModifyResponse

func NewModifyResponse(resultCode int) *ModifyResponse

func (*ModifyResponse) SetMessageID

func (e *ModifyResponse) SetMessageID(ID int)

type OCTETSTRING

type OCTETSTRING string

OCTETSTRING ASN.1 types

type PartialAttribute

type PartialAttribute struct {
	// contains filtered or unexported fields
}
PartialAttribute ::= SEQUENCE {
     type       AttributeDescription,
     vals       SET OF value AttributeValue }

func (*PartialAttribute) GetDescription

func (p *PartialAttribute) GetDescription() AttributeDescription

func (*PartialAttribute) GetValues

func (p *PartialAttribute) GetValues() []AttributeValue

type PartialAttributeList

type PartialAttributeList []PartialAttribute

PartialAttributeList ::= SEQUENCE OF

partialAttribute PartialAttribute

type ProtocolOp

type ProtocolOp interface {
}

type ResponseWriter

type ResponseWriter interface {
	// Write writes the LDAPResponse to the connection as part of an LDAP reply.
	Write(lr response)
}

ResponseWriter interface is used by an LDAP handler to construct an LDAP response.

type RouteMux

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

RouteMux manages all routes

func NewRouteMux

func NewRouteMux() *RouteMux

NewRouteMux returns a new *RouteMux RouteMux implements ldapserver.Handler

func (*RouteMux) Abandon

func (h *RouteMux) Abandon(handler HandlerFunc) *route

func (*RouteMux) Add

func (h *RouteMux) Add(handler HandlerFunc) *route

func (*RouteMux) Bind

func (h *RouteMux) Bind(handler HandlerFunc) *route

func (*RouteMux) Compare

func (h *RouteMux) Compare(handler HandlerFunc) *route

func (*RouteMux) Delete

func (h *RouteMux) Delete(handler HandlerFunc) *route

func (*RouteMux) Extended

func (h *RouteMux) Extended(handler HandlerFunc) *route

func (*RouteMux) Modify

func (h *RouteMux) Modify(handler HandlerFunc) *route

func (*RouteMux) NotFound

func (h *RouteMux) NotFound(handler HandlerFunc)

func (*RouteMux) Search

func (h *RouteMux) Search(handler HandlerFunc) *route

func (*RouteMux) ServeLDAP

func (h *RouteMux) ServeLDAP(w ResponseWriter, r *Message)

ServeLDAP dispatches the request to the handler whose pattern most closely matches the request request Message.

type SearchRequest

type SearchRequest struct {
	BaseObject   []byte
	Scope        int
	DerefAliases int
	SizeLimit    int
	TimeLimit    int
	TypesOnly    bool
	Attributes   [][]byte
	Filter       string
}

SearchRequest is a definition of the Search Operation baseObject - The name of the base object entry (or possibly the root) relative to which the Search is to be performed

func (*SearchRequest) GetAttributes

func (s *SearchRequest) GetAttributes() [][]byte

func (*SearchRequest) GetBaseObject

func (s *SearchRequest) GetBaseObject() []byte

func (*SearchRequest) GetDerefAliases

func (s *SearchRequest) GetDerefAliases() int

func (*SearchRequest) GetFilter

func (s *SearchRequest) GetFilter() string

func (*SearchRequest) GetScope

func (s *SearchRequest) GetScope() int

func (*SearchRequest) GetSizeLimit

func (s *SearchRequest) GetSizeLimit() int

func (*SearchRequest) GetTimeLimit

func (s *SearchRequest) GetTimeLimit() int

func (*SearchRequest) GetTypesOnly

func (s *SearchRequest) GetTypesOnly() bool

type SearchResponse

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

func NewSearchResultDoneResponse

func NewSearchResultDoneResponse(resultCode int) *SearchResponse

func (*SearchResponse) SetMessageID

func (e *SearchResponse) SetMessageID(ID int)

type SearchResultEntry

type SearchResultEntry struct {
	MessageID int
	// contains filtered or unexported fields
}

SearchResultEntry represents an entry found during the Search

func NewSearchResultEntry

func NewSearchResultEntry() *SearchResultEntry

func (*SearchResultEntry) AddAttribute

func (e *SearchResultEntry) AddAttribute(name AttributeDescription, values ...AttributeValue)

func (*SearchResultEntry) SetDn

func (e *SearchResultEntry) SetDn(dn string)

func (*SearchResultEntry) SetMessageID

func (e *SearchResultEntry) SetMessageID(ID int)

type Server

type Server struct {
	Listener     net.Listener
	ReadTimeout  time.Duration // optional read timeout
	WriteTimeout time.Duration // optional write timeout

	// OnNewConnection, if non-nil, is called on new connections.
	// If it returns non-nil, the connection is closed.
	OnNewConnection func(c net.Conn) error

	// Handler handle ldap message received by client
	// it SHOULD "implement" RequestHandler interface
	Handler Handler
	// contains filtered or unexported fields
}

Server is an LDAP server.

func NewServer

func NewServer() *Server

NewServer return a LDAP Server

func (*Server) Handle

func (s *Server) Handle(h Handler)

Handle registers the handler for the server. If a handler already exists for pattern, Handle panics

func (*Server) ListenAndServe

func (s *Server) ListenAndServe(addr string, options ...func(*Server)) error

ListenAndServe listens on the TCP network address s.Addr and then calls Serve to handle requests on incoming connections. If s.Addr is blank, ":389" is used.

func (*Server) Stop

func (s *Server) Stop()

Termination of the LDAP session is initiated by the server sending a Notice of Disconnection. In this case, each protocol peer gracefully terminates the LDAP session by ceasing exchanges at the LDAP message layer, tearing down any SASL layer, tearing down any TLS layer, and closing the transport connection. A protocol peer may determine that the continuation of any communication would be pernicious, and in this case, it may abruptly terminate the session by ceasing communication and closing the transport connection. In either case, when the LDAP session is terminated.

type UnbindRequest

type UnbindRequest struct {
}

UnbindRequest's function is to terminate an LDAP session. The Unbind operation is not the antithesis of the Bind operation as the name implies. The naming of these operations are historical. The Unbind operation should be thought of as the "quit" operation.

Directories

Path Synopsis
examples
ssl

Jump to

Keyboard shortcuts

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