Skip to content

Expose ResultCode and DiagnosticMessage on SearchResult - #626

Merged
cpuschma merged 1 commit into
go-ldap:masterfrom
Pujathacker2210:search-result-diagnostic
Sep 25, 2026
Merged

cpuschma merged 1 commit into
go-ldap:masterfrom
Pujathacker2210:search-result-diagnostic

Conversation

@Pujathacker2210

@Pujathacker2210 Pujathacker2210 commented Sep 7, 2026 •

Copy link
Copy Markdown
Contributor

Problem

GetLDAPError returns nil when resultCode is 0 (success), discarding
the diagnosticMessage from SearchResultDone. Per RFC 4511 §4.1.9, servers
may set diagnosticMessage even on a successful operation to communicate
additional information such as degraded state.

For example, Red Hat IPA sets diagnosticMessage when the directory is
reinitializing but still returns resultCode 0 with an empty entry list.
Callers of Search() currently have no way to see that message — they only
see zero entries and no error, which is indistinguishable from a genuine
empty result.

Solution

  • Add ResultCode and DiagnosticMessage fields to SearchResult.
  • In Search(), populate them from the SearchResultDone packet (case 5) before calling GetLDAPError, so they are preserved even whenGetLDAPError returns nil on success.
  • Add parseLDAPResult helper that extracts resultCode, matchedDN, and diagnosticMessage from an LDAPResult BER packet without the early return on success that GetLDAPError has.
  • Copy the new fields in appendTo so paged searches preserve them.

Backward compatibility

  • GetLDAPError is unchanged.
  • SearchResult is a struct; adding fields is backward compatible in Go.
  • Existing callers are unaffected — they never read the new fields.
  • Callers who need the diagnostic on success can now read result.DiagnosticMessage after Search() returns.

References

Prior art

Python's python-ldap library already exposes the diagnostic message after successful operations by calling get_option(OPT_DIAGNOSTIC_MESSAGE) on the LDAP handle (source). This PR brings the same capability to go-ldap by surfacing diagnosticMessage on the SearchResult struct regardless of resultCode.

@Pujathacker2210

Copy link
Copy Markdown
Contributor Author

@t2y @cpuschma @johnweldon - Request you to review the PR

@t2y

t2y commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

This is my personal opinion based on the changes. Before we proceed with this PR, I'd like others' opinions on two API changes.

  1. Add DiagnosticMessage() string to the Response interface

SearchAsync drops the diagnosticMessage on success just like Search. To support both, I'd add this method and have it work like Err(), i.e. valid after Next returns false. This breaks external implementations of Response (e.g. test fakes), but fixing them only takes one extra method.

  1. Add a DiagnosticMessage field to ldap.Error

The goal is to parse LDAPResult in one place. GetLDAPError and the success path in Search/SearchAsync would share one internal parser, and GetLDAPError would copy the diagnosticMessage into the new field. Callers could then read it as a plain field on both success (SearchResult.DiagnosticMessage) and failure (Error.DiagnosticMessage), instead of pulling it out of Err, which also holds client-side errors.

@cpuschma cpuschma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the comments.

I would prefer not to make this function publicly available yet, until the aforementioned code snippets have been resolved.

For now, please change the function to non-public, so that only the new fields in SearchResult are propagated.

Comment thread v3/error.go Outdated
Comment thread v3/error.go Outdated
Comment thread v3/error.go Outdated
Comment thread v3/error.go Outdated
@cpuschma cpuschma self-assigned this Sep 23, 2026
@cpuschma cpuschma added enhancement go Pull requests that update go code labels Sep 23, 2026
@Pujathacker2210

Copy link
Copy Markdown
Contributor Author

@cpuschma Thanks for the review! Pushed the changes:

ParseLDAPResult → parseLDAPResult (unexported)
Simplified to int64 only per your note on TagInteger
All malformed-packet paths now return an error instead of silent zero values

Please take another look when you get a chance. Also, @t2y raised two additional suggestions — adding DiagnosticMessage() to the Response interface and a DiagnosticMessage field to ldap.Error. Both would be breaking changes for external consumers. @cpuschma @johnweldon could you share your thoughts on those? Happy to incorporate them into this PR if there's consensus, or we can handle them as a follow-up.

Comment thread v3/search.go Outdated
result.Entries = append(result.Entries, entry)
case 5:
rc, _, diag, parseErr := parseLDAPResult(packet)
if parseErr == nil {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseErr is not returned, the error is silently dropped here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@cpuschma

Copy link
Copy Markdown
Member

@cpuschma Thanks for the review! Pushed the changes:

ParseLDAPResult → parseLDAPResult (unexported) Simplified to int64 only per your note on TagInteger All malformed-packet paths now return an error instead of silent zero values

Please take another look when you get a chance. Also, @t2y raised two additional suggestions — adding DiagnosticMessage() to the Response interface and a DiagnosticMessage field to ldap.Error. Both would be breaking changes for external consumers. @cpuschma @johnweldon could you share your thoughts on those? Happy to incorporate them into this PR if there's consensus, or we can handle them as a follow-up.

Let's not introduce breaking changes in a minor release. Currently we have a abundance of PRs regarding OOB reads for malformed packets we need to address first before new functions or even breaking changes can be introduced (#632)

@johnweldon johnweldon left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution!

Comment thread v3/search.go
Comment thread v3/error.go Outdated
Comment thread v3/error.go Outdated
Comment thread v3/error.go
Comment thread v3/search.go
@t2y

t2y commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

I agree with @cpuschma's direction. Let's not include breaking changes in a minor release. We can revisit changing the interface later if needed.

GetLDAPError returns nil when resultCode is 0, discarding the diagnosticMessage. Some servers set this field on success to signal degraded state (e.g. directory reinitializing).
Add ResultCode and DiagnosticMessage to SearchResult, populated before GetLDAPError. Add ParseLDAPResult to read all LDAPResult fields without the early return on success.
GetLDAPError is unchanged. Existing callers are unaffected.
@Pujathacker2210

Copy link
Copy Markdown
Contributor Author

@cpuschma @johnweldon Pushed the fixes and replied to each comment. Let me know if anything else needs to be addressed.

@cpuschma
cpuschma merged commit ca8bcfa into go-ldap:master Sep 25, 2026
4 checks passed
@Pujathacker2210

Copy link
Copy Markdown
Contributor Author

Thank you @cpuschma for merging the PR. Please confirm when will this be released.

@Pujathacker2210

Copy link
Copy Markdown
Contributor Author

@t2y @cpuschma @johnweldon Please suggest when will this code be released

@cpuschma

Copy link
Copy Markdown
Member

Some issues are still to be adressed before a new release is published. If you're eager to use the newest patches, you can use the current commit instead of the tagged release:

go get github.com/go-ldap/ldap/v3@05f305f2813dc3d18a886d8f927d9ac9ca18a986

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants