Generic Security Service Application Program Interface (GSS-API) Authentication and Key Exchange for the Secure Shell (SSH) Protocol
updated by
Extracted elements (30)
SPNEGO is prohibited because SSH already performs its own method negotiation, making SPNEGO's negotiation protection redundant. Furthermore, mixing SPNEGO and non-SPNEGO variants of the same mechanism creates interoperability problems and can subvert SSH's own negotiation order, potentially selecting a weaker method.
The 'null' host key algorithm exists to allow servers in Kerberos-only environments to advertise a valid key exchange algorithm when policy prohibits use of public-key host keys. Without it, a server configured to require GSS-API/Kerberos key exchange would have nothing to advertise in its host key algorithm list.
When a new host key for an already-known host is received via SSH_MSG_KEXGSS_HOSTKEY, clients SHOULD NOT issue strong warnings or abort, provided the GSS-API key exchange succeeds. Unlike traditional SSH, GSS-API-based key exchange authenticates new host keys, and host keys may change more frequently in GSS-API-heavy environments.
A client MUST NOT use the 'gssapi-keyex' method if the initial key exchange was not performed using a GSS-API-based method per Section 2. If a server receives such a request, it MUST return SSH_MSG_USERAUTH_FAILURE.
Channel bindings SHOULD NOT be specified in calls during GSS-API context establishment. No standard channel binding data is defined by this document, and use of network addresses as channel bindings may break SSH in the environments where it is most useful.
Either side MUST NOT send or accept Diffie-Hellman values e or f that are not in the range [1, p-1]. If this condition is violated, the key exchange fails.
If the client receives SSH_MSG_KEXGSS_CONTINUE after GSS_Init_sec_context() has already returned GSS_S_COMPLETE, or receives SSH_MSG_KEXGSS_COMPLETE (with boolean TRUE) after GSS_S_COMPLETE, a protocol error has occurred and the key exchange MUST fail.
Implementations of mechanisms conforming to this document MUST NOT use the results of insecure DNS queries to construct the GSS-API targ_name. If a client system is unable to securely determine the targ_name, it SHOULD NOT use this mechanism.
Mechanisms conforming to this document MUST NOT use SPNEGO as the underlying GSS-API mechanism. SPNEGO is both unnecessary (SSH performs its own method negotiation) and potentially harmful because it can result in use of a weaker method than desired.
Servers and clients SHOULD support DH groups with modulus length k bits where 1024 <= k <= 8192 for group exchange. The recommended values for min and max are 1024 and 8192 respectively.
Servers MUST NOT advertise the 'null' host key algorithm unless it is the only algorithm advertised. SSH_MSG_KEXGSS_HOSTKEY MUST NOT be sent when the 'null' host key algorithm is in use.
The server MUST choose the first mechanism OID from the client's list that it supports. If no OIDs are supported, the server MUST fail the request by sending SSH_MSG_USERAUTH_FAILURE. If a non-empty user name is presented and not authorized, authentication MUST fail.
When calling GSS_Init_sec_context() during key exchange, the client MUST set mutual_req_flag to 'true' to request mutual authentication and MUST set integ_req_flag to 'true' to request per-message integrity protection. If the resulting context does not have mutual_state or integ_avail set, the key exchange MUST fail.
When calling GSS_Init_sec_context() during user authentication, the client MUST set integ_req_flag to 'true'. The mutual_req_flag and replay_det_req_flag/sequence_req_flag SHOULD be set to 'false' since user auth only authenticates the client, not the server.
When the server receives SSH_MSG_USERAUTH_GSSAPI_MIC before the GSS-API context is fully established, or when the negotiated context does not support per-message integrity, the server MUST fail the authentication.
The gss-gex-sha1-* family uses SHA-1 and the group-exchange mechanism from RFC 4419, adding SSH_MSG_KEXGSS_GROUPREQ (byte 40) and SSH_MSG_KEXGSS_GROUP (byte 41) messages. The exchange hash for group exchange additionally includes min, n, max, p, and g fields.
The gss-group1-sha1-* family of key exchange methods uses SHA-1 as HASH and the 1024-bit group from SSH-TRANSPORT Section 8.1. Method names are formed by concatenating 'gss-group1-sha1-' with the Base64(MD5(DER(OID))) of the underlying GSS-API mechanism's OID.
The gss-group14-sha1-* family uses SHA-1 as HASH and the 2048-bit group from SSH-TRANSPORT Section 8.2. Method names follow the same Base64(MD5(DER(OID))) naming pattern with prefix 'gss-group14-sha1-'.
The 'gssapi-keyex' user authentication method reuses the GSS-API context established during the initial key exchange. It sends a single SSH_MSG_USERAUTH_REQUEST with a MIC computed over session identifier, request type, user name, service, and 'gssapi-keyex'. Any context from rekeying MUST NOT be used.
The 'null' host key algorithm has no associated key material and provides neither signature nor encryption. It is used when the host does not have or does not wish to use a public key, for example in Kerberos-only deployments. Any implementation supporting at least one Section 2 key exchange method MUST also support 'null'.
Message numbers defined: SSH_MSG_KEXGSS_INIT=30, CONTINUE=31, COMPLETE=32, HOSTKEY=33, ERROR=34, GROUPREQ=40, GROUP=41 for key exchange; SSH_MSG_USERAUTH_GSSAPI_RESPONSE=60, TOKEN=61, EXCHANGE_COMPLETE=63, ERROR=64, ERRTOK=65, MIC=66 for user authentication. Number 62 is unused in this specification.
This document registers SSH key exchange method name families 'gss-group1-sha1-*', 'gss-group14-sha1-*', and 'gss-gex-sha1-*'; reserves all 'gss-*' key exchange names; registers host public key algorithm 'null'; registers user authentication method names 'gssapi-with-mic' and 'gssapi-keyex'; reserves 'gssapi' and 'external-keyx' for backwards compatibility.
Revealing error details about authentication failures may be unacceptable under site security policy. Implementations SHOULD provide a means to suppress SSH_MSG_USERAUTH_GSSAPI_ERROR, SSH_MSG_USERAUTH_GSSAPI_ERRTOK, SSH_MSG_KEXGSS_ERROR, and GSS error tokens in SSH_MSG_KEXGSS_CONTINUE messages as a matter of configurable policy.
The key exchange method depends on the underlying GSS-API mechanism to provide both mutual authentication and per-message integrity. If either feature is unsupported by the mechanism or its implementation, the key exchange is not secure and MUST fail. Security of the overall connection depends on SSH, the GSS-API, and all underlying mechanisms.
SSH_MSG_KEXGSS_COMPLETE (byte 32) carries: mpint f, string per_msg_token (GSS MIC of H), boolean indicating whether an additional output_token follows, and optionally that string output_token. Two variants exist depending on whether the final GSS_Accept_sec_context() produced a non-zero-length token.
SSH_MSG_KEXGSS_ERROR (byte 34) carries: uint32 major_status, uint32 minor_status, string message (UTF-8 encoded, may contain CRLF-separated lines), string language tag. An analogous SSH_MSG_USERAUTH_GSSAPI_ERROR (byte 64) carries the same fields for user authentication errors.
SSH_MSG_KEXGSS_INIT (byte 30) carries: a string output_token from GSS_Init_sec_context() and an mpint e (the client's DH public value). The client MUST include e with the first message; receiving more than one e or none causes key exchange failure.
SSH_MSG_USERAUTH_GSSAPI_MIC (byte 66) carries a single string MIC field obtained by calling GSS_GetMIC() over: session identifier (string), SSH_MSG_USERAUTH_REQUEST (byte), user name, service, and 'gssapi-with-mic'. This message MUST be sent only after GSS_S_COMPLETE with integ_avail set.
SSH_MSG_USERAUTH_REQUEST for the 'gssapi-with-mic' method carries: user name (UTF-8 string), service name (ASCII string), method name 'gssapi-with-mic', uint32 n (number of mechanism OIDs), and n DER-encoded mechanism OID strings listed in order of preference.
The exchange hash H is computed as HASH(V_C || V_S || I_C || I_S || K_S || e || f || K) where all fields are strings or mpints as defined. GSS_GetMIC MUST be applied over H, not the original data. If no SSH_MSG_KEXGSS_HOSTKEY was sent, the empty string is used for K_S.