From 7f97b823a59bf4b85d74630c67f057dfaebf10f3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Zubov Date: Thu, 17 Aug 2023 13:48:08 +0300 Subject: [PATCH 1/3] ControlSyncRequest Encode: cookie optionality (#459) In SyncRequest cookie is optional, so do not add cookie if empty --- v3/control.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/v3/control.go b/v3/control.go index 6710feb..c2c3f87 100644 --- a/v3/control.go +++ b/v3/control.go @@ -928,9 +928,12 @@ func (c *ControlSyncRequest) GetControlType() string { func (c *ControlSyncRequest) Encode() *ber.Packet { _mode := int64(c.Mode) mode := ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagEnumerated, _mode, "Mode") - cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie") - cookie.Value = c.Cookie - cookie.Data.Write(c.Cookie) + var cookie *ber.Packet + if len(c.Cookie) > 0 { + cookie = ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie") + cookie.Value = c.Cookie + cookie.Data.Write(c.Cookie) + } reloadHint := ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.ReloadHint, "Reload Hint") packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control") @@ -940,7 +943,9 @@ func (c *ControlSyncRequest) Encode() *ber.Packet { val := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Sync Request)") seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Sync Request Value") seq.AppendChild(mode) - seq.AppendChild(cookie) + if cookie != nil { + seq.AppendChild(cookie) + } seq.AppendChild(reloadHint) val.AppendChild(seq) From afeeccd1300b75ba2bc2c3040d78986b15a96c1c Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Wed, 6 Sep 2023 01:38:20 -0600 Subject: [PATCH 2/3] feat: add support for Go 1.13's errors.Is/As functions (#461) ldap.Error wraps an underlying error, but doesn't interoperate with errors.Is or errors.As since it doesn't expose an Unwrap method. This change makes it easier to detect things like an LDAP error caused due to a network timeout. Co-authored-by: Christopher Puschmann --- v3/error.go | 2 ++ v3/error_test.go | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/v3/error.go b/v3/error.go index b9d6452..3c2559e 100644 --- a/v3/error.go +++ b/v3/error.go @@ -192,6 +192,8 @@ func (e *Error) Error() string { return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error()) } +func (e *Error) Unwrap() error { return e.Err } + // GetLDAPError creates an Error out of a BER packet representing a LDAPResult // The return is an error object. It can be casted to a Error structure. // This function returns nil if resultCode in the LDAPResult sequence is success(0). diff --git a/v3/error_test.go b/v3/error_test.go index 63018ee..c115e00 100644 --- a/v3/error_test.go +++ b/v3/error_test.go @@ -2,6 +2,7 @@ package ldap import ( "errors" + "io" "net" "strings" "testing" @@ -103,6 +104,24 @@ func TestGetLDAPErrorInvalidResponse(t *testing.T) { } } +func TestErrorIs(t *testing.T) { + err := NewError(ErrorNetwork, io.EOF) + if !errors.Is(err, io.EOF) { + t.Errorf("Expected an io.EOF error: %v", err) + } +} + +func TestErrorAs(t *testing.T) { + var netErr net.InvalidAddrError = "invalid addr" + err := NewError(ErrorNetwork, netErr) + + var target net.InvalidAddrError + ok := errors.As(err, &target) + if !ok { + t.Error("Expected an InvalidAddrError") + } +} + // TestGetLDAPErrorSuccess tests parsing of a result with no error (resultCode == 0). func TestGetLDAPErrorSuccess(t *testing.T) { bindResponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response") From ba89d92f86436f9c769aa235010e1111e7591e75 Mon Sep 17 00:00:00 2001 From: Christopher Puschmann Date: Wed, 6 Sep 2023 09:39:45 +0200 Subject: [PATCH 3/3] Mirror changes from afeeccd into root directory --- error.go | 2 ++ error_test.go | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/error.go b/error.go index b9d6452..3c2559e 100644 --- a/error.go +++ b/error.go @@ -192,6 +192,8 @@ func (e *Error) Error() string { return fmt.Sprintf("LDAP Result Code %d %q: %s", e.ResultCode, LDAPResultCodeMap[e.ResultCode], e.Err.Error()) } +func (e *Error) Unwrap() error { return e.Err } + // GetLDAPError creates an Error out of a BER packet representing a LDAPResult // The return is an error object. It can be casted to a Error structure. // This function returns nil if resultCode in the LDAPResult sequence is success(0). diff --git a/error_test.go b/error_test.go index 63018ee..c115e00 100644 --- a/error_test.go +++ b/error_test.go @@ -2,6 +2,7 @@ package ldap import ( "errors" + "io" "net" "strings" "testing" @@ -103,6 +104,24 @@ func TestGetLDAPErrorInvalidResponse(t *testing.T) { } } +func TestErrorIs(t *testing.T) { + err := NewError(ErrorNetwork, io.EOF) + if !errors.Is(err, io.EOF) { + t.Errorf("Expected an io.EOF error: %v", err) + } +} + +func TestErrorAs(t *testing.T) { + var netErr net.InvalidAddrError = "invalid addr" + err := NewError(ErrorNetwork, netErr) + + var target net.InvalidAddrError + ok := errors.As(err, &target) + if !ok { + t.Error("Expected an InvalidAddrError") + } +} + // TestGetLDAPErrorSuccess tests parsing of a result with no error (resultCode == 0). func TestGetLDAPErrorSuccess(t *testing.T) { bindResponse := ber.Encode(ber.ClassApplication, ber.TypeConstructed, ApplicationBindResponse, nil, "Bind Response")