Secure Shell Public Key Subsystem
updated by
- rfc-9519 — Update to the IANA SSH Protocol Parameters Registry Requirements
Extracted elements (30)
Implementations MAY use the first 15 bytes of the version packet as a 'magic cookie' (0x00 0x00 0x00 0x0F 0x00 0x00 0x00 0x07 0x76 0x65 0x72 0x73 0x69 0x6F 0x6E) to avoid processing spurious output from the user's shell, as described in Section 6.5 of the SSH Connection Protocol.
The Public Key Subsystem is designed for extreme simplicity in implementation and is not intended as a PKIX replacement. It provides an implementation-independent mechanism to configure SSH public keys, allowing client software to take on the burden of key distribution that SSH itself does not define.
All IANA-registered names MUST be printable US-ASCII strings, MUST NOT contain '@', ',', whitespace, or control characters (ASCII ≤ 32), are case-sensitive, and MUST NOT exceed 64 characters. Locally extensible names use the format 'name@domainname' where the domain portion must be a valid FQDN controlled by the defining organization.
Client implementations SHOULD reject SSH_MSG_CHANNEL_REQUEST for the publickey subsystem since it is normally sent only by the client, not the server. If want reply is TRUE, the server MUST respond with SSH_MSG_CHANNEL_SUCCESS or SSH_MSG_CHANNEL_FAILURE.
If password authentication is used to access the subsystem, servers SHOULD provide a configuration option to disable password authentication after the first public key is added.
If the server does not implement a critical attribute, it MUST fail the add with SSH_PUBLICKEY_ATTRIBUTE_NOT_SUPPORTED. Mere storage of the attribute is insufficient; the server must understand and implement the intent of the attribute.
If the server does not support administrative enforcement of attributes, it MUST return false in the compulsory field of listattributes responses. An implementation MAY choose not to support the listattributes request at all.
The server MUST attempt to store the public key for the authenticated user. If overwrite is false and the key already exists, the server MUST return SSH_PUBLICKEY_KEY_ALREADY_PRESENT. If overwrite is true but the key cannot be overwritten, the server MUST return SSH_PUBLICKEY_ACCESS_DENIED.
The server SHOULD respond with SSH_MSG_CHANNEL_FAILURE if the user is not allowed access to the Public Key Subsystem (e.g., authenticated with a restricted public key). Clients SHOULD request and check the reply for the subsystem open request.
There is no requirement that list responses be in any particular order. Client implementations MUST NOT rely on responses being in any order. Implementations SHOULD support the 'list' request.
The 'command-override' attribute specifies a command to execute in place of 'exec' or 'shell' requests when this key is in use; an empty value denies both. This attribute SHOULD be marked critical.
The 'comment' attribute contains user-specified UTF-8 text about the public key. The server MUST NOT interpret or act upon its content, SHOULD preserve it and return it in list operations, and this attribute SHOULD NOT be marked critical.
The 'from' attribute specifies a comma-separated list of hosts from which this key may be used. Authorizations from unlisted hosts MUST be denied, and the server SHOULD log such attempts. Identification may use IP address or reverse DNS lookup.
The 'port-forward' attribute restricts direct-tcpip requests to a comma-separated list of allowed hosts; an empty value denies all. The 'reverse-forward' attribute similarly restricts tcpip-forward requests to specified port numbers. Both SHOULD be critical.
The 'subsystem' attribute specifies a comma-separated list of subsystems that may be started via a 'subsystem' request when this key is in use; an empty value denies all subsystems. This attribute SHOULD be critical.
The 'x11', 'shell', 'exec', 'agent', and 'env' attributes each deny their respective session channel request types when the key is in use. The attribute-value field SHOULD be empty for each, and each SHOULD be marked critical.
IANA registries created by this document: Public Key Subsystem Request Names (version, add, remove, list, listattributes), Public Key Subsystem Response Names (version, status, publickey, attribute), and Public Key Subsystem Attribute Names (comment, comment-language, command-override, subsystem, x11, shell, exec, agent, env, from, port-forward, reverse-forward). New names require IETF Consensus.
Status codes range 0–255; 0–191 require Standards Action for new assignments; 192–255 are reserved for private/local use. Initial assignments: SSH_PUBLICKEY_SUCCESS (0), SSH_PUBLICKEY_ACCESS_DENIED (1), SSH_PUBLICKEY_STORAGE_EXCEEDED (2), SSH_PUBLICKEY_VERSION_NOT_SUPPORTED (3), SSH_PUBLICKEY_KEY_NOT_FOUND (4), SSH_PUBLICKEY_KEY_NOT_SUPPORTED (5), SSH_PUBLICKEY_KEY_ALREADY_PRESENT (6), SSH_PUBLICKEY_GENERAL_FAILURE (7), SSH_PUBLICKEY_REQUEST_NOT_SUPPORTED (8), SSH_PUBLICKEY_ATTRIBUTE_NOT_SUPPORTED (9).
Implementation errors in the server's handling of key attributes could cause keys to be authorized for access they were not intended to have, or have fewer restrictions applied than intended. Correct attribute implementation is critical to maintaining the security model.
This protocol assumes it runs over a secure channel with authenticated endpoints (i.e., SSH transport and user authentication layers) and is externally protected from network-level attacks. The server is responsible for enforcing access controls on the authenticated user.
Users may overwrite an existing key on the server while specifying fewer restrictions than previously present. Servers MUST take care to prevent clients from overriding administrator-enforced presets when performing overwrites.
Version negotiation: both sides send their highest supported version; the lower value is the protocol version to use. If either side cannot support the lower version, it SHOULD send SSH_PUBLICKEY_VERSION_NOT_SUPPORTED and then close the subsystem via SSH_MSG_CHANNEL_CLOSE. This is the only case where the client sends a status message.
All Public Key Subsystem requests and responses are encoded as: uint32 length (covers name + data, not itself), string name, followed by request/response-specific data. The client MUST receive acknowledgement of each request prior to sending a new request.
The 'add' request is encoded as: string 'add', string public key algorithm name, string public key blob, boolean overwrite, uint32 attribute-count, followed by attribute-count repetitions of {string attrib-name, string attrib-value, bool critical}.
The 'list' response returns zero or more packets each encoded as: string 'publickey', string public key algorithm name, string public key blob, uint32 attribute-count, followed by attribute-count repetitions of {string attrib-name, string attrib-value}. A final status packet MUST be sent after all responses.
The 'listattributes' response returns zero or more packets each encoded as: string 'attribute', string attribute name, boolean compulsory. The 'compulsory' field indicates whether the attribute is enforced by server administrative policy regardless of client specification. A status packet MUST be sent after all responses.
The 'remove' request is encoded as: string 'remove', string public key algorithm name, string public key blob. The server MUST attempt to remove the specified key for the authenticated user so it cannot be used for subsequent authentications.
The status message is encoded as: string 'status', uint32 status code, string description (UTF-8), string language tag (BCP 47). A status message MUST be sent for any unrecognized packets, and the subsystem SHOULD NOT be closed in response.
The subsystem is opened via SSH_MSG_CHANNEL_REQUEST with fields: byte SSH_MSG_CHANNEL_REQUEST, uint32 recipient channel, string 'subsystem', boolean want reply, string 'publickey'.
The version packet is encoded as: string 'version', uint32 protocol-version-number. Both sides MUST start the connection by sending this packet and MUST wait to receive it before continuing. This document defines version 2; the 'version' packet MUST NOT be sent again after the initial exchange.