// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ssh

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"strings"
)

type authResult int

const (
	authFailure authResult = iota
	authPartialSuccess
	authSuccess
)

// clientAuthenticate authenticates with the remote server. See RFC 4252.
func (c *connection) clientAuthenticate(config *ClientConfig) error {
	// initiate user auth session
	if err := c.transport.writePacket(Marshal(&serviceRequestMsg{serviceUserAuth})); err != nil {
		return err
	}
	packet, err := c.transport.readPacket()
	if err != nil {
		return err
	}
	// The server may choose to send a SSH_MSG_EXT_INFO at this point (if we
	// advertised willingness to receive one, which we always do) or not. See
	// RFC 8308, Section 2.4.
	extensions := make(map[string][]byte)
	if len(packet) > 0 && packet[0] == msgExtInfo {
		var extInfo extInfoMsg
		if err := Unmarshal(packet, &extInfo); err != nil {
			return err
		}
		payload := extInfo.Payload
		for i := uint32(0); i < extInfo.NumExtensions; i++ {
			name, rest, ok := parseString(payload)
			if !ok {
				return parseError(msgExtInfo)
			}
			value, rest, ok := parseString(rest)
			if !ok {
				return parseError(msgExtInfo)
			}
			extensions[string(name)] = value
			payload = rest
		}
		packet, err = c.transport.readPacket()
		if err != nil {
			return err
		}
	}
	var serviceAccept serviceAcceptMsg
	if err := Unmarshal(packet, &serviceAccept); err != nil {
		return err
	}

	// during the authentication phase the client first attempts the "none" method
	// then any untried methods suggested by the server.
	var tried []string
	var lastMethods []string

	sessionID := c.transport.getSessionID()
	for auth := AuthMethod(new(noneAuth)); auth != nil; {
		ok, methods, err := auth.auth(sessionID, config.User, c.transport, config.Rand, extensions)
		if err != nil {
			// We return the error later if there is no other method left to
			// try.
			ok = authFailure
		}
		if ok == authSuccess {
			// success
			return nil
		} else if ok == authFailure {
			if m := auth.method(); !contains(tried, m) {
				tried = append(tried, m)
			}
		}
		if methods == nil {
			methods = lastMethods
		}
		lastMethods = methods

		auth = nil

	findNext:
		for _, a := range config.Auth {
			candidateMethod := a.method()
			if contains(tried, candidateMethod) {
				continue
			}
			for _, meth := range methods {
				if meth == candidateMethod {
					auth = a
					break findNext
				}
			}
		}

		if auth == nil && err != nil {
			// We have an error and there are no other authentication methods to
			// try, so we return it.
			return err
		}
	}
	return fmt.Errorf("ssh: unable to authenticate, attempted methods %v, no supported methods remain", tried)
}

func contains(list []string, e string) bool {
	for _, s := range list {
		if s == e {
			return true
		}
	}
	return false
}

// An AuthMethod represents an instance of an RFC 4252 authentication method.
type AuthMethod interface {
	// auth authenticates user over transport t.
	// Returns true if authentication is successful.
	// If authentication is not successful, a []string of alternative
	// method names is returned. If the slice is nil, it will be ignored
	// and the previous set of possible methods will be reused.
	auth(session []byte, user string, p packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error)

	// method returns the RFC 4252 method name.
	method() string
}

// "none" authentication, RFC 4252 section 5.2.
type noneAuth int

func (n *noneAuth) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
	if err := c.writePacket(Marshal(&userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "none",
	})); err != nil {
		return authFailure, nil, err
	}

	return handleAuthResponse(c)
}

func (n *noneAuth) method() string {
	return "none"
}

// passwordCallback is an AuthMethod that fetches the password through
// a function call, e.g. by prompting the user.
type passwordCallback func() (password string, err error)

