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