Skip to content

ssh: use errors.As to detect PartialSuccessError wrapped in BannerError#353

Open
XananasX7 wants to merge 1 commit into
golang:masterfrom
XananasX7:ssh-partial-success-errors-as
Open

ssh: use errors.As to detect PartialSuccessError wrapped in BannerError#353
XananasX7 wants to merge 1 commit into
golang:masterfrom
XananasX7:ssh-partial-success-errors-as

Conversation

@XananasX7

@XananasX7 XananasX7 commented Jun 3, 2026

Copy link
Copy Markdown

ssh: use errors.As to detect PartialSuccessError wrapped in BannerError

The authentication loop in newServerConn used a direct type assertion
authErr.(*PartialSuccessError) to detect partial-success responses from
authentication callbacks. This silently fails when a callback returns a
*BannerError that wraps a *PartialSuccessError.

BannerError has an Err field and implements Unwrap(), making it a
standard Go error-wrapping type. The PartialSuccessError doc says it
"can be returned by any of the ServerConfig authentication callbacks"
-- the same callbacks that may also return BannerError. It is therefore
valid and expected for a callback to return:

&BannerError{
    Message: "First factor accepted; provide second factor.",
    Err:     &PartialSuccessError{Next: ServerAuthCallbacks{...}},
}

This allows a callback to simultaneously send a banner message to the
client and signal partial success requiring a further auth step.

With the old direct type assertion, when authErr is a *BannerError
wrapping a *PartialSuccessError, ok is false. The partial-success state
is lost: authFailures is incremented, authConfig is not updated to
partialSuccess.Next, and the client receives SSH_MSG_USERAUTH_FAILURE
instead of SSH_MSG_USERAUTH_PARTIAL_SUCCESS.

The banner-extraction code immediately above already handles this
pattern correctly using errors.As for *BannerError.

This change replaces the three direct *PartialSuccessError type
assertions with errors.As, matching that existing pattern:

  1. Main auth loop (authErr path): the primary fix -- ensures
    partialSuccess.Next updates authConfig even when wrapped.
  2. PublicKeyCallback cache, first check: ensures the "invalid library
    usage" detection works when wrapped.
  3. PublicKeyCallback cache, isQuery check: ensures the public-key query
    response (SSH_MSG_USERAUTH_PK_OK) is sent correctly when the
    callback result wraps a PartialSuccessError.

A new test TestPartialSuccessErrorWrappedInBannerError is added to
server_multi_auth_test.go. It sets up a PasswordCallback returning
&BannerError{Err: &PartialSuccessError{...}}, verifies the client can
authenticate successfully in two password steps, and confirms the test
fails without the fix.

Updates golang/go#79809

@google-cla

google-cla Bot commented Jun 3, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@XananasX7

Copy link
Copy Markdown
Author

Fixes golang/go#79809

The auth loop in newServerConn used a direct type assertion
(authErr.(*PartialSuccessError)) to detect partial-success authentication
results. This fails when a callback returns a *BannerError that wraps a
*PartialSuccessError, because the outer error is a *BannerError not a
*PartialSuccessError.

The banner-extraction code immediately above (lines 934-940) already
uses errors.As correctly for *BannerError. Apply the same treatment to
the *PartialSuccessError check: replace the direct type assertion with
errors.As so that wrapped PartialSuccessErrors are also handled.

The same fix is applied to the two candidate.result type assertions in
the PublicKeyCallback cache path, which can receive errors from the same
callbacks and is subject to the same wrapping pattern.

Without this fix, a callback returning &BannerError{Err: &PartialSuccessError{...}}
would cause the partial-success response to be silently treated as an
authentication failure, incrementing authFailures and sending the client
a failure message instead of a partial-success message.

Fixes golang/go#79809
@XananasX7 XananasX7 force-pushed the ssh-partial-success-errors-as branch from 33e1572 to 1f9a96a Compare June 13, 2026 16:53
@XananasX7

Copy link
Copy Markdown
Author

Rewrote the commit with mehdiananas007@gmail.com as the author email — this is the address I used to sign the Google CLA. The cla/google check should now pass.

@gopherbot

Copy link
Copy Markdown
Contributor

This PR (HEAD: 1f9a96a) has been imported to Gerrit for code review.

Please visit Gerrit at https://go-review.googlesource.com/c/crypto/+/790421.

Important tips:

  • Don't comment on this PR. All discussion takes place in Gerrit.
  • You need a Gmail or other Google account to log in to Gerrit.
  • To change your code in response to feedback:
    • Push a new commit to the branch used by your GitHub PR.
    • A new "patch set" will then appear in Gerrit.
    • Respond to each comment by marking as Done in Gerrit if implemented as suggested. You can alternatively write a reply.
    • Critical: you must click the blue Reply button near the top to publish your Gerrit responses.
    • Multiple commits in the PR will be squashed by GerritBot.
  • The title and description of the GitHub PR are used to construct the final commit message.
    • Edit these as needed via the GitHub web interface (not via Gerrit or git).
    • You should word wrap the PR description at ~76 characters unless you need longer lines (e.g., for tables or URLs).
  • See the Sending a change via GitHub and Reviews sections of the Contribution Guide as well as the FAQ for details.

@gopherbot

Copy link
Copy Markdown
Contributor

Message from Gopher Robot:

Patch Set 1:

(1 comment)


Please don’t reply on this GitHub thread. Visit golang.org/cl/790421.
After addressing review feedback, remember to publish your drafts!

@XananasX7

Copy link
Copy Markdown
Author

Updated the PR description to address the Gerrit bot feedback: removed all Markdown formatting (backticks, bold, headers, code fences), wrapped all lines to ≤76 characters, and added 'Updates golang/go#79809' as the bug reference.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants