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

10 years ago
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ldap
  5. import (
  6. "errors"
  7. "fmt"
  8. "io/ioutil"
  9. "github.com/gogits/gogs/modules/asn1-ber"
  10. )
  11. // LDAP Application Codes
  12. const (
  13. ApplicationBindRequest = 0
  14. ApplicationBindResponse = 1
  15. ApplicationUnbindRequest = 2
  16. ApplicationSearchRequest = 3
  17. ApplicationSearchResultEntry = 4
  18. ApplicationSearchResultDone = 5
  19. ApplicationModifyRequest = 6
  20. ApplicationModifyResponse = 7
  21. ApplicationAddRequest = 8
  22. ApplicationAddResponse = 9
  23. ApplicationDelRequest = 10
  24. ApplicationDelResponse = 11
  25. ApplicationModifyDNRequest = 12
  26. ApplicationModifyDNResponse = 13
  27. ApplicationCompareRequest = 14
  28. ApplicationCompareResponse = 15
  29. ApplicationAbandonRequest = 16
  30. ApplicationSearchResultReference = 19
  31. ApplicationExtendedRequest = 23
  32. ApplicationExtendedResponse = 24
  33. )
  34. var ApplicationMap = map[uint8]string{
  35. ApplicationBindRequest: "Bind Request",
  36. ApplicationBindResponse: "Bind Response",
  37. ApplicationUnbindRequest: "Unbind Request",
  38. ApplicationSearchRequest: "Search Request",
  39. ApplicationSearchResultEntry: "Search Result Entry",
  40. ApplicationSearchResultDone: "Search Result Done",
  41. ApplicationModifyRequest: "Modify Request",
  42. ApplicationModifyResponse: "Modify Response",
  43. ApplicationAddRequest: "Add Request",
  44. ApplicationAddResponse: "Add Response",
  45. ApplicationDelRequest: "Del Request",
  46. ApplicationDelResponse: "Del Response",
  47. ApplicationModifyDNRequest: "Modify DN Request",
  48. ApplicationModifyDNResponse: "Modify DN Response",
  49. ApplicationCompareRequest: "Compare Request",
  50. ApplicationCompareResponse: "Compare Response",
  51. ApplicationAbandonRequest: "Abandon Request",
  52. ApplicationSearchResultReference: "Search Result Reference",
  53. ApplicationExtendedRequest: "Extended Request",
  54. ApplicationExtendedResponse: "Extended Response",
  55. }
  56. // LDAP Result Codes
  57. const (
  58. LDAPResultSuccess = 0
  59. LDAPResultOperationsError = 1
  60. LDAPResultProtocolError = 2
  61. LDAPResultTimeLimitExceeded = 3
  62. LDAPResultSizeLimitExceeded = 4
  63. LDAPResultCompareFalse = 5
  64. LDAPResultCompareTrue = 6
  65. LDAPResultAuthMethodNotSupported = 7
  66. LDAPResultStrongAuthRequired = 8
  67. LDAPResultReferral = 10
  68. LDAPResultAdminLimitExceeded = 11
  69. LDAPResultUnavailableCriticalExtension = 12
  70. LDAPResultConfidentialityRequired = 13
  71. LDAPResultSaslBindInProgress = 14
  72. LDAPResultNoSuchAttribute = 16
  73. LDAPResultUndefinedAttributeType = 17
  74. LDAPResultInappropriateMatching = 18
  75. LDAPResultConstraintViolation = 19
  76. LDAPResultAttributeOrValueExists = 20
  77. LDAPResultInvalidAttributeSyntax = 21
  78. LDAPResultNoSuchObject = 32
  79. LDAPResultAliasProblem = 33
  80. LDAPResultInvalidDNSyntax = 34
  81. LDAPResultAliasDereferencingProblem = 36
  82. LDAPResultInappropriateAuthentication = 48
  83. LDAPResultInvalidCredentials = 49
  84. LDAPResultInsufficientAccessRights = 50
  85. LDAPResultBusy = 51
  86. LDAPResultUnavailable = 52
  87. LDAPResultUnwillingToPerform = 53
  88. LDAPResultLoopDetect = 54
  89. LDAPResultNamingViolation = 64
  90. LDAPResultObjectClassViolation = 65
  91. LDAPResultNotAllowedOnNonLeaf = 66
  92. LDAPResultNotAllowedOnRDN = 67
  93. LDAPResultEntryAlreadyExists = 68
  94. LDAPResultObjectClassModsProhibited = 69
  95. LDAPResultAffectsMultipleDSAs = 71
  96. LDAPResultOther = 80
  97. ErrorNetwork = 200
  98. ErrorFilterCompile = 201
  99. ErrorFilterDecompile = 202
  100. ErrorDebugging = 203
  101. )
  102. var LDAPResultCodeMap = map[uint8]string{
  103. LDAPResultSuccess: "Success",
  104. LDAPResultOperationsError: "Operations Error",
  105. LDAPResultProtocolError: "Protocol Error",
  106. LDAPResultTimeLimitExceeded: "Time Limit Exceeded",
  107. LDAPResultSizeLimitExceeded: "Size Limit Exceeded",
  108. LDAPResultCompareFalse: "Compare False",
  109. LDAPResultCompareTrue: "Compare True",
  110. LDAPResultAuthMethodNotSupported: "Auth Method Not Supported",
  111. LDAPResultStrongAuthRequired: "Strong Auth Required",
  112. LDAPResultReferral: "Referral",
  113. LDAPResultAdminLimitExceeded: "Admin Limit Exceeded",
  114. LDAPResultUnavailableCriticalExtension: "Unavailable Critical Extension",
  115. LDAPResultConfidentialityRequired: "Confidentiality Required",
  116. LDAPResultSaslBindInProgress: "Sasl Bind In Progress",
  117. LDAPResultNoSuchAttribute: "No Such Attribute",
  118. LDAPResultUndefinedAttributeType: "Undefined Attribute Type",
  119. LDAPResultInappropriateMatching: "Inappropriate Matching",
  120. LDAPResultConstraintViolation: "Constraint Violation",
  121. LDAPResultAttributeOrValueExists: "Attribute Or Value Exists",
  122. LDAPResultInvalidAttributeSyntax: "Invalid Attribute Syntax",
  123. LDAPResultNoSuchObject: "No Such Object",
  124. LDAPResultAliasProblem: "Alias Problem",
  125. LDAPResultInvalidDNSyntax: "Invalid DN Syntax",
  126. LDAPResultAliasDereferencingProblem: "Alias Dereferencing Problem",
  127. LDAPResultInappropriateAuthentication: "Inappropriate Authentication",
  128. LDAPResultInvalidCredentials: "Invalid Credentials",
  129. LDAPResultInsufficientAccessRights: "Insufficient Access Rights",
  130. LDAPResultBusy: "Busy",
  131. LDAPResultUnavailable: "Unavailable",
  132. LDAPResultUnwillingToPerform: "Unwilling To Perform",
  133. LDAPResultLoopDetect: "Loop Detect",
  134. LDAPResultNamingViolation: "Naming Violation",
  135. LDAPResultObjectClassViolation: "Object Class Violation",
  136. LDAPResultNotAllowedOnNonLeaf: "Not Allowed On Non Leaf",
  137. LDAPResultNotAllowedOnRDN: "Not Allowed On RDN",
  138. LDAPResultEntryAlreadyExists: "Entry Already Exists",
  139. LDAPResultObjectClassModsProhibited: "Object Class Mods Prohibited",
  140. LDAPResultAffectsMultipleDSAs: "Affects Multiple DSAs",
  141. LDAPResultOther: "Other",
  142. }
  143. // Adds descriptions to an LDAP Response packet for debugging
  144. func addLDAPDescriptions(packet *ber.Packet) (err error) {
  145. defer func() {
  146. if r := recover(); r != nil {
  147. err = NewError(ErrorDebugging, errors.New("ldap: cannot process packet to add descriptions"))
  148. }
  149. }()
  150. packet.Description = "LDAP Response"
  151. packet.Children[0].Description = "Message ID"
  152. application := packet.Children[1].Tag
  153. packet.Children[1].Description = ApplicationMap[application]
  154. switch application {
  155. case ApplicationBindRequest:
  156. addRequestDescriptions(packet)
  157. case ApplicationBindResponse:
  158. addDefaultLDAPResponseDescriptions(packet)
  159. case ApplicationUnbindRequest:
  160. addRequestDescriptions(packet)
  161. case ApplicationSearchRequest:
  162. addRequestDescriptions(packet)
  163. case ApplicationSearchResultEntry:
  164. packet.Children[1].Children[0].Description = "Object Name"
  165. packet.Children[1].Children[1].Description = "Attributes"
  166. for _, child := range packet.Children[1].Children[1].Children {
  167. child.Description = "Attribute"
  168. child.Children[0].Description = "Attribute Name"
  169. child.Children[1].Description = "Attribute Values"
  170. for _, grandchild := range child.Children[1].Children {
  171. grandchild.Description = "Attribute Value"
  172. }
  173. }
  174. if len(packet.Children) == 3 {
  175. addControlDescriptions(packet.Children[2])
  176. }
  177. case ApplicationSearchResultDone:
  178. addDefaultLDAPResponseDescriptions(packet)
  179. case ApplicationModifyRequest:
  180. addRequestDescriptions(packet)
  181. case ApplicationModifyResponse:
  182. case ApplicationAddRequest:
  183. addRequestDescriptions(packet)
  184. case ApplicationAddResponse:
  185. case ApplicationDelRequest:
  186. addRequestDescriptions(packet)
  187. case ApplicationDelResponse:
  188. case ApplicationModifyDNRequest:
  189. addRequestDescriptions(packet)
  190. case ApplicationModifyDNResponse:
  191. case ApplicationCompareRequest:
  192. addRequestDescriptions(packet)
  193. case ApplicationCompareResponse:
  194. case ApplicationAbandonRequest:
  195. addRequestDescriptions(packet)
  196. case ApplicationSearchResultReference:
  197. case ApplicationExtendedRequest:
  198. addRequestDescriptions(packet)
  199. case ApplicationExtendedResponse:
  200. }
  201. return nil
  202. }
  203. func addControlDescriptions(packet *ber.Packet) {
  204. packet.Description = "Controls"
  205. for _, child := range packet.Children {
  206. child.Description = "Control"
  207. child.Children[0].Description = "Control Type (" + ControlTypeMap[child.Children[0].Value.(string)] + ")"
  208. value := child.Children[1]
  209. if len(child.Children) == 3 {
  210. child.Children[1].Description = "Criticality"
  211. value = child.Children[2]
  212. }
  213. value.Description = "Control Value"
  214. switch child.Children[0].Value.(string) {
  215. case ControlTypePaging:
  216. value.Description += " (Paging)"
  217. if value.Value != nil {
  218. valueChildren := ber.DecodePacket(value.Data.Bytes())
  219. value.Data.Truncate(0)
  220. value.Value = nil
  221. valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
  222. value.AppendChild(valueChildren)
  223. }
  224. value.Children[0].Description = "Real Search Control Value"
  225. value.Children[0].Children[0].Description = "Paging Size"
  226. value.Children[0].Children[1].Description = "Cookie"
  227. }
  228. }
  229. }
  230. func addRequestDescriptions(packet *ber.Packet) {
  231. packet.Description = "LDAP Request"
  232. packet.Children[0].Description = "Message ID"
  233. packet.Children[1].Description = ApplicationMap[packet.Children[1].Tag]
  234. if len(packet.Children) == 3 {
  235. addControlDescriptions(packet.Children[2])
  236. }
  237. }
  238. func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
  239. resultCode := packet.Children[1].Children[0].Value.(uint64)
  240. packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[uint8(resultCode)] + ")"
  241. packet.Children[1].Children[1].Description = "Matched DN"
  242. packet.Children[1].Children[2].Description = "Error Message"
  243. if len(packet.Children[1].Children) > 3 {
  244. packet.Children[1].Children[3].Description = "Referral"
  245. }
  246. if len(packet.Children) == 3 {
  247. addControlDescriptions(packet.Children[2])
  248. }
  249. }
  250. func DebugBinaryFile(fileName string) error {
  251. file, err := ioutil.ReadFile(fileName)
  252. if err != nil {
  253. return NewError(ErrorDebugging, err)
  254. }
  255. ber.PrintBytes(file, "")
  256. packet := ber.DecodePacket(file)
  257. addLDAPDescriptions(packet)
  258. ber.PrintPacket(packet)
  259. return nil
  260. }
  261. type Error struct {
  262. Err error
  263. ResultCode uint8
  264. }
  265. func (e *Error) Error() string {
  266. return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
  267. }
  268. func NewError(resultCode uint8, err error) error {
  269. return &Error{ResultCode: resultCode, Err: err}
  270. }
  271. func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
  272. if len(packet.Children) >= 2 {
  273. response := packet.Children[1]
  274. if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) == 3 {
  275. return uint8(response.Children[0].Value.(uint64)), response.Children[2].Value.(string)
  276. }
  277. }
  278. return ErrorNetwork, "Invalid packet format"
  279. }