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 || u->id == 0){ 410 /* we don't know anyone named root... */ 411 seterror(tx, Eunknownuser); 412 freefid(fid); 413 return; 414 } 415 416 fid->u = u; 417 tx->qid = stat2qid(&fid->st); 418 return; 419 } 420 421 void 422 rwalk(Fcall *rx, Fcall *tx) 423 { 424 int i; 425 char *path, *e; 426 Fid *fid, *nfid; 427 428 e = nil; 429 if((fid = oldfid(rx->fid, &e)) == nil){ 430 seterror(tx, e); 431 return; 432 } 433 434 if(fid->omode != -1){ 435 seterror(tx, Ebadusefid); 436 return; 437 } 438 439 if(fidstat(fid, &e) < 0){ 440 seterror(tx, e); 441 return; 442 } 443 444 if(!S_ISDIR(fid->st.st_mode) && rx->nwname){ 445 seterror(tx, Enotdir); 446 return; 447 } 448 449 nfid = nil; 450 if(rx->newfid != rx->fid && (nfid = newfid(rx->newfid, &e)) == nil){ 451 seterror(tx, e); 452 return; 453 } 454 455 path = estrdup(fid->path); 456 e = nil; 457 for(i=0; i<rx->nwname; i++) 458 if(userwalk(fid->u, &path, rx->wname[i], &tx->wqid[i], &e) < 0) 459 break; 460 461 if(i == rx->nwname){ /* successful clone or walk */ 462 tx->nwqid = i; 463 if(nfid){ 464 nfid->path = path; 465 nfid->u = fid->u; 466 }else{ 467 free(fid->path); 468 fid->path = path; 469 } 470 }else{ 471 if(i > 0) /* partial walk? */ 472 tx->nwqid = i; 473 else 474 seterror(tx, e); 475 476 if(nfid) /* clone implicit new fid */ 477 freefid(nfid); 478 free(path); 479 } 480 return; 481 } 482 483 void 484 ropen(Fcall *rx, Fcall *tx) 485 { 486 char *e; 487 Fid *fid; 488 489 if((fid = oldfid(rx->fid, &e)) == nil){ 490 seterror(tx, e); 491 return; 492 } 493 494 if(fid->omode != -1){ 495 seterror(tx, Ebadusefid); 496 return; 497 } 498 499 if(fidstat(fid, &e) < 0){ 500 seterror(tx, e); 501 return; 502 } 503 504 if(!devallowed && S_ISSPECIAL(fid->st.st_mode)){ 505 seterror(tx, Especial); 506 return; 507 } 508 509 if(useropen(fid, rx->mode, &e) < 0){ 510 seterror(tx, e); 511 return; 512 } 513 514 tx->iounit = 0; 515 tx->qid = stat2qid(&fid->st); 516 } 517 518 void 519 rcreate(Fcall *rx, Fcall *tx) 520 { 521 char *e; 522 Fid *fid; 523 524 if((fid = oldfid(rx->fid, &e)) == nil){ 525 seterror(tx, e); 526 return; 527 } 528 529 if(fid->omode != -1){ 530 seterror(tx, Ebadusefid); 531 return; 532 } 533 534 if(fidstat(fid, &e) < 0){ 535 seterror(tx, e); 536 return; 537 } 538 539 if(!S_ISDIR(fid->st.st_mode)){ 540 seterror(tx, Enotdir); 541 return; 542 } 543 544 if(usercreate(fid, rx->name, rx->mode, rx->perm, &e) < 0){ 545 seterror(tx, e); 546 return; 547 } 548 549 if(fidstat(fid, &e) < 0){ 550 seterror(tx, e); 551 return; 552 } 553 554 tx->iounit = 0; 555 tx->qid = stat2qid(&fid->st); 556 } 557 558 uchar 559 modebyte(struct stat *st) 560 { 561 uchar b; 562 563 b = 0; 564 565 if(S_ISDIR(st->st_mode)) 566 b |= QTDIR; 567 568 /* no way to test append-only */ 569 /* no real way to test exclusive use, but mark devices as such */ 570 if(S_ISSPECIAL(st->st_mode)) 571 b |= QTEXCL; 572 573 return b; 574 } 575 576 ulong 577 plan9mode(struct stat *st) 578 { 579 return ((ulong)modebyte(st)<<24) | (st->st_mode & 0777); 580 } 581 582 /* 583 * this is for chmod, so don't worry about S_IFDIR 584 */ 585 mode_t 586 unixmode(Dir *d) 587 { 588 return (mode_t)(d->mode&0777); 589 } 590 591 Qid 592 stat2qid(struct stat *st) 593 { 594 uchar *p, *ep, *q; 595 Qid qid; 596 597 /* 598 * For now, ignore the device number. 599 */ 600 qid.path = 0; 601 p = (uchar*)&qid.path; 602 ep = p+sizeof(qid.path); 603 q = p+sizeof(ino_t); 604 if(q > ep){ 605 fprint(2, "warning: inode number too big\n"); 606 q = ep; 607 } 608 memmove(p, &st->st_ino, q-p); 609 q = q+sizeof(dev_t); 610 if(q > ep){ 611 /* fprint(2, "warning: inode number + device number too big %d+%d\n", sizeof(ino_t), sizeof(dev_t)); */ 612 q = ep - sizeof(dev_t); 613 if(q < p) 614 fprint(2, "warning: device number too big by itself\n"); 615 else 616 *(dev_t*)q ^= st->st_dev; 617 } 618 619 qid.vers = st->st_mtime ^ (st->st_size << 8); 620 qid.type = modebyte(st); 621 return qid; 622 } 623 624 void 625 stat2dir(char *path, struct stat *st, Dir *d) 626 { 627 User *u; 628 char *q; 629 630 memset(d, 0, sizeof(*d)); 631 d->qid = stat2qid(st); 632 d->mode = plan9mode(st); 633 d->atime = st->st_atime; 634 d->mtime = st->st_mtime; 635 d->length = st->st_size; 636 637 d->uid = (u = uid2user(st->st_uid)) ? u->name : "???"; 638 d->gid = (u = gid2user(st->st_gid)) ? u->name : "???"; 639 d->muid = ""; 640 641 if((q = strrchr(path, '/')) != nil) 642 d->name = q+1; 643 else 644 d->name = path; 645 } 646 647 void 648 rread(Fcall *rx, Fcall *tx) 649 { 650 char *e, *path; 651 uchar *p, *ep; 652 int n; 653 Fid *fid; 654 Dir d; 655 struct stat st; 656 657 if(rx->count > msize-IOHDRSZ){ 658 seterror(tx, Etoolarge); 659 return; 660 } 661 662 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 663 seterror(tx, e); 664 return; 665 } 666 667 if (fid->auth) { 668 char *e; 669 e = auth->read(rx, tx); 670 if (e) 671 seterror(tx, e); 672 return; 673 } 674 675 if(fid->omode == -1 || (fid->omode&3) == OWRITE){ 676 seterror(tx, Ebadusefid); 677 return; 678 } 679 680 if(fid->dir){ 681 if(rx->offset != fid->diroffset){ 682 if(rx->offset != 0){ 683 seterror(tx, Ebadoffset); 684 return; 685 } 686 rewinddir(fid->dir); 687 fid->diroffset = 0; 688 } 689 690 p = (uchar*)tx->data; 691 ep = (uchar*)tx->data+rx->count; 692 for(;;){ 693 if(p+BIT16SZ >= ep) 694 break; 695 if(fid->dirent == nil) /* one entry cache for when convD2M fails */ 696 if((fid->dirent = readdir(fid->dir)) == nil) 697 break; 698 if(strcmp(fid->dirent->d_name, ".") == 0 699 || strcmp(fid->dirent->d_name, "..") == 0){ 700 fid->dirent = nil; 701 continue; 702 } 703 path = estrpath(fid->path, fid->dirent->d_name); 704 memset(&st, 0, sizeof st); 705 if(stat(path, &st) < 0){ 706 fprint(2, "dirread: stat(%s) failed: %s\n", path, strerror(errno)); 707 fid->dirent = nil; 708 free(path); 709 continue; 710 } 711 free(path); 712 stat2dir(fid->dirent->d_name, &st, &d); 713 if((n=(old9p ? convD2Mold : convD2M)(&d, p, ep-p)) <= BIT16SZ) 714 break; 715 p += n; 716 fid->dirent = nil; 717 } 718 tx->count = p - (uchar*)tx->data; 719 fid->diroffset += tx->count; 720 }else{ 721 if((n = pread(fid->fd, tx->data, rx->count, rx->offset)) < 0){ 722 seterror(tx, strerror(errno)); 723 return; 724 } 725 tx->count = n; 726 } 727 } 728 729 void 730 rwrite(Fcall *rx, Fcall *tx) 731 { 732 char *e; 733 Fid *fid; 734 int n; 735 736 if(rx->count > msize-IOHDRSZ){ 737 seterror(tx, Etoolarge); 738 return; 739 } 740 741 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 742 seterror(tx, e); 743 return; 744 } 745 746 if (fid->auth) { 747 char *e; 748 e = auth->write(rx, tx); 749 if (e) 750 seterror(tx, e); 751 return; 752 } 753 754 if(fid->omode == -1 || (fid->omode&3) == OREAD || (fid->omode&3) == OEXEC){ 755 seterror(tx, Ebadusefid); 756 return; 757 } 758 759 if((n = pwrite(fid->fd, rx->data, rx->count, rx->offset)) < 0){ 760 seterror(tx, strerror(errno)); 761 return; 762 } 763 tx->count = n; 764 } 765 766 void 767 rclunk(Fcall *rx, Fcall *tx) 768 { 769 char *e; 770 Fid *fid; 771 772 if((fid = oldfidex(rx->fid, -1, &e)) == nil){ 773 seterror(tx, e); 774 return; 775 } 776 if (fid->auth) { 777 if (auth->clunk) { 778 e = (*auth->clunk)(rx, tx); 779 if (e) { 780 seterror(tx, e); 781 return; 782 } 783 } 784 } 785 else if(fid->omode != -1 && fid->omode&ORCLOSE) 786 remove(fid->path); 787 freefid(fid); 788 } 789 790 void 791 rremove(Fcall *rx, Fcall *tx) 792 { 793 char *e; 794 Fid *fid; 795 796 if((fid = oldfid(rx->fid, &e)) == nil){ 797 seterror(tx, e); 798 return; 799 } 800 if(userremove(fid, &e) < 0) 801 seterror(tx, e); 802 freefid(fid); 803 } 804 805 void 806 rstat(Fcall *rx, Fcall *tx) 807 { 808 char *e; 809 Fid *fid; 810 Dir d; 811 812 if((fid = oldfid(rx->fid, &e)) == nil){ 813 seterror(tx, e); 814 return; 815 } 816 817 if(fidstat(fid, &e) < 0){ 818 seterror(tx, e); 819 return; 820 } 821 822 stat2dir(fid->path, &fid->st, &d); 823 if((tx->nstat=(old9p ? convD2Mold : convD2M)(&d, tx->stat, msize)) <= BIT16SZ) 824 seterror(tx, "convD2M fails"); 825 } 826 827 void 828 rwstat(Fcall *rx, Fcall *tx) 829 { 830 char *e; 831 char *p, *old, *new, *dir; 832 gid_t gid; 833 Dir d; 834 Fid *fid; 835 836 if((fid = oldfid(rx->fid, &e)) == nil){ 837 seterror(tx, e); 838 return; 839 } 840 841 /* 842 * wstat is supposed to be atomic. 843 * we check all the things we can before trying anything. 844 * still, if we are told to truncate a file and rename it and only 845 * one works, we're screwed. in such cases we leave things 846 * half broken and return an error. it's hardly perfect. 847 */ 848 if((old9p ? convM2Dold : convM2D)(rx->stat, rx->nstat, &d, (char*)rx->stat) <= BIT16SZ){ 849 seterror(tx, Ewstatbuffer); 850 return; 851 } 852 853 if(fidstat(fid, &e) < 0){ 854 seterror(tx, e); 855 return; 856 } 857 858 /* 859 * The casting is necessary because d.mode is ulong and might, 860 * on some systems, be 64 bits. We only want to compare the 861 * bottom 32 bits, since that's all that gets sent in the protocol. 862 * 863 * Same situation for d.mtime and d.length (although that last check 864 * is admittedly superfluous, given the current lack of 128-bit machines). 865 */ 866 gid = (gid_t)-1; 867 if(d.gid[0] != '\0'){ 868 User *g; 869 870 g = gname2user(d.gid); 871 if(g == nil){ 872 seterror(tx, Eunknowngroup); 873 return; 874 } 875 gid = (gid_t)g->id; 876 877 if(groupchange(fid->u, gid2user(gid), &e) < 0){ 878 seterror(tx, e); 879 return; 880 } 881 } 882 883 if((u32int)d.mode != (u32int)~0 && (((d.mode&DMDIR)!=0) ^ (S_ISDIR(fid->st.st_mode)!=0))){ 884 seterror(tx, Edirchange); 885 return; 886 } 887 888 if(strcmp(fid->path, "/") == 0){ 889 seterror(tx, "no wstat of root"); 890 return; 891 } 892 893 /* 894 * try things in increasing order of harm to the file. 895 * mtime should come after truncate so that if you 896 * do both the mtime actually takes effect, but i'd rather 897 * leave truncate until last. 898 * (see above comment about atomicity). 899 */ 900 if((u32int)d.mode != (u32int)~0 && chmod(fid->path, unixmode(&d)) < 0){ 901 if(chatty9p) 902 fprint(2, "chmod(%s, 0%luo) failed\n", fid->path, unixmode(&d)); 903 seterror(tx, strerror(errno)); 904 return; 905 } 906 907 if((u32int)d.mtime != (u32int)~0){ 908 struct utimbuf t; 909 910 t.actime = 0; 911 t.modtime = d.mtime; 912 if(utime(fid->path, &t) < 0){ 913 if(chatty9p) 914 fprint(2, "utime(%s) failed\n", fid->path); 915 seterror(tx, strerror(errno)); 916 return; 917 } 918 } 919 920 if(gid != (gid_t)-1 && gid != fid->st.st_gid){ 921 if(chown(fid->path, (uid_t)-1, gid) < 0){ 922 if(chatty9p) 923 fprint(2, "chgrp(%s, %d) failed\n", fid->path, gid); 924 seterror(tx, strerror(errno)); 925 return; 926 } 927 } 928 929 if(d.name[0]){ 930 old = fid->path; 931 dir = estrdup(fid->path); 932 if((p = strrchr(dir, '/')) > dir) 933 *p = '\0'; 934 else{ 935 seterror(tx, "whoops: can't happen in u9fs"); 936 return; 937 } 938 939 new = estrpath(dir, d.name); 940 if(strcmp(old, new) != 0 && rename(old, new) < 0){ 941 if(chatty9p) 942 fprint(2, "rename(%s, %s) failed\n", old, new); 943 seterror(tx, strerror(errno)); 944 free(new); 945 free(dir); 946 return; 947 } 948 fid->path = new; 949 free(old); 950 free(dir); 951 } 952 953 if((u64int)d.length != (u64int)~0 && truncate(fid->path, d.length) < 0){ 954 fprint(2, "truncate(%s, %lld) failed\n", fid->path, d.length); 955 seterror(tx, strerror(errno)); 956 return; 957 } 958 } 959 960 /* 961 * we keep a table by numeric id. by name lookups happen infrequently 962 * while by-number lookups happen once for every directory entry read 963 * and every stat request. 964 */ 965 User *utab[64]; 966 User *gtab[64]; 967 968 User* 969 adduser(struct passwd *p) 970 { 971 User *u; 972 973 u = emalloc(sizeof(*u)); 974 u->id = p->pw_uid; 975 u->name = estrdup(p->pw_name); 976 u->next = utab[p->pw_uid%nelem(utab)]; 977 u->defaultgid = p->pw_gid; 978 utab[p->pw_uid%nelem(utab)] = u; 979 return u; 980 } 981 982 int 983 useringroup(User *u, User *g) 984 { 985 int i; 986 987 for(i=0; i<g->nmem; i++) 988 if(strcmp(g->mem[i], u->name) == 0) 989 return 1; 990 991 /* 992 * Hack around common Unix problem that everyone has 993 * default group "user" but /etc/group lists no members. 994 */ 995 if(u->defaultgid == g->id) 996 return 1; 997 return 0; 998 } 999 1000 User* 1001 addgroup(struct group *g) 1002 { 1003 User *u; 1004 char **p; 1005 int n; 1006 1007 u = emalloc(sizeof(*u)); 1008 n = 0; 1009 for(p=g->gr_mem; *p; p++) 1010 n++; 1011 u->mem = emalloc(sizeof(u->mem[0])*n); 1012 n = 0; 1013 for(p=g->gr_mem; *p; p++) 1014 u->mem[n++] = estrdup(*p); 1015 u->nmem = n; 1016 u->id = g->gr_gid; 1017 u->name = estrdup(g->gr_name); 1018 u->next = gtab[g->gr_gid%nelem(gtab)]; 1019 gtab[g->gr_gid%nelem(gtab)] = u; 1020 return u; 1021 } 1022 1023 User* 1024 uname2user(char *name) 1025 { 1026 int i; 1027 User *u; 1028 struct passwd *p; 1029 1030 for(i=0; i<nelem(utab); i++) 1031 for(u=utab[i]; u; u=u->next) 1032 if(strcmp(u->name, name) == 0) 1033 return u; 1034 1035 if((p = getpwnam(name)) == nil) 1036 return nil; 1037 return adduser(p); 1038 } 1039 1040 User* 1041 uid2user(int id) 1042 { 1043 User *u; 1044 struct passwd *p; 1045 1046 for(u=utab[id%nelem(utab)]; u; u=u->next) 1047 if(u->id == id) 1048 return u; 1049 1050 if((p = getpwuid(id)) == nil) 1051 return nil; 1052 return adduser(p); 1053 } 1054 1055 User* 1056 gname2user(char *name) 1057 { 1058 int i; 1059 User *u; 1060 struct group *g; 1061 1062 for(i=0; i<nelem(gtab); i++) 1063 for(u=gtab[i]; u; u=u->next) 1064 if(strcmp(u->name, name) == 0) 1065 return u; 1066 1067 if((g = getgrnam(name)) == nil) 1068 return nil; 1069 return addgroup(g); 1070 } 1071 1072 User* 1073 gid2user(int id) 1074 { 1075 User *u; 1076 struct group *g; 1077 1078 for(u=gtab[id%nelem(gtab)]; u; u=u->next) 1079 if(u->id == id) 1080 return u; 1081 1082 if((g = getgrgid(id)) == nil) 1083 return nil; 1084 return addgroup(g); 1085 } 1086 1087 void 1088 sysfatal(char *fmt, ...) 1089 { 1090 char buf[1024]; 1091 va_list va; 1092 1093 va_start(va, fmt); 1094 doprint(buf, buf+sizeof buf, fmt, va); 1095 va_end(va); 1096 fprint(2, "u9fs: %s\n", buf); 1097 fprint(2, "last unix error: %s\n", strerror(errno)); 1098 exit(1); 1099 } 1100 1101 void* 1102 emalloc(size_t n) 1103 { 1104 void *p; 1105 1106 if(n == 0) 1107 n = 1; 1108 p = malloc(n); 1109 if(p == 0) 1110 sysfatal("malloc(%ld) fails", (long)n); 1111 memset(p, 0, n); 1112 return p; 1113 } 1114 1115 void* 1116 erealloc(void *p, size_t n) 1117 { 1118 if(p == 0) 1119 p = malloc(n); 1120 else 1121 p = realloc(p, n); 1122 if(p == 0) 1123 sysfatal("realloc(..., %ld) fails", (long)n); 1124 return p; 1125 } 1126 1127 char* 1128 estrdup(char *p) 1129 { 1130 p = strdup(p); 1131 if(p == 0) 1132 sysfatal("strdup(%.20s) fails", p); 1133 return p; 1134 } 1135 1136 char* 1137 estrpath(char *p, char *q) 1138 { 1139 char *r, *s; 1140 1141 if(strcmp(q, "..") == 0){ 1142 r = estrdup(p); 1143 if((s = strrchr(r, '/')) && s > r) 1144 *s = '\0'; 1145 else if(s == r) 1146 s[1] = '\0'; 1147 return r; 1148 } 1149 1150 r = emalloc(strlen(p)+1+strlen(q)+1); 1151 strcpy(r, p); 1152 if(r[0]=='\0' || r[strlen(r)-1] != '/') 1153 strcat(r, "/"); 1154 strcat(r, q); 1155 return r; 1156 } 1157 1158 Fid *fidtab[1]; 1159 1160 Fid* 1161 lookupfid(int fid) 1162 { 1163 Fid *f; 1164 1165 for(f=fidtab[fid%nelem(fidtab)]; f; f=f->next) 1166 if(f->fid == fid) 1167 return f; 1168 return nil; 1169 } 1170 1171 Fid* 1172 newfid(int fid, char **ep) 1173 { 1174 Fid *f; 1175 1176 if(lookupfid(fid) != nil){ 1177 *ep = Efidactive; 1178 return nil; 1179 } 1180 1181 f = emalloc(sizeof(*f)); 1182 f->next = fidtab[fid%nelem(fidtab)]; 1183 if(f->next) 1184 f->next->prev = f; 1185 fidtab[fid%nelem(fidtab)] = f; 1186 f->fid = fid; 1187 f->fd = -1; 1188 f->omode = -1; 1189 return f; 1190 } 1191 1192 Fid* 1193 newauthfid(int fid, void *magic, char **ep) 1194 { 1195 Fid *af; 1196 af = newfid(fid, ep); 1197 if (af == nil) 1198 return nil; 1199 af->auth = 1; 1200 af->authmagic = magic; 1201 return af; 1202 } 1203 1204 Fid* 1205 oldfidex(int fid, int auth, char **ep) 1206 { 1207 Fid *f; 1208 1209 if((f = lookupfid(fid)) == nil){ 1210 *ep = Ebadfid; 1211 return nil; 1212 } 1213 1214 if (auth != -1 && f->auth != auth) { 1215 *ep = Ebadfid; 1216 return nil; 1217 } 1218 1219 if (!f->auth) { 1220 if(userchange(f->u, ep) < 0) 1221 return nil; 1222 } 1223 1224 return f; 1225 } 1226 1227 Fid* 1228 oldfid(int fid, char **ep) 1229 { 1230 return oldfidex(fid, 0, ep); 1231 } 1232 1233 Fid* 1234 oldauthfid(int fid, void **magic, char **ep) 1235 { 1236 Fid *af; 1237 af = oldfidex(fid, 1, ep); 1238 if (af == nil) 1239 return nil; 1240 *magic = af->authmagic; 1241 return af; 1242 } 1243 1244 void 1245 freefid(Fid *f) 1246 { 1247 if(f->prev) 1248 f->prev->next = f->next; 1249 else 1250 fidtab[f->fid%nelem(fidtab)] = f->next; 1251 if(f->next) 1252 f->next->prev = f->prev; 1253 if(f->dir) 1254 closedir(f->dir); 1255 if(f->fd) 1256 close(f->fd); 1257 free(f->path); 1258 free(f); 1259 } 1260 1261 int 1262 fidstat(Fid *fid, char **ep) 1263 { 1264 if(stat(fid->path, &fid->st) < 0){ 1265 fprint(2, "fidstat(%s) failed\n", fid->path); 1266 if(ep) 1267 *ep = strerror(errno); 1268 return -1; 1269 } 1270 if(S_ISDIR(fid->st.st_mode)) 1271 fid->st.st_size = 0; 1272 return 0; 1273 } 1274 1275 int 1276 userchange(User *u, char **ep) 1277 { 1278 if(defaultuser) 1279 return 0; 1280 1281 if(setreuid(0, 0) < 0){ 1282 fprint(2, "setreuid(0, 0) failed\n"); 1283 *ep = "cannot setuid back to root"; 1284 return -1; 1285 } 1286 1287 /* 1288 * Initgroups does not appear to be SUSV standard. 1289 * But it exists on SGI and on Linux, which makes me 1290 * think it's standard enough. We have to do something 1291 * like this, and the closest other function I can find is 1292 * setgroups (which initgroups eventually calls). 1293 * Setgroups is the same as far as standardization though, 1294 * so we're stuck using a non-SUSV call. Sigh. 1295 */ 1296 if(initgroups(u->name, u->defaultgid) < 0) 1297 fprint(2, "initgroups(%s) failed: %s\n", u->name, strerror(errno)); 1298 1299 if(setreuid(-1, u->id) < 0){ 1300 fprint(2, "setreuid(-1, %s) failed\n", u->name); 1301 *ep = strerror(errno); 1302 return -1; 1303 } 1304 1305 return 0; 1306 } 1307 1308 /* 1309 * We do our own checking here, then switch to root temporarily 1310 * to set our gid. In a perfect world, you'd be allowed to set your 1311 * egid to any of the supplemental groups of your euid, but this 1312 * is not the case on Linux 2.2.14 (and perhaps others). 1313 * 1314 * This is a race, of course, but it's a race against processes 1315 * that can edit the group lists. If you can do that, you can 1316 * change your own group without our help. 1317 */ 1318 int 1319 groupchange(User *u, User *g, char **ep) 1320 { 1321 if(!useringroup(u, g)){ 1322 if(chatty9p) 1323 fprint(2, "%s not in group %s\n", u->name, g->name); 1324 *ep = Enotingroup; 1325 return -1; 1326 } 1327 1328 setreuid(0,0); 1329 if(setregid(-1, g->id) < 0){ 1330 fprint(2, "setegid(%s/%d) failed in groupchange\n", g->name, g->id); 1331 *ep = strerror(errno); 1332 return -1; 1333 } 1334 if(userchange(u, ep) < 0) 1335 return -1; 1336 1337 return 0; 1338 } 1339 1340 1341 /* 1342 * An attempt to enforce permissions by looking at the 1343 * file system. Separation of checking permission and 1344 * actually performing the action is a terrible idea, of 1345 * course, so we use setreuid for most of the permission 1346 * enforcement. This is here only so we can give errors 1347 * on open(ORCLOSE) in some cases. 1348 */ 1349 int 1350 userperm(User *u, char *path, int type, int need) 1351 { 1352 char *p, *q; 1353 int i, have; 1354 struct stat st; 1355 User *g; 1356 1357 switch(type){ 1358 default: 1359 fprint(2, "bad type %d in userperm\n", type); 1360 return -1; 1361 case Tdot: 1362 if(stat(path, &st) < 0){ 1363 fprint(2, "userperm: stat(%s) failed\n", path); 1364 return -1; 1365 } 1366 break; 1367 case Tdotdot: 1368 p = estrdup(path); 1369 if((q = strrchr(p, '/'))==nil){ 1370 fprint(2, "userperm(%s, ..): bad path\n", p); 1371 free(p); 1372 return -1; 1373 } 1374 if(q > p) 1375 *q = '\0'; 1376 else 1377 *(q+1) = '\0'; 1378 if(stat(p, &st) < 0){ 1379 fprint(2, "userperm: stat(%s) (dotdot of %s) failed\n", 1380 p, path); 1381 free(p); 1382 return -1; 1383 } 1384 free(p); 1385 break; 1386 } 1387 1388 if(u == none){ 1389 fprint(2, "userperm: none wants %d in 0%luo\n", need, st.st_mode); 1390 have = st.st_mode&7; 1391 if((have&need)==need) 1392 return 0; 1393 return -1; 1394 } 1395 have = st.st_mode&7; 1396 if((uid_t)u->id == st.st_uid) 1397 have |= (st.st_mode>>6)&7; 1398 if((have&need)==need) 1399 return 0; 1400 if(((have|((st.st_mode>>3)&7))&need) != need) /* group won't help */ 1401 return -1; 1402 g = gid2user(st.st_gid); 1403 for(i=0; i<g->nmem; i++){ 1404 if(strcmp(g->mem[i], u->name) == 0){ 1405 have |= (st.st_mode>>3)&7; 1406 break; 1407 } 1408 } 1409 if((have&need)==need) 1410 return 0; 1411 return -1; 1412 } 1413 1414 int 1415 userwalk(User *u, char **path, char *elem, Qid *qid, char **ep) 1416 { 1417 char *npath; 1418 struct stat st; 1419 1420 npath = estrpath(*path, elem); 1421 if(stat(npath, &st) < 0){ 1422 free(npath); 1423 *ep = strerror(errno); 1424 return -1; 1425 } 1426 *qid = stat2qid(&st); 1427 free(*path); 1428 *path = npath; 1429 return 0; 1430 } 1431 1432 int 1433 useropen(Fid *fid, int omode, char **ep) 1434 { 1435 int a, o; 1436 1437 /* 1438 * Check this anyway, to try to head off problems later. 1439 */ 1440 if((omode&ORCLOSE) && userperm(fid->u, fid->path, Tdotdot, W_OK) < 0){ 1441 *ep = Eperm; 1442 return -1; 1443 } 1444 1445 switch(omode&3){ 1446 default: 1447 *ep = "programmer error"; 1448 return -1; 1449 case OREAD: 1450 a = R_OK; 1451 o = O_RDONLY; 1452 break; 1453 case ORDWR: 1454 a = R_OK|W_OK; 1455 o = O_RDWR; 1456 break; 1457 case OWRITE: 1458 a = R_OK; 1459 o = O_WRONLY; 1460 break; 1461 case OEXEC: 1462 a = X_OK; 1463 o = O_RDONLY; 1464 break; 1465 } 1466 if(omode & OTRUNC){ 1467 a |= W_OK; 1468 o |= O_TRUNC; 1469 } 1470 1471 if(S_ISDIR(fid->st.st_mode)){ 1472 if(a != R_OK){ 1473 fprint(2, "attempt by %s to open dir %d\n", fid->u->name, omode); 1474 *ep = Eperm; 1475 return -1; 1476 } 1477 if((fid->dir = opendir(fid->path)) == nil){ 1478 *ep = strerror(errno); 1479 return -1; 1480 } 1481 }else{ 1482 /* 1483 * This is wrong because access used the real uid 1484 * and not the effective uid. Let the open sort it out. 1485 * 1486 if(access(fid->path, a) < 0){ 1487 *ep = strerror(errno); 1488 return -1; 1489 } 1490 * 1491 */ 1492 if((fid->fd = open(fid->path, o)) < 0){ 1493 *ep = strerror(errno); 1494 return -1; 1495 } 1496 } 1497 fid->omode = omode; 1498 return 0; 1499 } 1500 1501 int 1502 usercreate(Fid *fid, char *elem, int omode, long perm, char **ep) 1503 { 1504 int o, m; 1505 char *opath, *npath; 1506 struct stat st, parent; 1507 1508 if(stat(fid->path, &parent) < 0){ 1509 *ep = strerror(errno); 1510 return -1; 1511 } 1512 1513 /* 1514 * Change group so that created file has expected group 1515 * by Plan 9 semantics. If that fails, might as well go 1516 * with the user's default group. 1517 */ 1518 if(groupchange(fid->u, gid2user(parent.st_gid), ep) < 0 1519 && groupchange(fid->u, gid2user(fid->u->defaultgid), ep) < 0) 1520 return -1; 1521 1522 m = (perm & DMDIR) ? 0777 : 0666; 1523 perm = perm & (~m | (fid->st.st_mode & m)); 1524 1525 npath = estrpath(fid->path, elem); 1526 if(perm & DMDIR){ 1527 if((omode&~ORCLOSE) != OREAD){ 1528 *ep = Eperm; 1529 free(npath); 1530 return -1; 1531 } 1532 if(stat(npath, &st) >= 0 || errno != ENOENT){ 1533 *ep = Eexist; 1534 free(npath); 1535 return -1; 1536 } 1537 /* race */ 1538 if(mkdir(npath, perm&0777) < 0){ 1539 *ep = strerror(errno); 1540 free(npath); 1541 return -1; 1542 } 1543 if((fid->dir = opendir(npath)) == nil){ 1544 *ep = strerror(errno); 1545 remove(npath); /* race */ 1546 free(npath); 1547 return -1; 1548 } 1549 }else{ 1550 o = O_CREAT|O_EXCL; 1551 switch(omode&3){ 1552 default: 1553 *ep = "programmer error"; 1554 return -1; 1555 case OREAD: 1556 case OEXEC: 1557 o |= O_RDONLY; 1558 break; 1559 case ORDWR: 1560 o |= O_RDWR; 1561 break; 1562 case OWRITE: 1563 o |= O_WRONLY; 1564 break; 1565 } 1566 if(omode & OTRUNC) 1567 o |= O_TRUNC; 1568 if((fid->fd = open(npath, o, perm&0777)) < 0){ 1569 if(chatty9p) 1570 fprint(2, "create(%s, 0x%x, 0%o) failed\n", npath, o, perm&0777); 1571 *ep = strerror(errno); 1572 free(npath); 1573 return -1; 1574 } 1575 } 1576 1577 opath = fid->path; 1578 fid->path = npath; 1579 if(fidstat(fid, ep) < 0){ 1580 fprint(2, "stat after create on %s failed\n", npath); 1581 remove(npath); /* race */ 1582 free(npath); 1583 fid->path = opath; 1584 if(fid->fd >= 0){ 1585 close(fid->fd); 1586 fid->fd = -1; 1587 }else{ 1588 closedir(fid->dir); 1589 fid->dir = nil; 1590 } 1591 return -1; 1592 } 1593 fid->omode = omode; 1594 free(opath); 1595 return 0; 1596 } 1597 1598 int 1599 userremove(Fid *fid, char **ep) 1600 { 1601 if(remove(fid->path) < 0){ 1602 *ep = strerror(errno); 1603 return -1; 1604 } 1605 return 0; 1606 } 1607 1608 void 1609 usage(void) 1610 { 1611 fprint(2, "usage: u9fs [-Dnz] [-a authmethod] [-m msize] [-u user] [root]\n"); 1612 exit(1); 1613 } 1614 1615 int 1616 main(int argc, char **argv) 1617 { 1618 char *authtype; 1619 int i; 1620 int fd; 1621 int logflag; 1622 1623 auth = authmethods[0]; 1624 logflag = O_WRONLY|O_APPEND|O_CREAT; 1625 ARGBEGIN{ 1626 case 'D': 1627 chatty9p = 1; 1628 break; 1629 case 'a': 1630 authtype = EARGF(usage()); 1631 auth = nil; 1632 for(i=0; i<nelem(authmethods); i++) 1633 if(strcmp(authmethods[i]->name, authtype)==0) 1634 auth = authmethods[i]; 1635 if(auth == nil) 1636 sysfatal("unknown auth type '%s'", authtype); 1637 break; 1638 case 'A': 1639 autharg = EARGF(usage()); 1640 break; 1641 case 'l': 1642 logfile = EARGF(usage()); 1643 break; 1644 case 'm': 1645 msize = strtol(EARGF(usage()), 0, 0); 1646 break; 1647 case 'n': 1648 network = 0; 1649 break; 1650 case 'u': 1651 defaultuser = EARGF(usage()); 1652 break; 1653 case 'z': 1654 logflag |= O_TRUNC; 1655 }ARGEND 1656 1657 if(argc > 1) 1658 usage(); 1659 1660 fd = open(logfile, logflag, 0666); 1661 if(fd < 0) 1662 sysfatal("cannot open log '%s'", logfile); 1663 1664 if(dup2(fd, 2) < 0) 1665 sysfatal("cannot dup fd onto stderr"); 1666 fprint(2, "u9fs\nkill %d\n", (int)getpid()); 1667 1668 fmtinstall('F', fcallconv); 1669 fmtinstall('D', dirconv); 1670 fmtinstall('M', dirmodeconv); 1671 1672 rxbuf = emalloc(msize); 1673 txbuf = emalloc(msize); 1674 databuf = emalloc(msize); 1675 1676 if(auth->init) 1677 auth->init(); 1678 1679 if(network) 1680 getremotehostname(remotehostname, sizeof remotehostname); 1681 1682 if(gethostname(hostname, sizeof hostname) < 0) 1683 strcpy(hostname, "gnot"); 1684 1685 umask(0); 1686 1687 if(argc == 1) 1688 if(chroot(argv[0]) < 0) 1689 sysfatal("chroot '%s' failed", argv[0]); 1690 1691 none = uname2user("none"); 1692 serve(0, 1); 1693 return 0; 1694 } 1695