|
@@ -0,0 +1,302 @@
|
|
|
+// Copyright 2011 The Go Authors. All rights reserved.
|
|
|
+// Use of this source code is governed by a BSD-style
|
|
|
+// license that can be found in the LICENSE file.
|
|
|
+
|
|
|
+package ldap
|
|
|
+
|
|
|
+import (
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "io/ioutil"
|
|
|
+
|
|
|
+ "github.com/gogits/gogs/modules/asn1-ber"
|
|
|
+)
|
|
|
+
|
|
|
+// LDAP Application Codes
|
|
|
+const (
|
|
|
+ ApplicationBindRequest = 0
|
|
|
+ ApplicationBindResponse = 1
|
|
|
+ ApplicationUnbindRequest = 2
|
|
|
+ ApplicationSearchRequest = 3
|
|
|
+ ApplicationSearchResultEntry = 4
|
|
|
+ ApplicationSearchResultDone = 5
|
|
|
+ ApplicationModifyRequest = 6
|
|
|
+ ApplicationModifyResponse = 7
|
|
|
+ ApplicationAddRequest = 8
|
|
|
+ ApplicationAddResponse = 9
|
|
|
+ ApplicationDelRequest = 10
|
|
|
+ ApplicationDelResponse = 11
|
|
|
+ ApplicationModifyDNRequest = 12
|
|
|
+ ApplicationModifyDNResponse = 13
|
|
|
+ ApplicationCompareRequest = 14
|
|
|
+ ApplicationCompareResponse = 15
|
|
|
+ ApplicationAbandonRequest = 16
|
|
|
+ ApplicationSearchResultReference = 19
|
|
|
+ ApplicationExtendedRequest = 23
|
|
|
+ ApplicationExtendedResponse = 24
|
|
|
+)
|
|
|
+
|
|
|
+var ApplicationMap = map[uint8]string{
|
|
|
+ ApplicationBindRequest: "Bind Request",
|
|
|
+ ApplicationBindResponse: "Bind Response",
|
|
|
+ ApplicationUnbindRequest: "Unbind Request",
|
|
|
+ ApplicationSearchRequest: "Search Request",
|
|
|
+ ApplicationSearchResultEntry: "Search Result Entry",
|
|
|
+ ApplicationSearchResultDone: "Search Result Done",
|
|
|
+ ApplicationModifyRequest: "Modify Request",
|
|
|
+ ApplicationModifyResponse: "Modify Response",
|
|
|
+ ApplicationAddRequest: "Add Request",
|
|
|
+ ApplicationAddResponse: "Add Response",
|
|
|
+ ApplicationDelRequest: "Del Request",
|
|
|
+ ApplicationDelResponse: "Del Response",
|
|
|
+ ApplicationModifyDNRequest: "Modify DN Request",
|
|
|
+ ApplicationModifyDNResponse: "Modify DN Response",
|
|
|
+ ApplicationCompareRequest: "Compare Request",
|
|
|
+ ApplicationCompareResponse: "Compare Response",
|
|
|
+ ApplicationAbandonRequest: "Abandon Request",
|
|
|
+ ApplicationSearchResultReference: "Search Result Reference",
|
|
|
+ ApplicationExtendedRequest: "Extended Request",
|
|
|
+ ApplicationExtendedResponse: "Extended Response",
|
|
|
+}
|
|
|
+
|
|
|
+// LDAP Result Codes
|
|
|
+const (
|
|
|
+ LDAPResultSuccess = 0
|
|
|
+ LDAPResultOperationsError = 1
|
|
|
+ LDAPResultProtocolError = 2
|
|
|
+ LDAPResultTimeLimitExceeded = 3
|
|
|
+ LDAPResultSizeLimitExceeded = 4
|
|
|
+ LDAPResultCompareFalse = 5
|
|
|
+ LDAPResultCompareTrue = 6
|
|
|
+ LDAPResultAuthMethodNotSupported = 7
|
|
|
+ LDAPResultStrongAuthRequired = 8
|
|
|
+ LDAPResultReferral = 10
|
|
|
+ LDAPResultAdminLimitExceeded = 11
|
|
|
+ LDAPResultUnavailableCriticalExtension = 12
|
|
|
+ LDAPResultConfidentialityRequired = 13
|
|
|
+ LDAPResultSaslBindInProgress = 14
|
|
|
+ LDAPResultNoSuchAttribute = 16
|
|
|
+ LDAPResultUndefinedAttributeType = 17
|
|
|
+ LDAPResultInappropriateMatching = 18
|
|
|
+ LDAPResultConstraintViolation = 19
|
|
|
+ LDAPResultAttributeOrValueExists = 20
|
|
|
+ LDAPResultInvalidAttributeSyntax = 21
|
|
|
+ LDAPResultNoSuchObject = 32
|
|
|
+ LDAPResultAliasProblem = 33
|
|
|
+ LDAPResultInvalidDNSyntax = 34
|
|
|
+ LDAPResultAliasDereferencingProblem = 36
|
|
|
+ LDAPResultInappropriateAuthentication = 48
|
|
|
+ LDAPResultInvalidCredentials = 49
|
|
|
+ LDAPResultInsufficientAccessRights = 50
|
|
|
+ LDAPResultBusy = 51
|
|
|
+ LDAPResultUnavailable = 52
|
|
|
+ LDAPResultUnwillingToPerform = 53
|
|
|
+ LDAPResultLoopDetect = 54
|
|
|
+ LDAPResultNamingViolation = 64
|
|
|
+ LDAPResultObjectClassViolation = 65
|
|
|
+ LDAPResultNotAllowedOnNonLeaf = 66
|
|
|
+ LDAPResultNotAllowedOnRDN = 67
|
|
|
+ LDAPResultEntryAlreadyExists = 68
|
|
|
+ LDAPResultObjectClassModsProhibited = 69
|
|
|
+ LDAPResultAffectsMultipleDSAs = 71
|
|
|
+ LDAPResultOther = 80
|
|
|
+
|
|
|
+ ErrorNetwork = 200
|
|
|
+ ErrorFilterCompile = 201
|
|
|
+ ErrorFilterDecompile = 202
|
|
|
+ ErrorDebugging = 203
|
|
|
+)
|
|
|
+
|
|
|
+var LDAPResultCodeMap = map[uint8]string{
|
|
|
+ LDAPResultSuccess: "Success",
|
|
|
+ LDAPResultOperationsError: "Operations Error",
|
|
|
+ LDAPResultProtocolError: "Protocol Error",
|
|
|
+ LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
|
|
|
+ LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
|
|
|
+ LDAPResultCompareFalse: "Compare False",
|
|
|
+ LDAPResultCompareTrue: "Compare True",
|
|
|
+ LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
|
|
|
+ LDAPResultStrongAuthRequired: "Strong Auth Required",
|
|
|
+ LDAPResultReferral: "Referral",
|
|
|
+ LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
|
|
|
+ LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
|
|
|
+ LDAPResultConfidentialityRequired: "Confidentiality Required",
|
|
|
+ LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
|
|
|
+ LDAPResultNoSuchAttribute: "No Such Attribute",
|
|
|
+ LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
|
|
|
+ LDAPResultInappropriateMatching: "Inappropriate Matching",
|
|
|
+ LDAPResultConstraintViolation: "Constraint Violation",
|
|
|
+ LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
|
|
|
+ LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
|
|
|
+ LDAPResultNoSuchObject: "No Such Object",
|
|
|
+ LDAPResultAliasProblem: "Alias Problem",
|
|
|
+ LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
|
|
|
+ LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
|
|
|
+ LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
|
|
|
+ LDAPResultInvalidCredentials: "Invalid Credentials",
|
|
|
+ LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
|
|
|
+ LDAPResultBusy: "Busy",
|
|
|
+ LDAPResultUnavailable: "Unavailable",
|
|
|
+ LDAPResultUnwillingToPerform: "Unwilling To Perform",
|
|
|
+ LDAPResultLoopDetect: "Loop Detect",
|
|
|
+ LDAPResultNamingViolation: "Naming Violation",
|
|
|
+ LDAPResultObjectClassViolation: "Object Class Violation",
|
|
|
+ LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
|
|
|
+ LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
|
|
|
+ LDAPResultEntryAlreadyExists: "Entry Already Exists",
|
|
|
+ LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
|
|
|
+ LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
|
|
|
+ LDAPResultOther: "Other",
|
|
|
+}
|
|
|
+
|
|
|
+// Adds descriptions to an LDAP Response packet for debugging
|
|
|
+func addLDAPDescriptions(packet *ber.Packet) (err error) {
|
|
|
+ defer func() {
|
|
|
+ if r := recover(); r != nil {
|
|
|
+ err = NewError(ErrorDebugging, errors.New("ldap: cannot process packet to add descriptions"))
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ packet.Description = "LDAP Response"
|
|
|
+ packet.Children[0].Description = "Message ID"
|
|
|
+
|
|
|
+ application := packet.Children[1].Tag
|
|
|
+ packet.Children[1].Description = ApplicationMap[application]
|
|
|
+
|
|
|
+ switch application {
|
|
|
+ case ApplicationBindRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationBindResponse:
|
|
|
+ addDefaultLDAPResponseDescriptions(packet)
|
|
|
+ case ApplicationUnbindRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationSearchRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationSearchResultEntry:
|
|
|
+ packet.Children[1].Children[0].Description = "Object Name"
|
|
|
+ packet.Children[1].Children[1].Description = "Attributes"
|
|
|
+ for _, child := range packet.Children[1].Children[1].Children {
|
|
|
+ child.Description = "Attribute"
|
|
|
+ child.Children[0].Description = "Attribute Name"
|
|
|
+ child.Children[1].Description = "Attribute Values"
|
|
|
+ for _, grandchild := range child.Children[1].Children {
|
|
|
+ grandchild.Description = "Attribute Value"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if len(packet.Children) == 3 {
|
|
|
+ addControlDescriptions(packet.Children[2])
|
|
|
+ }
|
|
|
+ case ApplicationSearchResultDone:
|
|
|
+ addDefaultLDAPResponseDescriptions(packet)
|
|
|
+ case ApplicationModifyRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationModifyResponse:
|
|
|
+ case ApplicationAddRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationAddResponse:
|
|
|
+ case ApplicationDelRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationDelResponse:
|
|
|
+ case ApplicationModifyDNRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationModifyDNResponse:
|
|
|
+ case ApplicationCompareRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationCompareResponse:
|
|
|
+ case ApplicationAbandonRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationSearchResultReference:
|
|
|
+ case ApplicationExtendedRequest:
|
|
|
+ addRequestDescriptions(packet)
|
|
|
+ case ApplicationExtendedResponse:
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func addControlDescriptions(packet *ber.Packet) {
|
|
|
+ packet.Description = "Controls"
|
|
|
+ for _, child := range packet.Children {
|
|
|
+ child.Description = "Control"
|
|
|
+ child.Children[0].Description = "Control Type (" + ControlTypeMap[child.Children[0].Value.(string)] + ")"
|
|
|
+ value := child.Children[1]
|
|
|
+ if len(child.Children) == 3 {
|
|
|
+ child.Children[1].Description = "Criticality"
|
|
|
+ value = child.Children[2]
|
|
|
+ }
|
|
|
+ value.Description = "Control Value"
|
|
|
+
|
|
|
+ switch child.Children[0].Value.(string) {
|
|
|
+ case ControlTypePaging:
|
|
|
+ value.Description += " (Paging)"
|
|
|
+ if value.Value != nil {
|
|
|
+ valueChildren := ber.DecodePacket(value.Data.Bytes())
|
|
|
+ value.Data.Truncate(0)
|
|
|
+ value.Value = nil
|
|
|
+ valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
|
|
|
+ value.AppendChild(valueChildren)
|
|
|
+ }
|
|
|
+ value.Children[0].Description = "Real Search Control Value"
|
|
|
+ value.Children[0].Children[0].Description = "Paging Size"
|
|
|
+ value.Children[0].Children[1].Description = "Cookie"
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func addRequestDescriptions(packet *ber.Packet) {
|
|
|
+ packet.Description = "LDAP Request"
|
|
|
+ packet.Children[0].Description = "Message ID"
|
|
|
+ packet.Children[1].Description = ApplicationMap[packet.Children[1].Tag]
|
|
|
+ if len(packet.Children) == 3 {
|
|
|
+ addControlDescriptions(packet.Children[2])
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
|
|
|
+ resultCode := packet.Children[1].Children[0].Value.(uint64)
|
|
|
+ packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[uint8(resultCode)] + ")"
|
|
|
+ packet.Children[1].Children[1].Description = "Matched DN"
|
|
|
+ packet.Children[1].Children[2].Description = "Error Message"
|
|
|
+ if len(packet.Children[1].Children) > 3 {
|
|
|
+ packet.Children[1].Children[3].Description = "Referral"
|
|
|
+ }
|
|
|
+ if len(packet.Children) == 3 {
|
|
|
+ addControlDescriptions(packet.Children[2])
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func DebugBinaryFile(fileName string) error {
|
|
|
+ file, err := ioutil.ReadFile(fileName)
|
|
|
+ if err != nil {
|
|
|
+ return NewError(ErrorDebugging, err)
|
|
|
+ }
|
|
|
+ ber.PrintBytes(file, "")
|
|
|
+ packet := ber.DecodePacket(file)
|
|
|
+ addLDAPDescriptions(packet)
|
|
|
+ ber.PrintPacket(packet)
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+type Error struct {
|
|
|
+ Err error
|
|
|
+ ResultCode uint8
|
|
|
+}
|
|
|
+
|
|
|
+func (e *Error) Error() string {
|
|
|
+ return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
|
|
|
+}
|
|
|
+
|
|
|
+func NewError(resultCode uint8, err error) error {
|
|
|
+ return &Error{ResultCode: resultCode, Err: err}
|
|
|
+}
|
|
|
+
|
|
|
+func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
|
|
|
+ if len(packet.Children) >= 2 {
|
|
|
+ response := packet.Children[1]
|
|
|
+ if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) == 3 {
|
|
|
+ return uint8(response.Children[0].Value.(uint64)), response.Children[2].Value.(string)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return ErrorNetwork, "Invalid packet format"
|
|
|
+}
|