You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
374 lines
14 KiB
374 lines
14 KiB
/*
|
|
* libwebsockets - small server side websockets and web server implementation
|
|
*
|
|
* Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to
|
|
* deal in the Software without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
* IN THE SOFTWARE.
|
|
*/
|
|
|
|
#if !defined(__LWS_PLUGIN_SSH_H__)
|
|
#define __LWS_PLUGIN_SSH_H__
|
|
|
|
#define LWS_CALLBACK_SSH_UART_SET_RXFLOW (LWS_CALLBACK_USER + 800)
|
|
|
|
#define LWS_SSH_OPS_VERSION 2
|
|
|
|
struct lws_ssh_pty {
|
|
char term[16];
|
|
char *modes;
|
|
uint32_t width_ch;
|
|
uint32_t height_ch;
|
|
uint32_t width_px;
|
|
uint32_t height_px;
|
|
uint32_t modes_len;
|
|
};
|
|
|
|
#define SSHMO_TTY_OP_END 0 /* Indicates end of options. */
|
|
#define SSHMO_VINTR 1 /* Interrupt character; 255 if none. Similarly
|
|
* for the other characters. Not all of these
|
|
* characters are supported on all systems. */
|
|
#define SSHMO_VQUIT 2 /* The quit character (sends SIGQUIT signal on
|
|
* POSIX systems). */
|
|
#define SSHMO_VERASE 3 /* Erase the character to left of the cursor. */
|
|
#define SSHMO_VKILL 4 /* Kill the current input line. */
|
|
#define SSHMO_VEOF 5 /* End-of-file character (sends EOF from the
|
|
* terminal). */
|
|
#define SSHMO_VEOL 6 /* End-of-line character in addition to
|
|
* carriage return and/or linefeed. */
|
|
#define SSHMO_VEOL2 7 /* Additional end-of-line character. */
|
|
#define SSHMO_VSTART 8 /* Continues paused output (normally
|
|
* control-Q). */
|
|
#define SSHMO_VSTOP 9 /* Pauses output (normally control-S). */
|
|
#define SSHMO_VSUSP 10 /* Suspends the current program. */
|
|
#define SSHMO_VDSUSP 11 /* Another suspend character. */
|
|
#define SSHMO_VREPRINT 12 /* Reprints the current input line. */
|
|
#define SSHMO_VWERASE 13 /* Erases a word left of cursor. */
|
|
#define SSHMO_VLNEXT 14 /* Enter the next character typed literally,
|
|
* even if it is a special character */
|
|
#define SSHMO_VFLUSH 15 /* Character to flush output. */
|
|
#define SSHMO_VSWTCH 16 /* Switch to a different shell layer. */
|
|
#define SSHMO_VSTATUS 17 /* Prints system status line (load, command,
|
|
* pid, etc). */
|
|
#define SSHMO_VDISCARD 18 /* Toggles the flushing of terminal output. */
|
|
#define SSHMO_IGNPAR 30 /* The ignore parity flag. The parameter
|
|
* SHOULD be 0 if this flag is FALSE,
|
|
* and 1 if it is TRUE. */
|
|
#define SSHMO_PARMRK 31 /* Mark parity and framing errors. */
|
|
#define SSHMO_INPCK 32 /* Enable checking of parity errors. */
|
|
#define SSHMO_ISTRIP 33 /* Strip 8th bit off characters. */
|
|
#define SSHMO_INLCR 34 /* Map NL into CR on input. */
|
|
#define SSHMO_IGNCR 35 /* Ignore CR on input. */
|
|
#define SSHMO_ICRNL 36 /* Map CR to NL on input. */
|
|
#define SSHMO_IUCLC 37 /* Translate uppercase characters to lowercase. */
|
|
#define SSHMO_IXON 38 /* Enable output flow control. */
|
|
#define SSHMO_IXANY 39 /* Any char will restart after stop. */
|
|
#define SSHMO_IXOFF 40 /* Enable input flow control. */
|
|
#define SSHMO_IMAXBEL 41 /* Ring bell on input queue full. */
|
|
#define SSHMO_ISIG 50 /* Enable signals INTR, QUIT, [D]SUSP. */
|
|
#define SSHMO_ICANON 51 /* Canonicalize input lines. */
|
|
#define SSHMO_XCASE 52 /* Enable input and output of uppercase
|
|
* characters by preceding their lowercase
|
|
* equivalents with "\". */
|
|
#define SSHMO_ECHO 53 /* Enable echoing. */
|
|
#define SSHMO_ECHOE 54 /* Visually erase chars. */
|
|
#define SSHMO_ECHOK 55 /* Kill character discards current line. */
|
|
#define SSHMO_ECHONL 56 /* Echo NL even if ECHO is off. */
|
|
#define SSHMO_NOFLSH 57 /* Don't flush after interrupt. */
|
|
#define SSHMO_TOSTOP 58 /* Stop background jobs from output. */
|
|
#define SSHMO_IEXTEN 59 /* Enable extensions. */
|
|
#define SSHMO_ECHOCTL 60 /* Echo control characters as ^(Char). */
|
|
#define SSHMO_ECHOKE 61 /* Visual erase for line kill. */
|
|
#define SSHMO_PENDIN 62 /* Retype pending input. */
|
|
#define SSHMO_OPOST 70 /* Enable output processing. */
|
|
#define SSHMO_OLCUC 71 /* Convert lowercase to uppercase. */
|
|
#define SSHMO_ONLCR 72 /* Map NL to CR-NL. */
|
|
#define SSHMO_OCRNL 73 /* Translate carriage return to newline (out). */
|
|
#define SSHMO_ONOCR 74 /* Translate newline to CR-newline (out). */
|
|
#define SSHMO_ONLRET 75 /* Newline performs a carriage return (out). */
|
|
#define SSHMO_CS7 90 /* 7 bit mode. */
|
|
#define SSHMO_CS8 91 /* 8 bit mode. */
|
|
#define SSHMO_PARENB 92 /* Parity enable. */
|
|
#define SSHMO_PARODD 93 /* Odd parity, else even. */
|
|
#define SSHMO_TTY_OP_ISPEED 128 /* Specifies the input baud rate in
|
|
* bits per second. */
|
|
#define SSHMO_TTY_OP_OSPEED 129 /* Specifies the output baud rate in
|
|
* bits per second. */
|
|
|
|
/*! \defgroup ssh-base plugin: lws-ssh-base
|
|
* \ingroup Protocols-and-Plugins
|
|
*
|
|
* ##Plugin lws-ssh-base
|
|
*
|
|
* This is the interface to customize the ssh server per-vhost. A pointer
|
|
* to your struct lws_ssh_ops with the members initialized is passed in using
|
|
* pvo when you create the vhost. The pvo is attached to the protocol name
|
|
*
|
|
* - "lws-ssh-base" - the ssh serving part
|
|
*
|
|
* - "lws-telnetd-base" - the telnet serving part
|
|
*
|
|
* This way you can have different instances of ssh servers wired up to
|
|
* different IO and server keys per-vhost.
|
|
*
|
|
* See also ./READMEs/README-plugin-sshd-base.md
|
|
*/
|
|
///@{
|
|
|
|
typedef void (*lws_ssh_finish_exec)(void *handle, int retcode);
|
|
|
|
struct lws_ssh_ops {
|
|
/**
|
|
* channel_create() - Channel created
|
|
*
|
|
* \param wsi: raw wsi representing this connection
|
|
* \param priv: pointer to void * you can allocate and attach to the
|
|
* channel
|
|
*
|
|
* Called when new channel created, *priv should be set to any
|
|
* allocation your implementation needs
|
|
*
|
|
* You probably want to save the wsi inside your priv struct. Calling
|
|
* lws_callback_on_writable() on this wsi causes your ssh server
|
|
* instance to call .tx_waiting() next time you can write something
|
|
* to the client.
|
|
*/
|
|
int (*channel_create)(struct lws *wsi, void **priv);
|
|
|
|
/**
|
|
* channel_destroy() - Channel is being destroyed
|
|
*
|
|
* \param priv: void * you set when channel was created (or NULL)
|
|
*
|
|
* Called when channel destroyed, priv should be freed if you allocated
|
|
* into it.
|
|
*/
|
|
int (*channel_destroy)(void *priv);
|
|
|
|
/**
|
|
* rx() - receive payload from peer
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param wsi: struct lws * for the ssh connection
|
|
* \param buf: pointer to start of received data
|
|
* \param len: bytes of received data available at buf
|
|
*
|
|
* len bytes of payload from the peer arrived and is available at buf
|
|
*/
|
|
int (*rx)(void *priv, struct lws *wsi, const uint8_t *buf, uint32_t len);
|
|
|
|
/**
|
|
* tx_waiting() - report if data waiting to transmit on the channel
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
*
|
|
* returns a bitmask of LWS_STDOUT and LWS_STDERR, with the bits set
|
|
* if they have tx waiting to send, else 0 if nothing to send
|
|
*
|
|
* You should use one of the lws_callback_on_writable() family to
|
|
* trigger the ssh protocol to ask if you have any tx waiting.
|
|
*
|
|
* Returning -1 from here will close the tcp connection to the client.
|
|
*/
|
|
int (*tx_waiting)(void *priv);
|
|
|
|
/**
|
|
* tx() - provide data to send on the channel
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param stdch: LWS_STDOUT or LWS_STDERR
|
|
* \param buf: start of the buffer to copy the transmit data into
|
|
* \param len: max length of the buffer in bytes
|
|
*
|
|
* copy and consume up to len bytes into *buf,
|
|
* return the actual copied count.
|
|
*
|
|
* You should use one of the lws_callback_on_writable() family to
|
|
* trigger the ssh protocol to ask if you have any tx waiting. If you
|
|
* do you will get calls here to fetch it, for each of LWS_STDOUT or
|
|
* LWS_STDERR that were reported to be waiting by tx_waiting().
|
|
*/
|
|
size_t (*tx)(void *priv, int stdch, uint8_t *buf, size_t len);
|
|
|
|
/**
|
|
* get_server_key() - retreive the secret keypair for this server
|
|
*
|
|
* \param wsi: the wsi representing the connection to the client
|
|
* \param buf: start of the buffer to copy the keypair into
|
|
* \param len: length of the buffer in bytes
|
|
*
|
|
* load the server key into buf, max len len. Returns length of buf
|
|
* set to key, or 0 if no key or other error. If there is no key,
|
|
* the error isn't fatal... the plugin will generate a random key and
|
|
* store it using *get_server_key() for subsequent times.
|
|
*/
|
|
size_t (*get_server_key)(struct lws *wsi, uint8_t *buf, size_t len);
|
|
|
|
/**
|
|
* set_server_key() - store the secret keypair of this server
|
|
*
|
|
* \param wsi: the wsi representing the connection to the client
|
|
* \param buf: start of the buffer containing the keypair
|
|
* \param len: length of the keypair in bytes
|
|
*
|
|
* store the server key in buf, length len, to nonvolatile stg.
|
|
* Return length stored, 0 for fail.
|
|
*/
|
|
size_t (*set_server_key)(struct lws *wsi, uint8_t *buf, size_t len);
|
|
|
|
/**
|
|
* set_env() - Set environment variable
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param name: env var name
|
|
* \param value: value to set env var to
|
|
*
|
|
* Client requested to set environment var. Return nonzero to fail.
|
|
*/
|
|
int (*set_env)(void *priv, const char *name, const char *value);
|
|
|
|
/**
|
|
* exec() - spawn command and wire up stdin/out/err to ssh channel
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param wsi: the struct lws the connection belongs to
|
|
* \param command: string containing path to app and arguments
|
|
* \param finish: function to call to indicate the exec finished
|
|
* \param finish_handle: opaque handle identifying this exec for use with \p finish
|
|
*
|
|
* Client requested to exec something. Return nonzero to fail.
|
|
*/
|
|
int (*exec)(void *priv, struct lws *wsi, const char *command, lws_ssh_finish_exec finish, void *finish_handle);
|
|
|
|
/**
|
|
* shell() - Spawn shell that is appropriate for user
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param wsi: the struct lws the connection belongs to
|
|
* \param finish: function to call to indicate the exec finished
|
|
* \param finish_handle: opaque handle identifying this exec for use with \p finish
|
|
*
|
|
* Spawn the appropriate shell for this user. Return 0 for OK
|
|
* or nonzero to fail.
|
|
*/
|
|
int (*shell)(void *priv, struct lws *wsi, lws_ssh_finish_exec finish, void *finish_handle);
|
|
|
|
/**
|
|
* pty_req() - Create a Pseudo-TTY as described in pty
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param pty: pointer to struct describing the desired pty
|
|
*
|
|
* Client requested a pty. Return nonzero to fail.
|
|
*/
|
|
int (*pty_req)(void *priv, struct lws_ssh_pty *pty);
|
|
|
|
/**
|
|
* child_process_io() - Child process has IO
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param wsi: the struct lws the connection belongs to
|
|
* \param args: information related to the cgi IO events
|
|
*
|
|
* Child process has IO
|
|
*/
|
|
int (*child_process_io)(void *priv, struct lws *wsi,
|
|
struct lws_cgi_args *args);
|
|
|
|
/**
|
|
* child_process_io() - Child process has terminated
|
|
*
|
|
* \param priv: void * you set when this channel was created
|
|
* \param wsi: the struct lws the connection belongs to
|
|
*
|
|
* Child process has terminated
|
|
*/
|
|
int (*child_process_terminated)(void *priv, struct lws *wsi);
|
|
|
|
/**
|
|
* disconnect_reason() - Optional notification why connection is lost
|
|
*
|
|
* \param reason: one of the SSH_DISCONNECT_ constants
|
|
* \param desc: UTF-8 description of reason
|
|
* \param desc_lang: RFC3066 language for description
|
|
*
|
|
* The remote peer may tell us why it's going to disconnect. Handling
|
|
* this is optional.
|
|
*/
|
|
void (*disconnect_reason)(uint32_t reason, const char *desc,
|
|
const char *desc_lang);
|
|
|
|
/**
|
|
* is_pubkey_authorized() - check if auth pubkey is valid for user
|
|
*
|
|
* \param username: username the key attempted to authenticate
|
|
* \param type: "ssh-rsa"
|
|
* \param peer: start of Public key peer used to authenticate
|
|
* \param peer_len: length of Public key at peer
|
|
*
|
|
* We confirmed the client has the private key for this public key...
|
|
* but is that keypair something authorized for this username on this
|
|
* server? 0 = OK, 1 = fail
|
|
*
|
|
* Normally this checks for a copy of the same public key stored
|
|
* somewhere out of band, it's the same procedure as openssh does
|
|
* when looking in ~/.ssh/authorized_keys
|
|
*/
|
|
int (*is_pubkey_authorized)(const char *username,
|
|
const char *type, const uint8_t *peer, int peer_len);
|
|
|
|
/**
|
|
* banner() - copy the connection banner to buffer
|
|
*
|
|
* \param buf: start of the buffer to copy to
|
|
* \param max_len: maximum number of bytes the buffer can hold
|
|
* \param lang: start of the buffer to copy language descriptor to
|
|
* \param max_lang_len: maximum number of bytes lang can hold
|
|
*
|
|
* Copy the text banner to be returned to client on connect,
|
|
* before auth, into buf. The text should be in UTF-8.
|
|
* if none wanted then leave .banner as NULL.
|
|
*
|
|
* lang should have a RFC3066 language descriptor like "en/US"
|
|
* copied to it.
|
|
*
|
|
* Returns the number of bytes copies to buf.
|
|
*/
|
|
size_t (*banner)(char *buf, size_t max_len, char *lang,
|
|
size_t max_lang_len);
|
|
|
|
/**
|
|
* SSH version string sent to client (required)
|
|
* By convention a string like "SSH-2.0-Libwebsockets"
|
|
*/
|
|
const char *server_string;
|
|
|
|
/**
|
|
* set to the API version you support (current is in
|
|
* LWS_SSH_OPS_VERSION) You should set it to an integer like 1,
|
|
* that reflects the latest api at the time your code was written. If
|
|
* the ops api_version is not equal to the LWS_SSH_OPS_VERSION of the
|
|
* plugin, it will error out at runtime.
|
|
*/
|
|
char api_version;
|
|
};
|
|
///@}
|
|
|
|
#endif
|
|
|