Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'doc/authplugin.but')
-rw-r--r--doc/authplugin.but519
1 files changed, 519 insertions, 0 deletions
diff --git a/doc/authplugin.but b/doc/authplugin.but
new file mode 100644
index 00000000..41bc0daa
--- /dev/null
+++ b/doc/authplugin.but
@@ -0,0 +1,519 @@
+\A{authplugin} PuTTY authentication plugin protocol
+
+This appendix contains the specification for the protocol spoken over
+local IPC between PuTTY and an authentication helper plugin.
+
+If you already have an authentication plugin and want to configure
+PuTTY to use it, see \k{config-ssh-authplugin} for how to do that.
+This appendix is for people writing new authentication plugins.
+
+\H{authplugin-req} Requirements
+
+The following requirements informed the specification of this protocol.
+
+\s{Automate keyboard-interactive authentication.} We're motivated in
+the first place by the observation that the general SSH userauth
+method \cq{keyboard-interactive} (defined in \k{authplugin-ref-ki})
+can be used for many kinds of challenge/response or one-time-password
+styles of authentication, and in more than one of those, the necessary
+responses might be obtained from an auxiliary network connection, such
+as an HTTPS transaction. So it's useful if a user doesn't have to
+manually copy-type or copy-paste from their web browser into their SSH
+client, but instead, the process can be automated.
+
+\s{Be able to pass prompts on to the user.} On the other hand, some
+userauth methods can be only \e{partially} automated; some of the
+server's prompts might still require human input. Also, the plugin
+automating the authentication might need to ask its own questions that
+are not provided by the SSH server. (For example, \q{please enter the
+master key that the real response will be generated by hashing}.) So
+after the plugin intercepts the server's questions, it needs to be
+able to ask its own questions of the user, which may or may not be the
+same questions sent by the server.
+
+\s{Allow automatic generation of the username.} Sometimes, the
+authentication method comes with a mechanism for discovering the
+username to be used in the SSH login. So the plugin has to start up
+early enough that the client hasn't committed to a username yet.
+
+\s{Future expansion route to other SSH userauth flavours.} The initial
+motivation for this protocol is specific to keyboard-interactive. But
+other SSH authentication methods exist, and they may also benefit from
+automation in future. We're making no attempt here to predict what
+those methods might be or how they might be automated, but we do need
+to leave a space where they can be slotted in later if necessary.
+
+\s{Minimal information loss.} Keyboard-interactive prompts and replies
+should be passed to and from the plugin in a form as close as possible
+to the way they look on the wire in SSH itself. Therefore, the
+protocol resembles SSH in its data formats and marshalling (instead
+of, for example, translating from SSH binary packet style to another
+well-known format such as JSON, which would introduce edge cases in
+character encoding).
+
+\s{Half-duplex.} Simultaneously trying to read one I/O stream and
+write another adds a lot of complexity to software. It becomes
+necessary to have an organised event loop containing \cw{select} or
+\cw{WaitForMultipleObjects} or similar, which can invoke the handler
+for whichever event happens soonest. There's no need to add that
+complexity in an application like this, which isn't transferring large
+amounts of bulk data or multiplexing unrelated activities. So, to keep
+life simple for plugin authors, we set the ground rule that it must
+always be 100% clear which side is supposed to be sending a message
+next. That way, the plugin can be written as sequential code
+progressing through the protocol, making simple read and write calls
+to receive or send each message.
+
+\s{Communicate success/failure, to facilitate caching in the plugin.}
+A plugin might want to cache recently used data for next time, but
+only in the case where authentication using that data was actually
+successful. So the client has to tell the plugin what the outcome was,
+if it's known. (But this is best-effort only. Obviously the plugin
+cannot \e{depend} on hearing the answer, because any IPC protocol at
+all carries the risk that the other end might crash or be killed by
+things outside its control.)
+
+\H{authplugin-transport} Transport and configuration
+
+Plugins are executable programs on the client platform.
+
+The SSH client must be manually configured to use a plugin for a
+particular connection. The configuration takes the form of a command
+line, including the location of the plugin executable, and optionally
+command-line arguments that are meaningful to the particular plugin.
+
+The client invokes the plugin as a subprocess, passing it a pair of
+8-bit-clean pipes as its standard input and output. On those pipes,
+the client and plugin will communicate via the protocol specified
+below.
+
+\H{authplugin-formats} Data formats and marshalling
+
+This protocol borrows the low-level data formatting from SSH itself,
+in particular the following wire encodings from
+\k{authplugin-ref-arch} section 5:
+
+\dt \s{byte}
+
+\dd An integer between 0 and 0xFF inclusive, transmitted as a single
+byte of binary data.
+
+\dt \s{boolean}
+
+\dd The values \q{true} or \q{false}, transmitted as the bytes 1 and 0
+respectively.
+
+\dt \s{uint32}
+
+\dd An integer between 0 and 0xFFFFFFFF inclusive, transmitted as 4
+bytes of binary data, in big-endian (\q{network}) byte order.
+
+\dt \s{string}
+
+\dd A sequence of bytes, preceded by a \s{uint32} giving the number of
+bytes in the sequence. The length field does not include itself. For
+example, the empty string is represented by four zero bytes (the
+\s{uint32} encoding of 0); the string "AB" is represented by the six
+bytes 0,0,0,2,'A','B'.
+
+Unlike SSH itself, the protocol spoken between the client and the
+plugin is unencrypted, because local inter-process pipes are assumed
+to be secured by the OS kernel. So the binary packet protocol is much
+simpler than SSH proper, and is similar to SFTP and the OpenSSH agent
+protocol.
+
+The data sent in each direction of the conversation consists of a
+sequence of \s{messages} exchanged between the SSH client and the
+plugin. Each message is encoded as a \s{string}. The contents of the
+string begin with a \s{byte} giving the message type, which determines
+the format of the rest of the message.
+
+\H{authplugin-version} Protocol versioning
+
+This protocol itself is versioned. At connection setup, the client
+states the highest version number it knows how to speak, and then the
+plugin responds by choosing the version number that will actually be
+spoken (which may not be higher than the client's value).
+
+Including a version number makes it possible to make breaking changes
+to the protocol later.
+
+Even version numbers represent released versions of this spec. Odd
+numbers represent drafts or development versions in between releases.
+A client and plugin negotiating an odd version number are not
+guaranteed to interoperate; the developer testing the combination is
+responsible for ensuring the two are compatible.
+
+This document describes version 2 of the protocol, the first released
+version. (The initial drafts had version 1.)
+
+\H{authplugin-overview} Overview and sequence of events
+
+At the very beginning of the user authentication phase of SSH, the
+client launches the plugin subprocess, if one is configured. It
+immediately sends the \cw{PLUGIN_INIT} message, telling the plugin
+some initial information about where the SSH connection is to.
+
+The plugin responds with \cw{PLUGIN_INIT_RESPONSE}, which may
+optionally tell the SSH client what username to use.
+
+The client begins trying to authenticate with the SSH server in the
+usual way, using the username provided by the plugin (if any) or
+alternatively one obtained via its normal (non-plugin) policy.
+
+The client follows its normal policy for selecting authentication
+methods to attempt. If it chooses a method that this protocol does not
+cover, then the client will perform that method in its own way without
+consulting the plugin.
+
+However, if the client and server decide to attempt a method that this
+protocol \e{does} cover, then the client sends \cw{PLUGIN_PROTOCOL}
+specifying the SSH protocol id for the authentication method being
+used. The plugin responds with \cw{PLUGIN_PROTOCOL_ACCEPT} if it's
+willing to assist with this auth method, or
+\cw{PLUGIN_PROTOCOL_REJECT} if it isn't.
+
+If the plugin sends \cw{PLUGIN_PROTOCOL_REJECT}, then the client will
+proceed as if the plugin were not present. Later, if another auth
+method is negotiated (either because this one failed, or because it
+succeeded but the server wants multiple auth methods), the client may
+send a further \cw{PLUGIN_PROTOCOL} and try again.
+
+If the plugin sends \cw{PLUGIN_PROTOCOL_ACCEPT}, then a protocol
+segment begins that is specific to that auth method, terminating in
+either \cw{PLUGIN_AUTH_SUCCESS} or \cw{PLUGIN_AUTH_FAILURE}. After
+that, again, the client may send a further \cw{PLUGIN_PROTOCOL}.
+
+Currently the only supported method is \cq{keyboard-interactive},
+defined in \k{authplugin-ref-ki}. Once the client has announced this
+to the server, the followup protocol is as follows:
+
+Each time the server sends an \cw{SSH_MSG_USERAUTH_INFO_REQUEST}
+message requesting authentication responses from the user, the SSH
+client translates the message into \cw{PLUGIN_KI_SERVER_REQUEST} and
+passes it on to the plugin.
+
+At this point, the plugin may optionally send back
+\cw{PLUGIN_KI_USER_REQUEST} containing prompts to be presented to the
+actual user. The client will reply with a matching
+\cw{PLUGIN_KI_USER_RESPONSE} after asking the user to reply to the
+question(s) in the request message. The plugin can repeat this cycle
+multiple times.
+
+Once the plugin has all the information it needs to respond to the
+server's authentication prompts, it sends \cw{PLUGIN_KI_SERVER_RESPONSE}
+back to the client, which translates it into
+\cw{SSH_MSG_USERAUTH_INFO_RESPONSE} to send on to the server.
+
+After that, as described in \k{authplugin-ref-ki}, the server is free
+to accept authentication, reject it, or send another
+\cw{SSH_MSG_USERAUTH_INFO_REQUEST}. Each
+\cw{SSH_MSG_USERAUTH_INFO_REQUEST} is dealt with in the same way as
+above.
+
+If the server terminates keyboard-interactive authentication with
+\cw{SSH_MSG_USERAUTH_SUCCESS} or \cw{SSH_MSG_USERAUTH_FAILURE}, the
+client informs the plugin by sending either \cw{PLUGIN_AUTH_SUCCESS}
+or \cw{PLUGIN_AUTH_FAILURE}. \cw{PLUGIN_AUTH_SUCCESS} is sent when
+\e{that particular authentication method} was successful, regardless
+of whether the SSH server chooses to request further authentication
+afterwards: in particular, \cw{SSH_MSG_USERAUTH_FAILURE} with the
+\q{partial success} flag (see \k{authplugin-ref-userauth} section 5.1) translates
+into \cw{PLUGIN_AUTH_SUCCESS}.
+
+The plugin's standard input will close when the client no longer
+requires the plugin's services, for any reason. This could be because
+authentication is complete (with overall success or overall failure),
+or because the user has manually aborted the session in
+mid-authentication, or because the client crashed.
+
+\H{authplugin-messages} Message formats
+
+This section describes the format of every message in the protocol.
+
+As described in \k{authplugin-formats}, every message starts with the same two
+fields:
+
+\b \s{uint32}: overall length of the message
+
+\b \s{byte}: message type.
+
+The length field does not include itself, but does include the type
+code.
+
+The following subsections each give the format of the remainder of the
+message, after the type code.
+
+The type codes themselves are defined here:
+
+\c #define PLUGIN_INIT 1
+\c #define PLUGIN_INIT_RESPONSE 2
+\c #define PLUGIN_PROTOCOL 3
+\c #define PLUGIN_PROTOCOL_ACCEPT 4
+\c #define PLUGIN_PROTOCOL_REJECT 5
+\c #define PLUGIN_AUTH_SUCCESS 6
+\c #define PLUGIN_AUTH_FAILURE 7
+\c #define PLUGIN_INIT_FAILURE 8
+\c
+\c #define PLUGIN_KI_SERVER_REQUEST 20
+\c #define PLUGIN_KI_SERVER_RESPONSE 21
+\c #define PLUGIN_KI_USER_REQUEST 22
+\c #define PLUGIN_KI_USER_RESPONSE 23
+
+If this protocol is extended to be able to assist with further auth
+methods, their message type codes will also begin from 20, overlapping
+the codes for keyboard-interactive.
+
+\S{PLUGIN_INIT} \cw{PLUGIN_INIT}
+
+\s{Direction}: client to plugin
+
+\s{When}: the first message sent at connection startup
+
+\s{What happens next}: the plugin will send \cw{PLUGIN_INIT_RESPONSE}
+or \cw{PLUGIN_INIT_FAILURE}
+
+\s{Message contents after the type code}:
+
+\b \s{uint32}: the highest version number of this protocol that the
+client knows how to speak.
+
+\b \s{string}: the hostname of the server. This will be the \e{logical}
+hostname, in cases where it differs from the physical destination of
+the network connection. Whatever name would be used by the SSH client
+to cache the server's host key, that's the same name passed in this
+message.
+
+\b \s{uint32}: the port number on the server. (Together with the host
+name, this forms a primary key identifying a particular server. Port
+numbers may be vital because a single host can run two unrelated SSH
+servers with completely different authentication requirements, e.g.
+system sshd on port 22 and Gerrit on port 29418.)
+
+\b \s{string}: the username that the client will use to log in, if the
+plugin chooses not to override it. An empty string means that the
+client has no opinion about this (and might, for example, prompt the
+user).
+
+\S{PLUGIN_INIT_RESPONSE} \cw{PLUGIN_INIT_RESPONSE}
+
+\s{Direction}: plugin to client
+
+\s{When}: response to \cw{PLUGIN_INIT}
+
+\s{What happens next}: the client will send \cw{PLUGIN_PROTOCOL}, or
+perhaps terminate the session (if no auth method is ever negotiated
+that the plugin can help with)
+
+\s{Message contents after the type code}:
+
+\b \s{uint32}: the version number of this protocol that the connection
+will use. Must be no greater than the max version number sent by the
+client in \cw{PLUGIN_INIT}.
+
+\b \s{string}: the username that the plugin suggests the client use. An
+empty string means that the plugin has no opinion and the client
+should stick with the username it already had (or prompt the user, if
+it had none).
+
+\S{PLUGIN_INIT_FAILURE} \cw{PLUGIN_INIT_FAILURE}
+
+\s{Direction}: plugin to client
+
+\s{When}: response to \cw{PLUGIN_INIT}
+
+\s{What happens next}: the session is over
+
+\s{Message contents after the type code}:
+
+\b \s{string}: an error message to present to the user indicating why
+the plugin was unable to start up.
+
+\S{PLUGIN_PROTOCOL} \cw{PLUGIN_PROTOCOL}
+
+\s{Direction}: client to plugin
+
+\s{When}: sent after \cw{PLUGIN_INIT_RESPONSE}, or after a previous
+auth phase terminates with \cw{PLUGIN_AUTH_SUCCESS} or
+\cw{PLUGIN_AUTH_FAILURE}
+
+\s{What happens next}: the plugin will send
+\cw{PLUGIN_PROTOCOL_ACCEPT} or \cw{PLUGIN_PROTOCOL_REJECT}
+
+\s{Message contents after the type code}:
+
+\b \s{string}: the SSH protocol id of the auth method the client
+intends to attempt. Currently the only method specified for use in
+this protocol is \cq{keyboard-interactive}.
+
+\S{PLUGIN_PROTOCOL_REJECT} \cw{PLUGIN_PROTOCOL_REJECT}
+
+\s{Direction}: plugin to client
+
+\s{When}: sent after \cw{PLUGIN_PROTOCOL}
+
+\s{What happens next}: the client will either send another
+\cw{PLUGIN_PROTOCOL} or terminate the session
+
+\s{Message contents after the type code}:
+
+\b \s{string}: an error message to present to the user, explaining why
+the plugin cannot help with this authentication protocol.
+
+\lcont{
+
+An example might be \q{unable to open <config file>: <OS error
+message>}, if the plugin depends on some configuration that the user
+has not set up.
+
+If the plugin does not support this this particular authentication
+protocol at all, this string should be left blank, so that no message
+will be presented to the user at all.
+
+}
+
+\S{PLUGIN_PROTOCOL_ACCEPT} \cw{PLUGIN_PROTOCOL_ACCEPT}
+
+\s{Direction}: plugin to client
+
+\s{When}: sent after \cw{PLUGIN_PROTOCOL}
+
+\s{What happens next}: depends on the auth protocol agreed on. For
+keyboard-interactive, the client will send
+\cw{PLUGIN_KI_SERVER_REQUEST} or \cw{PLUGIN_AUTH_SUCCESS} or
+\cw{PLUGIN_AUTH_FAILURE}. No other method is specified.
+
+\s{Message contents after the type code}: none.
+
+\S{PLUGIN_KI_SERVER_REQUEST} \cw{PLUGIN_KI_SERVER_REQUEST}
+
+\s{Direction}: client to plugin
+
+\s{When}: sent after \cw{PLUGIN_PROTOCOL}, or after a previous
+\cw{PLUGIN_KI_SERVER_RESPONSE}, when the SSH server has sent
+\cw{SSH_MSG_USERAUTH_INFO_REQUEST}
+
+\s{What happens next}: the plugin will send either
+\cw{PLUGIN_KI_USER_REQUEST} or \cw{PLUGIN_KI_SERVER_RESPONSE}
+
+\s{Message contents after the type code}: the exact contents of the
+\cw{SSH_MSG_USERAUTH_INFO_REQUEST} just sent by the server. See
+\k{authplugin-ref-ki} section 3.2 for details. The summary:
+
+\b \s{string}: name of this prompt collection (e.g. to use as a
+dialog-box title)
+
+\b \s{string}: instructions to be displayed before this prompt
+collection
+
+\b \s{string}: language tag (deprecated)
+
+\b \s{uint32}: number of prompts in this collection
+
+\b That many copies of:
+
+\lcont{
+
+\b \s{string}: prompt (in UTF-8)
+
+\b \s{boolean}: whether the response to this prompt is safe to echo to
+the screen
+
+}
+
+\S{PLUGIN_KI_SERVER_RESPONSE} \cw{PLUGIN_KI_SERVER_RESPONSE}
+
+\s{Direction}: plugin to client
+
+\s{When}: response to \cw{PLUGIN_KI_SERVER_REQUEST}, perhaps after one
+or more intervening pairs of \cw{PLUGIN_KI_USER_REQUEST} and
+\cw{PLUGIN_KI_USER_RESPONSE}
+
+\s{What happens next}: the client will send a further
+\cw{PLUGIN_KI_SERVER_REQUEST}, or \cw{PLUGIN_AUTH_SUCCESS} or
+\cw{PLUGIN_AUTH_FAILURE}
+
+\s{Message contents after the type code}: the exact contents of the
+\cw{SSH_MSG_USERAUTH_INFO_RESPONSE} that the client should send back
+to the server. See \k{authplugin-ref-ki} section 3.4 for details. The
+summary:
+
+\b \s{uint32}: number of responses (must match the \q{number of
+prompts} field from the corresponding server request)
+
+\b That many copies of:
+
+\lcont{
+
+\b \s{string}: response to the \e{n}th prompt (in UTF-8)
+
+}
+
+\S{PLUGIN_KI_USER_REQUEST} \cw{PLUGIN_KI_USER_REQUEST}
+
+\s{Direction}: plugin to client
+
+\s{When}: response to \cw{PLUGIN_KI_SERVER_REQUEST}, if the plugin
+cannot answer the server's auth prompts without presenting prompts of
+its own to the user
+
+\s{What happens next}: the client will send \cw{PLUGIN_KI_USER_RESPONSE}
+
+\s{Message contents after the type code}: exactly the same as in
+\cw{PLUGIN_KI_SERVER_REQUEST} (see \k{PLUGIN_KI_SERVER_REQUEST}).
+
+\S{PLUGIN_KI_USER_RESPONSE} \cw{PLUGIN_KI_USER_RESPONSE}
+
+\s{Direction}: client to plugin
+
+\s{When}: response to \cw{PLUGIN_KI_USER_REQUEST}
+
+\s{What happens next}: the plugin will send
+\cw{PLUGIN_KI_SERVER_RESPONSE}, or another \cw{PLUGIN_KI_USER_REQUEST}
+
+\s{Message contents after the type code}: exactly the same as in
+\cw{PLUGIN_KI_SERVER_RESPONSE} (see \k{PLUGIN_KI_SERVER_RESPONSE}).
+
+\S{PLUGIN_AUTH_SUCCESS} \cw{PLUGIN_AUTH_SUCCESS}
+
+\s{Direction}: client to plugin
+
+\s{When}: sent after \cw{PLUGIN_KI_SERVER_RESPONSE}, or (in unusual
+cases) after \cw{PLUGIN_PROTOCOL_ACCEPT}
+
+\s{What happens next}: the client will either send another
+\cw{PLUGIN_PROTOCOL} or terminate the session
+
+\s{Message contents after the type code}: none
+
+\S{PLUGIN_AUTH_FAILURE} \cw{PLUGIN_AUTH_FAILURE}
+
+\s{Direction}: client to plugin
+
+\s{When}: sent after \cw{PLUGIN_KI_SERVER_RESPONSE}, or (in unusual
+cases) after \cw{PLUGIN_PROTOCOL_ACCEPT}
+
+\s{What happens next}: the client will either send another
+\cw{PLUGIN_PROTOCOL} or terminate the session
+
+\s{Message contents after the type code}: none
+
+\H{authplugin-refs} References
+
+\B{authplugin-ref-arch} \W{https://www.rfc-editor.org/rfc/rfc4251}{RFC 4251}, \q{The Secure Shell (SSH) Protocol
+Architecture}.
+
+\B{authplugin-ref-userauth} \W{https://www.rfc-editor.org/rfc/rfc4252}{RFC
+4252}, \q{The Secure Shell (SSH) Authentication Protocol}.
+
+\B{authplugin-ref-ki}
+\W{https://www.rfc-editor.org/rfc/rfc4256}{RFC 4256},
+\q{Generic Message Exchange Authentication for the Secure Shell
+Protocol (SSH)} (better known by its wire id
+\q{keyboard-interactive}).
+
+\BR{authplugin-ref-arch} [RFC4251]
+
+\BR{authplugin-ref-userauth} [RFC4252]
+
+\BR{authplugin-ref-ki} [RFC4256]