-
Notifications
You must be signed in to change notification settings - Fork 17.8k
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: verified public key callback and arbitrary data in Permissions #70795
Comments
Related Issues
Related Discussions (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
CC @golang/security |
why would you need both at the same time? cc @drakkan |
*: before the recent mitigation for the CVE in #70779 it was called exactly once, now it can get called a second time depending on the order in which public keys are queried before deciding on one |
I think we need a stronger reason to allow both being set and for passing data with any, otherwise it's much simpler to say at most one can be set, like net/http/httputil.ReverseProxy's Rewrite/Director funcs. |
You can't have only one set. Only PublicKeyCallback is the status quo, with the problems that motivate this proposal. Only VerifiedPublicKeyCallback just doesn't work at the protocol level: the client will send a query asking for the acceptability of a public key before it sends a signature, and what do we do? We can't call VerifiedPublicKeyCallback with it, or it's just behaving like PublicKeyCallback. We always answer yes? That will probably break connections that expect signatures to always get accepted after a query was accepted. |
I came here looking exactly for this, the current structure is very limiting to only string data. Having an arbitrary interface as a field would solve a lot of issues. When having structures that are not easily string-marshable it is a big pain to pass them with the current system. I support both proposals on this issue |
Change https://go.dev/cl/636335 mentions this issue: |
I like this proposal, since we are discussing about a new PublicKey callback, I would like to propose to also add the public key algorithm, which is currently not avaible to library users, to this callback
|
Would that be to disambiguate between the different RSA signature schemes? Are there other situations in which the algorithm is not |
Yes, this is for RSA keys. You can allow for example |
Maybe ExtraData could be |
What happens if VerifiedPublicKeyCallback modifies the Can we see the full proposed doc comment of VerifiedPublicKeyCallback? |
A partial success error resets any previous authn state (except the attempt count I guess) and the only thing that ends up mattering for the future is the content of
Something like type ServerConfig struct {
...
// VerifiedPublicKeyCallback, if non-nil, is called after a client successfully
// confirms having control over a key that was previously approved by PublicKeyCallback.
// The permissions object passed to the callback is the one returned by PublicKeyCallback
// for the given public key and its ownership is transferred to the callback. The returned
// Permissions object can be the same object, optionally modified, or a completely new object.
// If VerifiedPublicKeyCallback is non-nil, PublicKeyCallback is not allowed to return a
// PartialSuccessError, which can instead be returned by VerifiedPublicKeyCallback.
VerifiedPublicKeyCallback func(conn ConnMetadata, key PublicKey, permissions *Permissions, signatureAlgorithm string) (*Permissions, error)
} |
Proposal Details
The
ServerConfig.PublicKeyCallback
callback gets called as part of the server-side SSH handshake whenever the client tries to authenticate with a public key or when the client asks whether or not a public key would be accepted by the server. No matter the order in which keys are presented, and notwithstanding the mitigation for CVE-2024-45337 (#70779), the callback is called before any signature from the client is verified (or potentially even received), which means that it's not practical or advisable to have the server make decisions on whether or not to continue with the authentication (potentially with a partial success) based on data and computations that require more effort than what can be allowed for an unauthenticated and untrusted client.I propose the addition of a new, optional callback to
ssh.ServerConfig
:If
PublicKeyCallback
returns no error for a given public key, the client provides aSSH_MSG_USERAUTH_REQUEST
message with a valid signature for that public key, andVerifiedPublicKeyCallback
is non-nil, theVerifiedPublicKeyCallback
will be called before the server sends a response to the client, passing in the sameConnMetadata
andPublicKey
that was passed to thePublicKeyCallback
, and the*Permissions
object that was returned byPublicKeyCallback
.The
VerifiedPublicKeyCallback
can then return the same or a new*Permissions
to complete the handshake, a*PartialSuccessError
to continue the handshake with a partial success and new authentication callbacks, or a different non-nil error to fail the authentication and let the client attempt to use a different authentication method (I believe that according to RFC 4252 the server is allowed to fail the authentication for a key that it has acknowledged as acceptable earlier in the handshake, but it might be worth checking the behavior of popular SSH clients in such a situation).VerifiedPublicKeyCallback
is guaranteed to not be called again after returning success - in case of a*PartialSuccessError
that includesPublicKeyCallback
, it might be called again once more for a different public key.To avoid ambiguous behavior,
PublicKeyCallback
is not allowed to return a*PartialSuccessError
ifVerifiedPublicKeyCallback
is non-nil.To better support passing data between the two callbacks - and to allow for extracting richer authentication data without risking the sort of misuse that led to CVE-2024-45337 - I also propose that we extend
Permissions
to include a singleany
field, for use by the authentication callbacks:The
ExtraData
field will be available for inspection inServerConn.Permissions
after the handshake, and it can be used to pass some arbitrary data fromPublicKeyCallback
toVerifiedPublicKeyCallback
.The text was updated successfully, but these errors were encountered: