Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: x/crypto/ssh: add ServerConfig.PreAuthConnCallback, ServerPreAuthConn (banner) interface #68688

Open
awly opened this issue Jul 31, 2024 · 8 comments
Labels
Proposal Proposal-Crypto Proposal related to crypto packages or other security issues
Milestone

Comments

@awly
Copy link
Contributor

awly commented Jul 31, 2024

Proposal Details

SSH server has 2 methods of sending banners (SSH_MSG_USERAUTH_BANNER) back to the client:

  1. BannerCallback, which runs before any auth handlers
  2. BannerError return, which can be returned from any auth handler

However, the SSH spec allows banners to be sent at any point in the connection until authentication is complete, not bound to auth attempts. While we could add a new method on ssh.ConnMetadata (which is passed to auth handlers) or ssh.Conn (which can be type-asserted from ssh.ConnMetadata), this would break backwards-compatibility for custom implementations of those interfaces.

I propose we add a new single-purpose interface:

// BannerSender sends banner messages from the server to the client. Banners
// can only be sent before authentication is complete, from callbacks in
// ServerConfig. Calls to SendBanner after authentication always fail. Callers
// can access a BannerSender using a checked type assertion on the ConnMetadata
// value passed to the callbacks in ServerConfig. 
type BannerSender interface {
    SendBanner(message string) error
}

This new method would be implemented on the unexported *x/crypto/ssh.connection type, which is passed as ConnMetadata in authentication handlers. This is not very discoverable, but is the least disruptive API change I could think of.

In #64962 (comment) I claimed that this was sufficient for Tailscale's use case, but turns out it was not, that's my bad.
For example, a server can print a custom prompt or instruction to the user while an authentication attempt is pending, which is required for the user to finish that attempt.

cc @drakkan @oxtoacart @bradfitz

@awly awly added the Proposal label Jul 31, 2024
@gopherbot gopherbot added this to the Proposal milestone Jul 31, 2024
@gabyhelp
Copy link

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

@ianlancetaylor ianlancetaylor moved this to Incoming in Proposals Aug 7, 2024
@ianlancetaylor ianlancetaylor added the Proposal-Crypto Proposal related to crypto packages or other security issues label Aug 7, 2024
@ianlancetaylor
Copy link
Contributor

CC @golang/security

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/613856 mentions this issue: ssh: add ServerConfig.GetPreAuthConn, ServerPreAuthConn (banner) interface

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/614416 mentions this issue: ssh: add BannerSender interface

@drakkan
Copy link
Member

drakkan commented Sep 29, 2024

I would like to discuss also the proposal implemented by @bradfitz in CL 613856.

Here is the proposal, I just change the name of the callback to make it more similar to the existing ones:

// ServerPreAuthConn is the interface available on an incoming server
// connection before authentication has completed.
type ServerPreAuthConn interface {
	unexportedMethodForFutureProofing() // permits growing ServerPreAuthConn safely later, ala testing.TB

	ConnMetadata

	// SendAuthBanner sends a banner message to the client.
	// It returns an error once the authentication phase has ended.
	SendAuthBanner(string) error
}

// ServerConfig holds server specific configuration data.
type ServerConfig struct {
     .....
     // PreAuthConnCallback, if non-nil, is called upon receiving a new connection
     // before any authentication has started. The provided ServerPreAuthConn
     // can be used before authentication is complete.
     PreAuthConnCallback func(ServerPreAuthConn)
}

The main difference with the other proposal is that here we add interface extension of the ConnMetadata that allows to send banners and we can obtain it by adding a PreAuthConnCallback to ServerConfig.

The other approach allows to send banners using the ConnMetadata interface received in the authentication callbacks.

PreAuthConnCallback seems more flexible, in the future we may consider reusing it to expose other methods or properties as well

@oxtoacart
Copy link
Contributor

@FiloSottile @drakkan Is there anything I can do to help move this forward?

@bradfitz
Copy link
Contributor

I dusted off my CL above, did the rename, and added some tests: https://go-review.googlesource.com/c/crypto/+/613856

bradfitz added a commit to tailscale/golang-x-crypto that referenced this issue Nov 1, 2024
… interface

Fixes golang/go#68688

Change-Id: Id5f72b32c61c9383a26ec182339486a432c7cdf5
@bradfitz bradfitz changed the title proposal: x/crypto/ssh: add BannerSender interface proposal: x/crypto/ssh: add ServerConfig.PreAuthConnCallback, ServerPreAuthConn (banner) interface Nov 5, 2024
@bradfitz
Copy link
Contributor

bradfitz commented Nov 5, 2024

@FiloSottile, @drakkan, https://go-review.googlesource.com/c/crypto/+/613856 contains the latest proposal (with @drakkan's renames from above) and the approved implementation, on Hold for approval here.

When does Crypto Proposal Committee meet? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Proposal Proposal-Crypto Proposal related to crypto packages or other security issues
Projects
Status: Incoming
Development

No branches or pull requests

7 participants