Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	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
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
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
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
270
stend(Srv *)
271
{
272
	closeioproc(io9p);
273
	threadkillgrp(threadgetgrp());
274
}
275
 
276
void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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 *
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
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
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
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
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
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
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
 
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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*
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 *
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
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
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
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
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 *
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
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
}