func (cb passwordCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
	type passwordAuthMsg struct {
		User     string `sshtype:"50"`
		Service  string
		Method   string
		Reply    bool
		Password string
	}

	pw, err := cb()
	// REVIEW NOTE: is there a need to support skipping a password attempt?
	// The program may only find out that the user doesn't have a password
	// when prompting.
	if err != nil {
		return authFailure, nil, err
	}

	if err := c.writePacket(Marshal(&passwordAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   cb.method(),
		Reply:    false,
		Password: pw,
	})); err != nil {
		return authFailure, nil, err
	}

	return handleAuthResponse(c)
}

func (cb passwordCallback) method() string {
	return "password"
}

// Password returns an AuthMethod using the given password.
func Password(secret string) AuthMethod {
	return passwordCallback(func() (string, error) { return secret, nil })
}

// PasswordCallback returns an AuthMethod that uses a callback for
// fetching a password.
func PasswordCallback(prompt func() (secret string, err error)) AuthMethod {
	return passwordCallback(prompt)
}

type publickeyAuthMsg struct {
	User    string `sshtype:"50"`
	Service string
	Method  string
	// HasSig indicates to the receiver packet that the auth request is signed and
	// should be used for authentication of the request.
	HasSig   bool
	Algoname string
	PubKey   []byte
	// Sig is tagged with "rest" so Marshal will exclude it during
	// validateKey
	Sig []byte `ssh:"rest"`
}

// publicKeyCallback is an AuthMethod that uses a set of key
// pairs for authentication.
type publicKeyCallback func() ([]Signer, error)

func (cb publicKeyCallback) method() string {
	return "publickey"
}

func pickSignatureAlgorithm(signer Signer, extensions map[string][]byte) (MultiAlgorithmSigner, string, error) {
	var as MultiAlgorithmSigner
	keyFormat := signer.PublicKey().Type()

	// If the signer implements MultiAlgorithmSigner we use the algorithms it
	// support, if it implements AlgorithmSigner we assume it supports all
	// algorithms, otherwise only the key format one.
	switch s := signer.(type) {
	case MultiAlgorithmSigner:
		as = s
	case AlgorithmSigner:
		as = &multiAlgorithmSigner{
			AlgorithmSigner:     s,
			supportedAlgorithms: algorithmsForKeyFormat(underlyingAlgo(keyFormat)),
		}
	default:
		as = &multiAlgorithmSigner{
			AlgorithmSigner:     algorithmSignerWrapper{signer},
			supportedAlgorithms: []string{underlyingAlgo(keyFormat)},
		}
	}

	getFallbackAlgo := func() (string, error) {
		// Fallback to use if there is no "server-sig-algs" extension or a
		// common algorithm cannot be found. We use the public key format if the
		// MultiAlgorithmSigner supports it, otherwise we return an error.
		if !contains(as.Algorithms(), underlyingAlgo(keyFormat)) {
			return "", fmt.Errorf("ssh: no common public key signature algorithm, server only supports %q for key type %q, signer only supports %v",
				underlyingAlgo(keyFormat), keyFormat, as.Algorithms())
		}
		return keyFormat, nil
	}

	extPayload, ok := extensions["server-sig-algs"]
	if !ok {
		// If there is no "server-sig-algs" extension use the fallback
		// algorithm.
		algo, err := getFallbackAlgo()
		return as, algo, err
	}

	// The server-sig-algs extension only carries underlying signature
	// algorithm, but we are trying to select a protocol-level public key
	// algorithm, which might be a certificate type. Extend the list of server
	// supported algorithms to include the corresponding certificate algorithms.
	serverAlgos := strings.Split(string(extPayload), ",")
	for _, algo := range serverAlgos {
		if certAlgo, ok := certificateAlgo(algo); ok {
			serverAlgos = append(serverAlgos, certAlgo)
		}
	}

	// Filter algorithms based on those supported by MultiAlgorithmSigner.
	var keyAlgos []string
	for _, algo := range algorithmsForKeyFormat(keyFormat) {
		if contains(as.Algorithms(), underlyingAlgo(algo)) {
			keyAlgos = append(keyAlgos, algo)
		}
	}

	algo, err := findCommon("public key signature algorithm", keyAlgos, serverAlgos)
	if err != nil {
		// If there is no overlap, return the fallback algorithm to support
		// servers that fail to list all supported algorithms.
		algo, err := getFallbackAlgo()
		return as, algo, err
	}
	return as, algo, nil
}

