Skip to content

Commit 056dc13

Browse files
authored
Merge pull request #98 from liggitt/dn-comparison
Ignore unescaped leading/trailing spaces in RDN type/value
2 parents e33f0a3 + 682bd53 commit 056dc13

File tree

3 files changed

+49
-7
lines changed

3 files changed

+49
-7
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
language: go
22
env:
33
global:
4-
- VET_VERSIONS="1.5 1.6 1.7 tip"
5-
- LINT_VERSIONS="1.5 1.6 1.7 tip"
4+
- VET_VERSIONS="1.6 1.7 tip"
5+
- LINT_VERSIONS="1.6 1.7 tip"
66
go:
77
- 1.2
88
- 1.3

dn.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,19 @@ func ParseDN(str string) (*DN, error) {
8383
attribute := new(AttributeTypeAndValue)
8484
escaping := false
8585

86+
unescapedTrailingSpaces := 0
87+
stringFromBuffer := func() string {
88+
s := buffer.String()
89+
s = s[0 : len(s)-unescapedTrailingSpaces]
90+
buffer.Reset()
91+
unescapedTrailingSpaces = 0
92+
return s
93+
}
94+
8695
for i := 0; i < len(str); i++ {
8796
char := str[i]
8897
if escaping {
98+
unescapedTrailingSpaces = 0
8999
escaping = false
90100
switch char {
91101
case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
@@ -107,10 +117,10 @@ func ParseDN(str string) (*DN, error) {
107117
buffer.WriteByte(dst[0])
108118
i++
109119
} else if char == '\\' {
120+
unescapedTrailingSpaces = 0
110121
escaping = true
111122
} else if char == '=' {
112-
attribute.Type = buffer.String()
113-
buffer.Reset()
123+
attribute.Type = stringFromBuffer()
114124
// Special case: If the first character in the value is # the
115125
// following data is BER encoded so we can just fast forward
116126
// and decode.
@@ -133,24 +143,33 @@ func ParseDN(str string) (*DN, error) {
133143
}
134144
} else if char == ',' || char == '+' {
135145
// We're done with this RDN or value, push it
136-
attribute.Value = buffer.String()
146+
attribute.Value = stringFromBuffer()
137147
rdn.Attributes = append(rdn.Attributes, attribute)
138148
attribute = new(AttributeTypeAndValue)
139149
if char == ',' {
140150
dn.RDNs = append(dn.RDNs, rdn)
141151
rdn = new(RelativeDN)
142152
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
143153
}
144-
buffer.Reset()
154+
} else if char == ' ' && buffer.Len() == 0 {
155+
// ignore unescaped leading spaces
156+
continue
145157
} else {
158+
if char == ' ' {
159+
// Track unescaped spaces in case they are trailing and we need to remove them
160+
unescapedTrailingSpaces++
161+
} else {
162+
// Reset if we see a non-space char
163+
unescapedTrailingSpaces = 0
164+
}
146165
buffer.WriteByte(char)
147166
}
148167
}
149168
if buffer.Len() > 0 {
150169
if len(attribute.Type) == 0 {
151170
return nil, errors.New("DN ended with incomplete type, value pair")
152171
}
153-
attribute.Value = buffer.String()
172+
attribute.Value = stringFromBuffer()
154173
rdn.Attributes = append(rdn.Attributes, attribute)
155174
dn.RDNs = append(dn.RDNs, rdn)
156175
}

dn_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ func TestSuccessfulDNParsing(t *testing.T) {
3131
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
3232
"CN=Lu\\C4\\8Di\\C4\\87": ldap.DN{[]*ldap.RelativeDN{
3333
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}},
34+
" CN = Lu\\C4\\8Di\\C4\\87 ": ldap.DN{[]*ldap.RelativeDN{
35+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}},
36+
` A = 1 , B = 2 `: ldap.DN{[]*ldap.RelativeDN{
37+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"A", "1"}}},
38+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"B", "2"}}}}},
39+
` A = 1 + B = 2 `: ldap.DN{[]*ldap.RelativeDN{
40+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
41+
&ldap.AttributeTypeAndValue{"A", "1"},
42+
&ldap.AttributeTypeAndValue{"B", "2"}}}}},
43+
` \ \ A\ \ = \ \ 1\ \ , \ \ B\ \ = \ \ 2\ \ `: ldap.DN{[]*ldap.RelativeDN{
44+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{" A ", " 1 "}}},
45+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{" B ", " 2 "}}}}},
46+
` \ \ A\ \ = \ \ 1\ \ + \ \ B\ \ = \ \ 2\ \ `: ldap.DN{[]*ldap.RelativeDN{
47+
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
48+
&ldap.AttributeTypeAndValue{" A ", " 1 "},
49+
&ldap.AttributeTypeAndValue{" B ", " 2 "}}}}},
3450
}
3551

3652
for test, answer := range testcases {
@@ -41,6 +57,13 @@ func TestSuccessfulDNParsing(t *testing.T) {
4157
}
4258
if !reflect.DeepEqual(dn, &answer) {
4359
t.Errorf("Parsed DN %s is not equal to the expected structure", test)
60+
t.Logf("Expected:")
61+
for _, rdn := range answer.RDNs {
62+
for _, attribs := range rdn.Attributes {
63+
t.Logf("#%v\n", attribs)
64+
}
65+
}
66+
t.Logf("Actual:")
4467
for _, rdn := range dn.RDNs {
4568
for _, attribs := range rdn.Attributes {
4669
t.Logf("#%v\n", attribs)

0 commit comments

Comments
 (0)