diff options
author | Unknwon <joe2010xtmf@163.com> | 2014-09-07 20:04:47 -0400 |
---|---|---|
committer | Unknwon <joe2010xtmf@163.com> | 2014-09-07 20:04:47 -0400 |
commit | 59a7c7c5a530cead1905c0c686869ea0f6a7949c (patch) | |
tree | 00e1e6a987b9fd032e24b2edd1603a0a711f3878 /modules/asn1-ber | |
parent | 25d6ae69d1cb392922b9d9dc0da1c17aef9a9db2 (diff) | |
download | gitea-59a7c7c5a530cead1905c0c686869ea0f6a7949c.tar.gz gitea-59a7c7c5a530cead1905c0c686869ea0f6a7949c.zip |
Remove ldap dep
Diffstat (limited to 'modules/asn1-ber')
-rw-r--r-- | modules/asn1-ber/LICENSE | 27 | ||||
-rw-r--r-- | modules/asn1-ber/Makefile | 11 | ||||
-rw-r--r-- | modules/asn1-ber/README | 14 | ||||
-rw-r--r-- | modules/asn1-ber/ber.go | 492 |
4 files changed, 544 insertions, 0 deletions
diff --git a/modules/asn1-ber/LICENSE b/modules/asn1-ber/LICENSE new file mode 100644 index 0000000000..7448756763 --- /dev/null +++ b/modules/asn1-ber/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/modules/asn1-ber/Makefile b/modules/asn1-ber/Makefile new file mode 100644 index 0000000000..acda29afb7 --- /dev/null +++ b/modules/asn1-ber/Makefile @@ -0,0 +1,11 @@ +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +include $(GOROOT)/src/Make.inc + +TARG=github.com/mmitton/asn1-ber +GOFILES=\ + ber.go\ + +include $(GOROOT)/src/Make.pkg diff --git a/modules/asn1-ber/README b/modules/asn1-ber/README new file mode 100644 index 0000000000..bb785a06fc --- /dev/null +++ b/modules/asn1-ber/README @@ -0,0 +1,14 @@ +ASN1 BER Encoding / Decoding Library for the GO programming language. + +Required Librarys: + None + +Working: + Very basic encoding / decoding needed for LDAP protocol + +Tests Implemented: + None + +TODO: + Fix all encoding / decoding to conform to ASN1 BER spec + Implement Tests / Benchmarks diff --git a/modules/asn1-ber/ber.go b/modules/asn1-ber/ber.go new file mode 100644 index 0000000000..3e99a273c6 --- /dev/null +++ b/modules/asn1-ber/ber.go @@ -0,0 +1,492 @@ +package ber + +import ( + "bytes" + "fmt" + "io" + "reflect" +) + +type Packet struct { + ClassType uint8 + TagType uint8 + Tag uint8 + Value interface{} + ByteValue []byte + Data *bytes.Buffer + Children []*Packet + Description string +} + +const ( + TagEOC = 0x00 + TagBoolean = 0x01 + TagInteger = 0x02 + TagBitString = 0x03 + TagOctetString = 0x04 + TagNULL = 0x05 + TagObjectIdentifier = 0x06 + TagObjectDescriptor = 0x07 + TagExternal = 0x08 + TagRealFloat = 0x09 + TagEnumerated = 0x0a + TagEmbeddedPDV = 0x0b + TagUTF8String = 0x0c + TagRelativeOID = 0x0d + TagSequence = 0x10 + TagSet = 0x11 + TagNumericString = 0x12 + TagPrintableString = 0x13 + TagT61String = 0x14 + TagVideotexString = 0x15 + TagIA5String = 0x16 + TagUTCTime = 0x17 + TagGeneralizedTime = 0x18 + TagGraphicString = 0x19 + TagVisibleString = 0x1a + TagGeneralString = 0x1b + TagUniversalString = 0x1c + TagCharacterString = 0x1d + TagBMPString = 0x1e + TagBitmask = 0x1f // xxx11111b +) + +var TagMap = map[uint8]string{ + TagEOC: "EOC (End-of-Content)", + TagBoolean: "Boolean", + TagInteger: "Integer", + TagBitString: "Bit String", + TagOctetString: "Octet String", + TagNULL: "NULL", + TagObjectIdentifier: "Object Identifier", + TagObjectDescriptor: "Object Descriptor", + TagExternal: "External", + TagRealFloat: "Real (float)", + TagEnumerated: "Enumerated", + TagEmbeddedPDV: "Embedded PDV", + TagUTF8String: "UTF8 String", + TagRelativeOID: "Relative-OID", + TagSequence: "Sequence and Sequence of", + TagSet: "Set and Set OF", + TagNumericString: "Numeric String", + TagPrintableString: "Printable String", + TagT61String: "T61 String", + TagVideotexString: "Videotex String", + TagIA5String: "IA5 String", + TagUTCTime: "UTC Time", + TagGeneralizedTime: "Generalized Time", + TagGraphicString: "Graphic String", + TagVisibleString: "Visible String", + TagGeneralString: "General String", + TagUniversalString: "Universal String", + TagCharacterString: "Character String", + TagBMPString: "BMP String", +} + +const ( + ClassUniversal = 0 // 00xxxxxxb + ClassApplication = 64 // 01xxxxxxb + ClassContext = 128 // 10xxxxxxb + ClassPrivate = 192 // 11xxxxxxb + ClassBitmask = 192 // 11xxxxxxb +) + +var ClassMap = map[uint8]string{ + ClassUniversal: "Universal", + ClassApplication: "Application", + ClassContext: "Context", + ClassPrivate: "Private", +} + +const ( + TypePrimitive = 0 // xx0xxxxxb + TypeConstructed = 32 // xx1xxxxxb + TypeBitmask = 32 // xx1xxxxxb +) + +var TypeMap = map[uint8]string{ + TypePrimitive: "Primative", + TypeConstructed: "Constructed", +} + +var Debug bool = false + +func PrintBytes(buf []byte, indent string) { + data_lines := make([]string, (len(buf)/30)+1) + num_lines := make([]string, (len(buf)/30)+1) + + for i, b := range buf { + data_lines[i/30] += fmt.Sprintf("%02x ", b) + num_lines[i/30] += fmt.Sprintf("%02d ", (i+1)%100) + } + + for i := 0; i < len(data_lines); i++ { + fmt.Print(indent + data_lines[i] + "\n") + fmt.Print(indent + num_lines[i] + "\n\n") + } +} + +func PrintPacket(p *Packet) { + printPacket(p, 0, false) +} + +func printPacket(p *Packet, indent int, printBytes bool) { + indent_str := "" + + for len(indent_str) != indent { + indent_str += " " + } + + class_str := ClassMap[p.ClassType] + + tagtype_str := TypeMap[p.TagType] + + tag_str := fmt.Sprintf("0x%02X", p.Tag) + + if p.ClassType == ClassUniversal { + tag_str = TagMap[p.Tag] + } + + value := fmt.Sprint(p.Value) + description := "" + + if p.Description != "" { + description = p.Description + ": " + } + + fmt.Printf("%s%s(%s, %s, %s) Len=%d %q\n", indent_str, description, class_str, tagtype_str, tag_str, p.Data.Len(), value) + + if printBytes { + PrintBytes(p.Bytes(), indent_str) + } + + for _, child := range p.Children { + printPacket(child, indent+1, printBytes) + } +} + +func resizeBuffer(in []byte, new_size uint64) (out []byte) { + out = make([]byte, new_size) + + copy(out, in) + + return +} + +func readBytes(reader io.Reader, buf []byte) error { + idx := 0 + buflen := len(buf) + + for idx < buflen { + n, err := reader.Read(buf[idx:]) + if err != nil { + return err + } + idx += n + } + + return nil +} + +func ReadPacket(reader io.Reader) (*Packet, error) { + buf := make([]byte, 2) + + err := readBytes(reader, buf) + + if err != nil { + return nil, err + } + + idx := uint64(2) + datalen := uint64(buf[1]) + + if Debug { + fmt.Printf("Read: datalen = %d len(buf) = %d ", datalen, len(buf)) + + for _, b := range buf { + fmt.Printf("%02X ", b) + } + + fmt.Printf("\n") + } + + if datalen&128 != 0 { + a := datalen - 128 + + idx += a + buf = resizeBuffer(buf, 2+a) + + err := readBytes(reader, buf[2:]) + + if err != nil { + return nil, err + } + + datalen = DecodeInteger(buf[2 : 2+a]) + + if Debug { + fmt.Printf("Read: a = %d idx = %d datalen = %d len(buf) = %d", a, idx, datalen, len(buf)) + + for _, b := range buf { + fmt.Printf("%02X ", b) + } + + fmt.Printf("\n") + } + } + + buf = resizeBuffer(buf, idx+datalen) + err = readBytes(reader, buf[idx:]) + + if err != nil { + return nil, err + } + + if Debug { + fmt.Printf("Read: len( buf ) = %d idx=%d datalen=%d idx+datalen=%d\n", len(buf), idx, datalen, idx+datalen) + + for _, b := range buf { + fmt.Printf("%02X ", b) + } + } + + p := DecodePacket(buf) + + return p, nil +} + +func DecodeString(data []byte) (ret string) { + for _, c := range data { + ret += fmt.Sprintf("%c", c) + } + + return +} + +func DecodeInteger(data []byte) (ret uint64) { + for _, i := range data { + ret = ret * 256 + ret = ret + uint64(i) + } + + return +} + +func EncodeInteger(val uint64) []byte { + var out bytes.Buffer + + found := false + + shift := uint(56) + + mask := uint64(0xFF00000000000000) + + for mask > 0 { + if !found && (val&mask != 0) { + found = true + } + + if found || (shift == 0) { + out.Write([]byte{byte((val & mask) >> shift)}) + } + + shift -= 8 + mask = mask >> 8 + } + + return out.Bytes() +} + +func DecodePacket(data []byte) *Packet { + p, _ := decodePacket(data) + + return p +} + +func decodePacket(data []byte) (*Packet, []byte) { + if Debug { + fmt.Printf("decodePacket: enter %d\n", len(data)) + } + + p := new(Packet) + + p.ClassType = data[0] & ClassBitmask + p.TagType = data[0] & TypeBitmask + p.Tag = data[0] & TagBitmask + + datalen := DecodeInteger(data[1:2]) + datapos := uint64(2) + + if datalen&128 != 0 { + datalen -= 128 + datapos += datalen + datalen = DecodeInteger(data[2 : 2+datalen]) + } + + p.Data = new(bytes.Buffer) + + p.Children = make([]*Packet, 0, 2) + + p.Value = nil + + value_data := data[datapos : datapos+datalen] + + if p.TagType == TypeConstructed { + for len(value_data) != 0 { + var child *Packet + + child, value_data = decodePacket(value_data) + p.AppendChild(child) + } + } else if p.ClassType == ClassUniversal { + p.Data.Write(data[datapos : datapos+datalen]) + p.ByteValue = value_data + + switch p.Tag { + case TagEOC: + case TagBoolean: + val := DecodeInteger(value_data) + + p.Value = val != 0 + case TagInteger: + p.Value = DecodeInteger(value_data) + case TagBitString: + case TagOctetString: + p.Value = DecodeString(value_data) + case TagNULL: + case TagObjectIdentifier: + case TagObjectDescriptor: + case TagExternal: + case TagRealFloat: + case TagEnumerated: + p.Value = DecodeInteger(value_data) + case TagEmbeddedPDV: + case TagUTF8String: + case TagRelativeOID: + case TagSequence: + case TagSet: + case TagNumericString: + case TagPrintableString: + p.Value = DecodeString(value_data) + case TagT61String: + case TagVideotexString: + case TagIA5String: + case TagUTCTime: + case TagGeneralizedTime: + case TagGraphicString: + case TagVisibleString: + case TagGeneralString: + case TagUniversalString: + case TagCharacterString: + case TagBMPString: + } + } else { + p.Data.Write(data[datapos : datapos+datalen]) + } + + return p, data[datapos+datalen:] +} + +func (p *Packet) DataLength() uint64 { + return uint64(p.Data.Len()) +} + +func (p *Packet) Bytes() []byte { + var out bytes.Buffer + + out.Write([]byte{p.ClassType | p.TagType | p.Tag}) + packet_length := EncodeInteger(p.DataLength()) + + if p.DataLength() > 127 || len(packet_length) > 1 { + out.Write([]byte{byte(len(packet_length) | 128)}) + out.Write(packet_length) + } else { + out.Write(packet_length) + } + + out.Write(p.Data.Bytes()) + + return out.Bytes() +} + +func (p *Packet) AppendChild(child *Packet) { + p.Data.Write(child.Bytes()) + + if len(p.Children) == cap(p.Children) { + newChildren := make([]*Packet, cap(p.Children)*2) + + copy(newChildren, p.Children) + p.Children = newChildren[0:len(p.Children)] + } + + p.Children = p.Children[0 : len(p.Children)+1] + p.Children[len(p.Children)-1] = child +} + +func Encode(ClassType, TagType, Tag uint8, Value interface{}, Description string) *Packet { + p := new(Packet) + + p.ClassType = ClassType + p.TagType = TagType + p.Tag = Tag + p.Data = new(bytes.Buffer) + + p.Children = make([]*Packet, 0, 2) + + p.Value = Value + p.Description = Description + + if Value != nil { + v := reflect.ValueOf(Value) + + if ClassType == ClassUniversal { + switch Tag { + case TagOctetString: + sv, ok := v.Interface().(string) + + if ok { + p.Data.Write([]byte(sv)) + } + } + } + } + + return p +} + +func NewSequence(Description string) *Packet { + return Encode(ClassUniversal, TypePrimitive, TagSequence, nil, Description) +} + +func NewBoolean(ClassType, TagType, Tag uint8, Value bool, Description string) *Packet { + intValue := 0 + + if Value { + intValue = 1 + } + + p := Encode(ClassType, TagType, Tag, nil, Description) + + p.Value = Value + p.Data.Write(EncodeInteger(uint64(intValue))) + + return p +} + +func NewInteger(ClassType, TagType, Tag uint8, Value uint64, Description string) *Packet { + p := Encode(ClassType, TagType, Tag, nil, Description) + + p.Value = Value + p.Data.Write(EncodeInteger(Value)) + + return p +} + +func NewString(ClassType, TagType, Tag uint8, Value, Description string) *Packet { + p := Encode(ClassType, TagType, Tag, nil, Description) + + p.Value = Value + p.Data.Write([]byte(Value)) + + return p +} |