Skip to content

Commit d0a5ced

Browse files
authored
Merge pull request #83 from liggitt/control_test
Fix control round-tripping, parsing
2 parents 537128f + a343d59 commit d0a5ced

2 files changed

Lines changed: 109 additions & 13 deletions

File tree

control.go

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (c *ControlPaging) Encode() *ber.Packet {
8989

9090
p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
9191
seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
92-
seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(c.PagingSize), "Paging Size"))
92+
seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, int64(c.PagingSize), "Paging Size"))
9393
cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
9494
cookie.Value = c.Cookie
9595
cookie.Data.Write(c.Cookie)
@@ -254,19 +254,54 @@ func FindControl(controls []Control, controlType string) Control {
254254

255255
// DecodeControl returns a control read from the given packet, or nil if no recognized control can be made
256256
func DecodeControl(packet *ber.Packet) Control {
257-
ControlType := packet.Children[0].Value.(string)
258-
Criticality := false
257+
var (
258+
ControlType = ""
259+
Criticality = false
260+
value *ber.Packet
261+
)
262+
263+
switch len(packet.Children) {
264+
case 0:
265+
// at least one child is required for control type
266+
return nil
267+
268+
case 1:
269+
// just type, no criticality or value
270+
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
271+
ControlType = packet.Children[0].Value.(string)
272+
273+
case 2:
274+
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
275+
ControlType = packet.Children[0].Value.(string)
276+
277+
// Children[1] could be criticality or value (both are optional)
278+
// duck-type on whether this is a boolean
279+
if _, ok := packet.Children[1].Value.(bool); ok {
280+
packet.Children[1].Description = "Criticality"
281+
Criticality = packet.Children[1].Value.(bool)
282+
} else {
283+
packet.Children[1].Description = "Control Value"
284+
value = packet.Children[1]
285+
}
286+
287+
case 3:
288+
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
289+
ControlType = packet.Children[0].Value.(string)
259290

260-
packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
261-
value := packet.Children[1]
262-
if len(packet.Children) == 3 {
263-
value = packet.Children[2]
264291
packet.Children[1].Description = "Criticality"
265292
Criticality = packet.Children[1].Value.(bool)
293+
294+
packet.Children[2].Description = "Control Value"
295+
value = packet.Children[2]
296+
297+
default:
298+
// more than 3 children is invalid
299+
return nil
266300
}
267301

268-
value.Description = "Control Value"
269302
switch ControlType {
303+
case ControlTypeManageDsaIT:
304+
return NewControlManageDsaIT(Criticality)
270305
case ControlTypePaging:
271306
value.Description += " (Paging)"
272307
c := new(ControlPaging)
@@ -341,13 +376,16 @@ func DecodeControl(packet *ber.Packet) Control {
341376
c.Expire = expire
342377
value.Value = c.Expire
343378

379+
return c
380+
default:
381+
c := new(ControlString)
382+
c.ControlType = ControlType
383+
c.Criticality = Criticality
384+
if value != nil {
385+
c.ControlValue = value.Value.(string)
386+
}
344387
return c
345388
}
346-
c := new(ControlString)
347-
c.ControlType = ControlType
348-
c.Criticality = Criticality
349-
c.ControlValue = value.Value.(string)
350-
return c
351389
}
352390

353391
// NewControlString returns a generic control

control_test.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package ldap
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"reflect"
7+
"runtime"
8+
"testing"
9+
10+
"gopkg.in/asn1-ber.v1"
11+
)
12+
13+
func TestControlPaging(t *testing.T) {
14+
runControlTest(t, NewControlPaging(0))
15+
runControlTest(t, NewControlPaging(100))
16+
}
17+
18+
func TestControlManageDsaIT(t *testing.T) {
19+
runControlTest(t, NewControlManageDsaIT(true))
20+
runControlTest(t, NewControlManageDsaIT(false))
21+
}
22+
23+
func TestControlString(t *testing.T) {
24+
runControlTest(t, NewControlString("x", true, "y"))
25+
runControlTest(t, NewControlString("x", true, ""))
26+
runControlTest(t, NewControlString("x", false, "y"))
27+
runControlTest(t, NewControlString("x", false, ""))
28+
}
29+
30+
func runControlTest(t *testing.T, originalControl Control) {
31+
header := ""
32+
if callerpc, _, line, ok := runtime.Caller(1); ok {
33+
if caller := runtime.FuncForPC(callerpc); caller != nil {
34+
header = fmt.Sprintf("%s:%d: ", caller.Name(), line)
35+
}
36+
}
37+
38+
encodedPacket := originalControl.Encode()
39+
encodedBytes := encodedPacket.Bytes()
40+
41+
// Decode directly from the encoded packet (ensures Value is correct)
42+
fromPacket := DecodeControl(encodedPacket)
43+
if !bytes.Equal(encodedBytes, fromPacket.Encode().Bytes()) {
44+
t.Errorf("%sround-trip from encoded packet failed", header)
45+
}
46+
if reflect.TypeOf(originalControl) != reflect.TypeOf(fromPacket) {
47+
t.Errorf("%sgot different type decoding from encoded packet: %T vs %T", header, fromPacket, originalControl)
48+
}
49+
50+
// Decode from the wire bytes (ensures ber-encoding is correct)
51+
fromBytes := DecodeControl(ber.DecodePacket(encodedBytes))
52+
if !bytes.Equal(encodedBytes, fromBytes.Encode().Bytes()) {
53+
t.Errorf("%sround-trip from encoded bytes failed", header)
54+
}
55+
if reflect.TypeOf(originalControl) != reflect.TypeOf(fromPacket) {
56+
t.Errorf("%sgot different type decoding from encoded bytes: %T vs %T", header, fromBytes, originalControl)
57+
}
58+
}

0 commit comments

Comments
 (0)