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

  1. package ldap
  2. import (
  3. "fmt"
  4. "gopkg.in/asn1-ber.v1"
  5. )
  6. // LDAP Result Codes
  7. const (
  8. LDAPResultSuccess = 0
  9. LDAPResultOperationsError = 1
  10. LDAPResultProtocolError = 2
  11. LDAPResultTimeLimitExceeded = 3
  12. LDAPResultSizeLimitExceeded = 4
  13. LDAPResultCompareFalse = 5
  14. LDAPResultCompareTrue = 6
  15. LDAPResultAuthMethodNotSupported = 7
  16. LDAPResultStrongAuthRequired = 8
  17. LDAPResultReferral = 10
  18. LDAPResultAdminLimitExceeded = 11
  19. LDAPResultUnavailableCriticalExtension = 12
  20. LDAPResultConfidentialityRequired = 13
  21. LDAPResultSaslBindInProgress = 14
  22. LDAPResultNoSuchAttribute = 16
  23. LDAPResultUndefinedAttributeType = 17
  24. LDAPResultInappropriateMatching = 18
  25. LDAPResultConstraintViolation = 19
  26. LDAPResultAttributeOrValueExists = 20
  27. LDAPResultInvalidAttributeSyntax = 21
  28. LDAPResultNoSuchObject = 32
  29. LDAPResultAliasProblem = 33
  30. LDAPResultInvalidDNSyntax = 34
  31. LDAPResultIsLeaf = 35
  32. LDAPResultAliasDereferencingProblem = 36
  33. LDAPResultInappropriateAuthentication = 48
  34. LDAPResultInvalidCredentials = 49
  35. LDAPResultInsufficientAccessRights = 50
  36. LDAPResultBusy = 51
  37. LDAPResultUnavailable = 52
  38. LDAPResultUnwillingToPerform = 53
  39. LDAPResultLoopDetect = 54
  40. LDAPResultSortControlMissing = 60
  41. LDAPResultOffsetRangeError = 61
  42. LDAPResultNamingViolation = 64
  43. LDAPResultObjectClassViolation = 65
  44. LDAPResultNotAllowedOnNonLeaf = 66
  45. LDAPResultNotAllowedOnRDN = 67
  46. LDAPResultEntryAlreadyExists = 68
  47. LDAPResultObjectClassModsProhibited = 69
  48. LDAPResultResultsTooLarge = 70
  49. LDAPResultAffectsMultipleDSAs = 71
  50. LDAPResultVirtualListViewErrorOrControlError = 76
  51. LDAPResultOther = 80
  52. LDAPResultServerDown = 81
  53. LDAPResultLocalError = 82
  54. LDAPResultEncodingError = 83
  55. LDAPResultDecodingError = 84
  56. LDAPResultTimeout = 85
  57. LDAPResultAuthUnknown = 86
  58. LDAPResultFilterError = 87
  59. LDAPResultUserCanceled = 88
  60. LDAPResultParamError = 89
  61. LDAPResultNoMemory = 90
  62. LDAPResultConnectError = 91
  63. LDAPResultNotSupported = 92
  64. LDAPResultControlNotFound = 93
  65. LDAPResultNoResultsReturned = 94
  66. LDAPResultMoreResultsToReturn = 95
  67. LDAPResultClientLoop = 96
  68. LDAPResultReferralLimitExceeded = 97
  69. LDAPResultInvalidResponse = 100
  70. LDAPResultAmbiguousResponse = 101
  71. LDAPResultTLSNotSupported = 112
  72. LDAPResultIntermediateResponse = 113
  73. LDAPResultUnknownType = 114
  74. LDAPResultCanceled = 118
  75. LDAPResultNoSuchOperation = 119
  76. LDAPResultTooLate = 120
  77. LDAPResultCannotCancel = 121
  78. LDAPResultAssertionFailed = 122
  79. LDAPResultAuthorizationDenied = 123
  80. LDAPResultSyncRefreshRequired = 4096
  81. ErrorNetwork = 200
  82. ErrorFilterCompile = 201
  83. ErrorFilterDecompile = 202
  84. ErrorDebugging = 203
  85. ErrorUnexpectedMessage = 204
  86. ErrorUnexpectedResponse = 205
  87. ErrorEmptyPassword = 206
  88. )
  89. // LDAPResultCodeMap contains string descriptions for LDAP error codes
  90. var LDAPResultCodeMap = map[uint16]string{
  91. LDAPResultSuccess: "Success",
  92. LDAPResultOperationsError: "Operations Error",
  93. LDAPResultProtocolError: "Protocol Error",
  94. LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
  95. LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
  96. LDAPResultCompareFalse: "Compare False",
  97. LDAPResultCompareTrue: "Compare True",
  98. LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
  99. LDAPResultStrongAuthRequired: "Strong Auth Required",
  100. LDAPResultReferral: "Referral",
  101. LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
  102. LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
  103. LDAPResultConfidentialityRequired: "Confidentiality Required",
  104. LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
  105. LDAPResultNoSuchAttribute: "No Such Attribute",
  106. LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
  107. LDAPResultInappropriateMatching: "Inappropriate Matching",
  108. LDAPResultConstraintViolation: "Constraint Violation",
  109. LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
  110. LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
  111. LDAPResultNoSuchObject: "No Such Object",
  112. LDAPResultAliasProblem: "Alias Problem",
  113. LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
  114. LDAPResultIsLeaf: "Is Leaf",
  115. LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
  116. LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
  117. LDAPResultInvalidCredentials: "Invalid Credentials",
  118. LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
  119. LDAPResultBusy: "Busy",
  120. LDAPResultUnavailable: "Unavailable",
  121. LDAPResultUnwillingToPerform: "Unwilling To Perform",
  122. LDAPResultLoopDetect: "Loop Detect",
  123. LDAPResultSortControlMissing: "Sort Control Missing",
  124. LDAPResultOffsetRangeError: "Result Offset Range Error",
  125. LDAPResultNamingViolation: "Naming Violation",
  126. LDAPResultObjectClassViolation: "Object Class Violation",
  127. LDAPResultResultsTooLarge: "Results Too Large",
  128. LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
  129. LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
  130. LDAPResultEntryAlreadyExists: "Entry Already Exists",
  131. LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
  132. LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
  133. LDAPResultVirtualListViewErrorOrControlError: "Failed because of a problem related to the virtual list view",
  134. LDAPResultOther: "Other",
  135. LDAPResultServerDown: "Cannot establish a connection",
  136. LDAPResultLocalError: "An error occurred",
  137. LDAPResultEncodingError: "LDAP encountered an error while encoding",
  138. LDAPResultDecodingError: "LDAP encountered an error while decoding",
  139. LDAPResultTimeout: "LDAP timeout while waiting for a response from the server",
  140. LDAPResultAuthUnknown: "The auth method requested in a bind request is unknown",
  141. LDAPResultFilterError: "An error occurred while encoding the given search filter",
  142. LDAPResultUserCanceled: "The user canceled the operation",
  143. LDAPResultParamError: "An invalid parameter was specified",
  144. LDAPResultNoMemory: "Out of memory error",
  145. LDAPResultConnectError: "A connection to the server could not be established",
  146. LDAPResultNotSupported: "An attempt has been made to use a feature not supported LDAP",
  147. LDAPResultControlNotFound: "The controls required to perform the requested operation were not found",
  148. LDAPResultNoResultsReturned: "No results were returned from the server",
  149. LDAPResultMoreResultsToReturn: "There are more results in the chain of results",
  150. LDAPResultClientLoop: "A loop has been detected. For example when following referrals",
  151. LDAPResultReferralLimitExceeded: "The referral hop limit has been exceeded",
  152. LDAPResultCanceled: "Operation was canceled",
  153. LDAPResultNoSuchOperation: "Server has no knowledge of the operation requested for cancellation",
  154. LDAPResultTooLate: "Too late to cancel the outstanding operation",
  155. LDAPResultCannotCancel: "The identified operation does not support cancellation or the cancel operation cannot be performed",
  156. LDAPResultAssertionFailed: "An assertion control given in the LDAP operation evaluated to false causing the operation to not be performed",
  157. LDAPResultSyncRefreshRequired: "Refresh Required",
  158. LDAPResultInvalidResponse: "Invalid Response",
  159. LDAPResultAmbiguousResponse: "Ambiguous Response",
  160. LDAPResultTLSNotSupported: "Tls Not Supported",
  161. LDAPResultIntermediateResponse: "Intermediate Response",
  162. LDAPResultUnknownType: "Unknown Type",
  163. LDAPResultAuthorizationDenied: "Authorization Denied",
  164. ErrorNetwork: "Network Error",
  165. ErrorFilterCompile: "Filter Compile Error",
  166. ErrorFilterDecompile: "Filter Decompile Error",
  167. ErrorDebugging: "Debugging Error",
  168. ErrorUnexpectedMessage: "Unexpected Message",
  169. ErrorUnexpectedResponse: "Unexpected Response",
  170. ErrorEmptyPassword: "Empty password not allowed by the client",
  171. }
  172. // Error holds LDAP error information
  173. type Error struct {
  174. // Err is the underlying error
  175. Err error
  176. // ResultCode is the LDAP error code
  177. ResultCode uint16
  178. // MatchedDN is the matchedDN returned if any
  179. MatchedDN string
  180. }
  181. func (e *Error) Error() string {
  182. return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
  183. }
  184. // GetLDAPError creates an Error out of a BER packet representing a LDAPResult
  185. // The return is an error object. It can be casted to a Error structure.
  186. // This function returns nil if resultCode in the LDAPResult sequence is success(0).
  187. func GetLDAPError(packet *ber.Packet) error {
  188. if packet == nil {
  189. return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")}
  190. } else if len(packet.Children) >= 2 {
  191. response := packet.Children[1]
  192. if response == nil {
  193. return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
  194. }
  195. if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
  196. resultCode := uint16(response.Children[0].Value.(int64))
  197. if resultCode == 0 { // No error
  198. return nil
  199. }
  200. return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
  201. Err: fmt.Errorf("%s", response.Children[2].Value.(string))}
  202. }
  203. }
  204. return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
  205. }
  206. // NewError creates an LDAP error with the given code and underlying error
  207. func NewError(resultCode uint16, err error) error {
  208. return &Error{ResultCode: resultCode, Err: err}
  209. }
  210. // IsErrorWithCode returns true if the given error is an LDAP error with the given result code
  211. func IsErrorWithCode(err error, desiredResultCode uint16) bool {
  212. if err == nil {
  213. return false
  214. }
  215. serverError, ok := err.(*Error)
  216. if !ok {
  217. return false
  218. }
  219. return serverError.ResultCode == desiredResultCode
  220. }