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