1 /* already in plan9.h #include <sys/types.h> *//* for struct passwd, struct group, struct stat ... */ 2 #include <sys/stat.h> /* for stat, umask */ 3 #include <stdlib.h> /* for malloc */ 4 #include <string.h> /* for strcpy, memmove */ 5 #include <pwd.h> /* for getpwnam, getpwuid */ 6 #include <grp.h> /* for getgrnam, getgrgid */ 7 #include <unistd.h> /* for gethostname, pread, pwrite, read, write */ 8 #include <utime.h> /* for utime */ 9 #include <dirent.h> /* for readdir */ 10 #include <errno.h> /* for errno */ 11 #include <stdio.h> /* for remove [sic] */ 12 #include <fcntl.h> /* for O_RDONLY, etc. */ 13 14 #include <sys/socket.h> /* various networking crud */ 15 #include <netinet/in.h> 16 #include <netdb.h> 17 18 #include <plan9.h> 19 #include <fcall.h> 20 #include <oldfcall.h> 21 #include <u9fs.h> 22 23 /* #ifndef because can be given in makefile */ 24 #ifndef DEFAULTLOG 25 #define DEFAULTLOG "/tmp/u9fs.log" 26 #endif 27 28 char *logfile = DEFAULTLOG; 29 30 #define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m)) 31 32 enum { 33 Tdot = 1, 34 Tdotdot 35 }; 36 37 enum { 38 P9P1, 39 P9P2000 40 }; 41 42 typedef struct User User; 43 struct User { 44 int id; 45 gid_t defaultgid; 46 char *name; 47 char **mem; /* group members */ 48 int nmem; 49 User *next; 50 }; 51 52 struct Fid { 53 int fid; 54 char *path; 55 struct stat st; 56 User *u; 57 int omode; 58 DIR *dir; 59 int diroffset; 60 int fd; 61 struct dirent *dirent; 62 Fid *next; 63 Fid *prev; 64 int auth; 65 void *authmagic; 66 }; 67 68 void* emalloc(size_t); 69 void* erealloc(void*, size_t); 70 char* estrdup(char*); 71 char* estrpath(char*, char*); 72 void sysfatal(char*, ...); 73 int okuser(char*); 74 75 void rversion(Fcall*, Fcall*); 76 void rauth(Fcall*, Fcall*); 77 void rattach(Fcall*, Fcall*); 78 void rflush(Fcall*, Fcall*); 79 void rclone(Fcall*, Fcall*); 80 void rwalk(Fcall*, Fcall*); 81 void ropen(Fcall*, Fcall*); 82 void rcreate(Fcall*, Fcall*); 83 void rread(Fcall*, Fcall*); 84 void rwrite(Fcall*, Fcall*); 85 void rclunk(Fcall*, Fcall*); 86 void rstat(Fcall*, Fcall*); 87 void rwstat(Fcall*, Fcall*); 88 void rclwalk(Fcall*, Fcall*); 89 void rremove(Fcall*, Fcall*); 90 91 User* uname2user(char*); 92 User* gname2user(char*); 93 User* uid2user(int); 94 User* gid2user(int); 95 96 Fid* newfid(int, char**); 97 Fid* oldfidex(int, int, char**); 98 Fid* oldfid(int, char**); 99 int fidstat(Fid*, char**); 100 void freefid(Fid*); 101 102 int userchange(User*, char**); 103 int userwalk(User*, char**, char*, Qid*, char**); 104 int useropen(Fid*, int, char**); 105 int usercreate(Fid*, char*, int, long, char**); 106 int userremove(Fid*, char**); 107 int userperm(User*, char*, int, int); 108 int useringroup(User*, User*); 109 110 Qid stat2qid(struct stat*); 111 112 void getfcallold(int, Fcall*, int); 113 void putfcallold(int, Fcall*); 114 115 char Eauth[] = "authentication failed"; 116 char Ebadfid[] = "fid unknown or out of range"; 117 char Ebadoffset[] = "bad offset in directory read"; 118 char Ebadusefid[] = "bad use of fid"; 119 char Edirchange[] = "wstat can't convert between files and directories"; 120 char Eexist[] = "file or directory already exists"; 121 char Efidactive[] = "fid already in use"; 122 char Enotdir[] = "not a directory"; 123 char Enotingroup[] = "not a member of proposed group"; 124 char Enotowner[] = "only owner can change group in wstat"; 125 char Eperm[] = "permission denied"; 126 char Especial0[] = "already attached without access to special files"; 127 char Especial1[] = "already attached with access to special files"; 128 char Especial[] = "no access to special file"; 129 char Etoolarge[] = "i/o count too large"; 130 char Eunknowngroup[] = "unknown group"; 131 char Eunknownuser[] = "unknown user"; 132 char Ewstatbuffer[] = "bogus wstat buffer"; 133 134 ulong msize = IOHDRSZ+8192; 135 uchar* rxbuf; 136 uchar* txbuf; 137 void* databuf; 138 int connected; 139 int devallowed; 140 char* autharg; 141 char* defaultuser; 142 char hostname[256]; 143 char remotehostname[256]; 144 int chatty9p = 0; 145 int network = 1; 146 int old9p = -1; 147 int authed; 148 User* none; 149 150 Auth *authmethods[] = { /* first is default */ 151 &authrhosts, 152 &authp9any, 153 &authnone, 154 }; 155 156 Auth *auth; 157 158 void 159 getfcallnew(int fd, Fcall *fc, int have) 160 { 161 int len; 162 163 if(have > BIT32SZ) 164 sysfatal("cannot happen"); 165 166 if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have) 167 sysfatal("couldn't read message"); 168 169 len = GBIT32(rxbuf); 170 if(len <= BIT32SZ) 171 sysfatal("bogus message"); 172 173 len -= BIT32SZ; 174 if(readn(fd, rxbuf+BIT32SZ, len) != len) 175 sysfatal("short message"); 176 177 if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ) 178 sysfatal("badly sized message type %d", rxbuf[0]); 179 } 180 181 void 182 getfcallold(int fd, Fcall *fc, int have) 183 { 184 int len, n; 185 186 if(have > 3) 187 sysfatal("cannot happen"); 188 189 if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have) 190 sysfatal("couldn't read message"); 191 192 len = oldhdrsize(rxbuf[0]); 193 if(len < 3) 194 sysfatal("bad message %d", rxbuf[0]); 195 if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3) 196 sysfatal("couldn't read message"); 197 198 n = iosize(rxbuf); 199 if(readn(fd, rxbuf+len, n) != n) 200 sysfatal("couldn't read message"); 201 len += n; 202 203 if(convM2Sold(rxbuf, len, fc) != len) 204 sysfatal("badly sized message type %d", rxbuf[0]); 205 } 206 207 void 208 putfcallnew(int wfd, Fcall *tx) 209 { 210 uint n; 211 212 if((n = convS2M(tx, txbuf, msize)) == 0) 213 sysfatal("couldn't format message type %d", tx->type); 214 if(write(wfd, txbuf, n) != n) 215 sysfatal("couldn't send message"); 216 } 217 218 void 219 putfcallold(int wfd, Fcall *tx) 220 { 221 uint n; 222 223 if((n = convS2Mold(tx, txbuf, msize)) == 0) 224 sysfatal("couldn't format message type %d", tx->type); 225 if(write(wfd, txbuf, n) != n) 226 sysfatal("couldn't send message"); 227 } 228 229 void 230 getfcall(int fd, Fcall *fc) 231 { 232 if(old9p == 1){ 233 getfcallold(fd, fc, 0); 234 return; 235 } 236 if(old9p == 0){ 237 getfcallnew(fd, fc, 0); 238 return; 239 } 240 241 /* auto-detect */ 242 243 if(readn(fd, rxbuf, 3) != 3) 244 sysfatal("couldn't read message"); 245 246 /* is it an old (9P1) message? */ 247 if(50 <= rxbuf[0] && rxbuf[0] <= 87 && (rxbuf[0]&1)==0 && GBIT16(rxbuf+1) == 0xFFFF){ 248 old9p = 1; 249 getfcallold(fd, fc, 3); 250 return; 251 } 252 253 getfcallnew(fd, fc, 3); 254 old9p = 0; 255 } 256 257 void 258 seterror(Fcall *f, char *error) 259 { 260 f->type = Rerror; 261 f->ename = error ? error : "programmer error"; 262 } 263 264 int 265 isowner(User *u, Fid *f) 266 { 267 return u->id == f->st.st_uid; 268 } 269 270 void 271 serve(int rfd, int wfd) 272 { 273 Fcall rx, tx; 274 275 for(;;){ 276 getfcall(rfd, &rx); 277 278 if(chatty9p) 279 fprint(2, "<- %F\n", &rx); 280 281 memset(&tx, 0, sizeof tx); 282 tx.type = rx.type+1; 283 tx.tag = rx.tag; 284 switch(rx.type){ 285 case Tflush: 286 break; 287 case Tversion: 288 rversion(&rx, &tx); 289 break; 290 case Tauth: 291 rauth(&rx, &tx); 292 break; 293 case Tattach: 294 rattach(&rx, &tx); 295 break; 296 case Twalk: 297 rwalk(&rx, &tx); 298 break; 299 case Tstat: 300 tx.stat = databuf; 301 rstat(&rx, &tx); 302 break; 303 case Twstat: 304 rwstat(&rx, &tx); 305 break; 306 case Topen: 307 ropen(&rx, &tx); 308 break; 309 case Tcreate: 310 rcreate(&rx, &tx); 311 break; 312 case Tread: 313 tx.data = databuf; 314 rread(&rx, &tx); 315 break; 316 case Twrite: 317 rwrite(&rx, &tx); 318 break; 319 case Tclunk: 320 rclunk(&rx, &tx); 321 break; 322 case Tremove: 323 rremove(&rx, &tx); 324 break; 325 default: 326 fprint(2, "unknown message %F\n", &rx); 327 seterror(&tx, "bad message"); 328 break; 329 } 330 331 if(chatty9p) 332 fprint(2, "-> %F\n", &tx); 333 334 (old9p ? putfcallold : putfcallnew)(wfd, &tx); 335 } 336 } 337 338 void 339 rversion(Fcall *rx, Fcall *tx) 340 { 341 if(msize > rx->msize) 342 msize = rx->msize; 343 tx->msize = msize; 344 if(strncmp(rx->version, "9P", 2) != 0) 345 tx->version = "unknown"; 346 else 347 tx->version = "9P2000"; 348 } 349 350 void 351 rauth(Fcall *rx, Fcall *tx) 352 { 353 char *e; 354 355 if((e = auth->auth(rx, tx)) != nil) 356 seterror(tx, e); 357 } 358 359 void 360 rattach(Fcall *rx, Fcall *tx) 361 { 362 char *e; 363 Fid *fid; 364 User *u; 365 366 if(rx->aname == nil) 367 rx->aname = ""; 368 369 if(strcmp(rx->aname, "device") == 0){ 370 if(connected && !devallowed){ 371 seterror(tx, Especial0); 372 return; 373 } 374 devallowed = 1; 375 }else{ 376 if(connected && devallowed){ 377 seterror(tx, Especial1); 378 return; 379 } 380 } 381 382 if(strcmp(rx->uname, "none") == 0){ 383 if(authed == 0){ 384 seterror(tx, Eauth); 385 return; 386 } 387 } else { 388 if((e = auth->attach(rx, tx)) != nil){ 389 seterror(tx, e); 390 return; 391 } 392 authed++; 393 } 394 395 if((fid = newfid(rx->fid, &e)) == nil){ 396 seterror(tx, e); 397 return; 398 } 399 fid->path = estrdup("/"); 400 if(fidstat(fid, &e) < 0){ 401 seterror(tx, e); 402 freefid(fid); 403 return; 404 } 405 406 if(defaultuser) 407 rx->uname = defaultuser; 408 409 if((u = uname2user(rx->uname)) == nil 410 || (!defaultuser && u->id == 0)){ 411 /* we don't know anyone named root... */ 412 seterror(tx, Eunknownuser); 413 freefid(fid); 414 return; 415 } 416 417 fid->u = u; 418 tx->qid = stat2qid(&fid->st); 419 return; 420 } 421 422 void 423 rwalk(Fcall *rx, Fcall *tx) 424 { 425 int i; 426 char *path, *e; 427 Fid *fid, *nfid; 428 429 e = nil; 430 if((fid = oldfid(rx->fid, &e)) == nil){ 431 seterror(tx, e); 432 return; 433 } 434 435 if(fid->omode != -1){ 436 seterror(tx, Ebadusefid); 437 return; 438 } 439 440 if(fidstat(fid, &e) < 0){ 441 seterror(tx, e); 442 return; 443 } 444 445 if(!S_ISDIR(fid->st.st_mode) && rx->nwname){ 446 seterror(tx, Enotdir); 447 return; 448 } 449 450 nfid = nil; 451 if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){ 452 seterror(tx, e); 453 return; 454 } 455 456 path = estrdup(fid->path); 457 e = nil; 458 for(i=0; i<rx->nwname; i++) 459 if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0) 460 break; 461 462 if(i == rx->nwname){ /* successful clone or walk */ 463 tx->nwqid = i; 464 if(nfid){ 465 nfid->path = path; 466 nfid->u = fid->u; 467 }else{ 468 free(fid->path); 469 fid->path = path; 470 } 471 }else{ 472 if(i > 0) /* partial walk? */ 473 tx->nwqid = i; 474 else 475 seterror(tx, e); 476 477 if(nfid) /* clone implicit new fid */ 478 freefid(nfid); 479 free(path); 480 } 481 return; 482 } 483 484 void 485 ropen(Fcall *rx, Fcall *tx) 486 { 487 char *e; 488 Fid *fid; 489 490 if((fid = oldfid(rx->fid, &e)) == nil){ 491 seterror(tx, e); 492 return; 493 } 494 495 if(fid->omode != -1){ 496 seterror(tx, Ebadusefid); 497 return; 498 } 499 500 if(fidstat(fid, &e) < 0){ 501 seterror(tx, e); 502 return; 503 } 504 505 if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){ 506 seterror(tx, Especial); 507 return; 508 } 509 510 if(useropen(fid, rx->mode, &e) < 0){ 511 seterror(tx, e); 512 return; 513 } 514 515 tx->iounit = 0; 516 tx->qid = stat2qid(&fid->st); 517 } 518 519 void 520 rcreate(Fcall *rx, Fcall *tx) 521 { 522 char *e; 523 Fid *fid; 524 525 if((fid = oldfid(rx->fid, &e)) == nil){ 526 seterror(tx, e); 527 return; 528 } 529 530 if(fid->omode != -1){ 531 seterror(tx, Ebadusefid); 532 return; 533 } 534 535 if(fidstat(fid, &e) < 0){ 536 seterror(tx, e); 537 return; 538 } 539 540 if(!S_ISDIR(fid->st.st_mode)){ 541 seterror(tx, Enotdir); 542 return; 543 } 544 545 if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){ 546 seterror(tx, e); 547 return; 548 } 549 550 if(fidstat(fid, &e) < 0){ 551 seterror(tx, e); 552 return; 553 } 554 555 tx->iounit = 0; 556 tx->qid = stat2qid(&fid->st); 557 } 558 559 uchar 560 modebyte(struct stat *st) 561 { 562 uchar b; 563 564 b = 0; 565 566 if(S_ISDIR(st->st_mode)) 567 b |= QTDIR; 568 569 /* no way to test append-only */ 570 /* no real way to test exclusive use, but mark devices as such */ 571 if(S_ISSPECIAL(st->st_mode)) 572 b |= QTEXCL; 573 574 return b; 575 } 576 577 ulong 578 plan9mode(struct stat *st) 579 { 580 return ((ulong)modebyte(st)<<24) | (st->st_mode & 0777); 581 } 582 583 /* 584 * this is for chmod, so don't worry about S_IFDIR 585 */ 586 mode_t 587 unixmode(Dir *d) 588 { 589 return (mode_t)(d->mode&0777); 590 } 591 592 Qid 593 stat2qid(struct stat *st) 594 { 595 uchar *p, *ep, *q; 596 Qid qid; 597 598 /* 599 * For now, ignore the device number. 600 */ 601 qid.path = 0; 602 p = (uchar*)&qid.path; 603 ep = p+sizeof(qid.path); 604 q = p+sizeof(ino_t); 605 if(q > ep){ 606 fprint(2, "warning: inode number too big\n"); 607 q = ep; 608 } 609 memmove(p, &st->st_ino, q-p); 610 q = q+sizeof(dev_t); 611 if(q > ep){ 612 /* fprint(2, "warning: inode number + device number too big %d+%d\n", sizeof(ino_t), sizeof(dev_t)); */ 613 q = ep - sizeof(dev_t); 614 if(q < p) 615 fprint(2, "warning: device number too big by itself\n"); 616 else 617 *(dev_t*)q ^= st->st_dev; 618 } 619 620 qid.vers = st->st_mtime ^ (st->st_size << 8); 621 qid.type = modebyte(st); 622 return qid; 623 } 624 625 void 626 stat2dir(char *path, struct stat *st, Dir *d) 627 { 628 User *u; 629 char *q; 630 631 memset(d, 0, sizeof(*d)); 632 d->qid = stat2qid(st); 633 d->mode = plan9mode(st); 634 d->atime = st->st_atime; 635 d->mtime = st->st_mtime; 636 d->length = st->st_size; 637 638 d->uid = (u = uid2user(st->st_uid)) ? u->name : "???"; 639 d->gid = (u = gid2user(st->st_gid)) ? u->name : "???"; 640 d->muid = ""; 641 642 if((q = strrchr(path, '/')) != nil) 643 d->name = q+1; 644 else 645 d->name = path; 646 } 647 648 void 649 rread(Fcall *rx, Fcall *tx) 650 { 651 char *e, *path; 652 uchar *p, *ep; 653 int n; 654 Fid *fid; 655 Dir d; 656 struct stat st; 657 658 if(rx->count > msize-IOHDRSZ){ 659 seterror(tx, Etoolarge); 660 return; 661 } 662 663 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 664 seterror(tx, e); 665 return; 666 } 667 668 if (fid->auth) { 669 char *e; 670 e = auth->read(rx, tx); 671 if (e) 672 seterror(tx, e); 673 return; 674 } 675 676 if(fid->omode == -1 || (fid->omode&3) == OWRITE){ 677 seterror(tx, Ebadusefid); 678 return; 679 } 680 681 if(fid->dir){ 682 if(rx->offset != fid->diroffset){ 683 if(rx->offset != 0){ 684 seterror(tx, Ebadoffset); 685 return; 686 } 687 rewinddir(fid->dir); 688 fid->diroffset = 0; 689 } 690 691 p = (uchar*)tx->data; 692 ep = (uchar*)tx->data+rx->count; 693 for(;;){ 694 if(p+BIT16SZ >= ep) 695 break; 696 if(fid->dirent == nil) /* one entry cache for when convD2M fails */ 697 if((fid->dirent = readdir(fid->dir)) == nil) 698 break; 699 if(strcmp(fid->dirent->d_name, ".") == 0 700 || strcmp(fid->dirent->d_name, "..") == 0){ 701 fid->dirent = nil; 702 continue; 703 } 704 path = estrpath(fid->path, fid->dirent->d_name); 705 memset(&st, 0, sizeof st); 706 if(stat(path, &st) < 0){ 707 fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno)); 708 fid->dirent = nil; 709 free(path); 710 continue; 711 } 712 free(path); 713 stat2dir(fid->dirent->d_name, &st, &d); 714 if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ) 715 break; 716 p += n; 717 fid->dirent = nil; 718 } 719 tx->count = p - (uchar*)tx->data; 720 fid->diroffset += tx->count; 721 }else{ 722 if((n = pread(fid->fd, tx->data, rx->count, rx->offset)) < 0){ 723 seterror(tx, strerror(errno)); 724 return; 725 } 726 tx->count = n; 727 } 728 } 729 730 void 731 rwrite(Fcall *rx, Fcall *tx) 732 { 733 char *e; 734 Fid *fid; 735 int n; 736 737 if(rx->count > msize-IOHDRSZ){ 738 seterror(tx, Etoolarge); 739 return; 740 } 741 742 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 743 seterror(tx, e); 744 return; 745 } 746 747 if (fid->auth) { 748 char *e; 749 e = auth->write(rx, tx); 750 if (e) 751 seterror(tx, e); 752 return; 753 } 754 755 if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){ 756 seterror(tx, Ebadusefid); 757 return; 758 } 759 760 if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){ 761 seterror(tx, strerror(errno)); 762 return; 763 } 764 tx->count = n; 765 } 766 767 void 768 rclunk(Fcall *rx, Fcall *tx) 769 { 770 char *e; 771 Fid *fid; 772 773 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 774 seterror(tx, e); 775 return; 776 } 777 if (fid->auth) { 778 if (auth->clunk) { 779 e = (*auth->clunk)(rx, tx); 780 if (e) { 781 seterror(tx, e); 782 return; 783 } 784 } 785 } 786 else if(fid->omode != -1 && fid->omode&ORCLOSE) 787 remove(fid->path); 788 freefid(fid); 789 } 790 791 void 792 rremove(Fcall *rx, Fcall *tx) 793 { 794 char *e; 795 Fid *fid; 796 797 if((fid = oldfid(rx->fid, &e)) == nil){ 798 seterror(tx, e); 799 return; 800 } 801 if(userremove(fid, &e) < 0) 802 seterror(tx, e); 803 freefid(fid); 804 } 805 806 void 807 rstat(Fcall *rx, Fcall *tx) 808 { 809 char *e; 810 Fid *fid; 811 Dir d; 812 813 if((fid = oldfid(rx->fid, &e)) == nil){ 814 seterror(tx, e); 815 return; 816 } 817 818 if(fidstat(fid, &e) < 0){ 819 seterror(tx, e); 820 return; 821 } 822 823 stat2dir(fid->path, &fid->st, &d); 824 if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ) 825 seterror(tx, "convD2M fails"); 826 } 827 828 void 829 rwstat(Fcall *rx, Fcall *tx) 830 { 831 char *e; 832 char *p, *old, *new, *dir; 833 gid_t gid; 834 Dir d; 835 Fid *fid; 836 837 if((fid = oldfid(rx->fid, &e)) == nil){ 838 seterror(tx, e); 839 return; 840 } 841 842 /* 843 * wstat is supposed to be atomic. 844 * we check all the things we can before trying anything. 845 * still, if we are told to truncate a file and rename it and only 846 * one works, we're screwed. in such cases we leave things 847 * half broken and return an error. it's hardly perfect. 848 */ 849 if((old9p ? convM2Dold : convM2D)(rx->stat, rx->nstat, &d, (char*)rx->stat) <= BIT16SZ){ 850 seterror(tx, Ewstatbuffer); 851 return; 852 } 853 854 if(fidstat(fid, &e) < 0){ 855 seterror(tx, e); 856 return; 857 } 858 859 /* 860 * The casting is necessary because d.mode is ulong and might, 861 * on some systems, be 64 bits. We only want to compare the 862 * bottom 32 bits, since that's all that gets sent in the protocol. 863 * 864 * Same situation for d.mtime and d.length (although that last check 865 * is admittedly superfluous, given the current lack of 128-bit machines). 866 */ 867 gid = (gid_t)-1; 868 if(d.gid[0] != '\0'){ 869 User *g; 870 871 g = gname2user(d.gid); 872 if(g == nil){ 873 seterror(tx, Eunknowngroup); 874 return; 875 } 876 gid = (gid_t)g->id; 877 878 if(groupchange(fid->u, gid2user(gid), &e) < 0){ 879 seterror(tx, e); 880 return; 881 } 882 } 883 884 if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){ 885 seterror(tx, Edirchange); 886 return; 887 } 888 889 if(strcmp(fid->path, "/") == 0){ 890 seterror(tx, "no wstat of root"); 891 return; 892 } 893 894 /* 895 * try things in increasing order of harm to the file. 896 * mtime should come after truncate so that if you 897 * do both the mtime actually takes effect, but i'd rather 898 * leave truncate until last. 899 * (see above comment about atomicity). 900 */ 901 if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){ 902 if(chatty9p) 903 fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d)); 904 seterror(tx, strerror(errno)); 905 return; 906 } 907 908 if((u32int)d.mtime != (u32int)~0){ 909 struct utimbuf t; 910 911 t.actime = 0; 912 t.modtime = d.mtime; 913 if(utime(fid->path, &t) < 0){ 914 if(chatty9p) 915 fprint(2, "utime(%s) failed\n", fid->path); 916 seterror(tx, strerror(errno)); 917 return; 918 } 919 } 920 921 if(gid != (gid_t)-1 && gid != fid->st.st_gid){ 922 if(chown(fid->path, (uid_t)-1, gid) < 0){ 923 if(chatty9p) 924 fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid); 925 seterror(tx, strerror(errno)); 926 return; 927 } 928 } 929 930 if(d.name[0]){ 931 old = fid->path; 932 dir = estrdup(fid->path); 933 if((p = strrchr(dir, '/')) > dir) 934 *p = '\0'; 935 else{ 936 seterror(tx, "whoops: can't happen in u9fs"); 937 return; 938 } 939 940 new = estrpath(dir, d.name); 941 if(strcmp(old, new) != 0 && rename(old, new) < 0){ 942 if(chatty9p) 943 fprint(2, "rename(%s, %s) failed\n", old, new); 944 seterror(tx, strerror(errno)); 945 free(new); 946 free(dir); 947 return; 948 } 949 fid->path = new; 950 free(old); 951 free(dir); 952 } 953 954 if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){ 955 fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length); 956 seterror(tx, strerror(errno)); 957 return; 958 } 959 } 960 961 /* 962 * we keep a table by numeric id. by name lookups happen infrequently 963 * while by-number lookups happen once for every directory entry read 964 * and every stat request. 965 */ 966 User *utab[64]; 967 User *gtab[64]; 968 969 User* 970 adduser(struct passwd *p) 971 { 972 User *u; 973 974 u = emalloc(sizeof(*u)); 975 u->id = p->pw_uid; 976 u->name = estrdup(p->pw_name); 977 u->next = utab[p->pw_uid%nelem(utab)]; 978 u->defaultgid = p->pw_gid; 979 utab[p->pw_uid%nelem(utab)] = u; 980 return u; 981 } 982 983 int 984 useringroup(User *u, User *g) 985 { 986 int i; 987 988 for(i=0; i<g->nmem; i++) 989 if(strcmp(g->mem[i], u->name) == 0) 990 return 1; 991 992 /* 993 * Hack around common Unix problem that everyone has 994 * default group "user" but /etc/group lists no members. 995 */ 996 if(u->defaultgid == g->id) 997 return 1; 998 return 0; 999 } 1000 1001 User* 1002 addgroup(struct group *g) 1003 { 1004 User *u; 1005 char **p; 1006 int n; 1007 1008 u = emalloc(sizeof(*u)); 1009 n = 0; 1010 for(p=g->gr_mem; *p; p++) 1011 n++; 1012 u->mem = emalloc(sizeof(u->mem[0])*n); 1013 n = 0; 1014 for(p=g->gr_mem; *p; p++) 1015 u->mem[n++] = estrdup(*p); 1016 u->nmem = n; 1017 u->id = g->gr_gid; 1018 u->name = estrdup(g->gr_name); 1019 u->next = gtab[g->gr_gid%nelem(gtab)]; 1020 gtab[g->gr_gid%nelem(gtab)] = u; 1021 return u; 1022 } 1023 1024 User* 1025 uname2user(char *name) 1026 { 1027 int i; 1028 User *u; 1029 struct passwd *p; 1030 1031 for(i=0; i<nelem(utab); i++) 1032 for(u=utab[i]; u; u=u->next) 1033 if(strcmp(u->name, name) == 0) 1034 return u; 1035 1036 if((p = getpwnam(name)) == nil) 1037 return nil; 1038 return adduser(p); 1039 } 1040 1041 User* 1042 uid2user(int id) 1043 { 1044 User *u; 1045 struct passwd *p; 1046 1047 for(u=utab[id%nelem(utab)]; u; u=u->next) 1048 if(u->id == id) 1049 return u; 1050 1051 if((p = getpwuid(id)) == nil) 1052 return nil; 1053 return adduser(p); 1054 } 1055 1056 User* 1057 gname2user(char *name) 1058 { 1059 int i; 1060 User *u; 1061 struct group *g; 1062 1063 for(i=0; i<nelem(gtab); i++) 1064 for(u=gtab[i]; u; u=u->next) 1065 if(strcmp(u->name, name) == 0) 1066 return u; 1067 1068 if((g = getgrnam(name)) == nil) 1069 return nil; 1070 return addgroup(g); 1071 } 1072 1073 User* 1074 gid2user(int id) 1075 { 1076 User *u; 1077 struct group *g; 1078 1079 for(u=gtab[id%nelem(gtab)]; u; u=u->next) 1080 if(u->id == id) 1081 return u; 1082 1083 if((g = getgrgid(id)) == nil) 1084 return nil; 1085 return addgroup(g); 1086 } 1087 1088 void 1089 sysfatal(char *fmt, ...) 1090 { 1091 char buf[1024]; 1092 va_list va; 1093 1094 va_start(va, fmt); 1095 doprint(buf, buf+sizeof buf, fmt, va); 1096 va_end(va); 1097 fprint(2, "u9fs: %s\n", buf); 1098 fprint(2, "last unix error: %s\n", strerror(errno)); 1099 exit(1); 1100 } 1101 1102 void* 1103 emalloc(size_t n) 1104 { 1105 void *p; 1106 1107 if(n == 0) 1108 n = 1; 1109 p = malloc(n); 1110 if(p == 0) 1111 sysfatal("malloc(%ld) fails", (long)n); 1112 memset(p, 0, n); 1113 return p; 1114 } 1115 1116 void* 1117 erealloc(void *p, size_t n) 1118 { 1119 if(p == 0) 1120 p = malloc(n); 1121 else 1122 p = realloc(p, n); 1123 if(p == 0) 1124 sysfatal("realloc(..., %ld) fails", (long)n); 1125 return p; 1126 } 1127 1128 char* 1129 estrdup(char *p) 1130 { 1131 p = strdup(p); 1132 if(p == 0) 1133 sysfatal("strdup(%.20s) fails", p); 1134 return p; 1135 } 1136 1137 char* 1138 estrpath(char *p, char *q) 1139 { 1140 char *r, *s; 1141 1142 if(strcmp(q, "..") == 0){ 1143 r = estrdup(p); 1144 if((s = strrchr(r, '/')) && s > r) 1145 *s = '\0'; 1146 else if(s == r) 1147 s[1] = '\0'; 1148 return r; 1149 } 1150 1151 r = emalloc(strlen(p)+1+strlen(q)+1); 1152 strcpy(r, p); 1153 if(r[0]=='\0' || r[strlen(r)-1] != '/') 1154 strcat(r, "/"); 1155 strcat(r, q); 1156 return r; 1157 } 1158 1159 Fid *fidtab[1]; 1160 1161 Fid* 1162 lookupfid(int fid) 1163 { 1164 Fid *f; 1165 1166 for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next) 1167 if(f->fid == fid) 1168 return f; 1169 return nil; 1170 } 1171 1172 Fid* 1173 newfid(int fid, char **ep) 1174 { 1175 Fid *f; 1176 1177 if(lookupfid(fid) != nil){ 1178 *ep = Efidactive; 1179 return nil; 1180 } 1181 1182 f = emalloc(sizeof(*f)); 1183 f->next = fidtab[fid%nelem(fidtab)]; 1184 if(f->next) 1185 f->next->prev = f; 1186 fidtab[fid%nelem(fidtab)] = f; 1187 f->fid = fid; 1188 f->fd = -1; 1189 f->omode = -1; 1190 return f; 1191 } 1192 1193 Fid* 1194 newauthfid(int fid, void *magic, char **ep) 1195 { 1196 Fid *af; 1197 af = newfid(fid, ep); 1198 if (af == nil) 1199 return nil; 1200 af->auth = 1; 1201 af->authmagic = magic; 1202 return af; 1203 } 1204 1205 Fid* 1206 oldfidex(int fid, int auth, char **ep) 1207 { 1208 Fid *f; 1209 1210 if((f = lookupfid(fid)) == nil){ 1211 *ep = Ebadfid; 1212 return nil; 1213 } 1214 1215 if (auth != -1 && f->auth != auth) { 1216 *ep = Ebadfid; 1217 return nil; 1218 } 1219 1220 if (!f->auth) { 1221 if(userchange(f->u, ep) < 0) 1222 return nil; 1223 } 1224 1225 return f; 1226 } 1227 1228 Fid* 1229 oldfid(int fid, char **ep) 1230 { 1231 return oldfidex(fid, 0, ep); 1232 } 1233 1234 Fid* 1235 oldauthfid(int fid, void **magic, char **ep) 1236 { 1237 Fid *af; 1238 af = oldfidex(fid, 1, ep); 1239 if (af == nil) 1240 return nil; 1241 *magic = af->authmagic; 1242 return af; 1243 } 1244 1245 void 1246 freefid(Fid *f) 1247 { 1248 if(f->prev) 1249 f->prev->next = f->next; 1250 else 1251 fidtab[f->fid%nelem(fidtab)] = f->next; 1252 if(f->next) 1253 f->next->prev = f->prev; 1254 if(f->dir) 1255 closedir(f->dir); 1256 if(f->fd) 1257 close(f->fd); 1258 free(f->path); 1259 free(f); 1260 } 1261 1262 int 1263 fidstat(Fid *fid, char **ep) 1264 { 1265 if(stat(fid->path, &fid->st) < 0){ 1266 fprint(2, "fidstat(%s) failed\n", fid->path); 1267 if(ep) 1268 *ep = strerror(errno); 1269 return -1; 1270 } 1271 if(S_ISDIR(fid->st.st_mode)) 1272 fid->st.st_size = 0; 1273 return 0; 1274 } 1275 1276 int 1277 userchange(User *u, char **ep) 1278 { 1279 if(defaultuser) 1280 return 0; 1281 1282 if(setreuid(0, 0) < 0){ 1283 fprint(2, "setreuid(0, 0) failed\n"); 1284 *ep = "cannot setuid back to root"; 1285 return -1; 1286 } 1287 1288 /* 1289 * Initgroups does not appear to be SUSV standard. 1290 * But it exists on SGI and on Linux, which makes me 1291 * think it's standard enough. We have to do something 1292 * like this, and the closest other function I can find is 1293 * setgroups (which initgroups eventually calls). 1294 * Setgroups is the same as far as standardization though, 1295 * so we're stuck using a non-SUSV call. Sigh. 1296 */ 1297 if(initgroups(u->name, u->defaultgid) < 0) 1298 fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno)); 1299 1300 if(setreuid(-1, u->id) < 0){ 1301 fprint(2, "setreuid(-1, %s) failed\n", u->name); 1302 *ep = strerror(errno); 1303 return -1; 1304 } 1305 1306 return 0; 1307 } 1308 1309 /* 1310 * We do our own checking here, then switch to root temporarily 1311 * to set our gid. In a perfect world, you'd be allowed to set your 1312 * egid to any of the supplemental groups of your euid, but this 1313 * is not the case on Linux 2.2.14 (and perhaps others). 1314 * 1315 * This is a race, of course, but it's a race against processes 1316 * that can edit the group lists. If you can do that, you can 1317 * change your own group without our help. 1318 */ 1319 int 1320 groupchange(User *u, User *g, char **ep) 1321 { 1322 if(g == nil) 1323 return -1; 1324 if(!useringroup(u, g)){ 1325 if(chatty9p) 1326 fprint(2, "%s not in group %s\n", u->name, g->name); 1327 *ep = Enotingroup; 1328 return -1; 1329 } 1330 1331 setreuid(0,0); 1332 if(setregid(-1, g->id) < 0){ 1333 fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id); 1334 *ep = strerror(errno); 1335 return -1; 1336 } 1337 if(userchange(u, ep) < 0) 1338 return -1; 1339 1340 return 0; 1341 } 1342 1343 1344 /* 1345 * An attempt to enforce permissions by looking at the 1346 * file system. Separation of checking permission and 1347 * actually performing the action is a terrible idea, of 1348 * course, so we use setreuid for most of the permission 1349 * enforcement. This is here only so we can give errors 1350 * on open(ORCLOSE) in some cases. 1351 */ 1352 int 1353 userperm(User *u, char *path, int type, int need) 1354 { 1355 char *p, *q; 1356 int i, have; 1357 struct stat st; 1358 User *g; 1359 1360 switch(type){ 1361 default: 1362 fprint(2, "bad type %d in userperm\n", type); 1363 return -1; 1364 case Tdot: 1365 if(stat(path, &st) < 0){ 1366 fprint(2, "userperm: stat(%s) failed\n", path); 1367 return -1; 1368 } 1369 break; 1370 case Tdotdot: 1371 p = estrdup(path); 1372 if((q = strrchr(p, '/'))==nil){ 1373 fprint(2, "userperm(%s, ..): bad path\n", p); 1374 free(p); 1375 return -1; 1376 } 1377 if(q > p) 1378 *q = '\0'; 1379 else 1380 *(q+1) = '\0'; 1381 if(stat(p, &st) < 0){ 1382 fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", 1383 p, path); 1384 free(p); 1385 return -1; 1386 } 1387 free(p); 1388 break; 1389 } 1390 1391 if(u == none){ 1392 fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode); 1393 have = st.st_mode&7; 1394 if((have&need)==need) 1395 return 0; 1396 return -1; 1397 } 1398 have = st.st_mode&7; 1399 if((uid_t)u->id == st.st_uid) 1400 have |= (st.st_mode>>6)&7; 1401 if((have&need)==need) 1402 return 0; 1403 if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */ 1404 return -1; 1405 g = gid2user(st.st_gid); 1406 for(i=0; i<g->nmem; i++){ 1407 if(strcmp(g->mem[i], u->name) == 0){ 1408 have |= (st.st_mode>>3)&7; 1409 break; 1410 } 1411 } 1412 if((have&need)==need) 1413 return 0; 1414 return -1; 1415 } 1416 1417 int 1418 userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) 1419 { 1420 char *npath; 1421 struct stat st; 1422 1423 npath = estrpath(*path, elem); 1424 if(stat(npath, &st) < 0){ 1425 free(npath); 1426 *ep = strerror(errno); 1427 return -1; 1428 } 1429 *qid = stat2qid(&st); 1430 free(*path); 1431 *path = npath; 1432 return 0; 1433 } 1434 1435 int 1436 useropen(Fid *fid, int omode, char **ep) 1437 { 1438 int a, o; 1439 1440 /* 1441 * Check this anyway, to try to head off problems later. 1442 */ 1443 if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){ 1444 *ep = Eperm; 1445 return -1; 1446 } 1447 1448 switch(omode&3){ 1449 default: 1450 *ep = "programmer error"; 1451 return -1; 1452 case OREAD: 1453 a = R_OK; 1454 o = O_RDONLY; 1455 break; 1456 case ORDWR: 1457 a = R_OK|W_OK; 1458 o = O_RDWR; 1459 break; 1460 case OWRITE: 1461 a = W_OK; 1462 o = O_WRONLY; 1463 break; 1464 case OEXEC: 1465 a = X_OK; 1466 o = O_RDONLY; 1467 break; 1468 } 1469 if(omode & OTRUNC){ 1470 a |= W_OK; 1471 o |= O_TRUNC; 1472 } 1473 1474 if(S_ISDIR(fid->st.st_mode)){ 1475 if(a != R_OK){ 1476 fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode); 1477 *ep = Eperm; 1478 return -1; 1479 } 1480 if((fid->dir = opendir(fid->path)) == nil){ 1481 *ep = strerror(errno); 1482 return -1; 1483 } 1484 }else{ 1485 /* 1486 * This is wrong because access used the real uid 1487 * and not the effective uid. Let the open sort it out. 1488 * 1489 if(access(fid->path, a) < 0){ 1490 *ep = strerror(errno); 1491 return -1; 1492 } 1493 * 1494 */ 1495 if((fid->fd = open(fid->path, o)) < 0){ 1496 *ep = strerror(errno); 1497 return -1; 1498 } 1499 } 1500 fid->omode = omode; 1501 return 0; 1502 } 1503 1504 int 1505 usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) 1506 { 1507 int o, m; 1508 char *opath, *npath; 1509 struct stat st, parent; 1510 1511 if(stat(fid->path, &parent) < 0){ 1512 *ep = strerror(errno); 1513 return -1; 1514 } 1515 1516 /* 1517 * Change group so that created file has expected group 1518 * by Plan 9 semantics. If that fails, might as well go 1519 * with the user's default group. 1520 */ 1521 if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0 1522 && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0) 1523 return -1; 1524 1525 m = (perm & DMDIR) ? 0777 : 0666; 1526 perm = perm & (~m | (fid->st.st_mode & m)); 1527 1528 npath = estrpath(fid->path, elem); 1529 if(perm & DMDIR){ 1530 if((omode&~ORCLOSE) != OREAD){ 1531 *ep = Eperm; 1532 free(npath); 1533 return -1; 1534 } 1535 if(stat(npath, &st) >= 0 || errno != ENOENT){ 1536 *ep = Eexist; 1537 free(npath); 1538 return -1; 1539 } 1540 /* race */ 1541 if(mkdir(npath, perm&0777) < 0){ 1542 *ep = strerror(errno); 1543 free(npath); 1544 return -1; 1545 } 1546 if((fid->dir = opendir(npath)) == nil){ 1547 *ep = strerror(errno); 1548 remove(npath); /* race */ 1549 free(npath); 1550 return -1; 1551 } 1552 }else{ 1553 o = O_CREAT|O_EXCL; 1554 switch(omode&3){ 1555 default: 1556 *ep = "programmer error"; 1557 return -1; 1558 case OREAD: 1559 case OEXEC: 1560 o |= O_RDONLY; 1561 break; 1562 case ORDWR: 1563 o |= O_RDWR; 1564 break; 1565 case OWRITE: 1566 o |= O_WRONLY; 1567 break; 1568 } 1569 if(omode & OTRUNC) 1570 o |= O_TRUNC; 1571 if((fid->fd = open(npath, o, perm&0777)) < 0){ 1572 if(chatty9p) 1573 fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777); 1574 *ep = strerror(errno); 1575 free(npath); 1576 return -1; 1577 } 1578 } 1579 1580 opath = fid->path; 1581 fid->path = npath; 1582 if(fidstat(fid, ep) < 0){ 1583 fprint(2, "stat after create on %s failed\n", npath); 1584 remove(npath); /* race */ 1585 free(npath); 1586 fid->path = opath; 1587 if(fid->fd >= 0){ 1588 close(fid->fd); 1589 fid->fd = -1; 1590 }else{ 1591 closedir(fid->dir); 1592 fid->dir = nil; 1593 } 1594 return -1; 1595 } 1596 fid->omode = omode; 1597 free(opath); 1598 return 0; 1599 } 1600 1601 int 1602 userremove(Fid *fid, char **ep) 1603 { 1604 if(remove(fid->path) < 0){ 1605 *ep = strerror(errno); 1606 return -1; 1607 } 1608 return 0; 1609 } 1610 1611 void 1612 usage(void) 1613 { 1614 fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n"); 1615 exit(1); 1616 } 1617 1618 int 1619 main(int argc, char **argv) 1620 { 1621 char *authtype; 1622 int i; 1623 int fd; 1624 int logflag; 1625 1626 auth = authmethods[0]; 1627 logflag = O_WRONLY|O_APPEND|O_CREAT; 1628 ARGBEGIN{ 1629 case 'D': 1630 chatty9p = 1; 1631 break; 1632 case 'a': 1633 authtype = EARGF(usage()); 1634 auth = nil; 1635 for(i=0; i<nelem(authmethods); i++) 1636 if(strcmp(authmethods[i]->name, authtype)==0) 1637 auth = authmethods[i]; 1638 if(auth == nil) 1639 sysfatal("unknown auth type '%s'", authtype); 1640 break; 1641 case 'A': 1642 autharg = EARGF(usage()); 1643 break; 1644 case 'l': 1645 logfile = EARGF(usage()); 1646 break; 1647 case 'm': 1648 msize = strtol(EARGF(usage()), 0, 0); 1649 break; 1650 case 'n': 1651 network = 0; 1652 break; 1653 case 'u': 1654 defaultuser = EARGF(usage()); 1655 break; 1656 case 'z': 1657 logflag |= O_TRUNC; 1658 }ARGEND 1659 1660 if(argc > 1) 1661 usage(); 1662 1663 fd = open(logfile, logflag, 0666); 1664 if(fd < 0) 1665 sysfatal("cannot open log '%s'", logfile); 1666 1667 if(dup2(fd, 2) < 0) 1668 sysfatal("cannot dup fd onto stderr"); 1669 fprint(2, "u9fs\nkill %d\n", (int)getpid()); 1670 1671 fmtinstall('F', fcallconv); 1672 fmtinstall('D', dirconv); 1673 fmtinstall('M', dirmodeconv); 1674 1675 rxbuf = emalloc(msize); 1676 txbuf = emalloc(msize); 1677 databuf = emalloc(msize); 1678 1679 if(auth->init) 1680 auth->init(); 1681 1682 if(network) 1683 getremotehostname(remotehostname, sizeof remotehostname); 1684 1685 if(gethostname(hostname, sizeof hostname) < 0) 1686 strcpy(hostname, "gnot"); 1687 1688 umask(0); 1689 1690 if(argc == 1) 1691 if(chroot(argv[0]) < 0) 1692 sysfatal("chroot '%s' failed", argv[0]); 1693 1694 none = uname2user("none"); 1695 serve(0, 1); 1696 return 0; 1697 } 1698