server.go raw

   1  // Copyright 2011 The Go Authors. All rights reserved.
   2  // Use of this source code is governed by a BSD-style
   3  // license that can be found in the LICENSE file.
   4  
   5  package ssh
   6  
   7  import (
   8  	"bytes"
   9  	"errors"
  10  	"fmt"
  11  	"io"
  12  	"net"
  13  	"slices"
  14  	"strings"
  15  )
  16  
  17  // The Permissions type holds fine-grained permissions that are
  18  // specific to a user or a specific authentication method for a user.
  19  // The Permissions value for a successful authentication attempt is
  20  // available in ServerConn, so it can be used to pass information from
  21  // the user-authentication phase to the application layer.
  22  type Permissions struct {
  23  	// CriticalOptions indicate restrictions to the default
  24  	// permissions, and are typically used in conjunction with
  25  	// user certificates. The standard for SSH certificates
  26  	// defines "force-command" (only allow the given command to
  27  	// execute) and "source-address" (only allow connections from
  28  	// the given address). The SSH package currently only enforces
  29  	// the "source-address" critical option. It is up to server
  30  	// implementations to enforce other critical options, such as
  31  	// "force-command", by checking them after the SSH handshake
  32  	// is successful. In general, SSH servers should reject
  33  	// connections that specify critical options that are unknown
  34  	// or not supported.
  35  	CriticalOptions map[string]string
  36  
  37  	// Extensions are extra functionality that the server may
  38  	// offer on authenticated connections. Lack of support for an
  39  	// extension does not preclude authenticating a user. Common
  40  	// extensions are "permit-agent-forwarding",
  41  	// "permit-X11-forwarding". The Go SSH library currently does
  42  	// not act on any extension, and it is up to server
  43  	// implementations to honor them. Extensions can be used to
  44  	// pass data from the authentication callbacks to the server
  45  	// application layer.
  46  	Extensions map[string]string
  47  
  48  	// ExtraData allows to store user defined data.
  49  	ExtraData map[any]any
  50  }
  51  
  52  type GSSAPIWithMICConfig struct {
  53  	// AllowLogin, must be set, is called when gssapi-with-mic
  54  	// authentication is selected (RFC 4462 section 3). The srcName is from the
  55  	// results of the GSS-API authentication. The format is username@DOMAIN.
  56  	// GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions.
  57  	// This callback is called after the user identity is established with GSSAPI to decide if the user can login with
  58  	// which permissions. If the user is allowed to login, it should return a nil error.
  59  	AllowLogin func(conn ConnMetadata, srcName string) (*Permissions, error)
  60  
  61  	// Server must be set. It's the implementation
  62  	// of the GSSAPIServer interface. See GSSAPIServer interface for details.
  63  	Server GSSAPIServer
  64  }
  65  
  66  // SendAuthBanner implements [ServerPreAuthConn].
  67  func (s *connection) SendAuthBanner(msg string) error {
  68  	return s.transport.writePacket(Marshal(&userAuthBannerMsg{
  69  		Message: msg,
  70  	}))
  71  }
  72  
  73  func (*connection) unexportedMethodForFutureProofing() {}
  74  
  75  // ServerPreAuthConn is the interface available on an incoming server
  76  // connection before authentication has completed.
  77  type ServerPreAuthConn interface {
  78  	unexportedMethodForFutureProofing() // permits growing ServerPreAuthConn safely later, ala testing.TB
  79  
  80  	ConnMetadata
  81  
  82  	// SendAuthBanner sends a banner message to the client.
  83  	// It returns an error once the authentication phase has ended.
  84  	SendAuthBanner(string) error
  85  }
  86  
  87  // ServerConfig holds server specific configuration data.
  88  type ServerConfig struct {
  89  	// Config contains configuration shared between client and server.
  90  	Config
  91  
  92  	// PublicKeyAuthAlgorithms specifies the supported client public key
  93  	// authentication algorithms. Note that this should not include certificate
  94  	// types since those use the underlying algorithm. This list is sent to the
  95  	// client if it supports the server-sig-algs extension. Order is irrelevant.
  96  	// If unspecified then a default set of algorithms is used.
  97  	PublicKeyAuthAlgorithms []string
  98  
  99  	hostKeys []Signer
 100  
 101  	// NoClientAuth is true if clients are allowed to connect without
 102  	// authenticating.
 103  	// To determine NoClientAuth at runtime, set NoClientAuth to true
 104  	// and the optional NoClientAuthCallback to a non-nil value.
 105  	NoClientAuth bool
 106  
 107  	// NoClientAuthCallback, if non-nil, is called when a user
 108  	// attempts to authenticate with auth method "none".
 109  	// NoClientAuth must also be set to true for this be used, or
 110  	// this func is unused.
 111  	NoClientAuthCallback func(ConnMetadata) (*Permissions, error)
 112  
 113  	// MaxAuthTries specifies the maximum number of authentication attempts
 114  	// permitted per connection. If set to a negative number, the number of
 115  	// attempts are unlimited. If set to zero, the number of attempts are limited
 116  	// to 6.
 117  	MaxAuthTries int
 118  
 119  	// PasswordCallback, if non-nil, is called when a user
 120  	// attempts to authenticate using a password.
 121  	PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
 122  
 123  	// PublicKeyCallback, if non-nil, is called when a client
 124  	// offers a public key for authentication. It must return a nil error
 125  	// if the given public key can be used to authenticate the
 126  	// given user. For example, see CertChecker.Authenticate. A
 127  	// call to this function does not guarantee that the key
 128  	// offered is in fact used to authenticate. To record any data
 129  	// depending on the public key, store it inside a
 130  	// Permissions.Extensions entry.
 131  	PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
 132  
 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  
 148  	// KeyboardInteractiveCallback, if non-nil, is called when
 149  	// keyboard-interactive authentication is selected (RFC
 150  	// 4256). The client object's Challenge function should be
 151  	// used to query the user. The callback may offer multiple
 152  	// Challenge rounds. To avoid information leaks, the client
 153  	// should be presented a challenge even if the user is
 154  	// unknown.
 155  	KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
 156  
 157  	// AuthLogCallback, if non-nil, is called to log all authentication
 158  	// attempts.
 159  	AuthLogCallback func(conn ConnMetadata, method string, err error)
 160  
 161  	// PreAuthConnCallback, if non-nil, is called upon receiving a new connection
 162  	// before any authentication has started. The provided ServerPreAuthConn
 163  	// can be used at any time before authentication is complete, including
 164  	// after this callback has returned.
 165  	PreAuthConnCallback func(ServerPreAuthConn)
 166  
 167  	// ServerVersion is the version identification string to announce in
 168  	// the public handshake.
 169  	// If empty, a reasonable default is used.
 170  	// Note that RFC 4253 section 4.2 requires that this string start with
 171  	// "SSH-2.0-".
 172  	ServerVersion string
 173  
 174  	// BannerCallback, if present, is called and the return string is sent to
 175  	// the client after key exchange completed but before authentication.
 176  	BannerCallback func(conn ConnMetadata) string
 177  
 178  	// GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used
 179  	// when gssapi-with-mic authentication is selected (RFC 4462 section 3).
 180  	GSSAPIWithMICConfig *GSSAPIWithMICConfig
 181  }
 182  
 183  // AddHostKey adds a private key as a host key. If an existing host
 184  // key exists with the same public key format, it is replaced. Each server
 185  // config must have at least one host key.
 186  func (s *ServerConfig) AddHostKey(key Signer) {
 187  	for i, k := range s.hostKeys {
 188  		if k.PublicKey().Type() == key.PublicKey().Type() {
 189  			s.hostKeys[i] = key
 190  			return
 191  		}
 192  	}
 193  
 194  	s.hostKeys = append(s.hostKeys, key)
 195  }
 196  
 197  // cachedPubKey contains the results of querying whether a public key is
 198  // acceptable for a user. This is a FIFO cache.
 199  type cachedPubKey struct {
 200  	user       string
 201  	pubKeyData []byte
 202  	result     error
 203  	perms      *Permissions
 204  }
 205  
 206  // maxCachedPubKeys is the number of cache entries we store.
 207  //
 208  // Due to consistent misuse of the PublicKeyCallback API, we have reduced this
 209  // to 1, such that the only key in the cache is the most recently seen one. This
 210  // forces the behavior that the last call to PublicKeyCallback will always be
 211  // with the key that is used for authentication.
 212  const maxCachedPubKeys = 1
 213  
 214  // pubKeyCache caches tests for public keys.  Since SSH clients
 215  // will query whether a public key is acceptable before attempting to
 216  // authenticate with it, we end up with duplicate queries for public
 217  // key validity.  The cache only applies to a single ServerConn.
 218  type pubKeyCache struct {
 219  	keys []cachedPubKey
 220  }
 221  
 222  // get returns the result for a given user/algo/key tuple.
 223  func (c *pubKeyCache) get(user string, pubKeyData []byte) (cachedPubKey, bool) {
 224  	for _, k := range c.keys {
 225  		if k.user == user && bytes.Equal(k.pubKeyData, pubKeyData) {
 226  			return k, true
 227  		}
 228  	}
 229  	return cachedPubKey{}, false
 230  }
 231  
 232  // add adds the given tuple to the cache.
 233  func (c *pubKeyCache) add(candidate cachedPubKey) {
 234  	if len(c.keys) >= maxCachedPubKeys {
 235  		c.keys = c.keys[1:]
 236  	}
 237  	c.keys = append(c.keys, candidate)
 238  }
 239  
 240  // ServerConn is an authenticated SSH connection, as seen from the
 241  // server
 242  type ServerConn struct {
 243  	Conn
 244  
 245  	// If the succeeding authentication callback returned a
 246  	// non-nil Permissions pointer, it is stored here.
 247  	Permissions *Permissions
 248  }
 249  
 250  // NewServerConn starts a new SSH server with c as the underlying
 251  // transport.  It starts with a handshake and, if the handshake is
 252  // unsuccessful, it closes the connection and returns an error.  The
 253  // Request and NewChannel channels must be serviced, or the connection
 254  // will hang.
 255  //
 256  // The returned error may be of type *ServerAuthError for
 257  // authentication errors.
 258  func NewServerConn(c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error) {
 259  	fullConf := *config
 260  	fullConf.SetDefaults()
 261  	if fullConf.MaxAuthTries == 0 {
 262  		fullConf.MaxAuthTries = 6
 263  	}
 264  	if len(fullConf.PublicKeyAuthAlgorithms) == 0 {
 265  		fullConf.PublicKeyAuthAlgorithms = defaultPubKeyAuthAlgos
 266  	} else {
 267  		for _, algo := range fullConf.PublicKeyAuthAlgorithms {
 268  			if !slices.Contains(SupportedAlgorithms().PublicKeyAuths, algo) && !slices.Contains(InsecureAlgorithms().PublicKeyAuths, algo) {
 269  				c.Close()
 270  				return nil, nil, nil, fmt.Errorf("ssh: unsupported public key authentication algorithm %s", algo)
 271  			}
 272  		}
 273  	}
 274  
 275  	s := &connection{
 276  		sshConn: sshConn{conn: c},
 277  	}
 278  	perms, err := s.serverHandshake(&fullConf)
 279  	if err != nil {
 280  		c.Close()
 281  		return nil, nil, nil, err
 282  	}
 283  	return &ServerConn{s, perms}, s.mux.incomingChannels, s.mux.incomingRequests, nil
 284  }
 285  
 286  // signAndMarshal signs the data with the appropriate algorithm,
 287  // and serializes the result in SSH wire format. algo is the negotiate
 288  // algorithm and may be a certificate type.
 289  func signAndMarshal(k AlgorithmSigner, rand io.Reader, data []byte, algo string) ([]byte, error) {
 290  	sig, err := k.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
 291  	if err != nil {
 292  		return nil, err
 293  	}
 294  
 295  	return Marshal(sig), nil
 296  }
 297  
 298  // handshake performs key exchange and user authentication.
 299  func (s *connection) serverHandshake(config *ServerConfig) (*Permissions, error) {
 300  	if len(config.hostKeys) == 0 {
 301  		return nil, errors.New("ssh: server has no host keys")
 302  	}
 303  
 304  	if !config.NoClientAuth && config.PasswordCallback == nil && config.PublicKeyCallback == nil &&
 305  		config.KeyboardInteractiveCallback == nil && (config.GSSAPIWithMICConfig == nil ||
 306  		config.GSSAPIWithMICConfig.AllowLogin == nil || config.GSSAPIWithMICConfig.Server == nil) {
 307  		return nil, errors.New("ssh: no authentication methods configured but NoClientAuth is also false")
 308  	}
 309  
 310  	if config.ServerVersion != "" {
 311  		s.serverVersion = []byte(config.ServerVersion)
 312  	} else {
 313  		s.serverVersion = []byte(packageVersion)
 314  	}
 315  	var err error
 316  	s.clientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
 317  	if err != nil {
 318  		return nil, err
 319  	}
 320  
 321  	tr := newTransport(s.sshConn.conn, config.Rand, false /* not client */)
 322  	s.transport = newServerTransport(tr, s.clientVersion, s.serverVersion, config)
 323  
 324  	if err := s.transport.waitSession(); err != nil {
 325  		return nil, err
 326  	}
 327  
 328  	// We just did the key change, so the session ID is established.
 329  	s.sessionID = s.transport.getSessionID()
 330  	s.algorithms = s.transport.getAlgorithms()
 331  
 332  	var packet []byte
 333  	if packet, err = s.transport.readPacket(); err != nil {
 334  		return nil, err
 335  	}
 336  
 337  	var serviceRequest serviceRequestMsg
 338  	if err = Unmarshal(packet, &serviceRequest); err != nil {
 339  		return nil, err
 340  	}
 341  	if serviceRequest.Service != serviceUserAuth {
 342  		return nil, errors.New("ssh: requested service '" + serviceRequest.Service + "' before authenticating")
 343  	}
 344  	serviceAccept := serviceAcceptMsg{
 345  		Service: serviceUserAuth,
 346  	}
 347  	if err := s.transport.writePacket(Marshal(&serviceAccept)); err != nil {
 348  		return nil, err
 349  	}
 350  
 351  	perms, err := s.serverAuthenticate(config)
 352  	if err != nil {
 353  		return nil, err
 354  	}
 355  	s.mux = newMux(s.transport)
 356  	return perms, err
 357  }
 358  
 359  func checkSourceAddress(addr net.Addr, sourceAddrs string) error {
 360  	if addr == nil {
 361  		return errors.New("ssh: no address known for client, but source-address match required")
 362  	}
 363  
 364  	tcpAddr, ok := addr.(*net.TCPAddr)
 365  	if !ok {
 366  		return fmt.Errorf("ssh: remote address %v is not an TCP address when checking source-address match", addr)
 367  	}
 368  
 369  	for _, sourceAddr := range strings.Split(sourceAddrs, ",") {
 370  		if allowedIP := net.ParseIP(sourceAddr); allowedIP != nil {
 371  			if allowedIP.Equal(tcpAddr.IP) {
 372  				return nil
 373  			}
 374  		} else {
 375  			_, ipNet, err := net.ParseCIDR(sourceAddr)
 376  			if err != nil {
 377  				return fmt.Errorf("ssh: error parsing source-address restriction %q: %v", sourceAddr, err)
 378  			}
 379  
 380  			if ipNet.Contains(tcpAddr.IP) {
 381  				return nil
 382  			}
 383  		}
 384  	}
 385  
 386  	return fmt.Errorf("ssh: remote address %v is not allowed because of source-address restriction", addr)
 387  }
 388  
 389  func gssExchangeToken(gssapiConfig *GSSAPIWithMICConfig, token []byte, s *connection,
 390  	sessionID []byte, userAuthReq userAuthRequestMsg) (authErr error, perms *Permissions, err error) {
 391  	gssAPIServer := gssapiConfig.Server
 392  	defer gssAPIServer.DeleteSecContext()
 393  	var srcName string
 394  	for {
 395  		var (
 396  			outToken     []byte
 397  			needContinue bool
 398  		)
 399  		outToken, srcName, needContinue, err = gssAPIServer.AcceptSecContext(token)
 400  		if err != nil {
 401  			return err, nil, nil
 402  		}
 403  		if len(outToken) != 0 {
 404  			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIToken{
 405  				Token: outToken,
 406  			})); err != nil {
 407  				return nil, nil, err
 408  			}
 409  		}
 410  		if !needContinue {
 411  			break
 412  		}
 413  		packet, err := s.transport.readPacket()
 414  		if err != nil {
 415  			return nil, nil, err
 416  		}
 417  		userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
 418  		if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
 419  			return nil, nil, err
 420  		}
 421  		token = userAuthGSSAPITokenReq.Token
 422  	}
 423  	packet, err := s.transport.readPacket()
 424  	if err != nil {
 425  		return nil, nil, err
 426  	}
 427  	userAuthGSSAPIMICReq := &userAuthGSSAPIMIC{}
 428  	if err := Unmarshal(packet, userAuthGSSAPIMICReq); err != nil {
 429  		return nil, nil, err
 430  	}
 431  	mic := buildMIC(string(sessionID), userAuthReq.User, userAuthReq.Service, userAuthReq.Method)
 432  	if err := gssAPIServer.VerifyMIC(mic, userAuthGSSAPIMICReq.MIC); err != nil {
 433  		return err, nil, nil
 434  	}
 435  	perms, authErr = gssapiConfig.AllowLogin(s, srcName)
 436  	return authErr, perms, nil
 437  }
 438  
 439  // isAlgoCompatible checks if the signature format is compatible with the
 440  // selected algorithm taking into account edge cases that occur with old
 441  // clients.
 442  func isAlgoCompatible(algo, sigFormat string) bool {
 443  	// Compatibility for old clients.
 444  	//
 445  	// For certificate authentication with OpenSSH 7.2-7.7 signature format can
 446  	// be rsa-sha2-256 or rsa-sha2-512 for the algorithm
 447  	// ssh-rsa-cert-v01@openssh.com.
 448  	//
 449  	// With gpg-agent < 2.2.6 the algorithm can be rsa-sha2-256 or rsa-sha2-512
 450  	// for signature format ssh-rsa.
 451  	if isRSA(algo) && isRSA(sigFormat) {
 452  		return true
 453  	}
 454  	// Standard case: the underlying algorithm must match the signature format.
 455  	return underlyingAlgo(algo) == sigFormat
 456  }
 457  
 458  // ServerAuthError represents server authentication errors and is
 459  // sometimes returned by NewServerConn. It appends any authentication
 460  // errors that may occur, and is returned if all of the authentication
 461  // methods provided by the user failed to authenticate.
 462  type ServerAuthError struct {
 463  	// Errors contains authentication errors returned by the authentication
 464  	// callback methods. The first entry is typically ErrNoAuth.
 465  	Errors []error
 466  }
 467  
 468  func (l ServerAuthError) Error() string {
 469  	var errs []string
 470  	for _, err := range l.Errors {
 471  		errs = append(errs, err.Error())
 472  	}
 473  	return "[" + strings.Join(errs, ", ") + "]"
 474  }
 475  
 476  // ServerAuthCallbacks defines server-side authentication callbacks.
 477  type ServerAuthCallbacks struct {
 478  	// PasswordCallback behaves like [ServerConfig.PasswordCallback].
 479  	PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)
 480  
 481  	// PublicKeyCallback behaves like [ServerConfig.PublicKeyCallback].
 482  	PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)
 483  
 484  	// KeyboardInteractiveCallback behaves like [ServerConfig.KeyboardInteractiveCallback].
 485  	KeyboardInteractiveCallback func(conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)
 486  
 487  	// GSSAPIWithMICConfig behaves like [ServerConfig.GSSAPIWithMICConfig].
 488  	GSSAPIWithMICConfig *GSSAPIWithMICConfig
 489  }
 490  
 491  // PartialSuccessError can be returned by any of the [ServerConfig]
 492  // authentication callbacks to indicate to the client that authentication has
 493  // partially succeeded, but further steps are required.
 494  type PartialSuccessError struct {
 495  	// Next defines the authentication callbacks to apply to further steps. The
 496  	// available methods communicated to the client are based on the non-nil
 497  	// ServerAuthCallbacks fields.
 498  	Next ServerAuthCallbacks
 499  }
 500  
 501  func (p *PartialSuccessError) Error() string {
 502  	return "ssh: authenticated with partial success"
 503  }
 504  
 505  // ErrNoAuth is the error value returned if no
 506  // authentication method has been passed yet. This happens as a normal
 507  // part of the authentication loop, since the client first tries
 508  // 'none' authentication to discover available methods.
 509  // It is returned in ServerAuthError.Errors from NewServerConn.
 510  var ErrNoAuth = errors.New("ssh: no auth passed yet")
 511  
 512  // BannerError is an error that can be returned by authentication handlers in
 513  // ServerConfig to send a banner message to the client.
 514  type BannerError struct {
 515  	Err     error
 516  	Message string
 517  }
 518  
 519  func (b *BannerError) Unwrap() error {
 520  	return b.Err
 521  }
 522  
 523  func (b *BannerError) Error() string {
 524  	if b.Err == nil {
 525  		return b.Message
 526  	}
 527  	return b.Err.Error()
 528  }
 529  
 530  func (s *connection) serverAuthenticate(config *ServerConfig) (*Permissions, error) {
 531  	if config.PreAuthConnCallback != nil {
 532  		config.PreAuthConnCallback(s)
 533  	}
 534  
 535  	sessionID := s.transport.getSessionID()
 536  	var cache pubKeyCache
 537  	var perms *Permissions
 538  
 539  	authFailures := 0
 540  	noneAuthCount := 0
 541  	var authErrs []error
 542  	var calledBannerCallback bool
 543  	partialSuccessReturned := false
 544  	// Set the initial authentication callbacks from the config. They can be
 545  	// changed if a PartialSuccessError is returned.
 546  	authConfig := ServerAuthCallbacks{
 547  		PasswordCallback:            config.PasswordCallback,
 548  		PublicKeyCallback:           config.PublicKeyCallback,
 549  		KeyboardInteractiveCallback: config.KeyboardInteractiveCallback,
 550  		GSSAPIWithMICConfig:         config.GSSAPIWithMICConfig,
 551  	}
 552  
 553  userAuthLoop:
 554  	for {
 555  		if authFailures >= config.MaxAuthTries && config.MaxAuthTries > 0 {
 556  			discMsg := &disconnectMsg{
 557  				Reason:  2,
 558  				Message: "too many authentication failures",
 559  			}
 560  
 561  			if err := s.transport.writePacket(Marshal(discMsg)); err != nil {
 562  				return nil, err
 563  			}
 564  			authErrs = append(authErrs, discMsg)
 565  			return nil, &ServerAuthError{Errors: authErrs}
 566  		}
 567  
 568  		var userAuthReq userAuthRequestMsg
 569  		if packet, err := s.transport.readPacket(); err != nil {
 570  			if err == io.EOF {
 571  				return nil, &ServerAuthError{Errors: authErrs}
 572  			}
 573  			return nil, err
 574  		} else if err = Unmarshal(packet, &userAuthReq); err != nil {
 575  			return nil, err
 576  		}
 577  
 578  		if userAuthReq.Service != serviceSSH {
 579  			return nil, errors.New("ssh: client attempted to negotiate for unknown service: " + userAuthReq.Service)
 580  		}
 581  
 582  		if s.user != userAuthReq.User && partialSuccessReturned {
 583  			return nil, fmt.Errorf("ssh: client changed the user after a partial success authentication, previous user %q, current user %q",
 584  				s.user, userAuthReq.User)
 585  		}
 586  
 587  		s.user = userAuthReq.User
 588  
 589  		if !calledBannerCallback && config.BannerCallback != nil {
 590  			calledBannerCallback = true
 591  			if msg := config.BannerCallback(s); msg != "" {
 592  				if err := s.SendAuthBanner(msg); err != nil {
 593  					return nil, err
 594  				}
 595  			}
 596  		}
 597  
 598  		perms = nil
 599  		authErr := ErrNoAuth
 600  
 601  		switch userAuthReq.Method {
 602  		case "none":
 603  			noneAuthCount++
 604  			// We don't allow none authentication after a partial success
 605  			// response.
 606  			if config.NoClientAuth && !partialSuccessReturned {
 607  				if config.NoClientAuthCallback != nil {
 608  					perms, authErr = config.NoClientAuthCallback(s)
 609  				} else {
 610  					authErr = nil
 611  				}
 612  			}
 613  		case "password":
 614  			if authConfig.PasswordCallback == nil {
 615  				authErr = errors.New("ssh: password auth not configured")
 616  				break
 617  			}
 618  			payload := userAuthReq.Payload
 619  			if len(payload) < 1 || payload[0] != 0 {
 620  				return nil, parseError(msgUserAuthRequest)
 621  			}
 622  			payload = payload[1:]
 623  			password, payload, ok := parseString(payload)
 624  			if !ok || len(payload) > 0 {
 625  				return nil, parseError(msgUserAuthRequest)
 626  			}
 627  
 628  			perms, authErr = authConfig.PasswordCallback(s, password)
 629  		case "keyboard-interactive":
 630  			if authConfig.KeyboardInteractiveCallback == nil {
 631  				authErr = errors.New("ssh: keyboard-interactive auth not configured")
 632  				break
 633  			}
 634  
 635  			prompter := &sshClientKeyboardInteractive{s}
 636  			perms, authErr = authConfig.KeyboardInteractiveCallback(s, prompter.Challenge)
 637  		case "publickey":
 638  			if authConfig.PublicKeyCallback == nil {
 639  				authErr = errors.New("ssh: publickey auth not configured")
 640  				break
 641  			}
 642  			payload := userAuthReq.Payload
 643  			if len(payload) < 1 {
 644  				return nil, parseError(msgUserAuthRequest)
 645  			}
 646  			isQuery := payload[0] == 0
 647  			payload = payload[1:]
 648  			algoBytes, payload, ok := parseString(payload)
 649  			if !ok {
 650  				return nil, parseError(msgUserAuthRequest)
 651  			}
 652  			algo := string(algoBytes)
 653  			if !slices.Contains(config.PublicKeyAuthAlgorithms, underlyingAlgo(algo)) {
 654  				authErr = fmt.Errorf("ssh: algorithm %q not accepted", algo)
 655  				break
 656  			}
 657  
 658  			pubKeyData, payload, ok := parseString(payload)
 659  			if !ok {
 660  				return nil, parseError(msgUserAuthRequest)
 661  			}
 662  
 663  			pubKey, err := ParsePublicKey(pubKeyData)
 664  			if err != nil {
 665  				return nil, err
 666  			}
 667  
 668  			candidate, ok := cache.get(s.user, pubKeyData)
 669  			if !ok {
 670  				candidate.user = s.user
 671  				candidate.pubKeyData = pubKeyData
 672  				candidate.perms, candidate.result = authConfig.PublicKeyCallback(s, pubKey)
 673  				_, 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  				}
 677  
 678  				if (candidate.result == nil || isPartialSuccessError) &&
 679  					candidate.perms != nil &&
 680  					candidate.perms.CriticalOptions != nil &&
 681  					candidate.perms.CriticalOptions[sourceAddressCriticalOption] != "" {
 682  					if err := checkSourceAddress(
 683  						s.RemoteAddr(),
 684  						candidate.perms.CriticalOptions[sourceAddressCriticalOption]); err != nil {
 685  						candidate.result = err
 686  					}
 687  				}
 688  				cache.add(candidate)
 689  			}
 690  
 691  			if isQuery {
 692  				// The client can query if the given public key
 693  				// would be okay.
 694  
 695  				if len(payload) > 0 {
 696  					return nil, parseError(msgUserAuthRequest)
 697  				}
 698  				_, isPartialSuccessError := candidate.result.(*PartialSuccessError)
 699  				if candidate.result == nil || isPartialSuccessError {
 700  					okMsg := userAuthPubKeyOkMsg{
 701  						Algo:   algo,
 702  						PubKey: pubKeyData,
 703  					}
 704  					if err = s.transport.writePacket(Marshal(&okMsg)); err != nil {
 705  						return nil, err
 706  					}
 707  					continue userAuthLoop
 708  				}
 709  				authErr = candidate.result
 710  			} else {
 711  				sig, payload, ok := parseSignature(payload)
 712  				if !ok || len(payload) > 0 {
 713  					return nil, parseError(msgUserAuthRequest)
 714  				}
 715  				// Ensure the declared public key algo is compatible with the
 716  				// decoded one. This check will ensure we don't accept e.g.
 717  				// ssh-rsa-cert-v01@openssh.com algorithm with ssh-rsa public
 718  				// key type. The algorithm and public key type must be
 719  				// consistent: both must be certificate algorithms, or neither.
 720  				if !slices.Contains(algorithmsForKeyFormat(pubKey.Type()), algo) {
 721  					authErr = fmt.Errorf("ssh: public key type %q not compatible with selected algorithm %q",
 722  						pubKey.Type(), algo)
 723  					break
 724  				}
 725  				// Ensure the public key algo and signature algo
 726  				// are supported.  Compare the private key
 727  				// algorithm name that corresponds to algo with
 728  				// sig.Format.  This is usually the same, but
 729  				// for certs, the names differ.
 730  				if !slices.Contains(config.PublicKeyAuthAlgorithms, sig.Format) {
 731  					authErr = fmt.Errorf("ssh: algorithm %q not accepted", sig.Format)
 732  					break
 733  				}
 734  				if !isAlgoCompatible(algo, sig.Format) {
 735  					authErr = fmt.Errorf("ssh: signature %q not compatible with selected algorithm %q", sig.Format, algo)
 736  					break
 737  				}
 738  
 739  				signedData := buildDataSignedForAuth(sessionID, userAuthReq, algo, pubKeyData)
 740  
 741  				if err := pubKey.Verify(signedData, sig); err != nil {
 742  					return nil, err
 743  				}
 744  
 745  				authErr = candidate.result
 746  				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  				}
 753  			}
 754  		case "gssapi-with-mic":
 755  			if authConfig.GSSAPIWithMICConfig == nil {
 756  				authErr = errors.New("ssh: gssapi-with-mic auth not configured")
 757  				break
 758  			}
 759  			gssapiConfig := authConfig.GSSAPIWithMICConfig
 760  			userAuthRequestGSSAPI, err := parseGSSAPIPayload(userAuthReq.Payload)
 761  			if err != nil {
 762  				return nil, parseError(msgUserAuthRequest)
 763  			}
 764  			// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication.
 765  			if userAuthRequestGSSAPI.N == 0 {
 766  				authErr = fmt.Errorf("ssh: Mechanism negotiation is not supported")
 767  				break
 768  			}
 769  			var i uint32
 770  			present := false
 771  			for i = 0; i < userAuthRequestGSSAPI.N; i++ {
 772  				if userAuthRequestGSSAPI.OIDS[i].Equal(krb5Mesh) {
 773  					present = true
 774  					break
 775  				}
 776  			}
 777  			if !present {
 778  				authErr = fmt.Errorf("ssh: GSSAPI authentication must use the Kerberos V5 mechanism")
 779  				break
 780  			}
 781  			// Initial server response, see RFC 4462 section 3.3.
 782  			if err := s.transport.writePacket(Marshal(&userAuthGSSAPIResponse{
 783  				SupportMech: krb5OID,
 784  			})); err != nil {
 785  				return nil, err
 786  			}
 787  			// Exchange token, see RFC 4462 section 3.4.
 788  			packet, err := s.transport.readPacket()
 789  			if err != nil {
 790  				return nil, err
 791  			}
 792  			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
 793  			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
 794  				return nil, err
 795  			}
 796  			authErr, perms, err = gssExchangeToken(gssapiConfig, userAuthGSSAPITokenReq.Token, s, sessionID,
 797  				userAuthReq)
 798  			if err != nil {
 799  				return nil, err
 800  			}
 801  		default:
 802  			authErr = fmt.Errorf("ssh: unknown method %q", userAuthReq.Method)
 803  		}
 804  
 805  		authErrs = append(authErrs, authErr)
 806  
 807  		if config.AuthLogCallback != nil {
 808  			config.AuthLogCallback(s, userAuthReq.Method, authErr)
 809  		}
 810  
 811  		var bannerErr *BannerError
 812  		if errors.As(authErr, &bannerErr) {
 813  			if bannerErr.Message != "" {
 814  				if err := s.SendAuthBanner(bannerErr.Message); err != nil {
 815  					return nil, err
 816  				}
 817  			}
 818  		}
 819  
 820  		if authErr == nil {
 821  			break userAuthLoop
 822  		}
 823  
 824  		var failureMsg userAuthFailureMsg
 825  
 826  		if partialSuccess, ok := authErr.(*PartialSuccessError); ok {
 827  			// After a partial success error we don't allow changing the user
 828  			// name and execute the NoClientAuthCallback.
 829  			partialSuccessReturned = true
 830  
 831  			// In case a partial success is returned, the server may send
 832  			// a new set of authentication methods.
 833  			authConfig = partialSuccess.Next
 834  
 835  			// Reset pubkey cache, as the new PublicKeyCallback might
 836  			// accept a different set of public keys.
 837  			cache = pubKeyCache{}
 838  
 839  			// Send back a partial success message to the user.
 840  			failureMsg.PartialSuccess = true
 841  		} else {
 842  			// Allow initial attempt of 'none' without penalty.
 843  			if authFailures > 0 || userAuthReq.Method != "none" || noneAuthCount != 1 {
 844  				authFailures++
 845  			}
 846  			if config.MaxAuthTries > 0 && authFailures >= config.MaxAuthTries {
 847  				// If we have hit the max attempts, don't bother sending the
 848  				// final SSH_MSG_USERAUTH_FAILURE message, since there are
 849  				// no more authentication methods which can be attempted,
 850  				// and this message may cause the client to re-attempt
 851  				// authentication while we send the disconnect message.
 852  				// Continue, and trigger the disconnect at the start of
 853  				// the loop.
 854  				//
 855  				// The SSH specification is somewhat confusing about this,
 856  				// RFC 4252 Section 5.1 requires each authentication failure
 857  				// be responded to with a respective SSH_MSG_USERAUTH_FAILURE
 858  				// message, but Section 4 says the server should disconnect
 859  				// after some number of attempts, but it isn't explicit which
 860  				// message should take precedence (i.e. should there be a failure
 861  				// message than a disconnect message, or if we are going to
 862  				// disconnect, should we only send that message.)
 863  				//
 864  				// Either way, OpenSSH disconnects immediately after the last
 865  				// failed authentication attempt, and given they are typically
 866  				// considered the golden implementation it seems reasonable
 867  				// to match that behavior.
 868  				continue
 869  			}
 870  		}
 871  
 872  		if authConfig.PasswordCallback != nil {
 873  			failureMsg.Methods = append(failureMsg.Methods, "password")
 874  		}
 875  		if authConfig.PublicKeyCallback != nil {
 876  			failureMsg.Methods = append(failureMsg.Methods, "publickey")
 877  		}
 878  		if authConfig.KeyboardInteractiveCallback != nil {
 879  			failureMsg.Methods = append(failureMsg.Methods, "keyboard-interactive")
 880  		}
 881  		if authConfig.GSSAPIWithMICConfig != nil && authConfig.GSSAPIWithMICConfig.Server != nil &&
 882  			authConfig.GSSAPIWithMICConfig.AllowLogin != nil {
 883  			failureMsg.Methods = append(failureMsg.Methods, "gssapi-with-mic")
 884  		}
 885  
 886  		if len(failureMsg.Methods) == 0 {
 887  			return nil, errors.New("ssh: no authentication methods available")
 888  		}
 889  
 890  		if err := s.transport.writePacket(Marshal(&failureMsg)); err != nil {
 891  			return nil, err
 892  		}
 893  	}
 894  
 895  	if err := s.transport.writePacket([]byte{msgUserAuthSuccess}); err != nil {
 896  		return nil, err
 897  	}
 898  	return perms, nil
 899  }
 900  
 901  // sshClientKeyboardInteractive implements a ClientKeyboardInteractive by
 902  // asking the client on the other side of a ServerConn.
 903  type sshClientKeyboardInteractive struct {
 904  	*connection
 905  }
 906  
 907  func (c *sshClientKeyboardInteractive) Challenge(name, instruction string, questions []string, echos []bool) (answers []string, err error) {
 908  	if len(questions) != len(echos) {
 909  		return nil, errors.New("ssh: echos and questions must have equal length")
 910  	}
 911  
 912  	var prompts []byte
 913  	for i := range questions {
 914  		prompts = appendString(prompts, questions[i])
 915  		prompts = appendBool(prompts, echos[i])
 916  	}
 917  
 918  	if err := c.transport.writePacket(Marshal(&userAuthInfoRequestMsg{
 919  		Name:        name,
 920  		Instruction: instruction,
 921  		NumPrompts:  uint32(len(questions)),
 922  		Prompts:     prompts,
 923  	})); err != nil {
 924  		return nil, err
 925  	}
 926  
 927  	packet, err := c.transport.readPacket()
 928  	if err != nil {
 929  		return nil, err
 930  	}
 931  	if packet[0] != msgUserAuthInfoResponse {
 932  		return nil, unexpectedMessageError(msgUserAuthInfoResponse, packet[0])
 933  	}
 934  	packet = packet[1:]
 935  
 936  	n, packet, ok := parseUint32(packet)
 937  	if !ok || int(n) != len(questions) {
 938  		return nil, parseError(msgUserAuthInfoResponse)
 939  	}
 940  
 941  	for i := uint32(0); i < n; i++ {
 942  		ans, rest, ok := parseString(packet)
 943  		if !ok {
 944  			return nil, parseError(msgUserAuthInfoResponse)
 945  		}
 946  
 947  		answers = append(answers, string(ans))
 948  		packet = rest
 949  	}
 950  	if len(packet) != 0 {
 951  		return nil, errors.New("ssh: junk at end of message")
 952  	}
 953  
 954  	return answers, nil
 955  }
 956