func (cb publicKeyCallback) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (authResult, []string, error) {
	// Authentication is performed by sending an enquiry to test if a key is
	// acceptable to the remote. If the key is acceptable, the client will
	// attempt to authenticate with the valid key.  If not the client will repeat
	// the process with the remaining keys.

	signers, err := cb()
	if err != nil {
		return authFailure, nil, err
	}
	var methods []string
	var errSigAlgo error

	origSignersLen := len(signers)
	for idx := 0; idx < len(signers); idx++ {
		signer := signers[idx]
		pub := signer.PublicKey()
		as, algo, err := pickSignatureAlgorithm(signer, extensions)
		if err != nil && errSigAlgo == nil {
			// If we cannot negotiate a signature algorithm store the first
			// error so we can return it to provide a more meaningful message if
			// no other signers work.
			errSigAlgo = err
			continue
		}
		ok, err := validateKey(pub, algo, user, c)
		if err != nil {
			return authFailure, nil, err
		}
		// OpenSSH 7.2-7.7 advertises support for rsa-sha2-256 and rsa-sha2-512
		// in the "server-sig-algs" extension but doesn't support these
		// algorithms for certificate authentication, so if the server rejects
		// the key try to use the obtained algorithm as if "server-sig-algs" had
		// not been implemented if supported from the algorithm signer.
		if !ok && idx < origSignersLen && isRSACert(algo) && algo != CertAlgoRSAv01 {
			if contains(as.Algorithms(), KeyAlgoRSA) {
				// We retry using the compat algorithm after all signers have
				// been tried normally.
				signers = append(signers, &multiAlgorithmSigner{
					AlgorithmSigner:     as,
					supportedAlgorithms: []string{KeyAlgoRSA},
				})
			}
		}
		if !ok {
			continue
		}

		pubKey := pub.Marshal()
		data := buildDataSignedForAuth(session, userAuthRequestMsg{
			User:    user,
			Service: serviceSSH,
			Method:  cb.method(),
		}, algo, pubKey)
		sign, err := as.SignWithAlgorithm(rand, data, underlyingAlgo(algo))
		if err != nil {
			return authFailure, nil, err
		}

		// manually wrap the serialized signature in a string
		s := Marshal(sign)
		sig := make([]byte, stringLength(len(s)))
		marshalString(sig, s)
		msg := publickeyAuthMsg{
			User:     user,
			Service:  serviceSSH,
			Method:   cb.method(),
			HasSig:   true,
			Algoname: algo,
			PubKey:   pubKey,
			Sig:      sig,
		}
		p := Marshal(&msg)
		if err := c.writePacket(p); err != nil {
			return authFailure, nil, err
		}
		var success authResult
		success, methods, err = handleAuthResponse(c)
		if err != nil {
			return authFailure, nil, err
		}

		// If authentication succeeds or the list of available methods does not
		// contain the "publickey" method, do not attempt to authenticate with any
		// other keys.  According to RFC 4252 Section 7, the latter can occur when
		// additional authentication methods are required.
		if success == authSuccess || !contains(methods, cb.method()) {
			return success, methods, err
		}
	}

	return authFailure, methods, errSigAlgo
}

// validateKey validates the key provided is acceptable to the server.
func validateKey(key PublicKey, algo string, user string, c packetConn) (bool, error) {
	pubKey := key.Marshal()
	msg := publickeyAuthMsg{
		User:     user,
		Service:  serviceSSH,
		Method:   "publickey",
		HasSig:   false,
		Algoname: algo,
		PubKey:   pubKey,
	}
	if err := c.writePacket(Marshal(&msg)); err != nil {
		return false, err
	}

	return confirmKeyAck(key, algo, c)
}

