Remove ldap dep
This commit is contained in:
		
							parent
							
								
									25d6ae69d1
								
							
						
					
					
						commit
						59a7c7c5a5
					
				@ -2,6 +2,8 @@
 | 
				
			|||||||
path = github.com/gogits/gogs
 | 
					path = github.com/gogits/gogs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[deps]
 | 
					[deps]
 | 
				
			||||||
 | 
					github.com/beego/memcache = 
 | 
				
			||||||
 | 
					github.com/beego/redigo = 
 | 
				
			||||||
github.com/Unknwon/cae = 
 | 
					github.com/Unknwon/cae = 
 | 
				
			||||||
github.com/Unknwon/com = 
 | 
					github.com/Unknwon/com = 
 | 
				
			||||||
github.com/Unknwon/goconfig = 
 | 
					github.com/Unknwon/goconfig = 
 | 
				
			||||||
@ -14,7 +16,6 @@ github.com/go-xorm/xorm =
 | 
				
			|||||||
github.com/gogits/gfm = 
 | 
					github.com/gogits/gfm = 
 | 
				
			||||||
github.com/gogits/git = 
 | 
					github.com/gogits/git = 
 | 
				
			||||||
github.com/gogits/oauth2 = 
 | 
					github.com/gogits/oauth2 = 
 | 
				
			||||||
github.com/juju2013/goldap = 
 | 
					 | 
				
			||||||
github.com/lib/pq = 
 | 
					github.com/lib/pq = 
 | 
				
			||||||
github.com/macaron-contrib/cache = 
 | 
					github.com/macaron-contrib/cache = 
 | 
				
			||||||
github.com/macaron-contrib/captcha = 
 | 
					github.com/macaron-contrib/captcha = 
 | 
				
			||||||
@ -22,6 +23,7 @@ github.com/macaron-contrib/csrf =
 | 
				
			|||||||
github.com/macaron-contrib/i18n = 
 | 
					github.com/macaron-contrib/i18n = 
 | 
				
			||||||
github.com/macaron-contrib/session = 
 | 
					github.com/macaron-contrib/session = 
 | 
				
			||||||
github.com/macaron-contrib/toolbox = 
 | 
					github.com/macaron-contrib/toolbox = 
 | 
				
			||||||
 | 
					github.com/mattn/go-sqlite3 = 
 | 
				
			||||||
github.com/nfnt/resize = 
 | 
					github.com/nfnt/resize = 
 | 
				
			||||||
