Skip to content

Commit 437615c

Browse files
koushik2506johnweldon
authored andcommitted
Issue 177 matcheddn (#191)
* * Changes for adding support for matchedDN parsing * * Replace getLDAPResultCode with GetLDAPError * * 'err' shadowed in some places fixed. * * Adding doc comment for GetLDAPError()
1 parent 43d151a commit 437615c

File tree

13 files changed

+97
-63
lines changed

13 files changed

+97
-63
lines changed

add.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ func (l *Conn) Add(addRequest *AddRequest) error {
106106
}
107107

108108
if packet.Children[1].Tag == ApplicationAddResponse {
109-
resultCode, resultDescription := getLDAPResultCode(packet)
110-
if resultCode != 0 {
111-
return NewError(resultCode, errors.New(resultDescription))
109+
err := GetLDAPError(packet)
110+
if err != nil {
111+
return err
112112
}
113113
} else {
114114
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)

bind.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
7979
}
8080

8181
if l.Debug {
82-
if err := addLDAPDescriptions(packet); err != nil {
82+
if err = addLDAPDescriptions(packet); err != nil {
8383
return nil, err
8484
}
8585
ber.PrintPacket(packet)
@@ -91,20 +91,16 @@ func (l *Conn) SimpleBind(simpleBindRequest *SimpleBindRequest) (*SimpleBindResu
9191

9292
if len(packet.Children) == 3 {
9393
for _, child := range packet.Children[2].Children {
94-
decodedChild, err := DecodeControl(child)
95-
if err != nil {
96-
return nil, fmt.Errorf("failed to decode child control: %s", err)
94+
decodedChild, decodeErr := DecodeControl(child)
95+
if decodeErr != nil {
96+
return nil, fmt.Errorf("failed to decode child control: %s", decodeErr)
9797
}
9898
result.Controls = append(result.Controls, decodedChild)
9999
}
100100
}
101101

102-
resultCode, resultDescription := getLDAPResultCode(packet)
103-
if resultCode != 0 {
104-
return result, NewError(resultCode, errors.New(resultDescription))
105-
}
106-
107-
return result, nil
102+
err = GetLDAPError(packet)
103+
return result, err
108104
}
109105

110106
// Bind performs a bind with the given username and password.

compare.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ func (l *Conn) Compare(dn, attribute, value string) (bool, error) {
6868
}
6969

7070
if packet.Children[1].Tag == ApplicationCompareResponse {
71-
resultCode, resultDescription := getLDAPResultCode(packet)
71+
err := GetLDAPError(packet)
7272

7373
switch {
74-
case resultCode == LDAPResultCompareTrue:
74+
case IsErrorWithCode(err, LDAPResultCompareTrue):
7575
return true, nil
76-
case resultCode == LDAPResultCompareFalse:
76+
case IsErrorWithCode(err, LDAPResultCompareFalse):
7777
return false, nil
7878
default:
79-
return false, NewError(resultCode, errors.New(resultDescription))
79+
return false, err
8080
}
8181
}
8282
return false, fmt.Errorf("unexpected Response: %d", packet.Children[1].Tag)

conn.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,18 +275,18 @@ func (l *Conn) StartTLS(config *tls.Config) error {
275275
ber.PrintPacket(packet)
276276
}
277277

278-
if resultCode, message := getLDAPResultCode(packet); resultCode == LDAPResultSuccess {
278+
if err := GetLDAPError(packet); err == nil {
279279
conn := tls.Client(l.conn, config)
280280

281-
if err := conn.Handshake(); err != nil {
281+
if connErr := conn.Handshake(); connErr != nil {
282282
l.Close()
283-
return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", err))
283+
return NewError(ErrorNetwork, fmt.Errorf("TLS handshake failed (%v)", connErr))
284284
}
285285

286286
l.isTLS = true
287287
l.conn = conn
288288
} else {
289-
return NewError(resultCode, fmt.Errorf("ldap: cannot StartTLS (%s)", message))
289+
return err
290290
}
291291
go l.reader()
292292

del.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ func (l *Conn) Del(delRequest *DelRequest) error {
7171
}
7272

7373
if packet.Children[1].Tag == ApplicationDelResponse {
74-
resultCode, resultDescription := getLDAPResultCode(packet)
75-
if resultCode != 0 {
76-
return NewError(resultCode, errors.New(resultDescription))
74+
err := GetLDAPError(packet)
75+
if err != nil {
76+
return err
7777
}
7878
} else {
7979
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)

error.go

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,35 +176,44 @@ var LDAPResultCodeMap = map[uint16]string{
176176
ErrorEmptyPassword: "Empty password not allowed by the client",
177177
}
178178

179-
func getLDAPResultCode(packet *ber.Packet) (code uint16, description string) {
180-
if packet == nil {
181-
return ErrorUnexpectedResponse, "Empty packet"
182-
} else if len(packet.Children) >= 2 {
183-
response := packet.Children[1]
184-
if response == nil {
185-
return ErrorUnexpectedResponse, "Empty response in packet"
186-
}
187-
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
188-
// Children[1].Children[2] is the diagnosticMessage which is guaranteed to exist as seen here: https://tools.ietf.org/html/rfc4511#section-4.1.9
189-
return uint16(response.Children[0].Value.(int64)), response.Children[2].Value.(string)
190-
}
191-
}
192-
193-
return ErrorNetwork, "Invalid packet format"
194-
}
195-
196179
// Error holds LDAP error information
197180
type Error struct {
198181
// Err is the underlying error
199182
Err error
200183
// ResultCode is the LDAP error code
201184
ResultCode uint16
185+
// MatchedDN is the matchedDN returned if any
186+
MatchedDN string
202187
}
203188

204189
func (e *Error) Error() string {
205190
return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error())
206191
}
207192

193+
// GetLDAPError creates an Error out of a BER packet representing a LDAPResult
194+
// The return is an error object. It can be casted to a Error structure.
195+
// This function returns nil if resultCode in the LDAPResult sequence is success(0).
196+
func GetLDAPError(packet *ber.Packet) error {
197+
if packet == nil {
198+
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty packet")}
199+
} else if len(packet.Children) >= 2 {
200+
response := packet.Children[1]
201+
if response == nil {
202+
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
203+
}
204+
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
205+
resultCode := uint16(response.Children[0].Value.(int64))
206+
if resultCode == 0 { // No error
207+
return nil
208+
}
209+
return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
210+
Err: fmt.Errorf(response.Children[2].Value.(string))}
211+
}
212+
}
213+
214+
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
215+
}
216+
208217
// NewError creates an LDAP error with the given code and underlying error
209218
func NewError(resultCode uint16, err error) error {
210219
return &Error{ResultCode: resultCode, Err: err}

error_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313
// TestNilPacket tests that nil packets don't cause a panic.
1414
func TestNilPacket(t *testing.T) {
1515
// Test for nil packet
16-
code, _ := getLDAPResultCode(nil)
17-
if code != ErrorUnexpectedResponse {
18-
t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code)
16+
err := GetLDAPError(nil)
17+
if !IsErrorWithCode(err, ErrorUnexpectedResponse) {
18+
t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", err)
1919
}
2020

2121
// Test for nil result
@@ -24,10 +24,10 @@ func TestNilPacket(t *testing.T) {
2424
nil, // Can't be nil
2525
}
2626
pack := &ber.Packet{Children: kids}
27-
code, _ = getLDAPResultCode(pack)
27+
err = GetLDAPError(pack)
2828

29-
if code != ErrorUnexpectedResponse {
30-
t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", code)
29+
if !IsErrorWithCode(err, ErrorUnexpectedResponse) {
30+
t.Errorf("Should have an 'ErrorUnexpectedResponse' error in nil packets, got: %v", err)
3131
}
3232
}
3333

ldap.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,9 @@ func addRequestDescriptions(packet *ber.Packet) error {
270270
}
271271

272272
func addDefaultLDAPResponseDescriptions(packet *ber.Packet) error {
273-
resultCode, _ := getLDAPResultCode(packet)
274-
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[resultCode] + ")"
275-
packet.Children[1].Children[1].Description = "Matched DN"
273+
err := GetLDAPError(packet)
274+
packet.Children[1].Children[0].Description = "Result Code (" + LDAPResultCodeMap[err.(*Error).ResultCode] + ")"
275+
packet.Children[1].Children[1].Description = "Matched DN (" + err.(*Error).MatchedDN + ")"
276276
packet.Children[1].Children[2].Description = "Error Message"
277277
if len(packet.Children[1].Children) > 3 {
278278
packet.Children[1].Children[3].Description = "Referral"

ldap_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,32 @@ func TestCompare(t *testing.T) {
271271

272272
fmt.Printf("TestCompare: -> %v\n", sr)
273273
}
274+
275+
func TestMatchDNError(t *testing.T) {
276+
fmt.Printf("TestMatchDNError: starting..\n")
277+
278+
l, err := Dial("tcp", fmt.Sprintf("%s:%d", ldapServer, ldapPort))
279+
if err != nil {
280+
t.Fatal(err.Error())
281+
}
282+
defer l.Close()
283+
284+
wrongBase := "ou=roups,dc=umich,dc=edu"
285+
286+
searchRequest := NewSearchRequest(
287+
wrongBase,
288+
ScopeWholeSubtree, DerefAlways, 0, 0, false,
289+
filter[0],
290+
attributes,
291+
nil)
292+
293+
_, err = l.Search(searchRequest)
294+
295+
if err == nil {
296+
t.Errorf("Expected Error, got nil")
297+
return
298+
}
299+
300+
fmt.Printf("TestMatchDNError: err: %s\n", err.Error())
301+
302+
}

moddn.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ func (l *Conn) ModifyDN(m *ModifyDNRequest) error {
9191
}
9292

9393
if packet.Children[1].Tag == ApplicationModifyDNResponse {
94-
resultCode, resultDescription := getLDAPResultCode(packet)
95-
if resultCode != 0 {
96-
return NewError(resultCode, errors.New(resultDescription))
94+
err := GetLDAPError(packet)
95+
if err != nil {
96+
return err
9797
}
9898
} else {
9999
log.Printf("Unexpected Response: %d", packet.Children[1].Tag)

0 commit comments

Comments
 (0)