func confirmKeyAck(key PublicKey, algo string, c packetConn) (bool, error) {
	pubKey := key.Marshal()

	for {
		packet, err := c.readPacket()
		if err != nil {
			return false, err
		}
		switch packet[0] {
		case msgUserAuthBanner:
			if err := handleBannerResponse(c, packet); err != nil {
				return false, err
			}
		case msgUserAuthPubKeyOk:
			var msg userAuthPubKeyOkMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return false, err
			}
			if msg.Algo != algo || !bytes.Equal(msg.PubKey, pubKey) {
				return false, nil
			}
			return true, nil
		case msgUserAuthFailure:
			return false, nil
		default:
			return false, unexpectedMessageError(msgUserAuthPubKeyOk, packet[0])
		}
	}
}

// PublicKeys returns an AuthMethod that uses the given key
// pairs.
func PublicKeys(signers ...Signer) AuthMethod {
	return publicKeyCallback(func() ([]Signer, error) { return signers, nil })
}

// PublicKeysCallback returns an AuthMethod that runs the given
// function to obtain a list of key pairs.
func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod {
	return publicKeyCallback(getSigners)
}

// handleAuthResponse returns whether the preceding authentication request succeeded
// along with a list of remaining authentication methods to try next and
// an error if an unexpected response was received.
func handleAuthResponse(c packetConn) (authResult, []string, error) {
	gotMsgExtInfo := false
	for {
		packet, err := c.readPacket()
		if err != nil {
			return authFailure, nil, err
		}

		switch packet[0] {
		case msgUserAuthBanner:
			if err := handleBannerResponse(c, packet); err != nil {
				return authFailure, nil, err
			}
		case msgExtInfo:
			// Ignore post-authentication RFC 8308 extensions, once.
			if gotMsgExtInfo {
				return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
			}
			gotMsgExtInfo = true
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return authFailure, nil, err
			}
			if msg.PartialSuccess {
				return authPartialSuccess, msg.Methods, nil
			}
			return authFailure, msg.Methods, nil
		case msgUserAuthSuccess:
			return authSuccess, nil, nil
		default:
			return authFailure, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
		}
	}
}

func handleBannerResponse(c packetConn, packet []byte) error {
	var msg userAuthBannerMsg
	if err := Unmarshal(packet, &msg); err != nil {
		return err
	}

	transport, ok := c.(*handshakeTransport)
	if !ok {
		return nil
	}

	if transport.bannerCallback != nil {
		return transport.bannerCallback(msg.Message)
	}

	return nil
}

// KeyboardInteractiveChallenge should print questions, optionally
// disabling echoing (e.g. for passwords), and return all the answers.
// Challenge may be called multiple times in a single session. After
// successful authentication, the server may send a challenge with no
// questions, for which the name and instruction messages should be
// printed.  RFC 4256 section 3.3 details how the UI should behave for
// both CLI and GUI environments.
type KeyboardInteractiveChallenge func(name, instruction string, questions []string, echos []bool) (answers []string, err error)

// KeyboardInteractive returns an AuthMethod using a prompt/response
// sequence controlled by the server.
func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod {
	return challenge
}

func (cb KeyboardInteractiveChallenge) method() string {
	return "keyboard-interactive"
}

