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