authplugin.but 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. \A{authplugin} PuTTY authentication plugin protocol
  2. This appendix contains the specification for the protocol spoken over
  3. local IPC between PuTTY and an authentication helper plugin.
  4. If you already have an authentication plugin and want to configure
  5. PuTTY to use it, see \k{config-ssh-authplugin} for how to do that.
  6. This appendix is for people writing new authentication plugins.
  7. \H{authplugin-req} Requirements
  8. The following requirements informed the specification of this protocol.
  9. \s{Automate keyboard-interactive authentication.} We're motivated in
  10. the first place by the observation that the general SSH userauth
  11. method \cq{keyboard-interactive} (defined in \k{authplugin-ref-ki})
  12. can be used for many kinds of challenge/response or one-time-password
  13. styles of authentication, and in more than one of those, the necessary
  14. responses might be obtained from an auxiliary network connection, such
  15. as an HTTPS transaction. So it's useful if a user doesn't have to
  16. manually copy-type or copy-paste from their web browser into their SSH
  17. client, but instead, the process can be automated.
  18. \s{Be able to pass prompts on to the user.} On the other hand, some
  19. userauth methods can be only \e{partially} automated; some of the
  20. server's prompts might still require human input. Also, the plugin
  21. automating the authentication might need to ask its own questions that
  22. are not provided by the SSH server. (For example, \q{please enter the
  23. master key that the real response will be generated by hashing}.) So
  24. after the plugin intercepts the server's questions, it needs to be
  25. able to ask its own questions of the user, which may or may not be the
  26. same questions sent by the server.
  27. \s{Allow automatic generation of the username.} Sometimes, the
  28. authentication method comes with a mechanism for discovering the
  29. username to be used in the SSH login. So the plugin has to start up
  30. early enough that the client hasn't committed to a username yet.
  31. \s{Future expansion route to other SSH userauth flavours.} The initial
  32. motivation for this protocol is specific to keyboard-interactive. But
  33. other SSH authentication methods exist, and they may also benefit from
  34. automation in future. We're making no attempt here to predict what
  35. those methods might be or how they might be automated, but we do need
  36. to leave a space where they can be slotted in later if necessary.
  37. \s{Minimal information loss.} Keyboard-interactive prompts and replies
  38. should be passed to and from the plugin in a form as close as possible
  39. to the way they look on the wire in SSH itself. Therefore, the
  40. protocol resembles SSH in its data formats and marshalling (instead
  41. of, for example, translating from SSH binary packet style to another
  42. well-known format such as JSON, which would introduce edge cases in
  43. character encoding).
  44. \s{Half-duplex.} Simultaneously trying to read one I/O stream and
  45. write another adds a lot of complexity to software. It becomes
  46. necessary to have an organised event loop containing \cw{select} or
  47. \cw{WaitForMultipleObjects} or similar, which can invoke the handler
  48. for whichever event happens soonest. There's no need to add that
  49. complexity in an application like this, which isn't transferring large
  50. amounts of bulk data or multiplexing unrelated activities. So, to keep
  51. life simple for plugin authors, we set the ground rule that it must
  52. always be 100% clear which side is supposed to be sending a message
  53. next. That way, the plugin can be written as sequential code
  54. progressing through the protocol, making simple read and write calls
  55. to receive or send each message.
  56. \s{Communicate success/failure, to facilitate caching in the plugin.}
  57. A plugin might want to cache recently used data for next time, but
  58. only in the case where authentication using that data was actually
  59. successful. So the client has to tell the plugin what the outcome was,
  60. if it's known. (But this is best-effort only. Obviously the plugin
  61. cannot \e{depend} on hearing the answer, because any IPC protocol at
  62. all carries the risk that the other end might crash or be killed by
  63. things outside its control.)
  64. \H{authplugin-transport} Transport and configuration
  65. Plugins are executable programs on the client platform.
  66. The SSH client must be manually configured to use a plugin for a
  67. particular connection. The configuration takes the form of a command
  68. line, including the location of the plugin executable, and optionally
  69. command-line arguments that are meaningful to the particular plugin.
  70. The client invokes the plugin as a subprocess, passing it a pair of
  71. 8-bit-clean pipes as its standard input and output. On those pipes,
  72. the client and plugin will communicate via the protocol specified
  73. below.
  74. \H{authplugin-formats} Data formats and marshalling
  75. This protocol borrows the low-level data formatting from SSH itself,
  76. in particular the following wire encodings from
  77. \k{authplugin-ref-arch} section 5:
  78. \dt \s{byte}
  79. \dd An integer between 0 and 0xFF inclusive, transmitted as a single
  80. byte of binary data.
  81. \dt \s{boolean}
  82. \dd The values \q{true} or \q{false}, transmitted as the bytes 1 and 0
  83. respectively.
  84. \dt \s{uint32}
  85. \dd An integer between 0 and 0xFFFFFFFF inclusive, transmitted as 4
  86. bytes of binary data, in big-endian (\q{network}) byte order.
  87. \dt \s{string}
  88. \dd A sequence of bytes, preceded by a \s{uint32} giving the number of
  89. bytes in the sequence. The length field does not include itself. For
  90. example, the empty string is represented by four zero bytes (the
  91. \s{uint32} encoding of 0); the string "AB" is represented by the six
  92. bytes 0,0,0,2,'A','B'.
  93. Unlike SSH itself, the protocol spoken between the client and the
  94. plugin is unencrypted, because local inter-process pipes are assumed
  95. to be secured by the OS kernel. So the binary packet protocol is much
  96. simpler than SSH proper, and is similar to SFTP and the OpenSSH agent
  97. protocol.
  98. The data sent in each direction of the conversation consists of a
  99. sequence of \s{messages} exchanged between the SSH client and the
  100. plugin. Each message is encoded as a \s{string}. The contents of the
  101. string begin with a \s{byte} giving the message type, which determines
  102. the format of the rest of the message.
  103. \H{authplugin-version} Protocol versioning
  104. This protocol itself is versioned. At connection setup, the client
  105. states the highest version number it knows how to speak, and then the
  106. plugin responds by choosing the version number that will actually be
  107. spoken (which may not be higher than the client's value).
  108. Including a version number makes it possible to make breaking changes
  109. to the protocol later.
  110. Even version numbers represent released versions of this spec. Odd
  111. numbers represent drafts or development versions in between releases.
  112. A client and plugin negotiating an odd version number are not
  113. guaranteed to interoperate; the developer testing the combination is
  114. responsible for ensuring the two are compatible.
  115. This document describes version 2 of the protocol, the first released
  116. version. (The initial drafts had version 1.)
  117. \H{authplugin-overview} Overview and sequence of events
  118. At the very beginning of the user authentication phase of SSH, the
  119. client launches the plugin subprocess, if one is configured. It
  120. immediately sends the \cw{PLUGIN_INIT} message, telling the plugin
  121. some initial information about where the SSH connection is to.
  122. The plugin responds with \cw{PLUGIN_INIT_RESPONSE}, which may
  123. optionally tell the SSH client what username to use.
  124. The client begins trying to authenticate with the SSH server in the
  125. usual way, using the username provided by the plugin (if any) or
  126. alternatively one obtained via its normal (non-plugin) policy.
  127. The client follows its normal policy for selecting authentication
  128. methods to attempt. If it chooses a method that this protocol does not
  129. cover, then the client will perform that method in its own way without
  130. consulting the plugin.
  131. However, if the client and server decide to attempt a method that this
  132. protocol \e{does} cover, then the client sends \cw{PLUGIN_PROTOCOL}
  133. specifying the SSH protocol id for the authentication method being
  134. used. The plugin responds with \cw{PLUGIN_PROTOCOL_ACCEPT} if it's
  135. willing to assist with this auth method, or
  136. \cw{PLUGIN_PROTOCOL_REJECT} if it isn't.
  137. If the plugin sends \cw{PLUGIN_PROTOCOL_REJECT}, then the client will
  138. proceed as if the plugin were not present. Later, if another auth
  139. method is negotiated (either because this one failed, or because it
  140. succeeded but the server wants multiple auth methods), the client may
  141. send a further \cw{PLUGIN_PROTOCOL} and try again.
  142. If the plugin sends \cw{PLUGIN_PROTOCOL_ACCEPT}, then a protocol
  143. segment begins that is specific to that auth method, terminating in
  144. either \cw{PLUGIN_AUTH_SUCCESS} or \cw{PLUGIN_AUTH_FAILURE}. After
  145. that, again, the client may send a further \cw{PLUGIN_PROTOCOL}.
  146. Currently the only supported method is \cq{keyboard-interactive},
  147. defined in \k{authplugin-ref-ki}. Once the client has announced this
  148. to the server, the followup protocol is as follows:
  149. Each time the server sends an \cw{SSH_MSG_USERAUTH_INFO_REQUEST}
  150. message requesting authentication responses from the user, the SSH
  151. client translates the message into \cw{PLUGIN_KI_SERVER_REQUEST} and
  152. passes it on to the plugin.
  153. At this point, the plugin may optionally send back
  154. \cw{PLUGIN_KI_USER_REQUEST} containing prompts to be presented to the
  155. actual user. The client will reply with a matching
  156. \cw{PLUGIN_KI_USER_RESPONSE} after asking the user to reply to the
  157. question(s) in the request message. The plugin can repeat this cycle
  158. multiple times.
  159. Once the plugin has all the information it needs to respond to the
  160. server's authentication prompts, it sends \cw{PLUGIN_KI_SERVER_RESPONSE}
  161. back to the client, which translates it into
  162. \cw{SSH_MSG_USERAUTH_INFO_RESPONSE} to send on to the server.
  163. After that, as described in \k{authplugin-ref-ki}, the server is free
  164. to accept authentication, reject it, or send another
  165. \cw{SSH_MSG_USERAUTH_INFO_REQUEST}. Each
  166. \cw{SSH_MSG_USERAUTH_INFO_REQUEST} is dealt with in the same way as
  167. above.
  168. If the server terminates keyboard-interactive authentication with
  169. \cw{SSH_MSG_USERAUTH_SUCCESS} or \cw{SSH_MSG_USERAUTH_FAILURE}, the
  170. client informs the plugin by sending either \cw{PLUGIN_AUTH_SUCCESS}
  171. or \cw{PLUGIN_AUTH_FAILURE}. \cw{PLUGIN_AUTH_SUCCESS} is sent when
  172. \e{that particular authentication method} was successful, regardless
  173. of whether the SSH server chooses to request further authentication
  174. afterwards: in particular, \cw{SSH_MSG_USERAUTH_FAILURE} with the
  175. \q{partial success} flag (see \k{authplugin-ref-userauth} section 5.1) translates
  176. into \cw{PLUGIN_AUTH_SUCCESS}.
  177. The plugin's standard input will close when the client no longer
  178. requires the plugin's services, for any reason. This could be because
  179. authentication is complete (with overall success or overall failure),
  180. or because the user has manually aborted the session in
  181. mid-authentication, or because the client crashed.
  182. \H{authplugin-messages} Message formats
  183. This section describes the format of every message in the protocol.
  184. As described in \k{authplugin-formats}, every message starts with the same two
  185. fields:
  186. \b \s{uint32}: overall length of the message
  187. \b \s{byte}: message type.
  188. The length field does not include itself, but does include the type
  189. code.
  190. The following subsections each give the format of the remainder of the
  191. message, after the type code.
  192. The type codes themselves are defined here:
  193. \c #define PLUGIN_INIT 1
  194. \c #define PLUGIN_INIT_RESPONSE 2
  195. \c #define PLUGIN_PROTOCOL 3
  196. \c #define PLUGIN_PROTOCOL_ACCEPT 4
  197. \c #define PLUGIN_PROTOCOL_REJECT 5
  198. \c #define PLUGIN_AUTH_SUCCESS 6
  199. \c #define PLUGIN_AUTH_FAILURE 7
  200. \c #define PLUGIN_INIT_FAILURE 8
  201. \c
  202. \c #define PLUGIN_KI_SERVER_REQUEST 20
  203. \c #define PLUGIN_KI_SERVER_RESPONSE 21
  204. \c #define PLUGIN_KI_USER_REQUEST 22
  205. \c #define PLUGIN_KI_USER_RESPONSE 23
  206. If this protocol is extended to be able to assist with further auth
  207. methods, their message type codes will also begin from 20, overlapping
  208. the codes for keyboard-interactive.
  209. \S{PLUGIN_INIT} \cw{PLUGIN_INIT}
  210. \s{Direction}: client to plugin
  211. \s{When}: the first message sent at connection startup
  212. \s{What happens next}: the plugin will send \cw{PLUGIN_INIT_RESPONSE}
  213. or \cw{PLUGIN_INIT_FAILURE}
  214. \s{Message contents after the type code}:
  215. \b \s{uint32}: the highest version number of this protocol that the
  216. client knows how to speak.
  217. \b \s{string}: the hostname of the server. This will be the \e{logical}
  218. hostname, in cases where it differs from the physical destination of
  219. the network connection. Whatever name would be used by the SSH client
  220. to cache the server's host key, that's the same name passed in this
  221. message.
  222. \b \s{uint32}: the port number on the server. (Together with the host
  223. name, this forms a primary key identifying a particular server. Port
  224. numbers may be vital because a single host can run two unrelated SSH
  225. servers with completely different authentication requirements, e.g.
  226. system sshd on port 22 and Gerrit on port 29418.)
  227. \b \s{string}: the username that the client will use to log in, if the
  228. plugin chooses not to override it. An empty string means that the
  229. client has no opinion about this (and might, for example, prompt the
  230. user).
  231. \S{PLUGIN_INIT_RESPONSE} \cw{PLUGIN_INIT_RESPONSE}
  232. \s{Direction}: plugin to client
  233. \s{When}: response to \cw{PLUGIN_INIT}
  234. \s{What happens next}: the client will send \cw{PLUGIN_PROTOCOL}, or
  235. perhaps terminate the session (if no auth method is ever negotiated
  236. that the plugin can help with)
  237. \s{Message contents after the type code}:
  238. \b \s{uint32}: the version number of this protocol that the connection
  239. will use. Must be no greater than the max version number sent by the
  240. client in \cw{PLUGIN_INIT}.
  241. \b \s{string}: the username that the plugin suggests the client use. An
  242. empty string means that the plugin has no opinion and the client
  243. should stick with the username it already had (or prompt the user, if
  244. it had none).
  245. \S{PLUGIN_INIT_FAILURE} \cw{PLUGIN_INIT_FAILURE}
  246. \s{Direction}: plugin to client
  247. \s{When}: response to \cw{PLUGIN_INIT}
  248. \s{What happens next}: the session is over
  249. \s{Message contents after the type code}:
  250. \b \s{string}: an error message to present to the user indicating why
  251. the plugin was unable to start up.
  252. \S{PLUGIN_PROTOCOL} \cw{PLUGIN_PROTOCOL}
  253. \s{Direction}: client to plugin
  254. \s{When}: sent after \cw{PLUGIN_INIT_RESPONSE}, or after a previous
  255. auth phase terminates with \cw{PLUGIN_AUTH_SUCCESS} or
  256. \cw{PLUGIN_AUTH_FAILURE}
  257. \s{What happens next}: the plugin will send
  258. \cw{PLUGIN_PROTOCOL_ACCEPT} or \cw{PLUGIN_PROTOCOL_REJECT}
  259. \s{Message contents after the type code}:
  260. \b \s{string}: the SSH protocol id of the auth method the client
  261. intends to attempt. Currently the only method specified for use in
  262. this protocol is \cq{keyboard-interactive}.
  263. \S{PLUGIN_PROTOCOL_REJECT} \cw{PLUGIN_PROTOCOL_REJECT}
  264. \s{Direction}: plugin to client
  265. \s{When}: sent after \cw{PLUGIN_PROTOCOL}
  266. \s{What happens next}: the client will either send another
  267. \cw{PLUGIN_PROTOCOL} or terminate the session
  268. \s{Message contents after the type code}:
  269. \b \s{string}: an error message to present to the user, explaining why
  270. the plugin cannot help with this authentication protocol.
  271. \lcont{
  272. An example might be \q{unable to open <config file>: <OS error
  273. message>}, if the plugin depends on some configuration that the user
  274. has not set up.
  275. If the plugin does not support this this particular authentication
  276. protocol at all, this string should be left blank, so that no message
  277. will be presented to the user at all.
  278. }
  279. \S{PLUGIN_PROTOCOL_ACCEPT} \cw{PLUGIN_PROTOCOL_ACCEPT}
  280. \s{Direction}: plugin to client
  281. \s{When}: sent after \cw{PLUGIN_PROTOCOL}
  282. \s{What happens next}: depends on the auth protocol agreed on. For
  283. keyboard-interactive, the client will send
  284. \cw{PLUGIN_KI_SERVER_REQUEST} or \cw{PLUGIN_AUTH_SUCCESS} or
  285. \cw{PLUGIN_AUTH_FAILURE}. No other method is specified.
  286. \s{Message contents after the type code}: none.
  287. \S{PLUGIN_KI_SERVER_REQUEST} \cw{PLUGIN_KI_SERVER_REQUEST}
  288. \s{Direction}: client to plugin
  289. \s{When}: sent after \cw{PLUGIN_PROTOCOL}, or after a previous
  290. \cw{PLUGIN_KI_SERVER_RESPONSE}, when the SSH server has sent
  291. \cw{SSH_MSG_USERAUTH_INFO_REQUEST}
  292. \s{What happens next}: the plugin will send either
  293. \cw{PLUGIN_KI_USER_REQUEST} or \cw{PLUGIN_KI_SERVER_RESPONSE}
  294. \s{Message contents after the type code}: the exact contents of the
  295. \cw{SSH_MSG_USERAUTH_INFO_REQUEST} just sent by the server. See
  296. \k{authplugin-ref-ki} section 3.2 for details. The summary:
  297. \b \s{string}: name of this prompt collection (e.g. to use as a
  298. dialog-box title)
  299. \b \s{string}: instructions to be displayed before this prompt
  300. collection
  301. \b \s{string}: language tag (deprecated)
  302. \b \s{uint32}: number of prompts in this collection
  303. \b That many copies of:
  304. \lcont{
  305. \b \s{string}: prompt (in UTF-8)
  306. \b \s{boolean}: whether the response to this prompt is safe to echo to
  307. the screen
  308. }
  309. \S{PLUGIN_KI_SERVER_RESPONSE} \cw{PLUGIN_KI_SERVER_RESPONSE}
  310. \s{Direction}: plugin to client
  311. \s{When}: response to \cw{PLUGIN_KI_SERVER_REQUEST}, perhaps after one
  312. or more intervening pairs of \cw{PLUGIN_KI_USER_REQUEST} and
  313. \cw{PLUGIN_KI_USER_RESPONSE}
  314. \s{What happens next}: the client will send a further
  315. \cw{PLUGIN_KI_SERVER_REQUEST}, or \cw{PLUGIN_AUTH_SUCCESS} or
  316. \cw{PLUGIN_AUTH_FAILURE}
  317. \s{Message contents after the type code}: the exact contents of the
  318. \cw{SSH_MSG_USERAUTH_INFO_RESPONSE} that the client should send back
  319. to the server. See \k{authplugin-ref-ki} section 3.4 for details. The
  320. summary:
  321. \b \s{uint32}: number of responses (must match the \q{number of
  322. prompts} field from the corresponding server request)
  323. \b That many copies of:
  324. \lcont{
  325. \b \s{string}: response to the \e{n}th prompt (in UTF-8)
  326. }
  327. \S{PLUGIN_KI_USER_REQUEST} \cw{PLUGIN_KI_USER_REQUEST}
  328. \s{Direction}: plugin to client
  329. \s{When}: response to \cw{PLUGIN_KI_SERVER_REQUEST}, if the plugin
  330. cannot answer the server's auth prompts without presenting prompts of
  331. its own to the user
  332. \s{What happens next}: the client will send \cw{PLUGIN_KI_USER_RESPONSE}
  333. \s{Message contents after the type code}: exactly the same as in
  334. \cw{PLUGIN_KI_SERVER_REQUEST} (see \k{PLUGIN_KI_SERVER_REQUEST}).
  335. \S{PLUGIN_KI_USER_RESPONSE} \cw{PLUGIN_KI_USER_RESPONSE}
  336. \s{Direction}: client to plugin
  337. \s{When}: response to \cw{PLUGIN_KI_USER_REQUEST}
  338. \s{What happens next}: the plugin will send
  339. \cw{PLUGIN_KI_SERVER_RESPONSE}, or another \cw{PLUGIN_KI_USER_REQUEST}
  340. \s{Message contents after the type code}: exactly the same as in
  341. \cw{PLUGIN_KI_SERVER_RESPONSE} (see \k{PLUGIN_KI_SERVER_RESPONSE}).
  342. \S{PLUGIN_AUTH_SUCCESS} \cw{PLUGIN_AUTH_SUCCESS}
  343. \s{Direction}: client to plugin
  344. \s{When}: sent after \cw{PLUGIN_KI_SERVER_RESPONSE}, or (in unusual
  345. cases) after \cw{PLUGIN_PROTOCOL_ACCEPT}
  346. \s{What happens next}: the client will either send another
  347. \cw{PLUGIN_PROTOCOL} or terminate the session
  348. \s{Message contents after the type code}: none
  349. \S{PLUGIN_AUTH_FAILURE} \cw{PLUGIN_AUTH_FAILURE}
  350. \s{Direction}: client to plugin
  351. \s{When}: sent after \cw{PLUGIN_KI_SERVER_RESPONSE}, or (in unusual
  352. cases) after \cw{PLUGIN_PROTOCOL_ACCEPT}
  353. \s{What happens next}: the client will either send another
  354. \cw{PLUGIN_PROTOCOL} or terminate the session
  355. \s{Message contents after the type code}: none
  356. \H{authplugin-refs} References
  357. \B{authplugin-ref-arch} \W{https://www.rfc-editor.org/rfc/rfc4251}{RFC 4251}, \q{The Secure Shell (SSH) Protocol
  358. Architecture}.
  359. \B{authplugin-ref-userauth} \W{https://www.rfc-editor.org/rfc/rfc4252}{RFC
  360. 4252}, \q{The Secure Shell (SSH) Authentication Protocol}.
  361. \B{authplugin-ref-ki}
  362. \W{https://www.rfc-editor.org/rfc/rfc4256}{RFC 4256},
  363. \q{Generic Message Exchange Authentication for the Secure Shell
  364. Protocol (SSH)} (better known by its wire id
  365. \q{keyboard-interactive}).
  366. \BR{authplugin-ref-arch} [RFC4251]
  367. \BR{authplugin-ref-userauth} [RFC4252]
  368. \BR{authplugin-ref-ki} [RFC4256]