func (cb KeyboardInteractiveChallenge) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
	type initiateMsg struct {
		User       string `sshtype:"50"`
		Service    string
		Method     string
		Language   string
		Submethods string
	}

	if err := c.writePacket(Marshal(&initiateMsg{
		User:    user,
		Service: serviceSSH,
		Method:  "keyboard-interactive",
	})); err != nil {
		return authFailure, nil, err
	}

	gotMsgExtInfo := false
	for {
		packet, err := c.readPacket()
		if err != nil {
			return authFailure, nil, err
		}

		// like handleAuthResponse, but with less options.
		switch packet[0] {
		case msgUserAuthBanner:
			if err := handleBannerResponse(c, packet); err != nil {
				return authFailure, nil, err
			}
			continue
		case msgExtInfo:
			// Ignore post-authentication RFC 8308 extensions, once.
			if gotMsgExtInfo {
				return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
			}
			gotMsgExtInfo = true
			continue
		case msgUserAuthInfoRequest:
			// OK
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return authFailure, nil, err
			}
			if msg.PartialSuccess {
				return authPartialSuccess, msg.Methods, nil
			}
			return authFailure, msg.Methods, nil
		case msgUserAuthSuccess:
			return authSuccess, nil, nil
		default:
			return authFailure, nil, unexpectedMessageError(msgUserAuthInfoRequest, packet[0])
		}

		var msg userAuthInfoRequestMsg
		if err := Unmarshal(packet, &msg); err != nil {
			return authFailure, nil, err
		}

		// Manually unpack the prompt/echo pairs.
		rest := msg.Prompts
		var prompts []string
		var echos []bool
		for i := 0; i < int(msg.NumPrompts); i++ {
			prompt, r, ok := parseString(rest)
			if !ok || len(r) == 0 {
				return authFailure, nil, errors.New("ssh: prompt format error")
			}
			prompts = append(prompts, string(prompt))
			echos = append(echos, r[0] != 0)
			rest = r[1:]
		}

		if len(rest) != 0 {
			return authFailure, nil, errors.New("ssh: extra data following keyboard-interactive pairs")
		}

		answers, err := cb(msg.Name, msg.Instruction, prompts, echos)
		if err != nil {
			return authFailure, nil, err
		}

		if len(answers) != len(prompts) {
			return authFailure, nil, fmt.Errorf("ssh: incorrect number of answers from keyboard-interactive callback %d (expected %d)", len(answers), len(prompts))
		}
		responseLength := 1 + 4
		for _, a := range answers {
			responseLength += stringLength(len(a))
		}
		serialized := make([]byte, responseLength)
		p := serialized
		p[0] = msgUserAuthInfoResponse
		p = p[1:]
		p = marshalUint32(p, uint32(len(answers)))
		for _, a := range answers {
			p = marshalString(p, []byte(a))
		}

		if err := c.writePacket(serialized); err != nil {
			return authFailure, nil, err
		}
	}
}

type retryableAuthMethod struct {
	authMethod AuthMethod
	maxTries   int
}

func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader, extensions map[string][]byte) (ok authResult, methods []string, err error) {
	for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
		ok, methods, err = r.authMethod.auth(session, user, c, rand, extensions)
		if ok != authFailure || err != nil { // either success, partial success or error terminate
			return ok, methods, err
		}
	}
	return ok, methods, err
}

func (r *retryableAuthMethod) method() string {
	return r.authMethod.method()
}

// RetryableAuthMethod is a decorator for other auth methods enabling them to
// be retried up to maxTries before considering that AuthMethod itself failed.
// If maxTries is <= 0, will retry indefinitely
//
// This is useful for interactive clients using challenge/response type
// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
// could mistype their response resulting in the server issuing a
// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
// [keyboard-interactive]); Without this decorator, the non-retryable
// AuthMethod would be removed from future consideration, and never tried again
// (and so the user would never be able to retry their entry).
func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
	return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}
}

// GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication.
// See RFC 4462 section 3
// gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details.
// target is the server host you want to log in to.
func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod {
	if gssAPIClient == nil {
		panic("gss-api client must be not nil with enable gssapi-with-mic")
	}
	return &gssAPIWithMICCallback{gssAPIClient: gssAPIClient, target: target}
}

type gssAPIWithMICCallback struct {
	gssAPIClient GSSAPIClient
	target       string
}

