Skip to content

Commit

Permalink
Merge pull request #98 from liggitt/dn-comparison
Browse files Browse the repository at this point in the history
Ignore unescaped leading/trailing spaces in RDN type/value
  • Loading branch information
liggitt authored Dec 1, 2016
2 parents e33f0a3 + 682bd53 commit 056dc13
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: go
env:
global:
- VET_VERSIONS="1.5 1.6 1.7 tip"
- LINT_VERSIONS="1.5 1.6 1.7 tip"
- VET_VERSIONS="1.6 1.7 tip"
- LINT_VERSIONS="1.6 1.7 tip"
go:
- 1.2
- 1.3
Expand Down
29 changes: 24 additions & 5 deletions dn.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,19 @@ func ParseDN(str string) (*DN, error) {
attribute := new(AttributeTypeAndValue)
escaping := false

unescapedTrailingSpaces := 0
stringFromBuffer := func() string {
s := buffer.String()
s = s[0 : len(s)-unescapedTrailingSpaces]
buffer.Reset()
unescapedTrailingSpaces = 0
return s
}

for i := 0; i < len(str); i++ {
char := str[i]
if escaping {
unescapedTrailingSpaces = 0
escaping = false
switch char {
case ' ', '"', '#', '+', ',', ';', '<', '=', '>', '\\':
Expand All @@ -107,10 +117,10 @@ func ParseDN(str string) (*DN, error) {
buffer.WriteByte(dst[0])
i++
} else if char == '\\' {
unescapedTrailingSpaces = 0
escaping = true
} else if char == '=' {
attribute.Type = buffer.String()
buffer.Reset()
attribute.Type = stringFromBuffer()
// Special case: If the first character in the value is # the
// following data is BER encoded so we can just fast forward
// and decode.
Expand All @@ -133,24 +143,33 @@ func ParseDN(str string) (*DN, error) {
}
} else if char == ',' || char == '+' {
// We're done with this RDN or value, push it
attribute.Value = buffer.String()
attribute.Value = stringFromBuffer()
rdn.Attributes = append(rdn.Attributes, attribute)
attribute = new(AttributeTypeAndValue)
if char == ',' {
dn.RDNs = append(dn.RDNs, rdn)
rdn = new(RelativeDN)
rdn.Attributes = make([]*AttributeTypeAndValue, 0)
}
buffer.Reset()
} else if char == ' ' && buffer.Len() == 0 {
// ignore unescaped leading spaces
continue
} else {
if char == ' ' {
// Track unescaped spaces in case they are trailing and we need to remove them
unescapedTrailingSpaces++
} else {
// Reset if we see a non-space char
unescapedTrailingSpaces = 0
}
buffer.WriteByte(char)
}
}
if buffer.Len() > 0 {
if len(attribute.Type) == 0 {
return nil, errors.New("DN ended with incomplete type, value pair")
}
attribute.Value = buffer.String()
attribute.Value = stringFromBuffer()
rdn.Attributes = append(rdn.Attributes, attribute)
dn.RDNs = append(dn.RDNs, rdn)
}
Expand Down
23 changes: 23 additions & 0 deletions dn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ func TestSuccessfulDNParsing(t *testing.T) {
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"DC", "net"}}}}},
"CN=Lu\\C4\\8Di\\C4\\87": ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}},
" CN = Lu\\C4\\8Di\\C4\\87 ": ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"CN", "Lučić"}}}}},
` A = 1 , B = 2 `: ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"A", "1"}}},
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{"B", "2"}}}}},
` A = 1 + B = 2 `: ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
&ldap.AttributeTypeAndValue{"A", "1"},
&ldap.AttributeTypeAndValue{"B", "2"}}}}},
` \ \ A\ \ = \ \ 1\ \ , \ \ B\ \ = \ \ 2\ \ `: ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{" A ", " 1 "}}},
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{&ldap.AttributeTypeAndValue{" B ", " 2 "}}}}},
` \ \ A\ \ = \ \ 1\ \ + \ \ B\ \ = \ \ 2\ \ `: ldap.DN{[]*ldap.RelativeDN{
&ldap.RelativeDN{[]*ldap.AttributeTypeAndValue{
&ldap.AttributeTypeAndValue{" A ", " 1 "},
&ldap.AttributeTypeAndValue{" B ", " 2 "}}}}},
}

for test, answer := range testcases {
Expand All @@ -41,6 +57,13 @@ func TestSuccessfulDNParsing(t *testing.T) {
}
if !reflect.DeepEqual(dn, &answer) {
t.Errorf("Parsed DN %s is not equal to the expected structure", test)
t.Logf("Expected:")
for _, rdn := range answer.RDNs {
for _, attribs := range rdn.Attributes {
t.Logf("#%v\n", attribs)
}
}
t.Logf("Actual:")
for _, rdn := range dn.RDNs {
for _, attribs := range rdn.Attributes {
t.Logf("#%v\n", attribs)
Expand Down

0 comments on commit 056dc13

Please sign in to comment.