mirror of https://github.com/gogits/gogs.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
302 lines
11 KiB
302 lines
11 KiB
// 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" |
|
}
|
|
|