summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/mattermost/ldap/error.go
blob: b1fda2d81b3dea68a5f499280a348e5116078828 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package ldap

import (
	"fmt"

	ber "github.com/go-asn1-ber/asn1-ber"
)

// 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")}
	}

	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("%s", 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
}