mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Use better LDAP lib and should fix #1139
This commit is contained in:
		| @@ -37,8 +37,10 @@ github.com/Unknwon/paginater = commit:7748a72 | |||||||
| golang.org/x/net =  | golang.org/x/net =  | ||||||
| golang.org/x/text = | golang.org/x/text = | ||||||
| golang.org/x/crypto = | golang.org/x/crypto = | ||||||
|  | gopkg.in/asn1-ber.v1 =  | ||||||
| gopkg.in/gomail.v2 = commit:df6fc79 | gopkg.in/gomail.v2 = commit:df6fc79 | ||||||
| gopkg.in/ini.v1 = commit:2e44421 | gopkg.in/ini.v1 = commit:2e44421 | ||||||
|  | gopkg.in/ldap.v2 =  | ||||||
| gopkg.in/macaron.v1 = commit:1c6dd87 | gopkg.in/macaron.v1 = commit:1c6dd87 | ||||||
| gopkg.in/redis.v2 = commit:e617904962 | gopkg.in/redis.v2 = commit:e617904962 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,27 +0,0 @@ | |||||||
| 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. |  | ||||||
| @@ -1,11 +0,0 @@ | |||||||
| # 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 |  | ||||||
| @@ -1,14 +0,0 @@ | |||||||
| 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 |  | ||||||
| @@ -1,497 +0,0 @@ | |||||||
| package ber |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"bytes" |  | ||||||
| 	"fmt" |  | ||||||
| 	"io" |  | ||||||
| 	"reflect" |  | ||||||
| 	"errors" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
|  |  | ||||||
| 	if reader == nil { |  | ||||||
| 		return errors.New("reader was nil, aborting") |  | ||||||
| 	} |  | ||||||
| 	 |  | ||||||
| 	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 string(data) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| 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 |  | ||||||
| } |  | ||||||
| @@ -11,7 +11,8 @@ import ( | |||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/modules/ldap" | 	"gopkg.in/ldap.v2" | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/modules/log" | 	"github.com/gogits/gogs/modules/log" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,27 +0,0 @@ | |||||||
| 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. |  | ||||||
| @@ -1,33 +0,0 @@ | |||||||
| 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 |  | ||||||
| @@ -1,63 +0,0 @@ | |||||||
| 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 |  | ||||||
| @@ -1,89 +0,0 @@ | |||||||
| // 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/gogits/gogs/modules/ldap" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| } |  | ||||||
| @@ -1,52 +0,0 @@ | |||||||
| // 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/gogits/gogs/modules/ldap" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| } |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| // 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/gogits/gogs/modules/ldap" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| } |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| // 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/gogits/gogs/modules/ldap" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| 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) |  | ||||||
| } |  | ||||||
| @@ -1,67 +0,0 @@ | |||||||
| # |  | ||||||
| # 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 |  | ||||||
| @@ -1,55 +0,0 @@ | |||||||
| // 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 |  | ||||||
| } |  | ||||||
| @@ -1,275 +0,0 @@ | |||||||
| // 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 |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,157 +0,0 @@ | |||||||
| // 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 |  | ||||||
| } |  | ||||||
| @@ -1,24 +0,0 @@ | |||||||
| package ldap |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"log" |  | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/modules/asn1-ber" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| // debugging 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) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,248 +0,0 @@ | |||||||
| // 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 |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,78 +0,0 @@ | |||||||
| package ldap |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"testing" |  | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/modules/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]) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,302 +0,0 @@ | |||||||
| // 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" |  | ||||||
| } |  | ||||||
| @@ -1,123 +0,0 @@ | |||||||
| 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)) |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,156 +0,0 @@ | |||||||
| // 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 |  | ||||||
| } |  | ||||||
| @@ -1,350 +0,0 @@ | |||||||
| // 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 |  | ||||||
| } |  | ||||||
		Reference in New Issue
	
	Block a user