search.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. //
  5. // File contains Search functionality
  6. //
  7. // https://tools.ietf.org/html/rfc4511
  8. //
  9. // SearchRequest ::= [APPLICATION 3] SEQUENCE {
  10. // baseObject LDAPDN,
  11. // scope ENUMERATED {
  12. // baseObject (0),
  13. // singleLevel (1),
  14. // wholeSubtree (2),
  15. // ... },
  16. // derefAliases ENUMERATED {
  17. // neverDerefAliases (0),
  18. // derefInSearching (1),
  19. // derefFindingBaseObj (2),
  20. // derefAlways (3) },
  21. // sizeLimit INTEGER (0 .. maxInt),
  22. // timeLimit INTEGER (0 .. maxInt),
  23. // typesOnly BOOLEAN,
  24. // filter Filter,
  25. // attributes AttributeSelection }
  26. //
  27. // AttributeSelection ::= SEQUENCE OF selector LDAPString
  28. // -- The LDAPString is constrained to
  29. // -- <attributeSelector> in Section 4.5.1.8
  30. //
  31. // Filter ::= CHOICE {
  32. // and [0] SET SIZE (1..MAX) OF filter Filter,
  33. // or [1] SET SIZE (1..MAX) OF filter Filter,
  34. // not [2] Filter,
  35. // equalityMatch [3] AttributeValueAssertion,
  36. // substrings [4] SubstringFilter,
  37. // greaterOrEqual [5] AttributeValueAssertion,
  38. // lessOrEqual [6] AttributeValueAssertion,
  39. // present [7] AttributeDescription,
  40. // approxMatch [8] AttributeValueAssertion,
  41. // extensibleMatch [9] MatchingRuleAssertion,
  42. // ... }
  43. //
  44. // SubstringFilter ::= SEQUENCE {
  45. // type AttributeDescription,
  46. // substrings SEQUENCE SIZE (1..MAX) OF substring CHOICE {
  47. // initial [0] AssertionValue, -- can occur at most once
  48. // any [1] AssertionValue,
  49. // final [2] AssertionValue } -- can occur at most once
  50. // }
  51. //
  52. // MatchingRuleAssertion ::= SEQUENCE {
  53. // matchingRule [1] MatchingRuleId OPTIONAL,
  54. // type [2] AttributeDescription OPTIONAL,
  55. // matchValue [3] AssertionValue,
  56. // dnAttributes [4] BOOLEAN DEFAULT FALSE }
  57. //
  58. //
  59. package ldap
  60. import (
  61. "errors"
  62. "fmt"
  63. "strings"
  64. "github.com/gogits/gogs/modules/asn1-ber"
  65. )
  66. const (
  67. ScopeBaseObject = 0
  68. ScopeSingleLevel = 1
  69. ScopeWholeSubtree = 2
  70. )
  71. var ScopeMap = map[int]string{
  72. ScopeBaseObject: "Base Object",
  73. ScopeSingleLevel: "Single Level",
  74. ScopeWholeSubtree: "Whole Subtree",
  75. }
  76. const (
  77. NeverDerefAliases = 0
  78. DerefInSearching = 1
  79. DerefFindingBaseObj = 2
  80. DerefAlways = 3
  81. )
  82. var DerefMap = map[int]string{
  83. NeverDerefAliases: "NeverDerefAliases",
  84. DerefInSearching: "DerefInSearching",
  85. DerefFindingBaseObj: "DerefFindingBaseObj",
  86. DerefAlways: "DerefAlways",
  87. }
  88. type Entry struct {
  89. DN string
  90. Attributes []*EntryAttribute
  91. }
  92. func (e *Entry) GetAttributeValues(attribute string) []string {
  93. for _, attr := range e.Attributes {
  94. if attr.Name == attribute {
  95. return attr.Values
  96. }
  97. }
  98. return []string{}
  99. }
  100. func (e *Entry) GetAttributeValue(attribute string) string {
  101. values := e.GetAttributeValues(attribute)
  102. if len(values) == 0 {
  103. return ""
  104. }
  105. return values[0]
  106. }
  107. func (e *Entry) Print() {
  108. fmt.Printf("DN: %s\n", e.DN)
  109. for _, attr := range e.Attributes {
  110. attr.Print()
  111. }
  112. }
  113. func (e *Entry) PrettyPrint(indent int) {
  114. fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
  115. for _, attr := range e.Attributes {
  116. attr.PrettyPrint(indent + 2)
  117. }
  118. }
  119. type EntryAttribute struct {
  120. Name string
  121. Values []string
  122. }
  123. func (e *EntryAttribute) Print() {
  124. fmt.Printf("%s: %s\n", e.Name, e.Values)
  125. }
  126. func (e *EntryAttribute) PrettyPrint(indent int) {
  127. fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
  128. }
  129. type SearchResult struct {
  130. Entries []*Entry
  131. Referrals []string
  132. Controls []Control
  133. }
  134. func (s *SearchResult) Print() {
  135. for _, entry := range s.Entries {
  136. entry.Print()
  137. }
  138. }
  139. func (s *SearchResult) PrettyPrint(indent int) {
  140. for _, entry := range s.Entries {
  141. entry.PrettyPrint(indent)
  142. }
  143. }
  144. type SearchRequest struct {
  145. BaseDN string
  146. Scope int
  147. DerefAliases int
  148. SizeLimit int
  149. TimeLimit int
  150. TypesOnly bool
  151. Filter string
  152. Attributes []string
  153. Controls []Control
  154. }
  155. func (s *SearchRequest) encode() (*ber.Packet, error) {
  156. request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
  157. request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, s.BaseDN, "Base DN"))
  158. request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.Scope), "Scope"))
  159. request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.DerefAliases), "Deref Aliases"))
  160. request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.SizeLimit), "Size Limit"))
  161. request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.TimeLimit), "Time Limit"))
  162. request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, s.TypesOnly, "Types Only"))
  163. // compile and encode filter
  164. filterPacket, err := CompileFilter(s.Filter)
  165. if err != nil {
  166. return nil, err
  167. }
  168. request.AppendChild(filterPacket)
  169. // encode attributes
  170. attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
  171. for _, attribute := range s.Attributes {
  172. attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
  173. }
  174. request.AppendChild(attributesPacket)
  175. return request, nil
  176. }
  177. func NewSearchRequest(
  178. BaseDN string,
  179. Scope, DerefAliases, SizeLimit, TimeLimit int,
  180. TypesOnly bool,
  181. Filter string,
  182. Attributes []string,
  183. Controls []Control,
  184. ) *SearchRequest {
  185. return &SearchRequest{
  186. BaseDN: BaseDN,
  187. Scope: Scope,
  188. DerefAliases: DerefAliases,
  189. SizeLimit: SizeLimit,
  190. TimeLimit: TimeLimit,
  191. TypesOnly: TypesOnly,
  192. Filter: Filter,
  193. Attributes: Attributes,
  194. Controls: Controls,
  195. }
  196. }
  197. func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
  198. if searchRequest.Controls == nil {
  199. searchRequest.Controls = make([]Control, 0)
  200. }
  201. pagingControl := NewControlPaging(pagingSize)
  202. searchRequest.Controls = append(searchRequest.Controls, pagingControl)
  203. searchResult := new(SearchResult)
  204. for {
  205. result, err := l.Search(searchRequest)
  206. l.Debug.Printf("Looking for Paging Control...")
  207. if err != nil {
  208. return searchResult, err
  209. }
  210. if result == nil {
  211. return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
  212. }
  213. for _, entry := range result.Entries {
  214. searchResult.Entries = append(searchResult.Entries, entry)
  215. }
  216. for _, referral := range result.Referrals {
  217. searchResult.Referrals = append(searchResult.Referrals, referral)
  218. }
  219. for _, control := range result.Controls {
  220. searchResult.Controls = append(searchResult.Controls, control)
  221. }
  222. l.Debug.Printf("Looking for Paging Control...")
  223. pagingResult := FindControl(result.Controls, ControlTypePaging)
  224. if pagingResult == nil {
  225. pagingControl = nil
  226. l.Debug.Printf("Could not find paging control. Breaking...")
  227. break
  228. }
  229. cookie := pagingResult.(*ControlPaging).Cookie
  230. if len(cookie) == 0 {
  231. pagingControl = nil
  232. l.Debug.Printf("Could not find cookie. Breaking...")
  233. break
  234. }
  235. pagingControl.SetCookie(cookie)
  236. }
  237. if pagingControl != nil {
  238. l.Debug.Printf("Abandoning Paging...")
  239. pagingControl.PagingSize = 0
  240. l.Search(searchRequest)
  241. }
  242. return searchResult, nil
  243. }
  244. func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
  245. messageID := l.nextMessageID()
  246. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
  247. packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
  248. // encode search request
  249. encodedSearchRequest, err := searchRequest.encode()
  250. if err != nil {
  251. return nil, err
  252. }
  253. packet.AppendChild(encodedSearchRequest)
  254. // encode search controls
  255. if searchRequest.Controls != nil {
  256. packet.AppendChild(encodeControls(searchRequest.Controls))
  257. }
  258. l.Debug.PrintPacket(packet)
  259. channel, err := l.sendMessage(packet)
  260. if err != nil {
  261. return nil, err
  262. }
  263. if channel == nil {
  264. return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
  265. }
  266. defer l.finishMessage(messageID)
  267. result := &SearchResult{
  268. Entries: make([]*Entry, 0),
  269. Referrals: make([]string, 0),
  270. Controls: make([]Control, 0)}
  271. foundSearchResultDone := false
  272. for !foundSearchResultDone {
  273. l.Debug.Printf("%d: waiting for response", messageID)
  274. packet = <-channel
  275. l.Debug.Printf("%d: got response %p", messageID, packet)
  276. if packet == nil {
  277. return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
  278. }
  279. if l.Debug {
  280. if err := addLDAPDescriptions(packet); err != nil {
  281. return nil, err
  282. }
  283. ber.PrintPacket(packet)
  284. }
  285. switch packet.Children[1].Tag {
  286. case 4:
  287. entry := new(Entry)
  288. entry.DN = packet.Children[1].Children[0].Value.(string)
  289. for _, child := range packet.Children[1].Children[1].Children {
  290. attr := new(EntryAttribute)
  291. attr.Name = child.Children[0].Value.(string)
  292. for _, value := range child.Children[1].Children {
  293. attr.Values = append(attr.Values, value.Value.(string))
  294. }
  295. entry.Attributes = append(entry.Attributes, attr)
  296. }
  297. result.Entries = append(result.Entries, entry)
  298. case 5:
  299. resultCode, resultDescription := getLDAPResultCode(packet)
  300. if resultCode != 0 {
  301. return result, NewError(resultCode, errors.New(resultDescription))
  302. }
  303. if len(packet.Children) == 3 {
  304. for _, child := range packet.Children[2].Children {
  305. result.Controls = append(result.Controls, DecodeControl(child))
  306. }
  307. }
  308. foundSearchResultDone = true
  309. case 19:
  310. result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
  311. }
  312. }
  313. l.Debug.Printf("%d: returning", messageID)
  314. return result, nil
  315. }