@@ -44,6 +44,9 @@ type Permissions struct {
4444 // pass data from the authentication callbacks to the server
4545 // application layer.
4646 Extensions map [string ]string
47+
48+ // ExtraData allows to store user defined data.
49+ ExtraData map [any ]any
4750}
4851
4952type GSSAPIWithMICConfig struct {
@@ -127,6 +130,21 @@ type ServerConfig struct {
127130 // Permissions.Extensions entry.
128131 PublicKeyCallback func (conn ConnMetadata , key PublicKey ) (* Permissions , error )
129132
133+ // VerifiedPublicKeyCallback, if non-nil, is called after a client
134+ // successfully confirms having control over a key that was previously
135+ // approved by PublicKeyCallback. The permissions object passed to the
136+ // callback is the one returned by PublicKeyCallback for the given public
137+ // key and its ownership is transferred to the callback. The returned
138+ // Permissions object can be the same object, optionally modified, or a
139+ // completely new object. If VerifiedPublicKeyCallback is non-nil,
140+ // PublicKeyCallback is not allowed to return a PartialSuccessError, which
141+ // can instead be returned by VerifiedPublicKeyCallback.
142+ //
143+ // VerifiedPublicKeyCallback does not affect which authentication methods
144+ // are included in the list of methods that can be attempted by the client.
145+ VerifiedPublicKeyCallback func (conn ConnMetadata , key PublicKey , permissions * Permissions ,
146+ signatureAlgorithm string ) (* Permissions , error )
147+
130148 // KeyboardInteractiveCallback, if non-nil, is called when
131149 // keyboard-interactive authentication is selected (RFC
132150 // 4256). The client object's Challenge function should be
@@ -653,6 +671,9 @@ userAuthLoop:
653671 candidate .pubKeyData = pubKeyData
654672 candidate .perms , candidate .result = authConfig .PublicKeyCallback (s , pubKey )
655673 _ , isPartialSuccessError := candidate .result .(* PartialSuccessError )
674+ if isPartialSuccessError && config .VerifiedPublicKeyCallback != nil {
675+ return nil , errors .New ("ssh: invalid library usage: PublicKeyCallback must not return partial success when VerifiedPublicKeyCallback is defined" )
676+ }
656677
657678 if (candidate .result == nil || isPartialSuccessError ) &&
658679 candidate .perms != nil &&
@@ -723,6 +744,12 @@ userAuthLoop:
723744
724745 authErr = candidate .result
725746 perms = candidate .perms
747+ if authErr == nil && config .VerifiedPublicKeyCallback != nil {
748+ // Only call VerifiedPublicKeyCallback after the key has been accepted
749+ // and successfully verified. If authErr is non-nil, the key is not
750+ // considered verified and the callback must not run.
751+ perms , authErr = config .VerifiedPublicKeyCallback (s , pubKey , perms , algo )
752+ }
726753 }
727754 case "gssapi-with-mic" :
728755 if authConfig .GSSAPIWithMICConfig == nil {
0 commit comments