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