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 #include <sys/stat.h> /* for stat, umask */ 5 #include <stdlib.h> /* for malloc */ 6 #include <string.h> /* for strcpy, memmove */ 7 #include <pwd.h> /* for getpwnam, getpwuid */ 8 #include <grp.h> /* for getgrnam, getgrgid */ 9 #include <unistd.h> /* for gethostname, pread, pwrite, read, write */ 10 #include <utime.h> /* for utime */ 11 #include <dirent.h> /* for readdir */ 12 #include <errno.h> /* for errno */ 13 #include <stdio.h> /* for remove [sic] */ 14 #include <fcntl.h> /* for O_RDONLY, etc. */ 15 16 #include <sys/socket.h> /* various networking crud */ 17 #include <netinet/in.h> 18 #include <netdb.h> 19 20 #include <fcall.h> 21 #include <oldfcall.h> 22 #include <u9fs.h> 23 24 /* #ifndef because can be given in makefile */ 25 #ifndef DEFAULTLOG 26 #define DEFAULTLOG "/tmp/u9fs.log" 27 #endif 28 29 char *logfile = DEFAULTLOG; 30 31 #define S_ISSPECIAL(m) (S_ISCHR(m) || S_ISBLK(m) || S_ISFIFO(m)) 32 33 enum { 34 Tdot = 1, 35 Tdotdot 36 }; 37 38 enum { 39 P9P1, 40 P9P2000 41 }; 42 43 typedef struct User User; 44 struct User { 45 int id; 46 gid_t defaultgid; 47 char *name; 48 char **mem; /* group members */ 49 int nmem; 50 User *next; 51 }; 52 53 struct Fid { 54 int fid; 55 char *path; 56 struct stat st; 57 User *u; 58 int omode; 59 DIR *dir; 60 int diroffset; 61 int fd; 62 struct dirent *dirent; 63 Fid *next; 64 Fid *prev; 65 int auth; 66 void *authmagic; 67 }; 68 69 void* emalloc(size_t); 70 void* erealloc(void*, size_t); 71 char* estrdup(char*); 72 char* estrpath(char*, char*); 73 void sysfatal(char*, ...); 74 int okuser(char*); 75 76 void rversion(Fcall*, Fcall*); 77 void rauth(Fcall*, Fcall*); 78 void rattach(Fcall*, Fcall*); 79 void rflush(Fcall*, Fcall*); 80 void rclone(Fcall*, Fcall*); 81 void rwalk(Fcall*, Fcall*); 82 void ropen(Fcall*, Fcall*); 83 void rcreate(Fcall*, Fcall*); 84 void rread(Fcall*, Fcall*); 85 void rwrite(Fcall*, Fcall*); 86 void rclunk(Fcall*, Fcall*); 87 void rstat(Fcall*, Fcall*); 88 void rwstat(Fcall*, Fcall*); 89 void rclwalk(Fcall*, Fcall*); 90 void rremove(Fcall*, Fcall*); 91 92 User* uname2user(char*); 93 User* gname2user(char*); 94 User* uid2user(int); 95 User* gid2user(int); 96 97 Fid* newfid(int, char**); 98 Fid* oldfidex(int, int, char**); 99 Fid* oldfid(int, char**); 100 int fidstat(Fid*, char**); 101 void freefid(Fid*); 102 103 int userchange(User*, char**); 104 int userwalk(User*, char**, char*, Qid*, char**); 105 int useropen(Fid*, int, char**); 106 int usercreate(Fid*, char*, int, long, char**); 107 int userremove(Fid*, char**); 108 int userperm(User*, char*, int, int); 109 int useringroup(User*, User*); 110 111 Qid stat2qid(struct stat*); 112 113 void getfcallold(int, Fcall*, int); 114 void putfcallold(int, Fcall*); 115 116 char Eauth[] = "authentication failed"; 117 char Ebadfid[] = "fid unknown or out of range"; 118 char Ebadoffset[] = "bad offset in directory read"; 119 char Ebadusefid[] = "bad use of fid"; 120 char Edirchange[] = "wstat can't convert between files and directories"; 121 char Eexist[] = "file or directory already exists"; 122 char Efidactive[] = "fid already in use"; 123 char Enotdir[] = "not a directory"; 124 char Enotingroup[] = "not a member of proposed group"; 125 char Enotowner[] = "only owner can change group in wstat"; 126 char Eperm[] = "permission denied"; 127 char Especial0[] = "already attached without access to special files"; 128 char Especial1[] = "already attached with access to special files"; 129 char Especial[] = "no access to special file"; 130 char Etoolarge[] = "i/o count too large"; 131 char Eunknowngroup[] = "unknown group"; 132 char Eunknownuser[] = "unknown user"; 133 char Ewstatbuffer[] = "bogus wstat buffer"; 134 135 ulong msize = IOHDRSZ+8192; 136 uchar* rxbuf; 137 uchar* txbuf; 138 void* databuf; 139 int connected; 140 int devallowed; 141 char* autharg; 142 char* defaultuser; 143 char hostname[256]; 144 char remotehostname[256]; 145 int chatty9p = 0; 146 int network = 1; 147 int old9p = -1; 148 int authed; 149 User* none; 150 151 Auth *authmethods[] = { /* first is default */ 152 &authrhosts, 153 &authp9any, 154 &authnone, 155 }; 156 157 Auth *auth; 158 159 void 160 getfcallnew(int fd, Fcall *fc, int have) 161 { 162 int len; 163 164 if(have > BIT32SZ) 165 sysfatal("cannot happen"); 166 167 if(have < BIT32SZ && readn(fd, rxbuf+have, BIT32SZ-have) != BIT32SZ-have) 168 sysfatal("couldn't read message"); 169 170 len = GBIT32(rxbuf); 171 if(len <= BIT32SZ) 172 sysfatal("bogus message"); 173 174 len -= BIT32SZ; 175 if(readn(fd, rxbuf+BIT32SZ, len) != len) 176 sysfatal("short message"); 177 178 if(convM2S(rxbuf, len+BIT32SZ, fc) != len+BIT32SZ) 179 sysfatal("badly sized message type %d", rxbuf[0]); 180 } 181 182 void 183 getfcallold(int fd, Fcall *fc, int have) 184 { 185 int len, n; 186 187 if(have > 3) 188 sysfatal("cannot happen"); 189 190 if(have < 3 && readn(fd, rxbuf, 3-have) != 3-have) 191 sysfatal("couldn't read message"); 192 193 len = oldhdrsize(rxbuf[0]); 194 if(len < 3) 195 sysfatal("bad message %d", rxbuf[0]); 196 if(len > 3 && readn(fd, rxbuf+3, len-3) != len-3) 197 sysfatal("couldn't read message"); 198 199 n = iosize(rxbuf); 200 if(readn(fd, rxbuf+len, n) != n) 201 sysfatal("couldn't read message"); 202 len += n; 203 204 if(convM2Sold(rxbuf, len, fc) != len) 205 sysfatal("badly sized message type %d", rxbuf[0]); 206 } 207 208 void 209 putfcallnew(int wfd, Fcall *tx) 210 { 211 uint n; 212 213 if((n = convS2M(tx, txbuf, msize)) == 0) 214 sysfatal("couldn't format message type %d", tx->type); 215 if(write(wfd, txbuf, n) != n) 216 sysfatal("couldn't send message"); 217 } 218 219 void 220 putfcallold(int wfd, Fcall *tx) 221 { 222 uint n; 223 224 if((n = convS2Mold(tx, txbuf, msize)) == 0) 225 sysfatal("couldn't format message type %d", tx->type); 226 if(write(wfd, txbuf, n) != n) 227 sysfatal("couldn't send message"); 228 } 229 230 void 231 getfcall(int fd, Fcall *fc) 232 { 233 if(old9p == 1){ 234 getfcallold(fd, fc, 0); 235 return; 236 } 237 if(old9p == 0){ 238 getfcallnew(fd, fc, 0); 239 return; 240 } 241 242 /* auto-detect */ 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 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, temp; 1095 1096 va_start(va, fmt); 1097 va_copy(temp, va); 1098 doprint(buf, buf+sizeof buf, fmt, &temp); 1099 va_end(temp); 1100 va_end(va); 1101 fprint(2, "u9fs: %s\n", buf); 1102 fprint(2, "last unix error: %s\n", strerror(errno)); 1103 exit(1); 1104 } 1105 1106 void* 1107 emalloc(size_t n) 1108 { 1109 void *p; 1110 1111 if(n == 0) 1112 n = 1; 1113 p = malloc(n); 1114 if(p == 0) 1115 sysfatal("malloc(%ld) fails", (long)n); 1116 memset(p, 0, n); 1117 return p; 1118 } 1119 1120 void* 1121 erealloc(void *p, size_t n) 1122 { 1123 if(p == 0) 1124 p = malloc(n); 1125 else 1126 p = realloc(p, n); 1127 if(p == 0) 1128 sysfatal("realloc(..., %ld) fails", (long)n); 1129 return p; 1130 } 1131 1132 char* 1133 estrdup(char *p) 1134 { 1135 p = strdup(p); 1136 if(p == 0) 1137 sysfatal("strdup(%.20s) fails", p); 1138 return p; 1139 } 1140 1141 char* 1142 estrpath(char *p, char *q) 1143 { 1144 char *r, *s; 1145 1146 if(strcmp(q, "..") == 0){ 1147 r = estrdup(p); 1148 if((s = strrchr(r, '/')) && s > r) 1149 *s = '\0'; 1150 else if(s == r) 1151 s[1] = '\0'; 1152 return r; 1153 } 1154 1155 r = emalloc(strlen(p)+1+strlen(q)+1); 1156 strcpy(r, p); 1157 if(r[0]=='\0' || r[strlen(r)-1] != '/') 1158 strcat(r, "/"); 1159 strcat(r, q); 1160 return r; 1161 } 1162 1163 Fid *fidtab[1]; 1164 1165 Fid* 1166 lookupfid(int fid) 1167 { 1168 Fid *f; 1169 1170 for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next) 1171 if(f->fid == fid) 1172 return f; 1173 return nil; 1174 } 1175 1176 Fid* 1177 newfid(int fid, char **ep) 1178 { 1179 Fid *f; 1180 1181 if(lookupfid(fid) != nil){ 1182 *ep = Efidactive; 1183 return nil; 1184 } 1185 1186 f = emalloc(sizeof(*f)); 1187 f->next = fidtab[fid%nelem(fidtab)]; 1188 if(f->next) 1189 f->next->prev = f; 1190 fidtab[fid%nelem(fidtab)] = f; 1191 f->fid = fid; 1192 f->fd = -1; 1193 f->omode = -1; 1194 return f; 1195 } 1196 1197 Fid* 1198 newauthfid(int fid, void *magic, char **ep) 1199 { 1200 Fid *af; 1201 af = newfid(fid, ep); 1202 if (af == nil) 1203 return nil; 1204 af->auth = 1; 1205 af->authmagic = magic; 1206 return af; 1207 } 1208 1209 Fid* 1210 oldfidex(int fid, int auth, char **ep) 1211 { 1212 Fid *f; 1213 1214 if((f = lookupfid(fid)) == nil){ 1215 *ep = Ebadfid; 1216 return nil; 1217 } 1218 1219 if (auth != -1 && f->auth != auth) { 1220 *ep = Ebadfid; 1221 return nil; 1222 } 1223 1224 if (!f->auth) { 1225 if(userchange(f->u, ep) < 0) 1226 return nil; 1227 } 1228 1229 return f; 1230 } 1231 1232 Fid* 1233 oldfid(int fid, char **ep) 1234 { 1235 return oldfidex(fid, 0, ep); 1236 } 1237 1238 Fid* 1239 oldauthfid(int fid, void **magic, char **ep) 1240 { 1241 Fid *af; 1242 af = oldfidex(fid, 1, ep); 1243 if (af == nil) 1244 return nil; 1245 *magic = af->authmagic; 1246 return af; 1247 } 1248 1249 void 1250 freefid(Fid *f) 1251 { 1252 if(f->prev) 1253 f->prev->next = f->next; 1254 else 1255 fidtab[f->fid%nelem(fidtab)] = f->next; 1256 if(f->next) 1257 f->next->prev = f->prev; 1258 if(f->dir) 1259 closedir(f->dir); 1260 if(f->fd) 1261 close(f->fd); 1262 free(f->path); 1263 free(f); 1264 } 1265 1266 int 1267 fidstat(Fid *fid, char **ep) 1268 { 1269 if(stat(fid->path, &fid->st) < 0){ 1270 fprint(2, "fidstat(%s) failed\n", fid->path); 1271 if(ep) 1272 *ep = strerror(errno); 1273 return -1; 1274 } 1275 if(S_ISDIR(fid->st.st_mode)) 1276 fid->st.st_size = 0; 1277 return 0; 1278 } 1279 1280 int 1281 userchange(User *u, char **ep) 1282 { 1283 if(defaultuser) 1284 return 0; 1285 1286 if(setreuid(0, 0) < 0){ 1287 fprint(2, "setreuid(0, 0) failed\n"); 1288 *ep = "cannot setuid back to root"; 1289 return -1; 1290 } 1291 1292 /* 1293 * Initgroups does not appear to be SUSV standard. 1294 * But it exists on SGI and on Linux, which makes me 1295 * think it's standard enough. We have to do something 1296 * like this, and the closest other function I can find is 1297 * setgroups (which initgroups eventually calls). 1298 * Setgroups is the same as far as standardization though, 1299 * so we're stuck using a non-SUSV call. Sigh. 1300 */ 1301 if(initgroups(u->name, u->defaultgid) < 0) 1302 fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno)); 1303 1304 if(setreuid(-1, u->id) < 0){ 1305 fprint(2, "setreuid(-1, %s) failed\n", u->name); 1306 *ep = strerror(errno); 1307 return -1; 1308 } 1309 1310 return 0; 1311 } 1312 1313 /* 1314 * We do our own checking here, then switch to root temporarily 1315 * to set our gid. In a perfect world, you'd be allowed to set your 1316 * egid to any of the supplemental groups of your euid, but this 1317 * is not the case on Linux 2.2.14 (and perhaps others). 1318 * 1319 * This is a race, of course, but it's a race against processes 1320 * that can edit the group lists. If you can do that, you can 1321 * change your own group without our help. 1322 */ 1323 int 1324 groupchange(User *u, User *g, char **ep) 1325 { 1326 if(g == nil) 1327 return -1; 1328 if(!useringroup(u, g)){ 1329 if(chatty9p) 1330 fprint(2, "%s not in group %s\n", u->name, g->name); 1331 *ep = Enotingroup; 1332 return -1; 1333 } 1334 1335 setreuid(0,0); 1336 if(setregid(-1, g->id) < 0){ 1337 fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id); 1338 *ep = strerror(errno); 1339 return -1; 1340 } 1341 if(userchange(u, ep) < 0) 1342 return -1; 1343 1344 return 0; 1345 } 1346 1347 1348 /* 1349 * An attempt to enforce permissions by looking at the 1350 * file system. Separation of checking permission and 1351 * actually performing the action is a terrible idea, of 1352 * course, so we use setreuid for most of the permission 1353 * enforcement. This is here only so we can give errors 1354 * on open(ORCLOSE) in some cases. 1355 */ 1356 int 1357 userperm(User *u, char *path, int type, int need) 1358 { 1359 char *p, *q; 1360 int i, have; 1361 struct stat st; 1362 User *g; 1363 1364 switch(type){ 1365 default: 1366 fprint(2, "bad type %d in userperm\n", type); 1367 return -1; 1368 case Tdot: 1369 if(stat(path, &st) < 0){ 1370 fprint(2, "userperm: stat(%s) failed\n", path); 1371 return -1; 1372 } 1373 break; 1374 case Tdotdot: 1375 p = estrdup(path); 1376 if((q = strrchr(p, '/'))==nil){ 1377 fprint(2, "userperm(%s, ..): bad path\n", p); 1378 free(p); 1379 return -1; 1380 } 1381 if(q > p) 1382 *q = '\0'; 1383 else 1384 *(q+1) = '\0'; 1385 if(stat(p, &st) < 0){ 1386 fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", 1387 p, path); 1388 free(p); 1389 return -1; 1390 } 1391 free(p); 1392 break; 1393 } 1394 1395 if(u == none){ 1396 fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode); 1397 have = st.st_mode&7; 1398 if((have&need)==need) 1399 return 0; 1400 return -1; 1401 } 1402 have = st.st_mode&7; 1403 if((uid_t)u->id == st.st_uid) 1404 have |= (st.st_mode>>6)&7; 1405 if((have&need)==need) 1406 return 0; 1407 if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */ 1408 return -1; 1409 g = gid2user(st.st_gid); 1410 for(i=0; i<g->nmem; i++){ 1411 if(strcmp(g->mem[i], u->name) == 0){ 1412 have |= (st.st_mode>>3)&7; 1413 break; 1414 } 1415 } 1416 if((have&need)==need) 1417 return 0; 1418 return -1; 1419 } 1420 1421 int 1422 userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) 1423 { 1424 char *npath; 1425 struct stat st; 1426 1427 npath = estrpath(*path, elem); 1428 if(stat(npath, &st) < 0){ 1429 free(npath); 1430 *ep = strerror(errno); 1431 return -1; 1432 } 1433 *qid = stat2qid(&st); 1434 free(*path); 1435 *path = npath; 1436 return 0; 1437 } 1438 1439 int 1440 useropen(Fid *fid, int omode, char **ep) 1441 { 1442 int a, o; 1443 1444 /* 1445 * Check this anyway, to try to head off problems later. 1446 */ 1447 if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){ 1448 *ep = Eperm; 1449 return -1; 1450 } 1451 1452 switch(omode&3){ 1453 default: 1454 *ep = "programmer error"; 1455 return -1; 1456 case OREAD: 1457 a = R_OK; 1458 o = O_RDONLY; 1459 break; 1460 case ORDWR: 1461 a = R_OK|W_OK; 1462 o = O_RDWR; 1463 break; 1464 case OWRITE: 1465 a = W_OK; 1466 o = O_WRONLY; 1467 break; 1468 case OEXEC: 1469 a = X_OK; 1470 o = O_RDONLY; 1471 break; 1472 } 1473 if(omode & OTRUNC){ 1474 a |= W_OK; 1475 o |= O_TRUNC; 1476 } 1477 1478 if(S_ISDIR(fid->st.st_mode)){ 1479 if(a != R_OK){ 1480 fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode); 1481 *ep = Eperm; 1482 return -1; 1483 } 1484 if((fid->dir = opendir(fid->path)) == nil){ 1485 *ep = strerror(errno); 1486 return -1; 1487 } 1488 }else{ 1489 /* 1490 * This is wrong because access used the real uid 1491 * and not the effective uid. Let the open sort it out. 1492 * 1493 if(access(fid->path, a) < 0){ 1494 *ep = strerror(errno); 1495 return -1; 1496 } 1497 * 1498 */ 1499 if((fid->fd = open(fid->path, o)) < 0){ 1500 *ep = strerror(errno); 1501 return -1; 1502 } 1503 } 1504 fid->omode = omode; 1505 return 0; 1506 } 1507 1508 int 1509 usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) 1510 { 1511 int o, m; 1512 char *opath, *npath; 1513 struct stat st, parent; 1514 1515 if(stat(fid->path, &parent) < 0){ 1516 *ep = strerror(errno); 1517 return -1; 1518 } 1519 1520 /* 1521 * Change group so that created file has expected group 1522 * by Plan 9 semantics. If that fails, might as well go 1523 * with the user's default group. 1524 */ 1525 if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0 1526 && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0) 1527 return -1; 1528 1529 m = (perm & DMDIR) ? 0777 : 0666; 1530 perm = perm & (~m | (fid->st.st_mode & m)); 1531 1532 npath = estrpath(fid->path, elem); 1533 if(perm & DMDIR){ 1534 if((omode&~ORCLOSE) != OREAD){ 1535 *ep = Eperm; 1536 free(npath); 1537 return -1; 1538 } 1539 if(stat(npath, &st) >= 0 || errno != ENOENT){ 1540 *ep = Eexist; 1541 free(npath); 1542 return -1; 1543 } 1544 /* race */ 1545 if(mkdir(npath, perm&0777) < 0){ 1546 *ep = strerror(errno); 1547 free(npath); 1548 return -1; 1549 } 1550 if((fid->dir = opendir(npath)) == nil){ 1551 *ep = strerror(errno); 1552 remove(npath); /* race */ 1553 free(npath); 1554 return -1; 1555 } 1556 }else{ 1557 o = O_CREAT|O_EXCL; 1558 switch(omode&3){ 1559 default: 1560 *ep = "programmer error"; 1561 return -1; 1562 case OREAD: 1563 case OEXEC: 1564 o |= O_RDONLY; 1565 break; 1566 case ORDWR: 1567 o |= O_RDWR; 1568 break; 1569 case OWRITE: 1570 o |= O_WRONLY; 1571 break; 1572 } 1573 if(omode & OTRUNC) 1574 o |= O_TRUNC; 1575 if((fid->fd = open(npath, o, perm&0777)) < 0){ 1576 if(chatty9p) 1577 fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777); 1578 *ep = strerror(errno); 1579 free(npath); 1580 return -1; 1581 } 1582 } 1583 1584 opath = fid->path; 1585 fid->path = npath; 1586 if(fidstat(fid, ep) < 0){ 1587 fprint(2, "stat after create on %s failed\n", npath); 1588 remove(npath); /* race */ 1589 free(npath); 1590 fid->path = opath; 1591 if(fid->fd >= 0){ 1592 close(fid->fd); 1593 fid->fd = -1; 1594 }else{ 1595 closedir(fid->dir); 1596 fid->dir = nil; 1597 } 1598 return -1; 1599 } 1600 fid->omode = omode; 1601 free(opath); 1602 return 0; 1603 } 1604 1605 int 1606 userremove(Fid *fid, char **ep) 1607 { 1608 if(remove(fid->path) < 0){ 1609 *ep = strerror(errno); 1610 return -1; 1611 } 1612 return 0; 1613 } 1614 1615 void 1616 usage(void) 1617 { 1618 fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n"); 1619 exit(1); 1620 } 1621 1622 int 1623 main(int argc, char **argv) 1624 { 1625 char *authtype; 1626 int i; 1627 int fd; 1628 int logflag; 1629 1630 auth = authmethods[0]; 1631 logflag = O_WRONLY|O_APPEND|O_CREAT; 1632 ARGBEGIN{ 1633 case 'D': 1634 chatty9p = 1; 1635 break; 1636 case 'a': 1637 authtype = EARGF(usage()); 1638 auth = nil; 1639 for(i=0; i<nelem(authmethods); i++) 1640 if(strcmp(authmethods[i]->name, authtype)==0) 1641 auth = authmethods[i]; 1642 if(auth == nil) 1643 sysfatal("unknown auth type '%s'", authtype); 1644 break; 1645 case 'A': 1646 autharg = EARGF(usage()); 1647 break; 1648 case 'l': 1649 logfile = EARGF(usage()); 1650 break; 1651 case 'm': 1652 msize = strtol(EARGF(usage()), 0, 0); 1653 break; 1654 case 'n': 1655 network = 0; 1656 break; 1657 case 'u': 1658 defaultuser = EARGF(usage()); 1659 break; 1660 case 'z': 1661 logflag |= O_TRUNC; 1662 }ARGEND 1663 1664 if(argc > 1) 1665 usage(); 1666 1667 fd = open(logfile, logflag, 0666); 1668 if(fd < 0) 1669 sysfatal("cannot open log '%s'", logfile); 1670 1671 if(dup2(fd, 2) < 0) 1672 sysfatal("cannot dup fd onto stderr"); 1673 fprint(2, "u9fs\nkill %d\n", (int)getpid()); 1674 1675 fmtinstall('F', fcallconv); 1676 fmtinstall('D', dirconv); 1677 fmtinstall('M', dirmodeconv); 1678 1679 rxbuf = emalloc(msize); 1680 txbuf = emalloc(msize); 1681 databuf = emalloc(msize); 1682 1683 if(auth->init) 1684 auth->init(); 1685 1686 if(network) 1687 getremotehostname(remotehostname, sizeof remotehostname); 1688 1689 if(gethostname(hostname, sizeof hostname) < 0) 1690 strcpy(hostname, "gnot"); 1691 1692 umask(0); 1693 1694 if(argc == 1) 1695 if(chroot(argv[0]) < 0) 1696 sysfatal("chroot '%s' failed", argv[0]); 1697 1698 none = uname2user("none"); 1699 1700 serve(0, 1); 1701 return 0; 1702 } 1703