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