From c43d537d5bb0eeb491153b00cdefcb54a6178187 Mon Sep 17 00:00:00 2001 From: ned Date: Sun, 23 Nov 2014 12:03:05 -0700 Subject: Implemented other LDAP server operations (add/delete/modify/extended/etc.) and tests. --- server.go | 544 ++++++++++++++++++++++++-------------------------------------- 1 file changed, 211 insertions(+), 333 deletions(-) (limited to 'server.go') diff --git a/server.go b/server.go index 4a46e6f..dcb6406 100644 --- a/server.go +++ b/server.go @@ -2,8 +2,6 @@ package ldap import ( "crypto/tls" - "errors" - "fmt" "github.com/nmcclain/asn1-ber" "io" "log" @@ -13,23 +11,55 @@ import ( ) type Binder interface { - Bind(bindDN, bindSimplePw string, conn net.Conn) (uint64, error) + Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) } type Searcher interface { - Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) + Search(boundDN string, req SearchRequest, conn net.Conn) (ServerSearchResult, error) +} +type Adder interface { + Add(boundDN string, req AddRequest, conn net.Conn) (LDAPResultCode, error) +} +type Modifier interface { + Modify(boundDN string, req ModifyRequest, conn net.Conn) (LDAPResultCode, error) +} +type Deleter interface { + Delete(boundDN, deleteDN string, conn net.Conn) (LDAPResultCode, error) +} +type ModifyDNr interface { + ModifyDN(boundDN string, req ModifyDNRequest, conn net.Conn) (LDAPResultCode, error) +} +type Comparer interface { + Compare(boundDN string, req CompareRequest, conn net.Conn) (LDAPResultCode, error) +} +type Abandoner interface { + Abandon(boundDN string, conn net.Conn) error +} +type Extender interface { + Extended(boundDN string, req ExtendedRequest, conn net.Conn) (LDAPResultCode, error) +} +type Unbinder interface { + Unbind(boundDN string, conn net.Conn) (LDAPResultCode, error) } type Closer interface { - Close(conn net.Conn) error + Close(boundDN string, conn net.Conn) error } -///////////////////////// +// type Server struct { - bindFns map[string]Binder - searchFns map[string]Searcher - closeFns map[string]Closer - quit chan bool + BindFns map[string]Binder + SearchFns map[string]Searcher + AddFns map[string]Adder + ModifyFns map[string]Modifier + DeleteFns map[string]Deleter + ModifyDNFns map[string]ModifyDNr + CompareFns map[string]Comparer + AbandonFns map[string]Abandoner + ExtendedFns map[string]Extender + UnbindFns map[string]Unbinder + CloseFns map[string]Closer + Quit chan bool EnforceLDAP bool - stats *Stats + Stats *Stats } type Stats struct { @@ -44,35 +74,75 @@ type ServerSearchResult struct { Entries []*Entry Referrals []string Controls []Control - ResultCode uint64 + ResultCode LDAPResultCode } -///////////////////////// +// func NewServer() *Server { s := new(Server) - s.quit = make(chan bool) + s.Quit = make(chan bool) d := defaultHandler{} - s.bindFns = make(map[string]Binder) - s.searchFns = make(map[string]Searcher) - s.closeFns = make(map[string]Closer) - s.bindFns[""] = d - s.searchFns[""] = d - s.closeFns[""] = d - s.stats = nil + s.BindFns = make(map[string]Binder) + s.SearchFns = make(map[string]Searcher) + s.AddFns = make(map[string]Adder) + s.ModifyFns = make(map[string]Modifier) + s.DeleteFns = make(map[string]Deleter) + s.ModifyDNFns = make(map[string]ModifyDNr) + s.CompareFns = make(map[string]Comparer) + s.AbandonFns = make(map[string]Abandoner) + s.ExtendedFns = make(map[string]Extender) + s.UnbindFns = make(map[string]Unbinder) + s.CloseFns = make(map[string]Closer) + s.BindFunc("", d) + s.SearchFunc("", d) + s.AddFunc("", d) + s.ModifyFunc("", d) + s.DeleteFunc("", d) + s.ModifyDNFunc("", d) + s.CompareFunc("", d) + s.AbandonFunc("", d) + s.ExtendedFunc("", d) + s.UnbindFunc("", d) + s.CloseFunc("", d) + s.Stats = nil return s } -func (server *Server) BindFunc(baseDN string, bindFn Binder) { - server.bindFns[baseDN] = bindFn +func (server *Server) BindFunc(baseDN string, f Binder) { + server.BindFns[baseDN] = f +} +func (server *Server) SearchFunc(baseDN string, f Searcher) { + server.SearchFns[baseDN] = f +} +func (server *Server) AddFunc(baseDN string, f Adder) { + server.AddFns[baseDN] = f +} +func (server *Server) ModifyFunc(baseDN string, f Modifier) { + server.ModifyFns[baseDN] = f } -func (server *Server) SearchFunc(baseDN string, searchFn Searcher) { - server.searchFns[baseDN] = searchFn +func (server *Server) DeleteFunc(baseDN string, f Deleter) { + server.DeleteFns[baseDN] = f } -func (server *Server) CloseFunc(baseDN string, closeFn Closer) { - server.closeFns[baseDN] = closeFn +func (server *Server) ModifyDNFunc(baseDN string, f ModifyDNr) { + server.ModifyDNFns[baseDN] = f +} +func (server *Server) CompareFunc(baseDN string, f Comparer) { + server.CompareFns[baseDN] = f +} +func (server *Server) AbandonFunc(baseDN string, f Abandoner) { + server.AbandonFns[baseDN] = f +} +func (server *Server) ExtendedFunc(baseDN string, f Extender) { + server.ExtendedFns[baseDN] = f +} +func (server *Server) UnbindFunc(baseDN string, f Unbinder) { + server.UnbindFns[baseDN] = f +} +func (server *Server) CloseFunc(baseDN string, f Closer) { + server.CloseFns[baseDN] = f } func (server *Server) QuitChannel(quit chan bool) { - server.quit = quit + server.Quit = quit } func (server *Server) ListenAndServeTLS(listenString string, certFile string, keyFile string) error { @@ -95,18 +165,18 @@ func (server *Server) ListenAndServeTLS(listenString string, certFile string, ke func (server *Server) SetStats(enable bool) { if enable { - server.stats = &Stats{} + server.Stats = &Stats{} } else { - server.stats = nil + server.Stats = nil } } func (server *Server) GetStats() Stats { defer func() { - server.stats.statsMutex.Unlock() + server.Stats.statsMutex.Unlock() }() - server.stats.statsMutex.Lock() - return *server.stats + server.Stats.statsMutex.Lock() + return *server.Stats } func (server *Server) ListenAndServe(listenString string) error { @@ -140,9 +210,9 @@ listener: for { select { case c := <-newConn: - server.stats.countConns(1) + server.Stats.countConns(1) go server.handleConnection(c) - case <-server.quit: + case <-server.Quit: ln.Close() break listener } @@ -150,8 +220,7 @@ listener: return nil } -///////////////////////// - +// func (server *Server) handleConnection(conn net.Conn) { boundDN := "" // "" == anonymous @@ -172,40 +241,46 @@ handler: break } // check the message ID and ClassType - messageID := packet.Children[0].Value.(uint64) + messageID, ok := packet.Children[0].Value.(uint64) + if !ok { + log.Print("malformed messageID") + break + } req := packet.Children[1] if req.ClassType != ber.ClassApplication { log.Print("req.ClassType != ber.ClassApplication") break } // handle controls if present + controls := []Control{} if len(packet.Children) > 2 { - controls := packet.Children[2] - ber.PrintPacket(controls) - log.Print("TODO Parse Controls") - /* - Controls ::= SEQUENCE OF control Control - - Control ::= SEQUENCE { - controlType LDAPOID, - criticality BOOLEAN DEFAULT FALSE, // unavailableCriticalExtension - controlValue OCTET STRING OPTIONAL } - */ + for _, child := range packet.Children[2].Children { + controls = append(controls, DecodeControl(child)) + } } + //log.Printf("DEBUG: handling operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) + //ber.PrintPacket(packet) // DEBUG + // dispatch the LDAP operation switch req.Tag { // ldap op code default: - //log.Printf("Bound as %s", boundDN) - //ber.PrintPacket(packet) + responsePacket := encodeLDAPResponse(messageID, ApplicationAddResponse, LDAPResultOperationsError, "Unsupported operation: add") + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + } log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) break handler case ApplicationBindRequest: - server.stats.countBinds(1) - ldapResultCode := server.handleBindRequest(req, server.bindFns, conn) + server.Stats.countBinds(1) + ldapResultCode := HandleBindRequest(req, server.BindFns, conn) if ldapResultCode == LDAPResultSuccess { - boundDN = req.Children[1].Value.(string) + boundDN, ok = req.Children[1].Value.(string) + if !ok { + log.Printf("Malformed Bind DN") + break handler + } } responsePacket := encodeBindResponse(messageID, ldapResultCode) if err = sendPacket(conn, responsePacket); err != nil { @@ -213,12 +288,13 @@ handler: break handler } case ApplicationSearchRequest: - server.stats.countSearches(1) - if err := server.handleSearchRequest(req, messageID, boundDN, server.searchFns, conn); err != nil { + server.Stats.countSearches(1) + if err := HandleSearchRequest(req, &controls, messageID, boundDN, server, conn); err != nil { log.Printf("handleSearchRequest error %s", err.Error()) // TODO: make this more testable/better err handling - stop using log, stop using breaks? e := err.(*Error) - if err = sendPacket(conn, encodeSearchDone(messageID, uint64(e.ResultCode))); err != nil { + if err = sendPacket(conn, encodeSearchDone(messageID, e.ResultCode)); err != nil { log.Printf("sendPacket error %s", err.Error()) + break handler } break handler } else { @@ -228,181 +304,65 @@ handler: } } case ApplicationUnbindRequest: - server.stats.countUnbinds(1) - break handler // simply disconnect - this IS implemented + server.Stats.countUnbinds(1) + break handler // simply disconnect case ApplicationExtendedRequest: - responsePacket := encodeLDAPResponse(messageID, ApplicationExtendedResponse, LDAPResultProtocolError, "Unsupported extended request") + ldapResultCode := HandleExtendedRequest(req, boundDN, server.ExtendedFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationExtendedResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) if err = sendPacket(conn, responsePacket); err != nil { log.Printf("sendPacket error %s", err.Error()) + break handler } - break handler case ApplicationAbandonRequest: - log.Printf("Abandoning request!") + HandleAbandonRequest(req, boundDN, server.AbandonFns, conn) break handler - // Unimplemented LDAP operations: - case ApplicationModifyRequest: - log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) - break handler case ApplicationAddRequest: - log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) - break handler - case ApplicationDelRequest: - log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) - break handler - case ApplicationModifyDNRequest: - log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) - break handler - case ApplicationCompareRequest: - log.Printf("Unhandled operation: %s [%d]", ApplicationMap[req.Tag], req.Tag) - break handler - } - } - - for _, c := range server.closeFns { - c.Close(conn) - } - - conn.Close() -} - -///////////////////////// -func (server *Server) handleSearchRequest(req *ber.Packet, messageID uint64, boundDN string, searchFns map[string]Searcher, conn net.Conn) (resultErr error) { - defer func() { - if r := recover(); r != nil { - resultErr = NewError(LDAPResultOperationsError, fmt.Errorf("Search function panic: %s", r)) - } - }() - - searchReq, err := parseSearchRequest(boundDN, req) - if err != nil { - return NewError(LDAPResultOperationsError, err) - } - - filterPacket, err := CompileFilter(searchReq.Filter) - if err != nil { - return NewError(LDAPResultOperationsError, err) - } - - fnNames := []string{} - for k := range searchFns { - fnNames = append(fnNames, k) - } - searchFn := routeFunc(searchReq.BaseDN, fnNames) - searchResp, err := searchFns[searchFn].Search(boundDN, searchReq, conn) - if err != nil { - return NewError(uint8(searchResp.ResultCode), err) - } - - if server.EnforceLDAP { - if searchReq.DerefAliases != NeverDerefAliases { // [-a {never|always|search|find} - // TODO: Server DerefAliases not implemented: RFC4511 4.5.1.3. SearchRequest.derefAliases - } - if len(searchReq.Controls) > 0 { - return NewError(LDAPResultOperationsError, errors.New("Server controls not implemented")) // TODO - } - if searchReq.TimeLimit > 0 { - return NewError(LDAPResultOperationsError, errors.New("Server TimeLimit not implemented")) // TODO - } - } - - for i, entry := range searchResp.Entries { - if server.EnforceLDAP { - // size limit - if searchReq.SizeLimit > 0 && i >= searchReq.SizeLimit { - break + ldapResultCode := HandleAddRequest(req, boundDN, server.AddFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationAddResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + break handler } - - // filter - keep, resultCode := ServerApplyFilter(filterPacket, entry) - if resultCode != LDAPResultSuccess { - return NewError(uint8(resultCode), errors.New("ServerApplyFilter error")) + case ApplicationModifyRequest: + ldapResultCode := HandleModifyRequest(req, boundDN, server.ModifyFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationModifyResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + break handler } - if !keep { - continue + case ApplicationDelRequest: + ldapResultCode := HandleDeleteRequest(req, boundDN, server.DeleteFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationDelResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + break handler } - - // constrained search scope - switch searchReq.Scope { - case ScopeWholeSubtree: // The scope is constrained to the entry named by baseObject and to all its subordinates. - case ScopeBaseObject: // The scope is constrained to the entry named by baseObject. - if entry.DN != searchReq.BaseDN { - continue - } - case ScopeSingleLevel: // The scope is constrained to the immediate subordinates of the entry named by baseObject. - parts := strings.Split(entry.DN, ",") - if len(parts) < 2 && entry.DN != searchReq.BaseDN { - continue - } - if dn := strings.Join(parts[1:], ","); dn != searchReq.BaseDN { - continue - } + case ApplicationModifyDNRequest: + ldapResultCode := HandleModifyDNRequest(req, boundDN, server.ModifyDNFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationModifyDNResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + break handler } - - // attributes - if len(searchReq.Attributes) > 1 || (len(searchReq.Attributes) == 1 && len(searchReq.Attributes[0]) > 0) { - entry, err = filterAttributes(entry, searchReq.Attributes) - if err != nil { - return NewError(LDAPResultOperationsError, err) - } + case ApplicationCompareRequest: + ldapResultCode := HandleCompareRequest(req, boundDN, server.CompareFns, conn) + responsePacket := encodeLDAPResponse(messageID, ApplicationCompareResponse, ldapResultCode, LDAPResultCodeMap[ldapResultCode]) + if err = sendPacket(conn, responsePacket); err != nil { + log.Printf("sendPacket error %s", err.Error()) + break handler } } - - // respond - responsePacket := encodeSearchResponse(messageID, searchReq, entry) - if err = sendPacket(conn, responsePacket); err != nil { - return NewError(LDAPResultOperationsError, err) - } } - return nil -} -///////////////////////// -func (server *Server) handleBindRequest(req *ber.Packet, bindFns map[string]Binder, conn net.Conn) (resultCode uint64) { - defer func() { - if r := recover(); r != nil { - resultCode = LDAPResultOperationsError - } - }() - - // we only support ldapv3 - ldapVersion := req.Children[0].Value.(uint64) - if ldapVersion != 3 { - log.Printf("Unsupported LDAP version: %d", ldapVersion) - return LDAPResultInappropriateAuthentication + for _, c := range server.CloseFns { + c.Close(boundDN, conn) } - // auth types - bindDN := req.Children[1].Value.(string) - bindAuth := req.Children[2] - switch bindAuth.Tag { - default: - log.Print("Unknown LDAP authentication method") - return LDAPResultInappropriateAuthentication - case LDAPBindAuthSimple: - if len(req.Children) == 3 { - fnNames := []string{} - for k := range bindFns { - fnNames = append(fnNames, k) - } - bindFn := routeFunc(bindDN, fnNames) - resultCode, err := bindFns[bindFn].Bind(bindDN, bindAuth.Data.String(), conn) - if err != nil { - log.Printf("BindFn Error %s", err.Error()) - } - return resultCode - } else { - log.Print("Simple bind request has wrong # children. len(req.Children) != 3") - return LDAPResultInappropriateAuthentication - } - case LDAPBindAuthSASL: - log.Print("SASL authentication is not supported") - return LDAPResultInappropriateAuthentication - } - return LDAPResultOperationsError + conn.Close() } -///////////////////////// +// func sendPacket(conn net.Conn, packet *ber.Packet) error { _, err := conn.Write(packet.Bytes()) if err != nil { @@ -412,38 +372,7 @@ func sendPacket(conn net.Conn, packet *ber.Packet) error { return nil } -///////////////////////// -func parseSearchRequest(boundDN string, req *ber.Packet) (SearchRequest, error) { - if len(req.Children) != 8 { - return SearchRequest{}, NewError(LDAPResultOperationsError, errors.New("Bad search request")) - } - - // Parse the request - baseObject := req.Children[0].Value.(string) - scope := int(req.Children[1].Value.(uint64)) - derefAliases := int(req.Children[2].Value.(uint64)) - sizeLimit := int(req.Children[3].Value.(uint64)) - timeLimit := int(req.Children[4].Value.(uint64)) - typesOnly := false - if req.Children[5].Value != nil { - typesOnly = req.Children[5].Value.(bool) - } - filter, err := DecompileFilter(req.Children[6]) - if err != nil { - return SearchRequest{}, err - } - attributes := []string{} - for _, attr := range req.Children[7].Children { - attributes = append(attributes, attr.Value.(string)) - } - searchReq := SearchRequest{baseObject, scope, - derefAliases, sizeLimit, timeLimit, - typesOnly, filter, attributes, nil} - - return searchReq, nil -} - -///////////////////////// +// func routeFunc(dn string, funcNames []string) string { bestPick := "" for _, fn := range funcNames { @@ -460,109 +389,58 @@ func routeFunc(dn string, funcNames []string) string { return bestPick } -///////////////////////// -func filterAttributes(entry *Entry, attributes []string) (*Entry, error) { - // only return requested attributes - newAttributes := []*EntryAttribute{} - - for _, attr := range entry.Attributes { - for _, requested := range attributes { - if strings.ToLower(attr.Name) == strings.ToLower(requested) { - newAttributes = append(newAttributes, attr) - } - } - } - entry.Attributes = newAttributes - - return entry, nil +// +func encodeLDAPResponse(messageID uint64, responseType uint8, ldapResultCode LDAPResultCode, message string) *ber.Packet { + responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response") + responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID")) + reponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, responseType, nil, ApplicationMap[responseType]) + reponse.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ldapResultCode), "resultCode: ")) + reponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: ")) + reponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, message, "errorMessage: ")) + responsePacket.AppendChild(reponse) + return responsePacket } -///////////////////////// +// type defaultHandler struct { } -func (h defaultHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (uint64, error) { - return LDAPResultInappropriateAuthentication, nil +func (h defaultHandler) Bind(bindDN, bindSimplePw string, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInvalidCredentials, nil } -func (h defaultHandler) Search(boundDN string, searchReq SearchRequest, conn net.Conn) (ServerSearchResult, error) { +func (h defaultHandler) Search(boundDN string, req SearchRequest, conn net.Conn) (ServerSearchResult, error) { return ServerSearchResult{make([]*Entry, 0), []string{}, []Control{}, LDAPResultSuccess}, nil } -func (h defaultHandler) Close(conn net.Conn) error { - conn.Close() - return nil +func (h defaultHandler) Add(boundDN string, req AddRequest, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInsufficientAccessRights, nil } - -///////////////////////// -func encodeBindResponse(messageID uint64, ldapResultCode uint64) *ber.Packet { - responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response") - responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID")) - - bindReponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response") - bindReponse.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, ldapResultCode, "resultCode: ")) - bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: ")) - bindReponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "errorMessage: ")) - - responsePacket.AppendChild(bindReponse) - - // ber.PrintPacket(responsePacket) - return responsePacket +func (h defaultHandler) Modify(boundDN string, req ModifyRequest, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInsufficientAccessRights, nil } -func encodeSearchResponse(messageID uint64, req SearchRequest, res *Entry) *ber.Packet { - responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response") - responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID")) - - searchEntry := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchResultEntry, nil, "Search Result Entry") - searchEntry.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, res.DN, "Object Name")) - - attrs := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes:") - for _, attribute := range res.Attributes { - attrs.AppendChild(encodeSearchAttribute(attribute.Name, attribute.Values)) - } - - searchEntry.AppendChild(attrs) - responsePacket.AppendChild(searchEntry) - - return responsePacket +func (h defaultHandler) Delete(boundDN, deleteDN string, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInsufficientAccessRights, nil } - -func encodeSearchAttribute(name string, values []string) *ber.Packet { - packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attribute") - packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, name, "Attribute Name")) - - valuesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "Attribute Values") - for _, value := range values { - valuesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Attribute Value")) - } - - packet.AppendChild(valuesPacket) - - return packet +func (h defaultHandler) ModifyDN(boundDN string, req ModifyDNRequest, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInsufficientAccessRights, nil } - -func encodeSearchDone(messageID uint64, ldapResultCode uint64) *ber.Packet { - responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response") - responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID")) - donePacket := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchResultDone, nil, "Search result done") - donePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, ldapResultCode, "resultCode: ")) - donePacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: ")) - donePacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "errorMessage: ")) - responsePacket.AppendChild(donePacket) - - return responsePacket +func (h defaultHandler) Compare(boundDN string, req CompareRequest, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultInsufficientAccessRights, nil } - -func encodeLDAPResponse(messageID uint64, responseType uint8, ldapResultCode uint64, message string) *ber.Packet { - responsePacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Response") - responsePacket.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "Message ID")) - reponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, responseType, nil, ApplicationMap[responseType]) - reponse.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, ldapResultCode, "resultCode: ")) - reponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, "", "matchedDN: ")) - reponse.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, message, "errorMessage: ")) - responsePacket.AppendChild(reponse) - return responsePacket +func (h defaultHandler) Abandon(boundDN string, conn net.Conn) error { + return nil +} +func (h defaultHandler) Extended(boundDN string, req ExtendedRequest, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultProtocolError, nil +} +func (h defaultHandler) Unbind(boundDN string, conn net.Conn) (LDAPResultCode, error) { + return LDAPResultSuccess, nil +} +func (h defaultHandler) Close(boundDN string, conn net.Conn) error { + conn.Close() + return nil } -///////////////////////// +// func (stats *Stats) countConns(delta int) { if stats != nil { stats.statsMutex.Lock() @@ -592,4 +470,4 @@ func (stats *Stats) countSearches(delta int) { } } -///////////////////////// +// -- cgit v1.2.3