# README
gldap
gldap
is a framework for building LDAP services. Among other things, it defines abstractions for:
Server
: supports both LDAP and LDAPS (TLS) protocols as well as the StartTLS requests.Request
: represents an LDAP request (bind, search, extended, etc) along with the inbound request message.ResponseWriter
: allows you to compose request responses.Mux
: an ldap request multiplexer. It matches the inbound request against a list of registered route handlers.HandlerFunc
: handlers provided to the Mux which serve individual ldap requests.
Example:
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/jimlambrt/gldap"
)
func main() {
// create a new server
s, err := gldap.NewServer()
if err != nil {
log.Fatalf("unable to create server: %s", err.Error())
}
// create a router and add a bind handler
r, err := gldap.NewMux()
if err != nil {
log.Fatalf("unable to create router: %s", err.Error())
}
r.Bind(bindHandler)
r.Search(searchHandler)
s.Router(r)
go s.Run(":10389") // listen on port 10389
// stop server gracefully when ctrl-c, sigint or sigterm occurs
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()
select {
case <-ctx.Done():
log.Printf("\nstopping directory")
s.Stop()
}
}
func bindHandler(w *gldap.ResponseWriter, r *gldap.Request) {
resp := r.NewBindResponse(
gldap.WithResponseCode(gldap.ResultInvalidCredentials),
)
defer func() {
w.Write(resp)
}()
m, err := r.GetSimpleBindMessage()
if err != nil {
log.Printf("not a simple bind message: %s", err)
return
}
if m.UserName == "alice" {
resp.SetResultCode(gldap.ResultSuccess)
log.Println("bind success")
return
}
func searchHandler(w *gldap.ResponseWriter, r *gldap.Request) {
resp := r.NewSearchDoneResponse()
defer func() {
w.Write(resp)
}()
m, err := r.GetSearchMessage()
if err != nil {
log.Printf("not a search message: %s", err)
return
}
log.Printf("search base dn: %s", m.BaseDN)
log.Printf("search scope: %d", m.Scope)
log.Printf("search filter: %s", m.Filter)
if strings.Contains(m.Filter, "uid=alice") || m.BaseDN == "uid=alice,ou=people,cn=example,dc=org" {
entry := r.NewSearchResponseEntry(
"uid=alice,ou=people,cn=example,dc=org",
gldap.WithAttributes(map[string][]string{
"objectclass": {"top", "person", "organizationalPerson", "inetOrgPerson"},
"uid": {"alice"},
"cn": {"alice eve smith"},
"givenname": {"alice"},
"sn": {"smith"},
"ou": {"people"},
"description": {"friend of Rivest, Shamir and Adleman"},
"password": {"{SSHA}U3waGJVC7MgXYc0YQe7xv7sSePuTP8zN"},
}),
)
entry.AddAttribute("email", []string{"[email protected]"})
w.Write(entry)
resp.SetResultCode(gldap.ResultSuccess)
}
if m.BaseDN == "ou=people,cn=example,dc=org" {
entry := r.NewSearchResponseEntry(
"ou=people,cn=example,dc=org",
gldap.WithAttributes(map[string][]string{
"objectclass": {"organizationalUnit"},
"ou": {"people"},
}),
)
w.Write(entry)
resp.SetResultCode(gldap.ResultSuccess)
}
return
}
Road map
Currently supported features:
ldap
,ldaps
andmTLS
connections- StartTLS Requests
- Bind Requests
- Simple Auth (user/pass)
- Search Requests
- Modify Requests
- Add Requests
- Delete Requests
- Unbind Requests
Future features
At this point, we may wait until issues are opened before planning new features given that all the basic LDAP operations are supported.
gldap.testdirectory
The testdirectory
package built using gldap
which provides an in-memory test
LDAP service with capabilities which make writing tests that depend on an LDAP
service much easier.
testdirectory
is also a great working example of how you can use gldap
to build a custom
ldap server to meet your specific needs.
Example:
// this testdirectory example demonstrates how can start a test directory for
// your unit tests which will automatically stop when the test is complete.
func TestExample(t *testing.T) {
// start a test directory running ldaps on an available free port (defaults)
// that allows anon binds (a default override)
td := testdirectory.Start(t,
testdirectory.WithDefaults(&testdirectory.Defaults{AllowAnonymousBind: true}),
)
// create some test new user entries (using defaults for ou, password, etc)
users := testdirectory.NewUsers(t, []string{"alice", "bob"})
// set the test directories user entries
td.SetUsers(users...)
// INSERT your tests here....
}
# Functions
ConvertString will convert an ASN1 BER Octet string into a "native" go string.
NewControlBeheraPasswordPolicy returns a ControlBeheraPasswordPolicy.
NewControlManageDsaIT returns a ControlManageDsaIT control.
NewControlMicrosoftNotification returns a ControlMicrosoftNotification control.
NewControlMicrosoftServerLinkTTL returns a ControlMicrosoftServerLinkTTL control.
NewControlMicrosoftShowDeleted returns a ControlMicrosoftShowDeleted control.
NewControlPaging returns a paging control.
NewControlString returns a generic control.
NewEntry returns an Entry object with the specified distinguished name and attribute key-value pairs.
NewEntryAttribute returns a new EntryAttribute with the desired key-value pair.
NewMux creates a new multiplexer.
NewServer creates a new ldap server
Options supported: - WithLogger allows you pass a logger with whatever hclog.Level you wish including hclog.Off to turn off all logging - WithReadTimeout will set a read time out per connection - WithWriteTimeout will set a write time out per connection - WithOnClose will define a callback the server will call every time a connection is closed.
SIDBytes creates a SID from the provided revision and identifierAuthority.
SIDBytesToString will convert SID bytes to a string.
No description provided by the author
TestWithDebug specifies that the test should be run under "debug" mode.
WithApplicationCode specifies the ldap application code.
WithAttributes specifies optional attributes for a response entry.
WithBaseDN specifies an optional base DN to associate with a Search route.
WithControlValue specifies the control value.
WithCriticality specifies the criticality.
WithDescription allows you to specify an optional description.
WithDiagnosticMessage provides an optional diagnostic message for the response.
WithDisablePanicRecovery will disable recovery from panics which occur when handling a request.
WithErrorCode specifies the error code.
WithFilter specifies an optional filter to associate with a Search route.
WithGraceAuthNsRemaining specifies the number of grace authentication remaining.
WithLabel specifies an optional label for the route.
WithLogger provides the optional logger.
WithMatchedDN provides an optional match DN for the response.
WithOnClose defines a OnCloseHandler that the server will use as a callback every time a connection to the server is closed.
WithReadTimeout will set a read time out per connection.
WithResponseCode specifies the ldap response code.
WithScope specifies and optional scope to associate with a Search route.
WithSecondsBeforeExpiration specifies the number of seconds before a password will expire.
WithTLSConfig provides an optional tls.Config.
WithWriter allows you to specify an optional writer.
WithWriteTimeout will set a write timeout per connection.
# Constants
Change operation choices.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
ldap application codes.
BaseObject (often referred to as “base”): Indicates that only the entry specified as the search base should be considered.
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
Ldap Behera Password Policy Draft 10 (https://tools.ietf.org/html/draft-behera-ldap-password-policy-10).
ControlTypeBeheraPasswordPolicy - https://tools.ietf.org/html/draft-behera-ldap-password-policy-10.
ControlTypeManageDsaIT - https://tools.ietf.org/html/rfc3296.
ControlTypeMicrosoftNotification - https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx.
ControlTypeMicrosoftServerLinkTTL - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/f4f523a8-abc0-4b3a-a471-6b2fef135481?redirectedfrom=MSDN.
ControlTypeMicrosoftShowDeleted - https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx.
ControlTypePaging - https://www.ietf.org/rfc/rfc2696.txt.
ControlTypeVChuPasswordMustChange - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00.
ControlTypeVChuPasswordWarning - https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00.
ControlTypeWhoAmI - https://tools.ietf.org/html/rfc4532.
Change operation choices.
Extended operation response/request names.
Extended operation response/request names.
Extended operation response/request names.
Extended operation response/request names.
Extended operation response/request names.
Extended operation response/request names.
Extended operation response/request names.
(https://tools.ietf.org/html/rfc4525).
Change operation choices.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
ldap result codes.
SimpleAuthChoice specifies a simple user/password authentication choice for the bind message.
SingleLevel (often referred to as “one”): Indicates that only the immediate children of the entry specified as the search base should be considered.
WholeSubtree (often referred to as “sub”): Indicates that the entry specified as the search base, and all of its subordinates to any depth, should be considered.
# Variables
ApplicationCodeMap contains human readable descriptions of ldap application codes.
BeheraPasswordPolicyErrorMap contains human readable descriptions of Behera Password Policy error codes.
ControlTypeMap maps controls to text descriptions.
ErrInternal is an internal error.
ErrInvalidParameter is an invalid parameter error.
ErrInvalidState is an invalid state error.
ErrUnknown is an unknown/undefined error.
ResultCodeMap contains string descriptions for ldap result codes.
# Structs
AddMessage is an add request message.
Attribute represents an LDAP attribute within AddMessage.
BindResponse represents the response to a bind request.
Change for a ModifyMessage as defined in https://tools.ietf.org/html/rfc4511.
ControlBeheraPasswordPolicy implements the control described in https://tools.ietf.org/html/draft-behera-ldap-password-policy-10.
ControlManageDsaIT implements the control described in https://tools.ietf.org/html/rfc3296.
ControlMicrosoftNotification implements the control described in https://msdn.microsoft.com/en-us/library/aa366983(v=vs.85).aspx.
ControlMicrosoftServerLinkTTL implements the control described in https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/f4f523a8-abc0-4b3a-a471-6b2fef135481?redirectedfrom=MSDN.
ControlMicrosoftShowDeleted implements the control described in https://msdn.microsoft.com/en-us/library/aa366989(v=vs.85).aspx.
ControlPaging implements the paging control described in https://www.ietf.org/rfc/rfc2696.txt.
ControlString implements the Control interface for simple controls.
ControlVChuPasswordMustChange implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00.
ControlVChuPasswordWarning implements the control described in https://tools.ietf.org/html/draft-vchu-ldap-pwd-policy-00.
DeleteMessage is an delete request message.
Entry represents an ldap entry.
EntryAttribute holds a single attribute.
ExtendedOperationMessage is an extended operation request message.
ExtendedResponse represents a response to an extended operation request.
GeneralResponse represents a general response (non-specific to a request).
ModifyMessage as defined in https://tools.ietf.org/html/rfc4511.
ModifyResponse is a response to a modify request.
Mux is an ldap request multiplexer.
PartialAttribute for a ModifyMessage as defined in https://tools.ietf.org/html/rfc4511.
Request represents an ldap request.
ResponseWriter is an ldap request response writer which is used by a HanderFunc to write responses to client requests.
SearchMessage is a search request message.
SearchResponseDone represents that handling a search requests is done.
SearchResponseEntry is an ldap entry that's part of search response.
Server is an ldap server that you can add a mux (multiplexer) router to and then run it to accept and process requests.
SimpleBindMessage is a simple bind request message.
UnbindMessage is an unbind request message.
# Type aliases
AuthChoice defines the authentication choice for bind message.
ExtendedOperationName is an extended operation request/response name.
HandlerFunc defines a function for handling an LDAP request.
OnCloseHandler defines a function for a "on close" callback handler.
Option defines a common functional options type which can be used in a variadic parameter pattern.
Password is a simple bind request password.
Scope represents the scope of a search (see: https://ldap.com/the-ldap-search-operation/).