func (g *gssAPIWithMICCallback) auth(session []byte, user string, c packetConn, rand io.Reader, _ map[string][]byte) (authResult, []string, error) {
	m := &userAuthRequestMsg{
		User:    user,
		Service: serviceSSH,
		Method:  g.method(),
	}
	// The GSS-API authentication method is initiated when the client sends an SSH_MSG_USERAUTH_REQUEST.
	// See RFC 4462 section 3.2.
	m.Payload = appendU32(m.Payload, 1)
	m.Payload = appendString(m.Payload, string(krb5OID))
	if err := c.writePacket(Marshal(m)); err != nil {
		return authFailure, nil, err
	}
	// The server responds to the SSH_MSG_USERAUTH_REQUEST with either an
	// SSH_MSG_USERAUTH_FAILURE if none of the mechanisms are supported or
	// with an SSH_MSG_USERAUTH_GSSAPI_RESPONSE.
	// See RFC 4462 section 3.3.
	// OpenSSH supports Kerberos V5 mechanism only for GSS-API authentication,so I don't want to check
	// selected mech if it is valid.
	packet, err := c.readPacket()
	if err != nil {
		return authFailure, nil, err
	}
	userAuthGSSAPIResp := &userAuthGSSAPIResponse{}
	if err := Unmarshal(packet, userAuthGSSAPIResp); err != nil {
		return authFailure, nil, err
	}
	// Start the loop into the exchange token.
	// See RFC 4462 section 3.4.
	var token []byte
	defer g.gssAPIClient.DeleteSecContext()
	for {
		// Initiates the establishment of a security context between the application and a remote peer.
		nextToken, needContinue, err := g.gssAPIClient.InitSecContext("host@"+g.target, token, false)
		if err != nil {
			return authFailure, nil, err
		}
		if len(nextToken) > 0 {
			if err := c.writePacket(Marshal(&userAuthGSSAPIToken{
				Token: nextToken,
			})); err != nil {
				return authFailure, nil, err
			}
		}
		if !needContinue {
			break
		}
		packet, err = c.readPacket()
		if err != nil {
			return authFailure, nil, err
		}
		switch packet[0] {
		case msgUserAuthFailure:
			var msg userAuthFailureMsg
			if err := Unmarshal(packet, &msg); err != nil {
				return authFailure, nil, err
			}
			if msg.PartialSuccess {
				return authPartialSuccess, msg.Methods, nil
			}
			return authFailure, msg.Methods, nil
		case msgUserAuthGSSAPIError:
			userAuthGSSAPIErrorResp := &userAuthGSSAPIError{}
			if err := Unmarshal(packet, userAuthGSSAPIErrorResp); err != nil {
				return authFailure, nil, err
			}
			return authFailure, nil, fmt.Errorf("GSS-API Error:\n"+
				"Major Status: %d\n"+
				"Minor Status: %d\n"+
				"Error Message: %s\n", userAuthGSSAPIErrorResp.MajorStatus, userAuthGSSAPIErrorResp.MinorStatus,
				userAuthGSSAPIErrorResp.Message)
		case msgUserAuthGSSAPIToken:
			userAuthGSSAPITokenReq := &userAuthGSSAPIToken{}
			if err := Unmarshal(packet, userAuthGSSAPITokenReq); err != nil {
				return authFailure, nil, err
			}
			token = userAuthGSSAPITokenReq.Token
		}
	}
	// Binding Encryption Keys.
	// See RFC 4462 section 3.5.
	micField := buildMIC(string(session), user, "ssh-connection", "gssapi-with-mic")
	micToken, err := g.gssAPIClient.GetMIC(micField)
	if err != nil {
		return authFailure, nil, err
	}
	if err := c.writePacket(Marshal(&userAuthGSSAPIMIC{
		MIC: micToken,
	})); err != nil {
		return authFailure, nil, err
	}
	return handleAuthResponse(c)
}

func (g *gssAPIWithMICCallback) method() string {
	return "gssapi-with-mic"
}
