// 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. // This package provides LDAP client functions. package ldap import ( "github.com/mmitton/asn1-ber" "fmt" ) 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() (p *ber.Packet) { p = ber.Encode( ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control" ) p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, c.ControlType, "Control Type (" + ControlTypeMap[ c.ControlType ] + ")" ) ) if c.Criticality { p.AppendChild( ber.NewBoolean( ber.ClassUniversal, ber.TypePrimative, ber.TagBoolean, c.Criticality, "Criticality" ) ) } p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, c.ControlValue, "Control Value" ) ) return } func (c *ControlString) String() string { return fmt.Sprintf( "Control Type: %s (%q) Criticality: %s 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() (p *ber.Packet) { p = ber.Encode( ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control" ) p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, ControlTypePaging, "Control Type (" + ControlTypeMap[ ControlTypePaging ] + ")" ) ) p2 := ber.Encode( ber.ClassUniversal, ber.TypePrimative, 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.TypePrimative, ber.TagInteger, uint64(c.PagingSize), "Paging Size" ) ) cookie := ber.Encode( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, nil, "Cookie" ) cookie.Value = c.Cookie cookie.Data.Write( c.Cookie ) seq.AppendChild( cookie ) p2.AppendChild( seq ) p.AppendChild( p2 ) return } func (c *ControlPaging) String() string { return fmt.Sprintf( "Control Type: %s (%q) Criticality: %s 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( p *ber.Packet ) Control { ControlType := p.Children[ 0 ].Value.(string) Criticality := false p.Children[ 0 ].Description = "Control Type (" + ControlTypeMap[ ControlType ] + ")" value := p.Children[ 1 ] if len( p.Children ) == 3 { value = p.Children[ 2 ] p.Children[ 1 ].Description = "Criticality" Criticality = p.Children[ 1 ].Value.(bool) } value.Description = "Control Value" switch ControlType { case ControlTypePaging: value.Description += " (Paging)" c := new( ControlPaging ) if value.Value != nil { value_children := ber.DecodePacket( value.Data.Bytes() ) value.Data.Truncate( 0 ) value.Value = nil value.AppendChild( value_children ) } 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 { p := ber.Encode( ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls" ) for _, control := range Controls { p.AppendChild( control.Encode() ) } return p }