xref: /plan9-contrib/sys/src/cmd/ssh2/netssh.c (revision c703450534a39fda5e37abe206338c3e0e4fc8cd)
1 /*
2  *  /net/ssh
3  */
4 #include <u.h>
5 #include <libc.h>
6 #include <fcall.h>
7 #include <thread.h>
8 #include <9p.h>
9 #include <mp.h>
10 #include <auth.h>
11 #include <authsrv.h>
12 #include <libsec.h>
13 #include <ip.h>
14 #include "netssh.h"
15 
16 extern int nokeyverify;
17 
18 void stclunk(Fid *);
19 void stend(Srv *);
20 void stflush(Req *);
21 void stopen(Req *);
22 void stread(Req *);
23 void stwrite(Req *);
24 
25 Srv netsshsrv = {
26 	.open = stopen,
27 	.read = stread,
28 	.write = stwrite,
29 	.flush = stflush,
30 	.destroyfid = stclunk,
31 	.end = stend,
32 };
33 
34 Cipher *cryptos[] = {
35 	&cipheraes128,
36 	&cipheraes192,
37 	&cipheraes256,
38 	&cipheraes128ctr,
39 	&cipheraes192ctr,
40 	&cipheraes256ctr,
41 //	&cipherblowfish,
42 	&cipher3des,
43 	&cipherrc4,
44 };
45 
46 Kex *kexes[] = {
47 	&dh1sha1,
48 	&dh14sha1,
49 };
50 
51 PKA *pkas[3];
52 
53 char *macnames[] = {
54 	"hmac-sha1",
55 };
56 
57 char *st_names[] = {
58 [Empty]		"Empty",
59 [Allocated]	"Allocated",
60 [Initting]	"Initting",
61 [Listening]	"Listening",
62 [Opening]	"Opening",
63 [Negotiating]	"Negotiating",
64 [Authing]	"Authing",
65 [Established]	"Established",
66 [Eof]		"Eof",
67 [Closing]	"Closing",
68 [Closed]	"Closed",
69 };
70 
71 int debug;
72 int kflag;
73 char *mntpt = "/net";
74 char uid[32];
75 Conn *connections[MAXCONN];
76 File *rootfile, *clonefile, *ctlfile, *keysfile;
77 Ioproc *io9p;
78 MBox keymbox;
79 QLock availlck;
80 Rendez availrend;
81 
82 SSHChan *alloc_chan(Conn *);
83 Conn *alloc_conn(void);
84 int auth_req(Packet *, Conn *);
85 int client_auth(Conn *, Ioproc *);
86 int dohandshake(Conn *, char *);
87 char *factlookup(int, int, char *[]);
88 void filedup(Req *, File *);
89 void readdata(void *);
90 void reader(void *);
91 void readreqrem(void *);
92 void send_kexinit(Conn *);
93 void server(char *, char *);
94 void shutdown(Conn *);
95 void stlisconn(void *);
96 void stlischan(void *);
97 int validatekex(Conn *, Packet *);
98 int validatekexc(Packet *);
99 int validatekexs(Packet *);
100 void writectlproc(void *);
101 void writedataproc(void *);
102 void writereqremproc(void *);
103 
104 static int deferredinit(Conn *c);
105 
106 static void
sshlogint(Conn * c,char * file,char * p)107 sshlogint(Conn *c, char *file, char *p)
108 {
109 	char *role, *id;
110 
111 	if (c == nil)
112 		role = "";
113 	else if (c->role == Server)
114 		role = "server ";
115 	else
116 		role = "client ";
117 	if (c == nil)
118 		id = strdup("");
119 	else if (c->user || c->remote)
120 		id = smprint("user %s@%s id %d ", c->user, c->remote, c->id);
121 	else
122 		id = smprint("id %d ", c->id);
123 
124 	syslog(0, file, "%s: %s%s%s", argv0, role, id, p);
125 	free(id);
126 }
127 
128 void
sshlog(Conn * c,char * fmt,...)129 sshlog(Conn *c, char *fmt, ...)
130 {
131 	va_list args;
132 	char *p;
133 
134 	/* do this first in case fmt contains "%r" */
135 	va_start(args, fmt);
136 	p = vsmprint(fmt, args);
137 	va_end(args);
138 
139 	sshlogint(c, "ssh", p);
140 	sshlogint(c, "sshdebug", p);	/* log in both places */
141 	free(p);
142 }
143 
144 void
sshdebug(Conn * c,char * fmt,...)145 sshdebug(Conn *c, char *fmt, ...)
146 {
147 	va_list args;
148 	char *p;
149 
150 	if (!debug)
151 		return;
152 
153 	/* do this first in case fmt contains "%r" */
154 	va_start(args, fmt);
155 	p = vsmprint(fmt, args);
156 	va_end(args);
157 
158 	sshlogint(c, "sshdebug", p);
159 	free(p);
160 }
161 
162 void
usage(void)163 usage(void)
164 {
165 	fprint(2, "usage: %s [-dkv] [-m mntpt] [-s srvpt]\n", argv0);
166 	exits("usage");
167 }
168 
169 void
threadmain(int argc,char * argv[])170 threadmain(int argc, char *argv[])
171 {
172 	char *p, *srvpt = nil;
173 
174 	quotefmtinstall();
175 	threadsetname("main");
176 	nokeyverify = 1;	/* temporary until verification is fixed */
177 	ARGBEGIN {
178 	case '9':
179 		chatty9p = 1;
180 		break;
181 	case 'd':
182 		debug++;
183 		break;
184 	case 'k':
185 		kflag = 1;
186 		break;
187 	case 'm':
188 		mntpt = EARGF(usage());
189 		break;
190 	case 's':
191 		srvpt = EARGF(usage());
192 		break;
193 	case 'v':
194 		nokeyverify = 1;
195 		break;
196 	case 'V':
197 		nokeyverify = 0;
198 		break;
199 	default:
200 		usage();
201 		break;
202 	} ARGEND;
203 
204 	p = getenv("nosshkeyverify");
205 	if (p && p[0] != '\0')
206 		nokeyverify = 1;
207 	free(p);
208 
209 	if (readfile("/dev/user", uid, sizeof uid) <= 0)
210 		strcpy(uid, "none");
211 
212 	keymbox.mchan = chancreate(4, 0);
213 	availrend.l = &availlck;
214 	dh_init(pkas);
215 
216 	/* become a daemon */
217 	if (rfork(RFNOTEG) < 0)
218 		fprint(2, "%s: rfork(NOTEG) failed: %r\n", argv0);
219 	server(mntpt, srvpt);
220 	threadexits(nil);
221 }
222 
223 int
readio(Ioproc * io,int fd,void * buf,int n)224 readio(Ioproc *io, int fd, void *buf, int n)
225 {
226 	if (io)
227 		return ioread(io, fd, buf, n);
228 	else
229 		return read(fd, buf, n);
230 }
231 
232 int
writeio(Ioproc * io,int fd,void * buf,int n)233 writeio(Ioproc *io, int fd, void *buf, int n)
234 {
235 	if (io)
236 		return iowrite(io, fd, buf, n);
237 	else
238 		return write(fd, buf, n);
239 }
240 
241 int
read9pmsg(int fd,void * abuf,uint n)242 read9pmsg(int fd, void *abuf, uint n)
243 {
244 	int m, len;
245 	uchar *buf;
246 
247 	if (io9p == nil)
248 		io9p = ioproc();
249 
250 	buf = abuf;
251 
252 	/* read count */
253 	m = ioreadn(io9p, fd, buf, BIT32SZ);
254 	if(m != BIT32SZ){
255 		if(m < 0)
256 			return -1;
257 		return 0;
258 	}
259 
260 	len = GBIT32(buf);
261 	if(len <= BIT32SZ || len > n){
262 		werrstr("bad length in 9P2000 message header");
263 		return -1;
264 	}
265 	len -= BIT32SZ;
266 	m = ioreadn(io9p, fd, buf+BIT32SZ, len);
267 	if(m < len)
268 		return 0;
269 	return BIT32SZ+m;
270 }
271 
272 void
stend(Srv *)273 stend(Srv *)
274 {
275 	closeioproc(io9p);
276 	threadkillgrp(threadgetgrp());
277 }
278 
279 void
server(char * mntpt,char * srvpt)280 server(char *mntpt, char *srvpt)
281 {
282 	Dir d;
283 	char *p;
284 	int fd;
285 
286 	netsshsrv.tree = alloctree(uid, uid, 0777, nil);
287 	rootfile = createfile(netsshsrv.tree->root, "ssh", uid, 0555|DMDIR,
288 		(void*)Qroot);
289 	clonefile = createfile(rootfile, "clone", uid, 0666, (void*)Qclone);
290 	ctlfile = createfile(rootfile, "ctl", uid, 0666, (void*)Qctl);
291 	keysfile = createfile(rootfile, "keys", uid, 0600, (void *)Qreqrem);
292 
293 	/*
294 	 * needs to be MBEFORE in case there are previous, now defunct,
295 	 * netssh processes mounted in mntpt.
296 	 */
297 	threadpostmountsrv(&netsshsrv, srvpt, mntpt, MBEFORE);
298 
299 	p = esmprint("%s/cs", mntpt);
300 	fd = open(p, OWRITE);
301 	free(p);
302 	if (fd >= 0) {
303 		fprint(fd, "add ssh");
304 		close(fd);
305 	}
306 	if (srvpt) {
307 		nulldir(&d);
308 		d.mode = 0666;
309 		p = esmprint("/srv/%s", srvpt);
310 		dirwstat(p, &d);
311 		free(p);
312 	}
313 	sshdebug(nil, "server started for %s", getuser());
314 }
315 
316 static void
respexit(Conn * c,Req * r,void * freeme,char * msg)317 respexit(Conn *c, Req *r, void *freeme, char *msg)
318 {
319 	if (msg)
320 		sshdebug(c, "%s", msg);
321 	r->aux = 0;
322 	respond(r, msg);
323 	free(freeme);
324 	threadexits(nil);	/* maybe use msg here */
325 }
326 
327 void
stopen(Req * r)328 stopen(Req *r)
329 {
330 	int lev, xconn, fd;
331 	uvlong qidpath;
332 	char *p;
333 	char buf[32];
334 	Conn *c;
335 	SSHChan *sc;
336 
337 	qidpath = (uvlong)r->fid->file->aux;
338 	lev = qidpath >> Levshift;
339 	switch ((ulong)(qidpath & Qtypemask)) {
340 	default:
341 		respond(r, nil);
342 		break;
343 	case Qlisten:
344 		r->aux = (void *)threadcreate((lev == Connection?
345 			stlisconn: stlischan), r, Defstk);
346 		break;
347 	case Qclone:
348 		switch (lev) {
349 		case Top:
350 			/* should use dial(2) instead of diddling /net/tcp */
351 			p = esmprint("%s/tcp/clone", mntpt);
352 			fd = open(p, ORDWR);
353 			if (fd < 0) {
354 				sshdebug(nil, "stopen: open %s failed: %r", p);
355 				free(p);
356 				responderror(r);
357 				return;
358 			}
359 			free(p);
360 
361 			c = alloc_conn();
362 			if (c == nil) {
363 				close(fd);
364 				respond(r, "no more connections");
365 				return;
366 			}
367 			c->ctlfd = fd;
368 			c->poisoned = 0;
369 			filedup(r, c->ctlfile);
370 			sshlog(c, "new connection on fd %d", fd);
371 			break;
372 		case Connection:
373 			xconn = (qidpath >> Connshift) & Connmask;
374 			c = connections[xconn];
375 			if (c == nil) {
376 				respond(r, "bad connection");
377 				return;
378 			}
379 			sc = alloc_chan(c);
380 			if (sc == nil) {
381 				respond(r, "no more channels");
382 				return;
383 			}
384 			filedup(r, sc->ctl);
385 			break;
386 		default:
387 			snprint(buf, sizeof buf, "bad level %d", lev);
388 			readstr(r, buf);
389 			break;
390 		}
391 		respond(r, nil);
392 		break;
393 	}
394 }
395 
396 static void
listerrexit(Req * r,Ioproc * io,Conn * cl)397 listerrexit(Req *r, Ioproc *io, Conn *cl)
398 {
399 	r->aux = 0;
400 	responderror(r);
401 	closeioproc(io);
402 	shutdown(cl);
403 	threadexits(nil);
404 }
405 
406 void
stlisconn(void * a)407 stlisconn(void *a)
408 {
409 	int xconn, fd, n;
410 	uvlong qidpath;
411 	char *msg;
412 	char buf[Numbsz], path[NETPATHLEN];
413 	Conn *c, *cl;
414 	Ioproc *io;
415 	Req *r;
416 
417 	threadsetname("stlisconn");
418 	r = a;
419 	qidpath = (uvlong)r->fid->file->aux;
420 	xconn = (qidpath >> Connshift) & Connmask;
421 
422 	cl = connections[xconn];
423 	if (cl == nil) {
424 		sshlog(cl, "bad connection");
425 		respond(r, "bad connection");
426 		threadexits("bad connection");
427 	}
428 	if (cl->poisoned) {
429 		sshdebug(cl, "stlisconn conn %d poisoned", xconn);
430 		r->aux = 0;
431 		respond(r, "top level listen conn poisoned");
432 		threadexits("top level listen conn poisoned");
433 	}
434 	if (cl->ctlfd < 0) {
435 		sshdebug(cl, "stlisconn conn %d ctlfd < 0; poisoned", xconn);
436 		r->aux = 0;
437 		respond(r, "top level listen with closed fd");
438 		shutdown(cl);
439 		cl->poisoned = 1;	/* no more use until ctlfd is set */
440 		threadexits("top level listen with closed fd");
441 	}
442 
443 	io = ioproc();
444 
445 	/* read xconn's tcp conn's ctl file */
446 	seek(cl->ctlfd, 0, 0);
447 	n = ioread(io, cl->ctlfd, buf, sizeof buf - 1);
448 	if (n == 0) {
449 		sshlog(cl, "stlisconn read eof on fd %d", cl->ctlfd);
450 		listerrexit(r, io, cl);
451 	} else if (n < 0) {
452 		sshlog(cl, "stlisconn read failed on fd %d: %r", cl->ctlfd);
453 		listerrexit(r, io, cl);
454 	}
455 	buf[n] = '\0';
456 
457 	cl->state = Listening;
458 	/* should use dial(2) instead of diddling /net/tcp */
459 	snprint(path, sizeof path, "%s/tcp/%s/listen", mntpt, buf);
460 	for(;;) {
461 		fd = ioopen(io, path, ORDWR);
462 		if (fd < 0)
463 			listerrexit(r, io, cl);
464 		c = alloc_conn();
465 		if (c)
466 			break;
467 		n = ioread(io, fd, buf, sizeof buf - 1);
468 		if (n <= 0)
469 			listerrexit(r, io, cl);
470 		buf[n] = '\0';
471 		msg = smprint("reject %s no available connections", buf);
472 		iowrite(io, fd, msg, strlen(msg));
473 		free(msg);
474 		close(fd);			/* surely ioclose? */
475 	}
476 	c->ctlfd = fd;
477 	if (c->ctlfd < 0) {
478 		sshlog(cl, "stlisconn c->ctlfd < 0 for conn %d", xconn);
479 		threadexitsall("stlisconn c->ctlfd < 0");
480 	}
481 	c->poisoned = 0;
482 	c->stifle = 1;			/* defer server; was for coexistence */
483 	filedup(r, c->ctlfile);
484 	sshdebug(c, "responding to listen open");
485 	r->aux = 0;
486 	respond(r, nil);
487 	closeioproc(io);
488 	threadexits(nil);
489 }
490 
491 void
stlischan(void * a)492 stlischan(void *a)
493 {
494 	Req *r;
495 	Packet *p2;
496 	Ioproc *io;
497 	Conn *c;
498 	SSHChan *sc;
499 	int i, n, xconn;
500 	uvlong qidpath;
501 
502 	threadsetname("stlischan");
503 	r = a;
504 	qidpath = (uvlong)r->fid->file->aux;
505 	xconn = (qidpath >> Connshift) & Connmask;
506 	c = connections[xconn];
507 	if (c == nil) {
508 		respond(r, "bad channel");
509 		sshlog(c, "bad channel");
510 		threadexits(nil);
511 	}
512 	if (c->state == Closed || c->state == Closing)
513 		respexit(c, r, nil, "channel listen on closed connection");
514 	sc = c->chans[qidpath & Chanmask];
515 
516 	qlock(&c->l);
517 	sc->lreq = r;
518 	for (i = 0; i < c->nchan; ++i)
519 		if (c->chans[i] && c->chans[i]->state == Opening &&
520 		    c->chans[i]->ann && strcmp(c->chans[i]->ann, sc->ann) == 0)
521 			break;
522 	if (i >= c->nchan) {
523 		sc->state = Listening;
524 		rsleep(&sc->r);
525 		i = sc->waker;
526 		if (i < 0) {
527 			qunlock(&c->l);
528 			r->aux = 0;
529 			responderror(r);
530 			threadexits(nil);
531 		}
532 	} else
533 		rwakeup(&c->chans[i]->r);
534 	qunlock(&c->l);
535 
536 	if (c->state == Closed || c->state == Closing || c->state == Eof)
537 		respexit(c, r, nil, "channel listen on closed connection");
538 	c->chans[i]->state = Established;
539 
540 	p2 = new_packet(c);
541 	c->chans[i]->rwindow = Maxpayload;
542 	add_byte(p2, SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
543 	hnputl(p2->payload + 1, c->chans[i]->otherid);
544 	hnputl(p2->payload + 5, c->chans[i]->id);
545 	hnputl(p2->payload + 9, Maxpayload);
546 	hnputl(p2->payload + 13, Maxrpcbuf);
547 	p2->rlength = 18;
548 	n = finish_packet(p2);
549 	filedup(r, c->chans[i]->ctl);
550 
551 	io = ioproc();
552 	n = iowrite(io, c->datafd, p2->nlength, n);
553 	closeioproc(io);
554 
555 	free(p2);
556 
557 	sshdebug(c, "responding to chan listen open");
558 	r->aux = 0;
559 	if (n < 0)
560 		responderror(r);
561 	else
562 		respond(r, nil);
563 	threadexits(nil);
564 }
565 
566 void
getdata(Conn * c,SSHChan * sc,Req * r)567 getdata(Conn *c, SSHChan *sc, Req *r)
568 {
569 	Packet *p;
570 	Plist *d;
571 	int n;
572 
573 	n = r->ifcall.count;
574 	if (sc->dataq->rem < n)
575 		n = sc->dataq->rem;
576 	if (n > Maxrpcbuf)
577 		n = Maxrpcbuf;
578 	r->ifcall.offset = 0;
579 
580 	readbuf(r, sc->dataq->st, n);
581 	sc->dataq->st += n;
582 	sc->dataq->rem -= n;
583 	sc->inrqueue -= n;
584 	if (sc->dataq->rem <= 0) {
585 		d = sc->dataq;
586 		sc->dataq = sc->dataq->next;
587 		if (d->pack->tlength > sc->rwindow)
588 			sc->rwindow = 0;
589 		else
590 			sc->rwindow -= d->pack->tlength;
591 		free(d->pack);
592 		free(d);
593 	}
594 	if (sc->rwindow < 16*1024) {		/* magic.  half-way, maybe? */
595 		sc->rwindow += Maxpayload;
596 		sshdebug(c, "increasing receive window to %lud, inq %lud\n",
597 			argv0, sc->rwindow, sc->inrqueue);
598 		p = new_packet(c);
599 		add_byte(p, SSH_MSG_CHANNEL_WINDOW_ADJUST);
600 		hnputl(p->payload+1, sc->otherid);
601 		hnputl(p->payload+5, Maxpayload);
602 		p->rlength += 8;
603 		n = finish_packet(p);
604 		iowrite(c->dio, c->datafd, p->nlength, n);
605 		free(p);
606 	}
607 	r->aux = 0;
608 	respond(r, nil);
609 }
610 
611 void
stread(Req * r)612 stread(Req *r)
613 {
614 	Conn *c;
615 	SSHChan *sc;
616 	int n, lev, cnum, xconn;
617 	uvlong qidpath;
618 	char buf[Arbbufsz], path[NETPATHLEN];
619 
620 	threadsetname("stread");
621 	qidpath = (uvlong)r->fid->file->aux;
622 	lev = qidpath >> Levshift;
623 	xconn = (qidpath >> Connshift) & Connmask;
624 	c = connections[xconn];
625 	if (c == nil) {
626 		if (lev != Top || (qidpath & Qtypemask) != Qreqrem) {
627 			respond(r, "Invalid connection");
628 			return;
629 		}
630 		cnum = 0;
631 		sc = nil;
632 	} else {
633 		cnum = qidpath & Chanmask;
634 		sc = c->chans[cnum];
635 	}
636 	switch ((ulong)(qidpath & Qtypemask)) {
637 	case Qctl:
638 	case Qlisten:
639 		if (r->ifcall.offset != 0) {
640 			respond(r, nil);
641 			break;
642 		}
643 		switch (lev) {
644 		case Top:
645 			readstr(r, st_names[c->state]);
646 			break;
647 		case Connection:
648 		case Subchannel:
649 			snprint(buf, sizeof buf, "%d", lev == Connection?
650 				xconn: cnum);
651 			readstr(r, buf);
652 			break;
653 		default:
654 			snprint(buf, sizeof buf, "stread error, level %d", lev);
655 			respond(r, buf);
656 			return;
657 		}
658 		respond(r, nil);
659 		break;
660 	case Qclone:
661 		if (r->ifcall.offset != 0) {
662 			respond(r, nil);
663 			break;
664 		}
665 		readstr(r, "Congratulations, you've achieved the impossible\n");
666 		respond(r, nil);
667 		break;
668 	case Qdata:
669 		if (lev == Top) {
670 			respond(r, nil);
671 			break;
672 		}
673 		if (lev == Connection) {
674 			if (0 && c->stifle) {	/* was for coexistence */
675 				c->stifle = 0;
676 				if (deferredinit(c) < 0) {
677 					respond(r, "deferredinit failed");
678 					break;
679 				}
680 			}
681 			if (c->cap)			/* auth capability? */
682 				readstr(r, c->cap);
683 			respond(r, nil);
684 			break;
685 		}
686 
687 		r->aux = (void *)threadcreate(readdata, r, Defstk);
688 		break;
689 	case Qlocal:
690 		if (lev == Connection)
691 			if (c->ctlfd < 0)
692 				readstr(r, "::!0\n");
693 			else {
694 				n = pread(c->ctlfd, buf, 10, 0); // magic 10
695 				buf[n >= 0? n: 0] = '\0';
696 				snprint(path, sizeof path, "%s/tcp/%s/local",
697 					mntpt, buf);
698 				readfile(path, buf, sizeof buf);
699 				readstr(r, buf);
700 			}
701 		respond(r, nil);
702 		break;
703 	case Qreqrem:
704 		r->aux = (void *)threadcreate(readreqrem, r, Defstk);
705 		break;
706 	case Qstatus:
707 		switch (lev) {
708 		case Top:
709 			readstr(r, "Impossible");
710 			break;
711 		case Connection:
712 			readstr(r, (uint)c->state > Closed?
713 				"Unknown": st_names[c->state]);
714 			break;
715 		case Subchannel:
716 			readstr(r, (uint)sc->state > Closed?
717 				"Unknown": st_names[sc->state]);
718 			break;
719 		}
720 		respond(r, nil);
721 		break;
722 	case Qtcp:
723 		/* connection number of underlying tcp connection */
724 		if (lev == Connection)
725 			if (c->ctlfd < 0)
726 				readstr(r, "-1\n");
727 			else {
728 				n = pread(c->ctlfd, buf, 10, 0); /* magic 10 */
729 				buf[n >= 0? n: 0] = '\0';
730 				readstr(r, buf);
731 			}
732 		respond(r, nil);
733 		break;
734 	default:
735 		respond(r, nil);
736 		break;
737 	}
738 }
739 
740 void
readreqrem(void * a)741 readreqrem(void *a)
742 {
743 	Ioproc *io;
744 	Req *r;
745 	Conn *c;
746 	SSHChan *sc;
747 	int fd, n, lev, cnum, xconn;
748 	uvlong qidpath;
749 	char buf[Arbbufsz], path[NETPATHLEN];
750 
751 	threadsetname("readreqrem");
752 	r = a;
753 	qidpath = (uvlong)r->fid->file->aux;
754 	lev = qidpath >> Levshift;
755 	xconn = (qidpath >> Connshift) & Connmask;
756 	c = connections[xconn];
757 	if (c == nil) {
758 		if (lev != Top) {
759 			respond(r, "Invalid connection");
760 			return;
761 		}
762 		sc = nil;
763 	} else {
764 		cnum = qidpath & Chanmask;
765 		sc = c->chans[cnum];
766 	}
767 	switch (lev) {
768 	case Top:
769 		if (r->ifcall.offset == 0 && keymbox.state != Empty) {
770 			r->aux = 0;
771 			respond(r, "Key file collision");	/* WTF? */
772 			break;
773 		}
774 		if (r->ifcall.offset != 0) {
775 			readstr(r, keymbox.msg);
776 			r->aux = 0;
777 			respond(r, nil);
778 			if (r->ifcall.offset + r->ifcall.count >=
779 			    strlen(keymbox.msg))
780 				keymbox.state = Empty;
781 			else
782 				keymbox.state = Allocated;
783 			break;
784 		}
785 		keymbox.state = Allocated;
786 		for(;;) {
787 			if (keymbox.msg == nil)
788 				if (recv(keymbox.mchan, nil) < 0) {
789 					r->aux = 0;
790 					responderror(r);
791 					keymbox.state = Empty;
792 					threadexits(nil);
793 				}
794 			if (keymbox.state == Empty)
795 				break;
796 			else if (keymbox.state == Allocated) {
797 				if (keymbox.msg) {
798 					readstr(r, keymbox.msg);
799 					if (r->ifcall.offset + r->ifcall.count
800 					    >= strlen(keymbox.msg)) {
801 						free(keymbox.msg);
802 						keymbox.msg = nil;
803 						keymbox.state = Empty;
804 					}
805 				}
806 				break;
807 			}
808 		}
809 		r->aux = 0;
810 		respond(r, nil);
811 		break;
812 	case Connection:
813 		if (c->ctlfd >= 0) {
814 			io = ioproc();
815 			seek(c->ctlfd, 0, 0);
816 			n = ioread(io, c->ctlfd, buf, 10); /* magic 10 */
817 			if (n < 0) {
818 				r->aux = 0;
819 				responderror(r);
820 				closeioproc(io);
821 				break;
822 			}
823 			buf[n] = '\0';
824 			snprint(path, NETPATHLEN, "%s/tcp/%s/remote", mntpt, buf);
825 			if ((fd = ioopen(io, path, OREAD)) < 0 ||
826 			    (n = ioread(io, fd, buf, Arbbufsz - 1)) < 0) {
827 				r->aux = 0;
828 				responderror(r);
829 				if (fd >= 0)
830 					ioclose(io, fd);
831 				closeioproc(io);
832 				break;
833 			}
834 			ioclose(io, fd);
835 			closeioproc(io);
836 			buf[n] = '\0';
837 			readstr(r, buf);
838 		} else
839 			readstr(r, "::!0\n");
840 		r->aux = 0;
841 		respond(r, nil);
842 		break;
843 	case Subchannel:
844 		if ((sc->state == Closed || sc->state == Closing ||
845 		    sc->state == Eof) && sc->reqq == nil && sc->dataq == nil) {
846 			sshdebug(c, "sending EOF1 to channel request listener");
847 			r->aux = 0;
848 			respond(r, nil);
849 			break;
850 		}
851 		while (sc->reqq == nil) {
852 			if (recv(sc->reqchan, nil) < 0) {
853 				r->aux = 0;
854 				responderror(r);
855 				threadexits(nil);
856 			}
857 			if ((sc->state == Closed || sc->state == Closing ||
858 			    sc->state == Eof) && sc->reqq == nil &&
859 			    sc->dataq == nil) {
860 				sshdebug(c, "sending EOF2 to channel request "
861 					"listener");
862 				respexit(c, r, nil, nil);
863 			}
864 		}
865 		n = r->ifcall.count;
866 		if (sc->reqq->rem < n)
867 			n = sc->reqq->rem;
868 		if (n > Maxrpcbuf)
869 			n = Maxrpcbuf;
870 		r->ifcall.offset = 0;
871 		readbuf(r, sc->reqq->st, n);
872 		sc->reqq->st += n;
873 		sc->reqq->rem -= n;
874 		if (sc->reqq->rem <= 0) {
875 			Plist *d = sc->reqq;
876 			sc->reqq = sc->reqq->next;
877 			free(d->pack);
878 			free(d);
879 		}
880 		r->aux = 0;
881 		respond(r, nil);
882 		break;
883 	}
884 	threadexits(nil);
885 }
886 
887 void
readdata(void * a)888 readdata(void *a)
889 {
890 	Req *r;
891 	Conn *c;
892 	SSHChan *sc;
893 	int cnum, xconn;
894 	uvlong qidpath;
895 
896 	threadsetname("readdata");
897 	r = a;
898 	qidpath = (uvlong)r->fid->file->aux;
899 	xconn = (qidpath >> Connshift) & Connmask;
900 	c = connections[xconn];
901 	if (c == nil) {
902 		respond(r, "bad connection");
903 		sshlog(c, "bad connection");
904 		threadexits(nil);
905 	}
906 	cnum = qidpath & Chanmask;
907 	sc = c->chans[cnum];
908 	if (sc->dataq == nil && (sc->state == Closed || sc->state == Closing ||
909 	    sc->state == Eof)) {
910 		sshdebug(c, "sending EOF1 to channel listener");
911 		r->aux = 0;
912 		respond(r, nil);
913 		threadexits(nil);
914 	}
915 	if (sc->dataq != nil) {
916 		getdata(c, sc, r);
917 		threadexits(nil);
918 	}
919 	while (sc->dataq == nil) {
920 		if (recv(sc->inchan, nil) < 0) {
921 			sshdebug(c, "got interrupt/error in readdata %r");
922 			r->aux = 0;
923 			responderror(r);
924 			threadexits(nil);
925 		}
926 		if (sc->dataq == nil && (sc->state == Closed ||
927 		    sc->state == Closing || sc->state == Eof)) {
928 			sshdebug(c, "sending EOF2 to channel listener");
929 			r->aux = 0;
930 			respond(r, nil);
931 			threadexits(nil);
932 		}
933 	}
934 	getdata(c, sc, r);
935 	threadexits(nil);
936 }
937 
938 void
stwrite(Req * r)939 stwrite(Req *r)
940 {
941 	Conn *c;
942 	SSHChan *ch;
943 	int lev, xconn;
944 	uvlong qidpath;
945 
946 	threadsetname("stwrite");
947 	qidpath = (uvlong)r->fid->file->aux;
948 	lev = qidpath >> Levshift;
949 	xconn = (qidpath >> Connshift) & Connmask;
950 	c = connections[xconn];
951 	if (c == nil) {
952 		respond(r, "invalid connection");
953 		return;
954 	}
955 	ch = c->chans[qidpath & Chanmask];
956 	switch ((ulong)(qidpath & Qtypemask)) {
957 	case Qclone:
958 	case Qctl:
959 		r->aux = (void *)threadcreate(writectlproc, r, Defstk);
960 		break;
961 	case Qdata:
962 		r->ofcall.count = r->ifcall.count;
963 		if (lev == Top || lev == Connection ||
964 		    c->state == Closed || c->state == Closing ||
965 		    ch->state == Closed || ch->state == Closing) {
966 			respond(r, nil);
967 			break;
968 		}
969 		if (0 && c->stifle) {		/* was for coexistence */
970 			c->stifle = 0;
971 			if (deferredinit(c) < 0) {
972 				respond(r, "deferredinit failed");
973 				break;
974 			}
975 		}
976 		r->aux = (void *)threadcreate(writedataproc, r, Defstk);
977 		break;
978 	case Qreqrem:
979 		r->aux = (void *)threadcreate(writereqremproc, r, Defstk);
980 		break;
981 	default:
982 		respond(r, nil);
983 		break;
984 	}
985 }
986 
987 static int
dialbyhand(Conn * c,int ntok,char * toks[])988 dialbyhand(Conn *c, int ntok, char *toks[])
989 {
990 	/*
991 	 * this uses /net/tcp to connect directly.
992 	 * should use dial(2) instead of doing it by hand.
993 	 */
994 	sshdebug(c, "tcp connect %s %s", toks[1], ntok > 3? toks[2]: "");
995 	return fprint(c->ctlfd, "connect %s %s", toks[1], ntok > 3? toks[2]: "");
996 }
997 
998 static void
userauth(Conn * c,Req * r,char * buf,int ntok,char * toks[])999 userauth(Conn *c, Req *r, char *buf, int ntok, char *toks[])
1000 {
1001 	int n;
1002 	char *attrs[5];
1003 	Packet *p;
1004 
1005 	if (ntok < 3 || ntok > 4)
1006 		respexit(c, r, buf, "bad connect command");
1007 	if (!c->service)
1008 		c->service = estrdup9p(toks[0]);
1009 	if (c->user)
1010 		free(c->user);
1011 	c->user = estrdup9p(toks[2]);
1012 	sshdebug(c, "userauth for user %s", c->user);
1013 
1014 	if (ntok == 4 && strcmp(toks[1], "k") == 0) {
1015 		if (c->authkey) {
1016 			free(c->authkey);
1017 			c->authkey = nil;
1018 		}
1019 		if (c->password)
1020 			free(c->password);
1021 		c->password = estrdup9p(toks[3]);
1022 		sshdebug(c, "userauth got password");
1023 	} else {
1024 		if (c->password) {
1025 			free(c->password);
1026 			c->password = nil;
1027 		}
1028 		memset(attrs, 0, sizeof attrs);
1029 		attrs[0] = "proto=rsa";
1030 		attrs[1] = "!dk?";
1031 		attrs[2] = smprint("user=%s", c->user);
1032 		attrs[3] = smprint("sys=%s", c->remote);
1033 		if (c->authkey)
1034 			free(c->authkey);
1035 		sshdebug(c, "userauth trying rsa");
1036 		if (ntok == 3)
1037 			c->authkey = factlookup(4, 2, attrs);
1038 		else {
1039 			attrs[4] = toks[3];
1040 			c->authkey = factlookup(5, 2, attrs);
1041 		}
1042 		free(attrs[2]);
1043 		free(attrs[3]);
1044 	}
1045 
1046 	if (!c->password && !c->authkey)
1047 		respexit(c, r, buf, "no auth info");
1048 	else if (c->state != Authing) {
1049 		p = new_packet(c);
1050 		add_byte(p, SSH_MSG_SERVICE_REQUEST);
1051 		add_string(p, c->service);
1052 		n = finish_packet(p);
1053 		sshdebug(c, "sending msg svc req for %s", c->service);
1054 		if (writeio(c->dio, c->datafd, p->nlength, n) != n) {
1055 			sshdebug(c, "authing write failed: %r");
1056 			free(p);
1057 			r->aux = 0;
1058 			responderror(r);
1059 			free(buf);
1060 			threadexits(nil);
1061 		}
1062 		free(p);
1063 	} else
1064 		if (client_auth(c, c->dio) < 0)
1065 			respexit(c, r, buf, "ssh-userauth client auth failed");
1066 	qlock(&c->l);
1067 	if (c->state != Established) {
1068 		sshdebug(c, "sleeping for auth");
1069 		rsleep(&c->r);
1070 	}
1071 	qunlock(&c->l);
1072 	if (c->state != Established)
1073 		respexit(c, r, buf, "ssh-userath auth failed (not Established)");
1074 }
1075 
1076 void
writectlproc(void * a)1077 writectlproc(void *a)
1078 {
1079 	Req *r;
1080 	Packet *p;
1081 	Conn *c;
1082 	SSHChan *ch;
1083 	char *tcpconn2, *buf, *toks[4];
1084 	int n, ntok, lev, xconn;
1085 	uvlong qidpath;
1086 	char path[NETPATHLEN], tcpconn[Numbsz];
1087 
1088 	threadsetname("writectlproc");
1089 	r = a;
1090 	qidpath = (uvlong)r->fid->file->aux;
1091 	lev = qidpath >> Levshift;
1092 	xconn = (qidpath >> Connshift) & Connmask;
1093 
1094 	c = connections[xconn];
1095 	if (c == nil) {
1096 		respond(r, "bad connection");
1097 		sshlog(c, "bad connection");
1098 		threadexits(nil);
1099 	}
1100 	ch = c->chans[qidpath & Chanmask];
1101 
1102 	if (r->ifcall.count <= Numbsz)
1103 		buf = emalloc9p(Numbsz + 1);
1104 	else
1105 		buf = emalloc9p(r->ifcall.count + 1);
1106 	memmove(buf, r->ifcall.data, r->ifcall.count);
1107 	buf[r->ifcall.count] = '\0';
1108 
1109 	sshdebug(c, "level %d writectl: %s", lev, buf);
1110 	ntok = tokenize(buf, toks, nelem(toks));
1111 	switch (lev) {
1112 	case Connection:
1113 		if (strcmp(toks[0], "id") == 0) {	/* was for sshswitch */
1114 			if (ntok < 2)
1115 				respexit(c, r, buf, "bad id request");
1116 			strncpy(c->idstring, toks[1], sizeof c->idstring);
1117 			sshdebug(c, "id %s", toks[1]);
1118 			break;
1119 		}
1120 		if (strcmp(toks[0], "connect") == 0) {
1121 			if (ntok < 2)
1122 				respexit(c, r, buf, "bad connect request");
1123 			/*
1124 			 * should use dial(2) instead of doing it by hand.
1125 			 */
1126 			memset(tcpconn, '\0', sizeof(tcpconn));
1127 			pread(c->ctlfd, tcpconn, sizeof tcpconn, 0);
1128 			dialbyhand(c, ntok, toks);
1129 
1130 			c->role = Client;
1131 			/* Override the PKA list; we can take any in */
1132 			pkas[0] = &rsa_pka;
1133 			pkas[1] = &dss_pka;
1134 			pkas[2] = nil;
1135 			tcpconn2 = estrdup9p(tcpconn);
1136 
1137 			/* swap id strings, negotiate crypto */
1138 			if (dohandshake(c, tcpconn2) < 0) {
1139 				sshlog(c, "connect handshake failed: "
1140 					"tcp conn %s", tcpconn2);
1141 				free(tcpconn2);
1142 				respexit(c, r, buf, "connect handshake failed");
1143 			}
1144 			free(tcpconn2);
1145 			keymbox.state = Empty;
1146 			nbsendul(keymbox.mchan, 1);
1147 			break;
1148 		}
1149 
1150 		if (c->state == Closed || c->state == Closing)
1151 			respexit(c, r, buf, "connection closed");
1152 		if (strcmp(toks[0], "ssh-userauth") == 0)
1153 			userauth(c, r, buf, ntok, toks);
1154 		else if (strcmp(toks[0], "ssh-connection") == 0) {
1155 			/* your ad here */
1156 		} else if (strcmp(toks[0], "hangup") == 0) {
1157 			if (c->rpid >= 0)
1158 				threadint(c->rpid);
1159 			shutdown(c);
1160 		} else if (strcmp(toks[0], "announce") == 0) {
1161 			sshdebug(c, "got %s argument for announce", toks[1]);
1162 			write(c->ctlfd, r->ifcall.data, r->ifcall.count);
1163 		} else if (strcmp(toks[0], "accept") == 0) {
1164 			/* should use dial(2) instead of diddling /net/tcp */
1165 			memset(tcpconn, '\0', sizeof(tcpconn));
1166 			pread(c->ctlfd, tcpconn, sizeof tcpconn, 0);
1167 			fprint(c->ctlfd, "accept %s", tcpconn);
1168 
1169 			c->role = Server;
1170 			tcpconn2 = estrdup9p(tcpconn);
1171 			/* swap id strings, negotiate crypto */
1172 			if (dohandshake(c, tcpconn2) < 0) {
1173 				sshlog(c, "accept handshake failed: "
1174 					"tcp conn %s", tcpconn2);
1175 				free(tcpconn2);
1176 				shutdown(c);
1177 				respexit(c, r, buf, "accept handshake failed");
1178 			}
1179 			free(tcpconn2);
1180 		} else if (strcmp(toks[0], "reject") == 0) {
1181 			memset(tcpconn, '\0', sizeof(tcpconn));
1182 			pread(c->ctlfd, tcpconn, sizeof tcpconn, 0);
1183 
1184 			snprint(path, NETPATHLEN, "%s/tcp/%s/data", mntpt, tcpconn);
1185 			c->datafd = open(path, ORDWR);
1186 
1187 			p = new_packet(c);
1188 			add_byte(p, SSH_MSG_DISCONNECT);
1189 			add_byte(p, SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT);
1190 			add_string(p, toks[2]);
1191 			add_string(p, "EN");
1192 			n = finish_packet(p);
1193 			if (c->dio && c->datafd >= 0)
1194 				iowrite(c->dio, c->datafd, p->nlength, n);
1195 			free(p);
1196 			if (c->ctlfd >= 0)
1197 				fprint(c->ctlfd, "reject %s %s", buf, toks[2]);
1198 			if (c->rpid >= 0)
1199 				threadint(c->rpid);
1200 			shutdown(c);
1201 		}
1202 		break;
1203 	case Subchannel:
1204 		if (c->state == Closed || c->state == Closing)
1205 			respexit(c, r, buf, "channel closed");
1206 		if (strcmp(toks[0], "connect") == 0) {
1207 			p = new_packet(c);
1208 			add_byte(p, SSH_MSG_CHANNEL_OPEN);
1209 			sshdebug(c, "chan writectl: connect %s",
1210 				ntok > 1? toks[1]: "session");
1211 			add_string(p, ntok > 1? toks[1]: "session");
1212 			add_uint32(p, ch->id);
1213 			add_uint32(p, Maxpayload);
1214 			add_uint32(p, Maxrpcbuf);
1215 			/* more stuff if it's an x11 session */
1216 			n = finish_packet(p);
1217 			iowrite(c->dio, c->datafd, p->nlength, n);
1218 			free(p);
1219 			qlock(&c->l);
1220 			if (ch->otherid == -1)
1221 				rsleep(&ch->r);
1222 			qunlock(&c->l);
1223 		} else if (strcmp(toks[0], "global") == 0) {
1224 			/* your ad here */
1225 		} else if (strcmp(toks[0], "hangup") == 0) {
1226 			if (ch->state != Closed && ch->state != Closing) {
1227 				ch->state = Closing;
1228 				if (ch->otherid != -1) {
1229 					p = new_packet(c);
1230 					add_byte(p, SSH_MSG_CHANNEL_CLOSE);
1231 					add_uint32(p, ch->otherid);
1232 					n = finish_packet(p);
1233 					iowrite(c->dio, c->datafd, p->nlength, n);
1234 					free(p);
1235 				}
1236 				qlock(&c->l);
1237 				rwakeup(&ch->r);
1238 				qunlock(&c->l);
1239 				nbsendul(ch->inchan, 1);
1240 				nbsendul(ch->reqchan, 1);
1241 			}
1242 			for (n = 0; n < MAXCONN && (c->chans[n] == nil ||
1243 			    c->chans[n]->state == Empty ||
1244 			    c->chans[n]->state == Closing ||
1245 			    c->chans[n]->state == Closed); ++n)
1246 				;
1247 			if (n >= MAXCONN) {
1248 				if (c->rpid >= 0)
1249 					threadint(c->rpid);
1250 				shutdown(c);
1251 			}
1252 		} else if (strcmp(toks[0], "announce") == 0) {
1253 			sshdebug(c, "got argument `%s' for chan announce",
1254 				toks[1]);
1255 			free(ch->ann);
1256 			ch->ann = estrdup9p(toks[1]);
1257 		}
1258 		break;
1259 	}
1260 	r->ofcall.count = r->ifcall.count;
1261 	r->aux = 0;
1262 	respond(r, nil);
1263 	free(buf);
1264 	threadexits(nil);
1265 }
1266 
1267 void
writereqremproc(void * a)1268 writereqremproc(void *a)
1269 {
1270 	Req *r;
1271 	Packet *p;
1272 	Conn *c;
1273 	SSHChan *ch;
1274 	char *cmd, *q, *buf, *toks[4];
1275 	int n, ntok, lev, xconn;
1276 	uvlong qidpath;
1277 
1278 	threadsetname("writereqremproc");
1279 	r = a;
1280 	qidpath = (uvlong)r->fid->file->aux;
1281 	lev = qidpath >> Levshift;
1282 	xconn = (qidpath >> Connshift) & Connmask;
1283 	c = connections[xconn];
1284 	if (c == nil) {
1285 		respond(r, "Invalid connection");
1286 		threadexits(nil);
1287 	}
1288 	ch = c->chans[qidpath & Chanmask];
1289 	if (r->ifcall.count <= 10)
1290 		buf = emalloc9p(10 + 1);
1291 	else
1292 		buf = emalloc9p(r->ifcall.count + 1);
1293 	memmove(buf, r->ifcall.data, r->ifcall.count);
1294 	buf[r->ifcall.count] = '\0';
1295 	sshdebug(c, "writereqrem: %s", buf);
1296 	ntok = tokenize(buf, toks, nelem(toks));
1297 
1298 	if (lev == Top) {
1299 		free(keymbox.msg);
1300 		keymbox.msg = buf;
1301 		nbsendul(keymbox.mchan, 1);
1302 		r->ofcall.count = r->ifcall.count;
1303 		respexit(c, r, nil, nil);
1304 	}
1305 
1306 	r->ofcall.count = r->ifcall.count;
1307 	if (c->state == Closed  || c->state == Closing ||
1308 	    ch->state == Closed || ch->state == Closing)
1309 		respexit(c, r, buf, nil);
1310 
1311 	p = new_packet(c);
1312 	if (strcmp(toks[0], "success") == 0) {
1313 		add_byte(p, SSH_MSG_CHANNEL_SUCCESS);
1314 		add_uint32(p, ch->otherid);
1315 	} else if (strcmp(toks[0], "failure") == 0) {
1316 		add_byte(p, SSH_MSG_CHANNEL_FAILURE);
1317 		add_uint32(p, ch->otherid);
1318 	} else if (strcmp(toks[0], "close") == 0) {
1319 		ch->state = Closing;
1320 		add_byte(p, SSH_MSG_CHANNEL_CLOSE);
1321 		add_uint32(p, ch->otherid);
1322 	} else if (strcmp(toks[0], "shell") == 0) {
1323 		ch->state = Established;
1324 		/*
1325 		 * Some servers *cough*OpenSSH*cough* don't seem to be able
1326 		 * to intelligently handle a shell with no pty.
1327 		 */
1328 		add_byte(p, SSH_MSG_CHANNEL_REQUEST);
1329 		add_uint32(p, ch->otherid);
1330 		add_string(p, "pty-req");
1331 		add_byte(p, 0);
1332 		if (ntok == 1)
1333 			add_string(p, "dumb");
1334 		else
1335 			add_string(p, toks[1]);
1336 		add_uint32(p, 0);
1337 		add_uint32(p, 0);
1338 		add_uint32(p, 0);
1339 		add_uint32(p, 0);
1340 		add_string(p, "");
1341 		n = finish_packet(p);
1342 		iowrite(c->dio, c->datafd, p->nlength, n);
1343 		init_packet(p);
1344 		p->c = c;
1345 		add_byte(p, SSH_MSG_CHANNEL_REQUEST);
1346 		add_uint32(p, ch->otherid);
1347 		add_string(p, "shell");
1348 		add_byte(p, 0);
1349 		sshdebug(c, "sending shell request: rlength=%lud twindow=%lud",
1350 			p->rlength, ch->twindow);
1351 	} else if (strcmp(toks[0], "exec") == 0) {
1352 		ch->state = Established;
1353 		add_byte(p, SSH_MSG_CHANNEL_REQUEST);
1354 		add_uint32(p, ch->otherid);
1355 		add_string(p, "exec");
1356 		add_byte(p, 0);
1357 
1358 		cmd = emalloc9p(Bigbufsz);
1359 		q = seprint(cmd, cmd+Bigbufsz, "%s", toks[1]);
1360 		for (n = 2; n < ntok; ++n) {
1361 			q = seprint(q, cmd+Bigbufsz, " %q", toks[n]);
1362 			if (q == nil)
1363 				break;
1364 		}
1365 		add_string(p, cmd);
1366 		free(cmd);
1367 	} else
1368 		respexit(c, r, buf, "bad request command");
1369 	n = finish_packet(p);
1370 	iowrite(c->dio, c->datafd, p->nlength, n);
1371 	free(p);
1372 	respexit(c, r, buf, nil);
1373 }
1374 
1375 void
writedataproc(void * a)1376 writedataproc(void *a)
1377 {
1378 	Req *r;
1379 	Packet *p;
1380 	Conn *c;
1381 	SSHChan *ch;
1382 	int n, xconn;
1383 	uvlong qidpath;
1384 
1385 	threadsetname("writedataproc");
1386 	r = a;
1387 	qidpath = (uvlong)r->fid->file->aux;
1388 	xconn = (qidpath >> Connshift) & Connmask;
1389 	c = connections[xconn];
1390 	if (c == nil) {
1391 		respond(r, "Invalid connection");
1392 		threadexits(nil);
1393 	}
1394 	ch = c->chans[qidpath & Chanmask];
1395 
1396 	p = new_packet(c);
1397 	add_byte(p, SSH_MSG_CHANNEL_DATA);
1398 	hnputl(p->payload+1, ch->otherid);
1399 	p->rlength += 4;
1400 	add_block(p, r->ifcall.data, r->ifcall.count);
1401 	n = finish_packet(p);
1402 
1403 	if (ch->sent + p->rlength > ch->twindow) {
1404 		qlock(&ch->xmtlock);
1405 		while (ch->sent + p->rlength > ch->twindow)
1406 			rsleep(&ch->xmtrendez);
1407 		qunlock(&ch->xmtlock);
1408 	}
1409 	iowrite(c->dio, c->datafd, p->nlength, n);
1410 	respexit(c, r, p, nil);
1411 }
1412 
1413 /*
1414  * Although this is named stclunk, it's attached to the destroyfid
1415  * member of the Srv struct.  It turns out there's no member
1416  * called clunk.  But if there are no other references, a 9P Tclunk
1417  * will end up calling destroyfid.
1418  */
1419 void
stclunk(Fid * f)1420 stclunk(Fid *f)
1421 {
1422 	Packet *p;
1423 	Conn *c;
1424 	SSHChan *sc;
1425 	int n, lev, cnum, chnum;
1426 	uvlong qidpath;
1427 
1428 	threadsetname("stclunk");
1429 	if (f == nil || f->file == nil)
1430 		return;
1431 	qidpath = (uvlong)f->file->aux;
1432 	lev = qidpath >> Levshift;
1433 	cnum = (qidpath >> Connshift) & Connmask;
1434 	chnum = qidpath & Chanmask;
1435 	c = connections[cnum];
1436 	sshdebug(c, "got clunk on file: %#llux %d %d %d: %s",
1437 		qidpath, lev, cnum, chnum, f->file->name);
1438 	/* qidpath test implies conn 0, chan 0 */
1439 	if (lev == Top && qidpath == Qreqrem) {
1440 		if (keymbox.state != Empty) {
1441 			keymbox.state = Empty;
1442 			// nbsendul(keymbox.mchan, 1);
1443 		}
1444 		keymbox.msg = nil;
1445 		return;
1446 	}
1447 
1448 	if (c == nil)
1449 		return;
1450 	if (lev == Connection && (qidpath & Qtypemask) == Qctl &&
1451 	    (c->state == Opening || c->state == Negotiating ||
1452 	     c->state == Authing)) {
1453 		for (n = 0; n < MAXCONN && (!c->chans[n] ||
1454 		    c->chans[n]->state == Empty ||
1455 		    c->chans[n]->state == Closed ||
1456 		    c->chans[n]->state == Closing); ++n)
1457 			;
1458 		if (n >= MAXCONN) {
1459 			if (c->rpid >= 0)
1460 				threadint(c->rpid);
1461 			shutdown(c);
1462 		}
1463 		return;
1464 	}
1465 
1466 	sc = c->chans[chnum];
1467 	if (lev != Subchannel)
1468 		return;
1469 	if ((qidpath & Qtypemask) == Qlisten && sc->state == Listening) {
1470 		qlock(&c->l);
1471 		if (sc->state != Closed) {
1472 			sc->state = Closed;
1473 			chanclose(sc->inchan);
1474 			chanclose(sc->reqchan);
1475 		}
1476 		qunlock(&c->l);
1477 	} else if ((qidpath & Qtypemask) == Qdata && sc->state != Empty &&
1478 	    sc->state != Closed && sc->state != Closing) {
1479 		if (f->file != sc->data && f->file != sc->request) {
1480 			sshlog(c, "great evil is upon us; destroying a fid "
1481 				"we didn't create");
1482 			return;
1483 		}
1484 
1485 		p = new_packet(c);
1486 		add_byte(p, SSH_MSG_CHANNEL_CLOSE);
1487 		hnputl(p->payload+1, sc->otherid);
1488 		p->rlength += 4;
1489 		n = finish_packet(p);
1490 		sc->state = Closing;
1491 		iowrite(c->dio, c->datafd, p->nlength, n);
1492 		free(p);
1493 
1494 		qlock(&c->l);
1495 		rwakeup(&sc->r);
1496 		qunlock(&c->l);
1497 		nbsendul(sc->inchan, 1);
1498 		nbsendul(sc->reqchan, 1);
1499 	}
1500 	for (n = 0; n < MAXCONN && (!c->chans[n] ||
1501 	    c->chans[n]->state == Empty || c->chans[n]->state == Closed ||
1502 	    c->chans[n]->state == Closing); ++n)
1503 		;
1504 	if (n >= MAXCONN) {
1505 		if (c->rpid >= 0)
1506 			threadint(c->rpid);
1507 		shutdown(c);
1508 	}
1509 }
1510 
1511 void
stflush(Req * r)1512 stflush(Req *r)
1513 {
1514 	Req *or;
1515 	uvlong qidpath;
1516 
1517 	threadsetname("stflush");
1518 	or = r->oldreq;
1519 	qidpath = (uvlong)or->fid->file->aux;
1520 	sshdebug(nil, "got flush on file %#llux %lld %lld %lld: %s %#p",
1521 		argv0, qidpath, qidpath >> Levshift,
1522 		(qidpath >> Connshift) & Connmask, qidpath & Chanmask,
1523 		or->fid->file->name, or->aux);
1524 	if (!or->aux)
1525 		respond(or, "interrupted");
1526 	else if (or->ifcall.type == Topen && (qidpath & Qtypemask) == Qlisten ||
1527 	    or->ifcall.type == Tread && (qidpath & Qtypemask) == Qdata &&
1528 	    (qidpath >> Levshift) == Subchannel ||
1529 	    or->ifcall.type == Tread && (qidpath & Qtypemask) == Qreqrem)
1530 		threadint((uintptr)or->aux);
1531 	else {
1532 		threadkill((uintptr)or->aux);
1533 		or->aux = 0;
1534 		respond(or, "interrupted");
1535 	}
1536 	respond(r, nil);
1537 }
1538 
1539 void
filedup(Req * r,File * src)1540 filedup(Req *r, File *src)
1541 {
1542 	r->ofcall.qid = src->qid;
1543 	closefile(r->fid->file);
1544 	r->fid->file = src;
1545 	incref(src);
1546 }
1547 
1548 Conn *
alloc_conn(void)1549 alloc_conn(void)
1550 {
1551 	int slevconn, i, s, firstnil;
1552 	char buf[Numbsz];
1553 	Conn *c;
1554 	static QLock aclock;
1555 
1556 	qlock(&aclock);
1557 	firstnil = -1;
1558 	for (i = 0; i < MAXCONN; ++i) {
1559 		if (connections[i] == nil) {
1560 			if (firstnil == -1)
1561 				firstnil = i;
1562 			continue;
1563 		}
1564 		s = connections[i]->state;
1565 		if (s == Empty || s == Closed)
1566 			break;
1567 	}
1568 	if (i >= MAXCONN) {
1569 		if (firstnil == -1) {		/* all slots in use? */
1570 			qunlock(&aclock);
1571 			return nil;
1572 		}
1573 		/* no reusable slots, allocate a new Conn */
1574 		connections[firstnil] = emalloc9p(sizeof(Conn));
1575 		memset(connections[firstnil], 0, sizeof(Conn));
1576 		i = firstnil;
1577 	}
1578 
1579 	c = connections[i];
1580 	memset(&c->r, '\0', sizeof(Rendez));
1581 	c->r.l = &c->l;
1582 	c->dio = ioproc();
1583 	c->rio = nil;
1584 	c->state = Allocated;
1585 	c->role = Server;
1586 	c->id = i;
1587 	c->stifle = c->poisoned = 0;
1588 	c->user = c->service = nil;
1589 	c->inseq = c->nchan = c->outseq = 0;
1590 	c->cscrypt = c->csmac = c->ctlfd = c->datafd = c->decrypt =
1591 		c->encrypt = c->inmac = c->ncscrypt = c->ncsmac =
1592 		c->nsccrypt = c->nscmac = c->outmac = c->rpid = c->sccrypt =
1593 		c->scmac = c->tcpconn = -1;
1594 	if (c->e) {
1595 		mpfree(c->e);
1596 		c->e = nil;
1597 	}
1598 	if (c->x) {
1599 		mpfree(c->x);
1600 		c->x = nil;
1601 	}
1602 
1603 	snprint(buf, sizeof buf, "%d", i);
1604 	if (c->dir == nil) {
1605 		slevconn = Connection << Levshift | i << Connshift;
1606 		c->dir = createfile(rootfile, buf, uid, 0555|DMDIR,
1607 			(void *)(slevconn | Qroot));
1608 		c->clonefile = createfile(c->dir, "clone", uid, 0666,
1609 			(void *)(slevconn | Qclone));
1610 		c->ctlfile = createfile(c->dir, "ctl", uid, 0666,
1611 			(void *)(slevconn | Qctl));
1612 		c->datafile = createfile(c->dir, "data", uid, 0666,
1613 			(void *)(slevconn | Qdata));
1614 		c->listenfile = createfile(c->dir, "listen", uid, 0666,
1615 			(void *)(slevconn | Qlisten));
1616 		c->localfile = createfile(c->dir, "local", uid, 0444,
1617 			(void *)(slevconn | Qlocal));
1618 		c->remotefile = createfile(c->dir, "remote", uid, 0444,
1619 			(void *)(slevconn | Qreqrem));
1620 		c->statusfile = createfile(c->dir, "status", uid, 0444,
1621 			(void *)(slevconn | Qstatus));
1622 		c->tcpfile = createfile(c->dir, "tcp", uid, 0444,
1623 			(void *)(slevconn | Qtcp));
1624 	}
1625 //	c->skexinit = c->rkexinit = nil;
1626 	c->got_sessid = 0;
1627 	c->otherid = nil;
1628 	c->inik = c->outik = nil;
1629 	c->s2ccs = c->c2scs = c->enccs = c->deccs = nil;
1630 	qunlock(&aclock);
1631 	return c;
1632 }
1633 
1634 SSHChan *
alloc_chan(Conn * c)1635 alloc_chan(Conn *c)
1636 {
1637 	int cnum, slcn;
1638 	char buf[Numbsz];
1639 	Plist *p, *next;
1640 	SSHChan *sc;
1641 
1642 	if (c->nchan >= MAXCONN)
1643 		return nil;
1644 	qlock(&c->l);
1645 	cnum = c->nchan;
1646 	if (c->chans[cnum] == nil) {
1647 		c->chans[cnum] = emalloc9p(sizeof(SSHChan));
1648 		memset(c->chans[cnum], 0, sizeof(SSHChan));
1649 	}
1650 	sc = c->chans[cnum];
1651 	snprint(buf, sizeof buf, "%d", cnum);
1652 	memset(&sc->r, '\0', sizeof(Rendez));
1653 	sc->r.l = &c->l;
1654 	sc->id = cnum;
1655 	sc->state = Empty;
1656 	sc->conn = c->id;
1657 	sc->otherid = sc->waker = -1;
1658 	sc->sent = sc->twindow = sc->rwindow = sc->inrqueue = 0;
1659 	sc->ann = nil;
1660 	sc->lreq = nil;
1661 
1662 	if (sc->dir == nil) {
1663 		slcn = Subchannel << Levshift | c->id << Connshift | cnum;
1664 		sc->dir = createfile(c->dir, buf, uid, 0555|DMDIR,
1665 			(void *)(slcn | Qroot));
1666 		sc->ctl = createfile(sc->dir, "ctl", uid, 0666,
1667 			(void *)(slcn | Qctl));
1668 		sc->data = createfile(sc->dir, "data", uid, 0666,
1669 			(void *)(slcn | Qdata));
1670 		sc->listen = createfile(sc->dir, "listen", uid, 0666,
1671 			(void *)(slcn | Qlisten));
1672 		sc->request = createfile(sc->dir, "request", uid, 0666,
1673 			(void *)(slcn | Qreqrem));
1674 		sc->status = createfile(sc->dir, "status", uid, 0444,
1675 			(void *)(slcn | Qstatus));
1676 		sc->tcp = createfile(sc->dir, "tcp", uid, 0444,
1677 			(void *)(slcn | Qtcp));
1678 	}
1679 	c->nchan++;
1680 
1681 	for (; sc->reqq != nil; sc->reqq = next) {
1682 		p = sc->reqq;
1683 		next = p->next;
1684 		free(p->pack);
1685 		free(p);
1686 	}
1687 	sc->dataq = sc->datatl = sc->reqtl = nil;
1688 
1689 	if (sc->inchan)
1690 		chanfree(sc->inchan);
1691 	sc->inchan = chancreate(4, 0);
1692 
1693 	if (sc->reqchan)
1694 		chanfree(sc->reqchan);
1695 	sc->reqchan = chancreate(4, 0);
1696 
1697 	memset(&sc->xmtrendez, '\0', sizeof(Rendez));
1698 	sc->xmtrendez.l = &sc->xmtlock;
1699 	qunlock(&c->l);
1700 	return sc;
1701 }
1702 
1703 static int
readlineio(Conn *,Ioproc * io,int fd,char * buf,int size)1704 readlineio(Conn *, Ioproc *io, int fd, char *buf, int size)
1705 {
1706 	int n;
1707 	char *p;
1708 
1709 	for (p = buf; p < buf + size - 1; p++) {
1710 		n = ioread(io, fd, p, 1);
1711 		if (n != 1 || *p == '\n') {
1712 			*p = '\0';
1713 			break;
1714 		}
1715 	}
1716 	return p - buf;
1717 }
1718 
1719 static char *
readremote(Conn * c,Ioproc * io,char * tcpconn)1720 readremote(Conn *c, Ioproc *io, char *tcpconn)
1721 {
1722 	int n, remfd;
1723 	char *p, *remote;
1724 	char path[Arbbufsz], buf[NETPATHLEN];
1725 
1726 	remote = nil;
1727 	snprint(path, sizeof path, "%s/tcp/%s/remote", mntpt, tcpconn);
1728 	remfd = ioopen(io, path, OREAD);
1729 	if (remfd < 0) {
1730 		sshlog(c, "readremote: can't open %s: %r", path);
1731 		return nil;
1732 	}
1733 	n = ioread(io, remfd, buf, sizeof buf - 1);
1734 	if (n > 0) {
1735 		buf[n] = 0;
1736 		p = strchr(buf, '!');
1737 		if (p)
1738 			*p = 0;
1739 		remote = estrdup9p(buf);
1740 	}
1741 	ioclose(io, remfd);
1742 	return remote;
1743 }
1744 
1745 static void
sendmyid(Conn * c,Ioproc * io)1746 sendmyid(Conn *c, Ioproc *io)
1747 {
1748 	char path[Arbbufsz];
1749 
1750 	snprint(path, sizeof path, "%s\r\n", MYID);
1751 	iowrite(io, c->datafd, path, strlen(path));
1752 }
1753 
1754 /* save and tidy up the remote id */
1755 static void
stashremid(Conn * c,char * remid)1756 stashremid(Conn *c, char *remid)
1757 {
1758 	char *nl;
1759 
1760 	if (c->otherid)
1761 		free(c->otherid);
1762 	c->otherid = estrdup9p(remid);
1763 
1764 	nl = strchr(c->otherid, '\n');
1765 	if (nl)
1766 		*nl = '\0';
1767 	nl = strchr(c->otherid, '\r');
1768 	if (nl)
1769 		*nl = '\0';
1770 }
1771 
1772 static void
hangupconn(Conn * c)1773 hangupconn(Conn *c)
1774 {
1775 	hangup(c->ctlfd);
1776 	close(c->ctlfd);
1777 	close(c->datafd);
1778 	c->ctlfd = c->datafd = -1;
1779 }
1780 
1781 #ifdef COEXIST
1782 static int
exchids(Conn * c,Ioproc * io,char * remid,int remsz)1783 exchids(Conn *c, Ioproc *io, char *remid, int remsz)
1784 {
1785 	int n;
1786 
1787 	/*
1788 	 * exchange versions.  server writes id, then reads;
1789 	 * client reads id then writes (in theory).
1790 	 */
1791 	if (c->role == Server) {
1792 		sendmyid(c, io);
1793 
1794 		n = readlineio(c, io, c->datafd, remid, remsz);
1795 		if (n < 5)		/* can't be a valid SSH id string */
1796 			return -1;
1797 		sshdebug(c, "dohandshake: server, got `%s', sent `%s'", remid,
1798 			MYID);
1799 	} else {
1800 		/* client: read server's id */
1801 		n = readlineio(c, io, c->datafd, remid, remsz);
1802 		if (n < 5)		/* can't be a valid SSH id string */
1803 			return -1;
1804 
1805 		sendmyid(c, io);
1806 		sshdebug(c, "dohandshake: client, got `%s' sent `%s'", remid, MYID);
1807 		if (remid[0] == '\0') {
1808 			sshlog(c, "dohandshake: client, empty remote id string;"
1809 				" out of sync");
1810 			return -1;
1811 		}
1812 	}
1813 	sshdebug(c, "remote id string `%s'", remid);
1814 	return 0;
1815 }
1816 
1817 /*
1818  * negotiate the protocols.
1819  * We don't do the full negotiation here, because we also have
1820  * to handle a re-negotiation request from the other end.
1821  * So we just kick it off and let the receiver process take it from there.
1822  */
1823 static int
negotiate(Conn * c)1824 negotiate(Conn *c)
1825 {
1826 	send_kexinit(c);
1827 
1828 	qlock(&c->l);
1829 	if ((c->role == Client && c->state != Negotiating) ||
1830 	    (c->role == Server && c->state != Established)) {
1831 		sshdebug(c, "awaiting establishment");
1832 		rsleep(&c->r);
1833 	}
1834 	qunlock(&c->l);
1835 
1836 	if (c->role == Server && c->state != Established ||
1837 	    c->role == Client && c->state != Negotiating) {
1838 		sshdebug(c, "failed to establish");
1839 		return -1;
1840 	}
1841 	sshdebug(c, "established; crypto now on");
1842 	return 0;
1843 }
1844 
1845 /* this was deferred when trying to make coexistence with v1 work */
1846 static int
deferredinit(Conn * c)1847 deferredinit(Conn *c)
1848 {
1849 	char remid[Arbbufsz];
1850 	Ioproc *io;
1851 
1852 	io = ioproc();
1853 	/*
1854 	 * don't bother checking the remote's id string.
1855 	 * as a client, we can cope with v1 if we don't verify the host key.
1856 	 */
1857 	if (exchids(c, io, remid, sizeof remid) < 0 ||
1858 	    0 && c->role == Client && strncmp(remid, "SSH-2", 5) != 0 &&
1859 	    strncmp(remid, "SSH-1.99", 8) != 0) {
1860 		/* not a protocol version we know; give up */
1861 		closeioproc(io);
1862 		hangupconn(c);
1863 		return -1;
1864 	}
1865 	closeioproc(io);
1866 	stashremid(c, remid);
1867 
1868 	c->state = Initting;
1869 
1870 	/* start the reader thread */
1871 	if (c->rpid < 0)
1872 		c->rpid = threadcreate(reader, c, Defstk);
1873 
1874 	return negotiate(c);
1875 }
1876 
1877 int
dohandshake(Conn * c,char * tcpconn)1878 dohandshake(Conn *c, char *tcpconn)
1879 {
1880 	int tcpdfd;
1881 	char *remote;
1882 	char path[Arbbufsz];
1883 	Ioproc *io;
1884 
1885 	io = ioproc();
1886 
1887 	/* read tcp conn's remote address into c->remote */
1888 	remote = readremote(c, io, tcpconn);
1889 	if (remote) {
1890 		free(c->remote);
1891 		c->remote = remote;
1892 	}
1893 
1894 	/* open tcp conn's data file */
1895 	c->tcpconn = atoi(tcpconn);
1896 	snprint(path, sizeof path, "%s/tcp/%s/data", mntpt, tcpconn);
1897 	tcpdfd = ioopen(io, path, ORDWR);
1898 	closeioproc(io);
1899 	if (tcpdfd < 0) {
1900 		sshlog(c, "dohandshake: can't open %s: %r", path);
1901 		return -1;
1902 	}
1903 	c->datafd = tcpdfd;		/* underlying tcp data descriptor */
1904 
1905 	return deferredinit(c);
1906 }
1907 #endif					/* COEXIST */
1908 
1909 int
dohandshake(Conn * c,char * tcpconn)1910 dohandshake(Conn *c, char *tcpconn)
1911 {
1912 	int fd, n;
1913 	char *p, *othid;
1914 	char path[Arbbufsz], buf[NETPATHLEN];
1915 	Ioproc *io;
1916 
1917 	io = ioproc();
1918 	snprint(path, sizeof path, "%s/tcp/%s/remote", mntpt, tcpconn);
1919 	fd = ioopen(io, path, OREAD);
1920 	n = ioread(io, fd, buf, sizeof buf - 1);
1921 	if (n > 0) {
1922 		buf[n] = 0;
1923 		p = strchr(buf, '!');
1924 		if (p)
1925 			*p = 0;
1926 		free(c->remote);
1927 		c->remote = estrdup9p(buf);
1928 	}
1929 	ioclose(io, fd);
1930 
1931 	snprint(path, sizeof path, "%s/tcp/%s/data", mntpt, tcpconn);
1932 	fd = ioopen(io, path, ORDWR);
1933 	if (fd < 0) {
1934 		closeioproc(io);
1935 		return -1;
1936 	}
1937 	c->datafd = fd;
1938 
1939 	/* exchange versions--we're only doing SSH2, unfortunately */
1940 
1941 	snprint(path, sizeof path, "%s\r\n", MYID);
1942 	if (c->idstring && c->idstring[0])
1943 		strncpy(path, c->idstring, sizeof path);
1944 	else {
1945 		iowrite(io, fd, path, strlen(path));
1946 		p = path;
1947 		n = 0;
1948 		do {
1949 			if (ioread(io, fd, p, 1) < 0) {
1950 				fprint(2, "%s: short read in ID exchange: %r\n",
1951 					argv0);
1952 				break;
1953 			}
1954 			++n;
1955 		} while (*p++ != '\n');
1956 		if (n < 5) {		/* can't be a valid SSH id string */
1957 			close(fd);
1958 			goto err;
1959 		}
1960 		*p = 0;
1961 	}
1962 	sshdebug(c, "id string `%s'", path);
1963 	if (c->idstring[0] == '\0' &&
1964 	    strncmp(path, "SSH-2", 5) != 0 &&
1965 	    strncmp(path, "SSH-1.99", 8) != 0) {
1966 		/* not a protocol version we know; give up */
1967 		ioclose(io, fd);
1968 		goto err;
1969 	}
1970 	closeioproc(io);
1971 
1972 	if (c->otherid)
1973 		free(c->otherid);
1974 	c->otherid = othid = estrdup9p(path);
1975 	for (n = strlen(othid) - 1; othid[n] == '\r' || othid[n] == '\n'; --n)
1976 		othid[n] = '\0';
1977 	c->state = Initting;
1978 
1979 	/* start the reader thread */
1980 	if (c->rpid < 0)
1981 		c->rpid = threadcreate(reader, c, Defstk);
1982 
1983 	/*
1984 	 * negotiate the protocols
1985 	 * We don't do the full negotiation here, because we also have
1986 	 * to handle a re-negotiation request from the other end.  So
1987 	 * we just kick it off and let the receiver process take it from there.
1988 	 */
1989 
1990 	send_kexinit(c);
1991 
1992 	qlock(&c->l);
1993 	if ((c->role == Client && c->state != Negotiating) ||
1994 	    (c->role == Server && c->state != Established))
1995 		rsleep(&c->r);
1996 	qunlock(&c->l);
1997 	if (c->role == Server && c->state != Established ||
1998 	    c->role == Client && c->state != Negotiating)
1999 		return -1;
2000 	return 0;
2001 err:
2002 	/* should use hangup in dial(2) instead of diddling /net/tcp */
2003 	snprint(path, sizeof path, "%s/tcp/%s/ctl", mntpt, tcpconn);
2004 	fd = ioopen(io, path, OWRITE);
2005 	iowrite(io, fd, "hangup", 6);
2006 	ioclose(io, fd);
2007 	closeioproc(io);
2008 	return -1;
2009 }
2010 
2011 void
send_kexinit(Conn * c)2012 send_kexinit(Conn *c)
2013 {
2014 	Packet *ptmp;
2015 	char *buf, *p, *e;
2016 	int i, msglen;
2017 
2018 	sshdebug(c, "initializing kexinit packet");
2019 	if (c->skexinit != nil)
2020 		free(c->skexinit);
2021 	c->skexinit = new_packet(c);
2022 
2023 	buf = emalloc9p(Bigbufsz);
2024 	buf[0] = (uchar)SSH_MSG_KEXINIT;
2025 
2026 	add_packet(c->skexinit, buf, 1);
2027 	for (i = 0; i < 16; ++i)
2028 		buf[i] = fastrand();
2029 
2030 	add_packet(c->skexinit, buf, 16);		/* cookie */
2031 	e = buf + Bigbufsz - 1;
2032 	p = seprint(buf, e, "%s", kexes[0]->name);
2033 	for (i = 1; i < nelem(kexes); ++i)
2034 		p = seprint(p, e, ",%s", kexes[i]->name);
2035 	sshdebug(c, "sent KEX algs: %s", buf);
2036 
2037 	add_string(c->skexinit, buf);		/* Key exchange */
2038 	if (pkas[0] == nil)
2039 		add_string(c->skexinit, "");
2040 	else{
2041 		p = seprint(buf, e, "%s", pkas[0]->name);
2042 		for (i = 1; i < nelem(pkas) && pkas[i] != nil; ++i)
2043 			p = seprint(p, e, ",%s", pkas[i]->name);
2044 		sshdebug(c, "sent host key algs: %s", buf);
2045 		add_string(c->skexinit, buf);		/* server's key algs */
2046 	}
2047 
2048 	p = seprint(buf, e, "%s", cryptos[0]->name);
2049 	for (i = 1; i < nelem(cryptos); ++i)
2050 		p = seprint(p, e, ",%s", cryptos[i]->name);
2051 	sshdebug(c, "sent crypto algs: %s", buf);
2052 
2053 	add_string(c->skexinit, buf);		/* c->s crypto */
2054 	add_string(c->skexinit, buf);		/* s->c crypto */
2055 	p = seprint(buf, e, "%s", macnames[0]);
2056 	for (i = 1; i < nelem(macnames); ++i)
2057 		p = seprint(p, e, ",%s", macnames[i]);
2058 	sshdebug(c, "sent MAC algs: %s", buf);
2059 
2060 	add_string(c->skexinit, buf);		/* c->s mac */
2061 	add_string(c->skexinit, buf);		/* s->c mac */
2062 	add_string(c->skexinit, "none");	/* c->s compression */
2063 	add_string(c->skexinit, "none");	/* s->c compression */
2064 	add_string(c->skexinit, "");		/* c->s languages */
2065 	add_string(c->skexinit, "");		/* s->c languages */
2066 	memset(buf, 0, 5);
2067 	add_packet(c->skexinit, buf, 5);
2068 
2069 	ptmp = new_packet(c);
2070 	memmove(ptmp, c->skexinit, sizeof(Packet));
2071 	msglen = finish_packet(ptmp);
2072 
2073 	if (c->dio && c->datafd >= 0)
2074 		iowrite(c->dio, c->datafd, ptmp->nlength, msglen);
2075 	free(ptmp);
2076 	free(buf);
2077 }
2078 
2079 static void
establish(Conn * c)2080 establish(Conn *c)
2081 {
2082 	qlock(&c->l);
2083 	c->state = Established;
2084 	rwakeup(&c->r);
2085 	qunlock(&c->l);
2086 }
2087 
2088 static int
negotiating(Conn * c,Packet * p,Packet * p2,char * buf,int size)2089 negotiating(Conn *c, Packet *p, Packet *p2, char *buf, int size)
2090 {
2091 	int i, n;
2092 
2093 	USED(size);
2094 	switch (p->payload[0]) {
2095 	case SSH_MSG_DISCONNECT:
2096 		if (debug) {
2097 			get_string(p, p->payload + 5, buf, Arbbufsz, nil);
2098 			sshdebug(c, "got disconnect: %s", buf);
2099 		}
2100 		return -1;
2101 	case SSH_MSG_NEWKEYS:
2102 		/*
2103 		 * If we're just updating, go straight to
2104 		 * established, otherwise wait for auth'n.
2105 		 */
2106 		i = c->encrypt;
2107 		memmove(c->c2siv, c->nc2siv, SHA1dlen*2);
2108 		memmove(c->s2civ, c->ns2civ, SHA1dlen*2);
2109 		memmove(c->c2sek, c->nc2sek, SHA1dlen*2);
2110 		memmove(c->s2cek, c->ns2cek, SHA1dlen*2);
2111 		memmove(c->c2sik, c->nc2sik, SHA1dlen*2);
2112 		memmove(c->s2cik, c->ns2cik, SHA1dlen*2);
2113 		c->cscrypt = c->ncscrypt;
2114 		c->sccrypt = c->nsccrypt;
2115 		c->csmac = c->ncsmac;
2116 		c->scmac = c->nscmac;
2117 		c->c2scs = cryptos[c->cscrypt]->init(c, 0);
2118 		c->s2ccs = cryptos[c->sccrypt]->init(c, 1);
2119 		if (c->role == Server) {
2120 			c->encrypt = c->sccrypt;
2121 			c->decrypt = c->cscrypt;
2122 			c->outmac = c->scmac;
2123 			c->inmac = c->csmac;
2124 			c->enccs = c->s2ccs;
2125 			c->deccs = c->c2scs;
2126 			c->outik = c->s2cik;
2127 			c->inik = c->c2sik;
2128 		} else{
2129 			c->encrypt = c->cscrypt;
2130 			c->decrypt = c->sccrypt;
2131 			c->outmac = c->csmac;
2132 			c->inmac = c->scmac;
2133 			c->enccs = c->c2scs;
2134 			c->deccs = c->s2ccs;
2135 			c->outik = c->c2sik;
2136 			c->inik = c->s2cik;
2137 		}
2138 		sshdebug(c, "using %s for encryption and %s for decryption",
2139 			cryptos[c->encrypt]->name, cryptos[c->decrypt]->name);
2140 		qlock(&c->l);
2141 		if (i != -1)
2142 			c->state = Established;
2143 		if (c->role == Client)
2144 			rwakeup(&c->r);
2145 		qunlock(&c->l);
2146 		break;
2147 	case SSH_MSG_KEXDH_INIT:
2148 		kexes[c->kexalg]->serverkex(c, p);
2149 		break;
2150 	case SSH_MSG_KEXDH_REPLY:
2151 		init_packet(p2);
2152 		p2->c = c;
2153 		if (kexes[c->kexalg]->clientkex2(c, p) < 0) {
2154 			add_byte(p2, SSH_MSG_DISCONNECT);
2155 			add_byte(p2, SSH_DISCONNECT_KEY_EXCHANGE_FAILED);
2156 			add_string(p2, "Key exchange failure");
2157 			add_string(p2, "");
2158 			n = finish_packet(p2);
2159 			iowrite(c->rio, c->datafd, p2->nlength, n);
2160 			shutdown(c);
2161 			free(p);
2162 			free(p2);
2163 			closeioproc(c->rio);
2164 			c->rio = nil;
2165 			c->rpid = -1;
2166 
2167 			qlock(&c->l);
2168 			rwakeup(&c->r);
2169 			qunlock(&c->l);
2170 
2171 			sshlog(c, "key exchange failure");
2172 			threadexits(nil);
2173 		}
2174 		add_byte(p2, SSH_MSG_NEWKEYS);
2175 		n = finish_packet(p2);
2176 		iowrite(c->rio, c->datafd, p2->nlength, n);
2177 		qlock(&c->l);
2178 		rwakeup(&c->r);
2179 		qunlock(&c->l);
2180 		break;
2181 	case SSH_MSG_SERVICE_REQUEST:
2182 		get_string(p, p->payload + 1, buf, Arbbufsz, nil);
2183 		sshdebug(c, "got service request: %s", buf);
2184 		if (strcmp(buf, "ssh-userauth") == 0 ||
2185 		    strcmp(buf, "ssh-connection") == 0) {
2186 			init_packet(p2);
2187 			p2->c = c;
2188 			sshdebug(c, "connection");
2189 			add_byte(p2, SSH_MSG_SERVICE_ACCEPT);
2190 			add_string(p2, buf);
2191 			n = finish_packet(p2);
2192 			iowrite(c->rio, c->datafd, p2->nlength, n);
2193 			c->state = Authing;
2194 		} else{
2195 			init_packet(p2);
2196 			p2->c = c;
2197 			add_byte(p2, SSH_MSG_DISCONNECT);
2198 			add_byte(p2, SSH_DISCONNECT_SERVICE_NOT_AVAILABLE);
2199 			add_string(p2, "Unknown service type");
2200 			add_string(p2, "");
2201 			n = finish_packet(p2);
2202 			iowrite(c->rio, c->datafd, p2->nlength, n);
2203 			return -1;
2204 		}
2205 		break;
2206 	case SSH_MSG_SERVICE_ACCEPT:
2207 		get_string(p, p->payload + 1, buf, Arbbufsz, nil);
2208 		if (c->service && strcmp(c->service, "ssh-userauth") == 0) {
2209 			free(c->service);
2210 			c->service = estrdup9p("ssh-connection");
2211 		}
2212 		sshdebug(c, "got service accept: %s: responding with %s %s",
2213 			buf, c->user, c->service);
2214 		n = client_auth(c, c->rio);
2215 		c->state = Authing;
2216 		if (n < 0) {
2217 			qlock(&c->l);
2218 			rwakeup(&c->r);
2219 			qunlock(&c->l);
2220 		}
2221 		break;
2222 	}
2223 	return 0;
2224 }
2225 
2226 static void
nochans(Conn * c,Packet * p,Packet * p2)2227 nochans(Conn *c, Packet *p, Packet *p2)
2228 {
2229 	int n;
2230 
2231 	init_packet(p2);
2232 	p2->c = c;
2233 	add_byte(p2, SSH_MSG_CHANNEL_OPEN_FAILURE);
2234 	add_block(p2, p->payload + 5, 4);
2235 	hnputl(p2->payload + p2->rlength - 1, 4);
2236 	p2->rlength += 4;
2237 	add_string(p2, "No available channels");
2238 	add_string(p2, "EN");
2239 	n = finish_packet(p2);
2240 	iowrite(c->rio, c->datafd, p2->nlength, n);
2241 }
2242 
2243 static int
established(Conn * c,Packet * p,Packet * p2,char * buf,int size)2244 established(Conn *c, Packet *p, Packet *p2, char *buf, int size)
2245 {
2246 	int i, n, cnum;
2247 	uchar *q;
2248 	Plist *pl;
2249 	SSHChan *ch;
2250 
2251 	USED(size);
2252 	if (debug > 1) {
2253 		sshdebug(c, "in Established state, got:");
2254 		dump_packet(p);
2255 	}
2256 	switch (p->payload[0]) {
2257 	case SSH_MSG_DISCONNECT:
2258 		if (debug) {
2259 			get_string(p, p->payload + 5, buf, Arbbufsz, nil);
2260 			sshdebug(c, "got disconnect: %s", buf);
2261 		}
2262 		return -1;
2263 	case SSH_MSG_IGNORE:
2264 	case SSH_MSG_UNIMPLEMENTED:
2265 		break;
2266 	case SSH_MSG_DEBUG:
2267 		if (debug || p->payload[1]) {
2268 			get_string(p, p->payload + 2, buf, Arbbufsz, nil);
2269 			sshdebug(c, "got debug message: %s", buf);
2270 		}
2271 		break;
2272 	case SSH_MSG_KEXINIT:
2273 		send_kexinit(c);
2274 		if (c->rkexinit)
2275 			free(c->rkexinit);
2276 		c->rkexinit = new_packet(c);
2277 		memmove(c->rkexinit, p, sizeof(Packet));
2278 		if (validatekex(c, p) < 0) {
2279 			sshdebug(c, "kex crypto algorithm mismatch (Established)");
2280 			return -1;
2281 		}
2282 		sshdebug(c, "using %s Kex algorithm and %s PKA",
2283 			kexes[c->kexalg]->name, pkas[c->pkalg]->name);
2284 		c->state = Negotiating;
2285 		break;
2286 	case SSH_MSG_GLOBAL_REQUEST:
2287 	case SSH_MSG_REQUEST_SUCCESS:
2288 	case SSH_MSG_REQUEST_FAILURE:
2289 		break;
2290 	case SSH_MSG_CHANNEL_OPEN:
2291 		q = get_string(p, p->payload + 1, buf, Arbbufsz, nil);
2292 		sshdebug(c, "searching for a listener for channel type %s", buf);
2293 		ch = alloc_chan(c);
2294 		if (ch == nil) {
2295 			nochans(c, p, p2);
2296 			break;
2297 		}
2298 
2299 		sshdebug(c, "alloced channel %d for listener", ch->id);
2300 		qlock(&c->l);
2301 		ch->otherid = nhgetl(q);
2302 		ch->twindow = nhgetl(q+4);
2303 		sshdebug(c, "got lock in channel open");
2304 		for (i = 0; i < c->nchan; ++i)
2305 			if (c->chans[i] && c->chans[i]->state == Listening &&
2306 			    c->chans[i]->ann &&
2307 			    strcmp(c->chans[i]->ann, buf) == 0)
2308 				break;
2309 		if (i >= c->nchan) {
2310 			sshdebug(c, "no listener: sleeping");
2311 			ch->state = Opening;
2312 			if (ch->ann)
2313 				free(ch->ann);
2314 			ch->ann = estrdup9p(buf);
2315 			sshdebug(c, "waiting for someone to announce %s", ch->ann);
2316 			rsleep(&ch->r);
2317 		} else{
2318 			sshdebug(c, "found listener on channel %d", ch->id);
2319 			c->chans[i]->waker = ch->id;
2320 			rwakeup(&c->chans[i]->r);
2321 		}
2322 		qunlock(&c->l);
2323 		break;
2324 	case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
2325 		cnum = nhgetl(p->payload + 1);
2326 		ch = c->chans[cnum];
2327 		qlock(&c->l);
2328 		ch->otherid = nhgetl(p->payload+5);
2329 		ch->twindow = nhgetl(p->payload+9);
2330 		rwakeup(&ch->r);
2331 		qunlock(&c->l);
2332 		break;
2333 	case SSH_MSG_CHANNEL_OPEN_FAILURE:
2334 		cnum = nhgetl(p->payload + 1);
2335 		ch = c->chans[cnum];
2336 		qlock(&c->l);
2337 		rwakeup(&ch->r);
2338 		qunlock(&c->l);
2339 		return -1;
2340 	case SSH_MSG_CHANNEL_WINDOW_ADJUST:
2341 		cnum = nhgetl(p->payload + 1);
2342 		ch = c->chans[cnum];
2343 		ch->twindow += nhgetl(p->payload + 5);
2344 		sshdebug(c, "new twindow for channel: %d: %lud", cnum, ch->twindow);
2345 		qlock(&ch->xmtlock);
2346 		rwakeup(&ch->xmtrendez);
2347 		qunlock(&ch->xmtlock);
2348 		break;
2349 	case SSH_MSG_CHANNEL_DATA:
2350 	case SSH_MSG_CHANNEL_EXTENDED_DATA:
2351 		cnum = nhgetl(p->payload + 1);
2352 		ch = c->chans[cnum];
2353 		pl = emalloc9p(sizeof(Plist));
2354 		pl->pack = emalloc9p(sizeof(Packet));
2355 		memmove(pl->pack, p, sizeof(Packet));
2356 		if (p->payload[0] == SSH_MSG_CHANNEL_DATA) {
2357 			pl->rem = nhgetl(p->payload + 5);
2358 			pl->st = pl->pack->payload + 9;
2359 		} else {
2360 			pl->rem = nhgetl(p->payload + 9);
2361 			pl->st = pl->pack->payload + 13;
2362 		}
2363 		pl->next = nil;
2364 		if (ch->dataq == nil)
2365 			ch->dataq = pl;
2366 		else
2367 			ch->datatl->next = pl;
2368 		ch->datatl = pl;
2369 		ch->inrqueue += pl->rem;
2370 		nbsendul(ch->inchan, 1);
2371 		break;
2372 	case SSH_MSG_CHANNEL_EOF:
2373 		cnum = nhgetl(p->payload + 1);
2374 		ch = c->chans[cnum];
2375 		if (ch->state != Closed && ch->state != Closing) {
2376 			ch->state = Eof;
2377 			nbsendul(ch->inchan, 1);
2378 			nbsendul(ch->reqchan, 1);
2379 		}
2380 		break;
2381 	case SSH_MSG_CHANNEL_CLOSE:
2382 		cnum = nhgetl(p->payload + 1);
2383 		ch = c->chans[cnum];
2384 		if (ch->state != Closed && ch->state != Closing) {
2385 			init_packet(p2);
2386 			p2->c = c;
2387 			add_byte(p2, SSH_MSG_CHANNEL_CLOSE);
2388 			hnputl(p2->payload + 1, ch->otherid);
2389 			p2->rlength += 4;
2390 			n = finish_packet(p2);
2391 			iowrite(c->rio, c->datafd, p2->nlength, n);
2392 		}
2393 		qlock(&c->l);
2394 		if (ch->state != Closed) {
2395 			ch->state = Closed;
2396 			rwakeup(&ch->r);
2397 			nbsendul(ch->inchan, 1);
2398 			nbsendul(ch->reqchan, 1);
2399 			chanclose(ch->inchan);
2400 			chanclose(ch->reqchan);
2401 		}
2402 		qunlock(&c->l);
2403 		for (i = 0; i < MAXCONN && (!c->chans[i] ||
2404 		    c->chans[i]->state == Empty || c->chans[i]->state == Closed);
2405 		    ++i)
2406 			;
2407 		if (i >= MAXCONN)
2408 			return -1;
2409 		break;
2410 	case SSH_MSG_CHANNEL_REQUEST:
2411 		cnum = nhgetl(p->payload + 1);
2412 		ch = c->chans[cnum];
2413 		sshdebug(c, "queueing channel request for channel: %d", cnum);
2414 		q = get_string(p, p->payload+5, buf, Arbbufsz, nil);
2415 		pl = emalloc9p(sizeof(Plist));
2416 		pl->pack = emalloc9p(sizeof(Packet));
2417 		n = snprint((char *)pl->pack->payload,
2418 			Maxpayload, "%s %c", buf, *q? 't': 'f');
2419 		sshdebug(c, "request message begins: %s",
2420 			(char *)pl->pack->payload);
2421 		memmove(pl->pack->payload + n, q + 1, p->rlength - (11 + n-2));
2422 		pl->rem = p->rlength - 11 + 2;
2423 		pl->st = pl->pack->payload;
2424 		pl->next = nil;
2425 		if (ch->reqq == nil)
2426 			ch->reqq = pl;
2427 		else
2428 			ch->reqtl->next = pl;
2429 		ch->reqtl = pl;
2430 		nbsendul(ch->reqchan, 1);
2431 		break;
2432 	case SSH_MSG_CHANNEL_SUCCESS:
2433 	case SSH_MSG_CHANNEL_FAILURE:
2434 	default:
2435 		break;
2436 	}
2437 	return 0;
2438 }
2439 
2440 static void
bail(Conn * c,Packet * p,Packet * p2,char * sts)2441 bail(Conn *c, Packet *p, Packet *p2, char *sts)
2442 {
2443 	shutdown(c);
2444 	free(p);
2445 	free(p2);
2446 	if (c->rio) {
2447 		closeioproc(c->rio);
2448 		c->rio = nil;
2449 	}
2450 	c->rpid = -1;
2451 	threadexits(sts);
2452 }
2453 
2454 static void
reader0(Conn * c,Packet * p,Packet * p2)2455 reader0(Conn *c, Packet *p, Packet *p2)
2456 {
2457 	int i, n, nl, np, nm, nb;
2458 	char buf[Arbbufsz];
2459 
2460 	nm = 0;
2461 	nb = 4;
2462 	if (c->decrypt != -1)
2463 		nb = cryptos[c->decrypt]->blklen;
2464 	sshdebug(c, "calling read for connection %d, state %d, nb %d, dc %d",
2465 		c->id, c->state, nb, c->decrypt);
2466 	if ((nl = ioreadn(c->rio, c->datafd, p->nlength, nb)) != nb) {
2467 		sshdebug(c, "reader for connection %d exiting, got %d: %r",
2468 			c->id, nl);
2469 		bail(c, p, p2, "reader exiting");
2470 	}
2471 	if (c->decrypt != -1)
2472 		cryptos[c->decrypt]->decrypt(c->deccs, p->nlength, nb);
2473 	p->rlength = nhgetl(p->nlength);
2474 	sshdebug(c, "got message length: %ld", p->rlength);
2475 	if (p->rlength > Maxpktpay) {
2476 		sshdebug(c, "absurd packet length: %ld, unrecoverable decrypt failure",
2477 			p->rlength);
2478 		bail(c, p, p2, "absurd packet length");
2479 	}
2480 	np = ioreadn(c->rio, c->datafd, p->nlength + nb, p->rlength + 4 - nb);
2481 	if (c->inmac != -1)
2482 		nm = ioreadn(c->rio, c->datafd, p->nlength + p->rlength + 4,
2483 			SHA1dlen);		/* SHA1dlen was magic 20 */
2484 	n = nl + np + nm;
2485 	if (debug) {
2486 		sshdebug(c, "got message of %d bytes %d padding", n, p->pad_len);
2487 		if (p->payload[0] > SSH_MSG_CHANNEL_OPEN) {
2488 			i = nhgetl(p->payload+1);
2489 			if (c->chans[i])
2490 				sshdebug(c, " for channel %d win %lud",
2491 					i, c->chans[i]->rwindow);
2492 			else
2493 				sshdebug(c, " for invalid channel %d", i);
2494 		}
2495 		sshdebug(c, " first byte: %d", p->payload[0]);
2496 	}
2497 	/* SHA1dlen was magic 20 */
2498 	if (np != p->rlength + 4 - nb || c->inmac != -1 && nm != SHA1dlen) {
2499 		sshdebug(c, "got EOF/error on connection read: %d %d %r", np, nm);
2500 		bail(c, p, p2, "error or eof");
2501 	}
2502 	p->tlength = n;
2503 	p->rlength = n - 4;
2504 	if (undo_packet(p) < 0) {
2505 		sshdebug(c, "bad packet in connection %d: exiting", c->id);
2506 		bail(c, p, p2, "bad packet");
2507 	}
2508 
2509 	if (c->state == Initting) {
2510 		if (p->payload[0] != SSH_MSG_KEXINIT) {
2511 			sshdebug(c, "missing KEX init packet: %d", p->payload[0]);
2512 			bail(c, p, p2, "bad kex");
2513 		}
2514 		if (c->rkexinit)
2515 			free(c->rkexinit);
2516 		c->rkexinit = new_packet(c);
2517 		memmove(c->rkexinit, p, sizeof(Packet));
2518 		if (validatekex(c, p) < 0) {
2519 			sshdebug(c, "kex crypto algorithm mismatch (Initting)");
2520 			bail(c, p, p2, "bad kex");
2521 		}
2522 		sshdebug(c, "using %s Kex algorithm and %s PKA",
2523 			kexes[c->kexalg]->name, pkas[c->pkalg]->name);
2524 		if (c->role == Client)
2525 			kexes[c->kexalg]->clientkex1(c, p);
2526 		c->state = Negotiating;
2527 	} else if (c->state == Negotiating) {
2528 		if (negotiating(c, p, p2, buf, sizeof buf) < 0)
2529 			bail(c, p, p2, "negotiating");
2530 	} else if (c->state == Authing) {
2531 		switch (p->payload[0]) {
2532 		case SSH_MSG_DISCONNECT:
2533 			if (debug) {
2534 				get_string(p, p->payload + 5, buf, Arbbufsz, nil);
2535 				sshdebug(c, "got disconnect: %s", buf);
2536 			}
2537 			bail(c, p, p2, "msg disconnect");
2538 		case SSH_MSG_USERAUTH_REQUEST:
2539 			switch (auth_req(p, c)) {
2540 			case 0:			/* success */
2541 				establish(c);
2542 				break;
2543 			case 1:			/* ok to try again */
2544 			case -1:		/* failure */
2545 				break;
2546 			case -2:		/* can't happen, now at least */
2547 				bail(c, p, p2, "in userauth request");
2548 			}
2549 			break;
2550 		case SSH_MSG_USERAUTH_FAILURE:
2551 			qlock(&c->l);
2552 			rwakeup(&c->r);
2553 			qunlock(&c->l);
2554 			break;
2555 		case SSH_MSG_USERAUTH_SUCCESS:
2556 			establish(c);
2557 			break;
2558 		case SSH_MSG_USERAUTH_BANNER:
2559 			break;
2560 		}
2561 	} else if (c->state == Established) {
2562 		if (established(c, p, p2, buf, sizeof buf) < 0)
2563 			bail(c, p, p2, "from established state");
2564 	} else {
2565 		sshdebug(c, "connection %d in bad state, reader exiting", c->id);
2566 		bail(c, p, p2, "bad conn state");
2567 	}
2568 }
2569 
2570 void
reader(void * a)2571 reader(void *a)
2572 {
2573 	Conn *c;
2574 	Packet *p, *p2;
2575 
2576 	threadsetname("reader");
2577 	c = a;
2578 	c->rpid = threadid();
2579 	sshdebug(c, "starting reader for connection %d, pid %d", c->id, c->rpid);
2580 	threadsetname("reader");
2581 	p = new_packet(c);
2582 	p2 = new_packet(c);
2583 	c->rio = ioproc();
2584 	for(;;)
2585 		reader0(c, p, p2);
2586 }
2587 
2588 int
validatekex(Conn * c,Packet * p)2589 validatekex(Conn *c, Packet *p)
2590 {
2591 	if (c->role == Server)
2592 		return validatekexs(p);
2593 	else
2594 		return validatekexc(p);
2595 }
2596 
2597 int
validatekexs(Packet * p)2598 validatekexs(Packet *p)
2599 {
2600 	uchar *q;
2601 	char *toks[Maxtoks];
2602 	int i, j, n;
2603 	char *buf;
2604 
2605 	buf = emalloc9p(Bigbufsz);
2606 	q = p->payload + 17;
2607 
2608 	q = get_string(p, q, buf, Bigbufsz, nil);
2609 	sshdebug(nil, "received KEX algs: %s", buf);
2610 	n = gettokens(buf, toks, nelem(toks), ",");
2611 	for (i = 0; i < n; ++i)
2612 		for (j = 0; j < nelem(kexes); ++j)
2613 			if (strcmp(toks[i], kexes[j]->name) == 0)
2614 				goto foundk;
2615 	sshdebug(nil, "kex algs not in kexes");
2616 	free(buf);
2617 	return -1;
2618 foundk:
2619 	p->c->kexalg = j;
2620 
2621 	q = get_string(p, q, buf, Bigbufsz, nil);
2622 	sshdebug(nil, "received host key algs: %s", buf);
2623 	n = gettokens(buf, toks, nelem(toks), ",");
2624 	for (i = 0; i < n; ++i)
2625 		for (j = 0; j < nelem(pkas) && pkas[j] != nil; ++j)
2626 			if (strcmp(toks[i], pkas[j]->name) == 0)
2627 				goto foundpka;
2628 	sshdebug(nil, "host key algs not in pkas");
2629 	free(buf);
2630 	return -1;
2631 foundpka:
2632 	p->c->pkalg = j;
2633 
2634 	q = get_string(p, q, buf, Bigbufsz, nil);
2635 	sshdebug(nil, "received C2S crypto algs: %s", buf);
2636 	n = gettokens(buf, toks, nelem(toks), ",");
2637 	for (i = 0; i < n; ++i)
2638 		for (j = 0; j < nelem(cryptos); ++j)
2639 			if (strcmp(toks[i], cryptos[j]->name) == 0)
2640 				goto foundc1;
2641 	sshdebug(nil, "c2s crypto algs not in cryptos");
2642 	free(buf);
2643 	return -1;
2644 foundc1:
2645 	p->c->ncscrypt = j;
2646 
2647 	q = get_string(p, q, buf, Bigbufsz, nil);
2648 	sshdebug(nil, "received S2C crypto algs: %s", buf);
2649 	n = gettokens(buf, toks, nelem(toks), ",");
2650 	for (i = 0; i < n; ++i)
2651 		for (j = 0; j < nelem(cryptos); ++j)
2652 			if (strcmp(toks[i], cryptos[j]->name) == 0)
2653 				goto foundc2;
2654 	sshdebug(nil, "s2c crypto algs not in cryptos");
2655 	free(buf);
2656 	return -1;
2657 foundc2:
2658 	p->c->nsccrypt = j;
2659 
2660 	q = get_string(p, q, buf, Bigbufsz, nil);
2661 	sshdebug(nil, "received C2S MAC algs: %s", buf);
2662 	n = gettokens(buf, toks, nelem(toks), ",");
2663 	for (i = 0; i < n; ++i)
2664 		for (j = 0; j < nelem(macnames); ++j)
2665 			if (strcmp(toks[i], macnames[j]) == 0)
2666 				goto foundm1;
2667 	sshdebug(nil, "c2s mac algs not in cryptos");
2668 	free(buf);
2669 	return -1;
2670 foundm1:
2671 	p->c->ncsmac = j;
2672 
2673 	q = get_string(p, q, buf, Bigbufsz, nil);
2674 	sshdebug(nil, "received S2C MAC algs: %s", buf);
2675 	n = gettokens(buf, toks, nelem(toks), ",");
2676 	for (i = 0; i < n; ++i)
2677 		for (j = 0; j < nelem(macnames); ++j)
2678 			if (strcmp(toks[i], macnames[j]) == 0)
2679 				goto foundm2;
2680 	sshdebug(nil, "s2c mac algs not in cryptos");
2681 	free(buf);
2682 	return -1;
2683 foundm2:
2684 	p->c->nscmac = j;
2685 
2686 	q = get_string(p, q, buf, Bigbufsz, nil);
2687 	q = get_string(p, q, buf, Bigbufsz, nil);
2688 	q = get_string(p, q, buf, Bigbufsz, nil);
2689 	q = get_string(p, q, buf, Bigbufsz, nil);
2690 	free(buf);
2691 	if (*q)
2692 		return 1;
2693 	return 0;
2694 }
2695 
2696 int
validatekexc(Packet * p)2697 validatekexc(Packet *p)
2698 {
2699 	uchar *q;
2700 	char *toks[Maxtoks];
2701 	int i, j, n;
2702 	char *buf;
2703 
2704 	buf = emalloc9p(Bigbufsz);
2705 	q = p->payload + 17;
2706 	q = get_string(p, q, buf, Bigbufsz, nil);
2707 	n = gettokens(buf, toks, nelem(toks), ",");
2708 	for (j = 0; j < nelem(kexes); ++j)
2709 		for (i = 0; i < n; ++i)
2710 			if (strcmp(toks[i], kexes[j]->name) == 0)
2711 				goto foundk;
2712 	free(buf);
2713 	return -1;
2714 foundk:
2715 	p->c->kexalg = j;
2716 
2717 	q = get_string(p, q, buf, Bigbufsz, nil);
2718 	n = gettokens(buf, toks, nelem(toks), ",");
2719 	for (j = 0; j < nelem(pkas) && pkas[j] != nil; ++j)
2720 		for (i = 0; i < n; ++i)
2721 			if (strcmp(toks[i], pkas[j]->name) == 0)
2722 				goto foundpka;
2723 	free(buf);
2724 	return -1;
2725 foundpka:
2726 	p->c->pkalg = j;
2727 
2728 	q = get_string(p, q, buf, Bigbufsz, nil);
2729 	n = gettokens(buf, toks, nelem(toks), ",");
2730 	for (j = 0; j < nelem(cryptos); ++j)
2731 		for (i = 0; i < n; ++i)
2732 			if (strcmp(toks[i], cryptos[j]->name) == 0)
2733 				goto foundc1;
2734 	free(buf);
2735 	return -1;
2736 foundc1:
2737 	p->c->ncscrypt = j;
2738 	q = get_string(p, q, buf, Bigbufsz, nil);
2739 	n = gettokens(buf, toks, nelem(toks), ",");
2740 	for (j = 0; j < nelem(cryptos); ++j)
2741 		for (i = 0; i < n; ++i)
2742 			if (strcmp(toks[i], cryptos[j]->name) == 0)
2743 				goto foundc2;
2744 	free(buf);
2745 	return -1;
2746 foundc2:
2747 	p->c->nsccrypt = j;
2748 
2749 	q = get_string(p, q, buf, Bigbufsz, nil);
2750 	n = gettokens(buf, toks, nelem(toks), ",");
2751 	for (j = 0; j < nelem(macnames); ++j)
2752 		for (i = 0; i < n; ++i)
2753 			if (strcmp(toks[i], macnames[j]) == 0)
2754 				goto foundm1;
2755 	free(buf);
2756 	return -1;
2757 foundm1:
2758 	p->c->ncsmac = j;
2759 
2760 	q = get_string(p, q, buf, Bigbufsz, nil);
2761 	n = gettokens(buf, toks, nelem(toks), ",");
2762 	for (j = 0; j < nelem(macnames); ++j)
2763 		for (i = 0; i < n; ++i)
2764 			if (strcmp(toks[i], macnames[j]) == 0)
2765 				goto foundm2;
2766 	free(buf);
2767 	return -1;
2768 foundm2:
2769 	p->c->nscmac = j;
2770 
2771 	q = get_string(p, q, buf, Bigbufsz, nil);
2772 	q = get_string(p, q, buf, Bigbufsz, nil);
2773 	q = get_string(p, q, buf, Bigbufsz, nil);
2774 	q = get_string(p, q, buf, Bigbufsz, nil);
2775 	free(buf);
2776 	return *q != 0;
2777 }
2778 
2779 int
memrandom(void * p,int n)2780 memrandom(void *p, int n)
2781 {
2782 	uchar *cp;
2783 
2784 	for (cp = (uchar*)p; n > 0; n--)
2785 		*cp++ = fastrand();
2786 	return 0;
2787 }
2788 
2789 /*
2790  *  create a change uid capability
2791  */
2792 char*
mkcap(char * from,char * to)2793 mkcap(char *from, char *to)
2794 {
2795 	int fd, fromtosz;
2796 	char *cap, *key;
2797 	uchar rand[SHA1dlen], hash[SHA1dlen];
2798 
2799 	fd = open("#¤/caphash", OWRITE);
2800 	if (fd < 0)
2801 		sshlog(nil, "can't open #¤/caphash: %r");
2802 
2803 	/* create the capability */
2804 	fromtosz = strlen(from) + 1 + strlen(to) + 1;
2805 	cap = emalloc9p(fromtosz + sizeof(rand)*3 + 1);
2806 	snprint(cap, fromtosz + sizeof(rand)*3 + 1, "%s@%s", from, to);
2807 	memrandom(rand, sizeof(rand));
2808 	key = cap + fromtosz;
2809 	enc64(key, sizeof(rand)*3, rand, sizeof(rand));
2810 
2811 	/* hash the capability */
2812 	hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
2813 
2814 	/* give the kernel the hash */
2815 	key[-1] = '@';
2816 	sshdebug(nil, "writing `%.*s' to caphash", SHA1dlen, hash);
2817 	if (write(fd, hash, SHA1dlen) != SHA1dlen) {
2818 		close(fd);
2819 		free(cap);
2820 		return nil;
2821 	}
2822 	close(fd);
2823 	return cap;
2824 }
2825 
2826 /*
2827  * ask keyfs (assumes we are on an auth server)
2828  */
2829 static AuthInfo *
keyfsauth(char * me,char * user,char * pw,char * key1,char * key2)2830 keyfsauth(char *me, char *user, char *pw, char *key1, char *key2)
2831 {
2832 	int fd;
2833 	char path[Arbpathlen];
2834 	AuthInfo *ai;
2835 
2836 	if (passtokey(key1, pw) == 0)
2837 		return nil;
2838 
2839 	snprint(path, Arbpathlen, "/mnt/keys/%s/key", user);
2840 	if ((fd = open(path, OREAD)) < 0) {
2841 		werrstr("Invalid user %s", user);
2842 		return nil;
2843 	}
2844 	if (read(fd, key2, DESKEYLEN) != DESKEYLEN) {
2845 		close(fd);
2846 		werrstr("Password mismatch 1");
2847 		return nil;
2848 	}
2849 	close(fd);
2850 
2851 	if (memcmp(key1, key2, DESKEYLEN) != 0) {
2852 		werrstr("Password mismatch 2");
2853 		return nil;
2854 	}
2855 
2856 	ai = emalloc9p(sizeof(AuthInfo));
2857 	ai->cuid = estrdup9p(user);
2858 	ai->suid = estrdup9p(me);
2859 	ai->cap = mkcap(me, user);
2860 	ai->nsecret = 0;
2861 	ai->secret = (uchar *)estrdup9p("");
2862 	return ai;
2863 }
2864 
2865 static void
userauthfailed(Packet * p2)2866 userauthfailed(Packet *p2)
2867 {
2868 	add_byte(p2, SSH_MSG_USERAUTH_FAILURE);
2869 	add_string(p2, "password,publickey");
2870 	add_byte(p2, 0);
2871 }
2872 
2873 static int
authreqpk(Packet * p,Packet * p2,Conn * c,char * user,uchar * q,char * alg,char * blob,char * sig,char * service,char * me)2874 authreqpk(Packet *p, Packet *p2, Conn *c, char *user, uchar *q,
2875 	char *alg, char *blob, char *sig, char *service, char *me)
2876 {
2877 	int n, thisway, nblob, nsig;
2878 	char method[32];
2879 
2880 	sshdebug(c, "auth_req publickey for user %s", user);
2881 	thisway = *q == '\0';
2882 	q = get_string(p, q+1, alg, Arbpathlen, nil);
2883 	q = get_string(p, q, blob, Blobsz, &nblob);
2884 	if (thisway) {
2885 		/*
2886 		 * Should really check to see if this user can
2887 		 * be authed this way.
2888 		 */
2889 		for (n = 0; n < nelem(pkas) && pkas[n] != nil &&
2890 		    strcmp(pkas[n]->name, alg) != 0; ++n)
2891 			;
2892 		if (n >= nelem(pkas) || pkas[n] == nil) {
2893 			userauthfailed(p2);
2894 			return -1;
2895 		}
2896 		add_byte(p2, SSH_MSG_USERAUTH_PK_OK);
2897 		add_string(p2, alg);
2898 		add_block(p2, blob, nblob);
2899 		return 1;
2900 	}
2901 
2902 	get_string(p, q, sig, Blobsz, &nsig);
2903 	for (n = 0; n < nelem(pkas) && pkas[n] != nil &&
2904 	    strcmp(pkas[n]->name, alg) != 0; ++n)
2905 		;
2906 	if (n >= nelem(pkas) || pkas[n] == nil) {
2907 		userauthfailed(p2);
2908 		return -1;
2909 	}
2910 
2911 	add_block(p2, c->sessid, SHA1dlen);
2912 	add_byte(p2, SSH_MSG_USERAUTH_REQUEST);
2913 	add_string(p2, user);
2914 	add_string(p2, service);
2915 	add_string(p2, method);
2916 	add_byte(p2, 1);
2917 	add_string(p2, alg);
2918 	add_block(p2, blob, nblob);
2919 	if (pkas[n]->verify(c, p2->payload, p2->rlength - 1, user, sig, nsig)
2920 	    == 0) {
2921 		init_packet(p2);
2922 		p2->c = c;
2923 		sshlog(c, "public key login failed");
2924 		userauthfailed(p2);
2925 		return -1;
2926 	}
2927 	free(c->cap);
2928 	c->cap = mkcap(me, user);
2929 	init_packet(p2);
2930 	p2->c = c;
2931 	sshlog(c, "logged in by public key");
2932 	add_byte(p2, SSH_MSG_USERAUTH_SUCCESS);
2933 	return 0;
2934 }
2935 
2936 int
auth_req(Packet * p,Conn * c)2937 auth_req(Packet *p, Conn *c)
2938 {
2939 	int n, ret;
2940 	char *alg, *blob, *sig, *service, *me, *user, *pw, *path;
2941 	char key1[DESKEYLEN], key2[DESKEYLEN], method[32];
2942 	uchar *q;
2943 	AuthInfo *ai;
2944 	Packet *p2;
2945 
2946 	service = emalloc9p(Arbpathlen);
2947 	me = emalloc9p(Arbpathlen);
2948 	user = emalloc9p(Arbpathlen);
2949 	pw = emalloc9p(Arbpathlen);
2950 	alg = emalloc9p(Arbpathlen);
2951 	path = emalloc9p(Arbpathlen);
2952 	blob = emalloc9p(Blobsz);
2953 	sig = emalloc9p(Blobsz);
2954 	ret = -1;				/* failure is default */
2955 
2956 	q = get_string(p, p->payload + 1, user, Arbpathlen, nil);
2957 	free(c->user);
2958 	c->user = estrdup9p(user);
2959 	q = get_string(p, q, service, Arbpathlen, nil);
2960 	q = get_string(p, q, method, sizeof method, nil);
2961 	sshdebug(c, "got userauth request: %s %s %s", user, service, method);
2962 
2963 	readfile("/dev/user", me, Arbpathlen);
2964 
2965 	p2 = new_packet(c);
2966 	if (strcmp(method, "publickey") == 0)
2967 		ret = authreqpk(p, p2, c, user, q, alg, blob, sig, service, me);
2968 	else if (strcmp(method, "password") == 0) {
2969 		get_string(p, q + 1, pw, Arbpathlen, nil);
2970 		// sshdebug(c, "%s", pw);	/* bad idea to log passwords */
2971 		sshdebug(c, "auth_req password");
2972 		if (kflag)
2973 			ai = keyfsauth(me, user, pw, key1, key2);
2974 		else
2975 			ai = auth_userpasswd(user, pw);
2976 		if (ai == nil) {
2977 			sshlog(c, "login failed: %r");
2978 			userauthfailed(p2);
2979 		} else {
2980 			sshdebug(c, "auth successful: cuid %s suid %s cap %s",
2981 				ai->cuid, ai->suid, ai->cap);
2982 			free(c->cap);
2983 			if (strcmp(user, me) == 0)
2984 				c->cap = estrdup9p("n/a");
2985 			else
2986 				c->cap = estrdup9p(ai->cap);
2987 			sshlog(c, "logged in by password");
2988 			add_byte(p2, SSH_MSG_USERAUTH_SUCCESS);
2989 			auth_freeAI(ai);
2990 			ret = 0;
2991 		}
2992 	} else
2993 		userauthfailed(p2);
2994 
2995 	n = finish_packet(p2);
2996 	iowrite(c->dio, c->datafd, p2->nlength, n);
2997 
2998 	free(service);
2999 	free(me);
3000 	free(user);
3001 	free(pw);
3002 	free(alg);
3003 	free(blob);
3004 	free(sig);
3005 	free(path);
3006 	free(p2);
3007 	return ret;
3008 }
3009 
3010 int
client_auth(Conn * c,Ioproc * io)3011 client_auth(Conn *c, Ioproc *io)
3012 {
3013 	Packet *p2, *p3, *p4;
3014 	char *r, *s;
3015 	mpint *ek, *nk;
3016 	int i, n;
3017 
3018 	sshdebug(c, "client_auth");
3019 	if (!c->password && !c->authkey)
3020 		return -1;
3021 
3022 	p2 = new_packet(c);
3023 	add_byte(p2, SSH_MSG_USERAUTH_REQUEST);
3024 	add_string(p2, c->user);
3025 	add_string(p2, c->service);
3026 	if (c->password) {
3027 		add_string(p2, "password");
3028 		add_byte(p2, 0);
3029 		add_string(p2, c->password);
3030 		sshdebug(c, "client_auth using password for svc %s", c->service);
3031 	} else {
3032 		sshdebug(c, "client_auth trying rsa public key");
3033 		add_string(p2, "publickey");
3034 		add_byte(p2, 1);
3035 		add_string(p2, "ssh-rsa");
3036 
3037 		r = strstr(c->authkey, " ek=");
3038 		s = strstr(c->authkey, " n=");
3039 		if (!r || !s) {
3040 			shutdown(c);
3041 			free(p2);
3042 			sshdebug(c, "client_auth no rsa key");
3043 			return -1;
3044 		}
3045 		ek = strtomp(r+4, nil, 16, nil);
3046 		nk = strtomp(s+3, nil, 16, nil);
3047 
3048 		p3 = new_packet(c);
3049 		add_string(p3, "ssh-rsa");
3050 		add_mp(p3, ek);
3051 		add_mp(p3, nk);
3052 		add_block(p2, p3->payload, p3->rlength-1);
3053 
3054 		p4 = new_packet(c);
3055 		add_block(p4, c->sessid, SHA1dlen);
3056 		add_byte(p4, SSH_MSG_USERAUTH_REQUEST);
3057 		add_string(p4, c->user);
3058 		add_string(p4, c->service);
3059 		add_string(p4, "publickey");
3060 		add_byte(p4, 1);
3061 		add_string(p4, "ssh-rsa");
3062 		add_block(p4, p3->payload, p3->rlength-1);
3063 		mpfree(ek);
3064 		mpfree(nk);
3065 		free(p3);
3066 
3067 		for (i = 0; pkas[i] && strcmp("ssh-rsa", pkas[i]->name) != 0;
3068 		    ++i)
3069 			;
3070 		sshdebug(c, "client_auth rsa signing alg %d: %r",  i);
3071 		if ((p3 = pkas[i]->sign(c, p4->payload, p4->rlength-1)) == nil) {
3072 			sshdebug(c, "client_auth rsa signing failed: %r");
3073 			free(p4);
3074 			free(p2);
3075 			return -1;
3076 		}
3077 		add_block(p2, p3->payload, p3->rlength-1);
3078 		free(p3);
3079 		free(p4);
3080 	}
3081 
3082 	n = finish_packet(p2);
3083 	if (writeio(io, c->datafd, p2->nlength, n) != n)
3084 		sshdebug(c, "client_auth write failed: %r");
3085 	free(p2);
3086 	return 0;
3087 }
3088 
3089 /* should use auth_getkey or something similar */
3090 char *
factlookup(int nattr,int nreq,char * attrs[])3091 factlookup(int nattr, int nreq, char *attrs[])
3092 {
3093 	Biobuf *bp;
3094 	char *buf, *toks[Maxtoks], *res, *q;
3095 	int ntok, nmatch, maxmatch;
3096 	int i, j;
3097 
3098 	res = nil;
3099 	bp = Bopen("/mnt/factotum/ctl", OREAD);
3100 	if (bp == nil)
3101 		return nil;
3102 	maxmatch = 0;
3103 	while (buf = Brdstr(bp, '\n', 1)) {
3104 		q = estrdup9p(buf);
3105 		ntok = gettokens(buf, toks, nelem(toks), " ");
3106 		nmatch = 0;
3107 		for (i = 0; i < nattr; ++i) {
3108 			for (j = 0; j < ntok; ++j)
3109 				if (strcmp(attrs[i], toks[j]) == 0) {
3110 					++nmatch;
3111 					break;
3112 				}
3113 			if (i < nreq && j >= ntok)
3114 				break;
3115 		}
3116 		if (i >= nattr && nmatch > maxmatch) {
3117 			free(res);
3118 			res = q;
3119 			maxmatch = nmatch;
3120 		} else
3121 			free(q);
3122 		free(buf);
3123 	}
3124 	Bterm(bp);
3125 	return res;
3126 }
3127 
3128 void
shutdown(Conn * c)3129 shutdown(Conn *c)
3130 {
3131 	Plist *p;
3132 	SSHChan *sc;
3133 	int i, ostate;
3134 
3135 	sshdebug(c, "shutting down connection %d", c->id);
3136 	ostate = c->state;
3137 	if (c->clonefile->ref <= 2 && c->ctlfile->ref <= 2 &&
3138 	    c->datafile->ref <= 2 && c->listenfile->ref <= 2 &&
3139 	    c->localfile->ref <= 2 && c->remotefile->ref <= 2 &&
3140 	    c->statusfile->ref <= 2)
3141 		c->state = Closed;
3142 	else {
3143 		if (c->state != Closed)
3144 			c->state = Closing;
3145 		sshdebug(c, "clone %ld ctl %ld data %ld listen %ld "
3146 			"local %ld remote %ld status %ld",
3147 			c->clonefile->ref, c->ctlfile->ref, c->datafile->ref,
3148 			c->listenfile->ref, c->localfile->ref, c->remotefile->ref,
3149 			c->statusfile->ref);
3150 	}
3151 	if (ostate == Closed || ostate == Closing) {
3152 		c->state = Closed;
3153 		return;
3154 	}
3155 	if (c->role == Server && c->remote)
3156 		sshlog(c, "closing connection");
3157 	hangupconn(c);
3158 	if (c->dio) {
3159 		closeioproc(c->dio);
3160 		c->dio = nil;
3161 	}
3162 
3163 	c->decrypt = -1;
3164 	c->inmac = -1;
3165 	c->nchan = 0;
3166 	free(c->otherid);
3167 	free(c->s2ccs);
3168 	c->s2ccs = nil;
3169 	free(c->c2scs);
3170 	c->c2scs = nil;
3171 	free(c->remote);
3172 	c->remote = nil;
3173 	if (c->x) {
3174 		mpfree(c->x);
3175 		c->x = nil;
3176 	}
3177 	if (c->e) {
3178 		mpfree(c->e);
3179 		c->e = nil;
3180 	}
3181 	free(c->user);
3182 	c->user = nil;
3183 	free(c->service);
3184 	c->service = nil;
3185 	c->otherid = nil;
3186 	qlock(&c->l);
3187 	rwakeupall(&c->r);
3188 	qunlock(&c->l);
3189 	for (i = 0; i < MAXCONN; ++i) {
3190 		sc = c->chans[i];
3191 		if (sc == nil)
3192 			continue;
3193 		free(sc->ann);
3194 		sc->ann = nil;
3195 		if (sc->state != Empty && sc->state != Closed) {
3196 			sc->state = Closed;
3197 			sc->lreq = nil;
3198 			while (sc->dataq != nil) {
3199 				p = sc->dataq;
3200 				sc->dataq = p->next;
3201 				free(p->pack);
3202 				free(p);
3203 			}
3204 			while (sc->reqq != nil) {
3205 				p = sc->reqq;
3206 				sc->reqq = p->next;
3207 				free(p->pack);
3208 				free(p);
3209 			}
3210 			qlock(&c->l);
3211 			rwakeupall(&sc->r);
3212 			nbsendul(sc->inchan, 1);
3213 			nbsendul(sc->reqchan, 1);
3214 			chanclose(sc->inchan);
3215 			chanclose(sc->reqchan);
3216 			qunlock(&c->l);
3217 		}
3218 	}
3219 	qlock(&availlck);
3220 	rwakeup(&availrend);
3221 	qunlock(&availlck);
3222 	sshdebug(c, "done processing shutdown of connection %d", c->id);
3223 }
3224