Skip to content

Commit 945cdf3

Browse files
authored
Extend ldap.Error to include reference to response (#272)
* Extend ldap.Error to include reference to response Address #271 * Just return the result It's even more inelegant to try to wrap the limit errors and re-parse the packet for the result. We'll keep the most recent packet in the `Error` as a useful addition, but we'll just return the result in any error case even though it's counter to common Go idioms.
1 parent 45321a6 commit 945cdf3

File tree

4 files changed

+52
-20
lines changed

4 files changed

+52
-20
lines changed

error.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ type Error struct {
184184
ResultCode uint16
185185
// MatchedDN is the matchedDN returned if any
186186
MatchedDN string
187+
// Packet is the returned packet if any
188+
Packet *ber.Packet
187189
}
188190

189191
func (e *Error) Error() string {
@@ -201,28 +203,32 @@ func GetLDAPError(packet *ber.Packet) error {
201203
if len(packet.Children) >= 2 {
202204
response := packet.Children[1]
203205
if response == nil {
204-
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
206+
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet}
205207
}
206208
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
207209
resultCode := uint16(response.Children[0].Value.(int64))
208210
if resultCode == 0 { // No error
209211
return nil
210212
}
211-
return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
212-
Err: fmt.Errorf("%s", response.Children[2].Value.(string))}
213+
return &Error{
214+
ResultCode: resultCode,
215+
MatchedDN: response.Children[1].Value.(string),
216+
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217+
Packet: packet,
218+
}
213219
}
214220
}
215221

216-
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
222+
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format"), Packet: packet}
217223
}
218224

219225
// NewError creates an LDAP error with the given code and underlying error
220226
func NewError(resultCode uint16, err error) error {
221227
return &Error{ResultCode: resultCode, Err: err}
222228
}
223229

224-
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
225-
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
230+
// IsErrorAnyOf returns true if the given error is an LDAP error with any one of the given result codes
231+
func IsErrorAnyOf(err error, codes ...uint16) bool {
226232
if err == nil {
227233
return false
228234
}
@@ -232,5 +238,15 @@ func IsErrorWithCode(err error, desiredResultCode uint16) bool {
232238
return false
233239
}
234240

235-
return serverError.ResultCode == desiredResultCode
241+
for _, code := range codes {
242+
if serverError.ResultCode == code {
243+
return true
244+
}
245+
}
246+
247+
return false
248+
}
249+
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
250+
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
251+
return IsErrorAnyOf(err, desiredResultCode)
236252
}

search.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
371371
for {
372372
packet, err := l.readPacket(msgCtx)
373373
if err != nil {
374-
return nil, err
374+
return result, err
375375
}
376376

377377
switch packet.Children[1].Tag {
@@ -391,13 +391,13 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
391391
case 5:
392392
err := GetLDAPError(packet)
393393
if err != nil {
394-
return nil, err
394+
return result, err
395395
}
396396
if len(packet.Children) == 3 {
397397
for _, child := range packet.Children[2].Children {
398398
decodedChild, err := DecodeControl(child)
399399
if err != nil {
400-
return nil, fmt.Errorf("failed to decode child control: %s", err)
400+
return result, fmt.Errorf("failed to decode child control: %w", err)
401401
}
402402
result.Controls = append(result.Controls, decodedChild)
403403
}

v3/error.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ type Error struct {
184184
ResultCode uint16
185185
// MatchedDN is the matchedDN returned if any
186186
MatchedDN string
187+
// Packet is the returned packet if any
188+
Packet *ber.Packet
187189
}
188190

189191
func (e *Error) Error() string {
@@ -201,28 +203,32 @@ func GetLDAPError(packet *ber.Packet) error {
201203
if len(packet.Children) >= 2 {
202204
response := packet.Children[1]
203205
if response == nil {
204-
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet")}
206+
return &Error{ResultCode: ErrorUnexpectedResponse, Err: fmt.Errorf("Empty response in packet"), Packet: packet}
205207
}
206208
if response.ClassType == ber.ClassApplication && response.TagType == ber.TypeConstructed && len(response.Children) >= 3 {
207209
resultCode := uint16(response.Children[0].Value.(int64))
208210
if resultCode == 0 { // No error
209211
return nil
210212
}
211-
return &Error{ResultCode: resultCode, MatchedDN: response.Children[1].Value.(string),
212-
Err: fmt.Errorf("%s", response.Children[2].Value.(string))}
213+
return &Error{
214+
ResultCode: resultCode,
215+
MatchedDN: response.Children[1].Value.(string),
216+
Err: fmt.Errorf("%s", response.Children[2].Value.(string)),
217+
Packet: packet,
218+
}
213219
}
214220
}
215221

216-
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format")}
222+
return &Error{ResultCode: ErrorNetwork, Err: fmt.Errorf("Invalid packet format"), Packet: packet}
217223
}
218224

219225
// NewError creates an LDAP error with the given code and underlying error
220226
func NewError(resultCode uint16, err error) error {
221227
return &Error{ResultCode: resultCode, Err: err}
222228
}
223229

224-
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
225-
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
230+
// IsErrorAnyOf returns true if the given error is an LDAP error with any one of the given result codes
231+
func IsErrorAnyOf(err error, codes ...uint16) bool {
226232
if err == nil {
227233
return false
228234
}
@@ -232,5 +238,15 @@ func IsErrorWithCode(err error, desiredResultCode uint16) bool {
232238
return false
233239
}
234240

235-
return serverError.ResultCode == desiredResultCode
241+
for _, code := range codes {
242+
if serverError.ResultCode == code {
243+
return true
244+
}
245+
}
246+
247+
return false
248+
}
249+
// IsErrorWithCode returns true if the given error is an LDAP error with the given result code
250+
func IsErrorWithCode(err error, desiredResultCode uint16) bool {
251+
return IsErrorAnyOf(err, desiredResultCode)
236252
}

v3/search.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
371371
for {
372372
packet, err := l.readPacket(msgCtx)
373373
if err != nil {
374-
return nil, err
374+
return result, err
375375
}
376376

377377
switch packet.Children[1].Tag {
@@ -391,13 +391,13 @@ func (l *Conn) Search(searchRequest *SearchRequest) (*SearchResult, error) {
391391
case 5:
392392
err := GetLDAPError(packet)
393393
if err != nil {
394-
return nil, err
394+
return result, err
395395
}
396396
if len(packet.Children) == 3 {
397397
for _, child := range packet.Children[2].Children {
398398
decodedChild, err := DecodeControl(child)
399399
if err != nil {
400-
return nil, fmt.Errorf("failed to decode child control: %s", err)
400+
return result, fmt.Errorf("failed to decode child control: %w", err)
401401
}
402402
result.Controls = append(result.Controls, decodedChild)
403403
}

0 commit comments

Comments
 (0)