xref: /aosp_15_r20/external/libwebsockets/READMEs/README.plugin-sshd-base.md (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Workerssh-base Plugin
2*1c60b9acSAndroid Build Coastguard Worker================
3*1c60b9acSAndroid Build Coastguard Worker
4*1c60b9acSAndroid Build Coastguard Worker## Introduction
5*1c60b9acSAndroid Build Coastguard Worker
6*1c60b9acSAndroid Build Coastguard Workerlws-ssh-base is a protcol plugin for libwebsockets that implements a
7*1c60b9acSAndroid Build Coastguard Workergeneric, abstract, ssh server.
8*1c60b9acSAndroid Build Coastguard Worker
9*1c60b9acSAndroid Build Coastguard Worker - very small footprint in code and memory, takes up small part of ESP32
10*1c60b9acSAndroid Build Coastguard Worker
11*1c60b9acSAndroid Build Coastguard Worker - written with security in mind: valgrind and Coverity -clean
12*1c60b9acSAndroid Build Coastguard Worker
13*1c60b9acSAndroid Build Coastguard Worker - binds to one or more vhosts, that controls listen port(s)
14*1c60b9acSAndroid Build Coastguard Worker
15*1c60b9acSAndroid Build Coastguard Worker - all IO and settings abstracted through a single "ops" struct from user code
16*1c60b9acSAndroid Build Coastguard Worker
17*1c60b9acSAndroid Build Coastguard Worker - each instance on a vhost has its own "ops" struct, defining server keys,
18*1c60b9acSAndroid Build Coastguard Worker   auth method and functions to implement IO and other operations
19*1c60b9acSAndroid Build Coastguard Worker
20*1c60b9acSAndroid Build Coastguard Worker - The plugin has no built-in behaviours like check ~/.ssh/authorized_keys,
21*1c60b9acSAndroid Build Coastguard Worker   treat auth usernames as system usernames, or spawn the user's shell.
22*1c60b9acSAndroid Build Coastguard Worker   Everything potentially dangerous is left to the user ops code to decide
23*1c60b9acSAndroid Build Coastguard Worker   how to handle.  It's NOT like sshd where running it implies it will accept
24*1c60b9acSAndroid Build Coastguard Worker   existing keys for any system user, will spawn a shell, etc, unless you
25*1c60b9acSAndroid Build Coastguard Worker   implement those parts in the ops callbacks.
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker - The plugin requires extra code around it in the form of the ops struct
28*1c60b9acSAndroid Build Coastguard Worker   handlers.  So it's role is something like an abstract base class for an ssh
29*1c60b9acSAndroid Build Coastguard Worker   server.  All the crypto, protocol sequencing and state machine are inside,
30*1c60b9acSAndroid Build Coastguard Worker   but all the IO except the network connection is outside.
31*1c60b9acSAndroid Build Coastguard Worker
32*1c60b9acSAndroid Build Coastguard Worker - Built as part of libwebsockets, like all plugins may be dynamically loaded
33*1c60b9acSAndroid Build Coastguard Worker   at runtime or built statically.  Test app `libwebsockets-test-sshd` provided
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker - Uses hash and RSA functions from either mbedTLS or OpenSSL automatically,
36*1c60b9acSAndroid Build Coastguard Worker   according to which library libwebsockets was built for
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard WorkerTo maintain its small size, it implements a single "best of breed" crypto for
39*1c60b9acSAndroid Build Coastguard Workerthe following functions:
40*1c60b9acSAndroid Build Coastguard Worker
41*1c60b9acSAndroid Build Coastguard Worker|Function|Crypto|
42*1c60b9acSAndroid Build Coastguard Worker|---|---|
43*1c60b9acSAndroid Build Coastguard Worker|KEX|[email protected]|
44*1c60b9acSAndroid Build Coastguard Worker|Server host key|ssh-rsa (4096b)|
45*1c60b9acSAndroid Build Coastguard Worker|Encryption|[email protected]|
46*1c60b9acSAndroid Build Coastguard Worker|Compression|None|
47*1c60b9acSAndroid Build Coastguard Worker
48*1c60b9acSAndroid Build Coastguard Worker## License
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Workerlws-ssh-base is Free Software, available under libwebsockets' MIT license.
51*1c60b9acSAndroid Build Coastguard Worker
52*1c60b9acSAndroid Build Coastguard WorkerThe crypto parts are available elsewhere under a BSD license.  But for
53*1c60b9acSAndroid Build Coastguard Workersimplicity the whole plugin is under MIT.
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker## Generating your own keys
56*1c60b9acSAndroid Build Coastguard Worker
57*1c60b9acSAndroid Build Coastguard Worker```
58*1c60b9acSAndroid Build Coastguard Worker $ ssh-keygen -t rsa -b 4096 -f mykeys
59*1c60b9acSAndroid Build Coastguard Worker```
60*1c60b9acSAndroid Build Coastguard Worker
61*1c60b9acSAndroid Build Coastguard Workerwill ask for a passphrase and generate the private key in `mykeys` and the
62*1c60b9acSAndroid Build Coastguard Workerpublic key in `mykeys.pub`.  If you already have a suitable RSA key you use
63*1c60b9acSAndroid Build Coastguard Workerwith ssh, you can just use that directly.
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Workerlws installs a test keypair in /usr[/local]/share/libwebsockets-test-server
66*1c60b9acSAndroid Build Coastguard Workerthat the test apps will accept.
67*1c60b9acSAndroid Build Coastguard Worker
68*1c60b9acSAndroid Build Coastguard Worker## Example code
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard Worker1) There's a working example app `libwebsockets-test-sshd` included that
71*1c60b9acSAndroid Build Coastguard Workerspawns a bash shell when an ssh client authenticates.  The username used on
72*1c60b9acSAndroid Build Coastguard Workerthe remote ssh has no meaning, it spawns the shell under the credentials of
73*1c60b9acSAndroid Build Coastguard Worker"lws-test-sshd" was run under.  It accepts the lws ssh test key which is
74*1c60b9acSAndroid Build Coastguard Workerinstalled into /usr[/local]/share/libwebsockets-test-server.
75*1c60b9acSAndroid Build Coastguard Worker
76*1c60b9acSAndroid Build Coastguard WorkerStart the server like this (it wants root only because the server key is stored
77*1c60b9acSAndroid Build Coastguard Workerin /etc)
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker```
80*1c60b9acSAndroid Build Coastguard Worker $ sudo libwebsockets-test-sshd
81*1c60b9acSAndroid Build Coastguard Worker```
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard WorkerConnect to it using the test private key like this
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker```
86*1c60b9acSAndroid Build Coastguard Worker $ ssh -p 2200 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys [email protected]
87*1c60b9acSAndroid Build Coastguard Worker```
88*1c60b9acSAndroid Build Coastguard Worker
89*1c60b9acSAndroid Build Coastguard Worker2) There's also a working example plugin `lws-sshd-demo` that "subclasses" the
90*1c60b9acSAndroid Build Coastguard Workerabstract `lws-ssh-base` plugin to make a protocol which can be used from,
91*1c60b9acSAndroid Build Coastguard Workereg, lwsws.  For an lwsws vhost that listens on port 2222 and responds with
92*1c60b9acSAndroid Build Coastguard Workerthe lws-sshd-demo ssh server, the related config is:
93*1c60b9acSAndroid Build Coastguard Worker
94*1c60b9acSAndroid Build Coastguard Worker```
95*1c60b9acSAndroid Build Coastguard Worker        {
96*1c60b9acSAndroid Build Coastguard Worker                "name": "sshd",
97*1c60b9acSAndroid Build Coastguard Worker                "port": "2222",
98*1c60b9acSAndroid Build Coastguard Worker                "onlyraw": "1",
99*1c60b9acSAndroid Build Coastguard Worker                "ws-protocols": [{
100*1c60b9acSAndroid Build Coastguard Worker                        "lws-ssh-base": {
101*1c60b9acSAndroid Build Coastguard Worker                                "status": "ok",
102*1c60b9acSAndroid Build Coastguard Worker                                "ops-from": "lws-sshd-demo"
103*1c60b9acSAndroid Build Coastguard Worker                        },
104*1c60b9acSAndroid Build Coastguard Worker                        "lws-sshd-demo": {
105*1c60b9acSAndroid Build Coastguard Worker                                "status": "ok",
106*1c60b9acSAndroid Build Coastguard Worker                                "raw": "1"
107*1c60b9acSAndroid Build Coastguard Worker                        }
108*1c60b9acSAndroid Build Coastguard Worker                }]
109*1c60b9acSAndroid Build Coastguard Worker        }
110*1c60b9acSAndroid Build Coastguard Worker```
111*1c60b9acSAndroid Build Coastguard Worker
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker
114*1c60b9acSAndroid Build Coastguard Worker## Integration to other apps
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker### Step 0: Build and install libwebsockets
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard WorkerFor the `libwebsockets-test-sshd` example, you will need CMake options
119*1c60b9acSAndroid Build Coastguard Worker`LWS_WITH_CGI`, since it uses lws helpers to spawn a shell.
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Workerlws-ssh-base itself doesn't require CGI support in libwebsockets.
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker### Step 1: make the code available in your app
124*1c60b9acSAndroid Build Coastguard Worker
125*1c60b9acSAndroid Build Coastguard WorkerInclude `lws-plugin-ssh-base` in your app, either as a runtime plugin or by using
126*1c60b9acSAndroid Build Coastguard Workerthe lws static include scheme.
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard WorkerTo bring in the whole of the ssh-base plugin
129*1c60b9acSAndroid Build Coastguard Workerinto your app in one step, statically, just include
130*1c60b9acSAndroid Build Coastguard Worker`plugins/ssh-base/include/lws-plugin-sshd-static-build-includes.h`, you can see
131*1c60b9acSAndroid Build Coastguard Workeran example of this in `./test-apps/test-sshd.c`.
132*1c60b9acSAndroid Build Coastguard Worker
133*1c60b9acSAndroid Build Coastguard Worker### Step 2: define your `struct lws_ssh_ops`
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker`plugins/ssh-base/include/lws-plugin-ssh.h` defines
136*1c60b9acSAndroid Build Coastguard Worker`struct lws_ssh_ops` which is used for all customization and integration
137*1c60b9acSAndroid Build Coastguard Workerof the plugin per vhost.  Eg,
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker```
140*1c60b9acSAndroid Build Coastguard Workerstatic const struct lws_ssh_ops ssh_ops = {
141*1c60b9acSAndroid Build Coastguard Worker	.channel_create			= ssh_ops_channel_create,
142*1c60b9acSAndroid Build Coastguard Worker	.channel_destroy		= ssh_ops_channel_destroy,
143*1c60b9acSAndroid Build Coastguard Worker	.tx_waiting			= ssh_ops_tx_waiting,
144*1c60b9acSAndroid Build Coastguard Worker	.tx				= ssh_ops_tx,
145*1c60b9acSAndroid Build Coastguard Worker	.rx				= ssh_ops_rx,
146*1c60b9acSAndroid Build Coastguard Worker	.get_server_key			= ssh_ops_get_server_key,
147*1c60b9acSAndroid Build Coastguard Worker	.set_server_key			= ssh_ops_set_server_key,
148*1c60b9acSAndroid Build Coastguard Worker	.set_env			= ssh_ops_set_env,
149*1c60b9acSAndroid Build Coastguard Worker	.pty_req			= ssh_ops_pty_req,
150*1c60b9acSAndroid Build Coastguard Worker	.child_process_io		= ssh_ops_child_process_io,
151*1c60b9acSAndroid Build Coastguard Worker	.child_process_terminated	= ssh_ops_child_process_terminated,
152*1c60b9acSAndroid Build Coastguard Worker	.exec				= ssh_ops_exec,
153*1c60b9acSAndroid Build Coastguard Worker	.shell				= ssh_ops_shell,
154*1c60b9acSAndroid Build Coastguard Worker	.is_pubkey_authorized		= ssh_ops_is_pubkey_authorized,
155*1c60b9acSAndroid Build Coastguard Worker	.banner				= ssh_ops_banner,
156*1c60b9acSAndroid Build Coastguard Worker	.disconnect_reason		= ssh_ops_disconnect_reason,
157*1c60b9acSAndroid Build Coastguard Worker	.server_string			= "SSH-2.0-Libwebsockets",
158*1c60b9acSAndroid Build Coastguard Worker	.api_version			= 1,
159*1c60b9acSAndroid Build Coastguard Worker};
160*1c60b9acSAndroid Build Coastguard Worker```
161*1c60b9acSAndroid Build Coastguard WorkerThe `ssh_ops_...()` functions are your implementations for the operations
162*1c60b9acSAndroid Build Coastguard Workerneeded by the plugin for your purposes.
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker### Step 3: enable `lws-ssh-base` protocol to a vhost and configure using pvo
165*1c60b9acSAndroid Build Coastguard Worker
166*1c60b9acSAndroid Build Coastguard WorkerA pointer to your struct lws_ssh_ops is passed into the vhost instance of the
167*1c60b9acSAndroid Build Coastguard Workerprotocol using per-vhost options
168*1c60b9acSAndroid Build Coastguard Worker
169*1c60b9acSAndroid Build Coastguard Worker```
170*1c60b9acSAndroid Build Coastguard Workerstatic const struct lws_protocol_vhost_options pvo_ssh_ops = {
171*1c60b9acSAndroid Build Coastguard Worker	NULL,
172*1c60b9acSAndroid Build Coastguard Worker	NULL,
173*1c60b9acSAndroid Build Coastguard Worker	"ops",
174*1c60b9acSAndroid Build Coastguard Worker	(void *)&ssh_ops
175*1c60b9acSAndroid Build Coastguard Worker};
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Workerstatic const struct lws_protocol_vhost_options pvo_ssh = {
178*1c60b9acSAndroid Build Coastguard Worker	NULL,
179*1c60b9acSAndroid Build Coastguard Worker	&pvo_ssh_ops,
180*1c60b9acSAndroid Build Coastguard Worker	"lws-sshd-base",
181*1c60b9acSAndroid Build Coastguard Worker	"" /* ignored, just matches the protocol name above */
182*1c60b9acSAndroid Build Coastguard Worker};
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker...
185*1c60b9acSAndroid Build Coastguard Worker	info.port = 22;
186*1c60b9acSAndroid Build Coastguard Worker	info.options = LWS_SERVER_OPTION_ONLY_RAW;
187*1c60b9acSAndroid Build Coastguard Worker	info.vhost_name = "sshd";
188*1c60b9acSAndroid Build Coastguard Worker	info.protocols = protocols_sshd;
189*1c60b9acSAndroid Build Coastguard Worker	info.pvo = &pvo_ssh;
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker	vh_sshd = lws_create_vhost(context, &info);
192*1c60b9acSAndroid Build Coastguard Worker```
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard WorkerThere are two possible pvos supported, "ops", shown above, directly passes the
195*1c60b9acSAndroid Build Coastguard Workerops structure in using the value on the "ops" pvo.
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard WorkerTo support other protocols that want to provide ops to lws-ssh-base themselves
198*1c60b9acSAndroid Build Coastguard Workerfor a particular vhost, you can also provide a pvo `"ops-from"` whose value is
199*1c60b9acSAndroid Build Coastguard Workerthe name of the protocol also enabled on this vhost, whose protocol ".user"
200*1c60b9acSAndroid Build Coastguard Workerpointer points to the ops struct lws-ssh-base should use.
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker## Integration to other plugins
203*1c60b9acSAndroid Build Coastguard Worker
204*1c60b9acSAndroid Build Coastguard WorkerA worked example of using the abstract `lws-ssh-base` plugin from another
205*1c60b9acSAndroid Build Coastguard Workerplugin that provides the ops struct is in `./plugins/protocol_lws_sshd_demo`.
206*1c60b9acSAndroid Build Coastguard Worker
207*1c60b9acSAndroid Build Coastguard WorkerThe key points to note
208*1c60b9acSAndroid Build Coastguard Worker
209*1c60b9acSAndroid Build Coastguard Worker - the plugin sets the ops struct for the vhost instantiation of `lws-ssh-base`
210*1c60b9acSAndroid Build Coastguard Worker by passing a pointer to the ops struct in its `lws_protocols` struct `user`
211*1c60b9acSAndroid Build Coastguard Worker member.
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker - the config for the vhost tells `lws-ssh-base` to pick up the ops struct
214*1c60b9acSAndroid Build Coastguard Worker pointer using an "ops-from" pvo that indicates the protocol name.
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker```
217*1c60b9acSAndroid Build Coastguard Worker 			"lws-ssh-base": {
218*1c60b9acSAndroid Build Coastguard Worker                                "status": "ok",
219*1c60b9acSAndroid Build Coastguard Worker                                "ops-from": "lws-sshd-demo"
220*1c60b9acSAndroid Build Coastguard Worker                        },
221*1c60b9acSAndroid Build Coastguard Worker```
222*1c60b9acSAndroid Build Coastguard Worker
223*1c60b9acSAndroid Build Coastguard Worker - the config for the vhost tells lws this vhost only serves RAW (ie, no http)
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker```
226*1c60b9acSAndroid Build Coastguard Worker         {
227*1c60b9acSAndroid Build Coastguard Worker                "name": "sshd",
228*1c60b9acSAndroid Build Coastguard Worker                "port": "2222",
229*1c60b9acSAndroid Build Coastguard Worker                "onlyraw": "1",
230*1c60b9acSAndroid Build Coastguard Worker                ...
231*1c60b9acSAndroid Build Coastguard Worker```
232*1c60b9acSAndroid Build Coastguard Worker
233*1c60b9acSAndroid Build Coastguard Worker - the config for the vhost marks the protocol that uses `lws-ssh-base`, not
234*1c60b9acSAndroid Build Coastguard Worker `lws-ssh-base` itself, as the protocol to be served for raw connections
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker```
237*1c60b9acSAndroid Build Coastguard Worker                        "lws-sshd-demo": {
238*1c60b9acSAndroid Build Coastguard Worker                                "status": "ok",
239*1c60b9acSAndroid Build Coastguard Worker                                "raw": "1"
240*1c60b9acSAndroid Build Coastguard Worker                         ...
241*1c60b9acSAndroid Build Coastguard Worker```
242*1c60b9acSAndroid Build Coastguard Worker
243*1c60b9acSAndroid Build Coastguard Worker## Notes
244*1c60b9acSAndroid Build Coastguard Worker
245*1c60b9acSAndroid Build Coastguard WorkerYou can have the vhost it binds to listen on a nonstandard port.  The ssh
246*1c60b9acSAndroid Build Coastguard Workercommandline app cane be told to connect to a non-22 port with
247*1c60b9acSAndroid Build Coastguard Worker`ssh -p portnum user@hostname`
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker
250