Build LDAP services w/ Go

gldap

Go Reference Coverage Go Report Card


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 and mTLS 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

Go Reference

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....
}
Owner
Jim
Software Engineer @hashicorp
Jim
Comments
  • Support for attach and fetch custom data with connection

    Support for attach and fetch custom data with connection

    Is your feature request related to a problem? Please describe. Currently, in order to maintain connection session data, we can use Request.GetConnectionID() to build an extra session table. Normally the session will be cleared when an unbind request is received. But when the connection is closed without receiving an unbind request, the related session cannot be correctly cleared.

    Describe the solution you'd like Provide methods to attach and fetch custom data with each connection:

    type conn struct {
            ...
    	extra interface{}
    }
    
    func (r *Request) SetConnectionExtra(value interface{}) {
    	r.conn.extra = value
    }
    func (r *Request) GetConnectionExtra() interface{} {
    	return r.conn.extra
    }
    
  • Support for mapping user after a Bind request

    Support for mapping user after a Bind request

    Is your feature request related to a problem? Please describe. I am creating an LDAP server using gldap and I can't figure out how to ensure that a user performing a search operation has been successfully authenticated just before.

    Describe the solution you'd like It might be helpful to provide at least the connection ID on each message to know "who" (i.e. which connection) made the request.

    Describe alternatives you've considered I tried to use any accessible information on the request message to bypass that, but couldn't find anything that would help.

  • Support Bind request controls

    Support Bind request controls

    Is your feature request related to a problem? Please describe.

    Currently, there's no way to receive Controls on inbound Bind requests or send Controls back with Bind responses.

    Describe the solution you'd like

    Add support for Controls on both Bind requests and responses.

  • Jimlambrt onclose callback

    Jimlambrt onclose callback

    WithOnClose(...) allows callers to define an optional OnCloseHandler that the server will use as a callback every time a connection to the server is closed. This allows callers to clean up resources for closed connections (using the conn ID to determine which one to clean up)

    Fixes https://github.com/jimlambrt/gldap/issues/37

  • feature: support for deleting an entry

    feature: support for deleting an entry

    PR includes:

    • chore: clean up a few cut/paste errors from previous commits
    • docs: updated docs based on effort to add the "delete" cmd
    • feature: support for deleting an entry
  • Quality improvements in:  testdirectory and packets

    Quality improvements in: testdirectory and packets

    This PR includes:

    • tests (testdirectory): additional testingT unit tests
    • tests (testdirectory): additional fixture unit tests
    • tests (testdirectory): additional options unit tests
    • fix (packet): properly assert search attribute packets
    • tests (testdirectory): additional directory unit tests
    • chore: updates from "make fmt"
  • Quality improvements in: conn, decodeControl, Entry and EntryAttribute

    Quality improvements in: conn, decodeControl, Entry and EntryAttribute

    This PR includes:

    • fix: check netConn properly when initializing a conn
    • fix: check the shutdown ctx when creating a new conn
    • chore: remove extra blank line found with gofumpt
    • fix: improve decodeControl(...) data validation
    • feature: support WithWriter option for PrettyPrint
    • tests: improve Entry/EntryAttribute unit tests
  • refactor: clean up some control bits

    refactor: clean up some control bits

    The following now validate their parameters and use options: NewControlString(...) NewControlManageDsaIT(...) NewControlMicrosoftShowDeleted(...) NewControlMicrosoftServerLinkTTL(...) NewControlMicrosoftShowDeleted(...) NewControlPaging(...)

  • Support search request Controls

    Support search request Controls

    Is your feature request related to a problem? Please describe.

    Currently, there's no way to receive Controls on inbound Search requests or send Controls back with Search responses.

    Describe the solution you'd like

    Add support for Controls on both Search requests and responses.

  • Support for Unbind

    Support for Unbind

    Is your feature request related to a problem? Please describe. Currently, there's no way to unbind from a server. Even if you send an unbind request, the server will continue to serve requests for the connection

    Describe the solution you'd like Add support for an Unbind request and stop serving requests for any connection that receives an unbind request.

  • Support for both LDAP and LDAP3 clients

    Support for both LDAP and LDAP3 clients

    Is your feature request related to a problem? Please describe. Currently, we only support binding with an LDAP3 client and clients using the previous version of the protocol are unable to bind.

    Describe the solution you'd like Support both LDAP and LDAP3 clients but allow the developer an option to only support LDAP3 if they wish via a new Option when creating a NewServer. This new WithRequiredVersion option will have to be passed along from the Server to each new conn and then to each new request, so it can be enforced when the new message is created.

