RFC 4462

Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol

๐Ÿ“… published May 2006, from ietf

RFC 4462 ๐ŸŽ€

Okay bestie, this one is Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol ๐ŸŒธ It's from the Network Working Group and dropped in May 2006 ๐Ÿ“…. It's a Standards Track doc, and it's written by J. Hutzelman (CMU), J. Salowey (Cisco Systems), J. Galbraith (Van Dyke Technologies, Inc.), and V. Welch (U Chicago / ANL) ๐Ÿงš. It doesn't list any RFCs it obsoletes or updates, so it's a clean slate ๐Ÿ’–

(Part 1 of 6 ๐Ÿ’…)


Status of This Memo โœจ

This doc is an Internet standards track protocol for the whole Internet community ๐Ÿฆ‹ It's basically asking everyone to talk about it and send suggestions for making it better. If you want to know where the protocol actually stands, check the current edition of "Internet Official Protocol Standards" (STD 1) ๐Ÿ“š And the memo can be shared as much as you want, since distribution is unlimited ๐Ÿซถ

Copyright (C) The Internet Society (2006).

Abstract

okay so SSH is the protocol people use for secure remote login and other secure stuff over a network you can't fully trust ๐Ÿ”

GSS-API is the thing that gives callers security services without caring which mechanism is underneath ๐Ÿงฉ It's mechanism-independent, which is so iconic ๐Ÿ‘‘

This memo is about using GSS-API for authentication and key exchange in SSH ๐Ÿ’œ It defines an SSH user authentication method that uses a specified GSS-API mechanism to authenticate a user ๐Ÿ™‹โ€โ™€๏ธ It also defines a whole family of SSH key exchange methods that use GSS-API to authenticate a Diffie-Hellman key exchange โœจ

And it defines two more things, honestly the main character moments ๐ŸŒˆ A new host public key algorithm for when nothing needs the host's public key ๐Ÿ”‘ And a new user authentication method that lets an authorization name ride along with whatever authentication already happened as a side effect of GSS-API-based key exchange ๐Ÿฆ‹

Table of Contents

   1. Introduction ....................................................3
      1.1. SSH Terminology ............................................3
      1.2. Key Words ..................................................3
   2. GSS-API-Authenticated Diffie-Hellman Key Exchange ...............3
      2.1. Generic GSS-API Key Exchange ...............................4
      2.2. Group Exchange ............................................10
      2.3. gss-group1-sha1-* .........................................11
      2.4. gss-group14-sha1-* ........................................12
      2.5. gss-gex-sha1-* ............................................12
      2.6. Other GSS-API Key Exchange Methods ........................12
   3. GSS-API User Authentication ....................................13
      3.1. GSS-API Authentication Overview ...........................13
      3.2. Initiating GSS-API Authentication .........................13
      3.3. Initial Server Response ...................................14
      3.4. GSS-API Session ...........................................15
      3.5. Binding Encryption Keys ...................................16
      3.6. Client Acknowledgement ....................................16
      3.7. Completion ................................................17
      3.8. Error Status ..............................................17
      3.9. Error Token ...............................................18
   4. Authentication Using GSS-API Key Exchange ......................19
   5. Null Host Key Algorithm ........................................20
   6. Summary of Message Numbers .....................................21
   7. GSS-API Considerations .........................................22
      7.1. Naming Conventions ........................................22
      7.2. Channel Bindings ..........................................22
      7.3. SPNEGO ....................................................23
   8. IANA Considerations ............................................24
   9. Security Considerations ........................................24
   10. Acknowledgements ..............................................25
   11. References ....................................................26
      11.1. Normative References .....................................26
      11.2. Informative References ...................................27

1. Introduction โœจ

This doc explains how SSH does key exchange and user authentication using GSS-API ๐ŸŽ€ It defines a family of key exchange methods, two user authentication methods, and a new host key algorithm ๐Ÿ’… Together, these let any GSS-API mechanism plug into SSH ๐Ÿ”Œ

Before you read this one, you should go through the SSH architecture doc [SSH-ARCH], the transport layer protocol [SSH-TRANSPORT], and the user authentication protocol [SSH-USERAUTH] ๐Ÿ“– This doc uses terms and notation from the architecture doc all the time without explaining them again, so you'll want that background ๐Ÿง 

1.1. SSH Terminology

The packets use the data types defined in the SSH architecture document [SSH-ARCH] ๐Ÿงƒ The big thing to remember is that a string is allowed to hold binary content ๐Ÿซง

The SSH_MSG_USERAUTH_REQUEST packet points at a service, and that service name is an SSH service name ๐Ÿ’โ€โ™€๏ธ It has nothing to do with GSS-API service names, so don't mix them up ๐Ÿ™ˆ Right now, the only service name that's defined is "ssh-connection", which refers to the SSH connection protocol [SSH-CONNECT] ๐ŸŒˆ

1.2. Key Words

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read the way [KEYWORDS] describes ๐Ÿ’œ

2. GSS-API-Authenticated Diffie-Hellman Key Exchange

This section is where the key exchange methods live ๐Ÿฆ‹ Each one combines the Diffie-Hellman key exchange from Section 8 of [SSH-TRANSPORT] with mutual authentication through GSS-API โœจ

Here's the vibe check ๐Ÿซถ The GSS-API key exchange methods in this section don't need a public key signature or encryption algorithm at all ๐Ÿ™Œ Because of that, they MAY be used with any host key algorithm, including the "null" algorithm from Section 5 ๐ŸŽ€

2.1. Generic GSS-API Key Exchange

Here are the symbols we'll be using ๐Ÿงš

  • C is the client, and S is the server ๐Ÿ‘ฏ
  • p is a large safe prime, g is a generator for a subgroup of GF(p), and q is the order of that subgroup ๐Ÿ”ข
  • V_S is S's version string, and V_C is C's version string ๐Ÿท๏ธ
  • I_C is C's KEXINIT message, and I_S is S's KEXINIT message ๐Ÿ“จ

