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