github.com/saintfish/chardet = 
 | 
					github.com/saintfish/chardet = 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								modules/asn1-ber/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/asn1-ber/LICENSE
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					met:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					   * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					distribution.
 | 
				
			||||||
 | 
					   * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
							
								
								
									
										11
									
								
								modules/asn1-ber/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								modules/asn1-ber/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					# Copyright 2009 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					# Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					# license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(GOROOT)/src/Make.inc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TARG=github.com/mmitton/asn1-ber
 | 
				
			||||||
 | 
					GOFILES=\
 | 
				
			||||||
 | 
						ber.go\
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(GOROOT)/src/Make.pkg
 | 
				
			||||||
							
								
								
									
										14
									
								
								modules/asn1-ber/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								modules/asn1-ber/README
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					ASN1 BER Encoding / Decoding Library for the GO programming language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Required Librarys: 
 | 
				
			||||||
 | 
					   None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Working:
 | 
				
			||||||
 | 
					   Very basic encoding / decoding needed for LDAP protocol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tests Implemented:
 | 
				
			||||||
 | 
					   None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TODO:
 | 
				
			||||||
 | 
					   Fix all encoding / decoding to conform to ASN1 BER spec
 | 
				
			||||||
 | 
					   Implement Tests / Benchmarks
 | 
				
			||||||
							
								
								
									
										492
									
								
								modules/asn1-ber/ber.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										492
									
								
								modules/asn1-ber/ber.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,492 @@
 | 
				
			|||||||
 | 
					package ber
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Packet struct {
 | 
				
			||||||
 | 
						ClassType   uint8
 | 
				
			||||||
 | 
						TagType     uint8
 | 
				
			||||||
 | 
						Tag         uint8
 | 
				
			||||||
 | 
						Value       interface{}
 | 
				
			||||||
 | 
						ByteValue   []byte
 | 
				
			||||||
 | 
						Data        *bytes.Buffer
 | 
				
			||||||
 | 
						Children    []*Packet
 | 
				
			||||||
 | 
						Description string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TagEOC              = 0x00
 | 
				
			||||||
 | 
						TagBoolean          = 0x01
 | 
				
			||||||
 | 
						TagInteger          = 0x02
 | 
				
			||||||
 | 
						TagBitString        = 0x03
 | 
				
			||||||
 | 
						TagOctetString      = 0x04
 | 
				
			||||||
 | 
						TagNULL             = 0x05
 | 
				
			||||||
 | 
						TagObjectIdentifier = 0x06
 | 
				
			||||||
 | 
						TagObjectDescriptor = 0x07
 | 
				
			||||||
 | 
						TagExternal         = 0x08
 | 
				
			||||||
 | 
						TagRealFloat        = 0x09
 | 
				
			||||||
 | 
						TagEnumerated       = 0x0a
 | 
				
			||||||
 | 
						TagEmbeddedPDV      = 0x0b
 | 
				
			||||||
 | 
						TagUTF8String       = 0x0c
 | 
				
			||||||
 | 
						TagRelativeOID      = 0x0d
 | 
				
			||||||
 | 
						TagSequence         = 0x10
 | 
				
			||||||
 | 
						TagSet              = 0x11
 | 
				
			||||||
 | 
						TagNumericString    = 0x12
 | 
				
			||||||
 | 
						TagPrintableString  = 0x13
 | 
				
			||||||
 | 
						TagT61String        = 0x14
 | 
				
			||||||
 | 
						TagVideotexString   = 0x15
 | 
				
			||||||
 | 
						TagIA5String        = 0x16
 | 
				
			||||||
 | 
						TagUTCTime          = 0x17
 | 
				
			||||||
 | 
						TagGeneralizedTime  = 0x18
 | 
				
			||||||
 | 
						TagGraphicString    = 0x19
 | 
				
			||||||
 | 
						TagVisibleString    = 0x1a
 | 
				
			||||||
 | 
						TagGeneralString    = 0x1b
 | 
				
			||||||
 | 
						TagUniversalString  = 0x1c
 | 
				
			||||||
 | 
						TagCharacterString  = 0x1d
 | 
				
			||||||
 | 
						TagBMPString        = 0x1e
 | 
				
			||||||
 | 
						TagBitmask          = 0x1f // xxx11111b
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var TagMap = map[uint8]string{
 | 
				
			||||||
 | 
						TagEOC:              "EOC (End-of-Content)",
 | 
				
			||||||
 | 
						TagBoolean:          "Boolean",
 | 
				
			||||||
 | 
						TagInteger:          "Integer",
 | 
				
			||||||
 | 
						TagBitString:        "Bit String",
 | 
				
			||||||
 | 
						TagOctetString:      "Octet String",
 | 
				
			||||||
 | 
						TagNULL:             "NULL",
 | 
				
			||||||
 | 
						TagObjectIdentifier: "Object Identifier",
 | 
				
			||||||
 | 
						TagObjectDescriptor: "Object Descriptor",
 | 
				
			||||||
 | 
						TagExternal:         "External",
 | 
				
			||||||
 | 
						TagRealFloat:        "Real (float)",
 | 
				
			||||||
 | 
						TagEnumerated:       "Enumerated",
 | 
				
			||||||
 | 
						TagEmbeddedPDV:      "Embedded PDV",
 | 
				
			||||||
 | 
						TagUTF8String:       "UTF8 String",
 | 
				
			||||||
 | 
						TagRelativeOID:      "Relative-OID",
 | 
				
			||||||
 | 
						TagSequence:         "Sequence and Sequence of",
 | 
				
			||||||
 | 
						TagSet:              "Set and Set OF",
 | 
				
			||||||
 | 
						TagNumericString:    "Numeric String",
 | 
				
			||||||
 | 
						TagPrintableString:  "Printable String",
 | 
				
			||||||
 | 
						TagT61String:        "T61 String",
 | 
				
			||||||
 | 
						TagVideotexString:   "Videotex String",
 | 
				
			||||||
 | 
						TagIA5String:        "IA5 String",
 | 
				
			||||||
 | 
						TagUTCTime:          "UTC Time",
 | 
				
			||||||
 | 
						TagGeneralizedTime:  "Generalized Time",
 | 
				
			||||||
 | 
						TagGraphicString:    "Graphic String",
 | 
				
			||||||
 | 
						TagVisibleString:    "Visible String",
 | 
				
			||||||
 | 
						TagGeneralString:    "General String",
 | 
				
			||||||
 | 
						TagUniversalString:  "Universal String",
 | 
				
			||||||
 | 
						TagCharacterString:  "Character String",
 | 
				
			||||||
 | 
						TagBMPString:        "BMP String",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ClassUniversal   = 0   // 00xxxxxxb
 | 
				
			||||||
 | 
						ClassApplication = 64  // 01xxxxxxb
 | 
				
			||||||
 | 
						ClassContext     = 128 // 10xxxxxxb
 | 
				
			||||||
 | 
						ClassPrivate     = 192 // 11xxxxxxb
 | 
				
			||||||
 | 
						ClassBitmask     = 192 // 11xxxxxxb
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ClassMap = map[uint8]string{
 | 
				
			||||||
 | 
						ClassUniversal:   "Universal",
 | 
				
			||||||
 | 
						ClassApplication: "Application",
 | 
				
			||||||
 | 
						ClassContext:     "Context",
 | 
				
			||||||
 | 
						ClassPrivate:     "Private",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						TypePrimitive   = 0  // xx0xxxxxb
 | 
				
			||||||
 | 
						TypeConstructed = 32 // xx1xxxxxb
 | 
				
			||||||
 | 
						TypeBitmask     = 32 // xx1xxxxxb
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var TypeMap = map[uint8]string{
 | 
				
			||||||
 | 
						TypePrimitive:   "Primative",
 | 
				
			||||||
 | 
						TypeConstructed: "Constructed",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var Debug bool = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PrintBytes(buf []byte, indent string) {
 | 
				
			||||||
 | 
						data_lines := make([]string, (len(buf)/30)+1)
 | 
				
			||||||
 | 
						num_lines := make([]string, (len(buf)/30)+1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, b := range buf {
 | 
				
			||||||
 | 
							data_lines[i/30] += fmt.Sprintf("%02x ", b)
 | 
				
			||||||
 | 
							num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i := 0; i < len(data_lines); i++ {
 | 
				
			||||||
 | 
							fmt.Print(indent + data_lines[i] + "\n")
 | 
				
			||||||
 | 
							fmt.Print(indent + num_lines[i] + "\n\n")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PrintPacket(p *Packet) {
 | 
				
			||||||
 | 
						printPacket(p, 0, false)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func printPacket(p *Packet, indent int, printBytes bool) {
 | 
				
			||||||
 | 
						indent_str := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for len(indent_str) != indent {
 | 
				
			||||||
 | 
							indent_str += " "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						class_str := ClassMap[p.ClassType]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tagtype_str := TypeMap[p.TagType]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tag_str := fmt.Sprintf("0x%02X", p.Tag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.ClassType == ClassUniversal {
 | 
				
			||||||
 | 
							tag_str = TagMap[p.Tag]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value := fmt.Sprint(p.Value)
 | 
				
			||||||
 | 
						description := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.Description != "" {
 | 
				
			||||||
 | 
							description = p.Description + ": "
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if printBytes {
 | 
				
			||||||
 | 
							PrintBytes(p.Bytes(), indent_str)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, child := range p.Children {
 | 
				
			||||||
 | 
							printPacket(child, indent+1, printBytes)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func resizeBuffer(in []byte, new_size uint64) (out []byte) {
 | 
				
			||||||
 | 
						out = make([]byte, new_size)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						copy(out, in)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readBytes(reader io.Reader, buf []byte) error {
 | 
				
			||||||
 | 
						idx := 0
 | 
				
			||||||
 | 
						buflen := len(buf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for idx < buflen {
 | 
				
			||||||
 | 
							n, err := reader.Read(buf[idx:])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							idx += n
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ReadPacket(reader io.Reader) (*Packet, error) {
 | 
				
			||||||
 | 
						buf := make([]byte, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := readBytes(reader, buf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						idx := uint64(2)
 | 
				
			||||||
 | 
						datalen := uint64(buf[1])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Debug {
 | 
				
			||||||
 | 
							fmt.Printf("Read: datalen = %d len(buf) = %d ", datalen, len(buf))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, b := range buf {
 | 
				
			||||||
 | 
								fmt.Printf("%02X ", b)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							fmt.Printf("\n")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if datalen&128 != 0 {
 | 
				
			||||||
 | 
							a := datalen - 128
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							idx += a
 | 
				
			||||||
 | 
							buf = resizeBuffer(buf, 2+a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err := readBytes(reader, buf[2:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							datalen = DecodeInteger(buf[2 : 2+a])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if Debug {
 | 
				
			||||||
 | 
								fmt.Printf("Read: a = %d  idx = %d  datalen = %d  len(buf) = %d", a, idx, datalen, len(buf))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for _, b := range buf {
 | 
				
			||||||
 | 
									fmt.Printf("%02X ", b)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								fmt.Printf("\n")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = resizeBuffer(buf, idx+datalen)
 | 
				
			||||||
 | 
						err = readBytes(reader, buf[idx:])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Debug {
 | 
				
			||||||
 | 
							fmt.Printf("Read: len( buf ) = %d  idx=%d datalen=%d idx+datalen=%d\n", len(buf), idx, datalen, idx+datalen)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, b := range buf {
 | 
				
			||||||
 | 
								fmt.Printf("%02X ", b)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p := DecodePacket(buf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecodeString(data []byte) (ret string) {
 | 
				
			||||||
 | 
						for _, c := range data {
 | 
				
			||||||
 | 
							ret += fmt.Sprintf("%c", c)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecodeInteger(data []byte) (ret uint64) {
 | 
				
			||||||
 | 
						for _, i := range data {
 | 
				
			||||||
 | 
							ret = ret * 256
 | 
				
			||||||
 | 
							ret = ret + uint64(i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func EncodeInteger(val uint64) []byte {
 | 
				
			||||||
 | 
						var out bytes.Buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						found := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						shift := uint(56)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mask := uint64(0xFF00000000000000)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for mask > 0 {
 | 
				
			||||||
 | 
							if !found && (val&mask != 0) {
 | 
				
			||||||
 | 
								found = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if found || (shift == 0) {
 | 
				
			||||||
 | 
								out.Write([]byte{byte((val & mask) >> shift)})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							shift -= 8
 | 
				
			||||||
 | 
							mask = mask >> 8
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return out.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecodePacket(data []byte) *Packet {
 | 
				
			||||||
 | 
						p, _ := decodePacket(data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func decodePacket(data []byte) (*Packet, []byte) {
 | 
				
			||||||
 | 
						if Debug {
 | 
				
			||||||
 | 
							fmt.Printf("decodePacket: enter %d\n", len(data))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p := new(Packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.ClassType = data[0] & ClassBitmask
 | 
				
			||||||
 | 
						p.TagType = data[0] & TypeBitmask
 | 
				
			||||||
 | 
						p.Tag = data[0] & TagBitmask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						datalen := DecodeInteger(data[1:2])
 | 
				
			||||||
 | 
						datapos := uint64(2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if datalen&128 != 0 {
 | 
				
			||||||
 | 
							datalen -= 128
 | 
				
			||||||
 | 
							datapos += datalen
 | 
				
			||||||
 | 
							datalen = DecodeInteger(data[2 : 2+datalen])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Data = new(bytes.Buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Children = make([]*Packet, 0, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Value = nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value_data := data[datapos : datapos+datalen]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.TagType == TypeConstructed {
 | 
				
			||||||
 | 
							for len(value_data) != 0 {
 | 
				
			||||||
 | 
								var child *Packet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								child, value_data = decodePacket(value_data)
 | 
				
			||||||
 | 
								p.AppendChild(child)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if p.ClassType == ClassUniversal {
 | 
				
			||||||
 | 
							p.Data.Write(data[datapos : datapos+datalen])
 | 
				
			||||||
 | 
							p.ByteValue = value_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch p.Tag {
 | 
				
			||||||
 | 
							case TagEOC:
 | 
				
			||||||
 | 
							case TagBoolean:
 | 
				
			||||||
 | 
								val := DecodeInteger(value_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								p.Value = val != 0
 | 
				
			||||||
 | 
							case TagInteger:
 | 
				
			||||||
 | 
								p.Value = DecodeInteger(value_data)
 | 
				
			||||||
 | 
							case TagBitString:
 | 
				
			||||||
 | 
							case TagOctetString:
 | 
				
			||||||
 | 
								p.Value = DecodeString(value_data)
 | 
				
			||||||
 | 
							case TagNULL:
 | 
				
			||||||
 | 
							case TagObjectIdentifier:
 | 
				
			||||||
 | 
							case TagObjectDescriptor:
 | 
				
			||||||
 | 
							case TagExternal:
 | 
				
			||||||
 | 
							case TagRealFloat:
 | 
				
			||||||
 | 
							case TagEnumerated:
 | 
				
			||||||
 | 
								p.Value = DecodeInteger(value_data)
 | 
				
			||||||
 | 
							case TagEmbeddedPDV:
 | 
				
			||||||
 | 
							case TagUTF8String:
 | 
				
			||||||
 | 
							case TagRelativeOID:
 | 
				
			||||||
 | 
							case TagSequence:
 | 
				
			||||||
 | 
							case TagSet:
 | 
				
			||||||
 | 
							case TagNumericString:
 | 
				
			||||||
 | 
							case TagPrintableString:
 | 
				
			||||||
 | 
								p.Value = DecodeString(value_data)
 | 
				
			||||||
 | 
							case TagT61String:
 | 
				
			||||||
 | 
							case TagVideotexString:
 | 
				
			||||||
 | 
							case TagIA5String:
 | 
				
			||||||
 | 
							case TagUTCTime:
 | 
				
			||||||
 | 
							case TagGeneralizedTime:
 | 
				
			||||||
 | 
							case TagGraphicString:
 | 
				
			||||||
 | 
							case TagVisibleString:
 | 
				
			||||||
 | 
							case TagGeneralString:
 | 
				
			||||||
 | 
							case TagUniversalString:
 | 
				
			||||||
 | 
							case TagCharacterString:
 | 
				
			||||||
 | 
							case TagBMPString:
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							p.Data.Write(data[datapos : datapos+datalen])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p, data[datapos+datalen:]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Packet) DataLength() uint64 {
 | 
				
			||||||
 | 
						return uint64(p.Data.Len())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Packet) Bytes() []byte {
 | 
				
			||||||
 | 
						var out bytes.Buffer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out.Write([]byte{p.ClassType | p.TagType | p.Tag})
 | 
				
			||||||
 | 
						packet_length := EncodeInteger(p.DataLength())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if p.DataLength() > 127 || len(packet_length) > 1 {
 | 
				
			||||||
 | 
							out.Write([]byte{byte(len(packet_length) | 128)})
 | 
				
			||||||
 | 
							out.Write(packet_length)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							out.Write(packet_length)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						out.Write(p.Data.Bytes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return out.Bytes()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *Packet) AppendChild(child *Packet) {
 | 
				
			||||||
 | 
						p.Data.Write(child.Bytes())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(p.Children) == cap(p.Children) {
 | 
				
			||||||
 | 
							newChildren := make([]*Packet, cap(p.Children)*2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							copy(newChildren, p.Children)
 | 
				
			||||||
 | 
							p.Children = newChildren[0:len(p.Children)]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Children = p.Children[0 : len(p.Children)+1]
 | 
				
			||||||
 | 
						p.Children[len(p.Children)-1] = child
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Encode(ClassType, TagType, Tag uint8, Value interface{}, Description string) *Packet {
 | 
				
			||||||
 | 
						p := new(Packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.ClassType = ClassType
 | 
				
			||||||
 | 
						p.TagType = TagType
 | 
				
			||||||
 | 
						p.Tag = Tag
 | 
				
			||||||
 | 
						p.Data = new(bytes.Buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Children = make([]*Packet, 0, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Value = Value
 | 
				
			||||||
 | 
						p.Description = Description
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Value != nil {
 | 
				
			||||||
 | 
							v := reflect.ValueOf(Value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if ClassType == ClassUniversal {
 | 
				
			||||||
 | 
								switch Tag {
 | 
				
			||||||
 | 
								case TagOctetString:
 | 
				
			||||||
 | 
									sv, ok := v.Interface().(string)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if ok {
 | 
				
			||||||
 | 
										p.Data.Write([]byte(sv))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSequence(Description string) *Packet {
 | 
				
			||||||
 | 
						return Encode(ClassUniversal, TypePrimitive, TagSequence, nil, Description)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewBoolean(ClassType, TagType, Tag uint8, Value bool, Description string) *Packet {
 | 
				
			||||||
 | 
						intValue := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if Value {
 | 
				
			||||||
 | 
							intValue = 1
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Value = Value
 | 
				
			||||||
 | 
						p.Data.Write(EncodeInteger(uint64(intValue)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewInteger(ClassType, TagType, Tag uint8, Value uint64, Description string) *Packet {
 | 
				
			||||||
 | 
						p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Value = Value
 | 
				
			||||||
 | 
						p.Data.Write(EncodeInteger(Value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewString(ClassType, TagType, Tag uint8, Value, Description string) *Packet {
 | 
				
			||||||
 | 
						p := Encode(ClassType, TagType, Tag, nil, Description)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p.Value = Value
 | 
				
			||||||
 | 
						p.Data.Write([]byte(Value))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return p
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -9,8 +9,8 @@ package ldap
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/ldap"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	goldap "github.com/juju2013/goldap"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Basic LDAP authentication service
 | 
					// Basic LDAP authentication service
 | 
				
			||||||
@ -68,9 +68,9 @@ func (ls Ldapsource) SearchEntry(name, passwd string) (string, bool) {
 | 
				
			|||||||
		return "", false
 | 
							return "", false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	search := goldap.NewSearchRequest(
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
		ls.BaseDN,
 | 
							ls.BaseDN,
 | 
				
			||||||
		goldap.ScopeWholeSubtree, goldap.NeverDerefAliases, 0, 0, false,
 | 
							ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
 | 
				
			||||||
		fmt.Sprintf(ls.Filter, name),
 | 
							fmt.Sprintf(ls.Filter, name),
 | 
				
			||||||
		[]string{ls.Attributes},
 | 
							[]string{ls.Attributes},
 | 
				
			||||||
		nil)
 | 
							nil)
 | 
				
			||||||
@ -87,10 +87,10 @@ func (ls Ldapsource) SearchEntry(name, passwd string) (string, bool) {
 | 
				
			|||||||
	return "", true
 | 
						return "", true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func ldapDial(ls Ldapsource) (*goldap.Conn, error) {
 | 
					func ldapDial(ls Ldapsource) (*ldap.Conn, error) {
 | 
				
			||||||
	if ls.UseSSL {
 | 
						if ls.UseSSL {
 | 
				
			||||||
		return goldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), nil)
 | 
							return ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port), nil)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return goldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
 | 
							return ldap.Dial("tcp", fmt.Sprintf("%s:%d", ls.Host, ls.Port))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								modules/ldap/LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								modules/ldap/LICENSE
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					Copyright (c) 2012 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					modification, are permitted provided that the following conditions are
 | 
				
			||||||
 | 
					met:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   * Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					   * Redistributions in binary form must reproduce the above
 | 
				
			||||||
 | 
					copyright notice, this list of conditions and the following disclaimer
 | 
				
			||||||
 | 
					in the documentation and/or other materials provided with the
 | 
				
			||||||
 | 
					distribution.
 | 
				
			||||||
 | 
					   * Neither the name of Google Inc. nor the names of its
 | 
				
			||||||
 | 
					contributors may be used to endorse or promote products derived from
 | 
				
			||||||
 | 
					this software without specific prior written permission.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
				
			||||||
 | 
					"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 | 
				
			||||||
 | 
					A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 | 
				
			||||||
 | 
					OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
				
			||||||
 | 
					SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 | 
				
			||||||
 | 
					LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
				
			||||||
 | 
					DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
				
			||||||
 | 
					THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
				
			||||||
 | 
					(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 | 
				
			||||||
 | 
					OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
				
			||||||
							
								
								
									
										33
									
								
								modules/ldap/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								modules/ldap/README
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					Basic LDAP v3 functionality for the GO programming language.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Required Librarys: 
 | 
				
			||||||
 | 
					   github.com/johnweldon/asn1-ber
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Working:
 | 
				
			||||||
 | 
					   Connecting to LDAP server
 | 
				
			||||||
 | 
					   Binding to LDAP server
 | 
				
			||||||
 | 
					   Searching for entries
 | 
				
			||||||
 | 
					   Compiling string filters to LDAP filters
 | 
				
			||||||
 | 
					   Paging Search Results
 | 
				
			||||||
 | 
					   Modify Requests / Responses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Examples:
 | 
				
			||||||
 | 
					   search
 | 
				
			||||||
 | 
					   modify
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tests Implemented:
 | 
				
			||||||
 | 
					   Filter Compile / Decompile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TODO:
 | 
				
			||||||
 | 
					   Add Requests / Responses
 | 
				
			||||||
 | 
					   Delete Requests / Responses
 | 
				
			||||||
 | 
					   Modify DN Requests / Responses
 | 
				
			||||||
 | 
					   Compare Requests / Responses
 | 
				
			||||||
 | 
					   Implement Tests / Benchmarks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This feature is disabled at the moment, because in some cases the "Search Request Done" packet will be handled before the last "Search Request Entry":
 | 
				
			||||||
 | 
					   Mulitple internal goroutines to handle network traffic
 | 
				
			||||||
 | 
					      Makes library goroutine safe
 | 
				
			||||||
 | 
					      Can perform multiple search requests at the same time and return
 | 
				
			||||||
 | 
					         the results to the proper goroutine.  All requests are blocking
 | 
				
			||||||
 | 
					         requests, so the goroutine does not need special handling
 | 
				
			||||||
							
								
								
									
										55
									
								
								modules/ldap/bind.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								modules/ldap/bind.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) Bind(username, password string) error {
 | 
				
			||||||
 | 
						messageID := l.nextMessageID()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
 | 
				
			||||||
 | 
						bindRequest := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindRequest, nil, "Bind Request")
 | 
				
			||||||
 | 
						bindRequest.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, 3, "Version"))
 | 
				
			||||||
 | 
						bindRequest.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, username, "User Name"))
 | 
				
			||||||
 | 
						bindRequest.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, password, "Password"))
 | 
				
			||||||
 | 
						packet.AppendChild(bindRequest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l.Debug {
 | 
				
			||||||
 | 
							ber.PrintPacket(packet)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channel, err := l.sendMessage(packet)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if channel == nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.finishMessage(messageID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet = <-channel
 | 
				
			||||||
 | 
						if packet == nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, errors.New("ldap: could not retrieve response"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l.Debug {
 | 
				
			||||||
 | 
							if err := addLDAPDescriptions(packet); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ber.PrintPacket(packet)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resultCode, resultDescription := getLDAPResultCode(packet)
 | 
				
			||||||
 | 
						if resultCode != 0 {
 | 
				
			||||||
 | 
							return NewError(resultCode, errors.New(resultDescription))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										275
									
								
								modules/ldap/conn.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								modules/ldap/conn.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,275 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/tls"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						MessageQuit     = 0
 | 
				
			||||||
 | 
						MessageRequest  = 1
 | 
				
			||||||
 | 
						MessageResponse = 2
 | 
				
			||||||
 | 
						MessageFinish   = 3
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type messagePacket struct {
 | 
				
			||||||
 | 
						Op        int
 | 
				
			||||||
 | 
						MessageID uint64
 | 
				
			||||||
 | 
						Packet    *ber.Packet
 | 
				
			||||||
 | 
						Channel   chan *ber.Packet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Conn represents an LDAP Connection
 | 
				
			||||||
 | 
					type Conn struct {
 | 
				
			||||||
 | 
						conn          net.Conn
 | 
				
			||||||
 | 
						isTLS         bool
 | 
				
			||||||
 | 
						isClosing     bool
 | 
				
			||||||
 | 
						Debug         debugging
 | 
				
			||||||
 | 
						chanConfirm   chan bool
 | 
				
			||||||
 | 
						chanResults   map[uint64]chan *ber.Packet
 | 
				
			||||||
 | 
						chanMessage   chan *messagePacket
 | 
				
			||||||
 | 
						chanMessageID chan uint64
 | 
				
			||||||
 | 
						wgSender      sync.WaitGroup
 | 
				
			||||||
 | 
						wgClose       sync.WaitGroup
 | 
				
			||||||
 | 
						once          sync.Once
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dial connects to the given address on the given network using net.Dial
 | 
				
			||||||
 | 
					// and then returns a new Conn for the connection.
 | 
				
			||||||
 | 
					func Dial(network, addr string) (*Conn, error) {
 | 
				
			||||||
 | 
						c, err := net.Dial(network, addr)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorNetwork, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn := NewConn(c)
 | 
				
			||||||
 | 
						conn.start()
 | 
				
			||||||
 | 
						return conn, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DialTLS connects to the given address on the given network using tls.Dial
 | 
				
			||||||
 | 
					// and then returns a new Conn for the connection.
 | 
				
			||||||
 | 
					func DialTLS(network, addr string, config *tls.Config) (*Conn, error) {
 | 
				
			||||||
 | 
						c, err := tls.Dial(network, addr, config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorNetwork, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						conn := NewConn(c)
 | 
				
			||||||
 | 
						conn.isTLS = true
 | 
				
			||||||
 | 
						conn.start()
 | 
				
			||||||
 | 
						return conn, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewConn returns a new Conn using conn for network I/O.
 | 
				
			||||||
 | 
					func NewConn(conn net.Conn) *Conn {
 | 
				
			||||||
 | 
						return &Conn{
 | 
				
			||||||
 | 
							conn:          conn,
 | 
				
			||||||
 | 
							chanConfirm:   make(chan bool),
 | 
				
			||||||
 | 
							chanMessageID: make(chan uint64),
 | 
				
			||||||
 | 
							chanMessage:   make(chan *messagePacket, 10),
 | 
				
			||||||
 | 
							chanResults:   map[uint64]chan *ber.Packet{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) start() {
 | 
				
			||||||
 | 
						go l.reader()
 | 
				
			||||||
 | 
						go l.processMessages()
 | 
				
			||||||
 | 
						l.wgClose.Add(1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close closes the connection.
 | 
				
			||||||
 | 
					func (l *Conn) Close() {
 | 
				
			||||||
 | 
						l.once.Do(func() {
 | 
				
			||||||
 | 
							l.isClosing = true
 | 
				
			||||||
 | 
							l.wgSender.Wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.Debug.Printf("Sending quit message and waiting for confirmation")
 | 
				
			||||||
 | 
							l.chanMessage <- &messagePacket{Op: MessageQuit}
 | 
				
			||||||
 | 
							<-l.chanConfirm
 | 
				
			||||||
 | 
							close(l.chanMessage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.Debug.Printf("Closing network connection")
 | 
				
			||||||
 | 
							if err := l.conn.Close(); err != nil {
 | 
				
			||||||
 | 
								log.Print(err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.conn = nil
 | 
				
			||||||
 | 
							l.wgClose.Done()
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						l.wgClose.Wait()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Returns the next available messageID
 | 
				
			||||||
 | 
					func (l *Conn) nextMessageID() uint64 {
 | 
				
			||||||
 | 
						if l.chanMessageID != nil {
 | 
				
			||||||
 | 
							if messageID, ok := <-l.chanMessageID; ok {
 | 
				
			||||||
 | 
								return messageID
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StartTLS sends the command to start a TLS session and then creates a new TLS Client
 | 
				
			||||||
 | 
					func (l *Conn) StartTLS(config *tls.Config) error {
 | 
				
			||||||
 | 
						messageID := l.nextMessageID()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l.isTLS {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, errors.New("ldap: already encrypted"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
 | 
				
			||||||
 | 
						request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationExtendedRequest, nil, "Start TLS")
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, 0, "1.3.6.1.4.1.1466.20037", "TLS Extended Command"))
 | 
				
			||||||
 | 
						packet.AppendChild(request)
 | 
				
			||||||
 | 
						l.Debug.PrintPacket(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := l.conn.Write(packet.Bytes())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet, err = ber.ReadPacket(l.conn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l.Debug {
 | 
				
			||||||
 | 
							if err := addLDAPDescriptions(packet); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ber.PrintPacket(packet)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if packet.Children[1].Children[0].Value.(uint64) == 0 {
 | 
				
			||||||
 | 
							conn := tls.Client(l.conn, config)
 | 
				
			||||||
 | 
							l.isTLS = true
 | 
				
			||||||
 | 
							l.conn = conn
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) sendMessage(packet *ber.Packet) (chan *ber.Packet, error) {
 | 
				
			||||||
 | 
						if l.isClosing {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorNetwork, errors.New("ldap: connection closed"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						out := make(chan *ber.Packet)
 | 
				
			||||||
 | 
						message := &messagePacket{
 | 
				
			||||||
 | 
							Op:        MessageRequest,
 | 
				
			||||||
 | 
							MessageID: packet.Children[0].Value.(uint64),
 | 
				
			||||||
 | 
							Packet:    packet,
 | 
				
			||||||
 | 
							Channel:   out,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.sendProcessMessage(message)
 | 
				
			||||||
 | 
						return out, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) finishMessage(messageID uint64) {
 | 
				
			||||||
 | 
						if l.isClosing {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						message := &messagePacket{
 | 
				
			||||||
 | 
							Op:        MessageFinish,
 | 
				
			||||||
 | 
							MessageID: messageID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.sendProcessMessage(message)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) sendProcessMessage(message *messagePacket) bool {
 | 
				
			||||||
 | 
						if l.isClosing {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.wgSender.Add(1)
 | 
				
			||||||
 | 
						l.chanMessage <- message
 | 
				
			||||||
 | 
						l.wgSender.Done()
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) processMessages() {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							for messageID, channel := range l.chanResults {
 | 
				
			||||||
 | 
								l.Debug.Printf("Closing channel for MessageID %d", messageID)
 | 
				
			||||||
 | 
								close(channel)
 | 
				
			||||||
 | 
								delete(l.chanResults, messageID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							close(l.chanMessageID)
 | 
				
			||||||
 | 
							l.chanConfirm <- true
 | 
				
			||||||
 | 
							close(l.chanConfirm)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var messageID uint64 = 1
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case l.chanMessageID <- messageID:
 | 
				
			||||||
 | 
								messageID++
 | 
				
			||||||
 | 
							case messagePacket, ok := <-l.chanMessage:
 | 
				
			||||||
 | 
								if !ok {
 | 
				
			||||||
 | 
									l.Debug.Printf("Shutting down - message channel is closed")
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								switch messagePacket.Op {
 | 
				
			||||||
 | 
								case MessageQuit:
 | 
				
			||||||
 | 
									l.Debug.Printf("Shutting down - quit message received")
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								case MessageRequest:
 | 
				
			||||||
 | 
									// Add to message list and write to network
 | 
				
			||||||
 | 
									l.Debug.Printf("Sending message %d", messagePacket.MessageID)
 | 
				
			||||||
 | 
									l.chanResults[messagePacket.MessageID] = messagePacket.Channel
 | 
				
			||||||
 | 
									// go routine
 | 
				
			||||||
 | 
									buf := messagePacket.Packet.Bytes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									_, err := l.conn.Write(buf)
 | 
				
			||||||
 | 
									if err != nil {
 | 
				
			||||||
 | 
										l.Debug.Printf("Error Sending Message: %s", err.Error())
 | 
				
			||||||
 | 
										break
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case MessageResponse:
 | 
				
			||||||
 | 
									l.Debug.Printf("Receiving message %d", messagePacket.MessageID)
 | 
				
			||||||
 | 
									if chanResult, ok := l.chanResults[messagePacket.MessageID]; ok {
 | 
				
			||||||
 | 
										chanResult <- messagePacket.Packet
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										log.Printf("Received unexpected message %d", messagePacket.MessageID)
 | 
				
			||||||
 | 
										ber.PrintPacket(messagePacket.Packet)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								case MessageFinish:
 | 
				
			||||||
 | 
									// Remove from message list
 | 
				
			||||||
 | 
									l.Debug.Printf("Finished message %d", messagePacket.MessageID)
 | 
				
			||||||
 | 
									close(l.chanResults[messagePacket.MessageID])
 | 
				
			||||||
 | 
									delete(l.chanResults, messagePacket.MessageID)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) reader() {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							l.Close()
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							packet, err := ber.ReadPacket(l.conn)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								l.Debug.Printf("reader: %s", err.Error())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							addLDAPDescriptions(packet)
 | 
				
			||||||
 | 
							message := &messagePacket{
 | 
				
			||||||
 | 
								Op:        MessageResponse,
 | 
				
			||||||
 | 
								MessageID: packet.Children[0].Value.(uint64),
 | 
				
			||||||
 | 
								Packet:    packet,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !l.sendProcessMessage(message) {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										157
									
								
								modules/ldap/control.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								modules/ldap/control.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ControlTypePaging = "1.2.840.113556.1.4.319"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ControlTypeMap = map[string]string{
 | 
				
			||||||
 | 
						ControlTypePaging: "Paging",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Control interface {
 | 
				
			||||||
 | 
						GetControlType() string
 | 
				
			||||||
 | 
						Encode() *ber.Packet
 | 
				
			||||||
 | 
						String() string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ControlString struct {
 | 
				
			||||||
 | 
						ControlType  string
 | 
				
			||||||
 | 
						Criticality  bool
 | 
				
			||||||
 | 
						ControlValue string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlString) GetControlType() string {
 | 
				
			||||||
 | 
						return c.ControlType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlString) Encode() *ber.Packet {
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlType, "Control Type ("+ControlTypeMap[c.ControlType]+")"))
 | 
				
			||||||
 | 
						if c.Criticality {
 | 
				
			||||||
 | 
							packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlValue, "Control Value"))
 | 
				
			||||||
 | 
						return packet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlString) String() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("Control Type: %s (%q)  Criticality: %t  Control Value: %s", ControlTypeMap[c.ControlType], c.ControlType, c.Criticality, c.ControlValue)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ControlPaging struct {
 | 
				
			||||||
 | 
						PagingSize uint32
 | 
				
			||||||
 | 
						Cookie     []byte
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlPaging) GetControlType() string {
 | 
				
			||||||
 | 
						return ControlTypePaging
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlPaging) Encode() *ber.Packet {
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypePaging, "Control Type ("+ControlTypeMap[ControlTypePaging]+")"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
 | 
				
			||||||
 | 
						seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
 | 
				
			||||||
 | 
						seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(c.PagingSize), "Paging Size"))
 | 
				
			||||||
 | 
						cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
 | 
				
			||||||
 | 
						cookie.Value = c.Cookie
 | 
				
			||||||
 | 
						cookie.Data.Write(c.Cookie)
 | 
				
			||||||
 | 
						seq.AppendChild(cookie)
 | 
				
			||||||
 | 
						p2.AppendChild(seq)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet.AppendChild(p2)
 | 
				
			||||||
 | 
						return packet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlPaging) String() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf(
 | 
				
			||||||
 | 
							"Control Type: %s (%q)  Criticality: %t  PagingSize: %d  Cookie: %q",
 | 
				
			||||||
 | 
							ControlTypeMap[ControlTypePaging],
 | 
				
			||||||
 | 
							ControlTypePaging,
 | 
				
			||||||
 | 
							false,
 | 
				
			||||||
 | 
							c.PagingSize,
 | 
				
			||||||
 | 
							c.Cookie)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *ControlPaging) SetCookie(cookie []byte) {
 | 
				
			||||||
 | 
						c.Cookie = cookie
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func FindControl(controls []Control, controlType string) Control {
 | 
				
			||||||
 | 
						for _, c := range controls {
 | 
				
			||||||
 | 
							if c.GetControlType() == controlType {
 | 
				
			||||||
 | 
								return c
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecodeControl(packet *ber.Packet) Control {
 | 
				
			||||||
 | 
						ControlType := packet.Children[0].Value.(string)
 | 
				
			||||||
 | 
						Criticality := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
 | 
				
			||||||
 | 
						value := packet.Children[1]
 | 
				
			||||||
 | 
						if len(packet.Children) == 3 {
 | 
				
			||||||
 | 
							value = packet.Children[2]
 | 
				
			||||||
 | 
							packet.Children[1].Description = "Criticality"
 | 
				
			||||||
 | 
							Criticality = packet.Children[1].Value.(bool)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value.Description = "Control Value"
 | 
				
			||||||
 | 
						switch ControlType {
 | 
				
			||||||
 | 
						case ControlTypePaging:
 | 
				
			||||||
 | 
							value.Description += " (Paging)"
 | 
				
			||||||
 | 
							c := new(ControlPaging)
 | 
				
			||||||
 | 
							if value.Value != nil {
 | 
				
			||||||
 | 
								valueChildren := ber.DecodePacket(value.Data.Bytes())
 | 
				
			||||||
 | 
								value.Data.Truncate(0)
 | 
				
			||||||
 | 
								value.Value = nil
 | 
				
			||||||
 | 
								value.AppendChild(valueChildren)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							value = value.Children[0]
 | 
				
			||||||
 | 
							value.Description = "Search Control Value"
 | 
				
			||||||
 | 
							value.Children[0].Description = "Paging Size"
 | 
				
			||||||
 | 
							value.Children[1].Description = "Cookie"
 | 
				
			||||||
 | 
							c.PagingSize = uint32(value.Children[0].Value.(uint64))
 | 
				
			||||||
 | 
							c.Cookie = value.Children[1].Data.Bytes()
 | 
				
			||||||
 | 
							value.Children[1].Value = c.Cookie
 | 
				
			||||||
 | 
							return c
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c := new(ControlString)
 | 
				
			||||||
 | 
						c.ControlType = ControlType
 | 
				
			||||||
 | 
						c.Criticality = Criticality
 | 
				
			||||||
 | 
						c.ControlValue = value.Value.(string)
 | 
				
			||||||
 | 
						return c
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
 | 
				
			||||||
 | 
						return &ControlString{
 | 
				
			||||||
 | 
							ControlType:  controlType,
 | 
				
			||||||
 | 
							Criticality:  criticality,
 | 
				
			||||||
 | 
							ControlValue: controlValue,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewControlPaging(pagingSize uint32) *ControlPaging {
 | 
				
			||||||
 | 
						return &ControlPaging{PagingSize: pagingSize}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func encodeControls(controls []Control) *ber.Packet {
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls")
 | 
				
			||||||
 | 
						for _, control := range controls {
 | 
				
			||||||
 | 
							packet.AppendChild(control.Encode())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return packet
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										24
									
								
								modules/ldap/debug.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								modules/ldap/debug.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// debbuging type
 | 
				
			||||||
 | 
					//     - has a Printf method to write the debug output
 | 
				
			||||||
 | 
					type debugging bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// write debug output
 | 
				
			||||||
 | 
					func (debug debugging) Printf(format string, args ...interface{}) {
 | 
				
			||||||
 | 
						if debug {
 | 
				
			||||||
 | 
							log.Printf(format, args...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (debug debugging) PrintPacket(packet *ber.Packet) {
 | 
				
			||||||
 | 
						if debug {
 | 
				
			||||||
 | 
							ber.PrintPacket(packet)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										63
									
								
								modules/ldap/examples/enterprise.ldif
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								modules/ldap/examples/enterprise.ldif
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					dn: dc=enterprise,dc=org
 | 
				
			||||||
 | 
					objectClass: dcObject
 | 
				
			||||||
 | 
					objectClass: organization
 | 
				
			||||||
 | 
					o: acme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=admin,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					objectClass: person
 | 
				
			||||||
 | 
					cn: admin
 | 
				
			||||||
 | 
					sn: admin
 | 
				
			||||||
 | 
					description: "LDAP Admin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					ou: crew
 | 
				
			||||||
 | 
					objectClass: organizationalUnit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=kirkj,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: kirkj
 | 
				
			||||||
 | 
					sn: Kirk
 | 
				
			||||||
 | 
					gn: James Tiberius
 | 
				
			||||||
 | 
					mail: james.kirk@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=spock,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: spock
 | 
				
			||||||
 | 
					sn: Spock
 | 
				
			||||||
 | 
					mail: spock@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=mccoyl,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: mccoyl
 | 
				
			||||||
 | 
					sn: McCoy
 | 
				
			||||||
 | 
					gn: Leonard
 | 
				
			||||||
 | 
					mail: leonard.mccoy@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=scottm,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: scottm
 | 
				
			||||||
 | 
					sn: Scott
 | 
				
			||||||
 | 
					gn: Montgomery
 | 
				
			||||||
 | 
					mail: Montgomery.scott@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=uhuran,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: uhuran
 | 
				
			||||||
 | 
					sn: Uhura
 | 
				
			||||||
 | 
					gn: Nyota
 | 
				
			||||||
 | 
					mail: nyota.uhura@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=suluh,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: suluh
 | 
				
			||||||
 | 
					sn: Sulu
 | 
				
			||||||
 | 
					gn: Hikaru
 | 
				
			||||||
 | 
					mail: hikaru.sulu@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					dn: cn=chekovp,ou=crew,dc=enterprise,dc=org
 | 
				
			||||||
 | 
					cn: chekovp
 | 
				
			||||||
 | 
					sn: Chekov
 | 
				
			||||||
 | 
					gn: pavel
 | 
				
			||||||
 | 
					mail: pavel.chekov@enterprise.org
 | 
				
			||||||
 | 
					objectClass: inetOrgPerson
 | 
				
			||||||
							
								
								
									
										89
									
								
								modules/ldap/examples/modify.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								modules/ldap/examples/modify.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/juju2013/goldap"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						LdapServer string = "localhost"
 | 
				
			||||||
 | 
						LdapPort   uint16 = 389
 | 
				
			||||||
 | 
						BaseDN     string = "dc=enterprise,dc=org"
 | 
				
			||||||
 | 
						BindDN     string = "cn=admin,dc=enterprise,dc=org"
 | 
				
			||||||
 | 
						BindPW     string = "enterprise"
 | 
				
			||||||
 | 
						Filter     string = "(cn=kirkj)"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func search(l *ldap.Conn, filter string, attributes []string) (*ldap.Entry, *ldap.Error) {
 | 
				
			||||||
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
 | 
							BaseDN,
 | 
				
			||||||
 | 
							ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
 | 
				
			||||||
 | 
							filter,
 | 
				
			||||||
 | 
							attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr, err := l.Search(search)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err)
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("Search: %s -> num of entries = %d\n", search.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
						if len(sr.Entries) == 0 {
 | 
				
			||||||
 | 
							return nil, ldap.NewError(ldap.ErrorDebugging, errors.New(fmt.Sprintf("no entries found for: %s", filter)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return sr.Entries[0], nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", LdapServer, LdapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
						// l.Debug = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.Bind(BindDN, BindPW)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("The Search for Kirk ... %s\n", Filter)
 | 
				
			||||||
 | 
						entry, err := search(l, Filter, []string{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal("could not get entry")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						entry.PrettyPrint(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("modify the mail address and add a description ... \n")
 | 
				
			||||||
 | 
						modify := ldap.NewModifyRequest(entry.DN)
 | 
				
			||||||
 | 
						modify.Add("description", []string{"Captain of the USS Enterprise"})
 | 
				
			||||||
 | 
						modify.Replace("mail", []string{"captain@enterprise.org"})
 | 
				
			||||||
 | 
						if err := l.Modify(modify); err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry, err = search(l, Filter, []string{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal("could not get entry")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						entry.PrettyPrint(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("reset the entry ... \n")
 | 
				
			||||||
 | 
						modify = ldap.NewModifyRequest(entry.DN)
 | 
				
			||||||
 | 
						modify.Delete("description", []string{})
 | 
				
			||||||
 | 
						modify.Replace("mail", []string{"james.kirk@enterprise.org"})
 | 
				
			||||||
 | 
						if err := l.Modify(modify); err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						entry, err = search(l, Filter, []string{})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal("could not get entry")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						entry.PrettyPrint(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										52
									
								
								modules/ldap/examples/search.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								modules/ldap/examples/search.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/juju2013/goldap"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ldapServer string   = "adserver"
 | 
				
			||||||
 | 
						ldapPort   uint16   = 3268
 | 
				
			||||||
 | 
						baseDN     string   = "dc=*,dc=*"
 | 
				
			||||||
 | 
						filter     string   = "(&(objectClass=user)(sAMAccountName=*)(memberOf=CN=*,OU=*,DC=*,DC=*))"
 | 
				
			||||||
 | 
						Attributes []string = []string{"memberof"}
 | 
				
			||||||
 | 
						user       string   = "*"
 | 
				
			||||||
 | 
						passwd     string   = "*"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
						// l.Debug = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = l.Bind(user, passwd)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Printf("ERROR: Cannot bind: %s\n", err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
 | 
							baseDN,
 | 
				
			||||||
 | 
							ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
 | 
				
			||||||
 | 
							filter,
 | 
				
			||||||
 | 
							Attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr, err := l.Search(search)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("Search: %s -> num of entries = %d\n", search.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
						sr.PrettyPrint(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								modules/ldap/examples/searchSSL.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								modules/ldap/examples/searchSSL.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/juju2013/goldap"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						LdapServer string   = "localhost"
 | 
				
			||||||
 | 
						LdapPort   uint16   = 636
 | 
				
			||||||
 | 
						BaseDN     string   = "dc=enterprise,dc=org"
 | 
				
			||||||
 | 
						Filter     string   = "(cn=kirkj)"
 | 
				
			||||||
 | 
						Attributes []string = []string{"mail"}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						l, err := ldap.DialSSL("tcp", fmt.Sprintf("%s:%d", LdapServer, LdapPort), nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.String())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
						// l.Debug = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
 | 
							BaseDN,
 | 
				
			||||||
 | 
							ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
 | 
				
			||||||
 | 
							Filter,
 | 
				
			||||||
 | 
							Attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr, err := l.Search(search)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.String())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("Search: %s -> num of entries = %d\n", search.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
						sr.PrettyPrint(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								modules/ldap/examples/searchTLS.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								modules/ldap/examples/searchTLS.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/juju2013/goldap"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						LdapServer string   = "localhost"
 | 
				
			||||||
 | 
						LdapPort   uint16   = 389
 | 
				
			||||||
 | 
						BaseDN     string   = "dc=enterprise,dc=org"
 | 
				
			||||||
 | 
						Filter     string   = "(cn=kirkj)"
 | 
				
			||||||
 | 
						Attributes []string = []string{"mail"}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						l, err := ldap.DialTLS("tcp", fmt.Sprintf("%s:%d", LdapServer, LdapPort), nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
						// l.Debug = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						search := ldap.NewSearchRequest(
 | 
				
			||||||
 | 
							BaseDN,
 | 
				
			||||||
 | 
							ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
 | 
				
			||||||
 | 
							Filter,
 | 
				
			||||||
 | 
							Attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr, err := l.Search(search)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("ERROR: %s\n", err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Printf("Search: %s -> num of entries = %d\n", search.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
						sr.PrettyPrint(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										67
									
								
								modules/ldap/examples/slapd.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								modules/ldap/examples/slapd.conf
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
				
			|||||||
 | 
					#
 | 
				
			||||||
 | 
					# See slapd.conf(5) for details on configuration options.
 | 
				
			||||||
 | 
					# This file should NOT be world readable.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					include		/private/etc/openldap/schema/core.schema
 | 
				
			||||||
 | 
					include 	/private/etc/openldap/schema/cosine.schema
 | 
				
			||||||
 | 
					include		/private/etc/openldap/schema/inetorgperson.schema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Define global ACLs to disable default read access.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Do not enable referrals until AFTER you have a working directory
 | 
				
			||||||
 | 
					# service AND an understanding of referrals.
 | 
				
			||||||
 | 
					#referral	ldap://root.openldap.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pidfile		/private/var/db/openldap/run/slapd.pid
 | 
				
			||||||
 | 
					argsfile	/private/var/db/openldap/run/slapd.args
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Load dynamic backend modules:
 | 
				
			||||||
 | 
					# modulepath	/usr/libexec/openldap
 | 
				
			||||||
 | 
					# moduleload	back_bdb.la
 | 
				
			||||||
 | 
					# moduleload	back_hdb.la
 | 
				
			||||||
 | 
					# moduleload	back_ldap.la
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sample security restrictions
 | 
				
			||||||
 | 
					#	Require integrity protection (prevent hijacking)
 | 
				
			||||||
 | 
					#	Require 112-bit (3DES or better) encryption for updates
 | 
				
			||||||
 | 
					#	Require 63-bit encryption for simple bind
 | 
				
			||||||
 | 
					# security ssf=1 update_ssf=112 simple_bind=64
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Sample access control policy:
 | 
				
			||||||
 | 
					#	Root DSE: allow anyone to read it
 | 
				
			||||||
 | 
					#	Subschema (sub)entry DSE: allow anyone to read it
 | 
				
			||||||
 | 
					#	Other DSEs:
 | 
				
			||||||
 | 
					#		Allow self write access
 | 
				
			||||||
 | 
					#		Allow authenticated users read access
 | 
				
			||||||
 | 
					#		Allow anonymous users to authenticate
 | 
				
			||||||
 | 
					#	Directives needed to implement policy:
 | 
				
			||||||
 | 
					# access to dn.base="" by * read
 | 
				
			||||||
 | 
					# access to dn.base="cn=Subschema" by * read
 | 
				
			||||||
 | 
					# access to *
 | 
				
			||||||
 | 
					#	by self write
 | 
				
			||||||
 | 
					#	by users read
 | 
				
			||||||
 | 
					#	by anonymous auth
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# if no access controls are present, the default policy
 | 
				
			||||||
 | 
					# allows anyone and everyone to read anything but restricts
 | 
				
			||||||
 | 
					# updates to rootdn.  (e.g., "access to * by * read")
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# rootdn can always read and write EVERYTHING!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#######################################################################
 | 
				
			||||||
 | 
					# BDB database definitions
 | 
				
			||||||
 | 
					#######################################################################
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					database	bdb
 | 
				
			||||||
 | 
					suffix		"dc=enterprise,dc=org"
 | 
				
			||||||
 | 
					rootdn		"cn=admin,dc=enterprise,dc=org"
 | 
				
			||||||
 | 
					# Cleartext passwords, especially for the rootdn, should
 | 
				
			||||||
 | 
					# be avoid.  See slappasswd(8) and slapd.conf(5) for details.
 | 
				
			||||||
 | 
					# Use of strong authentication encouraged.
 | 
				
			||||||
 | 
					rootpw		{SSHA}laO00HsgszhK1O0Z5qR0/i/US69Osfeu
 | 
				
			||||||
 | 
					# The database directory MUST exist prior to running slapd AND 
 | 
				
			||||||
 | 
					# should only be accessible by the slapd and slap tools.
 | 
				
			||||||
 | 
					# Mode 700 recommended.
 | 
				
			||||||
 | 
					directory	/private/var/db/openldap/openldap-data
 | 
				
			||||||
 | 
					# Indices to maintain
 | 
				
			||||||
 | 
					index	objectClass	eq
 | 
				
			||||||
							
								
								
									
										248
									
								
								modules/ldap/filter.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										248
									
								
								modules/ldap/filter.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,248 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						FilterAnd             = 0
 | 
				
			||||||
 | 
						FilterOr              = 1
 | 
				
			||||||
 | 
						FilterNot             = 2
 | 
				
			||||||
 | 
						FilterEqualityMatch   = 3
 | 
				
			||||||
 | 
						FilterSubstrings      = 4
 | 
				
			||||||
 | 
						FilterGreaterOrEqual  = 5
 | 
				
			||||||
 | 
						FilterLessOrEqual     = 6
 | 
				
			||||||
 | 
						FilterPresent         = 7
 | 
				
			||||||
 | 
						FilterApproxMatch     = 8
 | 
				
			||||||
 | 
						FilterExtensibleMatch = 9
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var FilterMap = map[uint64]string{
 | 
				
			||||||
 | 
						FilterAnd:             "And",
 | 
				
			||||||
 | 
						FilterOr:              "Or",
 | 
				
			||||||
 | 
						FilterNot:             "Not",
 | 
				
			||||||
 | 
						FilterEqualityMatch:   "Equality Match",
 | 
				
			||||||
 | 
						FilterSubstrings:      "Substrings",
 | 
				
			||||||
 | 
						FilterGreaterOrEqual:  "Greater Or Equal",
 | 
				
			||||||
 | 
						FilterLessOrEqual:     "Less Or Equal",
 | 
				
			||||||
 | 
						FilterPresent:         "Present",
 | 
				
			||||||
 | 
						FilterApproxMatch:     "Approx Match",
 | 
				
			||||||
 | 
						FilterExtensibleMatch: "Extensible Match",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						FilterSubstringsInitial = 0
 | 
				
			||||||
 | 
						FilterSubstringsAny     = 1
 | 
				
			||||||
 | 
						FilterSubstringsFinal   = 2
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var FilterSubstringsMap = map[uint64]string{
 | 
				
			||||||
 | 
						FilterSubstringsInitial: "Substrings Initial",
 | 
				
			||||||
 | 
						FilterSubstringsAny:     "Substrings Any",
 | 
				
			||||||
 | 
						FilterSubstringsFinal:   "Substrings Final",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func CompileFilter(filter string) (*ber.Packet, error) {
 | 
				
			||||||
 | 
						if len(filter) == 0 || filter[0] != '(' {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorFilterCompile, errors.New("ldap: filter does not start with an '('"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packet, pos, err := compileFilter(filter, 1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pos != len(filter) {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorFilterCompile, errors.New("ldap: finished compiling filter with extra at end: "+fmt.Sprint(filter[pos:])))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return packet, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DecompileFilter(packet *ber.Packet) (ret string, err error) {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if r := recover(); r != nil {
 | 
				
			||||||
 | 
								err = NewError(ErrorFilterDecompile, errors.New("ldap: error decompiling filter"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						ret = "("
 | 
				
			||||||
 | 
						err = nil
 | 
				
			||||||
 | 
						childStr := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch packet.Tag {
 | 
				
			||||||
 | 
						case FilterAnd:
 | 
				
			||||||
 | 
							ret += "&"
 | 
				
			||||||
 | 
							for _, child := range packet.Children {
 | 
				
			||||||
 | 
								childStr, err = DecompileFilter(child)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ret += childStr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case FilterOr:
 | 
				
			||||||
 | 
							ret += "|"
 | 
				
			||||||
 | 
							for _, child := range packet.Children {
 | 
				
			||||||
 | 
								childStr, err = DecompileFilter(child)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ret += childStr
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case FilterNot:
 | 
				
			||||||
 | 
							ret += "!"
 | 
				
			||||||
 | 
							childStr, err = DecompileFilter(packet.Children[0])
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ret += childStr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case FilterSubstrings:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += "="
 | 
				
			||||||
 | 
							switch packet.Children[1].Children[0].Tag {
 | 
				
			||||||
 | 
							case FilterSubstringsInitial:
 | 
				
			||||||
 | 
								ret += ber.DecodeString(packet.Children[1].Children[0].Data.Bytes()) + "*"
 | 
				
			||||||
 | 
							case FilterSubstringsAny:
 | 
				
			||||||
 | 
								ret += "*" + ber.DecodeString(packet.Children[1].Children[0].Data.Bytes()) + "*"
 | 
				
			||||||
 | 
							case FilterSubstringsFinal:
 | 
				
			||||||
 | 
								ret += "*" + ber.DecodeString(packet.Children[1].Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case FilterEqualityMatch:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += "="
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[1].Data.Bytes())
 | 
				
			||||||
 | 
						case FilterGreaterOrEqual:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += ">="
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[1].Data.Bytes())
 | 
				
			||||||
 | 
						case FilterLessOrEqual:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += "<="
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[1].Data.Bytes())
 | 
				
			||||||
 | 
						case FilterPresent:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += "=*"
 | 
				
			||||||
 | 
						case FilterApproxMatch:
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[0].Data.Bytes())
 | 
				
			||||||
 | 
							ret += "~="
 | 
				
			||||||
 | 
							ret += ber.DecodeString(packet.Children[1].Data.Bytes())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret += ")"
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func compileFilterSet(filter string, pos int, parent *ber.Packet) (int, error) {
 | 
				
			||||||
 | 
						for pos < len(filter) && filter[pos] == '(' {
 | 
				
			||||||
 | 
							child, newPos, err := compileFilter(filter, pos+1)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return pos, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pos = newPos
 | 
				
			||||||
 | 
							parent.AppendChild(child)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if pos == len(filter) {
 | 
				
			||||||
 | 
							return pos, NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pos + 1, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func compileFilter(filter string, pos int) (*ber.Packet, int, error) {
 | 
				
			||||||
 | 
						var packet *ber.Packet
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if r := recover(); r != nil {
 | 
				
			||||||
 | 
								err = NewError(ErrorFilterCompile, errors.New("ldap: error compiling filter"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newPos := pos
 | 
				
			||||||
 | 
						switch filter[pos] {
 | 
				
			||||||
 | 
						case '(':
 | 
				
			||||||
 | 
							packet, newPos, err = compileFilter(filter, pos+1)
 | 
				
			||||||
 | 
							newPos++
 | 
				
			||||||
 | 
							return packet, newPos, err
 | 
				
			||||||
 | 
						case '&':
 | 
				
			||||||
 | 
							packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterAnd, nil, FilterMap[FilterAnd])
 | 
				
			||||||
 | 
							newPos, err = compileFilterSet(filter, pos+1, packet)
 | 
				
			||||||
 | 
							return packet, newPos, err
 | 
				
			||||||
 | 
						case '|':
 | 
				
			||||||
 | 
							packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterOr, nil, FilterMap[FilterOr])
 | 
				
			||||||
 | 
							newPos, err = compileFilterSet(filter, pos+1, packet)
 | 
				
			||||||
 | 
							return packet, newPos, err
 | 
				
			||||||
 | 
						case '!':
 | 
				
			||||||
 | 
							packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterNot, nil, FilterMap[FilterNot])
 | 
				
			||||||
 | 
							var child *ber.Packet
 | 
				
			||||||
 | 
							child, newPos, err = compileFilter(filter, pos+1)
 | 
				
			||||||
 | 
							packet.AppendChild(child)
 | 
				
			||||||
 | 
							return packet, newPos, err
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							attribute := ""
 | 
				
			||||||
 | 
							condition := ""
 | 
				
			||||||
 | 
							for newPos < len(filter) && filter[newPos] != ')' {
 | 
				
			||||||
 | 
								switch {
 | 
				
			||||||
 | 
								case packet != nil:
 | 
				
			||||||
 | 
									condition += fmt.Sprintf("%c", filter[newPos])
 | 
				
			||||||
 | 
								case filter[newPos] == '=':
 | 
				
			||||||
 | 
									packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterEqualityMatch, nil, FilterMap[FilterEqualityMatch])
 | 
				
			||||||
 | 
								case filter[newPos] == '>' && filter[newPos+1] == '=':
 | 
				
			||||||
 | 
									packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterGreaterOrEqual, nil, FilterMap[FilterGreaterOrEqual])
 | 
				
			||||||
 | 
									newPos++
 | 
				
			||||||
 | 
								case filter[newPos] == '<' && filter[newPos+1] == '=':
 | 
				
			||||||
 | 
									packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterLessOrEqual, nil, FilterMap[FilterLessOrEqual])
 | 
				
			||||||
 | 
									newPos++
 | 
				
			||||||
 | 
								case filter[newPos] == '~' && filter[newPos+1] == '=':
 | 
				
			||||||
 | 
									packet = ber.Encode(ber.ClassContext, ber.TypeConstructed, FilterApproxMatch, nil, FilterMap[FilterLessOrEqual])
 | 
				
			||||||
 | 
									newPos++
 | 
				
			||||||
 | 
								case packet == nil:
 | 
				
			||||||
 | 
									attribute += fmt.Sprintf("%c", filter[newPos])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								newPos++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if newPos == len(filter) {
 | 
				
			||||||
 | 
								err = NewError(ErrorFilterCompile, errors.New("ldap: unexpected end of filter"))
 | 
				
			||||||
 | 
								return packet, newPos, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if packet == nil {
 | 
				
			||||||
 | 
								err = NewError(ErrorFilterCompile, errors.New("ldap: error parsing filter"))
 | 
				
			||||||
 | 
								return packet, newPos, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
 | 
				
			||||||
 | 
							switch {
 | 
				
			||||||
 | 
							case packet.Tag == FilterEqualityMatch && condition == "*":
 | 
				
			||||||
 | 
								packet.Tag = FilterPresent
 | 
				
			||||||
 | 
								packet.Description = FilterMap[uint64(packet.Tag)]
 | 
				
			||||||
 | 
							case packet.Tag == FilterEqualityMatch && condition[0] == '*' && condition[len(condition)-1] == '*':
 | 
				
			||||||
 | 
								// Any
 | 
				
			||||||
 | 
								packet.Tag = FilterSubstrings
 | 
				
			||||||
 | 
								packet.Description = FilterMap[uint64(packet.Tag)]
 | 
				
			||||||
 | 
								seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Substrings")
 | 
				
			||||||
 | 
								seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterSubstringsAny, condition[1:len(condition)-1], "Any Substring"))
 | 
				
			||||||
 | 
								packet.AppendChild(seq)
 | 
				
			||||||
 | 
							case packet.Tag == FilterEqualityMatch && condition[0] == '*':
 | 
				
			||||||
 | 
								// Final
 | 
				
			||||||
 | 
								packet.Tag = FilterSubstrings
 | 
				
			||||||
 | 
								packet.Description = FilterMap[uint64(packet.Tag)]
 | 
				
			||||||
 | 
								seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Substrings")
 | 
				
			||||||
 | 
								seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterSubstringsFinal, condition[1:], "Final Substring"))
 | 
				
			||||||
 | 
								packet.AppendChild(seq)
 | 
				
			||||||
 | 
							case packet.Tag == FilterEqualityMatch && condition[len(condition)-1] == '*':
 | 
				
			||||||
 | 
								// Initial
 | 
				
			||||||
 | 
								packet.Tag = FilterSubstrings
 | 
				
			||||||
 | 
								packet.Description = FilterMap[uint64(packet.Tag)]
 | 
				
			||||||
 | 
								seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Substrings")
 | 
				
			||||||
 | 
								seq.AppendChild(ber.NewString(ber.ClassContext, ber.TypePrimitive, FilterSubstringsInitial, condition[:len(condition)-1], "Initial Substring"))
 | 
				
			||||||
 | 
								packet.AppendChild(seq)
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, condition, "Condition"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							newPos++
 | 
				
			||||||
 | 
							return packet, newPos, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										78
									
								
								modules/ldap/filter_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								modules/ldap/filter_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
				
			|||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/johnweldon/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type compileTest struct {
 | 
				
			||||||
 | 
						filterStr  string
 | 
				
			||||||
 | 
						filterType int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var testFilters = []compileTest{
 | 
				
			||||||
 | 
						compileTest{filterStr: "(&(sn=Miller)(givenName=Bob))", filterType: FilterAnd},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(|(sn=Miller)(givenName=Bob))", filterType: FilterOr},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(!(sn=Miller))", filterType: FilterNot},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn=Miller)", filterType: FilterEqualityMatch},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn=Mill*)", filterType: FilterSubstrings},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn=*Mill)", filterType: FilterSubstrings},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn=*Mill*)", filterType: FilterSubstrings},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn>=Miller)", filterType: FilterGreaterOrEqual},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn<=Miller)", filterType: FilterLessOrEqual},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn=*)", filterType: FilterPresent},
 | 
				
			||||||
 | 
						compileTest{filterStr: "(sn~=Miller)", filterType: FilterApproxMatch},
 | 
				
			||||||
 | 
						// compileTest{ filterStr: "()", filterType: FilterExtensibleMatch },
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestFilter(t *testing.T) {
 | 
				
			||||||
 | 
						// Test Compiler and Decompiler
 | 
				
			||||||
 | 
						for _, i := range testFilters {
 | 
				
			||||||
 | 
							filter, err := CompileFilter(i.filterStr)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
 | 
				
			||||||
 | 
							} else if filter.Tag != uint8(i.filterType) {
 | 
				
			||||||
 | 
								t.Errorf("%q Expected %q got %q", i.filterStr, FilterMap[uint64(i.filterType)], FilterMap[uint64(filter.Tag)])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								o, err := DecompileFilter(filter)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									t.Errorf("Problem compiling %s - %s", i.filterStr, err.Error())
 | 
				
			||||||
 | 
								} else if i.filterStr != o {
 | 
				
			||||||
 | 
									t.Errorf("%q expected, got %q", i.filterStr, o)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkFilterCompile(b *testing.B) {
 | 
				
			||||||
 | 
						b.StopTimer()
 | 
				
			||||||
 | 
						filters := make([]string, len(testFilters))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test Compiler and Decompiler
 | 
				
			||||||
 | 
						for idx, i := range testFilters {
 | 
				
			||||||
 | 
							filters[idx] = i.filterStr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						maxIdx := len(filters)
 | 
				
			||||||
 | 
						b.StartTimer()
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							CompileFilter(filters[i%maxIdx])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func BenchmarkFilterDecompile(b *testing.B) {
 | 
				
			||||||
 | 
						b.StopTimer()
 | 
				
			||||||
 | 
						filters := make([]*ber.Packet, len(testFilters))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test Compiler and Decompiler
 | 
				
			||||||
 | 
						for idx, i := range testFilters {
 | 
				
			||||||
 | 
							filters[idx], _ = CompileFilter(i.filterStr)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						maxIdx := len(filters)
 | 
				
			||||||
 | 
						b.StartTimer()
 | 
				
			||||||
 | 
						for i := 0; i < b.N; i++ {
 | 
				
			||||||
 | 
							DecompileFilter(filters[i%maxIdx])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										302
									
								
								modules/ldap/ldap.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										302
									
								
								modules/ldap/ldap.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,302 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LDAP Application Codes
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ApplicationBindRequest           = 0
 | 
				
			||||||
 | 
						ApplicationBindResponse          = 1
 | 
				
			||||||
 | 
						ApplicationUnbindRequest         = 2
 | 
				
			||||||
 | 
						ApplicationSearchRequest         = 3
 | 
				
			||||||
 | 
						ApplicationSearchResultEntry     = 4
 | 
				
			||||||
 | 
						ApplicationSearchResultDone      = 5
 | 
				
			||||||
 | 
						ApplicationModifyRequest         = 6
 | 
				
			||||||
 | 
						ApplicationModifyResponse        = 7
 | 
				
			||||||
 | 
						ApplicationAddRequest            = 8
 | 
				
			||||||
 | 
						ApplicationAddResponse           = 9
 | 
				
			||||||
 | 
						ApplicationDelRequest            = 10
 | 
				
			||||||
 | 
						ApplicationDelResponse           = 11
 | 
				
			||||||
 | 
						ApplicationModifyDNRequest       = 12
 | 
				
			||||||
 | 
						ApplicationModifyDNResponse      = 13
 | 
				
			||||||
 | 
						ApplicationCompareRequest        = 14
 | 
				
			||||||
 | 
						ApplicationCompareResponse       = 15
 | 
				
			||||||
 | 
						ApplicationAbandonRequest        = 16
 | 
				
			||||||
 | 
						ApplicationSearchResultReference = 19
 | 
				
			||||||
 | 
						ApplicationExtendedRequest       = 23
 | 
				
			||||||
 | 
						ApplicationExtendedResponse      = 24
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ApplicationMap = map[uint8]string{
 | 
				
			||||||
 | 
						ApplicationBindRequest:           "Bind Request",
 | 
				
			||||||
 | 
						ApplicationBindResponse:          "Bind Response",
 | 
				
			||||||
 | 
						ApplicationUnbindRequest:         "Unbind Request",
 | 
				
			||||||
 | 
						ApplicationSearchRequest:         "Search Request",
 | 
				
			||||||
 | 
						ApplicationSearchResultEntry:     "Search Result Entry",
 | 
				
			||||||
 | 
						ApplicationSearchResultDone:      "Search Result Done",
 | 
				
			||||||
 | 
						ApplicationModifyRequest:         "Modify Request",
 | 
				
			||||||
 | 
						ApplicationModifyResponse:        "Modify Response",
 | 
				
			||||||
 | 
						ApplicationAddRequest:            "Add Request",
 | 
				
			||||||
 | 
						ApplicationAddResponse:           "Add Response",
 | 
				
			||||||
 | 
						ApplicationDelRequest:            "Del Request",
 | 
				
			||||||
 | 
						ApplicationDelResponse:           "Del Response",
 | 
				
			||||||
 | 
						ApplicationModifyDNRequest:       "Modify DN Request",
 | 
				
			||||||
 | 
						ApplicationModifyDNResponse:      "Modify DN Response",
 | 
				
			||||||
 | 
						ApplicationCompareRequest:        "Compare Request",
 | 
				
			||||||
 | 
						ApplicationCompareResponse:       "Compare Response",
 | 
				
			||||||
 | 
						ApplicationAbandonRequest:        "Abandon Request",
 | 
				
			||||||
 | 
						ApplicationSearchResultReference: "Search Result Reference",
 | 
				
			||||||
 | 
						ApplicationExtendedRequest:       "Extended Request",
 | 
				
			||||||
 | 
						ApplicationExtendedResponse:      "Extended Response",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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
 | 
				
			||||||
 | 
						LDAPResultAliasDereferencingProblem    = 36
 | 
				
			||||||
 | 
						LDAPResultInappropriateAuthentication  = 48
 | 
				
			||||||
 | 
						LDAPResultInvalidCredentials           = 49
 | 
				
			||||||
 | 
						LDAPResultInsufficientAccessRights     = 50
 | 
				
			||||||
 | 
						LDAPResultBusy                         = 51
 | 
				
			||||||
 | 
						LDAPResultUnavailable                  = 52
 | 
				
			||||||
 | 
						LDAPResultUnwillingToPerform           = 53
 | 
				
			||||||
 | 
						LDAPResultLoopDetect                   = 54
 | 
				
			||||||
 | 
						LDAPResultNamingViolation              = 64
 | 
				
			||||||
 | 
						LDAPResultObjectClassViolation         = 65
 | 
				
			||||||
 | 
						LDAPResultNotAllowedOnNonLeaf          = 66
 | 
				
			||||||
 | 
						LDAPResultNotAllowedOnRDN              = 67
 | 
				
			||||||
 | 
						LDAPResultEntryAlreadyExists           = 68
 | 
				
			||||||
 | 
						LDAPResultObjectClassModsProhibited    = 69
 | 
				
			||||||
 | 
						LDAPResultAffectsMultipleDSAs          = 71
 | 
				
			||||||
 | 
						LDAPResultOther                        = 80
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ErrorNetwork         = 200
 | 
				
			||||||
 | 
						ErrorFilterCompile   = 201
 | 
				
			||||||
 | 
						ErrorFilterDecompile = 202
 | 
				
			||||||
 | 
						ErrorDebugging       = 203
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var LDAPResultCodeMap = map[uint8]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",
 | 
				
			||||||
 | 
						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",
 | 
				
			||||||
 | 
						LDAPResultNamingViolation:              "Naming Violation",
 | 
				
			||||||
 | 
						LDAPResultObjectClassViolation:         "Object Class Violation",
 | 
				
			||||||
 | 
						LDAPResultNotAllowedOnNonLeaf:          "Not Allowed On Non Leaf",
 | 
				
			||||||
 | 
						LDAPResultNotAllowedOnRDN:              "Not Allowed On RDN",
 | 
				
			||||||
 | 
						LDAPResultEntryAlreadyExists:           "Entry Already Exists",
 | 
				
			||||||
 | 
						LDAPResultObjectClassModsProhibited:    "Object Class Mods Prohibited",
 | 
				
			||||||
 | 
						LDAPResultAffectsMultipleDSAs:          "Affects Multiple DSAs",
 | 
				
			||||||
 | 
						LDAPResultOther:                        "Other",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Adds descriptions to an LDAP Response packet for debugging
 | 
				
			||||||
 | 
					func addLDAPDescriptions(packet *ber.Packet) (err error) {
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if r := recover(); r != nil {
 | 
				
			||||||
 | 
								err = NewError(ErrorDebugging, errors.New("ldap: cannot process packet to add descriptions"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						packet.Description = "LDAP Response"
 | 
				
			||||||
 | 
						packet.Children[0].Description = "Message ID"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						application := packet.Children[1].Tag
 | 
				
			||||||
 | 
						packet.Children[1].Description = ApplicationMap[application]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch application {
 | 
				
			||||||
 | 
						case ApplicationBindRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationBindResponse:
 | 
				
			||||||
 | 
							addDefaultLDAPResponseDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationUnbindRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationSearchRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationSearchResultEntry:
 | 
				
			||||||
 | 
							packet.Children[1].Children[0].Description = "Object Name"
 | 
				
			||||||
 | 
							packet.Children[1].Children[1].Description = "Attributes"
 | 
				
			||||||
 | 
							for _, child := range packet.Children[1].Children[1].Children {
 | 
				
			||||||
 | 
								child.Description = "Attribute"
 | 
				
			||||||
 | 
								child.Children[0].Description = "Attribute Name"
 | 
				
			||||||
 | 
								child.Children[1].Description = "Attribute Values"
 | 
				
			||||||
 | 
								for _, grandchild := range child.Children[1].Children {
 | 
				
			||||||
 | 
									grandchild.Description = "Attribute Value"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(packet.Children) == 3 {
 | 
				
			||||||
 | 
								addControlDescriptions(packet.Children[2])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case ApplicationSearchResultDone:
 | 
				
			||||||
 | 
							addDefaultLDAPResponseDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationModifyRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationModifyResponse:
 | 
				
			||||||
 | 
						case ApplicationAddRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationAddResponse:
 | 
				
			||||||
 | 
						case ApplicationDelRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationDelResponse:
 | 
				
			||||||
 | 
						case ApplicationModifyDNRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationModifyDNResponse:
 | 
				
			||||||
 | 
						case ApplicationCompareRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationCompareResponse:
 | 
				
			||||||
 | 
						case ApplicationAbandonRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationSearchResultReference:
 | 
				
			||||||
 | 
						case ApplicationExtendedRequest:
 | 
				
			||||||
 | 
							addRequestDescriptions(packet)
 | 
				
			||||||
 | 
						case ApplicationExtendedResponse:
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addControlDescriptions(packet *ber.Packet) {
 | 
				
			||||||
 | 
						packet.Description = "Controls"
 | 
				
			||||||
 | 
						for _, child := range packet.Children {
 | 
				
			||||||
 | 
							child.Description = "Control"
 | 
				
			||||||
 | 
							child.Children[0].Description = "Control Type (" + ControlTypeMap[child.Children[0].Value.(string)] + ")"
 | 
				
			||||||
 | 
							value := child.Children[1]
 | 
				
			||||||
 | 
							if len(child.Children) == 3 {
 | 
				
			||||||
 | 
								child.Children[1].Description = "Criticality"
 | 
				
			||||||
 | 
								value = child.Children[2]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							value.Description = "Control Value"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch child.Children[0].Value.(string) {
 | 
				
			||||||
 | 
							case ControlTypePaging:
 | 
				
			||||||
 | 
								value.Description += " (Paging)"
 | 
				
			||||||
 | 
								if value.Value != nil {
 | 
				
			||||||
 | 
									valueChildren := ber.DecodePacket(value.Data.Bytes())
 | 
				
			||||||
 | 
									value.Data.Truncate(0)
 | 
				
			||||||
 | 
									value.Value = nil
 | 
				
			||||||
 | 
									valueChildren.Children[1].Value = valueChildren.Children[1].Data.Bytes()
 | 
				
			||||||
 | 
									value.AppendChild(valueChildren)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								value.Children[0].Description = "Real Search Control Value"
 | 
				
			||||||
 | 
								value.Children[0].Children[0].Description = "Paging Size"
 | 
				
			||||||
 | 
								value.Children[0].Children[1].Description = "Cookie"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addRequestDescriptions(packet *ber.Packet) {
 | 
				
			||||||
 | 
						packet.Description = "LDAP Request"
 | 
				
			||||||
 | 
						packet.Children[0].Description = "Message ID"
 | 
				
			||||||
 | 
						packet.Children[1].Description = ApplicationMap[packet.Children[1].Tag]
 | 
				
			||||||
 | 
						if len(packet.Children) == 3 {
 | 
				
			||||||
 | 
							addControlDescriptions(packet.Children[2])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func addDefaultLDAPResponseDescriptions(packet *ber.Packet) {
 | 
				
			||||||
 | 
						resultCode := packet.Children[1].Children[0].Value.(uint64)
 | 
				
			||||||
 | 
						packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[uint8(resultCode)] + ")"
 | 
				
			||||||
 | 
						packet.Children[1].Children[1].Description = "Matched DN"
 | 
				
			||||||
 | 
						packet.Children[1].Children[2].Description = "Error Message"
 | 
				
			||||||
 | 
						if len(packet.Children[1].Children) > 3 {
 | 
				
			||||||
 | 
							packet.Children[1].Children[3].Description = "Referral"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(packet.Children) == 3 {
 | 
				
			||||||
 | 
							addControlDescriptions(packet.Children[2])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DebugBinaryFile(fileName string) error {
 | 
				
			||||||
 | 
						file, err := ioutil.ReadFile(fileName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return NewError(ErrorDebugging, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ber.PrintBytes(file, "")
 | 
				
			||||||
 | 
						packet := ber.DecodePacket(file)
 | 
				
			||||||
 | 
						addLDAPDescriptions(packet)
 | 
				
			||||||
 | 
						ber.PrintPacket(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Error struct {
 | 
				
			||||||
 | 
						Err        error
 | 
				
			||||||
 | 
						ResultCode uint8
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Error) Error() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewError(resultCode uint8, err error) error {
 | 
				
			||||||
 | 
						return &Error{ResultCode: resultCode, Err: err}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getLDAPResultCode(packet *ber.Packet) (code uint8, description string) {
 | 
				
			||||||
 | 
						if len(packet.Children) >= 2 {
 | 
				
			||||||
 | 
							response := packet.Children[1]
 | 
				
			||||||
 | 
							if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) == 3 {
 | 
				
			||||||
 | 
								return uint8(response.Children[0].Value.(uint64)), response.Children[2].Value.(string)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ErrorNetwork, "Invalid packet format"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										123
									
								
								modules/ldap/ldap_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								modules/ldap/ldap_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
				
			|||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ldapServer = "ldap.itd.umich.edu"
 | 
				
			||||||
 | 
					var ldapPort = uint16(389)
 | 
				
			||||||
 | 
					var baseDN = "dc=umich,dc=edu"
 | 
				
			||||||
 | 
					var filter = []string{
 | 
				
			||||||
 | 
						"(cn=cis-fac)",
 | 
				
			||||||
 | 
						"(&(objectclass=rfc822mailgroup)(cn=*Computer*))",
 | 
				
			||||||
 | 
						"(&(objectclass=rfc822mailgroup)(cn=*Mathematics*))"}
 | 
				
			||||||
 | 
					var attributes = []string{
 | 
				
			||||||
 | 
						"cn",
 | 
				
			||||||
 | 
						"description"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConnect(t *testing.T) {
 | 
				
			||||||
 | 
						fmt.Printf("TestConnect: starting...\n")
 | 
				
			||||||
 | 
						l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
						fmt.Printf("TestConnect: finished...\n")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSearch(t *testing.T) {
 | 
				
			||||||
 | 
						fmt.Printf("TestSearch: starting...\n")
 | 
				
			||||||
 | 
						l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						searchRequest := NewSearchRequest(
 | 
				
			||||||
 | 
							baseDN,
 | 
				
			||||||
 | 
							ScopeWholeSubtree, DerefAlways, 0, 0, false,
 | 
				
			||||||
 | 
							filter[0],
 | 
				
			||||||
 | 
							attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sr, err := l.Search(searchRequest)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("TestSearch: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSearchWithPaging(t *testing.T) {
 | 
				
			||||||
 | 
						fmt.Printf("TestSearchWithPaging: starting...\n")
 | 
				
			||||||
 | 
						l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = l.Bind("", "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						searchRequest := NewSearchRequest(
 | 
				
			||||||
 | 
							baseDN,
 | 
				
			||||||
 | 
							ScopeWholeSubtree, DerefAlways, 0, 0, false,
 | 
				
			||||||
 | 
							filter[1],
 | 
				
			||||||
 | 
							attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
						sr, err := l.SearchWithPaging(searchRequest, 5)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("TestSearchWithPaging: %s -> num of entries = %d\n", searchRequest.Filter, len(sr.Entries))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func testMultiGoroutineSearch(t *testing.T, l *Conn, results chan *SearchResult, i int) {
 | 
				
			||||||
 | 
						searchRequest := NewSearchRequest(
 | 
				
			||||||
 | 
							baseDN,
 | 
				
			||||||
 | 
							ScopeWholeSubtree, DerefAlways, 0, 0, false,
 | 
				
			||||||
 | 
							filter[i],
 | 
				
			||||||
 | 
							attributes,
 | 
				
			||||||
 | 
							nil)
 | 
				
			||||||
 | 
						sr, err := l.Search(searchRequest)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							results <- nil
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						results <- sr
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestMultiGoroutineSearch(t *testing.T) {
 | 
				
			||||||
 | 
						fmt.Printf("TestMultiGoroutineSearch: starting...\n")
 | 
				
			||||||
 | 
						l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Errorf(err.Error())
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						results := make([]chan *SearchResult, len(filter))
 | 
				
			||||||
 | 
						for i := range filter {
 | 
				
			||||||
 | 
							results[i] = make(chan *SearchResult)
 | 
				
			||||||
 | 
							go testMultiGoroutineSearch(t, l, results[i], i)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for i := range filter {
 | 
				
			||||||
 | 
							sr := <-results[i]
 | 
				
			||||||
 | 
							if sr == nil {
 | 
				
			||||||
 | 
								t.Errorf("Did not receive results from goroutine for %q", filter[i])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								fmt.Printf("TestMultiGoroutineSearch(%d): %s -> num of entries = %d\n", i, filter[i], len(sr.Entries))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										156
									
								
								modules/ldap/modify.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								modules/ldap/modify.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,156 @@
 | 
				
			|||||||
 | 
					// Copyright 2014 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// File contains Modify functionality
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc4511
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// ModifyRequest ::= [APPLICATION 6] SEQUENCE {
 | 
				
			||||||
 | 
					//      object          LDAPDN,
 | 
				
			||||||
 | 
					//      changes         SEQUENCE OF change SEQUENCE {
 | 
				
			||||||
 | 
					//           operation       ENUMERATED {
 | 
				
			||||||
 | 
					//                add     (0),
 | 
				
			||||||
 | 
					//                delete  (1),
 | 
				
			||||||
 | 
					//                replace (2),
 | 
				
			||||||
 | 
					//                ...  },
 | 
				
			||||||
 | 
					//           modification    PartialAttribute } }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// PartialAttribute ::= SEQUENCE {
 | 
				
			||||||
 | 
					//      type       AttributeDescription,
 | 
				
			||||||
 | 
					//      vals       SET OF value AttributeValue }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// AttributeDescription ::= LDAPString
 | 
				
			||||||
 | 
					//                         -- Constrained to <attributedescription>
 | 
				
			||||||
 | 
					//                         -- [RFC4512]
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// AttributeValue ::= OCTET STRING
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						AddAttribute     = 0
 | 
				
			||||||
 | 
						DeleteAttribute  = 1
 | 
				
			||||||
 | 
						ReplaceAttribute = 2
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PartialAttribute struct {
 | 
				
			||||||
 | 
						attrType string
 | 
				
			||||||
 | 
						attrVals []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (p *PartialAttribute) encode() *ber.Packet {
 | 
				
			||||||
 | 
						seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "PartialAttribute")
 | 
				
			||||||
 | 
						seq.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, p.attrType, "Type"))
 | 
				
			||||||
 | 
						set := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSet, nil, "AttributeValue")
 | 
				
			||||||
 | 
						for _, value := range p.attrVals {
 | 
				
			||||||
 | 
							set.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, value, "Vals"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						seq.AppendChild(set)
 | 
				
			||||||
 | 
						return seq
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ModifyRequest struct {
 | 
				
			||||||
 | 
						dn                string
 | 
				
			||||||
 | 
						addAttributes     []PartialAttribute
 | 
				
			||||||
 | 
						deleteAttributes  []PartialAttribute
 | 
				
			||||||
 | 
						replaceAttributes []PartialAttribute
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ModifyRequest) Add(attrType string, attrVals []string) {
 | 
				
			||||||
 | 
						m.addAttributes = append(m.addAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ModifyRequest) Delete(attrType string, attrVals []string) {
 | 
				
			||||||
 | 
						m.deleteAttributes = append(m.deleteAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *ModifyRequest) Replace(attrType string, attrVals []string) {
 | 
				
			||||||
 | 
						m.replaceAttributes = append(m.replaceAttributes, PartialAttribute{attrType: attrType, attrVals: attrVals})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m ModifyRequest) encode() *ber.Packet {
 | 
				
			||||||
 | 
						request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationModifyRequest, nil, "Modify Request")
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, m.dn, "DN"))
 | 
				
			||||||
 | 
						changes := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Changes")
 | 
				
			||||||
 | 
						for _, attribute := range m.addAttributes {
 | 
				
			||||||
 | 
							change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
 | 
				
			||||||
 | 
							change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(AddAttribute), "Operation"))
 | 
				
			||||||
 | 
							change.AppendChild(attribute.encode())
 | 
				
			||||||
 | 
							changes.AppendChild(change)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, attribute := range m.deleteAttributes {
 | 
				
			||||||
 | 
							change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
 | 
				
			||||||
 | 
							change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(DeleteAttribute), "Operation"))
 | 
				
			||||||
 | 
							change.AppendChild(attribute.encode())
 | 
				
			||||||
 | 
							changes.AppendChild(change)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, attribute := range m.replaceAttributes {
 | 
				
			||||||
 | 
							change := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Change")
 | 
				
			||||||
 | 
							change.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(ReplaceAttribute), "Operation"))
 | 
				
			||||||
 | 
							change.AppendChild(attribute.encode())
 | 
				
			||||||
 | 
							changes.AppendChild(change)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						request.AppendChild(changes)
 | 
				
			||||||
 | 
						return request
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewModifyRequest(
 | 
				
			||||||
 | 
						dn string,
 | 
				
			||||||
 | 
					) *ModifyRequest {
 | 
				
			||||||
 | 
						return &ModifyRequest{
 | 
				
			||||||
 | 
							dn: dn,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) Modify(modifyRequest *ModifyRequest) error {
 | 
				
			||||||
 | 
						messageID := l.nextMessageID()
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
 | 
				
			||||||
 | 
						packet.AppendChild(modifyRequest.encode())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.Debug.PrintPacket(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channel, err := l.sendMessage(packet)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if channel == nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, errors.New("ldap: could not send message"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.finishMessage(messageID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.Debug.Printf("%d: waiting for response", messageID)
 | 
				
			||||||
 | 
						packet = <-channel
 | 
				
			||||||
 | 
						l.Debug.Printf("%d: got response %p", messageID, packet)
 | 
				
			||||||
 | 
						if packet == nil {
 | 
				
			||||||
 | 
							return NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if l.Debug {
 | 
				
			||||||
 | 
							if err := addLDAPDescriptions(packet); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ber.PrintPacket(packet)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if packet.Children[1].Tag == ApplicationModifyResponse {
 | 
				
			||||||
 | 
							resultCode, resultDescription := getLDAPResultCode(packet)
 | 
				
			||||||
 | 
							if resultCode != 0 {
 | 
				
			||||||
 | 
								return NewError(resultCode, errors.New(resultDescription))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.Printf("Unexpected Response: %d", packet.Children[1].Tag)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.Debug.Printf("%d: returning", messageID)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										350
									
								
								modules/ldap/search.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								modules/ldap/search.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,350 @@
 | 
				
			|||||||
 | 
					// Copyright 2011 The Go Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a BSD-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// File contains Search functionality
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// https://tools.ietf.org/html/rfc4511
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         SearchRequest ::= [APPLICATION 3] SEQUENCE {
 | 
				
			||||||
 | 
					//              baseObject      LDAPDN,
 | 
				
			||||||
 | 
					//              scope           ENUMERATED {
 | 
				
			||||||
 | 
					//                   baseObject              (0),
 | 
				
			||||||
 | 
					//                   singleLevel             (1),
 | 
				
			||||||
 | 
					//                   wholeSubtree            (2),
 | 
				
			||||||
 | 
					//                   ...  },
 | 
				
			||||||
 | 
					//              derefAliases    ENUMERATED {
 | 
				
			||||||
 | 
					//                   neverDerefAliases       (0),
 | 
				
			||||||
 | 
					//                   derefInSearching        (1),
 | 
				
			||||||
 | 
					//                   derefFindingBaseObj     (2),
 | 
				
			||||||
 | 
					//                   derefAlways             (3) },
 | 
				
			||||||
 | 
					//              sizeLimit       INTEGER (0 ..  maxInt),
 | 
				
			||||||
 | 
					//              timeLimit       INTEGER (0 ..  maxInt),
 | 
				
			||||||
 | 
					//              typesOnly       BOOLEAN,
 | 
				
			||||||
 | 
					//              filter          Filter,
 | 
				
			||||||
 | 
					//              attributes      AttributeSelection }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         AttributeSelection ::= SEQUENCE OF selector LDAPString
 | 
				
			||||||
 | 
					//                         -- The LDAPString is constrained to
 | 
				
			||||||
 | 
					//                         -- <attributeSelector> in Section 4.5.1.8
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         Filter ::= CHOICE {
 | 
				
			||||||
 | 
					//              and             [0] SET SIZE (1..MAX) OF filter Filter,
 | 
				
			||||||
 | 
					//              or              [1] SET SIZE (1..MAX) OF filter Filter,
 | 
				
			||||||
 | 
					//              not             [2] Filter,
 | 
				
			||||||
 | 
					//              equalityMatch   [3] AttributeValueAssertion,
 | 
				
			||||||
 | 
					//              substrings      [4] SubstringFilter,
 | 
				
			||||||
 | 
					//              greaterOrEqual  [5] AttributeValueAssertion,
 | 
				
			||||||
 | 
					//              lessOrEqual     [6] AttributeValueAssertion,
 | 
				
			||||||
 | 
					//              present         [7] AttributeDescription,
 | 
				
			||||||
 | 
					//              approxMatch     [8] AttributeValueAssertion,
 | 
				
			||||||
 | 
					//              extensibleMatch [9] MatchingRuleAssertion,
 | 
				
			||||||
 | 
					//              ...  }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         SubstringFilter ::= SEQUENCE {
 | 
				
			||||||
 | 
					//              type           AttributeDescription,
 | 
				
			||||||
 | 
					//              substrings     SEQUENCE SIZE (1..MAX) OF substring CHOICE {
 | 
				
			||||||
 | 
					//                   initial [0] AssertionValue,  -- can occur at most once
 | 
				
			||||||
 | 
					//                   any     [1] AssertionValue,
 | 
				
			||||||
 | 
					//                   final   [2] AssertionValue } -- can occur at most once
 | 
				
			||||||
 | 
					//              }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//         MatchingRuleAssertion ::= SEQUENCE {
 | 
				
			||||||
 | 
					//              matchingRule    [1] MatchingRuleId OPTIONAL,
 | 
				
			||||||
 | 
					//              type            [2] AttributeDescription OPTIONAL,
 | 
				
			||||||
 | 
					//              matchValue      [3] AssertionValue,
 | 
				
			||||||
 | 
					//              dnAttributes    [4] BOOLEAN DEFAULT FALSE }
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ldap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/asn1-ber"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ScopeBaseObject   = 0
 | 
				
			||||||
 | 
						ScopeSingleLevel  = 1
 | 
				
			||||||
 | 
						ScopeWholeSubtree = 2
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ScopeMap = map[int]string{
 | 
				
			||||||
 | 
						ScopeBaseObject:   "Base Object",
 | 
				
			||||||
 | 
						ScopeSingleLevel:  "Single Level",
 | 
				
			||||||
 | 
						ScopeWholeSubtree: "Whole Subtree",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						NeverDerefAliases   = 0
 | 
				
			||||||
 | 
						DerefInSearching    = 1
 | 
				
			||||||
 | 
						DerefFindingBaseObj = 2
 | 
				
			||||||
 | 
						DerefAlways         = 3
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var DerefMap = map[int]string{
 | 
				
			||||||
 | 
						NeverDerefAliases:   "NeverDerefAliases",
 | 
				
			||||||
 | 
						DerefInSearching:    "DerefInSearching",
 | 
				
			||||||
 | 
						DerefFindingBaseObj: "DerefFindingBaseObj",
 | 
				
			||||||
 | 
						DerefAlways:         "DerefAlways",
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Entry struct {
 | 
				
			||||||
 | 
						DN         string
 | 
				
			||||||
 | 
						Attributes []*EntryAttribute
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Entry) GetAttributeValues(attribute string) []string {
 | 
				
			||||||
 | 
						for _, attr := range e.Attributes {
 | 
				
			||||||
 | 
							if attr.Name == attribute {
 | 
				
			||||||
 | 
								return attr.Values
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return []string{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Entry) GetAttributeValue(attribute string) string {
 | 
				
			||||||
 | 
						values := e.GetAttributeValues(attribute)
 | 
				
			||||||
 | 
						if len(values) == 0 {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return values[0]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Entry) Print() {
 | 
				
			||||||
 | 
						fmt.Printf("DN: %s\n", e.DN)
 | 
				
			||||||
 | 
						for _, attr := range e.Attributes {
 | 
				
			||||||
 | 
							attr.Print()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *Entry) PrettyPrint(indent int) {
 | 
				
			||||||
 | 
						fmt.Printf("%sDN: %s\n", strings.Repeat(" ", indent), e.DN)
 | 
				
			||||||
 | 
						for _, attr := range e.Attributes {
 | 
				
			||||||
 | 
							attr.PrettyPrint(indent + 2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type EntryAttribute struct {
 | 
				
			||||||
 | 
						Name   string
 | 
				
			||||||
 | 
						Values []string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EntryAttribute) Print() {
 | 
				
			||||||
 | 
						fmt.Printf("%s: %s\n", e.Name, e.Values)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e *EntryAttribute) PrettyPrint(indent int) {
 | 
				
			||||||
 | 
						fmt.Printf("%s%s: %s\n", strings.Repeat(" ", indent), e.Name, e.Values)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchResult struct {
 | 
				
			||||||
 | 
						Entries   []*Entry
 | 
				
			||||||
 | 
						Referrals []string
 | 
				
			||||||
 | 
						Controls  []Control
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SearchResult) Print() {
 | 
				
			||||||
 | 
						for _, entry := range s.Entries {
 | 
				
			||||||
 | 
							entry.Print()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SearchResult) PrettyPrint(indent int) {
 | 
				
			||||||
 | 
						for _, entry := range s.Entries {
 | 
				
			||||||
 | 
							entry.PrettyPrint(indent)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchRequest struct {
 | 
				
			||||||
 | 
						BaseDN       string
 | 
				
			||||||
 | 
						Scope        int
 | 
				
			||||||
 | 
						DerefAliases int
 | 
				
			||||||
 | 
						SizeLimit    int
 | 
				
			||||||
 | 
						TimeLimit    int
 | 
				
			||||||
 | 
						TypesOnly    bool
 | 
				
			||||||
 | 
						Filter       string
 | 
				
			||||||
 | 
						Attributes   []string
 | 
				
			||||||
 | 
						Controls     []Control
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *SearchRequest) encode() (*ber.Packet, error) {
 | 
				
			||||||
 | 
						request := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationSearchRequest, nil, "Search Request")
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, s.BaseDN, "Base DN"))
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.Scope), "Scope"))
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, uint64(s.DerefAliases), "Deref Aliases"))
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.SizeLimit), "Size Limit"))
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(s.TimeLimit), "Time Limit"))
 | 
				
			||||||
 | 
						request.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, s.TypesOnly, "Types Only"))
 | 
				
			||||||
 | 
						// compile and encode filter
 | 
				
			||||||
 | 
						filterPacket, err := CompileFilter(s.Filter)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						request.AppendChild(filterPacket)
 | 
				
			||||||
 | 
						// encode attributes
 | 
				
			||||||
 | 
						attributesPacket := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Attributes")
 | 
				
			||||||
 | 
						for _, attribute := range s.Attributes {
 | 
				
			||||||
 | 
							attributesPacket.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, attribute, "Attribute"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						request.AppendChild(attributesPacket)
 | 
				
			||||||
 | 
						return request, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSearchRequest(
 | 
				
			||||||
 | 
						BaseDN string,
 | 
				
			||||||
 | 
						Scope, DerefAliases, SizeLimit, TimeLimit int,
 | 
				
			||||||
 | 
						TypesOnly bool,
 | 
				
			||||||
 | 
						Filter string,
 | 
				
			||||||
 | 
						Attributes []string,
 | 
				
			||||||
 | 
						Controls []Control,
 | 
				
			||||||
 | 
					) *SearchRequest {
 | 
				
			||||||
 | 
						return &SearchRequest{
 | 
				
			||||||
 | 
							BaseDN:       BaseDN,
 | 
				
			||||||
 | 
							Scope:        Scope,
 | 
				
			||||||
 | 
							DerefAliases: DerefAliases,
 | 
				
			||||||
 | 
							SizeLimit:    SizeLimit,
 | 
				
			||||||
 | 
							TimeLimit:    TimeLimit,
 | 
				
			||||||
 | 
							TypesOnly:    TypesOnly,
 | 
				
			||||||
 | 
							Filter:       Filter,
 | 
				
			||||||
 | 
							Attributes:   Attributes,
 | 
				
			||||||
 | 
							Controls:     Controls,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) SearchWithPaging(searchRequest *SearchRequest, pagingSize uint32) (*SearchResult, error) {
 | 
				
			||||||
 | 
						if searchRequest.Controls == nil {
 | 
				
			||||||
 | 
							searchRequest.Controls = make([]Control, 0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pagingControl := NewControlPaging(pagingSize)
 | 
				
			||||||
 | 
						searchRequest.Controls = append(searchRequest.Controls, pagingControl)
 | 
				
			||||||
 | 
						searchResult := new(SearchResult)
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							result, err := l.Search(searchRequest)
 | 
				
			||||||
 | 
							l.Debug.Printf("Looking for Paging Control...")
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return searchResult, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if result == nil {
 | 
				
			||||||
 | 
								return searchResult, NewError(ErrorNetwork, errors.New("ldap: packet not received"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, entry := range result.Entries {
 | 
				
			||||||
 | 
								searchResult.Entries = append(searchResult.Entries, entry)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, referral := range result.Referrals {
 | 
				
			||||||
 | 
								searchResult.Referrals = append(searchResult.Referrals, referral)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, control := range result.Controls {
 | 
				
			||||||
 | 
								searchResult.Controls = append(searchResult.Controls, control)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							l.Debug.Printf("Looking for Paging Control...")
 | 
				
			||||||
 | 
							pagingResult := FindControl(result.Controls, ControlTypePaging)
 | 
				
			||||||
 | 
							if pagingResult == nil {
 | 
				
			||||||
 | 
								pagingControl = nil
 | 
				
			||||||
 | 
								l.Debug.Printf("Could not find paging control.  Breaking...")
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							cookie := pagingResult.(*ControlPaging).Cookie
 | 
				
			||||||
 | 
							if len(cookie) == 0 {
 | 
				
			||||||
 | 
								pagingControl = nil
 | 
				
			||||||
 | 
								l.Debug.Printf("Could not find cookie.  Breaking...")
 | 
				
			||||||
 | 
								break
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pagingControl.SetCookie(cookie)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if pagingControl != nil {
 | 
				
			||||||
 | 
							l.Debug.Printf("Abandoning Paging...")
 | 
				
			||||||
 | 
							pagingControl.PagingSize = 0
 | 
				
			||||||
 | 
							l.Search(searchRequest)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return searchResult, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
 | 
				
			||||||
 | 
						messageID := l.nextMessageID()
 | 
				
			||||||
 | 
						packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "LDAP Request")
 | 
				
			||||||
 | 
						packet.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, messageID, "MessageID"))
 | 
				
			||||||
 | 
						// encode search request
 | 
				
			||||||
 | 
						encodedSearchRequest, err := searchRequest.encode()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						packet.AppendChild(encodedSearchRequest)
 | 
				
			||||||
 | 
						// encode search controls
 | 
				
			||||||
 | 
						if searchRequest.Controls != nil {
 | 
				
			||||||
 | 
							packet.AppendChild(encodeControls(searchRequest.Controls))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						l.Debug.PrintPacket(packet)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						channel, err := l.sendMessage(packet)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if channel == nil {
 | 
				
			||||||
 | 
							return nil, NewError(ErrorNetwork, errors.New("ldap: could not send message"))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer l.finishMessage(messageID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						result := &SearchResult{
 | 
				
			||||||
 | 
							Entries:   make([]*Entry, 0),
 | 
				
			||||||
 | 
							Referrals: make([]string, 0),
 | 
				
			||||||
 | 
							Controls:  make([]Control, 0)}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						foundSearchResultDone := false
 | 
				
			||||||
 | 
						for !foundSearchResultDone {
 | 
				
			||||||
 | 
							l.Debug.Printf("%d: waiting for response", messageID)
 | 
				
			||||||
 | 
							packet = <-channel
 | 
				
			||||||
 | 
							l.Debug.Printf("%d: got response %p", messageID, packet)
 | 
				
			||||||
 | 
							if packet == nil {
 | 
				
			||||||
 | 
								return nil, NewError(ErrorNetwork, errors.New("ldap: could not retrieve message"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if l.Debug {
 | 
				
			||||||
 | 
								if err := addLDAPDescriptions(packet); err != nil {
 | 
				
			||||||
 | 
									return nil, err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ber.PrintPacket(packet)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch packet.Children[1].Tag {
 | 
				
			||||||
 | 
							case 4:
 | 
				
			||||||
 | 
								entry := new(Entry)
 | 
				
			||||||
 | 
								entry.DN = packet.Children[1].Children[0].Value.(string)
 | 
				
			||||||
 | 
								for _, child := range packet.Children[1].Children[1].Children {
 | 
				
			||||||
 | 
									attr := new(EntryAttribute)
 | 
				
			||||||
 | 
									attr.Name = child.Children[0].Value.(string)
 | 
				
			||||||
 | 
									for _, value := range child.Children[1].Children {
 | 
				
			||||||
 | 
										attr.Values = append(attr.Values, value.Value.(string))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									entry.Attributes = append(entry.Attributes, attr)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								result.Entries = append(result.Entries, entry)
 | 
				
			||||||
 | 
							case 5:
 | 
				
			||||||
 | 
								resultCode, resultDescription := getLDAPResultCode(packet)
 | 
				
			||||||
 | 
								if resultCode != 0 {
 | 
				
			||||||
 | 
									return result, NewError(resultCode, errors.New(resultDescription))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if len(packet.Children) == 3 {
 | 
				
			||||||
 | 
									for _, child := range packet.Children[2].Children {
 | 
				
			||||||
 | 
										result.Controls = append(result.Controls, DecodeControl(child))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								foundSearchResultDone = true
 | 
				
			||||||
 | 
							case 19:
 | 
				
			||||||
 | 
								result.Referrals = append(result.Referrals, packet.Children[1].Children[0].Value.(string))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						l.Debug.Printf("%d: returning", messageID)
 | 
				
			||||||
 | 
						return result, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user