summaryrefslogtreecommitdiffstats
path: root/examples/proxy.go
diff options
context:
space:
mode:
Diffstat (limited to 'examples/proxy.go')
-rw-r--r--examples/proxy.go106
1 files changed, 106 insertions, 0 deletions
diff --git a/examples/proxy.go b/examples/proxy.go
new file mode 100644
index 0000000..d6b01d0
--- /dev/null
+++ b/examples/proxy.go
@@ -0,0 +1,106 @@
+package main
+
+import (
+ "crypto/sha256"
+ "fmt"
+ "github.com/nmcclain/ldap"
+ "log"
+ "net"
+ "sync"
+)
+
+type ldapHandler struct {
+ sessions map[string]session
+ lock sync.Mutex
+ ldapServer string
+ ldapPort int
+}
+
+///////////// Run a simple LDAP proxy
+func main() {
+ s := ldap.NewServer()
+
+ handler := ldapHandler{
+ sessions: make(map[string]session),
+ ldapServer: "localhost",
+ ldapPort: 3389,
+ }
+ s.BindFunc("", handler)
+ s.SearchFunc("", handler)
+ s.CloseFunc("", handler)
+
+ // start the server
+ if err := s.ListenAndServe("localhost:3388"); err != nil {
+ log.Fatal("LDAP Server Failed: %s", err.Error())
+ }
+}
+
+/////////////
+type session struct {
+ id string
+ c net.Conn
+ ldap *ldap.Conn
+}
+
+func (h ldapHandler) getSession(conn net.Conn) (session, error) {
+ id := connID(conn)
+ h.lock.Lock()
+ s, ok := h.sessions[id] // use server connection if it exists
+ h.lock.Unlock()
+ if !ok { // open a new server connection if not
+ l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", h.ldapServer, h.ldapPort))
+ if err != nil {
+ return session{}, err
+ }
+ s = session{id: id, c: conn, ldap: l}
+ h.lock.Lock()
+ h.sessions[s.id] = s
+ h.lock.Unlock()
+ }
+ return s, nil
+}
+
+/////////////
+func (h ldapHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (uint64, error) {
+ s, err := h.getSession(conn)
+ if err != nil {
+ return ldap.LDAPResultOperationsError, err
+ }
+ if err := s.ldap.Bind(bindDN, bindSimplePw); err != nil {
+ return ldap.LDAPResultOperationsError, err
+ }
+ return ldap.LDAPResultSuccess, nil
+}
+
+/////////////
+func (h ldapHandler) Search(boundDN string, searchReq ldap.SearchRequest, conn net.Conn) (ldap.ServerSearchResult, error) {
+ s, err := h.getSession(conn)
+ if err != nil {
+ return ldap.ServerSearchResult{ResultCode: ldap.LDAPResultOperationsError}, nil
+ }
+ search := ldap.NewSearchRequest(
+ searchReq.BaseDN,
+ ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
+ searchReq.Filter,
+ searchReq.Attributes,
+ nil)
+ sr, err := s.ldap.Search(search)
+ if err != nil {
+ return ldap.ServerSearchResult{}, err
+ }
+ //log.Printf("P: Search OK: %s -> num of entries = %d\n", search.Filter, len(sr.Entries))
+ return ldap.ServerSearchResult{sr.Entries, []string{}, []ldap.Control{}, ldap.LDAPResultSuccess}, nil
+}
+func (h ldapHandler) Close(conn net.Conn) error {
+ conn.Close() // close connection to the server when then client is closed
+ h.lock.Lock()
+ defer h.lock.Unlock()
+ delete(h.sessions, connID(conn))
+ return nil
+}
+func connID(conn net.Conn) string {
+ h := sha256.New()
+ h.Write([]byte(conn.LocalAddr().String() + conn.RemoteAddr().String()))
+ sha := fmt.Sprintf("% x", h.Sum(nil))
+ return string(sha)
+}