1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * ws protocol handler plugin for sshd demo
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2019 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
7*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
8*1c60b9acSAndroid Build Coastguard Worker *
9*1c60b9acSAndroid Build Coastguard Worker * The person who associated a work with this deed has dedicated
10*1c60b9acSAndroid Build Coastguard Worker * the work to the public domain by waiving all of his or her rights
11*1c60b9acSAndroid Build Coastguard Worker * to the work worldwide under copyright law, including all related
12*1c60b9acSAndroid Build Coastguard Worker * and neighboring rights, to the extent allowed by law. You can copy,
13*1c60b9acSAndroid Build Coastguard Worker * modify, distribute and perform the work, even for commercial purposes,
14*1c60b9acSAndroid Build Coastguard Worker * all without asking permission.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * These test plugins are intended to be adapted for use in your code, which
17*1c60b9acSAndroid Build Coastguard Worker * may be proprietary. So unlike the library itself, they are licensed
18*1c60b9acSAndroid Build Coastguard Worker * Public Domain.
19*1c60b9acSAndroid Build Coastguard Worker */
20*1c60b9acSAndroid Build Coastguard Worker
21*1c60b9acSAndroid Build Coastguard Worker #if !defined (LWS_PLUGIN_STATIC)
22*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_DLL)
23*1c60b9acSAndroid Build Coastguard Worker #define LWS_DLL
24*1c60b9acSAndroid Build Coastguard Worker #endif
25*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_INTERNAL)
26*1c60b9acSAndroid Build Coastguard Worker #define LWS_INTERNAL
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
29*1c60b9acSAndroid Build Coastguard Worker #endif
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker #include <lws-ssh.h>
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
34*1c60b9acSAndroid Build Coastguard Worker #include <stdlib.h>
35*1c60b9acSAndroid Build Coastguard Worker #include <errno.h>
36*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker #define TEST_SERVER_KEY_PATH "/etc/lws-test-sshd-server-key"
39*1c60b9acSAndroid Build Coastguard Worker
40*1c60b9acSAndroid Build Coastguard Worker struct per_vhost_data__lws_sshd_demo {
41*1c60b9acSAndroid Build Coastguard Worker const struct lws_protocols *ssh_base_protocol;
42*1c60b9acSAndroid Build Coastguard Worker int privileged_fd;
43*1c60b9acSAndroid Build Coastguard Worker };
44*1c60b9acSAndroid Build Coastguard Worker
45*1c60b9acSAndroid Build Coastguard Worker /*
46*1c60b9acSAndroid Build Coastguard Worker * This is a copy of the lws ssh test public key, you can find it in
47*1c60b9acSAndroid Build Coastguard Worker * /usr[/local]/share/libwebsockets-test-server/lws-ssh-test-keys.pub
48*1c60b9acSAndroid Build Coastguard Worker * and the matching private key there too in .../lws-ssh-test-keys
49*1c60b9acSAndroid Build Coastguard Worker *
50*1c60b9acSAndroid Build Coastguard Worker * If the vhost with this protocol is using localhost:2222, you can test with
51*1c60b9acSAndroid Build Coastguard Worker * the matching private key like this:
52*1c60b9acSAndroid Build Coastguard Worker *
53*1c60b9acSAndroid Build Coastguard Worker * ssh -p 2222 -i /usr/local/share/libwebsockets-test-server/lws-ssh-test-keys [email protected]
54*1c60b9acSAndroid Build Coastguard Worker *
55*1c60b9acSAndroid Build Coastguard Worker * These keys are distributed for testing! Don't use them on a real system
56*1c60b9acSAndroid Build Coastguard Worker * unless you want anyone with a copy of lws to access it.
57*1c60b9acSAndroid Build Coastguard Worker */
58*1c60b9acSAndroid Build Coastguard Worker static const char *authorized_key =
59*1c60b9acSAndroid Build Coastguard Worker "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCnWiP+c+kSD6Lk+C6NA9KruApa45sbt"
60*1c60b9acSAndroid Build Coastguard Worker "94/dxT0bCITlAA/+PBk6mR1lwWgXYozOMdrHrqx34piqDyXnc4HabqCaOm/FrYhkCPL8z"
61*1c60b9acSAndroid Build Coastguard Worker "a26PMYqteSosuwKv//5iT6ZWhNnsMwExBwtV6MIq0MxAeWqxRnYNWpNM8iN6sFzkdG/YF"
62*1c60b9acSAndroid Build Coastguard Worker "dyHrIBTgwzM77NLCMl6GEkJErRCFppC2SwYxGa3BRrgUwX3LkV8HpMIaYHFo1Qgj7Scqm"
63*1c60b9acSAndroid Build Coastguard Worker "HwS2R75SOqi2aOWDpKjznARg9JgzDWSQi4seBMV2oL0BTwJANSDf+p0sQLsaKGJhpVpBQ"
64*1c60b9acSAndroid Build Coastguard Worker "yS2wUeyuGyytupWzEluQrajMZq52iotcogv5BfeulfTTFbJP4kuHOsSP0lsQ2lpMDQANS"
65*1c60b9acSAndroid Build Coastguard Worker "HEvXxzHJLDLXM9gXJzwJ+ZiRt6R+bfmP1nfN3MiWtxcIbBanWwQK6xTCKBe4wPaKta5EU"
66*1c60b9acSAndroid Build Coastguard Worker "6wsLPeakOIVzoeaOu/HsbtPZlwX0Mu/oUFcfKyKAhlkU15MOAIEfUPo8Yh52bWMlIlpZa"
67*1c60b9acSAndroid Build Coastguard Worker "4xWbLMGw3GrsrPPdcsAauyqvY4/NjjWQbWhP1SuUfvv5709PIiOUjVKK2HUwmR1ouch6X"
68*1c60b9acSAndroid Build Coastguard Worker "MQGXfMR1h1Wjvc+bkNs17gCIrQnFilAZLC3Sm3Opiz/4LO99Hw448G0RM2vQn0mJE46w"
69*1c60b9acSAndroid Build Coastguard Worker "Eu/B10U6Jf4Efojhh1dk85BD1LTIb+N3Q== ssh-test-key@lws";
70*1c60b9acSAndroid Build Coastguard Worker
71*1c60b9acSAndroid Build Coastguard Worker enum states {
72*1c60b9acSAndroid Build Coastguard Worker SSH_TEST_GREET,
73*1c60b9acSAndroid Build Coastguard Worker SSH_TEST_PRESSED,
74*1c60b9acSAndroid Build Coastguard Worker SSH_TEST_DONE,
75*1c60b9acSAndroid Build Coastguard Worker };
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker static const char * const strings[] =
78*1c60b9acSAndroid Build Coastguard Worker {
79*1c60b9acSAndroid Build Coastguard Worker /* SSH_TEST_GREET */
80*1c60b9acSAndroid Build Coastguard Worker "Thanks for logging to lws sshd server demo.\n\r"
81*1c60b9acSAndroid Build Coastguard Worker "\n\r"
82*1c60b9acSAndroid Build Coastguard Worker "This demo is very simple, it waits for you to press\n\r"
83*1c60b9acSAndroid Build Coastguard Worker "a key, and acknowledges it. Then press another key\n\r"
84*1c60b9acSAndroid Build Coastguard Worker "and it will exit. But actually that demos the basic\n\r"
85*1c60b9acSAndroid Build Coastguard Worker "sshd functions underneath. You can use the ops struct\n\r"
86*1c60b9acSAndroid Build Coastguard Worker "members to add a pty / shell or whatever you want.\n\r"
87*1c60b9acSAndroid Build Coastguard Worker "\n\r"
88*1c60b9acSAndroid Build Coastguard Worker "Press a key...\n\r",
89*1c60b9acSAndroid Build Coastguard Worker
90*1c60b9acSAndroid Build Coastguard Worker /* SSH_TEST_PRESSED */
91*1c60b9acSAndroid Build Coastguard Worker "Thanks for pressing a key. Press another to exit.\n\r",
92*1c60b9acSAndroid Build Coastguard Worker
93*1c60b9acSAndroid Build Coastguard Worker /* SSH_TEST_DONE */
94*1c60b9acSAndroid Build Coastguard Worker "Bye!\n\r"
95*1c60b9acSAndroid Build Coastguard Worker };
96*1c60b9acSAndroid Build Coastguard Worker
97*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv {
98*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi;
99*1c60b9acSAndroid Build Coastguard Worker enum states state;
100*1c60b9acSAndroid Build Coastguard Worker const char *ptr;
101*1c60b9acSAndroid Build Coastguard Worker int pos;
102*1c60b9acSAndroid Build Coastguard Worker int len;
103*1c60b9acSAndroid Build Coastguard Worker };
104*1c60b9acSAndroid Build Coastguard Worker
105*1c60b9acSAndroid Build Coastguard Worker static void
enter_state(struct sshd_instance_priv * priv,enum states state)106*1c60b9acSAndroid Build Coastguard Worker enter_state(struct sshd_instance_priv *priv, enum states state)
107*1c60b9acSAndroid Build Coastguard Worker {
108*1c60b9acSAndroid Build Coastguard Worker priv->state = state;
109*1c60b9acSAndroid Build Coastguard Worker priv->ptr = strings[state];
110*1c60b9acSAndroid Build Coastguard Worker priv->pos = 0;
111*1c60b9acSAndroid Build Coastguard Worker priv->len = (int)strlen(priv->ptr);
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(priv->wsi);
114*1c60b9acSAndroid Build Coastguard Worker }
115*1c60b9acSAndroid Build Coastguard Worker
116*1c60b9acSAndroid Build Coastguard Worker /* ops: channel lifecycle */
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_channel_create(struct lws * wsi,void ** _priv)119*1c60b9acSAndroid Build Coastguard Worker ssh_ops_channel_create(struct lws *wsi, void **_priv)
120*1c60b9acSAndroid Build Coastguard Worker {
121*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv;
122*1c60b9acSAndroid Build Coastguard Worker
123*1c60b9acSAndroid Build Coastguard Worker priv = malloc(sizeof(struct sshd_instance_priv));
124*1c60b9acSAndroid Build Coastguard Worker *_priv = priv;
125*1c60b9acSAndroid Build Coastguard Worker if (!priv)
126*1c60b9acSAndroid Build Coastguard Worker return 1;
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard Worker memset(priv, 0, sizeof(*priv));
129*1c60b9acSAndroid Build Coastguard Worker priv->wsi = wsi;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker return 0;
132*1c60b9acSAndroid Build Coastguard Worker }
133*1c60b9acSAndroid Build Coastguard Worker
134*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_channel_destroy(void * _priv)135*1c60b9acSAndroid Build Coastguard Worker ssh_ops_channel_destroy(void *_priv)
136*1c60b9acSAndroid Build Coastguard Worker {
137*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv = _priv;
138*1c60b9acSAndroid Build Coastguard Worker
139*1c60b9acSAndroid Build Coastguard Worker free(priv);
140*1c60b9acSAndroid Build Coastguard Worker
141*1c60b9acSAndroid Build Coastguard Worker return 0;
142*1c60b9acSAndroid Build Coastguard Worker }
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker /* ops: IO */
145*1c60b9acSAndroid Build Coastguard Worker
146*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_tx_waiting(void * _priv)147*1c60b9acSAndroid Build Coastguard Worker ssh_ops_tx_waiting(void *_priv)
148*1c60b9acSAndroid Build Coastguard Worker {
149*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv = _priv;
150*1c60b9acSAndroid Build Coastguard Worker
151*1c60b9acSAndroid Build Coastguard Worker if (priv->state == SSH_TEST_DONE &&
152*1c60b9acSAndroid Build Coastguard Worker priv->pos == priv->len)
153*1c60b9acSAndroid Build Coastguard Worker return -1; /* exit */
154*1c60b9acSAndroid Build Coastguard Worker
155*1c60b9acSAndroid Build Coastguard Worker if (priv->pos != priv->len)
156*1c60b9acSAndroid Build Coastguard Worker return LWS_STDOUT;
157*1c60b9acSAndroid Build Coastguard Worker
158*1c60b9acSAndroid Build Coastguard Worker return 0;
159*1c60b9acSAndroid Build Coastguard Worker }
160*1c60b9acSAndroid Build Coastguard Worker
161*1c60b9acSAndroid Build Coastguard Worker static size_t
ssh_ops_tx(void * _priv,int stdch,uint8_t * buf,size_t len)162*1c60b9acSAndroid Build Coastguard Worker ssh_ops_tx(void *_priv, int stdch, uint8_t *buf, size_t len)
163*1c60b9acSAndroid Build Coastguard Worker {
164*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv = _priv;
165*1c60b9acSAndroid Build Coastguard Worker size_t chunk = len;
166*1c60b9acSAndroid Build Coastguard Worker
167*1c60b9acSAndroid Build Coastguard Worker if (stdch != LWS_STDOUT)
168*1c60b9acSAndroid Build Coastguard Worker return 0;
169*1c60b9acSAndroid Build Coastguard Worker
170*1c60b9acSAndroid Build Coastguard Worker if ((size_t)(priv->len - priv->pos) < chunk)
171*1c60b9acSAndroid Build Coastguard Worker chunk = (size_t)(priv->len - priv->pos);
172*1c60b9acSAndroid Build Coastguard Worker
173*1c60b9acSAndroid Build Coastguard Worker if (!chunk)
174*1c60b9acSAndroid Build Coastguard Worker return 0;
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, priv->ptr + priv->pos, chunk);
177*1c60b9acSAndroid Build Coastguard Worker priv->pos += (int)chunk;
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker if (priv->state == SSH_TEST_DONE && priv->pos == priv->len) {
180*1c60b9acSAndroid Build Coastguard Worker /*
181*1c60b9acSAndroid Build Coastguard Worker * we are sending the last thing we want to send
182*1c60b9acSAndroid Build Coastguard Worker * before exiting. Make it ask again at ssh_ops_tx_waiting()
183*1c60b9acSAndroid Build Coastguard Worker * and we will exit then, after this has been sent
184*1c60b9acSAndroid Build Coastguard Worker */
185*1c60b9acSAndroid Build Coastguard Worker lws_callback_on_writable(priv->wsi);
186*1c60b9acSAndroid Build Coastguard Worker }
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker return chunk;
189*1c60b9acSAndroid Build Coastguard Worker }
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker
192*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_rx(void * _priv,struct lws * wsi,const uint8_t * buf,uint32_t len)193*1c60b9acSAndroid Build Coastguard Worker ssh_ops_rx(void *_priv, struct lws *wsi, const uint8_t *buf, uint32_t len)
194*1c60b9acSAndroid Build Coastguard Worker {
195*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv = _priv;
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker if (priv->state < SSH_TEST_DONE)
198*1c60b9acSAndroid Build Coastguard Worker enter_state(priv, priv->state + 1);
199*1c60b9acSAndroid Build Coastguard Worker else
200*1c60b9acSAndroid Build Coastguard Worker return -1;
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker return 0;
203*1c60b9acSAndroid Build Coastguard Worker }
204*1c60b9acSAndroid Build Coastguard Worker
205*1c60b9acSAndroid Build Coastguard Worker /* ops: storage for the (autogenerated) persistent server key */
206*1c60b9acSAndroid Build Coastguard Worker
207*1c60b9acSAndroid Build Coastguard Worker static size_t
ssh_ops_get_server_key(struct lws * wsi,uint8_t * buf,size_t len)208*1c60b9acSAndroid Build Coastguard Worker ssh_ops_get_server_key(struct lws *wsi, uint8_t *buf, size_t len)
209*1c60b9acSAndroid Build Coastguard Worker {
210*1c60b9acSAndroid Build Coastguard Worker struct per_vhost_data__lws_sshd_demo *vhd =
211*1c60b9acSAndroid Build Coastguard Worker (struct per_vhost_data__lws_sshd_demo *)
212*1c60b9acSAndroid Build Coastguard Worker lws_protocol_vh_priv_get(lws_get_vhost(wsi),
213*1c60b9acSAndroid Build Coastguard Worker lws_get_protocol(wsi));
214*1c60b9acSAndroid Build Coastguard Worker int n;
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker if (lseek(vhd->privileged_fd, 0, SEEK_SET) < 0)
217*1c60b9acSAndroid Build Coastguard Worker return 0;
218*1c60b9acSAndroid Build Coastguard Worker n = (int)read(vhd->privileged_fd, buf, (unsigned int)len);
219*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
220*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: read failed: %d\n", __func__, n);
221*1c60b9acSAndroid Build Coastguard Worker n = 0;
222*1c60b9acSAndroid Build Coastguard Worker }
223*1c60b9acSAndroid Build Coastguard Worker
224*1c60b9acSAndroid Build Coastguard Worker return (size_t)n;
225*1c60b9acSAndroid Build Coastguard Worker }
226*1c60b9acSAndroid Build Coastguard Worker
227*1c60b9acSAndroid Build Coastguard Worker static size_t
ssh_ops_set_server_key(struct lws * wsi,uint8_t * buf,size_t len)228*1c60b9acSAndroid Build Coastguard Worker ssh_ops_set_server_key(struct lws *wsi, uint8_t *buf, size_t len)
229*1c60b9acSAndroid Build Coastguard Worker {
230*1c60b9acSAndroid Build Coastguard Worker struct per_vhost_data__lws_sshd_demo *vhd =
231*1c60b9acSAndroid Build Coastguard Worker (struct per_vhost_data__lws_sshd_demo *)
232*1c60b9acSAndroid Build Coastguard Worker lws_protocol_vh_priv_get(lws_get_vhost(wsi),
233*1c60b9acSAndroid Build Coastguard Worker lws_get_protocol(wsi));
234*1c60b9acSAndroid Build Coastguard Worker int n;
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker n = (int)write(vhd->privileged_fd, buf, (unsigned int)len);
237*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
238*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: read failed: %d\n", __func__, errno);
239*1c60b9acSAndroid Build Coastguard Worker n = 0;
240*1c60b9acSAndroid Build Coastguard Worker }
241*1c60b9acSAndroid Build Coastguard Worker
242*1c60b9acSAndroid Build Coastguard Worker return (size_t)n;
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker
245*1c60b9acSAndroid Build Coastguard Worker /* ops: auth */
246*1c60b9acSAndroid Build Coastguard Worker
247*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_is_pubkey_authorized(const char * username,const char * type,const uint8_t * peer,int peer_len)248*1c60b9acSAndroid Build Coastguard Worker ssh_ops_is_pubkey_authorized(const char *username, const char *type,
249*1c60b9acSAndroid Build Coastguard Worker const uint8_t *peer, int peer_len)
250*1c60b9acSAndroid Build Coastguard Worker {
251*1c60b9acSAndroid Build Coastguard Worker char *aps, *p, *ps;
252*1c60b9acSAndroid Build Coastguard Worker int n = (int)strlen(type), alen = 2048, ret = 2, len;
253*1c60b9acSAndroid Build Coastguard Worker size_t s = 0;
254*1c60b9acSAndroid Build Coastguard Worker
255*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: checking pubkey for %s\n", __func__, username);
256*1c60b9acSAndroid Build Coastguard Worker
257*1c60b9acSAndroid Build Coastguard Worker s = strlen(authorized_key) + 1;
258*1c60b9acSAndroid Build Coastguard Worker
259*1c60b9acSAndroid Build Coastguard Worker aps = malloc(s);
260*1c60b9acSAndroid Build Coastguard Worker if (!aps) {
261*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("OOM 1\n");
262*1c60b9acSAndroid Build Coastguard Worker goto bail_p1;
263*1c60b9acSAndroid Build Coastguard Worker }
264*1c60b9acSAndroid Build Coastguard Worker memcpy(aps, authorized_key, s);
265*1c60b9acSAndroid Build Coastguard Worker
266*1c60b9acSAndroid Build Coastguard Worker /* we only understand RSA */
267*1c60b9acSAndroid Build Coastguard Worker if (strcmp(type, "ssh-rsa")) {
268*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("type is not ssh-rsa\n");
269*1c60b9acSAndroid Build Coastguard Worker goto bail_p1;
270*1c60b9acSAndroid Build Coastguard Worker }
271*1c60b9acSAndroid Build Coastguard Worker p = aps;
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker if (strncmp(p, type, (unsigned int)n)) {
274*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("lead-in string does not match %s\n", type);
275*1c60b9acSAndroid Build Coastguard Worker goto bail_p1;
276*1c60b9acSAndroid Build Coastguard Worker }
277*1c60b9acSAndroid Build Coastguard Worker
278*1c60b9acSAndroid Build Coastguard Worker p += n;
279*1c60b9acSAndroid Build Coastguard Worker if (*p != ' ') {
280*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("missing space at end of lead-in\n");
281*1c60b9acSAndroid Build Coastguard Worker goto bail_p1;
282*1c60b9acSAndroid Build Coastguard Worker }
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker p++;
285*1c60b9acSAndroid Build Coastguard Worker ps = malloc((unsigned int)alen);
286*1c60b9acSAndroid Build Coastguard Worker if (!ps) {
287*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("OOM 2\n");
288*1c60b9acSAndroid Build Coastguard Worker free(aps);
289*1c60b9acSAndroid Build Coastguard Worker goto bail;
290*1c60b9acSAndroid Build Coastguard Worker }
291*1c60b9acSAndroid Build Coastguard Worker len = lws_b64_decode_string(p, ps, alen);
292*1c60b9acSAndroid Build Coastguard Worker free(aps);
293*1c60b9acSAndroid Build Coastguard Worker if (len < 0) {
294*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("key too big\n");
295*1c60b9acSAndroid Build Coastguard Worker goto bail;
296*1c60b9acSAndroid Build Coastguard Worker }
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker if (peer_len > len) {
299*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("peer_len %d bigger than decoded len %d\n",
300*1c60b9acSAndroid Build Coastguard Worker peer_len, len);
301*1c60b9acSAndroid Build Coastguard Worker goto bail;
302*1c60b9acSAndroid Build Coastguard Worker }
303*1c60b9acSAndroid Build Coastguard Worker
304*1c60b9acSAndroid Build Coastguard Worker /*
305*1c60b9acSAndroid Build Coastguard Worker * once we are past that, it's the same <len32>name
306*1c60b9acSAndroid Build Coastguard Worker * <len32>E<len32>N that the peer sends us
307*1c60b9acSAndroid Build Coastguard Worker */
308*1c60b9acSAndroid Build Coastguard Worker if (memcmp(peer, ps, (unsigned int)peer_len)) {
309*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: factors mismatch, rejecting key\n", __func__);
310*1c60b9acSAndroid Build Coastguard Worker goto bail;
311*1c60b9acSAndroid Build Coastguard Worker }
312*1c60b9acSAndroid Build Coastguard Worker
313*1c60b9acSAndroid Build Coastguard Worker lwsl_info("pubkey authorized\n");
314*1c60b9acSAndroid Build Coastguard Worker
315*1c60b9acSAndroid Build Coastguard Worker ret = 0;
316*1c60b9acSAndroid Build Coastguard Worker bail:
317*1c60b9acSAndroid Build Coastguard Worker free(ps);
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker return ret;
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker bail_p1:
322*1c60b9acSAndroid Build Coastguard Worker if (aps)
323*1c60b9acSAndroid Build Coastguard Worker free(aps);
324*1c60b9acSAndroid Build Coastguard Worker
325*1c60b9acSAndroid Build Coastguard Worker return 1;
326*1c60b9acSAndroid Build Coastguard Worker }
327*1c60b9acSAndroid Build Coastguard Worker
328*1c60b9acSAndroid Build Coastguard Worker static int
ssh_ops_shell(void * _priv,struct lws * wsi,lws_ssh_finish_exec finish,void * finish_handle)329*1c60b9acSAndroid Build Coastguard Worker ssh_ops_shell(void *_priv, struct lws *wsi, lws_ssh_finish_exec finish, void *finish_handle)
330*1c60b9acSAndroid Build Coastguard Worker {
331*1c60b9acSAndroid Build Coastguard Worker struct sshd_instance_priv *priv = _priv;
332*1c60b9acSAndroid Build Coastguard Worker
333*1c60b9acSAndroid Build Coastguard Worker /* for this demo, we don't open a real shell */
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker enter_state(priv, SSH_TEST_GREET);
336*1c60b9acSAndroid Build Coastguard Worker
337*1c60b9acSAndroid Build Coastguard Worker return 0;
338*1c60b9acSAndroid Build Coastguard Worker }
339*1c60b9acSAndroid Build Coastguard Worker
340*1c60b9acSAndroid Build Coastguard Worker /* ops: banner */
341*1c60b9acSAndroid Build Coastguard Worker
342*1c60b9acSAndroid Build Coastguard Worker static size_t
ssh_ops_banner(char * buf,size_t max_len,char * lang,size_t max_lang_len)343*1c60b9acSAndroid Build Coastguard Worker ssh_ops_banner(char *buf, size_t max_len, char *lang, size_t max_lang_len)
344*1c60b9acSAndroid Build Coastguard Worker {
345*1c60b9acSAndroid Build Coastguard Worker int n = lws_snprintf(buf, max_len, "\n"
346*1c60b9acSAndroid Build Coastguard Worker " |\\---/| lws-ssh Test Server\n"
347*1c60b9acSAndroid Build Coastguard Worker " | o_o | SSH Terminal Server\n"
348*1c60b9acSAndroid Build Coastguard Worker " \\_^_/ Copyright (C) 2017 Crash Barrier Ltd\n\n");
349*1c60b9acSAndroid Build Coastguard Worker
350*1c60b9acSAndroid Build Coastguard Worker lws_snprintf(lang, max_lang_len, "en/US");
351*1c60b9acSAndroid Build Coastguard Worker
352*1c60b9acSAndroid Build Coastguard Worker return (size_t)n;
353*1c60b9acSAndroid Build Coastguard Worker }
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker static void
ssh_ops_disconnect_reason(uint32_t reason,const char * desc,const char * desc_lang)356*1c60b9acSAndroid Build Coastguard Worker ssh_ops_disconnect_reason(uint32_t reason, const char *desc,
357*1c60b9acSAndroid Build Coastguard Worker const char *desc_lang)
358*1c60b9acSAndroid Build Coastguard Worker {
359*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("DISCONNECT reason 0x%X, %s (lang %s)\n", reason, desc,
360*1c60b9acSAndroid Build Coastguard Worker desc_lang);
361*1c60b9acSAndroid Build Coastguard Worker }
362*1c60b9acSAndroid Build Coastguard Worker
363*1c60b9acSAndroid Build Coastguard Worker
364*1c60b9acSAndroid Build Coastguard Worker static const struct lws_ssh_ops ssh_ops = {
365*1c60b9acSAndroid Build Coastguard Worker .channel_create = ssh_ops_channel_create,
366*1c60b9acSAndroid Build Coastguard Worker .channel_destroy = ssh_ops_channel_destroy,
367*1c60b9acSAndroid Build Coastguard Worker .tx_waiting = ssh_ops_tx_waiting,
368*1c60b9acSAndroid Build Coastguard Worker .tx = ssh_ops_tx,
369*1c60b9acSAndroid Build Coastguard Worker .rx = ssh_ops_rx,
370*1c60b9acSAndroid Build Coastguard Worker .get_server_key = ssh_ops_get_server_key,
371*1c60b9acSAndroid Build Coastguard Worker .set_server_key = ssh_ops_set_server_key,
372*1c60b9acSAndroid Build Coastguard Worker .set_env = NULL,
373*1c60b9acSAndroid Build Coastguard Worker .pty_req = NULL,
374*1c60b9acSAndroid Build Coastguard Worker .child_process_io = NULL,
375*1c60b9acSAndroid Build Coastguard Worker .child_process_terminated = NULL,
376*1c60b9acSAndroid Build Coastguard Worker .exec = NULL,
377*1c60b9acSAndroid Build Coastguard Worker .shell = ssh_ops_shell,
378*1c60b9acSAndroid Build Coastguard Worker .is_pubkey_authorized = ssh_ops_is_pubkey_authorized,
379*1c60b9acSAndroid Build Coastguard Worker .banner = ssh_ops_banner,
380*1c60b9acSAndroid Build Coastguard Worker .disconnect_reason = ssh_ops_disconnect_reason,
381*1c60b9acSAndroid Build Coastguard Worker .server_string = "SSH-2.0-Libwebsockets",
382*1c60b9acSAndroid Build Coastguard Worker .api_version = 2,
383*1c60b9acSAndroid Build Coastguard Worker };
384*1c60b9acSAndroid Build Coastguard Worker
385*1c60b9acSAndroid Build Coastguard Worker static int
callback_lws_sshd_demo(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)386*1c60b9acSAndroid Build Coastguard Worker callback_lws_sshd_demo(struct lws *wsi, enum lws_callback_reasons reason,
387*1c60b9acSAndroid Build Coastguard Worker void *user, void *in, size_t len)
388*1c60b9acSAndroid Build Coastguard Worker {
389*1c60b9acSAndroid Build Coastguard Worker struct per_vhost_data__lws_sshd_demo *vhd =
390*1c60b9acSAndroid Build Coastguard Worker (struct per_vhost_data__lws_sshd_demo *)
391*1c60b9acSAndroid Build Coastguard Worker lws_protocol_vh_priv_get(lws_get_vhost(wsi),
392*1c60b9acSAndroid Build Coastguard Worker lws_get_protocol(wsi));
393*1c60b9acSAndroid Build Coastguard Worker
394*1c60b9acSAndroid Build Coastguard Worker switch (reason) {
395*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_PROTOCOL_INIT:
396*1c60b9acSAndroid Build Coastguard Worker vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
397*1c60b9acSAndroid Build Coastguard Worker lws_get_protocol(wsi),
398*1c60b9acSAndroid Build Coastguard Worker sizeof(struct per_vhost_data__lws_sshd_demo));
399*1c60b9acSAndroid Build Coastguard Worker if (!vhd)
400*1c60b9acSAndroid Build Coastguard Worker return 0;
401*1c60b9acSAndroid Build Coastguard Worker /*
402*1c60b9acSAndroid Build Coastguard Worker * During this we still have the privs / caps we were started
403*1c60b9acSAndroid Build Coastguard Worker * with. So open an fd on the server key, either just for read
404*1c60b9acSAndroid Build Coastguard Worker * or for creat / trunc if doesn't exist. This allows us to
405*1c60b9acSAndroid Build Coastguard Worker * deal with it down /etc/.. when just after this we will lose
406*1c60b9acSAndroid Build Coastguard Worker * the privileges needed to read / write /etc/...
407*1c60b9acSAndroid Build Coastguard Worker */
408*1c60b9acSAndroid Build Coastguard Worker vhd->privileged_fd = lws_open(TEST_SERVER_KEY_PATH, O_RDONLY);
409*1c60b9acSAndroid Build Coastguard Worker if (vhd->privileged_fd == -1)
410*1c60b9acSAndroid Build Coastguard Worker vhd->privileged_fd = lws_open(TEST_SERVER_KEY_PATH,
411*1c60b9acSAndroid Build Coastguard Worker O_CREAT | O_TRUNC | O_RDWR, 0600);
412*1c60b9acSAndroid Build Coastguard Worker if (vhd->privileged_fd == -1) {
413*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: Can't open %s\n", __func__,
414*1c60b9acSAndroid Build Coastguard Worker TEST_SERVER_KEY_PATH);
415*1c60b9acSAndroid Build Coastguard Worker return 0;
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker break;
418*1c60b9acSAndroid Build Coastguard Worker
419*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_PROTOCOL_DESTROY:
420*1c60b9acSAndroid Build Coastguard Worker if (vhd)
421*1c60b9acSAndroid Build Coastguard Worker close(vhd->privileged_fd);
422*1c60b9acSAndroid Build Coastguard Worker break;
423*1c60b9acSAndroid Build Coastguard Worker
424*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_VHOST_CERT_AGING:
425*1c60b9acSAndroid Build Coastguard Worker break;
426*1c60b9acSAndroid Build Coastguard Worker
427*1c60b9acSAndroid Build Coastguard Worker case LWS_CALLBACK_EVENT_WAIT_CANCELLED:
428*1c60b9acSAndroid Build Coastguard Worker break;
429*1c60b9acSAndroid Build Coastguard Worker
430*1c60b9acSAndroid Build Coastguard Worker default:
431*1c60b9acSAndroid Build Coastguard Worker if (!vhd->ssh_base_protocol) {
432*1c60b9acSAndroid Build Coastguard Worker vhd->ssh_base_protocol = lws_vhost_name_to_protocol(
433*1c60b9acSAndroid Build Coastguard Worker lws_get_vhost(wsi),
434*1c60b9acSAndroid Build Coastguard Worker "lws-ssh-base");
435*1c60b9acSAndroid Build Coastguard Worker if (vhd->ssh_base_protocol)
436*1c60b9acSAndroid Build Coastguard Worker user = lws_adjust_protocol_psds(wsi,
437*1c60b9acSAndroid Build Coastguard Worker vhd->ssh_base_protocol->per_session_data_size);
438*1c60b9acSAndroid Build Coastguard Worker }
439*1c60b9acSAndroid Build Coastguard Worker
440*1c60b9acSAndroid Build Coastguard Worker if (vhd->ssh_base_protocol)
441*1c60b9acSAndroid Build Coastguard Worker return vhd->ssh_base_protocol->callback(wsi, reason,
442*1c60b9acSAndroid Build Coastguard Worker user, in, len);
443*1c60b9acSAndroid Build Coastguard Worker else
444*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("can't find lws-ssh-base\n");
445*1c60b9acSAndroid Build Coastguard Worker break;
446*1c60b9acSAndroid Build Coastguard Worker }
447*1c60b9acSAndroid Build Coastguard Worker
448*1c60b9acSAndroid Build Coastguard Worker return 0;
449*1c60b9acSAndroid Build Coastguard Worker }
450*1c60b9acSAndroid Build Coastguard Worker
451*1c60b9acSAndroid Build Coastguard Worker #define LWS_PLUGIN_PROTOCOL_LWS_SSHD_DEMO \
452*1c60b9acSAndroid Build Coastguard Worker { \
453*1c60b9acSAndroid Build Coastguard Worker "lws-sshd-demo", \
454*1c60b9acSAndroid Build Coastguard Worker callback_lws_sshd_demo, \
455*1c60b9acSAndroid Build Coastguard Worker 0, \
456*1c60b9acSAndroid Build Coastguard Worker 1024, /* rx buf size must be >= permessage-deflate rx size */ \
457*1c60b9acSAndroid Build Coastguard Worker 0, (void *)&ssh_ops, 0 \
458*1c60b9acSAndroid Build Coastguard Worker }
459*1c60b9acSAndroid Build Coastguard Worker
460*1c60b9acSAndroid Build Coastguard Worker #if !defined (LWS_PLUGIN_STATIC)
461*1c60b9acSAndroid Build Coastguard Worker
462*1c60b9acSAndroid Build Coastguard Worker LWS_VISIBLE const struct lws_protocols lws_sshd_demo_protocols[] = {
463*1c60b9acSAndroid Build Coastguard Worker LWS_PLUGIN_PROTOCOL_LWS_SSHD_DEMO
464*1c60b9acSAndroid Build Coastguard Worker };
465*1c60b9acSAndroid Build Coastguard Worker
466*1c60b9acSAndroid Build Coastguard Worker LWS_VISIBLE const lws_plugin_protocol_t lws_sshd_demo = {
467*1c60b9acSAndroid Build Coastguard Worker .hdr = {
468*1c60b9acSAndroid Build Coastguard Worker "lws sshd demo",
469*1c60b9acSAndroid Build Coastguard Worker "lws_protocol_plugin",
470*1c60b9acSAndroid Build Coastguard Worker LWS_BUILD_HASH,
471*1c60b9acSAndroid Build Coastguard Worker LWS_PLUGIN_API_MAGIC
472*1c60b9acSAndroid Build Coastguard Worker },
473*1c60b9acSAndroid Build Coastguard Worker
474*1c60b9acSAndroid Build Coastguard Worker .protocols = lws_sshd_demo_protocols,
475*1c60b9acSAndroid Build Coastguard Worker .count_protocols = LWS_ARRAY_SIZE(lws_sshd_demo_protocols),
476*1c60b9acSAndroid Build Coastguard Worker .extensions = NULL,
477*1c60b9acSAndroid Build Coastguard Worker .count_extensions = 0,
478*1c60b9acSAndroid Build Coastguard Worker };
479*1c60b9acSAndroid Build Coastguard Worker
480*1c60b9acSAndroid Build Coastguard Worker #endif
481