Proof-of-Concept tool for CVE-2021-29156, an LDAP injection vulnerability in ForgeRock OpenAM v13.0.0.

CVE-2021-29156 Proof-of-Concept (c) 2021 GuidePoint Security Charlton Trezevant [email protected] Background Today GuidePoint

Apr 13, 2022
Help fuzz various protocols and waits for ping backs Integrates LDAP server and JNDI payload

l9fuzz Fuzzes various protocols with JNDI LDAP payloads and listen for ping backs Features Low CPU/Memory footprint Integrated LDAP server Trace orign

Jan 13, 2022
Nov 9, 2022
Kerberoasting attack implementation in Golang using go-ldap and gokrb5
Kerberoasting attack implementation in Golang using go-ldap and gokrb5

Goberoast Kerberoasting attack implementation in Golang using go-ldap and gokrb5. Build You can build the project by simply typing go build within the

Jan 19, 2022
PoC for running AWS services(kinesis, dynamodb, lambdas) locally with Localstack

hotdog-localstack-PoC PoC for running AWS services(kinesis, dynamodb, lambdas) locally with Localstack alias awslocal="aws --endpoint-url=http://local

Dec 3, 2022
Build awesome Golang desktop apps and beautiful interfaces with Vue.js, React.js, Framework 7, and more...
Build awesome Golang desktop apps and beautiful interfaces with Vue.js, React.js, Framework 7, and more...

Guark Guark allows you to build beautiful user interfaces using modern web technologies such as Vue.js, React.js..., while your app logic handled and

Jan 1, 2023
Build Go applications for IOS
Build Go applications for IOS

go-build-for-ios Build Go applications for IOS This repository contains a PoC that lets you build any Go application for IOS platform. Cross-compilati

Jul 18, 2022
A port scan and service weakpass brute tool build by golang.
A port scan and service weakpass brute tool build by golang.

A port scan and service weakpass brute tool build by golang.

Jan 5, 2023
Build & Scan - Container Image

BSImage (build&scan image) Requirements Trivy Docker BSImage (shell script version) Usage of build (shell script version) ./bsimage.sh start <image:ta

Apr 12, 2022
Jan 9, 2023
A minimalistic LDAP server that is meant for test vulnerability to JNDI+LDAP injection attacks in Java, especially CVE-2021-44228.

jndi-ldap-test-server This is a minimalistic LDAP server that is meant for test vulnerability to JNDI+LDAP injection attacks in Java, especially CVE-2

Oct 3, 2022
Mail-alias-resolve-ldap - Resolve mail alias addresses in LDAP

alias-resolve-ldap alias-resolve-ldap was written to be used as a hook for the c

Jan 30, 2022
Go-ldap-pool - A simple connection pool for go-ldap

Basic connection pool for go-ldap This little library use the go-ldap library an

Dec 17, 2022
Build LDAP services w/ Go

gldap gldap is a framework for building LDAP services. Among other things, it defines abstractions for: Server: supports both LDAP and LDAPS (TLS) pro

Jan 6, 2023
Basic LDAP v3 functionality for the GO programming language.

Basic LDAP v3 functionality for the GO programming language. Install For the latest version use: go get gopkg.in/ldap.v2 Import the latest version wi

May 24, 2022
HA LDAP based key/value solution for projects configuration storing with multi master replication support

Recon is the simple solution for storing configs of you application. There are no specified instruments, no specified data protocols. For the full power of Recon you only need curl.

Jun 15, 2022
Basic LDAP v3 functionality for the GO programming language.

Basic LDAP v3 functionality for the GO programming language. The library implements the following specifications: https://tools.ietf.org/html/rfc4511

Dec 31, 2022
Proof-of-Concept tool for CVE-2021-29156, an LDAP injection vulnerability in ForgeRock OpenAM v13.0.0.

CVE-2021-29156 Proof-of-Concept (c) 2021 GuidePoint Security Charlton Trezevant [email protected] Background Today GuidePoint

Apr 13, 2022
A system written in Golang to help ops team to automate the process of mapping Vault groups to LDAP Groups.

A system written in Golang to help ops team to automate the process of mapping Vault groups to LDAP Groups. This utility automatically adds LDAP Groups' members to the corresponding Vault Groups.

Nov 12, 2021
Help fuzz various protocols and waits for ping backs Integrates LDAP server and JNDI payload

l9fuzz Fuzzes various protocols with JNDI LDAP payloads and listen for ping backs Features Low CPU/Memory footprint Integrated LDAP server Trace orign

Jan 13, 2022