Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
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.
234 lines
12 KiB
234 lines
12 KiB
package ldap |
|
|
|
import ( |
|
"fmt" |
|
|
|
"gopkg.in/asn1-ber.v1" |
|
) |
|
|
|
// 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 |
|
LDAPResultIsLeaf = 35 |
|
LDAPResultAliasDereferencingProblem = 36 |
|
LDAPResultInappropriateAuthentication = 48 |
|
LDAPResultInvalidCredentials = 49 |
|
LDAPResultInsufficientAccessRights = 50 |
|
LDAPResultBusy = 51 |
|
LDAPResultUnavailable = 52 |
|
LDAPResultUnwillingToPerform = 53 |
|
LDAPResultLoopDetect = 54 |
|
LDAPResultSortControlMissing = 60 |
|
LDAPResultOffsetRangeError = 61 |
|
LDAPResultNamingViolation = 64 |
|
LDAPResultObjectClassViolation = 65 |
|
LDAPResultNotAllowedOnNonLeaf = 66 |
|
LDAPResultNotAllowedOnRDN = 67 |
|
LDAPResultEntryAlreadyExists = 68 |
|
LDAPResultObjectClassModsProhibited = 69 |
|
LDAPResultResultsTooLarge = 70 |
|
LDAPResultAffectsMultipleDSAs = 71 |
|
LDAPResultVirtualListViewErrorOrControlError = 76 |
|
LDAPResultOther = 80 |
|
LDAPResultServerDown = 81 |
|
LDAPResultLocalError = 82 |
|
LDAPResultEncodingError = 83 |
|
LDAPResultDecodingError = 84 |
|
LDAPResultTimeout = 85 |
|
LDAPResultAuthUnknown = 86 |
|
LDAPResultFilterError = 87 |
|
LDAPResultUserCanceled = 88 |
|
LDAPResultParamError = 89 |
|
LDAPResultNoMemory = 90 |
|
LDAPResultConnectError = 91 |
|
LDAPResultNotSupported = 92 |
|
LDAPResultControlNotFound = 93 |
|
LDAPResultNoResultsReturned = 94 |
|
LDAPResultMoreResultsToReturn = 95 |
|
LDAPResultClientLoop = 96 |
|
LDAPResultReferralLimitExceeded = 97 |
|
LDAPResultInvalidResponse = 100 |
|
LDAPResultAmbiguousResponse = 101 |
|
LDAPResultTLSNotSupported = 112 |
|
LDAPResultIntermediateResponse = 113 |
|
LDAPResultUnknownType = 114 |
|
LDAPResultCanceled = 118 |
|
LDAPResultNoSuchOperation = 119 |
|
LDAPResultTooLate = 120 |
|
LDAPResultCannotCancel = 121 |
|
LDAPResultAssertionFailed = 122 |
|
LDAPResultAuthorizationDenied = 123 |
|
LDAPResultSyncRefreshRequired = 4096 |
|
|
|
ErrorNetwork = 200 |
|
ErrorFilterCompile = 201 |
|
ErrorFilterDecompile = 202 |
|
ErrorDebugging = 203 |
|
ErrorUnexpectedMessage = 204 |
|
ErrorUnexpectedResponse = 205 |
|
ErrorEmptyPassword = 206 |
|
) |
|
|
|
// LDAPResultCodeMap contains string descriptions for LDAP error codes |
|
var LDAPResultCodeMap = map[uint16]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", |
|
LDAPResultIsLeaf: "Is Leaf", |
|
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", |
|
LDAPResultSortControlMissing: "Sort Control Missing", |
|
LDAPResultOffsetRangeError: "Result Offset Range Error", |
|
LDAPResultNamingViolation: "Naming Violation", |
|
LDAPResultObjectClassViolation: "Object Class Violation", |
|
LDAPResultResultsTooLarge: "Results Too Large", |
|
LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf", |
|
LDAPResultNotAllowedOnRDN: "Not Allowed On RDN", |
|
LDAPResultEntryAlreadyExists: "Entry Already Exists", |
|
LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited", |
|
LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs", |
|
LDAPResultVirtualListViewErrorOrControlError: "Failed because of a problem related to the virtual list view", |
|
LDAPResultOther: "Other", |
|
LDAPResultServerDown: "Cannot establish a connection", |
|
LDAPResultLocalError: "An error occurred", |
|
LDAPResultEncodingError: "LDAP encountered an error while encoding", |
|
LDAPResultDecodingError: "LDAP encountered an error while decoding", |
|
LDAPResultTimeout: "LDAP timeout while waiting for a response from the server", |
|
LDAPResultAuthUnknown: "The auth method requested in a bind request is unknown", |
|
LDAPResultFilterError: "An error occurred while encoding the given search filter", |
|
LDAPResultUserCanceled: "The user canceled the operation", |
|
LDAPResultParamError: "An invalid parameter was specified", |
|
LDAPResultNoMemory: "Out of memory error", |
|
LDAPResultConnectError: "A connection to the server could not be established", |
|
LDAPResultNotSupported: "An attempt has been made to use a feature not supported LDAP", |
|
LDAPResultControlNotFound: "The controls required to perform the requested operation were not found", |
|
LDAPResultNoResultsReturned: "No results were returned from the server", |
|
LDAPResultMoreResultsToReturn: "There are more results in the chain of results", |
|
LDAPResultClientLoop: "A loop has been detected. For example when following referrals", |
|
LDAPResultReferralLimitExceeded: "The referral hop limit has been exceeded", |
|
LDAPResultCanceled: "Operation was canceled", |
|
LDAPResultNoSuchOperation: "Server has no knowledge of the operation requested for cancellation", |
|
LDAPResultTooLate: "Too late to cancel the outstanding operation", |
|
LDAPResultCannotCancel: "The identified operation does not support cancellation or the cancel operation cannot be performed", |
|
LDAPResultAssertionFailed: "An assertion control given in the LDAP operation evaluated to false causing the operation to not be performed", |
|
LDAPResultSyncRefreshRequired: "Refresh Required", |
|
LDAPResultInvalidResponse: "Invalid Response", |
|
LDAPResultAmbiguousResponse: "Ambiguous Response", |
|
LDAPResultTLSNotSupported: "Tls Not Supported", |
|
LDAPResultIntermediateResponse: "Intermediate Response", |
|
LDAPResultUnknownType: "Unknown Type", |
|
LDAPResultAuthorizationDenied: "Authorization Denied", |
|
|
|
ErrorNetwork: "Network Error", |
|
ErrorFilterCompile: "Filter Compile Error", |
|
ErrorFilterDecompile: "Filter Decompile Error", |
|
ErrorDebugging: "Debugging Error", |
|
ErrorUnexpectedMessage: "Unexpected Message", |
|
ErrorUnexpectedResponse: "Unexpected Response", |
|
ErrorEmptyPassword: "Empty password not allowed by the client", |
|
} |
|
|
|
// Error holds LDAP error information |
|
type Error struct { |
|
// Err is the underlying error |
|
Err error |
|
// ResultCode is the LDAP error code |
|
ResultCode uint16 |
|
// MatchedDN is the matchedDN returned if any |
|
MatchedDN string |
|
} |
|
|
|
func (e *Error) Error() string { |
|
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error()) |
|
} |
|
|
|
// GetLDAPError creates an Error out of a BER packet representing a LDAPResult |
|
// The return is an error object. It can be casted to a Error structure. |
|
// This function returns nil if resultCode in the LDAPResult sequence is success(0). |
|
func GetLDAPError(packet *ber.Packet) error { |
|
if packet == nil { |
|
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")} |
|
} else if len(packet.Children) >= 2 { |
|
response := packet.Children[1] |
|
if response == nil { |
|
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")} |
|
} |
|
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 { |
|
resultCode := uint16(response.Children[0].Value.(int64)) |
|
if resultCode == 0 { // No error |
|
return nil |
|
} |
|
return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string), |
|
Err: fmt.Errorf(response.Children[2].Value.(string))} |
|
} |
|
} |
|
|
|
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")} |
|
} |
|
|
|
// NewError creates an LDAP error with the given code and underlying error |
|
func NewError(resultCode uint16, err error) error { |
|
return &Error{ResultCode: resultCode, Err: err} |
|
} |
|
|
|
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code |
|
func IsErrorWithCode(err error, desiredResultCode uint16) bool { |
|
if err == nil { |
|
return false |
|
} |
|
|
|
serverError, ok := err.(*Error) |
|
if !ok { |
|
return false |
|
} |
|
|
|
return serverError.ResultCode == desiredResultCode |
|
}
|
|
|