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: /* success */ 2538 establish(c); 2539 break; 2540 case 1: /* ok to try again */ 2541 case -1: /* failure */ 2542 break; 2543 case -2: /* can't happen, now at least */ 2544 bail(c, p, p2, "in userauth request"); 2545 } 2546 break; 2547 case SSH_MSG_USERAUTH_FAILURE: 2548 qlock(&c->l); 2549 rwakeup(&c->r); 2550 qunlock(&c->l); 2551 break; 2552 case SSH_MSG_USERAUTH_SUCCESS: 2553 establish(c); 2554 break; 2555 case SSH_MSG_USERAUTH_BANNER: 2556 break; 2557 } 2558 } else if (c->state == Established) { 2559 if (established(c, p, p2, buf, sizeof buf) < 0) 2560 bail(c, p, p2, "from established state"); 2561 } else { 2562 sshdebug(c, "connection %d in bad state, reader exiting", c->id); 2563 bail(c, p, p2, "bad conn state"); 2564 } 2565 } 2566 2567 void 2568 reader(void *a) 2569 { 2570 Conn *c; 2571 Packet *p, *p2; 2572 2573 threadsetname("reader"); 2574 c = a; 2575 c->rpid = threadid(); 2576 sshdebug(c, "starting reader for connection %d, pid %d", c->id, c->rpid); 2577 threadsetname("reader"); 2578 p = new_packet(c); 2579 p2 = new_packet(c); 2580 c->rio = ioproc(); 2581 for(;;) 2582 reader0(c, p, p2); 2583 } 2584 2585 int 2586 validatekex(Conn *c, Packet *p) 2587 { 2588 if (c->role == Server) 2589 return validatekexs(p); 2590 else 2591 return validatekexc(p); 2592 } 2593 2594 int 2595 validatekexs(Packet *p) 2596 { 2597 uchar *q; 2598 char *toks[Maxtoks]; 2599 int i, j, n; 2600 char *buf; 2601 2602 buf = emalloc9p(Bigbufsz); 2603 q = p->payload + 17; 2604 2605 q = get_string(p, q, buf, Bigbufsz, nil); 2606 sshdebug(nil, "received KEX algs: %s", buf); 2607 n = gettokens(buf, toks, nelem(toks), ","); 2608 for (i = 0; i < n; ++i) 2609 for (j = 0; j < nelem(kexes); ++j) 2610 if (strcmp(toks[i], kexes[j]->name) == 0) 2611 goto foundk; 2612 sshdebug(nil, "kex algs not in kexes"); 2613 free(buf); 2614 return -1; 2615 foundk: 2616 p->c->kexalg = j; 2617 2618 q = get_string(p, q, buf, Bigbufsz, nil); 2619 sshdebug(nil, "received host key algs: %s", buf); 2620 n = gettokens(buf, toks, nelem(toks), ","); 2621 for (i = 0; i < n; ++i) 2622 for (j = 0; j < nelem(pkas) && pkas[j] != nil; ++j) 2623 if (strcmp(toks[i], pkas[j]->name) == 0) 2624 goto foundpka; 2625 sshdebug(nil, "host key algs not in pkas"); 2626 free(buf); 2627 return -1; 2628 foundpka: 2629 p->c->pkalg = j; 2630 2631 q = get_string(p, q, buf, Bigbufsz, nil); 2632 sshdebug(nil, "received C2S crypto algs: %s", buf); 2633 n = gettokens(buf, toks, nelem(toks), ","); 2634 for (i = 0; i < n; ++i) 2635 for (j = 0; j < nelem(cryptos); ++j) 2636 if (strcmp(toks[i], cryptos[j]->name) == 0) 2637 goto foundc1; 2638 sshdebug(nil, "c2s crypto algs not in cryptos"); 2639 free(buf); 2640 return -1; 2641 foundc1: 2642 p->c->ncscrypt = j; 2643 2644 q = get_string(p, q, buf, Bigbufsz, nil); 2645 sshdebug(nil, "received S2C crypto algs: %s", buf); 2646 n = gettokens(buf, toks, nelem(toks), ","); 2647 for (i = 0; i < n; ++i) 2648 for (j = 0; j < nelem(cryptos); ++j) 2649 if (strcmp(toks[i], cryptos[j]->name) == 0) 2650 goto foundc2; 2651 sshdebug(nil, "s2c crypto algs not in cryptos"); 2652 free(buf); 2653 return -1; 2654 foundc2: 2655 p->c->nsccrypt = j; 2656 2657 q = get_string(p, q, buf, Bigbufsz, nil); 2658 sshdebug(nil, "received C2S MAC algs: %s", buf); 2659 n = gettokens(buf, toks, nelem(toks), ","); 2660 for (i = 0; i < n; ++i) 2661 for (j = 0; j < nelem(macnames); ++j) 2662 if (strcmp(toks[i], macnames[j]) == 0) 2663 goto foundm1; 2664 sshdebug(nil, "c2s mac algs not in cryptos"); 2665 free(buf); 2666 return -1; 2667 foundm1: 2668 p->c->ncsmac = j; 2669 2670 q = get_string(p, q, buf, Bigbufsz, nil); 2671 sshdebug(nil, "received S2C MAC algs: %s", buf); 2672 n = gettokens(buf, toks, nelem(toks), ","); 2673 for (i = 0; i < n; ++i) 2674 for (j = 0; j < nelem(macnames); ++j) 2675 if (strcmp(toks[i], macnames[j]) == 0) 2676 goto foundm2; 2677 sshdebug(nil, "s2c mac algs not in cryptos"); 2678 free(buf); 2679 return -1; 2680 foundm2: 2681 p->c->nscmac = j; 2682 2683 q = get_string(p, q, buf, Bigbufsz, nil); 2684 q = get_string(p, q, buf, Bigbufsz, nil); 2685 q = get_string(p, q, buf, Bigbufsz, nil); 2686 q = get_string(p, q, buf, Bigbufsz, nil); 2687 free(buf); 2688 if (*q) 2689 return 1; 2690 return 0; 2691 } 2692 2693 int 2694 validatekexc(Packet *p) 2695 { 2696 uchar *q; 2697 char *toks[Maxtoks]; 2698 int i, j, n; 2699 char *buf; 2700 2701 buf = emalloc9p(Bigbufsz); 2702 q = p->payload + 17; 2703 q = get_string(p, q, buf, Bigbufsz, nil); 2704 n = gettokens(buf, toks, nelem(toks), ","); 2705 for (j = 0; j < nelem(kexes); ++j) 2706 for (i = 0; i < n; ++i) 2707 if (strcmp(toks[i], kexes[j]->name) == 0) 2708 goto foundk; 2709 free(buf); 2710 return -1; 2711 foundk: 2712 p->c->kexalg = j; 2713 2714 q = get_string(p, q, buf, Bigbufsz, nil); 2715 n = gettokens(buf, toks, nelem(toks), ","); 2716 for (j = 0; j < nelem(pkas) && pkas[j] != nil; ++j) 2717 for (i = 0; i < n; ++i) 2718 if (strcmp(toks[i], pkas[j]->name) == 0) 2719 goto foundpka; 2720 free(buf); 2721 return -1; 2722 foundpka: 2723 p->c->pkalg = j; 2724 2725 q = get_string(p, q, buf, Bigbufsz, nil); 2726 n = gettokens(buf, toks, nelem(toks), ","); 2727 for (j = 0; j < nelem(cryptos); ++j) 2728 for (i = 0; i < n; ++i) 2729 if (strcmp(toks[i], cryptos[j]->name) == 0) 2730 goto foundc1; 2731 free(buf); 2732 return -1; 2733 foundc1: 2734 p->c->ncscrypt = j; 2735 q = get_string(p, q, buf, Bigbufsz, nil); 2736 n = gettokens(buf, toks, nelem(toks), ","); 2737 for (j = 0; j < nelem(cryptos); ++j) 2738 for (i = 0; i < n; ++i) 2739 if (strcmp(toks[i], cryptos[j]->name) == 0) 2740 goto foundc2; 2741 free(buf); 2742 return -1; 2743 foundc2: 2744 p->c->nsccrypt = j; 2745 2746 q = get_string(p, q, buf, Bigbufsz, nil); 2747 n = gettokens(buf, toks, nelem(toks), ","); 2748 for (j = 0; j < nelem(macnames); ++j) 2749 for (i = 0; i < n; ++i) 2750 if (strcmp(toks[i], macnames[j]) == 0) 2751 goto foundm1; 2752 free(buf); 2753 return -1; 2754 foundm1: 2755 p->c->ncsmac = j; 2756 2757 q = get_string(p, q, buf, Bigbufsz, nil); 2758 n = gettokens(buf, toks, nelem(toks), ","); 2759 for (j = 0; j < nelem(macnames); ++j) 2760 for (i = 0; i < n; ++i) 2761 if (strcmp(toks[i], macnames[j]) == 0) 2762 goto foundm2; 2763 free(buf); 2764 return -1; 2765 foundm2: 2766 p->c->nscmac = j; 2767 2768 q = get_string(p, q, buf, Bigbufsz, nil); 2769 q = get_string(p, q, buf, Bigbufsz, nil); 2770 q = get_string(p, q, buf, Bigbufsz, nil); 2771 q = get_string(p, q, buf, Bigbufsz, nil); 2772 free(buf); 2773 return *q != 0; 2774 } 2775 2776 int 2777 memrandom(void *p, int n) 2778 { 2779 uchar *cp; 2780 2781 for (cp = (uchar*)p; n > 0; n--) 2782 *cp++ = fastrand(); 2783 return 0; 2784 } 2785 2786 /* 2787 * create a change uid capability 2788 */ 2789 char* 2790 mkcap(char *from, char *to) 2791 { 2792 int fd, fromtosz; 2793 char *cap, *key; 2794 uchar rand[SHA1dlen], hash[SHA1dlen]; 2795 2796 fd = open("#¤/caphash", OWRITE); 2797 if (fd < 0) 2798 sshlog(nil, "can't open #¤/caphash: %r"); 2799 2800 /* create the capability */ 2801 fromtosz = strlen(from) + 1 + strlen(to) + 1; 2802 cap = emalloc9p(fromtosz + sizeof(rand)*3 + 1); 2803 snprint(cap, fromtosz + sizeof(rand)*3 + 1, "%s@%s", from, to); 2804 memrandom(rand, sizeof(rand)); 2805 key = cap + fromtosz; 2806 enc64(key, sizeof(rand)*3, rand, sizeof(rand)); 2807 2808 /* hash the capability */ 2809 hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); 2810 2811 /* give the kernel the hash */ 2812 key[-1] = '@'; 2813 sshdebug(nil, "writing `%.*s' to caphash", SHA1dlen, hash); 2814 if (write(fd, hash, SHA1dlen) != SHA1dlen) { 2815 close(fd); 2816 free(cap); 2817 return nil; 2818 } 2819 close(fd); 2820 return cap; 2821 } 2822 2823 /* 2824 * ask keyfs (assumes we are on an auth server) 2825 */ 2826 static AuthInfo * 2827 keyfsauth(char *me, char *user, char *pw, char *key1, char *key2) 2828 { 2829 int fd; 2830 char path[Arbpathlen]; 2831 AuthInfo *ai; 2832 2833 if (passtokey(key1, pw) == 0) 2834 return nil; 2835 2836 snprint(path, Arbpathlen, "/mnt/keys/%s/key", user); 2837 if ((fd = open(path, OREAD)) < 0) { 2838 werrstr("Invalid user %s", user); 2839 return nil; 2840 } 2841 if (read(fd, key2, DESKEYLEN) != DESKEYLEN) { 2842 close(fd); 2843 werrstr("Password mismatch 1"); 2844 return nil; 2845 } 2846 close(fd); 2847 2848 if (memcmp(key1, key2, DESKEYLEN) != 0) { 2849 werrstr("Password mismatch 2"); 2850 return nil; 2851 } 2852 2853 ai = emalloc9p(sizeof(AuthInfo)); 2854 ai->cuid = estrdup9p(user); 2855 ai->suid = estrdup9p(me); 2856 ai->cap = mkcap(me, user); 2857 ai->nsecret = 0; 2858 ai->secret = (uchar *)estrdup9p(""); 2859 return ai; 2860 } 2861 2862 static void 2863 userauthfailed(Packet *p2) 2864 { 2865 add_byte(p2, SSH_MSG_USERAUTH_FAILURE); 2866 add_string(p2, "password,publickey"); 2867 add_byte(p2, 0); 2868 } 2869 2870 static int 2871 authreqpk(Packet *p, Packet *p2, Conn *c, char *user, uchar *q, 2872 char *alg, char *blob, char *sig, char *service, char *me) 2873 { 2874 int n, thisway, nblob, nsig; 2875 char method[32]; 2876 2877 sshdebug(c, "auth_req publickey for user %s", user); 2878 thisway = *q == '\0'; 2879 q = get_string(p, q+1, alg, Arbpathlen, nil); 2880 q = get_string(p, q, blob, Blobsz, &nblob); 2881 if (thisway) { 2882 /* 2883 * Should really check to see if this user can 2884 * be authed this way. 2885 */ 2886 for (n = 0; n < nelem(pkas) && pkas[n] != nil && 2887 strcmp(pkas[n]->name, alg) != 0; ++n) 2888 ; 2889 if (n >= nelem(pkas) || pkas[n] == nil) { 2890 userauthfailed(p2); 2891 return -1; 2892 } 2893 add_byte(p2, SSH_MSG_USERAUTH_PK_OK); 2894 add_string(p2, alg); 2895 add_block(p2, blob, nblob); 2896 return 1; 2897 } 2898 2899 get_string(p, q, sig, Blobsz, &nsig); 2900 for (n = 0; n < nelem(pkas) && pkas[n] != nil && 2901 strcmp(pkas[n]->name, alg) != 0; ++n) 2902 ; 2903 if (n >= nelem(pkas) || pkas[n] == nil) { 2904 userauthfailed(p2); 2905 return -1; 2906 } 2907 2908 add_block(p2, c->sessid, SHA1dlen); 2909 add_byte(p2, SSH_MSG_USERAUTH_REQUEST); 2910 add_string(p2, user); 2911 add_string(p2, service); 2912 add_string(p2, method); 2913 add_byte(p2, 1); 2914 add_string(p2, alg); 2915 add_block(p2, blob, nblob); 2916 if (pkas[n]->verify(c, p2->payload, p2->rlength - 1, user, sig, nsig) 2917 == 0) { 2918 init_packet(p2); 2919 p2->c = c; 2920 sshlog(c, "public key login failed"); 2921 userauthfailed(p2); 2922 return -1; 2923 } 2924 free(c->cap); 2925 c->cap = mkcap(me, user); 2926 init_packet(p2); 2927 p2->c = c; 2928 sshlog(c, "logged in by public key"); 2929 add_byte(p2, SSH_MSG_USERAUTH_SUCCESS); 2930 return 0; 2931 } 2932 2933 int 2934 auth_req(Packet *p, Conn *c) 2935 { 2936 int n, ret; 2937 char *alg, *blob, *sig, *service, *me, *user, *pw, *path; 2938 char key1[DESKEYLEN], key2[DESKEYLEN], method[32]; 2939 uchar *q; 2940 AuthInfo *ai; 2941 Packet *p2; 2942 2943 service = emalloc9p(Arbpathlen); 2944 me = emalloc9p(Arbpathlen); 2945 user = emalloc9p(Arbpathlen); 2946 pw = emalloc9p(Arbpathlen); 2947 alg = emalloc9p(Arbpathlen); 2948 path = emalloc9p(Arbpathlen); 2949 blob = emalloc9p(Blobsz); 2950 sig = emalloc9p(Blobsz); 2951 ret = -1; /* failure is default */ 2952 2953 q = get_string(p, p->payload + 1, user, Arbpathlen, nil); 2954 free(c->user); 2955 c->user = estrdup9p(user); 2956 q = get_string(p, q, service, Arbpathlen, nil); 2957 q = get_string(p, q, method, sizeof method, nil); 2958 sshdebug(c, "got userauth request: %s %s %s", user, service, method); 2959 2960 readfile("/dev/user", me, Arbpathlen); 2961 2962 p2 = new_packet(c); 2963 if (strcmp(method, "publickey") == 0) 2964 ret = authreqpk(p, p2, c, user, q, alg, blob, sig, service, me); 2965 else if (strcmp(method, "password") == 0) { 2966 get_string(p, q + 1, pw, Arbpathlen, nil); 2967 // sshdebug(c, "%s", pw); /* bad idea to log passwords */ 2968 sshdebug(c, "auth_req password"); 2969 if (kflag) 2970 ai = keyfsauth(me, user, pw, key1, key2); 2971 else 2972 ai = auth_userpasswd(user, pw); 2973 if (ai == nil) { 2974 sshlog(c, "login failed: %r"); 2975 userauthfailed(p2); 2976 } else { 2977 sshdebug(c, "auth successful: cuid %s suid %s cap %s", 2978 ai->cuid, ai->suid, ai->cap); 2979 free(c->cap); 2980 if (strcmp(user, me) == 0) 2981 c->cap = estrdup9p("n/a"); 2982 else 2983 c->cap = estrdup9p(ai->cap); 2984 sshlog(c, "logged in by password"); 2985 add_byte(p2, SSH_MSG_USERAUTH_SUCCESS); 2986 auth_freeAI(ai); 2987 ret = 0; 2988 } 2989 } else 2990 userauthfailed(p2); 2991 2992 n = finish_packet(p2); 2993 iowrite(c->dio, c->datafd, p2->nlength, n); 2994 2995 free(service); 2996 free(me); 2997 free(user); 2998 free(pw); 2999 free(alg); 3000 free(blob); 3001 free(sig); 3002 free(path); 3003 free(p2); 3004 return ret; 3005 } 3006 3007 int 3008 client_auth(Conn *c, Ioproc *io) 3009 { 3010 Packet *p2, *p3, *p4; 3011 char *r, *s; 3012 mpint *ek, *nk; 3013 int i, n; 3014 3015 sshdebug(c, "client_auth"); 3016 if (!c->password && !c->authkey) 3017 return -1; 3018 3019 p2 = new_packet(c); 3020 add_byte(p2, SSH_MSG_USERAUTH_REQUEST); 3021 add_string(p2, c->user); 3022 add_string(p2, c->service); 3023 if (c->password) { 3024 add_string(p2, "password"); 3025 add_byte(p2, 0); 3026 add_string(p2, c->password); 3027 sshdebug(c, "client_auth using password for svc %s", c->service); 3028 } else { 3029 sshdebug(c, "client_auth trying rsa public key"); 3030 add_string(p2, "publickey"); 3031 add_byte(p2, 1); 3032 add_string(p2, "ssh-rsa"); 3033 3034 r = strstr(c->authkey, " ek="); 3035 s = strstr(c->authkey, " n="); 3036 if (!r || !s) { 3037 shutdown(c); 3038 free(p2); 3039 sshdebug(c, "client_auth no rsa key"); 3040 return -1; 3041 } 3042 ek = strtomp(r+4, nil, 16, nil); 3043 nk = strtomp(s+3, nil, 16, nil); 3044 3045 p3 = new_packet(c); 3046 add_string(p3, "ssh-rsa"); 3047 add_mp(p3, ek); 3048 add_mp(p3, nk); 3049 add_block(p2, p3->payload, p3->rlength-1); 3050 3051 p4 = new_packet(c); 3052 add_block(p4, c->sessid, SHA1dlen); 3053 add_byte(p4, SSH_MSG_USERAUTH_REQUEST); 3054 add_string(p4, c->user); 3055 add_string(p4, c->service); 3056 add_string(p4, "publickey"); 3057 add_byte(p4, 1); 3058 add_string(p4, "ssh-rsa"); 3059 add_block(p4, p3->payload, p3->rlength-1); 3060 mpfree(ek); 3061 mpfree(nk); 3062 free(p3); 3063 3064 for (i = 0; pkas[i] && strcmp("ssh-rsa", pkas[i]->name) != 0; 3065 ++i) 3066 ; 3067 sshdebug(c, "client_auth rsa signing alg %d: %r", i); 3068 if ((p3 = pkas[i]->sign(c, p4->payload, p4->rlength-1)) == nil) { 3069 sshdebug(c, "client_auth rsa signing failed: %r"); 3070 free(p4); 3071 free(p2); 3072 return -1; 3073 } 3074 add_block(p2, p3->payload, p3->rlength-1); 3075 free(p3); 3076 free(p4); 3077 } 3078 3079 n = finish_packet(p2); 3080 if (writeio(io, c->datafd, p2->nlength, n) != n) 3081 sshdebug(c, "client_auth write failed: %r"); 3082 free(p2); 3083 return 0; 3084 } 3085 3086 /* should use auth_getkey or something similar */ 3087 char * 3088 factlookup(int nattr, int nreq, char *attrs[]) 3089 { 3090 Biobuf *bp; 3091 char *buf, *toks[Maxtoks], *res, *q; 3092 int ntok, nmatch, maxmatch; 3093 int i, j; 3094 3095 res = nil; 3096 bp = Bopen("/mnt/factotum/ctl", OREAD); 3097 if (bp == nil) 3098 return nil; 3099 maxmatch = 0; 3100 while (buf = Brdstr(bp, '\n', 1)) { 3101 q = estrdup9p(buf); 3102 ntok = gettokens(buf, toks, nelem(toks), " "); 3103 nmatch = 0; 3104 for (i = 0; i < nattr; ++i) { 3105 for (j = 0; j < ntok; ++j) 3106 if (strcmp(attrs[i], toks[j]) == 0) { 3107 ++nmatch; 3108 break; 3109 } 3110 if (i < nreq && j >= ntok) 3111 break; 3112 } 3113 if (i >= nattr && nmatch > maxmatch) { 3114 free(res); 3115 res = q; 3116 maxmatch = nmatch; 3117 } else 3118 free(q); 3119 free(buf); 3120 } 3121 Bterm(bp); 3122 return res; 3123 } 3124 3125 void 3126 shutdown(Conn *c) 3127 { 3128 Plist *p; 3129 SSHChan *sc; 3130 int i, ostate; 3131 3132 sshdebug(c, "shutting down connection %d", c->id); 3133 ostate = c->state; 3134 if (c->clonefile->ref <= 2 && c->ctlfile->ref <= 2 && 3135 c->datafile->ref <= 2 && c->listenfile->ref <= 2 && 3136 c->localfile->ref <= 2 && c->remotefile->ref <= 2 && 3137 c->statusfile->ref <= 2) 3138 c->state = Closed; 3139 else { 3140 if (c->state != Closed) 3141 c->state = Closing; 3142 sshdebug(c, "clone %ld ctl %ld data %ld listen %ld " 3143 "local %ld remote %ld status %ld", 3144 c->clonefile->ref, c->ctlfile->ref, c->datafile->ref, 3145 c->listenfile->ref, c->localfile->ref, c->remotefile->ref, 3146 c->statusfile->ref); 3147 } 3148 if (ostate == Closed || ostate == Closing) { 3149 c->state = Closed; 3150 return; 3151 } 3152 if (c->role == Server && c->remote) 3153 sshlog(c, "closing connection"); 3154 hangupconn(c); 3155 if (c->dio) { 3156 closeioproc(c->dio); 3157 c->dio = nil; 3158 } 3159 3160 c->decrypt = -1; 3161 c->inmac = -1; 3162 c->nchan = 0; 3163 free(c->otherid); 3164 free(c->s2ccs); 3165 c->s2ccs = nil; 3166 free(c->c2scs); 3167 c->c2scs = nil; 3168 free(c->remote); 3169 c->remote = nil; 3170 if (c->x) { 3171 mpfree(c->x); 3172 c->x = nil; 3173 } 3174 if (c->e) { 3175 mpfree(c->e); 3176 c->e = nil; 3177 } 3178 free(c->user); 3179 c->user = nil; 3180 free(c->service); 3181 c->service = nil; 3182 c->otherid = nil; 3183 qlock(&c->l); 3184 rwakeupall(&c->r); 3185 qunlock(&c->l); 3186 for (i = 0; i < MAXCONN; ++i) { 3187 sc = c->chans[i]; 3188 if (sc == nil) 3189 continue; 3190 free(sc->ann); 3191 sc->ann = nil; 3192 if (sc->state != Empty && sc->state != Closed) { 3193 sc->state = Closed; 3194 sc->lreq = nil; 3195 while (sc->dataq != nil) { 3196 p = sc->dataq; 3197 sc->dataq = p->next; 3198 free(p->pack); 3199 free(p); 3200 } 3201 while (sc->reqq != nil) { 3202 p = sc->reqq; 3203 sc->reqq = p->next; 3204 free(p->pack); 3205 free(p); 3206 } 3207 qlock(&c->l); 3208 rwakeupall(&sc->r); 3209 nbsendul(sc->inchan, 1); 3210 nbsendul(sc->reqchan, 1); 3211 chanclose(sc->inchan); 3212 chanclose(sc->reqchan); 3213 qunlock(&c->l); 3214 } 3215 } 3216 qlock(&availlck); 3217 rwakeup(&availrend); 3218 qunlock(&availlck); 3219 sshdebug(c, "done processing shutdown of connection %d", c->id); 3220 } 3221