1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
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
25 #include "libwebsockets.h"
26 #include "lws-ssh.h"
27
28 #include <string.h>
29 #include <stdlib.h>
30
sshd_zalloc(size_t s)31 void *sshd_zalloc(size_t s)
32 {
33 void *p = malloc(s);
34
35 if (p)
36 memset(p, 0, s);
37
38 return p;
39 }
40
41 uint32_t
lws_g32(uint8_t ** p)42 lws_g32(uint8_t **p)
43 {
44 uint32_t v = 0;
45
46 v = (v << 8) | *((*p)++);
47 v = (v << 8) | *((*p)++);
48 v = (v << 8) | *((*p)++);
49 v = (v << 8) | *((*p)++);
50
51 return v;
52 }
53
54 uint32_t
lws_p32(uint8_t * p,uint32_t v)55 lws_p32(uint8_t *p, uint32_t v)
56 {
57 *p++ = (uint8_t)(v >> 24);
58 *p++ = (uint8_t)(v >> 16);
59 *p++ = (uint8_t)(v >> 8);
60 *p++ = (uint8_t)v;
61
62 return v;
63 }
64
65 int
lws_cstr(uint8_t ** p,const char * s,uint32_t max)66 lws_cstr(uint8_t **p, const char *s, uint32_t max)
67 {
68 uint32_t n = (uint32_t)strlen(s);
69
70 if (n > max)
71 return 1;
72
73 lws_p32(*p, n);
74 *p += 4;
75 strcpy((char *)(*p), s);
76 *p += n;
77
78 return 0;
79 }
80
81 int
lws_buf(uint8_t ** p,void * s,uint32_t len)82 lws_buf(uint8_t **p, void *s, uint32_t len)
83 {
84 lws_p32(*p, len);
85 *p += 4;
86 memcpy((char *)(*p), s, len);
87 *p += len;
88
89 return 0;
90 }
91
92 void
write_task(struct per_session_data__sshd * pss,struct lws_ssh_channel * ch,int task)93 write_task(struct per_session_data__sshd *pss, struct lws_ssh_channel *ch,
94 int task)
95 {
96 pss->write_task[pss->wt_head] = (uint8_t)task;
97 pss->write_channel[pss->wt_head] = ch;
98 pss->wt_head = (pss->wt_head + 1) & 7;
99 lws_callback_on_writable(pss->wsi);
100 }
101
102 void
write_task_insert(struct per_session_data__sshd * pss,struct lws_ssh_channel * ch,int task)103 write_task_insert(struct per_session_data__sshd *pss, struct lws_ssh_channel *ch,
104 int task)
105 {
106 pss->wt_tail = (pss->wt_tail - 1) & 7;
107 pss->write_task[pss->wt_tail] = (uint8_t)task;
108 pss->write_channel[pss->wt_tail] = ch;
109 lws_callback_on_writable(pss->wsi);
110 }
111
112
113 void
lws_pad_set_length(struct per_session_data__sshd * pss,void * start,uint8_t ** p,struct lws_ssh_keys * keys)114 lws_pad_set_length(struct per_session_data__sshd *pss, void *start, uint8_t **p,
115 struct lws_ssh_keys *keys)
116 {
117 uint32_t len = (uint32_t)lws_ptr_diff(*p, start);
118 uint8_t padc = 4, *bs = start;
119
120 if (keys->full_length)
121 len -= 4;
122
123 if ((len + padc) & (uint32_t)(keys->padding_alignment - 1))
124 padc = (uint8_t)((uint8_t)padc + (uint8_t)(keys->padding_alignment -
125 ((len + padc) & (uint32_t)(keys->padding_alignment - 1))));
126
127 bs[4] = padc;
128 len += padc;
129
130 if (!keys->valid) /* no crypto = pad with 00 */
131 while (padc--)
132 *((*p)++) = 0;
133 else { /* crypto active = pad with random */
134 lws_get_random(pss->vhd->context, *p, padc);
135 (*p) += padc;
136 }
137 if (keys->full_length)
138 len += 4;
139
140 lws_p32(start, len - 4);
141 }
142
143 static uint32_t
offer(struct per_session_data__sshd * pss,uint8_t * p,uint32_t len,int first,int * payload_len)144 offer(struct per_session_data__sshd *pss, uint8_t *p, uint32_t len, int first,
145 int *payload_len)
146 {
147 uint8_t *op = p, *lp, *end = p + len - 1;
148 int n, padc = 4, keylen;
149 char keyt[32];
150 uint8_t keybuf[256];
151
152 keylen = (int)get_gen_server_key_25519(pss, keybuf, (int)sizeof(keybuf));
153 if (!keylen) {
154 lwsl_notice("get_gen_server_key failed\n");
155 return 1;
156 }
157 lwsl_info("keylen %d\n", keylen);
158 n = ed25519_key_parse(keybuf, (unsigned int)keylen,
159 keyt, sizeof(keyt), NULL, NULL);
160 if (n) {
161 lwsl_notice("unable to parse server key: %d\n", n);
162 return 1;
163 }
164
165 /*
166 * byte SSH_MSG_KEXINIT
167 * byte[16] cookie (random bytes)
168 * name-list kex_algorithms
169 * name-list server_host_key_algorithms
170 * name-list encryption_algorithms_client_to_server
171 * name-list encryption_algorithms_server_to_client
172 * name-list mac_algorithms_client_to_server
173 * name-list mac_algorithms_server_to_client
174 * name-list compression_algorithms_client_to_server
175 * name-list compression_algorithms_server_to_client
176 * name-list langua->es_client_to_server
177 * name-list langua->es_server_to_client
178 * boolean first_kex_packet_follows
179 * uint32 0 (reserved for future extension)
180 */
181
182 p += 5; /* msg len + padding */
183
184 *p++ = SSH_MSG_KEXINIT;
185 lws_get_random(pss->vhd->context, p, 16);
186 p += 16;
187
188 /* KEX algorithms */
189
190 lp = p;
191 p += 4;
192 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "curve25519-sha256@libssh.org");
193 p += lws_p32(lp, (uint32_t)n);
194
195 /* Server Host Key Algorithms */
196
197 lp = p;
198 p += 4;
199 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "%s", keyt);
200 p += lws_p32(lp, (uint32_t)n);
201
202 /* Encryption Algorithms: C -> S */
203
204 lp = p;
205 p += 4;
206 // n = lws_snprintf((char *)p, end - p, "aes256-gcm@openssh.com");
207 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "chacha20-poly1305@openssh.com");
208 p += lws_p32(lp, (uint32_t)n);
209
210 /* Encryption Algorithms: S -> C */
211
212 lp = p;
213 p += 4;
214 // n = lws_snprintf((char *)p, end - p, "aes256-gcm@openssh.com");
215 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "chacha20-poly1305@openssh.com");
216 p += lws_p32(lp, (uint32_t)n);
217
218 /* MAC Algorithms: C -> S */
219
220 lp = p;
221 p += 4;
222 /* bogus: chacha20 does not use MACs, but 'none' is not offered */
223 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "hmac-sha2-256");
224 p += lws_p32(lp, (uint32_t)n);
225
226 /* MAC Algorithms: S -> C */
227
228 lp = p;
229 p += 4;
230 /* bogus: chacha20 does not use MACs, but 'none' is not offered */
231 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "hmac-sha2-256");
232 p += lws_p32(lp, (uint32_t)n);
233
234 /* Compression Algorithms: C -> S */
235
236 lp = p;
237 p += 4;
238 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "none");
239 p += lws_p32(lp, (uint32_t)n);
240
241 /* Compression Algorithms: S -> C */
242
243 lp = p;
244 p += 4;
245 n = lws_snprintf((char *)p, lws_ptr_diff_size_t(end, p), "none");
246 p += lws_p32(lp, (uint32_t)n);
247
248 if (p - op < 13 + padc + 8)
249 return 0;
250
251 /* Languages: C -> S */
252
253 *p++ = 0;
254 *p++ = 0;
255 *p++ = 0;
256 *p++ = 0;
257
258 /* Languages: S -> C */
259
260 *p++ = 0;
261 *p++ = 0;
262 *p++ = 0;
263 *p++ = 0;
264
265 /* First KEX packet coming */
266
267 *p++ = !!first;
268
269 /* Reserved */
270
271 *p++ = 0;
272 *p++ = 0;
273 *p++ = 0;
274 *p++ = 0;
275
276 len = (uint32_t)lws_ptr_diff(p, op);
277 if (payload_len)
278 /* starts at buf + 5 and excludes padding */
279 *payload_len = (int)(len - 5);
280
281 /* we must give at least 4 bytes of 00 padding */
282
283 if (((int)len + padc) & 7)
284 padc += 8 - (((int)len + padc) & 7);
285
286 op[4] = (uint8_t)padc;
287 len += (uint32_t)padc;
288
289 while (padc--)
290 *p++ = 0;
291
292 /* recorded length does not include the uint32_t len itself */
293 lws_p32(op, len - 4);
294
295 return len;
296 }
297
298 static int
handle_name(struct per_session_data__sshd * pss)299 handle_name(struct per_session_data__sshd *pss)
300 {
301 struct lws_kex *kex = pss->kex;
302 char keyt[32];
303 uint8_t keybuf[256];
304 int n = 0, len;
305
306 switch (pss->parser_state) {
307 case SSH_KEX_NL_KEX_ALGS:
308 if (!strcmp(pss->name, "curve25519-sha256@libssh.org"))
309 kex->match_bitfield |= 1;
310 break;
311 case SSH_KEX_NL_SHK_ALGS:
312 len = (int)get_gen_server_key_25519(pss, keybuf, (int)sizeof(keybuf));
313 if (!len)
314 break;
315 if (ed25519_key_parse(keybuf, (unsigned int)len,
316 keyt, sizeof(keyt),
317 NULL, NULL)) {
318 lwsl_err("Unable to parse host key %d\n", n);
319 } else {
320 if (!strcmp(pss->name, keyt)) {
321 kex->match_bitfield |= 2;
322 break;
323 }
324 }
325 break;
326 case SSH_KEX_NL_EACTS_ALGS:
327 if (!strcmp(pss->name, "chacha20-poly1305@openssh.com"))
328 kex->match_bitfield |= 4;
329 break;
330 case SSH_KEX_NL_EASTC_ALGS:
331 if (!strcmp(pss->name, "chacha20-poly1305@openssh.com"))
332 kex->match_bitfield |= 8;
333 break;
334 case SSH_KEX_NL_MACTS_ALGS:
335 if (!strcmp(pss->name, "hmac-sha2-256"))
336 kex->match_bitfield |= 16;
337 break;
338 case SSH_KEX_NL_MASTC_ALGS:
339 if (!strcmp(pss->name, "hmac-sha2-256"))
340 kex->match_bitfield |= 32;
341 break;
342 case SSH_KEX_NL_CACTS_ALGS:
343 if (!strcmp(pss->name, "none"))
344 kex->match_bitfield |= 64;
345 break;
346 case SSH_KEX_NL_CASTC_ALGS:
347 if (!strcmp(pss->name, "none"))
348 kex->match_bitfield |= 128;
349 break;
350 case SSH_KEX_NL_LCTS_ALGS:
351 case SSH_KEX_NL_LSTC_ALGS:
352 break;
353 default:
354 break;
355 }
356
357 return 0;
358 }
359
360
361 static int
lws_kex_create(struct per_session_data__sshd * pss)362 lws_kex_create(struct per_session_data__sshd *pss)
363 {
364 pss->kex = sshd_zalloc(sizeof(struct lws_kex));
365 lwsl_info("%s\n", __func__);
366 return !pss->kex;
367 }
368
369 static void
lws_kex_destroy(struct per_session_data__sshd * pss)370 lws_kex_destroy(struct per_session_data__sshd *pss)
371 {
372 if (!pss->kex)
373 return;
374
375 lwsl_info("Destroying KEX\n");
376
377 if (pss->kex->I_C) {
378 free(pss->kex->I_C);
379 pss->kex->I_C = NULL;
380 }
381 if (pss->kex->I_S) {
382 free(pss->kex->I_S);
383 pss->kex->I_S = NULL;
384 }
385
386 lws_explicit_bzero(pss->kex, sizeof(*pss->kex));
387 free(pss->kex);
388 pss->kex = NULL;
389 }
390
391 static void
ssh_free(void * p)392 ssh_free(void *p)
393 {
394 if (!p)
395 return;
396
397 lwsl_debug("%s: FREE %p\n", __func__, p);
398 free(p);
399 }
400
401 #define ssh_free_set_NULL(x) if (x) { ssh_free(x); (x) = NULL; }
402
403 static void
lws_ua_destroy(struct per_session_data__sshd * pss)404 lws_ua_destroy(struct per_session_data__sshd *pss)
405 {
406 if (!pss->ua)
407 return;
408
409 lwsl_info("%s\n", __func__);
410
411 if (pss->ua->username)
412 ssh_free(pss->ua->username);
413 if (pss->ua->service)
414 ssh_free(pss->ua->service);
415 if (pss->ua->alg)
416 ssh_free(pss->ua->alg);
417 if (pss->ua->pubkey)
418 ssh_free(pss->ua->pubkey);
419 if (pss->ua->sig) {
420 lws_explicit_bzero(pss->ua->sig, pss->ua->sig_len);
421 ssh_free(pss->ua->sig);
422 }
423
424 lws_explicit_bzero(pss->ua, sizeof(*pss->ua));
425 free(pss->ua);
426 pss->ua = NULL;
427 }
428
429
430 static int
rsa_hash_alg_from_ident(const char * ident)431 rsa_hash_alg_from_ident(const char *ident)
432 {
433 if (strcmp(ident, "ssh-rsa") == 0 ||
434 strcmp(ident, "ssh-rsa-cert-v01@openssh.com") == 0)
435 return LWS_GENHASH_TYPE_SHA1;
436 if (strcmp(ident, "rsa-sha2-256") == 0)
437 return LWS_GENHASH_TYPE_SHA256;
438 if (strcmp(ident, "rsa-sha2-512") == 0)
439 return LWS_GENHASH_TYPE_SHA512;
440
441 return -1;
442 }
443
444 static void
state_get_string_alloc(struct per_session_data__sshd * pss,int next)445 state_get_string_alloc(struct per_session_data__sshd *pss, int next)
446 {
447 pss->parser_state = SSHS_GET_STRING_LEN_ALLOC;
448 pss->state_after_string = (char)next;
449 }
450
451 static void
state_get_string(struct per_session_data__sshd * pss,int next)452 state_get_string(struct per_session_data__sshd *pss, int next)
453 {
454 pss->parser_state = SSHS_GET_STRING_LEN;
455 pss->state_after_string = (char)next;
456 }
457
458 static void
state_get_u32(struct per_session_data__sshd * pss,int next)459 state_get_u32(struct per_session_data__sshd *pss, int next)
460 {
461 pss->parser_state = SSHS_GET_U32;
462 pss->state_after_string = (char)next;
463 }
464
465 static struct lws_ssh_channel *
ssh_get_server_ch(struct per_session_data__sshd * pss,uint32_t chi)466 ssh_get_server_ch(struct per_session_data__sshd *pss, uint32_t chi)
467 {
468 struct lws_ssh_channel *ch = pss->ch_list;
469
470 while (ch) {
471 if (ch->server_ch == chi)
472 return ch;
473 ch = ch->next;
474 }
475
476 return NULL;
477 }
478
479 #if 0
480 static struct lws_ssh_channel *
481 ssh_get_peer_ch(struct per_session_data__sshd *pss, uint32_t chi)
482 {
483 struct lws_ssh_channel *ch = pss->ch_list;
484
485 while (ch) {
486 if (ch->sender_ch == chi)
487 return ch;
488 ch = ch->next;
489 }
490
491 return NULL;
492 }
493 #endif
494
495 static void
ssh_destroy_channel(struct per_session_data__sshd * pss,struct lws_ssh_channel * ch)496 ssh_destroy_channel(struct per_session_data__sshd *pss,
497 struct lws_ssh_channel *ch)
498 {
499 lws_start_foreach_llp(struct lws_ssh_channel **, ppch, pss->ch_list) {
500 if (*ppch == ch) {
501 lwsl_info("Deleting ch %p\n", ch);
502 if (pss->vhd && pss->vhd->ops &&
503 pss->vhd->ops->channel_destroy)
504 pss->vhd->ops->channel_destroy(ch->priv);
505 *ppch = ch->next;
506 if (ch->sub)
507 free(ch->sub);
508 free(ch);
509
510 return;
511 }
512 } lws_end_foreach_llp(ppch, next);
513
514 lwsl_notice("Failed to delete ch\n");
515 }
516
517 static void
lws_ssh_exec_finish(void * finish_handle,int retcode)518 lws_ssh_exec_finish(void *finish_handle, int retcode)
519 {
520 struct lws_ssh_channel *ch = (struct lws_ssh_channel *)finish_handle;
521 struct per_session_data__sshd *pss = ch->pss;
522
523 ch->retcode = retcode;
524 write_task(pss, ch, SSH_WT_EXIT_STATUS);
525 ch->scheduled_close = 1;
526 write_task(pss, ch, SSH_WT_CH_CLOSE);
527 }
528
529 static int
lws_ssh_parse_plaintext(struct per_session_data__sshd * pss,uint8_t * p,size_t len)530 lws_ssh_parse_plaintext(struct per_session_data__sshd *pss, uint8_t *p, size_t len)
531 {
532 struct lws_gencrypto_keyelem e[LWS_GENCRYPTO_RSA_KEYEL_COUNT];
533 struct lws_genrsa_ctx ctx;
534 struct lws_ssh_channel *ch;
535 struct lws_subprotocol_scp *scp;
536 uint8_t *pp, *ps, hash[64];
537 #if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
538 uint8_t *otmp = NULL;
539 #endif
540 uint32_t m;
541 int n;
542
543 while (len --) {
544 again:
545 switch(pss->parser_state) {
546 case SSH_INITIALIZE_TRANSIENT:
547 pss->parser_state = SSHS_IDSTRING;
548 pss->ctr = 0;
549 pss->copy_to_I_C = 0;
550
551 /* fallthru */
552 case SSHS_IDSTRING:
553 if (*p == 0x0d) {
554 pss->V_C[pss->npos] = '\0';
555 pss->npos = 0;
556 lwsl_info("peer id: %s\n", pss->V_C);
557 p++;
558 pss->parser_state = SSHS_IDSTRING_CR;
559 break;
560 }
561 if (pss->npos < sizeof(pss->V_C) - 1)
562 pss->V_C[pss->npos++] = (char)*p;
563 p++;
564 break;
565
566 case SSHS_IDSTRING_CR:
567 if (*p++ != 0x0a) {
568 lwsl_notice("mangled id string\n");
569 return 1;
570 }
571 pss->ssh_sequence_ctr_cts = 0;
572 pss->parser_state = SSHS_MSG_LEN;
573 break;
574
575 case SSHS_MSG_LEN:
576 pss->msg_len = (pss->msg_len << 8) | *p++;
577 if (++pss->ctr != 4)
578 break;
579
580 if (pss->active_keys_cts.valid) {
581 uint8_t b[4];
582
583 POKE_U32(b, (uint32_t)pss->msg_len);
584 pss->msg_len = lws_chachapoly_get_length(
585 &pss->active_keys_cts,
586 pss->ssh_sequence_ctr_cts, b);
587 } else
588 pss->ssh_sequence_ctr_cts++;
589
590 lwsl_info("msg len %d\n", pss->msg_len);
591
592 pss->parser_state = SSHS_MSG_PADDING;
593 pss->ctr = 0;
594 pss->pos = 4;
595 if (pss->msg_len < 2 + 4) {
596 lwsl_notice("illegal msg size\n");
597 goto bail;
598 }
599 break;
600
601 case SSHS_MSG_PADDING:
602 pss->msg_padding = *p++;
603 pss->parser_state = SSHS_MSG_ID;
604 break;
605
606 case SSHS_MSG_ID:
607 pss->msg_id = *p++;
608 pss->ctr = 0;
609 switch (pss->msg_id) {
610 case SSH_MSG_DISCONNECT:
611 /*
612 * byte SSH_MSG_DISCONNECT
613 * uint32 reason code
614 * string description in ISO-10646
615 * UTF-8 encoding [RFC3629]
616 * string language tag [RFC3066]
617 */
618 lwsl_notice("SSH_MSG_DISCONNECT\n");
619 state_get_u32(pss, SSHS_NVC_DISCONNECT_REASON);
620 break;
621 case SSH_MSG_IGNORE:
622 lwsl_notice("SSH_MSG_IGNORE\n");
623 break;
624 case SSH_MSG_UNIMPLEMENTED:
625 lwsl_notice("SSH_MSG_UNIMPLEMENTED\n");
626 break;
627 case SSH_MSG_DEBUG:
628 lwsl_notice("SSH_MSG_DEBUG\n");
629 break;
630 case SSH_MSG_SERVICE_REQUEST:
631 lwsl_info("SSH_MSG_SERVICE_REQUEST\n");
632 /* payload is a string */
633 state_get_string(pss, SSHS_DO_SERVICE_REQUEST);
634 break;
635 case SSH_MSG_SERVICE_ACCEPT:
636 lwsl_notice("SSH_MSG_ACCEPT\n");
637 break;
638
639 case SSH_MSG_KEXINIT:
640 if (pss->kex_state !=
641 KEX_STATE_EXPECTING_CLIENT_OFFER) {
642 pss->parser_state = SSH_KEX_STATE_SKIP;
643 break;
644 }
645 if (!pss->kex) {
646 lwsl_notice("%s: SSH_MSG_KEXINIT: NULL pss->kex\n", __func__);
647 goto bail;
648 }
649 pss->parser_state = SSH_KEX_STATE_COOKIE;
650 pss->kex->I_C_payload_len = 0;
651 pss->kex->I_C_alloc_len = pss->msg_len;
652 pss->kex->I_C = sshd_zalloc(pss->kex->I_C_alloc_len);
653 if (!pss->kex->I_C) {
654 lwsl_notice("OOM 3\n");
655 goto bail;
656 }
657 pss->kex->I_C[pss->kex->I_C_payload_len++] =
658 pss->msg_id;
659 pss->copy_to_I_C = 1;
660 break;
661 case SSH_MSG_KEX_ECDH_INIT:
662 pss->parser_state = SSH_KEX_STATE_ECDH_KEYLEN;
663 break;
664
665 case SSH_MSG_NEWKEYS:
666 if (pss->kex_state !=
667 KEX_STATE_REPLIED_TO_OFFER &&
668 pss->kex_state !=
669 KEX_STATE_CRYPTO_INITIALIZED) {
670 lwsl_notice("unexpected newkeys\n");
671
672 goto bail;
673 }
674 /*
675 * it means we should now use the keys we
676 * agreed on
677 */
678 lwsl_info("Activating CTS keys\n");
679 pss->active_keys_cts = pss->kex->keys_next_cts;
680 if (lws_chacha_activate(&pss->active_keys_cts))
681 goto bail;
682
683 pss->kex->newkeys |= 2;
684 if (pss->kex->newkeys == 3)
685 lws_kex_destroy(pss);
686
687 if (pss->msg_padding) {
688 pss->copy_to_I_C = 0;
689 pss->parser_state =
690 SSHS_MSG_EAT_PADDING;
691 break;
692 } else {
693 pss->parser_state = SSHS_MSG_LEN;
694 }
695 break;
696
697 case SSH_MSG_USERAUTH_REQUEST:
698 /*
699 * byte SSH_MSG_USERAUTH_REQUEST
700 * string user name in UTF-8
701 * encoding [RFC3629]
702 * string service name in US-ASCII
703 * string "publickey"
704 * boolean FALSE
705 * string public key alg
706 * string public key blob
707 */
708 lwsl_info("SSH_MSG_USERAUTH_REQUEST\n");
709 if (pss->ua) {
710 lwsl_notice("pss->ua overwrite\n");
711
712 goto bail;
713 }
714
715 pss->ua = sshd_zalloc(sizeof(*pss->ua));
716 if (!pss->ua)
717 goto bail;
718
719 state_get_string_alloc(pss, SSHS_DO_UAR_SVC);
720 /* username is destroyed with userauth struct */
721 if (!pss->sent_banner) {
722 if (pss->vhd->ops->banner)
723 write_task(pss, NULL,
724 SSH_WT_UA_BANNER);
725 pss->sent_banner = 1;
726 }
727 break;
728 case SSH_MSG_USERAUTH_FAILURE:
729 goto bail;
730 case SSH_MSG_USERAUTH_SUCCESS:
731 goto bail;
732 case SSH_MSG_USERAUTH_BANNER:
733 goto bail;
734
735 case SSH_MSG_CHANNEL_OPEN:
736 state_get_string(pss, SSHS_NVC_CHOPEN_TYPE);
737 break;
738
739 case SSH_MSG_CHANNEL_REQUEST:
740 /* RFC4254
741 *
742 * byte SSH_MSG_CHANNEL_REQUEST
743 * uint32 recipient channel
744 * string "pty-req"
745 * boolean want_reply
746 * string TERM environment variable value
747 * (e.g., vt100)
748 * uint32 terminal width, characters
749 * (e.g., 80)
750 * uint32 terminal height, rows (e.g., 24)
751 * uint32 terminal width, px (e.g., 640)
752 * uint32 terminal height, px (e.g., 480)
753 * string encoded terminal modes
754 */
755 state_get_u32(pss, SSHS_NVC_CHRQ_RECIP);
756 break;
757
758 case SSH_MSG_CHANNEL_EOF:
759 /* RFC4254
760 * When a party will no longer send more data
761 * to a channel, it SHOULD send
762 * SSH_MSG_CHANNEL_EOF.
763 *
764 * byte SSH_MSG_CHANNEL_EOF
765 * uint32 recipient channel
766 */
767 state_get_u32(pss, SSHS_NVC_CH_EOF);
768 break;
769
770 case SSH_MSG_CHANNEL_CLOSE:
771 /* RFC4254
772 *
773 * byte SSH_MSG_CHANNEL_CLOSE
774 * uint32 recipient channel
775 *
776 * This message does not consume window space
777 * and can be sent even if no window space is
778 * available.
779 *
780 * It is RECOMMENDED that all data sent before
781 * this message be delivered to the actual
782 * destination, if possible.
783 */
784 state_get_u32(pss, SSHS_NVC_CH_CLOSE);
785 break;
786
787 case SSH_MSG_CHANNEL_DATA:
788 /* RFC4254
789 *
790 * byte SSH_MSG_CHANNEL_DATA
791 * uint32 recipient channel
792 * string data
793 */
794 state_get_u32(pss, SSHS_NVC_CD_RECIP);
795 break;
796
797 case SSH_MSG_CHANNEL_WINDOW_ADJUST:
798 /* RFC452
799 *
800 * byte SSH_MSG_CHANNEL_WINDOW_ADJUST
801 * uint32 recipient channel
802 * uint32 bytes to add
803 */
804 if (!pss->ch_list)
805 goto bail;
806
807 state_get_u32(pss, SSHS_NVC_WA_RECIP);
808 break;
809 default:
810 lwsl_notice("unk msg_id %d\n", pss->msg_id);
811
812 goto bail;
813 }
814 break;
815
816 case SSH_KEX_STATE_COOKIE:
817 if (pss->msg_len < 16 + 1 + 1 + (10 * 4) + 5) {
818 lwsl_notice("sanity: kex length failed\n");
819 goto bail;
820 }
821 pss->kex->kex_cookie[pss->ctr++] = *p++;
822 if (pss->ctr != sizeof(pss->kex->kex_cookie))
823 break;
824 pss->parser_state = SSH_KEX_NL_KEX_ALGS_LEN;
825 pss->ctr = 0;
826 break;
827 case SSH_KEX_NL_KEX_ALGS_LEN:
828 case SSH_KEX_NL_SHK_ALGS_LEN:
829 case SSH_KEX_NL_EACTS_ALGS_LEN:
830 case SSH_KEX_NL_EASTC_ALGS_LEN:
831 case SSH_KEX_NL_MACTS_ALGS_LEN:
832 case SSH_KEX_NL_MASTC_ALGS_LEN:
833 case SSH_KEX_NL_CACTS_ALGS_LEN:
834 case SSH_KEX_NL_CASTC_ALGS_LEN:
835 case SSH_KEX_NL_LCTS_ALGS_LEN:
836 case SSH_KEX_NL_LSTC_ALGS_LEN:
837 case SSH_KEX_STATE_ECDH_KEYLEN:
838
839 pss->len = (pss->len << 8) | *p++;
840 if (++pss->ctr != 4)
841 break;
842
843 switch (pss->parser_state) {
844 case SSH_KEX_STATE_ECDH_KEYLEN:
845 pss->parser_state = SSH_KEX_STATE_ECDH_Q_C;
846 break;
847 default:
848 pss->parser_state++;
849 if (pss->len == 0)
850 pss->parser_state++;
851 break;
852 }
853 pss->ctr = 0;
854 pss->npos = 0;
855 if (pss->msg_len - pss->pos < pss->len) {
856 lwsl_notice("sanity: length %d - %d < %d\n",
857 pss->msg_len, pss->pos, pss->len);
858 goto bail;
859 }
860 break;
861
862 case SSH_KEX_NL_KEX_ALGS:
863 case SSH_KEX_NL_SHK_ALGS:
864 case SSH_KEX_NL_EACTS_ALGS:
865 case SSH_KEX_NL_EASTC_ALGS:
866 case SSH_KEX_NL_MACTS_ALGS:
867 case SSH_KEX_NL_MASTC_ALGS:
868 case SSH_KEX_NL_CACTS_ALGS:
869 case SSH_KEX_NL_CASTC_ALGS:
870 case SSH_KEX_NL_LCTS_ALGS:
871 case SSH_KEX_NL_LSTC_ALGS:
872 if (*p != ',') {
873 if (pss->npos < sizeof(pss->name) - 1)
874 pss->name[pss->npos++] = (char)*p;
875 } else {
876 pss->name[pss->npos] = '\0';
877 pss->npos = 0;
878 handle_name(pss);
879 }
880 p++;
881 if (!--pss->len) {
882 pss->name[pss->npos] = '\0';
883 if (pss->npos)
884 handle_name(pss);
885 pss->parser_state++;
886 break;
887 }
888 break;
889
890 case SSH_KEX_FIRST_PKT:
891 pss->first_coming = !!*p++;
892 pss->parser_state = SSH_KEX_RESERVED;
893 break;
894
895 case SSH_KEX_RESERVED:
896 pss->len = (pss->len << 8) | *p++;
897 if (++pss->ctr != 4)
898 break;
899 pss->ctr = 0;
900 if (pss->msg_padding) {
901 pss->copy_to_I_C = 0;
902 pss->parser_state = SSHS_MSG_EAT_PADDING;
903 break;
904 }
905 pss->parser_state = SSHS_MSG_LEN;
906 break;
907
908 case SSH_KEX_STATE_ECDH_Q_C:
909 if (pss->len != 32) {
910 lwsl_notice("wrong key len\n");
911 goto bail;
912 }
913 pss->kex->Q_C[pss->ctr++] = *p++;
914 if (pss->ctr != 32)
915 break;
916 lwsl_info("Q_C parsed\n");
917 pss->parser_state = SSHS_MSG_EAT_PADDING;
918 break;
919
920 case SSH_KEX_STATE_SKIP:
921 if (pss->pos - 4 < pss->msg_len) {
922 p++;
923 break;
924 }
925 lwsl_debug("skip done pos %d, msg_len %d len=%ld, \n",
926 pss->pos, pss->msg_len, (long)len);
927 pss->parser_state = SSHS_MSG_LEN;
928 pss->ctr = 0;
929 break;
930
931 case SSHS_MSG_EAT_PADDING:
932 p++;
933 if (--pss->msg_padding)
934 break;
935 if (pss->msg_len + 4 != pss->pos) {
936 lwsl_notice("sanity: kex end mismatch %d %d\n",
937 pss->pos, pss->msg_len);
938 goto bail;
939 }
940
941 switch (pss->msg_id) {
942 case SSH_MSG_KEX_ECDH_INIT:
943 if (pss->kex->match_bitfield != 0xff) {
944 lwsl_notice("unable to negotiate\n");
945 goto bail;
946 }
947 if (kex_ecdh(pss, pss->kex->kex_r,
948 &pss->kex->kex_r_len)) {
949 lwsl_notice("hex_ecdh failed\n");
950 goto bail;
951 }
952 write_task(pss, NULL, SSH_WT_OFFER_REPLY);
953 break;
954 }
955
956 pss->parser_state = SSHS_MSG_LEN;
957 pss->ctr = 0;
958 break;
959
960 case SSHS_GET_STRING_LEN:
961 pss->npos = 0;
962 pss->len = (pss->len << 8) | *p++;
963 if (++pss->ctr != 4)
964 break;
965 pss->ctr = 0;
966 pss->parser_state = SSHS_GET_STRING;
967 break;
968
969 case SSHS_GET_STRING:
970 if (pss->npos >= sizeof(pss->name) - 1) {
971 lwsl_notice("non-alloc string too big\n");
972 goto bail;
973 }
974 pss->name[pss->npos++] = (char)*p++;
975 if (pss->npos != pss->len)
976 break;
977
978 pss->name[pss->npos] = '\0';
979 pss->parser_state = pss->state_after_string;
980 goto again;
981
982 case SSHS_GET_STRING_LEN_ALLOC:
983 pss->npos = 0;
984 pss->len = (pss->len << 8) | *p++;
985 if (++pss->ctr != 4)
986 break;
987 pss->ctr = 0;
988 pss->last_alloc = sshd_zalloc(pss->len + 1);
989 lwsl_debug("SSHS_GET_STRING_LEN_ALLOC: %p, state %d\n",
990 pss->last_alloc, pss->state_after_string);
991 if (!pss->last_alloc) {
992 lwsl_notice("alloc string too big\n");
993 goto bail;
994 }
995 pss->parser_state = SSHS_GET_STRING_ALLOC;
996 break;
997
998 case SSHS_GET_STRING_ALLOC:
999 if (pss->npos >= pss->len)
1000 goto bail;
1001 pss->last_alloc[pss->npos++] = *p++;
1002 if (pss->npos != pss->len)
1003 break;
1004 pss->last_alloc[pss->npos] = '\0';
1005 pss->parser_state = pss->state_after_string;
1006 goto again;
1007
1008 /*
1009 * User Authentication
1010 */
1011
1012 case SSHS_DO_SERVICE_REQUEST:
1013 pss->okayed_userauth = 1;
1014 pss->parser_state = SSHS_MSG_EAT_PADDING;
1015 /*
1016 * this only 'accepts' that we can negotiate auth for
1017 * this service, not accepts the auth
1018 */
1019 write_task(pss, NULL, SSH_WT_UA_ACCEPT);
1020 break;
1021
1022 case SSHS_DO_UAR_SVC:
1023 pss->ua->username = (char *)pss->last_alloc;
1024 pss->last_alloc = NULL; /* it was adopted */
1025 state_get_string_alloc(pss, SSHS_DO_UAR_PUBLICKEY);
1026 /* destroyed with UA struct */
1027 break;
1028
1029 case SSHS_DO_UAR_PUBLICKEY:
1030 pss->ua->service = (char *)pss->last_alloc;
1031 pss->last_alloc = NULL; /* it was adopted */
1032
1033 /* Sect 5, RFC4252
1034 *
1035 * The 'user name' and 'service name' are repeated in
1036 * every new authentication attempt, and MAY change.
1037 *
1038 * The server implementation MUST carefully check them
1039 * in every message, and MUST flush any accumulated
1040 * authentication states if they change. If it is
1041 * unable to flush an authentication state, it MUST
1042 * disconnect if the 'user name' or 'service name'
1043 * changes.
1044 */
1045
1046 if (pss->seen_auth_req_before && (
1047 strcmp(pss->ua->username,
1048 pss->last_auth_req_username) ||
1049 strcmp(pss->ua->service,
1050 pss->last_auth_req_service))) {
1051 lwsl_notice("username / svc changed\n");
1052
1053 goto bail;
1054 }
1055
1056 pss->seen_auth_req_before = 1;
1057 lws_strncpy(pss->last_auth_req_username,
1058 pss->ua->username,
1059 sizeof(pss->last_auth_req_username));
1060 lws_strncpy(pss->last_auth_req_service,
1061 pss->ua->service,
1062 sizeof(pss->last_auth_req_service));
1063
1064 if (strcmp(pss->ua->service, "ssh-connection"))
1065 goto ua_fail;
1066 state_get_string(pss, SSHS_NVC_DO_UAR_CHECK_PUBLICKEY);
1067 break;
1068
1069 case SSHS_NVC_DO_UAR_CHECK_PUBLICKEY:
1070 if (!strcmp(pss->name, "none")) {
1071 /* we must fail it */
1072 lwsl_info("got 'none' req, refusing\n");
1073 goto ua_fail;
1074 }
1075
1076 if (strcmp(pss->name, "publickey")) {
1077 lwsl_notice("expected 'publickey' got '%s'\n",
1078 pss->name);
1079 goto ua_fail;
1080 }
1081 pss->parser_state = SSHS_DO_UAR_SIG_PRESENT;
1082 break;
1083
1084 case SSHS_DO_UAR_SIG_PRESENT:
1085 lwsl_info("SSHS_DO_UAR_SIG_PRESENT\n");
1086 pss->ua->sig_present = (char)*p++;
1087 state_get_string_alloc(pss, SSHS_NVC_DO_UAR_ALG);
1088 /* destroyed with UA struct */
1089 break;
1090
1091 case SSHS_NVC_DO_UAR_ALG:
1092 pss->ua->alg = (char *)pss->last_alloc;
1093 pss->last_alloc = NULL; /* it was adopted */
1094 if (rsa_hash_alg_from_ident(pss->ua->alg) < 0) {
1095 lwsl_notice("unknown alg\n");
1096 goto ua_fail;
1097 }
1098 state_get_string_alloc(pss, SSHS_NVC_DO_UAR_PUBKEY_BLOB);
1099 /* destroyed with UA struct */
1100 break;
1101
1102 case SSHS_NVC_DO_UAR_PUBKEY_BLOB:
1103 pss->ua->pubkey = pss->last_alloc;
1104 pss->last_alloc = NULL; /* it was adopted */
1105 pss->ua->pubkey_len = pss->npos;
1106 /*
1107 * RFC4253
1108 *
1109 * ssh-rsa
1110 *
1111 * The structure inside the blob is
1112 *
1113 * mpint e
1114 * mpint n
1115 *
1116 * Let's see if this key is authorized
1117 */
1118
1119 n = 1;
1120 if (pss->vhd->ops && pss->vhd->ops->is_pubkey_authorized)
1121 n = pss->vhd->ops->is_pubkey_authorized(
1122 pss->ua->username, pss->ua->alg,
1123 pss->ua->pubkey, (int)pss->ua->pubkey_len);
1124 if (n) {
1125 lwsl_info("rejecting peer pubkey\n");
1126 goto ua_fail;
1127 }
1128
1129 if (pss->ua->sig_present) {
1130 state_get_string_alloc(pss, SSHS_NVC_DO_UAR_SIG);
1131 /* destroyed with UA struct */
1132 break;
1133 }
1134
1135 /*
1136 * This key is at least one we would be prepared
1137 * to accept if he really has it... since no sig
1138 * client should resend everything with a sig
1139 * appended. OK it and delete this initial UA
1140 */
1141 write_task(pss, NULL, SSH_WT_UA_PK_OK);
1142 pss->parser_state = SSHS_MSG_EAT_PADDING;
1143 break;
1144
1145 case SSHS_NVC_DO_UAR_SIG:
1146 /*
1147 * Now the pubkey is coming with a sig
1148 */
1149 /* Sect 5.1 RFC4252
1150 *
1151 * SSH_MSG_USERAUTH_SUCCESS MUST be sent only once.
1152 * When SSH_MSG_USERAUTH_SUCCESS has been sent, any
1153 * further authentication requests received after that
1154 * SHOULD be silently ignored.
1155 */
1156 if (pss->ssh_auth_state == SSH_AUTH_STATE_GAVE_AUTH_IGNORE_REQS) {
1157 lwsl_info("Silently ignoring auth req after accepted\n");
1158 goto ua_fail_silently;
1159 }
1160 lwsl_info("SSHS_DO_UAR_SIG\n");
1161 pss->ua->sig = pss->last_alloc;
1162 pss->last_alloc = NULL; /* it was adopted */
1163 pss->ua->sig_len = pss->npos;
1164 pss->parser_state = SSHS_MSG_EAT_PADDING;
1165
1166 /*
1167 * RFC 4252 p9
1168 *
1169 * The value of 'signature' is a signature with
1170 * the private host key of the following data, in
1171 * this order:
1172 *
1173 * string session identifier
1174 * byte SSH_MSG_USERAUTH_REQUEST
1175 * string user name
1176 * string service name
1177 * string "publickey"
1178 * boolean TRUE
1179 * string public key algorithm name
1180 * string public key to be used for auth
1181 *
1182 * We reproduce the signature plaintext and the
1183 * hash, and then decrypt the incoming signed block.
1184 * What comes out is some ASN1, in there is the
1185 * hash decrypted. We find it and confirm it
1186 * matches the hash we computed ourselves.
1187 *
1188 * First step is generate the sig plaintext
1189 */
1190 n = 4 + 32 +
1191 1 +
1192 4 + (int)strlen(pss->ua->username) +
1193 4 + (int)strlen(pss->ua->service) +
1194 4 + 9 +
1195 1 +
1196 4 + (int)strlen(pss->ua->alg) +
1197 4 + (int)pss->ua->pubkey_len;
1198
1199 ps = sshd_zalloc((unsigned int)n);
1200 if (!ps) {
1201 lwsl_notice("OOM 4\n");
1202 goto ua_fail;
1203 }
1204
1205 pp = ps;
1206 lws_buf(&pp, pss->session_id, 32);
1207 *pp++ = SSH_MSG_USERAUTH_REQUEST;
1208 lws_cstr(&pp, pss->ua->username, 64);
1209 lws_cstr(&pp, pss->ua->service, 64);
1210 lws_cstr(&pp, "publickey", 64);
1211 *pp++ = 1;
1212 lws_cstr(&pp, pss->ua->alg, 64);
1213 lws_buf(&pp, pss->ua->pubkey, pss->ua->pubkey_len);
1214
1215 /* Next hash the plaintext */
1216
1217 if (lws_genhash_init(&pss->ua->hash_ctx,
1218 (enum lws_genhash_types)rsa_hash_alg_from_ident(pss->ua->alg))) {
1219 lwsl_notice("genhash init failed\n");
1220 free(ps);
1221 goto ua_fail;
1222 }
1223
1224 if (lws_genhash_update(&pss->ua->hash_ctx, ps, lws_ptr_diff_size_t(pp, ps))) {
1225 lwsl_notice("genhash update failed\n");
1226 free(ps);
1227 goto ua_fail;
1228 }
1229 lws_genhash_destroy(&pss->ua->hash_ctx, hash);
1230 free(ps);
1231
1232 /*
1233 * Prepare the RSA decryption context: load in
1234 * the E and N factors
1235 */
1236
1237 memset(e, 0, sizeof(e));
1238 pp = pss->ua->pubkey;
1239 m = lws_g32(&pp);
1240 pp += m;
1241 m = lws_g32(&pp);
1242 e[LWS_GENCRYPTO_RSA_KEYEL_E].buf = pp;
1243 e[LWS_GENCRYPTO_RSA_KEYEL_E].len = m;
1244 pp += m;
1245 m = lws_g32(&pp);
1246 e[LWS_GENCRYPTO_RSA_KEYEL_N].buf = pp;
1247 e[LWS_GENCRYPTO_RSA_KEYEL_N].len = m;
1248
1249 if (lws_genrsa_create(&ctx, e, pss->vhd->context,
1250 LGRSAM_PKCS1_1_5,
1251 LWS_GENHASH_TYPE_UNKNOWN))
1252 goto ua_fail;
1253 /*
1254 * point to the encrypted signature payload we
1255 * were sent
1256 */
1257 pp = pss->ua->sig;
1258 m = lws_g32(&pp);
1259 pp += m;
1260 m = lws_g32(&pp);
1261 #if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
1262
1263 /*
1264 * decrypt it, resulting in an error, or some ASN1
1265 * including the decrypted signature
1266 */
1267 otmp = sshd_zalloc(m);
1268 if (!otmp)
1269 /* ua_fail1 frees bn_e, bn_n and rsa */
1270 goto ua_fail1;
1271
1272 n = lws_genrsa_public_decrypt(&ctx, pp, m, otmp, m);
1273 if (n > 0) {
1274 /* the decrypted sig is in ASN1 format */
1275 m = 0;
1276 while ((int)m < n) {
1277 /* sig payload */
1278 if (otmp[m] == 0x04 &&
1279 otmp[m + 1] == lws_genhash_size(
1280 pss->ua->hash_ctx.type)) {
1281 m = (uint32_t)memcmp(&otmp[m + 2], hash,
1282 (unsigned int)lws_genhash_size(pss->ua->hash_ctx.type));
1283 break;
1284 }
1285 /* go into these */
1286 if (otmp[m] == 0x30) {
1287 m += 2;
1288 continue;
1289 }
1290 /* otherwise skip payloads */
1291 m += (uint32_t)(otmp[m + 1] + 2);
1292 }
1293 }
1294
1295 free(otmp);
1296 #else
1297 ctx.ctx->MBEDTLS_PRIVATE(len) = m;
1298 n = lws_genrsa_hash_sig_verify(&ctx, hash,
1299 (enum lws_genhash_types)rsa_hash_alg_from_ident(pss->ua->alg),
1300 pp, m) == 0 ? 1 : 0;
1301 #endif
1302 lws_genrsa_destroy(&ctx);
1303
1304 /*
1305 * if no good, m is nonzero and inform peer
1306 */
1307 if (n <= 0) {
1308 lwsl_notice("hash sig verify fail: %d\n", m);
1309 goto ua_fail;
1310 }
1311
1312 /* if it checks out, inform peer */
1313
1314 lwsl_info("sig check OK\n");
1315
1316 /* Sect 5.1 RFC4252
1317 *
1318 * SSH_MSG_USERAUTH_SUCCESS MUST be sent only once.
1319 * When SSH_MSG_USERAUTH_SUCCESS has been sent, any
1320 * further authentication requests received after that
1321 * SHOULD be silently ignored.
1322 */
1323 pss->ssh_auth_state = SSH_AUTH_STATE_GAVE_AUTH_IGNORE_REQS;
1324
1325 write_task(pss, NULL, SSH_WT_UA_SUCCESS);
1326 lws_ua_destroy(pss);
1327 break;
1328
1329 /*
1330 * Channels
1331 */
1332
1333 case SSHS_GET_U32:
1334 pss->len = (pss->len << 8) | *p++;
1335 if (++pss->ctr != 4)
1336 break;
1337 pss->ctr = 0;
1338 pss->parser_state = pss->state_after_string;
1339 goto again;
1340
1341 /*
1342 * Channel: Disconnect
1343 */
1344
1345 case SSHS_NVC_DISCONNECT_REASON:
1346 pss->disconnect_reason = pss->len;
1347 state_get_string_alloc(pss, SSHS_NVC_DISCONNECT_DESC);
1348 break;
1349
1350 case SSHS_NVC_DISCONNECT_DESC:
1351 pss->disconnect_desc = (char *)pss->last_alloc;
1352 pss->last_alloc = NULL; /* it was adopted */
1353 state_get_string(pss, SSHS_NVC_DISCONNECT_LANG);
1354 break;
1355
1356 case SSHS_NVC_DISCONNECT_LANG:
1357 lwsl_notice("SSHS_NVC_DISCONNECT_LANG\n");
1358 if (pss->vhd->ops && pss->vhd->ops->disconnect_reason)
1359 pss->vhd->ops->disconnect_reason(
1360 pss->disconnect_reason,
1361 pss->disconnect_desc, pss->name);
1362 ssh_free_set_NULL(pss->last_alloc);
1363 break;
1364
1365 /*
1366 * Channel: Open
1367 */
1368
1369 case SSHS_NVC_CHOPEN_TYPE:
1370 /* channel open */
1371 if (strcmp(pss->name, "session")) {
1372 lwsl_notice("Failing on not session\n");
1373 pss->reason = 3;
1374 goto ch_fail;
1375 }
1376 lwsl_info("SSHS_NVC_CHOPEN_TYPE: creating session\n");
1377 pss->ch_temp = sshd_zalloc(sizeof(*pss->ch_temp));
1378 if (!pss->ch_temp)
1379 return -1;
1380
1381 pss->ch_temp->type = SSH_CH_TYPE_SESSION;
1382 pss->ch_temp->pss = pss;
1383 state_get_u32(pss, SSHS_NVC_CHOPEN_SENDER_CH);
1384 break;
1385
1386 case SSHS_NVC_CHOPEN_SENDER_CH:
1387 pss->ch_temp->sender_ch = pss->len;
1388 state_get_u32(pss, SSHS_NVC_CHOPEN_WINSIZE);
1389 break;
1390 case SSHS_NVC_CHOPEN_WINSIZE:
1391 lwsl_info("Initial window set to %d\n", pss->len);
1392 pss->ch_temp->window = (int32_t)pss->len;
1393 state_get_u32(pss, SSHS_NVC_CHOPEN_PKTSIZE);
1394 break;
1395 case SSHS_NVC_CHOPEN_PKTSIZE:
1396 pss->ch_temp->max_pkt = pss->len;
1397 pss->ch_temp->peer_window_est = LWS_SSH_INITIAL_WINDOW;
1398 pss->ch_temp->server_ch = (uint32_t)pss->next_ch_num++;
1399 /*
1400 * add us to channel list... leave as ch_temp
1401 * as write task needs it and will NULL down
1402 */
1403 lwsl_info("creating new session ch\n");
1404 pss->ch_temp->next = pss->ch_list;
1405 pss->ch_list = pss->ch_temp;
1406 if (pss->vhd->ops && pss->vhd->ops->channel_create)
1407 pss->vhd->ops->channel_create(pss->wsi,
1408 &pss->ch_temp->priv);
1409 write_task(pss, pss->ch_temp, SSH_WT_CH_OPEN_CONF);
1410 pss->parser_state = SSHS_MSG_EAT_PADDING;
1411 break;
1412
1413 /*
1414 * SSH_MSG_CHANNEL_REQUEST
1415 */
1416
1417 case SSHS_NVC_CHRQ_RECIP:
1418 pss->ch_recip = pss->len;
1419 state_get_string(pss, SSHS_NVC_CHRQ_TYPE);
1420 break;
1421
1422 case SSHS_NVC_CHRQ_TYPE:
1423 pss->parser_state = SSHS_CHRQ_WANT_REPLY;
1424 break;
1425
1426 case SSHS_CHRQ_WANT_REPLY:
1427 pss->rq_want_reply = *p++;
1428 lwsl_info("SSHS_CHRQ_WANT_REPLY: %s, wantrep: %d\n",
1429 pss->name, pss->rq_want_reply);
1430
1431 pss->ch_temp = ssh_get_server_ch(pss, pss->ch_recip);
1432
1433 /* after this they differ by the request */
1434
1435 /*
1436 * a PTY for a shell
1437 */
1438 if (!strcmp(pss->name, "pty-req")) {
1439 state_get_string(pss, SSHS_NVC_CHRQ_TERM);
1440 break;
1441 }
1442 /*
1443 * a shell
1444 */
1445 if (!strcmp(pss->name, "shell")) {
1446 pss->channel_doing_spawn = pss->ch_temp->server_ch;
1447 if (pss->vhd->ops && pss->vhd->ops->shell &&
1448 !pss->vhd->ops->shell(pss->ch_temp->priv,
1449 pss->wsi,
1450 lws_ssh_exec_finish, pss->ch_temp)) {
1451
1452 if (pss->rq_want_reply)
1453 write_task_insert(pss, pss->ch_temp,
1454 SSH_WT_CHRQ_SUCC);
1455 pss->parser_state = SSHS_MSG_EAT_PADDING;
1456 break;
1457 }
1458
1459 goto chrq_fail;
1460 }
1461 /*
1462 * env vars to be set in the shell
1463 */
1464 if (!strcmp(pss->name, "env")) {
1465 state_get_string(pss, SSHS_NVC_CHRQ_ENV_NAME);
1466 break;
1467 }
1468
1469 /*
1470 * exec something
1471 */
1472 if (!strcmp(pss->name, "exec")) {
1473 state_get_string_alloc(pss, SSHS_NVC_CHRQ_EXEC_CMD);
1474 break;
1475 }
1476
1477 /*
1478 * spawn a subsystem
1479 */
1480 if (!strcmp(pss->name, "subsystem")) {
1481 lwsl_notice("subsystem\n");
1482 state_get_string_alloc(pss,
1483 SSHS_NVC_CHRQ_SUBSYSTEM);
1484 break;
1485 }
1486 if (!strcmp(pss->name, "window-change")) {
1487 lwsl_info("%s: window-change\n", __func__);
1488 state_get_u32(pss,
1489 SSHS_NVC_CHRQ_WNDCHANGE_TW);
1490 break;
1491 }
1492
1493 if (pss->rq_want_reply)
1494 goto chrq_fail;
1495
1496 pss->parser_state = SSH_KEX_STATE_SKIP;
1497 break;
1498
1499 /* CHRQ pty-req */
1500
1501 case SSHS_NVC_CHRQ_TERM:
1502 memcpy(pss->args.pty.term, pss->name,
1503 sizeof(pss->args.pty.term) - 1);
1504 state_get_u32(pss, SSHS_NVC_CHRQ_TW);
1505 break;
1506 case SSHS_NVC_CHRQ_TW:
1507 pss->args.pty.width_ch = pss->len;
1508 state_get_u32(pss, SSHS_NVC_CHRQ_TH);
1509 break;
1510 case SSHS_NVC_CHRQ_TH:
1511 pss->args.pty.height_ch = pss->len;
1512 state_get_u32(pss, SSHS_NVC_CHRQ_TWP);
1513 break;
1514 case SSHS_NVC_CHRQ_TWP:
1515 pss->args.pty.width_px = pss->len;
1516 state_get_u32(pss, SSHS_NVC_CHRQ_THP);
1517 break;
1518 case SSHS_NVC_CHRQ_THP:
1519 pss->args.pty.height_px = pss->len;
1520 state_get_string_alloc(pss, SSHS_NVC_CHRQ_MODES);
1521 break;
1522 case SSHS_NVC_CHRQ_MODES:
1523 /* modes is a stream of byte-pairs, not a string */
1524 pss->args.pty.modes = (char *)pss->last_alloc;
1525 pss->last_alloc = NULL; /* it was adopted */
1526 pss->args.pty.modes_len = pss->npos;
1527 n = 0;
1528 if (pss->vhd->ops && pss->vhd->ops->pty_req)
1529 n = pss->vhd->ops->pty_req(pss->ch_temp->priv,
1530 &pss->args.pty);
1531 ssh_free_set_NULL(pss->args.pty.modes);
1532 if (n)
1533 goto chrq_fail;
1534 if (pss->rq_want_reply)
1535 write_task(pss, pss->ch_temp, SSH_WT_CHRQ_SUCC);
1536 pss->parser_state = SSHS_MSG_EAT_PADDING;
1537 break;
1538
1539 /* CHRQ env */
1540
1541 case SSHS_NVC_CHRQ_ENV_NAME:
1542 strcpy(pss->args.aux, pss->name);
1543 state_get_string(pss, SSHS_NVC_CHRQ_ENV_VALUE);
1544 break;
1545
1546 case SSHS_NVC_CHRQ_ENV_VALUE:
1547 if (pss->vhd->ops && pss->vhd->ops->set_env)
1548 if (pss->vhd->ops->set_env(pss->ch_temp->priv,
1549 pss->args.aux, pss->name))
1550 goto chrq_fail;
1551 pss->parser_state = SSHS_MSG_EAT_PADDING;
1552 break;
1553
1554 /* CHRQ exec */
1555
1556 case SSHS_NVC_CHRQ_EXEC_CMD:
1557 /*
1558 * byte SSH_MSG_CHANNEL_REQUEST
1559 * uint32 recipient channel
1560 * string "exec"
1561 * boolean want reply
1562 * string command
1563 *
1564 * This message will request that the server start the
1565 * execution of the given command. The 'command' string
1566 * may contain a path. Normal precautions MUST be taken
1567 * to prevent the execution of unauthorized commands.
1568 *
1569 * scp sends "scp -t /path/..."
1570 */
1571 lwsl_info("exec cmd: %s %02X\n", pss->last_alloc, *p);
1572
1573 pss->channel_doing_spawn = pss->ch_temp->server_ch;
1574
1575 if (pss->vhd->ops && pss->vhd->ops->exec &&
1576 !pss->vhd->ops->exec(pss->ch_temp->priv, pss->wsi,
1577 (const char *)pss->last_alloc,
1578 lws_ssh_exec_finish, pss->ch_temp)) {
1579 ssh_free_set_NULL(pss->last_alloc);
1580 if (pss->rq_want_reply)
1581 write_task_insert(pss, pss->ch_temp,
1582 SSH_WT_CHRQ_SUCC);
1583
1584 pss->parser_state = SSHS_MSG_EAT_PADDING;
1585 break;
1586 }
1587
1588 /*
1589 * even if he doesn't want to exec it, we know how to
1590 * fake scp
1591 */
1592
1593 /* we only alloc "exec" of scp for scp destination */
1594 n = 1;
1595 if (pss->last_alloc[0] != 's' ||
1596 pss->last_alloc[1] != 'c' ||
1597 pss->last_alloc[2] != 'p' ||
1598 pss->last_alloc[3] != ' ')
1599 /* disallow it */
1600 n = 0;
1601
1602 ssh_free_set_NULL(pss->last_alloc);
1603 if (!n)
1604 goto chrq_fail;
1605
1606 /* our channel speaks SCP protocol now */
1607
1608 scp = sshd_zalloc(sizeof(*scp));
1609 if (!scp)
1610 return -1;
1611
1612 pss->ch_temp->type = SSH_CH_TYPE_SCP;
1613 pss->ch_temp->sub = (lws_subprotocol *)scp;
1614
1615 scp->ips = SSHS_SCP_COLLECTSTR;
1616
1617 if (pss->rq_want_reply)
1618 write_task(pss, pss->ch_temp, SSH_WT_CHRQ_SUCC);
1619
1620 /* we start the scp protocol first by sending an ACK */
1621 write_task(pss, pss->ch_temp, SSH_WT_SCP_ACK_OKAY);
1622
1623 pss->parser_state = SSHS_MSG_EAT_PADDING;
1624 break;
1625
1626 case SSHS_NVC_CHRQ_SUBSYSTEM:
1627 lwsl_notice("subsystem: %s", pss->last_alloc);
1628 n = 0;
1629 #if 0
1630 if (!strcmp(pss->name, "sftp")) {
1631 lwsl_notice("SFTP session\n");
1632 pss->ch_temp->type = SSH_CH_TYPE_SFTP;
1633 n = 1;
1634 }
1635 #endif
1636 ssh_free_set_NULL(pss->last_alloc);
1637 // if (!n)
1638 goto ch_fail;
1639 #if 0
1640 if (pss->rq_want_reply)
1641 write_task(pss, ssh_get_server_ch(pss,
1642 pss->ch_recip), SSH_WT_CHRQ_SUCC);
1643 pss->parser_state = SSHS_MSG_EAT_PADDING;
1644 break;
1645 #endif
1646
1647 /* CHRQ window-change */
1648
1649 case SSHS_NVC_CHRQ_WNDCHANGE_TW:
1650 pss->args.pty.width_ch = pss->len;
1651 state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TH);
1652 break;
1653 case SSHS_NVC_CHRQ_WNDCHANGE_TH:
1654 pss->args.pty.height_ch = pss->len;
1655 state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_TWP);
1656 break;
1657 case SSHS_NVC_CHRQ_WNDCHANGE_TWP:
1658 pss->args.pty.width_px = pss->len;
1659 state_get_u32(pss, SSHS_NVC_CHRQ_WNDCHANGE_THP);
1660 break;
1661 case SSHS_NVC_CHRQ_WNDCHANGE_THP:
1662 pss->args.pty.height_px = pss->len;
1663 pss->args.pty.term[0] = 0;
1664 pss->args.pty.modes = NULL;
1665 pss->args.pty.modes_len = 0;
1666 n = 0;
1667 if (pss->vhd->ops && pss->vhd->ops->pty_req)
1668 n = pss->vhd->ops->pty_req(pss->ch_temp->priv,
1669 &pss->args.pty);
1670 if (n)
1671 goto chrq_fail;
1672 pss->parser_state = SSHS_MSG_EAT_PADDING;
1673 break;
1674
1675 /* SSH_MSG_CHANNEL_DATA */
1676
1677 case SSHS_NVC_CD_RECIP:
1678 pss->ch_recip = pss->len;
1679
1680 ch = ssh_get_server_ch(pss, pss->ch_recip);
1681 ch->peer_window_est -= (int32_t)pss->msg_len;
1682
1683 if (pss->msg_len < sizeof(pss->name))
1684 state_get_string(pss, SSHS_NVC_CD_DATA);
1685 else
1686 state_get_string_alloc(pss,
1687 SSHS_NVC_CD_DATA_ALLOC);
1688 break;
1689
1690 case SSHS_NVC_CD_DATA_ALLOC:
1691 case SSHS_NVC_CD_DATA:
1692 /*
1693 * Actual protocol incoming payload
1694 */
1695 if (pss->parser_state == SSHS_NVC_CD_DATA_ALLOC)
1696 pp = pss->last_alloc;
1697 else
1698 pp = (uint8_t *)pss->name;
1699 lwsl_info("SSHS_NVC_CD_DATA\n");
1700
1701 ch = ssh_get_server_ch(pss, pss->ch_recip);
1702 switch (ch->type) {
1703 case SSH_CH_TYPE_SCP:
1704 scp = &ch->sub->scp;
1705 switch (scp->ips) {
1706 case SSHS_SCP_COLLECTSTR:
1707 /* gather the ascii-coded headers */
1708 for (n = 0; n < (int)pss->npos; n++)
1709 lwsl_notice("0x%02X %c\n",
1710 pp[n], pp[n]);
1711
1712 /* Header triggers the transfer? */
1713 if (pp[0] == 'C' && pp[pss->npos - 1] == '\x0a') {
1714 while (*pp != ' ' && *pp != '\x0a')
1715 pp++;
1716 if (*pp++ != ' ') {
1717 write_task(pss, ch,
1718 SSH_WT_SCP_ACK_ERROR);
1719 pss->parser_state = SSHS_MSG_EAT_PADDING;
1720 break;
1721 }
1722 scp->len = (uint64_t)atoll((const char *)pp);
1723 lwsl_notice("scp payload %llu expected\n",
1724 (unsigned long long)scp->len);
1725 scp->ips = SSHS_SCP_PAYLOADIN;
1726 }
1727 /* ack it */
1728 write_task(pss, pss->ch_temp,
1729 SSH_WT_SCP_ACK_OKAY);
1730 break;
1731 case SSHS_SCP_PAYLOADIN:
1732 /* the scp file payload */
1733 if (pss->vhd->ops)
1734 pss->vhd->ops->rx(ch->priv,
1735 pss->wsi, pp, pss->npos);
1736 if (scp->len >= pss->npos)
1737 scp->len -= pss->npos;
1738 else
1739 scp->len = 0;
1740 if (!scp->len) {
1741 lwsl_notice("scp txfer completed\n");
1742 scp->ips = SSHS_SCP_COLLECTSTR;
1743 break;
1744 }
1745 break;
1746 }
1747 break;
1748 default: /* scp payload */
1749 if (pss->vhd->ops)
1750 pss->vhd->ops->rx(ch->priv, pss->wsi,
1751 pp, pss->npos);
1752 break;
1753 }
1754 if (pss->parser_state == SSHS_NVC_CD_DATA_ALLOC)
1755 ssh_free_set_NULL(pss->last_alloc);
1756
1757 if (ch->peer_window_est < 32768) {
1758 write_task(pss, ch, SSH_WT_WINDOW_ADJUST);
1759 ch->peer_window_est += 32768;
1760 lwsl_info("extra peer WINDOW_ADJUST (~ %d)\n",
1761 ch->peer_window_est);
1762 }
1763
1764 pss->parser_state = SSHS_MSG_EAT_PADDING;
1765 break;
1766
1767 case SSHS_NVC_WA_RECIP:
1768 pss->ch_recip = pss->len;
1769 state_get_u32(pss, SSHS_NVC_WA_ADD);
1770 break;
1771
1772 case SSHS_NVC_WA_ADD:
1773 ch = ssh_get_server_ch(pss, pss->ch_recip);
1774 if (ch) {
1775 ch->window += (int32_t)pss->len;
1776 lwsl_notice("got additional window %d (now %d)\n",
1777 pss->len, ch->window);
1778 }
1779 pss->parser_state = SSHS_MSG_EAT_PADDING;
1780 break;
1781
1782 /*
1783 * channel close
1784 */
1785
1786 case SSHS_NVC_CH_EOF:
1787 /*
1788 * No explicit response is sent to this
1789 * message. However, the application may send
1790 * EOF to whatever is at the other end of the
1791 * channel. Note that the channel remains open
1792 * after this message, and more data may still
1793 * be sent in the other direction. This message
1794 * does not consume window space and can be sent
1795 * even if no window space is available.
1796 */
1797 lwsl_notice("SSH_MSG_CHANNEL_EOF: %d\n", pss->ch_recip);
1798 ch = ssh_get_server_ch(pss, pss->ch_recip);
1799 if (!ch) {
1800 lwsl_notice("unknown ch %d\n", pss->ch_recip);
1801 return -1;
1802 }
1803
1804 if (!ch->scheduled_close) {
1805 lwsl_notice("scheduling CLOSE\n");
1806 ch->scheduled_close = 1;
1807 write_task(pss, ch, SSH_WT_CH_CLOSE);
1808 }
1809 pss->parser_state = SSHS_MSG_EAT_PADDING;
1810 break;
1811
1812 case SSHS_NVC_CH_CLOSE:
1813 /*
1814 * When either party wishes to terminate the
1815 * channel, it sends SSH_MSG_CHANNEL_CLOSE.
1816 * Upon receiving this message, a party MUST
1817 * send back an SSH_MSG_CHANNEL_CLOSE unless it
1818 * has already sent this message for the
1819 * channel. The channel is considered closed
1820 * for a party when it has both sent and
1821 * received SSH_MSG_CHANNEL_CLOSE, and the
1822 * party may then reuse the channel number.
1823 * A party MAY send SSH_MSG_CHANNEL_CLOSE
1824 * without having sent or received
1825 * SSH_MSG_CHANNEL_EOF.
1826 */
1827 lwsl_notice("SSH_MSG_CHANNEL_CLOSE ch %d\n",
1828 pss->ch_recip);
1829 ch = ssh_get_server_ch(pss, pss->ch_recip);
1830 if (!ch)
1831 goto bail;
1832
1833 pss->parser_state = SSHS_MSG_EAT_PADDING;
1834
1835 if (ch->sent_close) {
1836 /*
1837 * This is acking our sent close...
1838 * we can destroy the channel with no
1839 * further communication.
1840 */
1841 ssh_destroy_channel(pss, ch);
1842 break;
1843 }
1844
1845 ch->received_close = 1;
1846 ch->scheduled_close = 1;
1847 write_task(pss, ch, SSH_WT_CH_CLOSE);
1848 break;
1849
1850 default:
1851 break;
1852
1853 chrq_fail:
1854 lwsl_notice("chrq_fail\n");
1855 write_task(pss, pss->ch_temp, SSH_WT_CHRQ_FAILURE);
1856 pss->parser_state = SSH_KEX_STATE_SKIP;
1857 break;
1858
1859 ch_fail:
1860 if (pss->ch_temp) {
1861 free(pss->ch_temp);
1862 pss->ch_temp = NULL;
1863 }
1864 write_task(pss, pss->ch_temp, SSH_WT_CH_FAILURE);
1865 pss->parser_state = SSH_KEX_STATE_SKIP;
1866 break;
1867
1868 #if !defined(MBEDTLS_VERSION_NUMBER) || MBEDTLS_VERSION_NUMBER < 0x03000000
1869 ua_fail1:
1870 #endif
1871 lws_genrsa_destroy(&ctx);
1872 ua_fail:
1873 write_task(pss, NULL, SSH_WT_UA_FAILURE);
1874 ua_fail_silently:
1875 lws_ua_destroy(pss);
1876 /* Sect 4, RFC4252
1877 *
1878 * Additionally, the implementation SHOULD limit the
1879 * number of failed authentication attempts a client
1880 * may perform in a single session (the RECOMMENDED
1881 * limit is 20 attempts). If the threshold is
1882 * exceeded, the server SHOULD disconnect.
1883 */
1884 if (pss->count_auth_attempts++ > 20)
1885 goto bail;
1886
1887 pss->parser_state = SSH_KEX_STATE_SKIP;
1888 break;
1889 }
1890
1891 pss->pos++;
1892 }
1893
1894 return 0;
1895 bail:
1896 lws_kex_destroy(pss);
1897 lws_ua_destroy(pss);
1898
1899 return SSH_DISCONNECT_KEY_EXCHANGE_FAILED;
1900 }
1901
1902 static int
parse(struct per_session_data__sshd * pss,uint8_t * p,size_t len)1903 parse(struct per_session_data__sshd *pss, uint8_t *p, size_t len)
1904 {
1905 while (len--) {
1906
1907 if (pss->copy_to_I_C && pss->kex->I_C_payload_len <
1908 pss->kex->I_C_alloc_len &&
1909 pss->parser_state != SSHS_MSG_EAT_PADDING)
1910 pss->kex->I_C[pss->kex->I_C_payload_len++] = *p;
1911
1912 if (pss->active_keys_cts.valid &&
1913 pss->parser_state == SSHS_MSG_LEN)
1914 /* take a copy for full decrypt */
1915 pss->packet_assembly[pss->pa_pos++] = *p;
1916
1917 if (pss->active_keys_cts.valid &&
1918 pss->parser_state == SSHS_MSG_PADDING &&
1919 pss->msg_len) {
1920 /* we are going to have to decrypt it */
1921 uint32_t cp, l = pss->msg_len + 4 +
1922 pss->active_keys_cts.MAC_length;
1923 uint8_t pt[2048];
1924
1925 len++;
1926 cp = (uint32_t)len;
1927
1928 if (cp > l - pss->pa_pos)
1929 cp = l - pss->pa_pos;
1930
1931 if (cp > sizeof(pss->packet_assembly) -
1932 pss->pa_pos) {
1933 lwsl_err("Packet is too big to decrypt\n");
1934
1935 goto bail;
1936 }
1937 if (pss->msg_len < 2 + 4) {
1938 lwsl_err("packet too small\n");
1939
1940 goto bail;
1941 }
1942
1943 memcpy(&pss->packet_assembly[pss->pa_pos], p, cp);
1944 pss->pa_pos += cp;
1945 len -= cp;
1946 p += cp;
1947
1948 if (pss->pa_pos != l)
1949 return 0;
1950
1951 /* decrypt it */
1952 cp = (uint32_t)lws_chacha_decrypt(&pss->active_keys_cts,
1953 pss->ssh_sequence_ctr_cts++,
1954 pss->packet_assembly,
1955 pss->pa_pos, pt);
1956 if (cp) {
1957 lwsl_notice("Decryption failed: %d\n", cp);
1958 goto bail;
1959 }
1960
1961 if (lws_ssh_parse_plaintext(pss, pt + 4, pss->msg_len))
1962 goto bail;
1963
1964 pss->pa_pos = 0;
1965 pss->ctr = 0;
1966 continue;
1967 }
1968
1969 if (lws_ssh_parse_plaintext(pss, p, 1))
1970 goto bail;
1971
1972 p++;
1973 }
1974
1975 return 0;
1976
1977 bail:
1978 lws_kex_destroy(pss);
1979 lws_ua_destroy(pss);
1980
1981 return SSH_DISCONNECT_KEY_EXCHANGE_FAILED;
1982 }
1983
1984 static uint32_t
pad_and_encrypt(uint8_t * dest,void * ps,uint8_t * pp,struct per_session_data__sshd * pss,int skip_pad)1985 pad_and_encrypt(uint8_t *dest, void *ps, uint8_t *pp,
1986 struct per_session_data__sshd *pss, int skip_pad)
1987 {
1988 uint32_t n;
1989
1990 if (!skip_pad)
1991 lws_pad_set_length(pss, ps, &pp, &pss->active_keys_stc);
1992 n = (uint32_t)lws_ptr_diff(pp, ps);
1993
1994 if (!pss->active_keys_stc.valid) {
1995 memcpy(dest, ps, n);
1996 return n;
1997 }
1998
1999 lws_chacha_encrypt(&pss->active_keys_stc, pss->ssh_sequence_ctr_stc,
2000 ps, n, dest);
2001 n += pss->active_keys_stc.MAC_length;
2002
2003 return n;
2004 }
2005
2006 static int
lws_callback_raw_sshd(struct lws * wsi,enum lws_callback_reasons reason,void * user,void * in,size_t len)2007 lws_callback_raw_sshd(struct lws *wsi, enum lws_callback_reasons reason,
2008 void *user, void *in, size_t len)
2009 {
2010 struct per_session_data__sshd *pss =
2011 (struct per_session_data__sshd *)user, **p;
2012 struct per_vhost_data__sshd *vhd = NULL;
2013 uint8_t buf[LWS_PRE + 1024], *pp, *ps = &buf[LWS_PRE + 512], *ps1 = NULL;
2014 const struct lws_protocol_vhost_options *pvo;
2015 const struct lws_protocols *prot;
2016 struct lws_ssh_channel *ch;
2017 char lang[10];
2018 int n, m, o;
2019
2020 /*
2021 * Because we are an abstract protocol plugin, we will get called by
2022 * wsi that actually bind to a plugin "on top of us" that calls thru
2023 * to our callback.
2024 *
2025 * Under those circumstances, we can't simply get a pointer to our own
2026 * protocol from the wsi. If there's a pss already, we can get it from
2027 * there, but the first time for each connection we have to look it up.
2028 */
2029 if (pss && pss->vhd)
2030 vhd = (struct per_vhost_data__sshd *)
2031 lws_protocol_vh_priv_get(lws_get_vhost(wsi),
2032 pss->vhd->protocol);
2033 else
2034 if (lws_get_vhost(wsi))
2035 vhd = (struct per_vhost_data__sshd *)
2036 lws_protocol_vh_priv_get(lws_get_vhost(wsi),
2037 lws_vhost_name_to_protocol(
2038 lws_get_vhost(wsi), "lws-ssh-base"));
2039
2040 switch ((int)reason) {
2041 case LWS_CALLBACK_PROTOCOL_INIT:
2042 vhd = lws_protocol_vh_priv_zalloc(lws_get_vhost(wsi),
2043 lws_get_protocol(wsi),
2044 sizeof(struct per_vhost_data__sshd));
2045 if (!vhd)
2046 return 0;
2047 vhd->context = lws_get_context(wsi);
2048 vhd->protocol = lws_get_protocol(wsi);
2049 vhd->vhost = lws_get_vhost(wsi);
2050
2051 pvo = (const struct lws_protocol_vhost_options *)in;
2052 while (pvo) {
2053 /*
2054 * the user code passes the ops struct address to us
2055 * using a pvo (per-vhost option)
2056 */
2057 if (!strcmp(pvo->name, "ops"))
2058 vhd->ops = (const struct lws_ssh_ops *)pvo->value;
2059
2060 /*
2061 * the user code is telling us to get the ops struct
2062 * from another protocol's protocol.user pointer
2063 */
2064 if (!strcmp(pvo->name, "ops-from")) {
2065 prot = lws_vhost_name_to_protocol(vhd->vhost,
2066 pvo->value);
2067 if (prot)
2068 vhd->ops = (const struct lws_ssh_ops *)prot->user;
2069 else
2070 lwsl_err("%s: can't find protocol %s\n",
2071 __func__, pvo->value);
2072 }
2073
2074 pvo = pvo->next;
2075 }
2076
2077 if (!vhd->ops) {
2078 lwsl_warn("ssh pvo \"ops\" is mandatory\n");
2079 return 0;
2080 }
2081 /*
2082 * The user code ops api_version has to be current
2083 */
2084 if (vhd->ops->api_version != LWS_SSH_OPS_VERSION) {
2085 lwsl_err("FATAL ops is api_version v%d but code is v%d\n",
2086 vhd->ops->api_version, LWS_SSH_OPS_VERSION);
2087 return 1;
2088 }
2089 break;
2090
2091 case LWS_CALLBACK_RAW_ADOPT:
2092 lwsl_info("LWS_CALLBACK_RAW_ADOPT\n");
2093 if (!vhd || !pss)
2094 return -1;
2095 pss->next = vhd->live_pss_list;
2096 vhd->live_pss_list = pss;
2097 pss->parser_state = SSH_INITIALIZE_TRANSIENT;
2098 pss->wsi = wsi;
2099 pss->vhd = vhd;
2100 pss->kex_state = KEX_STATE_EXPECTING_CLIENT_OFFER;
2101 pss->active_keys_cts.padding_alignment = 8;
2102 pss->active_keys_stc.padding_alignment = 8;
2103 if (lws_kex_create(pss))
2104 return -1;
2105 write_task(pss, NULL, SSH_WT_VERSION);
2106
2107 /* sect 4 RFC4252
2108 *
2109 * The server SHOULD have a timeout for authentication and
2110 * disconnect if the authentication has not been accepted
2111 * within the timeout period.
2112 *
2113 * The RECOMMENDED timeout period is 10 minutes.
2114 */
2115 lws_set_timeout(wsi, (enum pending_timeout)
2116 SSH_PENDING_TIMEOUT_CONNECT_TO_SUCCESSFUL_AUTH, 10 * 60);
2117 break;
2118
2119 case LWS_CALLBACK_RAW_CLOSE:
2120 if (!pss)
2121 return -1;
2122 lwsl_info("LWS_CALLBACK_RAW_CLOSE\n");
2123 lws_kex_destroy(pss);
2124 lws_ua_destroy(pss);
2125
2126 ssh_free_set_NULL(pss->last_alloc);
2127
2128 while (pss->ch_list)
2129 ssh_destroy_channel(pss, pss->ch_list);
2130
2131 lws_chacha_destroy(&pss->active_keys_cts);
2132 lws_chacha_destroy(&pss->active_keys_stc);
2133
2134 p = &vhd->live_pss_list;
2135
2136 while (*p) {
2137 if ((*p) == pss) {
2138 *p = pss->next;
2139 continue;
2140 }
2141 p = &((*p)->next);
2142 }
2143 break;
2144
2145 case LWS_CALLBACK_RAW_RX:
2146 if (!pss)
2147 return -1;
2148 if (parse(pss, in, len))
2149 return -1;
2150 break;
2151
2152 case LWS_CALLBACK_RAW_WRITEABLE:
2153 if (!pss)
2154 break;
2155 n = 0;
2156 o = pss->write_task[pss->wt_tail];
2157 ch = pss->write_channel[pss->wt_tail];
2158
2159 if (pss->wt_head == pss->wt_tail)
2160 o = SSH_WT_NONE;
2161
2162 switch (o) {
2163 case SSH_WT_VERSION:
2164 if (!pss->vhd)
2165 break;
2166 n = lws_snprintf((char *)buf + LWS_PRE,
2167 sizeof(buf) - LWS_PRE - 1, "%s\r\n",
2168 pss->vhd->ops->server_string);
2169 write_task(pss, NULL, SSH_WT_OFFER);
2170 break;
2171
2172 case SSH_WT_OFFER:
2173 if (!pss->vhd)
2174 break;
2175 m = 0;
2176 n = (int)offer(pss, buf + LWS_PRE,
2177 sizeof(buf) - LWS_PRE, 0, &m);
2178 if (n == 0) {
2179 lwsl_notice("Too small\n");
2180
2181 return -1;
2182 }
2183
2184 if (!pss->kex) {
2185 lwsl_notice("%s: SSH_WT_OFFER: pss->kex is NULL\n",
2186 __func__);
2187 return -1;
2188 }
2189
2190 /* we need a copy of it to generate the hash later */
2191 if (pss->kex->I_S)
2192 free(pss->kex->I_S);
2193 pss->kex->I_S = sshd_zalloc((unsigned int)m);
2194 if (!pss->kex->I_S) {
2195 lwsl_notice("OOM 5: %d\n", m);
2196
2197 return -1;
2198 }
2199 /* without length + padcount part */
2200 memcpy(pss->kex->I_S, buf + LWS_PRE + 5, (unsigned int)m);
2201 pss->kex->I_S_payload_len = (uint32_t)m; /* without padding */
2202 break;
2203
2204 case SSH_WT_OFFER_REPLY:
2205 memcpy(ps, pss->kex->kex_r, pss->kex->kex_r_len);
2206 n = (int)pad_and_encrypt(&buf[LWS_PRE], ps,
2207 ps + pss->kex->kex_r_len, pss, 1);
2208 pss->kex_state = KEX_STATE_REPLIED_TO_OFFER;
2209 /* afterwards, must do newkeys */
2210 write_task(pss, NULL, SSH_WT_SEND_NEWKEYS);
2211 break;
2212
2213 case SSH_WT_SEND_NEWKEYS:
2214 pp = ps + 5;
2215 *pp++ = SSH_MSG_NEWKEYS;
2216 goto pac;
2217
2218 case SSH_WT_UA_ACCEPT:
2219 /*
2220 * If the server supports the service (and permits
2221 * the client to use it), it MUST respond with the
2222 * following:
2223 *
2224 * byte SSH_MSG_SERVICE_ACCEPT
2225 * string service name
2226 */
2227 pp = ps + 5;
2228 *pp++ = SSH_MSG_SERVICE_ACCEPT;
2229 lws_p32(pp, pss->npos);
2230 pp += 4;
2231 strcpy((char *)pp, pss->name);
2232 pp += pss->npos;
2233 goto pac;
2234
2235 case SSH_WT_UA_FAILURE:
2236 pp = ps + 5;
2237 *pp++ = SSH_MSG_USERAUTH_FAILURE;
2238 lws_p32(pp, 9);
2239 pp += 4;
2240 strcpy((char *)pp, "publickey");
2241 pp += 9;
2242 *pp++ = 0;
2243 goto pac;
2244
2245 case SSH_WT_UA_BANNER:
2246 pp = ps + 5;
2247 *pp++ = SSH_MSG_USERAUTH_BANNER;
2248 if (pss->vhd && pss->vhd->ops->banner)
2249 n = (int)pss->vhd->ops->banner((char *)&buf[650],
2250 150 - 1,
2251 lang, (int)sizeof(lang));
2252 lws_p32(pp, (uint32_t)n);
2253 pp += 4;
2254 strcpy((char *)pp, (char *)&buf[650]);
2255 pp += n;
2256 if (lws_cstr(&pp, lang, sizeof(lang)))
2257 goto bail;
2258 goto pac;
2259
2260 case SSH_WT_UA_PK_OK:
2261 /*
2262 * The server MUST respond to this message with
2263 * either SSH_MSG_USERAUTH_FAILURE or with the
2264 * following:
2265 *
2266 * byte SSH_MSG_USERAUTH_PK_OK
2267 * string public key alg name from the request
2268 * string public key blob from the request
2269 */
2270 n = 74 + (int)pss->ua->pubkey_len;
2271 if (n > (int)sizeof(buf) - LWS_PRE) {
2272 lwsl_notice("pubkey too large\n");
2273 goto bail;
2274 }
2275 ps1 = sshd_zalloc((unsigned int)n);
2276 if (!ps1)
2277 goto bail;
2278 ps = ps1;
2279 pp = ps1 + 5;
2280 *pp++ = SSH_MSG_USERAUTH_PK_OK;
2281 if (lws_cstr(&pp, pss->ua->alg, 64)) {
2282 free(ps1);
2283 goto bail;
2284 }
2285 lws_p32(pp, pss->ua->pubkey_len);
2286 pp += 4;
2287 memcpy(pp, pss->ua->pubkey, pss->ua->pubkey_len);
2288 pp += pss->ua->pubkey_len;
2289
2290 /* we no longer need the UA now we judged it */
2291 lws_ua_destroy(pss);
2292
2293 goto pac;
2294
2295 case SSH_WT_UA_SUCCESS:
2296 pp = ps + 5;
2297 *pp++ = SSH_MSG_USERAUTH_SUCCESS;
2298 /* end SSH_PENDING_TIMEOUT_CONNECT_TO_SUCCESSFUL_AUTH */
2299 lws_set_timeout(wsi, NO_PENDING_TIMEOUT, 0);
2300 goto pac;
2301
2302 case SSH_WT_CH_OPEN_CONF:
2303 pp = ps + 5;
2304 *pp++ = SSH_MSG_CHANNEL_OPEN_CONFIRMATION;
2305 lws_p32(pp, pss->ch_temp->sender_ch);
2306 pp += 4;
2307 lws_p32(pp, pss->ch_temp->server_ch);
2308 pp += 4;
2309 /* tx initial window size towards us */
2310 lws_p32(pp, LWS_SSH_INITIAL_WINDOW);
2311 pp += 4;
2312 /* maximum packet size towards us */
2313 lws_p32(pp, 800);
2314 pp += 4;
2315 lwsl_info("SSH_WT_CH_OPEN_CONF\n");
2316 /* it's on the linked-list */
2317 pss->ch_temp = NULL;
2318 goto pac;
2319
2320 case SSH_WT_CH_FAILURE:
2321 pp = ps + 5;
2322 *pp++ = SSH_MSG_CHANNEL_OPEN_FAILURE;
2323 lws_p32(pp, ch->sender_ch);
2324 pp += 4;
2325 lws_p32(pp, ch->server_ch);
2326 pp += 4;
2327 lws_cstr(&pp, "reason", 64);
2328 lws_cstr(&pp, "en/US", 64);
2329 lwsl_info("SSH_WT_CH_FAILURE\n");
2330 goto pac;
2331
2332 case SSH_WT_CHRQ_SUCC:
2333 pp = ps + 5;
2334 *pp++ = SSH_MSG_CHANNEL_SUCCESS;
2335 lws_p32(pp, ch->sender_ch);
2336 lwsl_info("SSH_WT_CHRQ_SUCC\n");
2337 pp += 4;
2338 goto pac;
2339
2340 case SSH_WT_CHRQ_FAILURE:
2341 pp = ps + 5;
2342 *pp++ = SSH_MSG_CHANNEL_FAILURE;
2343 lws_p32(pp, ch->sender_ch);
2344 pp += 4;
2345 lwsl_info("SSH_WT_CHRQ_FAILURE\n");
2346 goto pac;
2347
2348 case SSH_WT_CH_CLOSE:
2349 pp = ps + 5;
2350 *pp++ = SSH_MSG_CHANNEL_CLOSE;
2351 lws_p32(pp, ch->sender_ch);
2352 lwsl_info("SSH_WT_CH_CLOSE\n");
2353 pp += 4;
2354 goto pac;
2355
2356 case SSH_WT_CH_EOF:
2357 pp = ps + 5;
2358 *pp++ = SSH_MSG_CHANNEL_EOF;
2359 lws_p32(pp, ch->sender_ch);
2360 lwsl_info("SSH_WT_CH_EOF\n");
2361 pp += 4;
2362 goto pac;
2363
2364 case SSH_WT_SCP_ACK_ERROR:
2365 case SSH_WT_SCP_ACK_OKAY:
2366 pp = ps + 5;
2367 *pp++ = SSH_MSG_CHANNEL_DATA;
2368 /* ps + 6 */
2369 lws_p32(pp, ch->sender_ch);
2370 pp += 4;
2371 lws_p32(pp, 1);
2372 pp += 4;
2373 if (o == SSH_WT_SCP_ACK_ERROR)
2374 *pp++ = 2;
2375 else
2376 *pp++ = 0;
2377 lwsl_info("SSH_WT_SCP_ACK_OKAY\n");
2378 goto pac;
2379
2380 case SSH_WT_WINDOW_ADJUST:
2381 pp = ps + 5;
2382 *pp++ = SSH_MSG_CHANNEL_WINDOW_ADJUST;
2383 /* ps + 6 */
2384 lws_p32(pp, ch->sender_ch);
2385 pp += 4;
2386 lws_p32(pp, 32768);
2387 pp += 4;
2388 lwsl_info("send SSH_MSG_CHANNEL_WINDOW_ADJUST\n");
2389 goto pac;
2390
2391 case SSH_WT_EXIT_STATUS:
2392 pp = ps + 5;
2393 *pp++ = SSH_MSG_CHANNEL_REQUEST;
2394 lws_p32(pp, ch->sender_ch);
2395 pp += 4;
2396 lws_p32(pp, 11);
2397 pp += 4;
2398 strcpy((char *)pp, "exit-status");
2399 pp += 11;
2400 *pp++ = 0;
2401 lws_p32(pp, (uint32_t)ch->retcode);
2402 pp += 4;
2403 lwsl_info("send SSH_MSG_CHANNEL_EXIT_STATUS\n");
2404 goto pac;
2405
2406 case SSH_WT_NONE:
2407 default:
2408 /* sending payload */
2409
2410 ch = ssh_get_server_ch(pss, 0);
2411 /* have a channel up to send on? */
2412 if (!ch)
2413 break;
2414
2415 if (!pss->vhd || !pss->vhd->ops)
2416 break;
2417 n = pss->vhd->ops->tx_waiting(ch->priv);
2418 if (n < 0)
2419 return -1;
2420 if (!n)
2421 /* nothing to send */
2422 break;
2423
2424 if (n == (LWS_STDOUT | LWS_STDERR)) {
2425 /* pick one using round-robin */
2426 if (pss->serviced_stderr_last)
2427 n = LWS_STDOUT;
2428 else
2429 n = LWS_STDERR;
2430 }
2431
2432 pss->serviced_stderr_last = !!(n & LWS_STDERR);
2433
2434 /* stdout or stderr */
2435 pp = ps + 5;
2436 if (n == LWS_STDOUT)
2437 *pp++ = SSH_MSG_CHANNEL_DATA;
2438 else
2439 *pp++ = SSH_MSG_CHANNEL_EXTENDED_DATA;
2440 /* ps + 6 */
2441 lws_p32(pp, pss->ch_list->sender_ch);
2442 m = 14;
2443 if (n == LWS_STDERR) {
2444 pp += 4;
2445 /* data type code... 1 for stderr payload */
2446 lws_p32(pp, SSH_EXTENDED_DATA_STDERR);
2447 m = 18;
2448 }
2449 /* also skip another strlen u32 at + 10 / +14 */
2450 pp += 8;
2451 /* ps + 14 / + 18 */
2452
2453 pp += pss->vhd->ops->tx(ch->priv, n, pp,
2454 lws_ptr_diff_size_t(
2455 &buf[sizeof(buf) - 1], pp));
2456
2457 lws_p32(ps + m - 4, (uint32_t)lws_ptr_diff(pp, (ps + m)));
2458
2459 if (pss->vhd->ops->tx_waiting(ch->priv) > 0)
2460 lws_callback_on_writable(wsi);
2461
2462 ch->window -= lws_ptr_diff(pp, ps) - m;
2463 //lwsl_debug("our send window: %d\n", ch->window);
2464
2465 /* fallthru */
2466 pac:
2467 if (!pss->vhd)
2468 break;
2469 n = (int)pad_and_encrypt(&buf[LWS_PRE], ps, pp, pss, 0);
2470 break;
2471
2472 bail:
2473 lws_ua_destroy(pss);
2474 lws_kex_destroy(pss);
2475
2476 return 1;
2477
2478 }
2479
2480 if (n > 0) {
2481 m = lws_write(wsi, (unsigned char *)buf + LWS_PRE, (unsigned int)n,
2482 LWS_WRITE_HTTP);
2483
2484 switch(o) {
2485 case SSH_WT_SEND_NEWKEYS:
2486 lwsl_info("Activating STC keys\n");
2487 pss->active_keys_stc = pss->kex->keys_next_stc;
2488 lws_chacha_activate(&pss->active_keys_stc);
2489 pss->kex_state = KEX_STATE_CRYPTO_INITIALIZED;
2490 pss->kex->newkeys |= 1;
2491 if (pss->kex->newkeys == 3)
2492 lws_kex_destroy(pss);
2493 break;
2494 case SSH_WT_UA_PK_OK:
2495 free(ps1);
2496 break;
2497 case SSH_WT_CH_CLOSE:
2498 if (ch->received_close) {
2499 /*
2500 * We are sending this at the behest of
2501 * the remote peer...
2502 * we can destroy the channel with no
2503 * further communication.
2504 */
2505 ssh_destroy_channel(pss, ch);
2506 break;
2507 }
2508 ch->sent_close = 1;
2509 break;
2510 }
2511 if (m < 0) {
2512 lwsl_err("ERR %d from write\n", m);
2513 goto bail;
2514 }
2515
2516 if (o != SSH_WT_VERSION)
2517 pss->ssh_sequence_ctr_stc++;
2518
2519 if (o != SSH_WT_NONE)
2520 pss->wt_tail =
2521 (pss->wt_tail + 1) & 7;
2522 } else
2523 if (o == SSH_WT_UA_PK_OK) /* free it either way */
2524 free(ps1);
2525
2526 ch = ssh_get_server_ch(pss, 0);
2527
2528 if (pss->wt_head != pss->wt_tail ||
2529 (ch && ch->priv && pss->vhd &&
2530 pss->vhd->ops->tx_waiting(ch->priv)))
2531 lws_callback_on_writable(wsi);
2532
2533 break;
2534
2535 case LWS_CALLBACK_SSH_UART_SET_RXFLOW:
2536 /*
2537 * this is sent to set rxflow state on any connections that
2538 * sink on a particular sink. The sink index affected is in len
2539 *
2540 * More than one protocol may sink to the same uart, and the
2541 * protocol may select the sink itself, eg, in the URL used
2542 * to set up the connection.
2543 */
2544 lwsl_notice("sshd LWS_CALLBACK_SSH_UART_SET_RXFLOW: wsi %p, %d\n",
2545 wsi, (int)len & 1);
2546 lws_rx_flow_control(wsi, len & 1);
2547 break;
2548
2549 case LWS_CALLBACK_CGI:
2550 if (!pss)
2551 break;
2552 if (pss->vhd && pss->vhd->ops &&
2553 pss->vhd->ops->child_process_io &&
2554 pss->vhd->ops->child_process_io(pss->ch_temp->priv,
2555 pss->wsi, (struct lws_cgi_args *)in))
2556 return -1;
2557 break;
2558
2559 case LWS_CALLBACK_CGI_PROCESS_ATTACH:
2560 if (!pss)
2561 break;
2562 ch = ssh_get_server_ch(pss, pss->channel_doing_spawn);
2563 if (ch) {
2564 ch->spawn_pid = (uint32_t)len; /* child process PID */
2565 lwsl_notice("associated PID %d to ch %d\n", (int)len,
2566 pss->channel_doing_spawn);
2567 }
2568 break;
2569
2570 case LWS_CALLBACK_CGI_TERMINATED:
2571 if (!pss)
2572 break;
2573 if (pss->vhd && pss->vhd->ops &&
2574 pss->vhd->ops->child_process_terminated)
2575 pss->vhd->ops->child_process_terminated(pss->ch_temp->priv,
2576 pss->wsi);
2577 /*
2578 * we have the child PID in len... we need to match it to a
2579 * channel that is on the wsi
2580 */
2581 ch = pss->ch_list;
2582
2583 while (ch) {
2584 if (ch->spawn_pid == len) {
2585 lwsl_notice("starting close of ch with PID %d\n",
2586 (int)len);
2587 ch->scheduled_close = 1;
2588 write_task(pss, ch, SSH_WT_CH_CLOSE);
2589 break;
2590 }
2591 ch = ch->next;
2592 }
2593 break;
2594
2595 default:
2596 break;
2597 }
2598
2599 return 0;
2600 }
2601
2602 #define LWS_PLUGIN_PROTOCOL_LWS_RAW_SSHD { \
2603 "lws-ssh-base", \
2604 lws_callback_raw_sshd, \
2605 sizeof(struct per_session_data__sshd), \
2606 1024, 0, NULL, 900 \
2607 }
2608
2609 LWS_VISIBLE const struct lws_protocols lws_ssh_base_protocols[] = {
2610 LWS_PLUGIN_PROTOCOL_LWS_RAW_SSHD,
2611 { NULL, NULL, 0, 0, 0, NULL, 0 } /* terminator */
2612 };
2613
2614 #if !defined (LWS_PLUGIN_STATIC)
2615
2616 LWS_VISIBLE const lws_plugin_protocol_t lws_ssh_base = {
2617 .hdr = {
2618 "ssh base",
2619 "lws_protocol_plugin",
2620 LWS_BUILD_HASH,
2621 LWS_PLUGIN_API_MAGIC
2622 },
2623
2624 .protocols = lws_ssh_base_protocols,
2625 .count_protocols = LWS_ARRAY_SIZE(lws_ssh_base_protocols),
2626 .extensions = NULL,
2627 .count_extensions = 0,
2628 };
2629
2630 #endif
2631