lws-plugin-ssh.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. * libwebsockets - small server side websockets and web server implementation
  3. *
  4. * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to
  8. * deal in the Software without restriction, including without limitation the
  9. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. * sell copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22. * IN THE SOFTWARE.
  23. */
  24. #if !defined(__LWS_PLUGIN_SSH_H__)
  25. #define __LWS_PLUGIN_SSH_H__
  26. #define LWS_CALLBACK_SSH_UART_SET_RXFLOW (LWS_CALLBACK_USER + 800)
  27. #define LWS_SSH_OPS_VERSION 2
  28. struct lws_ssh_pty {
  29. char term[16];
  30. char *modes;
  31. uint32_t width_ch;
  32. uint32_t height_ch;
  33. uint32_t width_px;
  34. uint32_t height_px;
  35. uint32_t modes_len;
  36. };
  37. #define SSHMO_TTY_OP_END 0 /* Indicates end of options. */
  38. #define SSHMO_VINTR 1 /* Interrupt character; 255 if none. Similarly
  39. * for the other characters. Not all of these
  40. * characters are supported on all systems. */
  41. #define SSHMO_VQUIT 2 /* The quit character (sends SIGQUIT signal on
  42. * POSIX systems). */
  43. #define SSHMO_VERASE 3 /* Erase the character to left of the cursor. */
  44. #define SSHMO_VKILL 4 /* Kill the current input line. */
  45. #define SSHMO_VEOF 5 /* End-of-file character (sends EOF from the
  46. * terminal). */
  47. #define SSHMO_VEOL 6 /* End-of-line character in addition to
  48. * carriage return and/or linefeed. */
  49. #define SSHMO_VEOL2 7 /* Additional end-of-line character. */
  50. #define SSHMO_VSTART 8 /* Continues paused output (normally
  51. * control-Q). */
  52. #define SSHMO_VSTOP 9 /* Pauses output (normally control-S). */
  53. #define SSHMO_VSUSP 10 /* Suspends the current program. */
  54. #define SSHMO_VDSUSP 11 /* Another suspend character. */
  55. #define SSHMO_VREPRINT 12 /* Reprints the current input line. */
  56. #define SSHMO_VWERASE 13 /* Erases a word left of cursor. */
  57. #define SSHMO_VLNEXT 14 /* Enter the next character typed literally,
  58. * even if it is a special character */
  59. #define SSHMO_VFLUSH 15 /* Character to flush output. */
  60. #define SSHMO_VSWTCH 16 /* Switch to a different shell layer. */
  61. #define SSHMO_VSTATUS 17 /* Prints system status line (load, command,
  62. * pid, etc). */
  63. #define SSHMO_VDISCARD 18 /* Toggles the flushing of terminal output. */
  64. #define SSHMO_IGNPAR 30 /* The ignore parity flag. The parameter
  65. * SHOULD be 0 if this flag is FALSE,
  66. * and 1 if it is TRUE. */
  67. #define SSHMO_PARMRK 31 /* Mark parity and framing errors. */
  68. #define SSHMO_INPCK 32 /* Enable checking of parity errors. */
  69. #define SSHMO_ISTRIP 33 /* Strip 8th bit off characters. */
  70. #define SSHMO_INLCR 34 /* Map NL into CR on input. */
  71. #define SSHMO_IGNCR 35 /* Ignore CR on input. */
  72. #define SSHMO_ICRNL 36 /* Map CR to NL on input. */
  73. #define SSHMO_IUCLC 37 /* Translate uppercase characters to lowercase. */
  74. #define SSHMO_IXON 38 /* Enable output flow control. */
  75. #define SSHMO_IXANY 39 /* Any char will restart after stop. */
  76. #define SSHMO_IXOFF 40 /* Enable input flow control. */
  77. #define SSHMO_IMAXBEL 41 /* Ring bell on input queue full. */
  78. #define SSHMO_ISIG 50 /* Enable signals INTR, QUIT, [D]SUSP. */
  79. #define SSHMO_ICANON 51 /* Canonicalize input lines. */
  80. #define SSHMO_XCASE 52 /* Enable input and output of uppercase
  81. * characters by preceding their lowercase
  82. * equivalents with "\". */
  83. #define SSHMO_ECHO 53 /* Enable echoing. */
  84. #define SSHMO_ECHOE 54 /* Visually erase chars. */
  85. #define SSHMO_ECHOK 55 /* Kill character discards current line. */
  86. #define SSHMO_ECHONL 56 /* Echo NL even if ECHO is off. */
  87. #define SSHMO_NOFLSH 57 /* Don't flush after interrupt. */
  88. #define SSHMO_TOSTOP 58 /* Stop background jobs from output. */
  89. #define SSHMO_IEXTEN 59 /* Enable extensions. */
  90. #define SSHMO_ECHOCTL 60 /* Echo control characters as ^(Char). */
  91. #define SSHMO_ECHOKE 61 /* Visual erase for line kill. */
  92. #define SSHMO_PENDIN 62 /* Retype pending input. */
  93. #define SSHMO_OPOST 70 /* Enable output processing. */
  94. #define SSHMO_OLCUC 71 /* Convert lowercase to uppercase. */
  95. #define SSHMO_ONLCR 72 /* Map NL to CR-NL. */
  96. #define SSHMO_OCRNL 73 /* Translate carriage return to newline (out). */
  97. #define SSHMO_ONOCR 74 /* Translate newline to CR-newline (out). */
  98. #define SSHMO_ONLRET 75 /* Newline performs a carriage return (out). */
  99. #define SSHMO_CS7 90 /* 7 bit mode. */
  100. #define SSHMO_CS8 91 /* 8 bit mode. */
  101. #define SSHMO_PARENB 92 /* Parity enable. */
  102. #define SSHMO_PARODD 93 /* Odd parity, else even. */
  103. #define SSHMO_TTY_OP_ISPEED 128 /* Specifies the input baud rate in
  104. * bits per second. */
  105. #define SSHMO_TTY_OP_OSPEED 129 /* Specifies the output baud rate in
  106. * bits per second. */
  107. /*! \defgroup ssh-base plugin: lws-ssh-base
  108. * \ingroup Protocols-and-Plugins
  109. *
  110. * ##Plugin lws-ssh-base
  111. *
  112. * This is the interface to customize the ssh server per-vhost. A pointer
  113. * to your struct lws_ssh_ops with the members initialized is passed in using
  114. * pvo when you create the vhost. The pvo is attached to the protocol name
  115. *
  116. * - "lws-ssh-base" - the ssh serving part
  117. *
  118. * - "lws-telnetd-base" - the telnet serving part
  119. *
  120. * This way you can have different instances of ssh servers wired up to
  121. * different IO and server keys per-vhost.
  122. *
  123. * See also ./READMEs/README-plugin-sshd-base.md
  124. */
  125. ///@{
  126. typedef void (*lws_ssh_finish_exec)(void *handle, int retcode);
  127. struct lws_ssh_ops {
  128. /**
  129. * channel_create() - Channel created
  130. *
  131. * \param wsi: raw wsi representing this connection
  132. * \param priv: pointer to void * you can allocate and attach to the
  133. * channel
  134. *
  135. * Called when new channel created, *priv should be set to any
  136. * allocation your implementation needs
  137. *
  138. * You probably want to save the wsi inside your priv struct. Calling
  139. * lws_callback_on_writable() on this wsi causes your ssh server
  140. * instance to call .tx_waiting() next time you can write something
  141. * to the client.
  142. */
  143. int (*channel_create)(struct lws *wsi, void **priv);
  144. /**
  145. * channel_destroy() - Channel is being destroyed
  146. *
  147. * \param priv: void * you set when channel was created (or NULL)
  148. *
  149. * Called when channel destroyed, priv should be freed if you allocated
  150. * into it.
  151. */
  152. int (*channel_destroy)(void *priv);
  153. /**
  154. * rx() - receive payload from peer
  155. *
  156. * \param priv: void * you set when this channel was created
  157. * \param wsi: struct lws * for the ssh connection
  158. * \param buf: pointer to start of received data
  159. * \param len: bytes of received data available at buf
  160. *
  161. * len bytes of payload from the peer arrived and is available at buf
  162. */
  163. int (*rx)(void *priv, struct lws *wsi, const uint8_t *buf, uint32_t len);
  164. /**
  165. * tx_waiting() - report if data waiting to transmit on the channel
  166. *
  167. * \param priv: void * you set when this channel was created
  168. *
  169. * returns a bitmask of LWS_STDOUT and LWS_STDERR, with the bits set
  170. * if they have tx waiting to send, else 0 if nothing to send
  171. *
  172. * You should use one of the lws_callback_on_writable() family to
  173. * trigger the ssh protocol to ask if you have any tx waiting.
  174. *
  175. * Returning -1 from here will close the tcp connection to the client.
  176. */
  177. int (*tx_waiting)(void *priv);
  178. /**
  179. * tx() - provide data to send on the channel
  180. *
  181. * \param priv: void * you set when this channel was created
  182. * \param stdch: LWS_STDOUT or LWS_STDERR
  183. * \param buf: start of the buffer to copy the transmit data into
  184. * \param len: max length of the buffer in bytes
  185. *
  186. * copy and consume up to len bytes into *buf,
  187. * return the actual copied count.
  188. *
  189. * You should use one of the lws_callback_on_writable() family to
  190. * trigger the ssh protocol to ask if you have any tx waiting. If you
  191. * do you will get calls here to fetch it, for each of LWS_STDOUT or
  192. * LWS_STDERR that were reported to be waiting by tx_waiting().
  193. */
  194. size_t (*tx)(void *priv, int stdch, uint8_t *buf, size_t len);
  195. /**
  196. * get_server_key() - retreive the secret keypair for this server
  197. *
  198. * \param wsi: the wsi representing the connection to the client
  199. * \param buf: start of the buffer to copy the keypair into
  200. * \param len: length of the buffer in bytes
  201. *
  202. * load the server key into buf, max len len. Returns length of buf
  203. * set to key, or 0 if no key or other error. If there is no key,
  204. * the error isn't fatal... the plugin will generate a random key and
  205. * store it using *get_server_key() for subsequent times.
  206. */
  207. size_t (*get_server_key)(struct lws *wsi, uint8_t *buf, size_t len);
  208. /**
  209. * set_server_key() - store the secret keypair of this server
  210. *
  211. * \param wsi: the wsi representing the connection to the client
  212. * \param buf: start of the buffer containing the keypair
  213. * \param len: length of the keypair in bytes
  214. *
  215. * store the server key in buf, length len, to nonvolatile stg.
  216. * Return length stored, 0 for fail.
  217. */
  218. size_t (*set_server_key)(struct lws *wsi, uint8_t *buf, size_t len);
  219. /**
  220. * set_env() - Set environment variable
  221. *
  222. * \param priv: void * you set when this channel was created
  223. * \param name: env var name
  224. * \param value: value to set env var to
  225. *
  226. * Client requested to set environment var. Return nonzero to fail.
  227. */
  228. int (*set_env)(void *priv, const char *name, const char *value);
  229. /**
  230. * exec() - spawn command and wire up stdin/out/err to ssh channel
  231. *
  232. * \param priv: void * you set when this channel was created
  233. * \param wsi: the struct lws the connection belongs to
  234. * \param command: string containing path to app and arguments
  235. * \param finish: function to call to indicate the exec finished
  236. * \param finish_handle: opaque handle identifying this exec for use with \p finish
  237. *
  238. * Client requested to exec something. Return nonzero to fail.
  239. */
  240. int (*exec)(void *priv, struct lws *wsi, const char *command, lws_ssh_finish_exec finish, void *finish_handle);
  241. /**
  242. * shell() - Spawn shell that is appropriate for user
  243. *
  244. * \param priv: void * you set when this channel was created
  245. * \param wsi: the struct lws the connection belongs to
  246. * \param finish: function to call to indicate the exec finished
  247. * \param finish_handle: opaque handle identifying this exec for use with \p finish
  248. *
  249. * Spawn the appropriate shell for this user. Return 0 for OK
  250. * or nonzero to fail.
  251. */
  252. int (*shell)(void *priv, struct lws *wsi, lws_ssh_finish_exec finish, void *finish_handle);
  253. /**
  254. * pty_req() - Create a Pseudo-TTY as described in pty
  255. *
  256. * \param priv: void * you set when this channel was created
  257. * \param pty: pointer to struct describing the desired pty
  258. *
  259. * Client requested a pty. Return nonzero to fail.
  260. */
  261. int (*pty_req)(void *priv, struct lws_ssh_pty *pty);
  262. /**
  263. * child_process_io() - Child process has IO
  264. *
  265. * \param priv: void * you set when this channel was created
  266. * \param wsi: the struct lws the connection belongs to
  267. * \param args: information related to the cgi IO events
  268. *
  269. * Child process has IO
  270. */
  271. int (*child_process_io)(void *priv, struct lws *wsi,
  272. struct lws_cgi_args *args);
  273. /**
  274. * child_process_io() - Child process has terminated
  275. *
  276. * \param priv: void * you set when this channel was created
  277. * \param wsi: the struct lws the connection belongs to
  278. *
  279. * Child process has terminated
  280. */
  281. int (*child_process_terminated)(void *priv, struct lws *wsi);
  282. /**
  283. * disconnect_reason() - Optional notification why connection is lost
  284. *
  285. * \param reason: one of the SSH_DISCONNECT_ constants
  286. * \param desc: UTF-8 description of reason
  287. * \param desc_lang: RFC3066 language for description
  288. *
  289. * The remote peer may tell us why it's going to disconnect. Handling
  290. * this is optional.
  291. */
  292. void (*disconnect_reason)(uint32_t reason, const char *desc,
  293. const char *desc_lang);
  294. /**
  295. * is_pubkey_authorized() - check if auth pubkey is valid for user
  296. *
  297. * \param username: username the key attempted to authenticate
  298. * \param type: "ssh-rsa"
  299. * \param peer: start of Public key peer used to authenticate
  300. * \param peer_len: length of Public key at peer
  301. *
  302. * We confirmed the client has the private key for this public key...
  303. * but is that keypair something authorized for this username on this
  304. * server? 0 = OK, 1 = fail
  305. *
  306. * Normally this checks for a copy of the same public key stored
  307. * somewhere out of band, it's the same procedure as openssh does
  308. * when looking in ~/.ssh/authorized_keys
  309. */
  310. int (*is_pubkey_authorized)(const char *username,
  311. const char *type, const uint8_t *peer, int peer_len);
  312. /**
  313. * banner() - copy the connection banner to buffer
  314. *
  315. * \param buf: start of the buffer to copy to
  316. * \param max_len: maximum number of bytes the buffer can hold
  317. * \param lang: start of the buffer to copy language descriptor to
  318. * \param max_lang_len: maximum number of bytes lang can hold
  319. *
  320. * Copy the text banner to be returned to client on connect,
  321. * before auth, into buf. The text should be in UTF-8.
  322. * if none wanted then leave .banner as NULL.
  323. *
  324. * lang should have a RFC3066 language descriptor like "en/US"
  325. * copied to it.
  326. *
  327. * Returns the number of bytes copies to buf.
  328. */
  329. size_t (*banner)(char *buf, size_t max_len, char *lang,
  330. size_t max_lang_len);
  331. /**
  332. * SSH version string sent to client (required)
  333. * By convention a string like "SSH-2.0-Libwebsockets"
  334. */
  335. const char *server_string;
  336. /**
  337. * set to the API version you support (current is in
  338. * LWS_SSH_OPS_VERSION) You should set it to an integer like 1,
  339. * that reflects the latest api at the time your code was written. If
  340. * the ops api_version is not equal to the LWS_SSH_OPS_VERSION of the
  341. * plugin, it will error out at runtime.
  342. */
  343. char api_version;
  344. };
  345. ///@}
  346. #endif