Now the steps, bestie ๐Ÿ’…

  1. C picks a random number x (1 < x < q) and computes e = g^x mod p ๐ŸŽฒ
  2. C calls GSS_Init_sec_context(), feeding it the most recent reply token S sent during this exchange, if there is one ๐Ÿ“ฌ For this call, the client MUST set mutual_req_flag to "true" so mutual authentication happens ๐Ÿค It MUST also set integ_req_flag to "true" so per-message integrity protection is supported for the context ๐Ÿ›ก๏ธ On top of that, deleg_req_flag MAY be set to "true" to ask for access delegation, but only if the user asked for it ๐ŸŽŸ๏ธ Since this exchange only authenticates the host, anon_req_flag doesn't really matter here ๐Ÿ™ˆ If the client doesn't support the "gssapi-keyex" user authentication method from Section 4, or isn't planning to use that method with the GSS-API context from the key exchange, then anon_req_flag SHOULD be set to "true" ๐Ÿ•ถ๏ธ Otherwise, it MAY be set to true if the client wants to hide its identity ๐Ÿซฅ The key exchange only sends one token once the context is established, so the context doesn't need replay or out-of-sequence detection ๐Ÿ™…โ€โ™€๏ธ That means replay_det_req_flag and sequence_req_flag don't need to be set for this process ๐Ÿ’ค These flags SHOULD be set to "false" โœจ
    • Say the resulting major_status is GSS_S_COMPLETE but mutual_state isn't true ๐Ÿ’€ Then mutual authentication never got established, and the key exchange MUST fail ๐Ÿ˜ญ
    • Say the resulting major_status is GSS_S_COMPLETE but integ_avail isn't true ๐Ÿ’€ Then per-message integrity protection isn't available, and the key exchange MUST fail ๐Ÿ˜ญ
    • Say the resulting major_status is GSS_S_COMPLETE and both mutual_state and integ_avail are true ๐Ÿฅณ Then the resulting output token gets sent to S ๐Ÿ“ค
    • Say the resulting major_status is GSS_S_CONTINUE_NEEDED} ๐Ÿ” Then the output_token goes to S, and S replies with a new token to hand back to GSS_Init_sec_context()` ๐Ÿ”„
    • The client MUST also include "e" with the very first message it sends to the server during this process ๐Ÿ“ฉ If the server gets more than one "e", or none at all, the key exchange fails ๐Ÿ™ƒ
    • If the call doesn't produce a token with non-zero length to send to the server, that's an error ๐Ÿšซ In that case, the key exchange MUST fail ๐Ÿ’”
  3. S calls GSS_Accept_sec_context() using the token it got from C ๐Ÿ“ฅ
    • Say the resulting major_status is GSS_S_COMPLETE but mutual_state isn't true ๐Ÿ’€ Then mutual authentication never got established, and the key exchange MUST fail ๐Ÿ˜ญ
    • Say the resulting major_status is GSS_S_COMPLETE but integ_avail isn't true ๐Ÿ’€ Then per-message integrity protection isn't available, and the key exchange MUST fail ๐Ÿ˜ญ
    • Say the resulting major_status is GSS_S_COMPLETE and both mutual_state and integ_avail are true ๐ŸŽ‰ Then the security context is established, and things keep going at step 4 โœจ
    • Say the resulting major_status is GSS_S_CONTINUE_NEEDED ๐Ÿ” Then the output token goes to C, and processing goes back to step 2 ๐Ÿ”™
    • Say the resulting major_status is GSS_S_COMPLETE, but a non-zero-length reply token still comes back ๐Ÿ“ฆ Then that token gets sent to the client ๐Ÿซถ
  4. S generates a random number y (0 < y < q) and computes f = g^y mod p ๐ŸŽฒ It works out K = e^y mod p and then H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) ๐Ÿงฎ Next it calls GSS_GetMIC() to get a GSS-API message integrity code for H ๐Ÿ” Finally, S sends f and that message integrity code (MIC) over to C ๐Ÿ“ฌ
  5. This step only happens under two conditions ๐Ÿ‘€ The first is that the server's final call to GSS_Accept_sec_context() produced a final reply token with non-zero length to send to the client. The second is that no earlier client call to GSS_Init_sec_context() has returned a major_status of GSS_S_COMPLETE. When both are true, the client makes one more call to GSS_Init_sec_context() to process that final reply token ๐ŸŽ€ This call is done exactly the way it's described above ๐Ÿ’… But if the resulting major_status is anything other than GSS_S_COMPLETE, or a non-zero-length token comes back, that's an error and the key exchange MUST fail ๐Ÿšจ
  6. Last step, bestie ๐Ÿ C computes K = f^x mod p and H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) ๐Ÿงฎ Then it calls GSS_VerifyMIC() to check that the MIC S sent matches H ๐Ÿ” If the MIC doesn't verify, the key exchange MUST fail ๐Ÿ’”

And that's part 1 of 6 ๐Ÿฆ‹ Stay tuned, there's so much more coming ๐Ÿ’œ

Either side MUST NOT send or accept e or f values that are not in the range [1, p-1]. If this condition is violated, the key exchange fails. ๐Ÿ’…

If any call to GSS_Init_sec_context() or GSS_Accept_sec_context() returns a major_status other than GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED, or any other GSS-API call returns a major_status other than GSS_S_COMPLETE, the key exchange fails. ๐Ÿ˜ญ In that case there are a few ways to tell the peer what went wrong before you close the connection, as [SSH-TRANSPORT] requires:

  • If the key exchange fails due to any GSS-API error on the server (including errors returned by GSS_Accept_sec_context()), the server MAY send a message informing the client of the details of the error. If an error token is also sent (see below), then this message MUST be sent before the error token. ๐Ÿงš
  • If the key exchange fails due to a GSS-API error returned from the server's call to GSS_Accept_sec_context(), and an "error token" is also returned, then the server SHOULD send the error token to the client so the GSS security exchange can wrap up. ๐ŸŽ€
  • If the key exchange fails due to a GSS-API error returned from the client's call to GSS_Init_sec_context(), and an "error token" is also returned, then the client SHOULD send the error token to the server so the GSS security exchange can wrap up. ๐ŸŒธ

As noted in Section 9, it may be desirable under site security policy to hide the precise nature of the error, so it is RECOMMENDED that implementations provide a method to suppress these messages as a matter of policy. ๐Ÿ™ˆ Security people are right to be paranoid, bestie.

Now for the messages themselves. The hash algorithm used to compute the exchange hash is set by the method name and is called HASH. The Diffie-Hellman group and the underlying GSS-API mechanism are also set by the method name. ๐Ÿฆ‹

After the client's first call to GSS_Init_sec_context(), it sends the following:

        byte      SSH_MSG_KEXGSS_INIT
        string    output_token (from GSS_Init_sec_context())
        mpint     e

When the server receives the SSH_MSG_KEXGSS_INIT message, the server MAY send the following message, before any other messages, to tell the client its host key. ๐Ÿ”‘

        byte      SSH_MSG_KEXGSS_HOSTKEY
        string    server public host key and certificates (K_S)

This key exchange method doesn't need the host key for any encryption, so this message is OPTIONAL. If the "null" host key algorithm described in Section 5 is used, this message MUST NOT be sent. If this message is sent, the server public host key(s) and/or certificate(s) in it are encoded as a single string, in the format specified by the public key type in use (see [SSH-TRANSPORT], Section 6.6). โœจ

In traditional SSH setups, host keys usually change rarely, and there is often no way to validate a host key the client hasn't seen before. So when a known host suddenly shows a new key, that is usually treated as a possible man-in-the-middle attack, and clients often throw strong warnings or abort the connection. ๐Ÿ‘€

GSS-API-based key exchange is different, though. Host keys sent in the SSH_MSG_KEXGSS_HOSTKEY message are authenticated as part of the GSS-API key exchange, even when the client has never seen them before. Plus, in environments where GSS-API-based key exchange gets used a lot, it's possible and even likely that host keys will change much more often and/or without any warning. ๐ŸŒˆ

So, when a known host sends a new key via the SSH_MSG_KEXGSS_HOSTKEY message, clients SHOULD NOT issue strong warnings or abort the connection, provided the GSS-API-based key exchange succeeds. ๐Ÿ’–

To make key re-exchange possible after the user's GSS-API credentials expire, client implementations SHOULD store host keys received via SSH_MSG_KEXGSS_HOSTKEY for the duration of the session, even when those keys aren't kept for long-term use. ๐Ÿซถ

Each time the server's call to GSS_Accept_sec_context() returns a major_status of GSS_S_CONTINUE_NEEDED, it sends the following reply to the client:

        byte      SSH_MSG_KEXGSS_CONTINUE
        string    output_token (from GSS_Accept_sec_context())

If the client receives this message after a call to GSS_Init_sec_context() has returned a major_status of GSS_S_COMPLETE, a protocol error has occurred and the key exchange MUST fail. ๐Ÿšจ

Each time the client receives the message above, it makes another call to GSS_Init_sec_context(). Then it sends the following:

        byte      SSH_MSG_KEXGSS_CONTINUE
        string    output_token (from GSS_Init_sec_context())

The server and client keep trading these two messages for as long as the server's calls to GSS_Accept_sec_context() result in major_status codes of GSS_S_CONTINUE_NEEDED. Once a call results in a major_status of GSS_S_COMPLETE, it sends one of two final messages. ๐Ÿ

If the server's final call to GSS_Accept_sec_context() (the one resulting in a major_status of GSS_S_COMPLETE) returns a non-zero-length token to send to the client, it sends the following:

        byte      SSH_MSG_KEXGSS_COMPLETE
        mpint     f
        string    per_msg_token (MIC of H)
        boolean   TRUE
        string    output_token (from GSS_Accept_sec_context())

If the client receives this message after a call to GSS_Init_sec_context() has returned a major_status of GSS_S_COMPLETE, a protocol error has occurred and the key exchange MUST fail. ๐Ÿ’€

If the server's final call to GSS_Accept_sec_context() (the one resulting in a major_status of GSS_S_COMPLETE) returns a zero-length token or no token at all, it sends the following:

        byte      SSH_MSG_KEXGSS_COMPLETE
        mpint     f
        string    per_msg_token (MIC of H)
        boolean   FALSE

If the client receives this message when no call to GSS_Init_sec_context() has yet resulted in a major_status of GSS_S_COMPLETE, a protocol error has occurred and the key exchange MUST fail. ๐Ÿ™…โ€โ™€๏ธ

If either the client's call to GSS_Init_sec_context() or the server's call to GSS_Accept_sec_context() returns an error status and produces an output token (called an "error token"), then the following SHOULD be sent to pass the error information along to the peer:

        byte      SSH_MSG_KEXGSS_CONTINUE
        string    error_token

If a server sends both this message and an SSH_MSG_KEXGSS_ERROR message, the SSH_MSG_KEXGSS_ERROR message MUST be sent first, so clients can record and/or display the error information before they process the error token. This order matters a lot, because a client processing an error token will likely disconnect without reading any further messages. ๐Ÿ˜ค

If there's a GSS-API error on the server, the server MAY send the following message before it terminates the connection:

        byte      SSH_MSG_KEXGSS_ERROR
        uint32    major_status
        uint32    minor_status
        string    message
        string    language tag

The message text MUST be encoded in the UTF-8 encoding described in [UTF8]. Language tags are the ones described in [LANGTAG]. Heads up: the message text may contain multiple lines separated by carriage return-line feed (CRLF) sequences, so application developers should keep that in mind when displaying these messages. ๐Ÿ“ฃ

The hash H is computed as the HASH hash of the concatenation of the following:

        string    V_C, the client's version string (CR, NL excluded)
        string    V_S, the server's version string (CR, NL excluded)
        string    I_C, the payload of the client's SSH_MSG_KEXINIT
        string    I_S, the payload of the server's SSH_MSG_KEXINIT
        string    K_S, the host key
        mpint     e, exchange value sent by the client
        mpint     f, exchange value sent by the server
        mpint     K, the shared secret

This value is called the exchange hash, and it's what authenticates the key exchange. The exchange hash SHOULD be kept secret. If the server has not sent, and the client has not received, an SSH_MSG_KEXGSS_HOSTKEY message, then the empty string is used in place of K_S when computing the exchange hash. ๐Ÿ”

The GSS_GetMIC call MUST be applied over H, not the original data. ๐Ÿซง

2.2. Group Exchange โœจ

This section describes a modification to the generic GSS-API-authenticated Diffie-Hellman key exchange that lets the two sides negotiate the group to use, based on a method described in [GROUP-EXCHANGE]. ๐ŸŒธ

The server keeps a list of safe primes and matching generators to pick from. These are chosen as described in Section 3 of [GROUP-EXCHANGE]. The client asks the server for a modulus, giving the minimum, maximum, and preferred sizes. The server replies with a suitable modulus and generator. Then the exchange continues as described in Section 2.1 above. ๐Ÿงš

This description uses the following symbols, on top of the ones defined above:

  • n is the size of the modulus p in bits that the client would like to receive from the server.
  • min and max are the minimal and maximal sizes of p in bits that are acceptable to the client.
  1. C sends "min || n || max" to S, indicating the minimal acceptable group size, the preferred size of the group, and the maximal group size in bits the client will accept.
  2. S finds a group that best matches the client's request, and sends "p || g" to C.
  3. The exchange proceeds as described in Section 2.1 above, beginning with step 1, except that the exchange hash is computed as described below.

Servers and clients SHOULD support groups with a modulus length of k bits, where 1024 <= k <= 8192. The recommended values for min and max are 1024 and 8192, respectively. ๐ŸŽ€

This is implemented with the following messages, on top of the ones described above. First, the client sends:

        byte      SSH_MSG_KEXGSS_GROUPREQ
        uint32    min, minimal size in bits of an acceptable group
        uint32    n, preferred size in bits of the group the server
                  should send
        uint32    max, maximal size in bits of an acceptable group

The server responds with:

        byte      SSH_MSG_KEXGSS_GROUP
        mpint     p, safe prime
        mpint     g, generator for subgroup in GF(p)

This is followed by the message exchange described above in Section 2.1, except that the exchange hash H is computed as the HASH hash of the concatenation of the following:

        string    V_C, the client's version string (CR, NL excluded)
        string    V_S, the server's version string (CR, NL excluded)
        string    I_C, the payload of the client's SSH_MSG_KEXINIT
        string    I_S, the payload of the server's SSH_MSG_KEXINIT
        string    K_S, the host key
        uint32    min, minimal size in bits of an acceptable group
        uint32    n, preferred size in bits of the group the server
                  should send
        uint32    max, maximal size in bits of an acceptable group
        mpint     p, safe prime
        mpint     g, generator for subgroup in GF(p)
        mpint     e, exchange value sent by the client
        mpint     f, exchange value sent by the server
        mpint     K, the shared secret

2.3. gss-group1-sha1-*

Okay so this one is giving classic Diffie-Hellman with the old-school group 1 vibes ๐Ÿฆ‹. Each of these methods uses GSS-API-authenticated Diffie-Hellman key exchange like we just covered in Section 2.1 ๐ŸŽ€, with SHA-1 as HASH, and the group defined in Section 8.1 of [SSH-TRANSPORT] ๐Ÿ’œ. The method name is the string "gss-group1-sha1-" glued onto the Base64 encoding of the MD5 hash [MD5] of the ASN.1 Distinguished Encoding Rules (DER) encoding [ASN1] of the underlying GSS-API mechanism's Object Identifier (OID) โœจ. Base64 encoding is described in Section 6.8 of [MIME] ๐ŸŒธ.

Every single one of these key exchange methods is implicitly registered by this specification ๐Ÿซถ. The IESG is considered to be the owner of all of them, but NOT the owner of the underlying GSS-API mechanism ๐Ÿ’…. Not the same thing, bestie ๐Ÿ™ˆ.

2.4. gss-group14-sha1-*

Same energy, bigger group ๐Ÿ”ฅ. This one is GSS-API authenticated Diffie-Hellman key exchange as described in Section 2.1 ๐Ÿ’–, with SHA-1 as HASH, and the group defined in Section 8.2 of [SSH-TRANSPORT] ๐Ÿ“. The method name is "gss-group14-sha1-" plus the Base64 encoding of the MD5 hash [MD5] of the ASN.1 DER encoding [ASN1] of the underlying GSS-API mechanism's OID. Base64 encoding is described in Section 6.8 of [MIME] ๐Ÿงš.

Again, every such key exchange method is implicitly registered by this specification โญ. The IESG is considered to be the owner of all such key exchange methods, but this does NOT imply that the IESG owns the underlying GSS-API mechanism ๐Ÿ‘‘.

2.5. gss-gex-sha1-*

This is the group exchange version ๐Ÿฆ‹. Each of these methods is GSS-API-authenticated Diffie-Hellman key exchange as described in Section 2.2 ๐Ÿ’œ, with SHA-1 as HASH. The method name is the string "gss-gex-sha1-" with the Base64 encoding of the MD5 hash [MD5] of the ASN.1 DER encoding [ASN1] of the underlying GSS-API mechanism's OID. Base64 encoding is described in Section 6.8 of [MIME] ๐ŸŒˆ.

Every such key exchange method is implicitly registered by this specification ๐ŸŽ€. The IESG is considered to be the owner of all such key exchange methods, but this does NOT imply that the IESG is considered to be the owner of the underlying GSS-API mechanism ๐Ÿ’….

2.6. Other GSS-API Key Exchange Methods

Any key exchange method name starting with "gss-" is reserved for methods that conform to this document ๐Ÿ”’. That means methods that use the GSS-API-authenticated Diffie-Hellman key exchange algorithm described in Section 2.1 โœจ, including future methods that use different groups and/or hash functions ๐ŸŒธ. The plan is that the names for any future methods get defined in a similar way to Section 2.3 ๐Ÿงš.

3. GSS-API User Authentication โœจ

This section describes a general-purpose user authentication method based on [GSSAPI] ๐Ÿซถ. It's meant to run over the SSH user authentication protocol [SSH-USERAUTH] ๐Ÿ’–.

The authentication method name for this protocol is "gssapi-with-mic" ๐Ÿ“.

3.1. GSS-API Authentication Overview

GSS-API authentication has to maintain a context ๐Ÿง . It starts when the client sends an SSH_MSG_USERAUTH_REQUEST, listing the mechanism OIDs the client supports ๐ŸŽ€.

If the server supports any of the requested mechanism OIDs, it sends an SSH_MSG_USERAUTH_GSSAPI_RESPONSE message containing the mechanism OID ๐Ÿฆ‹.

Once the client receives SSH_MSG_USERAUTH_GSSAPI_RESPONSE, the client and server swap SSH_MSG_USERAUTH_GSSAPI_TOKEN packets back and forth until the authentication mechanism either succeeds or fails ๐Ÿ”ฅ.

If at any point during the exchange the client sends a new SSH_MSG_USERAUTH_REQUEST packet, the GSS-API context gets completely discarded and destroyed ๐Ÿ’€, and any further GSS-API authentication MUST restart from the beginning ๐Ÿ™…โ€โ™€๏ธ.

If authentication succeeds and the client presents a non-empty user name, the SSH server implementation checks that the user name is authorized based on the credentials exchanged in the GSS-API exchange ๐Ÿ‘‘. If the user name is not authorized, then the authentication MUST fail ๐Ÿ˜ญ.

3.2. Initiating GSS-API Authentication

GSS-API authentication starts when the client sends an SSH_MSG_USERAUTH_REQUEST ๐ŸŒธ:

        byte      SSH_MSG_USERAUTH_REQUEST
        string    user name (in ISO-10646 UTF-8 encoding)
        string    service name (in US-ASCII)
        string    "gssapi-with-mic" (US-ASCII method name)
        uint32    n, the number of mechanism OIDs client supports
        string[n] mechanism OIDs

Mechanism OIDs are encoded with the ASN.1 Distinguished Encoding Rules (DER), as described in [ASN1] and in Section 3.1 of [GSSAPI] ๐Ÿงš. The mechanism OIDs MUST be listed in order of preference ๐Ÿ’œ, and the server must pick the first mechanism OID on the list that it supports ๐ŸŽฏ.

The client SHOULD only send GSS-API mechanism OIDs for mechanisms that have the same priority compared to non-GSS-API authentication methods ๐Ÿซถ. Otherwise, authentication methods might get run out of order ๐Ÿ™ˆ. So the client could first send an SSH_MSG_USERAUTH_REQUEST for one GSS-API mechanism, then try public key authentication, and then try another GSS-API mechanism ๐Ÿฆ‹.

If the server doesn't support any of the specified OIDs, the server MUST fail the request by sending an SSH_MSG_USERAUTH_FAILURE packet ๐Ÿ˜ค.

The user name can be an empty string if it can be deduced from the results of the GSS-API authentication ๐ŸŒˆ. If the user name isn't empty and the requested user doesn't exist, the server MAY disconnect, or MAY send a bogus list of acceptable authentications but never accept any ๐Ÿ™ƒ. This makes it possible for the server to avoid revealing which accounts exist ๐Ÿ”’. Either way, if the user doesn't exist, the authentication request MUST NOT be accepted ๐Ÿšซ.

Note that the 'user name' value is encoded in ISO-10646 UTF-8 ๐Ÿ’…. How the server interprets the user name and decides whether the client is authorized based on their GSS-API credentials is up to the server ๐ŸŒธ. The encoding the system uses for user names is a matter for the ssh server implementation ๐Ÿงš. However, if the client reads the user name in some other encoding (e.g., ISO 8859-1 - ISO Latin1), it MUST convert the user name to ISO-10646 UTF-8 before transmitting ๐Ÿ“, and the server MUST convert the user name to the encoding used on that system for user names ๐Ÿซถ.

Any normalization or other preparation of names is done by the ssh server based on the system's requirements, and it's outside the scope of SSH โœจ. SSH implementations that maintain private user databases SHOULD prepare user names as described by [SASLPREP] ๐Ÿ’–.

The client MAY at any time continue with a new SSH_MSG_USERAUTH_REQUEST message ๐Ÿฆ‹. When it does, the server MUST abandon the previous authentication attempt and continue with the new one ๐Ÿ”„.

3.3. Initial Server Response

The server answers 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, like this ๐Ÿ’œ:

        byte        SSH_MSG_USERAUTH_GSSAPI_RESPONSE
        string      selected mechanism OID

The mechanism OID must be one of the OIDs the client sent in the SSH_MSG_USERAUTH_REQUEST packet ๐ŸŽ€.

3.4. GSS-API Session

Once the mechanism OID has been selected, the client then starts an exchange of one or more pairs of SSH_MSG_USERAUTH_GSSAPI_TOKEN packets ๐ŸŒˆ. These packets carry the tokens produced by the 'GSS_Init_sec_context()' and 'GSS_Accept_sec_context()' calls ๐Ÿงš. The actual number of packets exchanged is decided by the underlying GSS-API mechanism ๐Ÿซถ.

        byte        SSH_MSG_USERAUTH_GSSAPI_TOKEN
        string      data returned from either GSS_Init_sec_context()
                    or GSS_Accept_sec_context()

If an error happens during this exchange on the server side, the server can end the method by sending an SSH_MSG_USERAUTH_FAILURE packet ๐Ÿ’€. If an error happens on the client side, the client can end the method by sending a new SSH_MSG_USERAUTH_REQUEST packet ๐Ÿ™ƒ.

When calling GSS_Init_sec_context(), the client MUST set integ_req_flag to "true" to ask that per-message integrity protection be supported for this context ๐Ÿ”. On top of that, deleg_req_flag MAY be set to "true" to request access delegation, if the user asked for it ๐ŸŒธ.

Since user authentication by its nature only authenticates the client, setting mutual_req_flag isn't needed for this process ๐Ÿ’…. This flag SHOULD be set to "false" ๐Ÿซถ.

Since user authentication only involves exchanging a single token once the context is established, the context doesn't need to support detection of replayed or out-of-sequence tokens ๐Ÿง . So setting replay_det_req_flag and sequence_req_flag isn't needed here ๐Ÿ™Œ. These flags SHOULD be set to "false" ๐Ÿ’–.

Additional SSH_MSG_USERAUTH_GSSAPI_TOKEN messages are sent if and only if the calls to the GSS-API routines produce send tokens of non-zero length ๐Ÿฆ‹.

Any major status code other than GSS_S_COMPLETE or GSS_S_CONTINUE_NEEDED SHOULD be treated as a failure ๐Ÿšจ.

3.5. Binding Encryption Keys

Sometimes you can get extra security by only allowing access if the client sends a valid message integrity code (MIC) that binds the GSS-API context to the keys used for encryption and integrity protection of the SSH session ๐Ÿ”โœจ. With this extra layer, a "man-in-the-middle" attacker who has convinced a client they're legit can't relay user authentication messages between the real client and server to get into the real server ๐Ÿ˜ฑ. This extra protection is available when the negotiated GSS-API context supports per-message integrity protection, which shows up as the integ_avail flag being set when GSS_Init_sec_context() or GSS_Accept_sec_context() returns successfully ๐Ÿ›ก๏ธ.

When the client's call to GSS_Init_sec_context() returns GSS_S_COMPLETE with the integ_avail flag set, the client MUST wrap up the user authentication exchange by sending this message ๐ŸŽ€:

        byte      SSH_MSG_USERAUTH_GSSAPI_MIC
        string    MIC

This message MUST be sent only if GSS_Init_sec_context() returned GSS_S_COMPLETE ๐Ÿ’œ. If a token is also returned, the SSH_MSG_USERAUTH_GSSAPI_TOKEN message MUST be sent before this one ๐Ÿฆ‹.

The contents of the MIC field come from calling GSS_GetMIC() over the following, using the GSS-API context that was just established ๐Ÿงš:

        string    session identifier
        byte      SSH_MSG_USERAUTH_REQUEST
        string    user name
        string    service
        string    "gssapi-with-mic"

If the server receives this message before the GSS-API context is fully established, the server MUST fail the authentication ๐Ÿšซ.

If the server receives this message while the negotiated GSS-API context doesn't support per-message integrity protection, the server MUST fail the authentication ๐Ÿ˜ค.

3.6. Client Acknowledgement ๐Ÿซถ

okay so some servers are like "we're chill letting users in even when the GSS-API context can't do per-message integrity protection" ๐Ÿคทโ€โ™€๏ธ. In that case the server can finish the GSS-API method successfully while the client's last call to GSS_Init_sec_context() fails ๐Ÿ˜ญ. If the server just assumed everything was fine on the client's side and wrapped up, the client could fail the method but still not be able to try other methods, because the server had already moved on. Not the vibe! So the client sends one final message to say "I'm authenticated, we're good" ๐Ÿ’….

When the client's call to GSS_Init_sec_context() returns GSS_S_COMPLETE with the integ_avail flag not set, the client MUST conclude the user authentication exchange by sending this message:

           byte      SSH_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE

This message MUST be sent only if GSS_Init_sec_context() returned GSS_S_COMPLETE. If a token is also returned, then the SSH_MSG_USERAUTH_GSSAPI_TOKEN message MUST be sent before this one. ๐Ÿงš

If this message reaches the server before the GSS-API context is fully established, the server MUST fail the authentication. ๐Ÿ™ˆ

If this message reaches the server when the negotiated GSS-API context supports per-message integrity protection, the server MUST fail the authentication. ๐Ÿ’€

Whether a server lets authentication go through with GSS-API mechanisms and/or contexts that don't support per-message integrity protection is totally up to the site policy ๐Ÿ‘‘. The server MAY fail an otherwise valid gssapi-with-mic authentication if per-message integrity protection isn't supported.


3.7. Completion ๐ŸŽ€

Same as every other SSH auth method, a win is signalled by an SSH_MSG_USERAUTH_SUCCESS if no more auth is needed. If the server needs further authentication, it sends an SSH_MSG_USERAUTH_FAILURE with the partial success flag set instead ๐ŸŒธ. This packet SHOULD be sent immediately after receiving the SSH_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE packet โญ.


3.8. Error Status ๐Ÿšจ

Okay so if a GSS-API error happens on the server during context establishment, the server MAY send this message to tell the client what went wrong, before it sends an SSH_MSG_USERAUTH_FAILURE ๐Ÿ™ˆ:

           byte      SSH_MSG_USERAUTH_GSSAPI_ERROR
           uint32    major_status
           uint32    minor_status
           string    message
           string    language tag

The message text MUST be encoded in the UTF-8 encoding described in [UTF8]. Language tags are the ones described in [LANGTAG]. Heads up: the message text can have multiple lines, separated by carriage return-line feed (CRLF) sequences, so app devs should keep that in mind when they display these messages ๐Ÿ’–.

Clients that receive this message MAY log the error details and/or show them to the user ๐Ÿ“. Any server sending this message MUST ignore any SSH_MSG_UNIMPLEMENTED the client sends back in response ๐Ÿซ .


3.9. Error Token ๐Ÿ’”

So, during context establishment, if a client's call to GSS_Init_sec_context() or a server's call to GSS_Accept_sec_context() returns a token along with an error status, the resulting "error token" SHOULD be sent to the peer using this message:

           byte        SSH_MSG_USERAUTH_GSSAPI_ERRTOK
           string      error token

This message means the authentication is about to fail. It exists so the error token can be communicated without losing synchronization ๐Ÿ”„.

When a server sends this message, it MUST be followed by an SSH_MSG_USERAUTH_FAILURE message, which applies to the same authentication request ๐ŸŽฏ. A client that receives this message SHOULD wait for that following SSH_MSG_USERAUTH_FAILURE before starting another attempt โณ.

When a client sends this message, it MUST be followed by a new authentication request or by terminating the connection. A server that receives this message MUST NOT send an SSH_MSG_USERAUTH_FAILURE in reply, because a client could otherwise read that as a response to the next authentication sequence ๐Ÿ™…โ€โ™€๏ธ.

Any server sending this message MUST ignore any SSH_MSG_UNIMPLEMENTED the client sends back in response. If a server sends both this message and an SSH_MSG_USERAUTH_GSSAPI_ERROR message, the SSH_MSG_USERAUTH_GSSAPI_ERROR message MUST be sent first, so the client can store and/or display the error status before it processes the error token ๐Ÿ’….


4. Authentication Using GSS-API Key Exchange โœจ

This section describes a user authentication method built on the framework in [SSH-USERAUTH]. It authenticates the user by reusing an existing GSS-API context that was established during key exchange ๐Ÿฆ‹.

The authentication method name for this protocol is "gssapi-keyex".

This method may be used only if the initial key exchange was done with a GSS-API-based key exchange method defined in accordance with Section 2. The GSS-API context used with this method is always the one established during an initial GSS-API-based key exchange. Any context established during key exchange for the purpose of rekeying MUST NOT be used with this method ๐Ÿšซ.

The server SHOULD include this user authentication method in the list of methods that can continue (in an SSH_MSG_USERAUTH_FAILURE) if the initial key exchange was done with a GSS-API-based key exchange method and provides information about the user's identity that is useful to the server ๐Ÿง . It MUST NOT include this method if the initial key exchange was not done with a GSS-API-based key exchange method defined in accordance with Section 2 ๐Ÿ™…โ€โ™€๏ธ.

The client SHOULD attempt this method if the server advertises it, the initial key exchange was done with a GSS-API-based key exchange method, and this method hasn't already been tried โœจ. The client SHOULD NOT try this method more than once per session. It MUST NOT try this method if the initial key exchange was not done with a GSS-API-based key exchange method defined in accordance with Section 2 ๐Ÿซถ.

If a server receives a request for this method when the initial key exchange was not done with a GSS-API-based key exchange method defined in accordance with Section 2, it MUST return SSH_MSG_USERAUTH_FAILURE ๐Ÿ’€.

This method is defined as a single message:

           byte        SSH_MSG_USERAUTH_REQUEST
           string      user name
           string      service
           string      "gssapi-keyex"
           string      MIC

The contents of the MIC field come from calling GSS_GetMIC over the following, using the GSS-API context that was established during initial key exchange ๐Ÿ”:

           string      session identifier
           byte        SSH_MSG_USERAUTH_REQUEST
           string      user name
           string      service
           string      "gssapi-keyex"

When this message is received and the initial key exchange was done with a GSS-API-based key exchange method, the server uses GSS_VerifyMIC() to check that the MIC is valid. If the MIC isn't valid, the user authentication fails, and the server MUST return SSH_MSG_USERAUTH_FAILURE โŒ.

If the MIC is valid and the server is satisfied with the user's credentials, it MAY return either SSH_MSG_USERAUTH_SUCCESS or SSH_MSG_USERAUTH_FAILURE with the partial success flag set, depending on whether more authentications are needed ๐Ÿ‘‘.


5. Null Host Key Algorithm ๐ŸŒˆ

The "null" host key algorithm has no associated host key material and provides neither signature nor encryption algorithms. So it can be used only with key exchange methods that don't need any public-key operations and don't need host public key material. The key exchange methods described in Section 2 are examples of such methods ๐Ÿ“.

This algorithm is used when, as a matter of configuration, the host doesn't have a public key or doesn't want to use one ๐Ÿ™ˆ. For example, it can be used when an administrator has decided, as a matter of policy, that all key exchanges must be authenticated using Kerberos [KRB5]. Then the only permitted key exchange method is the GSS-API-authenticated Diffie-Hellman exchange described above, with Kerberos V5 as the underlying GSS-API mechanism ๐Ÿงš. In that kind of setup, the server implementation supports the "ssh-dss" key algorithm (as required by [SSH-TRANSPORT]), but configuration could prohibit it from using that algorithm. Here the server still needs some key exchange algorithm to advertise, and the "null" algorithm fills that role ๐ŸŽ€.

Keep in mind that using "null" this way means the server won't be able to interoperate with clients that don't support this algorithm. It's not really a big deal, though, because in this configuration it also couldn't interoperate with implementations that don't support the GSS-API-authenticated key exchange and Kerberos ๐Ÿคทโ€โ™€๏ธ.

Any implementation that supports at least one key exchange method conforming to Section 2 MUST also support the "null" host key algorithm. Servers MUST NOT advertise the "null" host key algorithm unless it's the only algorithm advertised ๐Ÿ”ฅ.


6. Summary of Message Numbers ๐Ÿ”ข

The following message numbers have been defined for use with GSS-API-based key exchange methods ๐Ÿ’œ:

       #define SSH_MSG_KEXGSS_INIT                       30
       #define SSH_MSG_KEXGSS_CONTINUE                   31
       #define SSH_MSG_KEXGSS_COMPLETE                   32
       #define SSH_MSG_KEXGSS_HOSTKEY                    33
       #define SSH_MSG_KEXGSS_ERROR                      34
       #define SSH_MSG_KEXGSS_GROUPREQ                   40
       #define SSH_MSG_KEXGSS_GROUP                      41

The numbers 30-49 are specific to key exchange and may be redefined by other kex methods ๐Ÿฆ‹.

The following message numbers have been defined for use with the 'gssapi-with-mic' user authentication method ๐Ÿซง:

       #define SSH_MSG_USERAUTH_GSSAPI_RESPONSE          60
       #define SSH_MSG_USERAUTH_GSSAPI_TOKEN             61
       #define SSH_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE 63
       #define SSH_MSG_USERAUTH_GSSAPI_ERROR             64
       #define SSH_MSG_USERAUTH_GSSAPI_ERRTOK            65
       #define SSH_MSG_USERAUTH_GSSAPI_MIC               66

The numbers 60-79 are specific to user authentication and may be redefined by other user auth methods. Note that in the method described in this document, message number 62 is unused ๐Ÿ™ƒ.


7. GSS-API Considerations โœจ

7.1. Naming Conventions ๐ŸŽ€

Okay so bestie, the SSH client has to figure out the right targ_name to use when it identifies the server by calling GSS_Init_sec_context(). For that, we use the GSS-API mechanism-independent name form for host-based services, which is described in Section 4.1 of [GSSAPI]. โœจ

Here's the specific move: the targ_name you pass to GSS_Init_sec_context() comes from calling GSS_Import_name() with an input_name_type of GSS_C_NT_HOSTBASED_SERVICE, and an input_name_string that's the string "host@" glued onto the hostname of the SSH server. ๐Ÿ’–

Now this part is so important. The GSS-API mechanism uses the targ_name to check the server's identity, so it has to be figured out in a secure way. ๐Ÿ™ˆ One common approach is building the targ_name from the hostname the user typed in, but that's lowkey risky, because some GSS-API mechanisms don't canonicalize hostnames. So if the user didn't type a fully-qualified, canonical hostname, this approach will probably fail. Implementers are free to try other methods, but they have to make sure those are secure. For example, you should not trust an unprotected DNS record to map a host alias to the server's primary name, or an IP address to a hostname, because an attacker can change that mapping and impersonate the server. ๐Ÿ˜ญ

So the rules are: implementations of mechanisms conforming to this document MUST NOT use the results of insecure DNS queries to construct the targ_name. Clients MAY use a mapping from local configuration or some other secure means to figure out the targ_name. And if a client system can't securely determine which targ_name to use, then it SHOULD NOT use this mechanism at all. Periodt. ๐Ÿ”ฅ

7.2. Channel Bindings ๐Ÿฆ‹

Here the document recommends that channel bindings SHOULD NOT be specified in the calls during context establishment. No standard data is defined for channel bindings in this document, and using network addresses as channel bindings may break SSH in environments where it's most useful, so it's giving "pls don't." ๐Ÿ™…โ€โ™€๏ธ

7.3. SPNEGO ๐Ÿ’…

Okay, so the Simple and Protected GSS-API Negotiation Mechanism [SPNEGO] used together with the authentication and key exchange methods in this document is both unnecessary and undesirable. That's why mechanisms conforming to this document MUST NOT use SPNEGO as the underlying GSS-API mechanism. ๐Ÿšซ

The reason is that SSH already does its own negotiation of authentication and key exchange methods, so SPNEGO's negotiation doesn't add any benefit. Even worse, as explained below, it can end up picking a weaker method than you wanted. ๐Ÿ˜ฌ

Normally SPNEGO protects the GSS-API mechanism negotiation by having the server compute a MIC of the list of mechanisms the client proposed, and then the client checks that value. For key exchange, that protection isn't needed, since the key exchange methods here already do an equivalent thing: they generate a MIC of the SSH exchange hash, which is a hash of several items including the lists of key exchange mechanisms supported by both sides. For user authentication, the protection isn't needed either, because the negotiation happens over a secure channel and the host's identity has already been proved to the user. โœจ

Mixing SPNEGO with GSS-API mechanisms that are used without SPNEGO can cause interoperability problems. For instance, a client that supports key exchange with the Kerberos V5 GSS-API mechanism [KRB5-GSS] only underneath SPNEGO won't interoperate with a server that supports key exchange only using the Kerberos V5 GSS-API mechanism directly. So letting GSS-API mechanisms be used both with and without SPNEGO is undesirable. ๐Ÿ™ƒ

Here's a spicy scenario. Say a client's policy is to first prefer GSS-API-based key exchange method X, then non-GSS-API method Y, then GSS-API-based method Z. If the server supports Y and Z but not X, then trying to use SPNEGO to negotiate a GSS-API mechanism might end up using method Z when method Y would have been the better choice. That means SPNEGO could subvert the negotiation algorithm for key exchange methods described in Section 7.1 of [SSH-TRANSPORT], and/or the negotiation algorithm for user authentication methods described in [SSH-USERAUTH]. Main character energy, but make it a disaster. ๐Ÿ’€

8. IANA Considerations ๐ŸŒธ

Consistent with Section 8 of [SSH-ARCH] and Section 4.6 of [SSH-NUMBERS], this document makes the following registrations. ๐Ÿ“‹

  • The family of SSH key exchange method names beginning with gss-group1-sha1- and not containing the at-sign ('@'), to name the key exchange methods defined in Section 2.3.
  • The family of SSH key exchange method names beginning with gss-gex-sha1- and not containing the at-sign ('@'), to name the key exchange methods defined in Section 2.5.
  • All other SSH key exchange method names beginning with gss- and not containing the at-sign ('@'), to be reserved for future key exchange methods defined in conformance with this document, as noted in Section 2.6.
  • The SSH host public key algorithm name null, to name the NULL host key algorithm defined in Section 5.
  • The SSH user authentication method name gssapi-with-mic, to name the GSS-API user authentication method defined in Section 3.
  • The SSH user authentication method name gssapi-keyex, to name the GSS-API user authentication method defined in Section 4.
  • The SSH user authentication method name gssapi is to be reserved, so it doesn't clash with implementations supporting an earlier version of this specification.
  • The SSH user authentication method name external-keyx is to be reserved, so it doesn't clash with implementations supporting an earlier version of this specification.

This document creates no new registries. Nothing new to register, no drama. โœจ

9. Security Considerations ๐Ÿ”

This document describes authentication and key-exchange protocols, so security considerations are discussed throughout. Very serious, very important, very dramatic. ๐Ÿ˜ค

This protocol depends on the SSH protocol itself, the GSS-API, any underlying GSS-API mechanisms that get used, and any protocols those mechanisms might depend on. Each of these components plays a part in the security of the resulting connection, and each has its own security considerations. It's a whole web, bestie. ๐Ÿ•ธ๏ธ

The key exchange method described in Section 2 depends on the underlying GSS-API mechanism to provide both mutual authentication and per-message integrity services. If either of these features isn't supported by a particular GSS-API mechanism, or by a particular implementation of a GSS-API mechanism, then the key exchange is not secure and MUST fail. No exceptions, no vibes-based security. ๐Ÿšจ

For the "external-keyx" user authentication method to be used, it MUST have access to user authentication information obtained as a side-effect of the key exchange. If that information is unavailable, the authentication MUST fail. ๐Ÿ™…โ€โ™€๏ธ

Okay, this one is a balancing act. Revealing information about why an authentication failed may be considered by some sites to be an unacceptable security risk for a production environment. However, having that information available can be invaluable for debugging. So it is RECOMMENDED that implementations provide a means for controlling, as a matter of policy, whether to send SSH_MSG_USERAUTH_GSSAPI_ERROR, SSH_MSG_USERAUTH_GSSAPI_ERRTOK, and SSH_MSG_KEXGSS_ERROR messages, and SSH_MSG_KEXGSS_CONTINUE messages containing a GSS-API error token. Give the people in charge the knobs. ๐ŸŽ›๏ธโœจ

10. Acknowledgements ๐Ÿซถ

The authors would like to thank the following individuals for their invaluable assistance and contributions to this document: ๐Ÿ’œ

  • Sam Hartman
  • Love Hornquist-Astrand
  • Joel N. Weber II
  • Simon Wilkinson
  • Nicolas Williams

Much of the text describing DH group exchange was borrowed from [GROUP-EXCHANGE], by Markus Friedl, Niels Provos, and William A. Simpson. Shoutout to the people who wrote the homework we all copied. ๐Ÿ™Œ

11. References ๐Ÿ“š

11.1. Normative References

[ASN1]            ISO/IEC, "ASN.1 Encoding Rules: Specification of
                  Basic Encoding Rules (BER), Canonical Encoding
                  Rules (CER) and Distinguished Encoding Rules
                  (DER)", ITU-T Recommendation X.690 (1997), ISO/
                  IEC 8825-1:1998, November 1998.

[GROUP-EXCHANGE]  Friedl, M., Provos, N., and W. Simpson, "Diffie-
                  Hellman Group Exchange for the Secure Shell (SSH)
                  Transport Layer Protocol", RFC 4419, March 2006.

[GSSAPI]          Linn, J., "Generic Security Service Application
                  Program Interface Version 2, Update 1", RFC 2743,
                  January 2000.

[KEYWORDS]        Bradner, S., "Key words for use in RFCs to Indicate
                  Requirement Levels", BCP 14, RFC 2119, March 1997.

[LANGTAG]         Alvestrand, H., "Tags for the Identification of
                  Languages", BCP 47, RFC 3066, January 2001.

[MD5]             Rivest, R., "The MD5 Message-Digest Algorithm", RFC
                  1321, April 1992.

[MIME]            Freed, N. and N. Borenstein, "Multipurpose Internet
                  Mail Extensions (MIME) Part One: Format of Internet
                  Message Bodies", RFC 2045, November 1996.

[SSH-ARCH]        Ylonen, T. and C. Lonvick, "The Secure Shell (SSH)
                  Protocol Architecture", RFC 4251, January 2006.

[SSH-CONNECT]     Ylonen, T. and C. Lonvick, "The Secure Shell (SSH)
                  Connection Protocol", RFC 4254, January 2006.

[SSH-NUMBERS]     Lehtinen, S. and C. Lonvick, "The Secure Shell
                  (SSH) Protocol Assigned Numbers", RFC 4250, January
                  2006.

[SSH-TRANSPORT]   Ylonen, T. and C. Lonvick, "The Secure Shell (SSH)
                  Transport Layer Protocol", RFC 4253, January 2006.

[SSH-USERAUTH]    Ylonen, T. and C. Lonvick, "The Secure Shell (SSH)
                  Authentication Protocol", RFC 4252, January 2006.

[UTF8]            Yergeau, F., "UTF-8, a transformation format of ISO
                  10646", STD 63, RFC 3629, November 2003.

11.2. Informative References

[KRB5]            Neuman, C., Yu, T., Hartman, S., and K. Raeburn,
                  "The Kerberos Network Authentication Service (V5)",
                  RFC 4120, July 2005.

[KRB5-GSS]        Zhu, L., Jaganathan, K., and S. Hartman, "The
                  Kerberos Version 5 Generic Security Service
                  Application Program Interface (GSS-API) Mechanism:
                  Version 2", RFC 4121, July 2005.

[SASLPREP]        Zeilenga, K., "SASLprep: Stringprep Profile for
                  User Names and Passwords", RFC 4013, February 2005.

[SPNEGO]          Zhu, L., Leach, P., Jaganathan, K., and W.
                  Ingersoll, "The Simple and Protected Generic
                  Security Service Application Program Interface
                  (GSS-API) Negotiation Mechanism", RFC 4178, October
                  2005.

Authors' Addresses ๐ŸŽ€

Okay bestie, here are the humans who made this happen! ๐Ÿ’– Each block is exactly how their info appears in the RFC, so you can find them.

Jeffrey Hutzelman
Carnegie Mellon University
5000 Forbes Ave
Pittsburgh, PA  15213
US

Phone: +1 412 268 7225
EMail: jhutz+@cmu.edu
URI:   http://www.cs.cmu.edu/~jhutz/
Joseph Salowey
Cisco Systems
2901 Third Avenue
Seattle, WA  98121
US

Phone: +1 206 256 3380
EMail: jsalowey@cisco.com
Joseph Galbraith
Van Dyke Technologies, Inc.
4848 Tramway Ridge Dr. NE
Suite 101
Albuquerque, NM  87111
US

EMail: galb@vandyke.com
Von Welch
University of Chicago & Argonne National Laboratory
Distributed Systems Laboratory
701 E. Washington
Urbana, IL  61801
US

EMail: welch@mcs.anl.gov

Okay, legal stuff but make it cute ๐Ÿซถ The copyright is held by The Internet Society (2006).

This document is subject to the rights, licenses and restrictions in BCP 78. Except for what BCP 78 says, the authors keep all of their rights. โœจ

Also, this document and everything in it is provided "AS IS" ๐Ÿ˜ญ The contributor, the organization they represent or are sponsored by (if any), the Internet Society, and the Internet Engineering Task Force all disclaim every warranty, whether express or implied. That includes no promise that using the information won't infringe any rights, and no implied warranties of merchantability or fitness for a particular purpose. Not gonna lie, that's a lot of "nope" energy ๐Ÿ’€


Intellectual Property ๐Ÿ’…

The IETF doesn't take a side on whether any Intellectual Property Rights or other claimed rights are valid, or how far they reach. It also doesn't say whether a license would be available for the tech described here. And it hasn't made any independent effort to find out what rights might exist. ๐Ÿ™ˆ If you want the details on how RFC documents handle rights, check out BCP 78 and BCP 79.

Copies of IPR disclosures sent to the IETF Secretariat are available, along with any assurances of licenses. You can also find the results of anyone trying to get a general license or permission to use these proprietary rights, if that's relevant to implementers or users of this spec. All of that lives in the IETF online IPR repository at http://www.ietf.org/ipr. ๐ŸŒธ

The IETF also invites anyone to flag any copyrights, patents, patent applications, or other proprietary rights that might cover technology needed to implement this standard. Send that info to the IETF at ietf-ipr@ietf.org. Be that friend who speaks up ๐Ÿ“ฃโœจ


Acknowledgement ๐Ÿงš

Funding for the RFC Editor function comes from the IETF Administrative Support Activity (IASA). So the people keeping these documents tidy are supported by it. Thank you, IASA, you're iconic ๐Ÿ‘‘๐ŸŒˆ

๐Ÿ“ฆ where this page comes from