diff options
Diffstat (limited to 'examples/proxy.go')
-rw-r--r-- | examples/proxy.go | 106 |
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) +} |