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 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 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 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 163 usage(void) 164 { 165 fprint(2, "usage: %s [-dkv] [-m mntpt] [-s srvpt]\n", argv0); 166 exits("usage"); 167 } 168 169 void 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 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 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 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 273 stend(Srv *) 274 { 275 closeioproc(io9p); 276 threadkillgrp(threadgetgrp()); 277 } 278 279 void 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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* 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 * 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 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 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 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 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 * 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 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