Unified · Split
| @@ -8,27 +8,23 @@ OFILES=\ · 7 unmodified lines | ||
| 8 | 8 | readcons.$O\ |
| 9 | 9 | secstore.$O\ |
| 10 | 10 | latin1.$O\ |
| 11 | + $(OS)-factotum.$O\ | |
| 11 | 12 | |
| 12 | −LIBS=\ | |
| 13 | +LIBS1=\ | |
| 13 | 14 | kern/libkern.a\ |
| 14 | 15 | exportfs/libexportfs.a\ |
| 16 | + libauth/libauth.a\ | |
| 15 | 17 | libauthsrv/libauthsrv.a\ |
| 16 | 18 | libsec/libsec.a\ |
| 17 | 19 | libmp/libmp.a\ |
| 18 | 20 | libmemdraw/libmemdraw.a\ |
| 19 | 21 | libmemlayer/libmemlayer.a\ |
| 20 | 22 | libdraw/libdraw.a\ |
| 21 | − libc/libc.a\ | |
| 22 | − kern/libkern.a\ | |
| 23 | 23 | gui-$(GUI)/libgui.a\ |
| 24 | − libmemdraw/libmemdraw.a\ | |
| 25 | − libdraw/libdraw.a\ | |
| 26 | − kern/libkern.a\ | |
| 27 | 24 | libc/libc.a\ |
| 28 | − libmemdraw/libmemdraw.a\ | |
| 29 | − libmemlayer/libmemlayer.a\ | |
| 30 | − libdraw/libdraw.a\ | |
| 31 | − libmachdep.a | |
| 25 | + | |
| 26 | +# stupid gcc | |
| 27 | +LIBS=$(LIBS1) $(LIBS1) $(LIBS1) libmachdep.a | |
| 32 | 28 | |
| 33 | 29 | $(TARG): $(OFILES) $(LIBS) |
| 34 | 30 | $(CC) $(LDFLAGS) -o $(TARG) $(OFILES) $(LIBS) $(LDADD) |
| @@ -45,6 +41,9 @@ kern/libkern.a: · 10 unmodified lines | ||
| 45 | 41 | exportfs/libexportfs.a: |
| 46 | 42 | (cd exportfs; make) |
| 47 | 43 | |
| 44 | +libauth/libauth.a: | |
| 45 | + (cd libauth; make) | |
| 46 | + | |
| 48 | 47 | libauthsrv/libauthsrv.a: |
| 49 | 48 | (cd libauthsrv; make) |
| 50 | 49 | |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #define Maxfdata 8192 |
| 18 | 18 | #define MaxStr 128 |
| 19 | 19 | |
| 20 | −static char* getuser(void); | |
| 21 | 20 | static void fatal(int, char*, ...); |
| 22 | 21 | static void catcher(void*, char*); |
| 23 | 22 | static void usage(void); |
| @@ -98,7 +97,9 @@ cpumain(int argc, char **argv) · 74 unmodified lines | ||
| 98 | 97 | close(fd); |
| 99 | 98 | } |
| 100 | 99 | |
| 101 | − user = readcons("user", getenv("USER"), 0); | |
| 100 | + user = getenv("USER"); | |
| 101 | + if(user == nil) | |
| 102 | + user = readcons("user", nil, 0); | |
| 102 | 103 | secstoreserver = nil; |
| 103 | 104 | ARGBEGIN{ |
| 104 | 105 | case 'a': |
| @@ -126,6 +127,9 @@ cpumain(int argc, char **argv) · 21 unmodified lines | ||
| 126 | 127 | } |
| 127 | 128 | break; |
| 128 | 129 | */ |
| 130 | + case 'k': | |
| 131 | + keyspec = EARGF(usage()); | |
| 132 | + break; | |
| 129 | 133 | case 'u': |
| 130 | 134 | user = EARGF(usage()); |
| 131 | 135 | break; |
| @@ -136,6 +140,15 @@ cpumain(int argc, char **argv) · 4 unmodified lines | ||
| 136 | 140 | usage(); |
| 137 | 141 | }ARGEND; |
| 138 | 142 | |
| 143 | + if((fd = dialfactotum()) < 0) | |
| 144 | + fprint(2, "dial factotum: %r\n"); | |
| 145 | + else if(sysmount(fd, -1, "/mnt/factotum", MREPL, "") < 0) | |
| 146 | + fprint(2, "mount factotum: %r\n"); | |
| 147 | + else if((fd = open("/mnt/factotum/ctl", OREAD)) < 0) | |
| 148 | + fprint(2, "open /mnt/factotum/ctl: %r\n"); | |
| 149 | + else | |
| 150 | + close(fd); | |
| 151 | + | |
| 139 | 152 | if(secstoreserver == nil) |
| 140 | 153 | secstoreserver = authserver; |
| 141 | 154 | |
| @@ -436,6 +449,96 @@ gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf) · 294 unmodified lines | ||
| 436 | 449 | return mkserverticket(tr, key, tbuf); |
| 437 | 450 | } |
| 438 | 451 | |
| 452 | +/* | |
| 453 | + * prompt user for a key. don't care about memory leaks, runs standalone | |
| 454 | + */ | |
| 455 | +static Attr* | |
| 456 | +promptforkey(char *params) | |
| 457 | +{ | |
| 458 | + char *v; | |
| 459 | + int fd; | |
| 460 | + Attr *a, *attr; | |
| 461 | + char *def; | |
| 462 | + | |
| 463 | + fd = open("/dev/cons", ORDWR); | |
| 464 | + if(fd < 0) | |
| 465 | + sysfatal("opening /dev/cons: %r"); | |
| 466 | + | |
| 467 | + attr = _parseattr(params); | |
| 468 | + fprint(fd, "\n!Adding key:"); | |
| 469 | + for(a=attr; a; a=a->next) | |
| 470 | + if(a->type != AttrQuery && a->name[0] != '!') | |
| 471 | + fprint(fd, " %q=%q", a->name, a->val); | |
| 472 | + fprint(fd, "\n"); | |
| 473 | + | |
| 474 | + for(a=attr; a; a=a->next){ | |
| 475 | + v = a->name; | |
| 476 | + if(a->type != AttrQuery || v[0]=='!') | |
| 477 | + continue; | |
| 478 | + def = nil; | |
| 479 | + if(strcmp(v, "user") == 0) | |
| 480 | + def = getuser(); | |
| 481 | + a->val = readcons(v, def, 0); | |
| 482 | + if(a->val == nil) | |
| 483 | + sysfatal("user terminated key input"); | |
| 484 | + a->type = AttrNameval; | |
| 485 | + } | |
| 486 | + for(a=attr; a; a=a->next){ | |
| 487 | + v = a->name; | |
| 488 | + if(a->type != AttrQuery || v[0]!='!') | |
| 489 | + continue; | |
| 490 | + def = nil; | |
| 491 | + if(strcmp(v+1, "user") == 0) | |
| 492 | + def = getuser(); | |
| 493 | + a->val = readcons(v+1, def, 1); | |
| 494 | + if(a->val == nil) | |
| 495 | + sysfatal("user terminated key input"); | |
| 496 | + a->type = AttrNameval; | |
| 497 | + } | |
| 498 | + fprint(fd, "!\n"); | |
| 499 | + close(fd); | |
| 500 | + return attr; | |
| 501 | +} | |
| 502 | + | |
| 503 | +/* | |
| 504 | + * send a key to the mounted factotum | |
| 505 | + */ | |
| 506 | +static int | |
| 507 | +sendkey(Attr *attr) | |
| 508 | +{ | |
| 509 | + int fd, rv; | |
| 510 | + char buf[1024]; | |
| 511 | + | |
| 512 | + fd = open("/mnt/factotum/ctl", ORDWR); | |
| 513 | + if(fd < 0) | |
| 514 | + sysfatal("opening /mnt/factotum/ctl: %r"); | |
| 515 | + rv = fprint(fd, "key %A\n", attr); | |
| 516 | + read(fd, buf, sizeof buf); | |
| 517 | + close(fd); | |
| 518 | + return rv; | |
| 519 | +} | |
| 520 | + | |
| 521 | +int | |
| 522 | +askuser(char *params) | |
| 523 | +{ | |
| 524 | + Attr *attr; | |
| 525 | + | |
| 526 | + fmtinstall('A', _attrfmt); | |
| 527 | + | |
| 528 | + attr = promptforkey(params); | |
| 529 | + if(attr == nil) | |
| 530 | + sysfatal("no key supplied"); | |
| 531 | + if(sendkey(attr) < 0) | |
| 532 | + sysfatal("sending key to factotum: %r"); | |
| 533 | + return 0; | |
| 534 | +} | |
| 535 | + | |
| 536 | +AuthInfo* | |
| 537 | +p9anyfactotum(int fd, int afd) | |
| 538 | +{ | |
| 539 | + return auth_proxy(fd, askuser, "proto=p9any role=client %s", keyspec); | |
| 540 | +} | |
| 541 | + | |
| 439 | 542 | AuthInfo* |
| 440 | 543 | p9any(int fd) |
| 441 | 544 | { |
| @@ -444,11 +547,14 @@ p9any(int fd) · 2 unmodified lines | ||
| 444 | 547 | char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; |
| 445 | 548 | char authkey[DESKEYLEN]; |
| 446 | 549 | Authenticator auth; |
| 447 | − int i, v2, n; | |
| 550 | + int afd, i, v2, n; | |
| 448 | 551 | Ticketreq tr; |
| 449 | 552 | Ticket t; |
| 450 | 553 | AuthInfo *ai; |
| 451 | 554 | |
| 555 | + if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) | |
| 556 | + return p9anyfactotum(fd, afd); | |
| 557 | + | |
| 452 | 558 | if((n = readstr(fd, buf, sizeof buf)) < 0) |
| 453 | 559 | fatal(1, "cannot read p9any negotiation"); |
| 454 | 560 | bbuf = buf; |
| @@ -598,9 +704,3 @@ setamalg(char *s) · 143 unmodified lines | ||
| 598 | 704 | return setam(s); |
| 599 | 705 | } |
| 600 | 706 | |
| 601 | −char* | |
| 602 | −getuser(void) | |
| 603 | −{ | |
| 604 | − return getenv("USER"); | |
| 605 | −} | |
| 606 | − | |
| @@ -8,3 +8,5 @@ extern int exportfs(int, int); · 7 unmodified lines | ||
| 8 | 8 | extern char *user; |
| 9 | 9 | extern char *getkey(char*, char*); |
| 10 | 10 | extern char *findkey(char**, char*); |
| 11 | +extern int dialfactotum(void); | |
| 12 | +extern char *getuser(void); | |
| @@ -99,7 +99,7 @@ exportfs(int fd, int msgsz) · 98 unmodified lines | ||
| 99 | 99 | fatal("convM2S format error"); |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | −//iprint("<- %F\n", &r->work); | |
| 102 | +if(0) iprint("<- %F\n", &r->work); | |
| 103 | 103 | DEBUG(DFD, "%F\n", &r->work); |
| 104 | 104 | (fcalls[r->work.type])(r); |
| 105 | 105 | } |
| @@ -110,6 +110,7 @@ reply(Fcall *r, Fcall *t, char *err) · 4 unmodified lines | ||
| 110 | 110 | { |
| 111 | 111 | uchar *data; |
| 112 | 112 | int m, n; |
| 113 | +static QLock lk; | |
| 113 | 114 | |
| 114 | 115 | t->tag = r->tag; |
| 115 | 116 | t->fid = r->fid; |
| @@ -120,7 +121,7 @@ reply(Fcall *r, Fcall *t, char *err) · 4 unmodified lines | ||
| 120 | 121 | else |
| 121 | 122 | t->type = r->type + 1; |
| 122 | 123 | |
| 123 | −//iprint("-> %F\n", t); | |
| 124 | +if(0) iprint("-> %F\n", t); | |
| 124 | 125 | DEBUG(DFD, "\t%F\n", t); |
| 125 | 126 | |
| 126 | 127 | data = malloc(messagesize); /* not mallocz; no need to clear */ |
| @@ -431,6 +431,7 @@ slave(Fsrpc *f) · 430 unmodified lines | ||
| 431 | 431 | Proc *p; |
| 432 | 432 | int pid; |
| 433 | 433 | static int nproc; |
| 434 | + static QLock lk; | |
| 434 | 435 | |
| 435 | 436 | for(;;) { |
| 436 | 437 | for(p = Proclist; p; p = p->next) { |
| @@ -50,6 +50,8 @@ extern int dirwstat(char*, Dir*); · 49 unmodified lines | ||
| 50 | 50 | extern int dirfwstat(int, Dir*); |
| 51 | 51 | extern long dirread(int, Dir*, long); |
| 52 | 52 | |
| 53 | +extern int lfdfd(int); | |
| 54 | + | |
| 53 | 55 | /* |
| 54 | 56 | * network dialing and authentication |
| 55 | 57 | */ |
| @@ -13,6 +13,7 @@ OFILES=\ · 12 unmodified lines | ||
| 13 | 13 | devfs-$(OS).$O\ |
| 14 | 14 | devip.$O\ |
| 15 | 15 | devip-$(OS).$O\ |
| 16 | + devlfd.$O\ | |
| 16 | 17 | devmnt.$O\ |
| 17 | 18 | devmouse.$O\ |
| 18 | 19 | devpipe.$O\ |
| @@ -175,25 +175,6 @@ print(char *fmt, ...) · 174 unmodified lines | ||
| 175 | 175 | return n; |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | −int | |
| 179 | −iprint(char *fmt, ...) | |
| 180 | −{ | |
| 181 | − int n, s; | |
| 182 | − va_list arg; | |
| 183 | − char buf[PRINTSIZE]; | |
| 184 | − | |
| 185 | − s = splhi(); | |
| 186 | − va_start(arg, fmt); | |
| 187 | − n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; | |
| 188 | − va_end(arg); | |
| 189 | − if(screenputs != nil && iprintscreenputs) | |
| 190 | − screenputs(buf, n); | |
| 191 | − uartputs(buf, n); | |
| 192 | − splx(s); | |
| 193 | − | |
| 194 | − return n; | |
| 195 | −} | |
| 196 | − | |
| 197 | 178 | void |
| 198 | 179 | panic(char *fmt, ...) |
| 199 | 180 | { |
| @@ -1208,3 +1189,23 @@ writebintime(char *buf, int n) · 1008 unmodified lines | ||
| 1208 | 1189 | } |
| 1209 | 1190 | |
| 1210 | 1191 | |
| 1192 | +int | |
| 1193 | +iprint(char *fmt, ...) | |
| 1194 | +{ | |
| 1195 | + int n, s; | |
| 1196 | + va_list arg; | |
| 1197 | + char buf[PRINTSIZE]; | |
| 1198 | + | |
| 1199 | + s = splhi(); | |
| 1200 | + va_start(arg, fmt); | |
| 1201 | + n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf; | |
| 1202 | + va_end(arg); | |
| 1203 | + if(screenputs != nil && iprintscreenputs) | |
| 1204 | + screenputs(buf, n); | |
| 1205 | +#undef write | |
| 1206 | + write(2, buf, n); | |
| 1207 | + splx(s); | |
| 1208 | + | |
| 1209 | + return n; | |
| 1210 | +} | |
| 1211 | + | |
| @@ -0,0 +1,126 @@ | ||
| 1 | +#include "u.h" | |
| 2 | +#include <errno.h> | |
| 3 | +#include "lib.h" | |
| 4 | +#include "dat.h" | |
| 5 | +#include "fns.h" | |
| 6 | +#include "error.h" | |
| 7 | + | |
| 8 | +#undef pread | |
| 9 | +#undef pwrite | |
| 10 | + | |
| 11 | +Chan* | |
| 12 | +lfdchan(int fd) | |
| 13 | +{ | |
| 14 | + Chan *c; | |
| 15 | + | |
| 16 | + c = newchan(); | |
| 17 | + c->type = devno('L', 0); | |
| 18 | + c->aux = (void*)fd; | |
| 19 | + c->name = newcname("fd"); | |
| 20 | + c->mode = ORDWR; | |
| 21 | + c->qid.type = 0; | |
| 22 | + c->qid.path = 0; | |
| 23 | + c->qid.vers = 0; | |
| 24 | + c->dev = 0; | |
| 25 | + c->offset = 0; | |
| 26 | + return c; | |
| 27 | +} | |
| 28 | + | |
| 29 | +int | |
| 30 | +lfdfd(int fd) | |
| 31 | +{ | |
| 32 | + return newfd(lfdchan(fd)); | |
| 33 | +} | |
| 34 | + | |
| 35 | +static Chan* | |
| 36 | +lfdattach(char *x) | |
| 37 | +{ | |
| 38 | + USED(x); | |
| 39 | + | |
| 40 | + error(Egreg); | |
| 41 | + return nil; | |
| 42 | +} | |
| 43 | + | |
| 44 | +static Walkqid* | |
| 45 | +lfdwalk(Chan *c, Chan *nc, char **name, int nname) | |
| 46 | +{ | |
| 47 | + USED(c); | |
| 48 | + USED(nc); | |
| 49 | + USED(name); | |
| 50 | + USED(nname); | |
| 51 | + | |
| 52 | + error(Egreg); | |
| 53 | + return nil; | |
| 54 | +} | |
| 55 | + | |
| 56 | +static int | |
| 57 | +lfdstat(Chan *c, uchar *dp, int n) | |
| 58 | +{ | |
| 59 | + USED(c); | |
| 60 | + USED(dp); | |
| 61 | + USED(n); | |
| 62 | + error(Egreg); | |
| 63 | + return -1; | |
| 64 | +} | |
| 65 | + | |
| 66 | +static Chan* | |
| 67 | +lfdopen(Chan *c, int omode) | |
| 68 | +{ | |
| 69 | + USED(c); | |
| 70 | + USED(omode); | |
| 71 | + | |
| 72 | + error(Egreg); | |
| 73 | + return nil; | |
| 74 | +} | |
| 75 | + | |
| 76 | +static void | |
| 77 | +lfdclose(Chan *c) | |
| 78 | +{ | |
| 79 | + close((int)c->aux); | |
| 80 | +} | |
| 81 | + | |
| 82 | +static long | |
| 83 | +lfdread(Chan *c, void *buf, long n, vlong off) | |
| 84 | +{ | |
| 85 | + USED(off); /* can't pread on pipes */ | |
| 86 | + n = read((int)c->aux, buf, n); | |
| 87 | + if(n < 0){ | |
| 88 | + iprint("error %d\n", errno); | |
| 89 | + oserror(); | |
| 90 | + } | |
| 91 | + return n; | |
| 92 | +} | |
| 93 | + | |
| 94 | +static long | |
| 95 | +lfdwrite(Chan *c, void *buf, long n, vlong off) | |
| 96 | +{ | |
| 97 | + USED(off); /* can't pread on pipes */ | |
| 98 | + | |
| 99 | + n = write((int)c->aux, buf, n); | |
| 100 | + if(n < 0){ | |
| 101 | + iprint("error %d\n", errno); | |
| 102 | + oserror(); | |
| 103 | + } | |
| 104 | + return n; | |
| 105 | +} | |
| 106 | + | |
| 107 | +Dev lfddevtab = { | |
| 108 | + 'L', | |
| 109 | + "lfd", | |
| 110 | + | |
| 111 | + devreset, | |
| 112 | + devinit, | |
| 113 | + devshutdown, | |
| 114 | + lfdattach, | |
| 115 | + lfdwalk, | |
| 116 | + lfdstat, | |
| 117 | + lfdopen, | |
| 118 | + devcreate, | |
| 119 | + lfdclose, | |
| 120 | + lfdread, | |
| 121 | + devbread, | |
| 122 | + lfdwrite, | |
| 123 | + devbwrite, | |
| 124 | + devremove, | |
| 125 | + devwstat, | |
| 126 | +}; | |
| @@ -8,9 +8,12 @@ enum · 7 unmodified lines | ||
| 8 | 8 | { |
| 9 | 9 | Qdir = 0, |
| 10 | 10 | Qboot = 0x1000, |
| 11 | + Qmnt = 0x2000, | |
| 12 | + Qfactotum, | |
| 11 | 13 | |
| 12 | 14 | Nrootfiles = 32, |
| 13 | 15 | Nbootfiles = 32, |
| 16 | + Nmntfiles = 2, | |
| 14 | 17 | }; |
| 15 | 18 | |
| 16 | 19 | typedef struct Dirlist Dirlist; |
| @@ -26,6 +29,7 @@ struct Dirlist · 9 unmodified lines | ||
| 26 | 29 | static Dirtab rootdir[Nrootfiles] = { |
| 27 | 30 | "#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555, |
| 28 | 31 | "boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555, |
| 32 | + "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, | |
| 29 | 33 | }; |
| 30 | 34 | static uchar *rootdata[Nrootfiles]; |
| 31 | 35 | static Dirlist rootlist = |
| @@ -33,7 +37,7 @@ static Dirlist rootlist = · 1 unmodified line | ||
| 33 | 37 | 0, |
| 34 | 38 | rootdir, |
| 35 | 39 | rootdata, |
| 36 | − 2, | |
| 40 | + 3, | |
| 37 | 41 | Nrootfiles |
| 38 | 42 | }; |
| 39 | 43 | |
| @@ -50,6 +54,19 @@ static Dirlist bootlist = · 10 unmodified lines | ||
| 50 | 54 | Nbootfiles |
| 51 | 55 | }; |
| 52 | 56 | |
| 57 | +static Dirtab mntdir[Nmntfiles] = { | |
| 58 | + "mnt", {Qmnt, 0, QTDIR}, 0, DMDIR|0555, | |
| 59 | + "factotum", {Qfactotum, 0, QTDIR}, 0, DMDIR|0555, | |
| 60 | +}; | |
| 61 | +static Dirlist mntlist = | |
| 62 | +{ | |
| 63 | + Qmnt, | |
| 64 | + mntdir, | |
| 65 | + nil, | |
| 66 | + 2, | |
| 67 | + Nmntfiles | |
| 68 | +}; | |
| 69 | + | |
| 53 | 70 | /* |
| 54 | 71 | * add a file to the list |
| 55 | 72 | */ |
| @@ -97,7 +114,6 @@ rootreset(void) · 41 unmodified lines | ||
| 97 | 114 | addrootdir("dev"); |
| 98 | 115 | addrootdir("env"); |
| 99 | 116 | addrootdir("fd"); |
| 100 | − addrootdir("mnt"); | |
| 101 | 117 | addrootdir("net"); |
| 102 | 118 | addrootdir("net.alt"); |
| 103 | 119 | addrootdir("proc"); |
| @@ -129,6 +145,13 @@ rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp) · 25 unmodified lines | ||
| 129 | 145 | return 1; |
| 130 | 146 | } |
| 131 | 147 | return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp); |
| 148 | + case Qmnt: | |
| 149 | + if(s == DEVDOTDOT){ | |
| 150 | + Qid tqiddir = {Qdir, 0, QTDIR}; | |
| 151 | + devdir(c, tqiddir, "#/", 0, eve, 0555, dp); | |
| 152 | + return 1; | |
| 153 | + } | |
| 154 | + return devgen(c, name, mntlist.dir, mntlist.ndir, s, dp); | |
| 132 | 155 | case Qboot: |
| 133 | 156 | if(s == DEVDOTDOT){ |
| 134 | 157 | Qid tqiddir = {Qdir, 0, QTDIR}; |
| @@ -139,22 +162,25 @@ rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp) · 4 unmodified lines | ||
| 139 | 162 | default: |
| 140 | 163 | if(s == DEVDOTDOT){ |
| 141 | 164 | Qid tqiddir = {Qdir, 0, QTDIR}; |
| 142 | − if((int)c->qid.path < Qboot) | |
| 143 | − devdir(c, tqiddir, "#/", 0, eve, 0555, dp); | |
| 144 | − else { | |
| 145 | − tqiddir.path = Qboot; | |
| 146 | − devdir(c, tqiddir, "#/", 0, eve, 0555, dp); | |
| 147 | − } | |
| 165 | + tqiddir.path = c->qid.path&0xF000; | |
| 166 | + devdir(c, tqiddir, "#/", 0, eve, 0555, dp); | |
| 148 | 167 | return 1; |
| 149 | 168 | } |
| 150 | 169 | if(s != 0) |
| 151 | 170 | return -1; |
| 152 | − if((int)c->qid.path < Qboot){ | |
| 171 | + switch((int)c->qid.path & 0xF000){ | |
| 172 | + case Qdir: | |
| 153 | 173 | t = c->qid.path-1; |
| 154 | 174 | l = &rootlist; |
| 155 | − }else{ | |
| 175 | + break; | |
| 176 | + case Qboot: | |
| 156 | 177 | t = c->qid.path - Qboot - 1; |
| 157 | 178 | l = &bootlist; |
| 179 | + break; | |
| 180 | + case Qmnt: | |
| 181 | + t = c->qid.path - Qmnt - 1; | |
| 182 | + l = &mntlist; | |
| 183 | + break; | |
| 158 | 184 | } |
| 159 | 185 | if(t >= l->ndir) |
| 160 | 186 | return -1; |
| @@ -209,17 +235,19 @@ rootread(Chan *c, void *buf, long n, vlong off) · 48 unmodified lines | ||
| 209 | 235 | switch(t){ |
| 210 | 236 | case Qdir: |
| 211 | 237 | case Qboot: |
| 238 | + case Qmnt: | |
| 212 | 239 | return devdirread(c, buf, n, nil, 0, rootgen); |
| 213 | 240 | } |
| 214 | 241 | |
| 215 | − if(t<Qboot) | |
| 216 | − l = &rootlist; | |
| 217 | − else{ | |
| 218 | − t -= Qboot; | |
| 242 | + if(t&Qboot) | |
| 219 | 243 | l = &bootlist; |
| 220 | − } | |
| 221 | − | |
| 244 | + else if(t&Qmnt) | |
| 245 | + l = &mntlist; | |
| 246 | + else | |
| 247 | + l = &bootlist; | |
| 248 | + t &= 0xFFF; | |
| 222 | 249 | t--; |
| 250 | + | |
| 223 | 251 | if(t >= l->ndir) |
| 224 | 252 | error(Egreg); |
| 225 | 253 | |
| @@ -765,6 +765,7 @@ sslput(Dstate *s, Block * volatile b) · 764 unmodified lines | ||
| 765 | 765 | int offset; |
| 766 | 766 | |
| 767 | 767 | if(waserror()){ |
| 768 | +iprint("error: %s\n", up->errstr); | |
| 768 | 769 | if(b != nil) |
| 769 | 770 | free(b); |
| 770 | 771 | nexterror(); |
| @@ -1071,8 +1072,9 @@ sslwrite(Chan *c, void *a, long n, vlong o) · 300 unmodified lines | ||
| 1071 | 1072 | nexterror(); |
| 1072 | 1073 | } |
| 1073 | 1074 | qlock(&s->out.q); |
| 1074 | − | |
| 1075 | 1075 | p = a; |
| 1076 | +if(0) iprint("write %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", | |
| 1077 | + n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); | |
| 1076 | 1078 | e = p + n; |
| 1077 | 1079 | do { |
| 1078 | 1080 | m = e - p; |
| @@ -1092,7 +1094,9 @@ sslwrite(Chan *c, void *a, long n, vlong o) · 13 unmodified lines | ||
| 1092 | 1094 | |
| 1093 | 1095 | p += m; |
| 1094 | 1096 | } while(p < e); |
| 1095 | − | |
| 1097 | + p = a; | |
| 1098 | +if(0) iprint("wrote %d %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\n", | |
| 1099 | + n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); | |
| 1096 | 1100 | poperror(); |
| 1097 | 1101 | qunlock(&s->out.q); |
| 1098 | 1102 | return n; |
| @@ -12,6 +12,8 @@ extern Dev mousedevtab; · 11 unmodified lines | ||
| 12 | 12 | extern Dev drawdevtab; |
| 13 | 13 | extern Dev ipdevtab; |
| 14 | 14 | extern Dev fsdevtab; |
| 15 | +extern Dev mntdevtab; | |
| 16 | +extern Dev lfddevtab; | |
| 15 | 17 | |
| 16 | 18 | Dev *devtab[] = { |
| 17 | 19 | &rootdevtab, |
| @@ -22,6 +24,8 @@ Dev *devtab[] = { · 4 unmodified lines | ||
| 22 | 24 | &drawdevtab, |
| 23 | 25 | &ipdevtab, |
| 24 | 26 | &fsdevtab, |
| 27 | + &mntdevtab, | |
| 28 | + &lfddevtab, | |
| 25 | 29 | 0 |
| 26 | 30 | }; |
| 27 | 31 | |
| @@ -0,0 +1,21 @@ | ||
| 1 | +ROOT=.. | |
| 2 | +include ../Make.config | |
| 3 | + | |
| 4 | +LIB=libauth.a | |
| 5 | +OFILES=\ | |
| 6 | + attr.$O\ | |
| 7 | + auth_attr.$O\ | |
| 8 | + auth_challenge.$O\ | |
| 9 | + auth_getuserpasswd.$O\ | |
| 10 | + auth_proxy.$O\ | |
| 11 | + auth_respond.$O\ | |
| 12 | + auth_rpc.$O\ | |
| 13 | + auth_userpasswd.$O\ | |
| 14 | + | |
| 15 | +$(LIB): $(OFILES) | |
| 16 | + $(AR) r $(LIB) $(OFILES) | |
| 17 | + $(RANLIB) $(LIB) | |
| 18 | + | |
| 19 | +%.$O: %.c | |
| 20 | + $(CC) $(CFLAGS) $*.c | |
| 21 | + | |
| @@ -0,0 +1,174 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | + | |
| 5 | +int | |
| 6 | +_attrfmt(Fmt *fmt) | |
| 7 | +{ | |
| 8 | + char *b, buf[1024], *ebuf; | |
| 9 | + Attr *a; | |
| 10 | + | |
| 11 | + ebuf = buf+sizeof buf; | |
| 12 | + b = buf; | |
| 13 | + strcpy(buf, " "); | |
| 14 | + for(a=va_arg(fmt->args, Attr*); a; a=a->next){ | |
| 15 | + if(a->name == nil) | |
| 16 | + continue; | |
| 17 | + switch(a->type){ | |
| 18 | + case AttrQuery: | |
| 19 | + b = seprint(b, ebuf, " %q?", a->name); | |
| 20 | + break; | |
| 21 | + case AttrNameval: | |
| 22 | + b = seprint(b, ebuf, " %q=%q", a->name, a->val); | |
| 23 | + break; | |
| 24 | + case AttrDefault: | |
| 25 | + b = seprint(b, ebuf, " %q:=%q", a->name, a->val); | |
| 26 | + break; | |
| 27 | + } | |
| 28 | + } | |
| 29 | + return fmtstrcpy(fmt, buf+1); | |
| 30 | +} | |
| 31 | + | |
| 32 | +Attr* | |
| 33 | +_copyattr(Attr *a) | |
| 34 | +{ | |
| 35 | + Attr **la, *na; | |
| 36 | + | |
| 37 | + na = nil; | |
| 38 | + la = &na; | |
| 39 | + for(; a; a=a->next){ | |
| 40 | + *la = _mkattr(a->type, a->name, a->val, nil); | |
| 41 | + setmalloctag(*la, getcallerpc(&a)); | |
| 42 | + la = &(*la)->next; | |
| 43 | + } | |
| 44 | + *la = nil; | |
| 45 | + return na; | |
| 46 | +} | |
| 47 | + | |
| 48 | +Attr* | |
| 49 | +_delattr(Attr *a, char *name) | |
| 50 | +{ | |
| 51 | + Attr *fa; | |
| 52 | + Attr **la; | |
| 53 | + | |
| 54 | + for(la=&a; *la; ){ | |
| 55 | + if(strcmp((*la)->name, name) == 0){ | |
| 56 | + fa = *la; | |
| 57 | + *la = (*la)->next; | |
| 58 | + fa->next = nil; | |
| 59 | + _freeattr(fa); | |
| 60 | + }else | |
| 61 | + la=&(*la)->next; | |
| 62 | + } | |
| 63 | + return a; | |
| 64 | +} | |
| 65 | + | |
| 66 | +Attr* | |
| 67 | +_findattr(Attr *a, char *n) | |
| 68 | +{ | |
| 69 | + for(; a; a=a->next) | |
| 70 | + if(strcmp(a->name, n) == 0 && a->type != AttrQuery) | |
| 71 | + return a; | |
| 72 | + return nil; | |
| 73 | +} | |
| 74 | + | |
| 75 | +void | |
| 76 | +_freeattr(Attr *a) | |
| 77 | +{ | |
| 78 | + Attr *anext; | |
| 79 | + | |
| 80 | + for(; a; a=anext){ | |
| 81 | + anext = a->next; | |
| 82 | + free(a->name); | |
| 83 | + free(a->val); | |
| 84 | + a->name = (void*)~0; | |
| 85 | + a->val = (void*)~0; | |
| 86 | + a->next = (void*)~0; | |
| 87 | + free(a); | |
| 88 | + } | |
| 89 | +} | |
| 90 | + | |
| 91 | +Attr* | |
| 92 | +_mkattr(int type, char *name, char *val, Attr *next) | |
| 93 | +{ | |
| 94 | + Attr *a; | |
| 95 | + | |
| 96 | + a = malloc(sizeof(*a)); | |
| 97 | + if(a==nil) | |
| 98 | + sysfatal("_mkattr malloc: %r"); | |
| 99 | + a->type = type; | |
| 100 | + a->name = strdup(name); | |
| 101 | + a->val = strdup(val); | |
| 102 | + if(a->name==nil || a->val==nil) | |
| 103 | + sysfatal("_mkattr malloc: %r"); | |
| 104 | + a->next = next; | |
| 105 | + setmalloctag(a, getcallerpc(&type)); | |
| 106 | + return a; | |
| 107 | +} | |
| 108 | + | |
| 109 | +static Attr* | |
| 110 | +cleanattr(Attr *a) | |
| 111 | +{ | |
| 112 | + Attr *fa; | |
| 113 | + Attr **la; | |
| 114 | + | |
| 115 | + for(la=&a; *la; ){ | |
| 116 | + if((*la)->type==AttrQuery && _findattr(a, (*la)->name)){ | |
| 117 | + fa = *la; | |
| 118 | + *la = (*la)->next; | |
| 119 | + fa->next = nil; | |
| 120 | + _freeattr(fa); | |
| 121 | + }else | |
| 122 | + la=&(*la)->next; | |
| 123 | + } | |
| 124 | + return a; | |
| 125 | +} | |
| 126 | + | |
| 127 | +Attr* | |
| 128 | +_parseattr(char *s) | |
| 129 | +{ | |
| 130 | + char *p, *t, *tok[256]; | |
| 131 | + int i, ntok, type; | |
| 132 | + Attr *a; | |
| 133 | + | |
| 134 | + s = strdup(s); | |
| 135 | + if(s == nil) | |
| 136 | + sysfatal("_parseattr strdup: %r"); | |
| 137 | + | |
| 138 | + ntok = tokenize(s, tok, nelem(tok)); | |
| 139 | + a = nil; | |
| 140 | + for(i=ntok-1; i>=0; i--){ | |
| 141 | + t = tok[i]; | |
| 142 | + if(p = strchr(t, '=')){ | |
| 143 | + *p++ = '\0'; | |
| 144 | + // if(p-2 >= t && p[-2] == ':'){ | |
| 145 | + // p[-2] = '\0'; | |
| 146 | + // type = AttrDefault; | |
| 147 | + // }else | |
| 148 | + type = AttrNameval; | |
| 149 | + a = _mkattr(type, t, p, a); | |
| 150 | + setmalloctag(a, getcallerpc(&s)); | |
| 151 | + } | |
| 152 | + else if(t[strlen(t)-1] == '?'){ | |
| 153 | + t[strlen(t)-1] = '\0'; | |
| 154 | + a = _mkattr(AttrQuery, t, "", a); | |
| 155 | + setmalloctag(a, getcallerpc(&s)); | |
| 156 | + }else{ | |
| 157 | + /* really a syntax error, but better to provide some indication */ | |
| 158 | + a = _mkattr(AttrNameval, t, "", a); | |
| 159 | + setmalloctag(a, getcallerpc(&s)); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + free(s); | |
| 163 | + return cleanattr(a); | |
| 164 | +} | |
| 165 | + | |
| 166 | +char* | |
| 167 | +_strfindattr(Attr *a, char *n) | |
| 168 | +{ | |
| 169 | + a = _findattr(a, n); | |
| 170 | + if(a == nil) | |
| 171 | + return nil; | |
| 172 | + return a->val; | |
| 173 | +} | |
| 174 | + | |
| @@ -0,0 +1,13 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <authsrv.h> | |
| 5 | +#include "authlocal.h" | |
| 6 | + | |
| 7 | +Attr* | |
| 8 | +auth_attr(AuthRpc *rpc) | |
| 9 | +{ | |
| 10 | + if(auth_rpc(rpc, "attr", nil, 0) != ARok) | |
| 11 | + return nil; | |
| 12 | + return _parseattr(rpc->arg); | |
| 13 | +} | |
| @@ -0,0 +1,117 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <authsrv.h> | |
| 5 | +#include "authlocal.h" | |
| 6 | + | |
| 7 | +Chalstate* | |
| 8 | +auth_challenge(char *fmt, ...) | |
| 9 | +{ | |
| 10 | + char *p; | |
| 11 | + va_list arg; | |
| 12 | + Chalstate *c; | |
| 13 | + | |
| 14 | + quotefmtinstall(); /* just in case */ | |
| 15 | + va_start(arg, fmt); | |
| 16 | + p = vsmprint(fmt, arg); | |
| 17 | + va_end(arg); | |
| 18 | + if(p == nil) | |
| 19 | + return nil; | |
| 20 | + | |
| 21 | + c = mallocz(sizeof(*c), 1); | |
| 22 | + if(c == nil){ | |
| 23 | + free(p); | |
| 24 | + return nil; | |
| 25 | + } | |
| 26 | + | |
| 27 | + if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){ | |
| 28 | + Error: | |
| 29 | + auth_freechal(c); | |
| 30 | + free(p); | |
| 31 | + return nil; | |
| 32 | + } | |
| 33 | + | |
| 34 | + if((c->rpc=auth_allocrpc(c->afd)) == nil | |
| 35 | + || auth_rpc(c->rpc, "start", p, strlen(p)) != ARok | |
| 36 | + || auth_rpc(c->rpc, "read", nil, 0) != ARok) | |
| 37 | + goto Error; | |
| 38 | + | |
| 39 | + if(c->rpc->narg > sizeof(c->chal)-1){ | |
| 40 | + werrstr("buffer too small for challenge"); | |
| 41 | + goto Error; | |
| 42 | + } | |
| 43 | + memmove(c->chal, c->rpc->arg, c->rpc->narg); | |
| 44 | + c->nchal = c->rpc->narg; | |
| 45 | + free(p); | |
| 46 | + return c; | |
| 47 | +} | |
| 48 | + | |
| 49 | +AuthInfo* | |
| 50 | +auth_response(Chalstate *c) | |
| 51 | +{ | |
| 52 | + int ret; | |
| 53 | + AuthInfo *ai; | |
| 54 | + | |
| 55 | + ai = nil; | |
| 56 | + if(c->afd < 0){ | |
| 57 | + werrstr("auth_response: connection not open"); | |
| 58 | + return nil; | |
| 59 | + } | |
| 60 | + if(c->resp == nil){ | |
| 61 | + werrstr("auth_response: nil response"); | |
| 62 | + return nil; | |
| 63 | + } | |
| 64 | + if(c->nresp == 0){ | |
| 65 | + werrstr("auth_response: unspecified response length"); | |
| 66 | + return nil; | |
| 67 | + } | |
| 68 | + | |
| 69 | + if(c->user){ | |
| 70 | + if(auth_rpc(c->rpc, "write", c->user, strlen(c->user)) != ARok){ | |
| 71 | + /* | |
| 72 | + * if this fails we're out of phase with factotum. | |
| 73 | + * give up. | |
| 74 | + */ | |
| 75 | + goto Out; | |
| 76 | + } | |
| 77 | + } | |
| 78 | + | |
| 79 | + if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){ | |
| 80 | + /* | |
| 81 | + * don't close the connection -- maybe we'll try again. | |
| 82 | + */ | |
| 83 | + return nil; | |
| 84 | + } | |
| 85 | + | |
| 86 | + switch(ret = auth_rpc(c->rpc, "read", nil, 0)){ | |
| 87 | + case ARok: | |
| 88 | + default: | |
| 89 | + werrstr("factotum protocol botch %d %s", ret, c->rpc->ibuf); | |
| 90 | + break; | |
| 91 | + case ARdone: | |
| 92 | + ai = auth_getinfo(c->rpc); | |
| 93 | + break; | |
| 94 | + } | |
| 95 | + | |
| 96 | +Out: | |
| 97 | + close(c->afd); | |
| 98 | + auth_freerpc(c->rpc); | |
| 99 | + c->afd = -1; | |
| 100 | + c->rpc = nil; | |
| 101 | + return ai; | |
| 102 | +} | |
| 103 | + | |
| 104 | +void | |
| 105 | +auth_freechal(Chalstate *c) | |
| 106 | +{ | |
| 107 | + if(c == nil) | |
| 108 | + return; | |
| 109 | + | |
| 110 | + if(c->afd >= 0) | |
| 111 | + close(c->afd); | |
| 112 | + if(c->rpc != nil) | |
| 113 | + auth_freerpc(c->rpc); | |
| 114 | + | |
| 115 | + memset(c, 0xBB, sizeof(*c)); | |
| 116 | + free(c); | |
| 117 | +} | |
| @@ -0,0 +1,75 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include "authlocal.h" | |
| 5 | + | |
| 6 | +enum { | |
| 7 | + ARgiveup = 100, | |
| 8 | +}; | |
| 9 | + | |
| 10 | +static int | |
| 11 | +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) | |
| 12 | +{ | |
| 13 | + int ret; | |
| 14 | + | |
| 15 | + for(;;){ | |
| 16 | + if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) | |
| 17 | + return ret; | |
| 18 | + if(getkey == nil) | |
| 19 | + return ARgiveup; /* don't know how */ | |
| 20 | + if((*getkey)(rpc->arg) < 0) | |
| 21 | + return ARgiveup; /* user punted */ | |
| 22 | + } | |
| 23 | +} | |
| 24 | + | |
| 25 | +UserPasswd* | |
| 26 | +auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...) | |
| 27 | +{ | |
| 28 | + AuthRpc *rpc; | |
| 29 | + char *f[3], *p, *params; | |
| 30 | + int fd; | |
| 31 | + va_list arg; | |
| 32 | + UserPasswd *up; | |
| 33 | + | |
| 34 | + up = nil; | |
| 35 | + rpc = nil; | |
| 36 | + params = nil; | |
| 37 | + | |
| 38 | + fd = open("/mnt/factotum/rpc", ORDWR); | |
| 39 | + if(fd < 0) | |
| 40 | + goto out; | |
| 41 | + rpc = auth_allocrpc(fd); | |
| 42 | + if(rpc == nil) | |
| 43 | + goto out; | |
| 44 | + quotefmtinstall(); /* just in case */ | |
| 45 | + va_start(arg, fmt); | |
| 46 | + params = vsmprint(fmt, arg); | |
| 47 | + va_end(arg); | |
| 48 | + if(params == nil) | |
| 49 | + goto out; | |
| 50 | + | |
| 51 | + if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok | |
| 52 | + || dorpc(rpc, "read", nil, 0, getkey) != ARok) | |
| 53 | + goto out; | |
| 54 | + | |
| 55 | + rpc->arg[rpc->narg] = '\0'; | |
| 56 | + if(tokenize(rpc->arg, f, 2) != 2){ | |
| 57 | + werrstr("bad answer from factotum"); | |
| 58 | + goto out; | |
| 59 | + } | |
| 60 | + up = malloc(sizeof(*up)+rpc->narg+1); | |
| 61 | + if(up == nil) | |
| 62 | + goto out; | |
| 63 | + p = (char*)&up[1]; | |
| 64 | + strcpy(p, f[0]); | |
| 65 | + up->user = p; | |
| 66 | + p += strlen(p)+1; | |
| 67 | + strcpy(p, f[1]); | |
| 68 | + up->passwd = p; | |
| 69 | + | |
| 70 | +out: | |
| 71 | + free(params); | |
| 72 | + auth_freerpc(rpc); | |
| 73 | + close(fd); | |
| 74 | + return up; | |
| 75 | +} | |
| @@ -0,0 +1,212 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <fcall.h> | |
| 4 | +#include <auth.h> | |
| 5 | +#include "authlocal.h" | |
| 6 | + | |
| 7 | +enum { | |
| 8 | + ARgiveup = 100, | |
| 9 | +}; | |
| 10 | + | |
| 11 | +static uchar* | |
| 12 | +gstring(uchar *p, uchar *ep, char **s) | |
| 13 | +{ | |
| 14 | + uint n; | |
| 15 | + | |
| 16 | + if(p == nil) | |
| 17 | + return nil; | |
| 18 | + if(p+BIT16SZ > ep) | |
| 19 | + return nil; | |
| 20 | + n = GBIT16(p); | |
| 21 | + p += BIT16SZ; | |
| 22 | + if(p+n > ep) | |
| 23 | + return nil; | |
| 24 | + *s = malloc(n+1); | |
| 25 | + memmove((*s), p, n); | |
| 26 | + (*s)[n] = '\0'; | |
| 27 | + p += n; | |
| 28 | + return p; | |
| 29 | +} | |
| 30 | + | |
| 31 | +static uchar* | |
| 32 | +gcarray(uchar *p, uchar *ep, uchar **s, int *np) | |
| 33 | +{ | |
| 34 | + uint n; | |
| 35 | + | |
| 36 | + if(p == nil) | |
| 37 | + return nil; | |
| 38 | + if(p+BIT16SZ > ep) | |
| 39 | + return nil; | |
| 40 | + n = GBIT16(p); | |
| 41 | + p += BIT16SZ; | |
| 42 | + if(p+n > ep) | |
| 43 | + return nil; | |
| 44 | + *s = malloc(n); | |
| 45 | + if(*s == nil) | |
| 46 | + return nil; | |
| 47 | + memmove((*s), p, n); | |
| 48 | + *np = n; | |
| 49 | + p += n; | |
| 50 | + return p; | |
| 51 | +} | |
| 52 | + | |
| 53 | +void | |
| 54 | +auth_freeAI(AuthInfo *ai) | |
| 55 | +{ | |
| 56 | + if(ai == nil) | |
| 57 | + return; | |
| 58 | + free(ai->cuid); | |
| 59 | + free(ai->suid); | |
| 60 | + free(ai->cap); | |
| 61 | + free(ai->secret); | |
| 62 | + free(ai); | |
| 63 | +} | |
| 64 | + | |
| 65 | +static uchar* | |
| 66 | +convM2AI(uchar *p, int n, AuthInfo **aip) | |
| 67 | +{ | |
| 68 | + uchar *e = p+n; | |
| 69 | + AuthInfo *ai; | |
| 70 | + | |
| 71 | + ai = mallocz(sizeof(*ai), 1); | |
| 72 | + if(ai == nil) | |
| 73 | + return nil; | |
| 74 | + | |
| 75 | + p = gstring(p, e, &ai->cuid); | |
| 76 | + p = gstring(p, e, &ai->suid); | |
| 77 | + p = gstring(p, e, &ai->cap); | |
| 78 | + p = gcarray(p, e, &ai->secret, &ai->nsecret); | |
| 79 | + if(p == nil) | |
| 80 | + auth_freeAI(ai); | |
| 81 | + else | |
| 82 | + *aip = ai; | |
| 83 | + return p; | |
| 84 | +} | |
| 85 | + | |
| 86 | +AuthInfo* | |
| 87 | +auth_getinfo(AuthRpc *rpc) | |
| 88 | +{ | |
| 89 | + AuthInfo *a; | |
| 90 | + | |
| 91 | + if(auth_rpc(rpc, "authinfo", nil, 0) != ARok) | |
| 92 | + return nil; | |
| 93 | + if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){ | |
| 94 | + werrstr("bad auth info from factotum"); | |
| 95 | + return nil; | |
| 96 | + } | |
| 97 | + return a; | |
| 98 | +} | |
| 99 | + | |
| 100 | +static int | |
| 101 | +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) | |
| 102 | +{ | |
| 103 | + int ret; | |
| 104 | + | |
| 105 | + for(;;){ | |
| 106 | + if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) | |
| 107 | + return ret; | |
| 108 | + if(getkey == nil) | |
| 109 | + return ARgiveup; /* don't know how */ | |
| 110 | + if((*getkey)(rpc->arg) < 0) | |
| 111 | + return ARgiveup; /* user punted */ | |
| 112 | + } | |
| 113 | +} | |
| 114 | + | |
| 115 | +/* | |
| 116 | + * this just proxies what the factotum tells it to. | |
| 117 | + */ | |
| 118 | +AuthInfo* | |
| 119 | +fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params) | |
| 120 | +{ | |
| 121 | + char *buf; | |
| 122 | + int m, n, ret; | |
| 123 | + AuthInfo *a; | |
| 124 | + char oerr[ERRMAX]; | |
| 125 | + | |
| 126 | + rerrstr(oerr, sizeof oerr); | |
| 127 | + werrstr("UNKNOWN AUTH ERROR"); | |
| 128 | + | |
| 129 | + if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ | |
| 130 | + werrstr("fauth_proxy start: %r"); | |
| 131 | + return nil; | |
| 132 | + } | |
| 133 | + | |
| 134 | + buf = malloc(AuthRpcMax); | |
| 135 | + if(buf == nil) | |
| 136 | + return nil; | |
| 137 | + for(;;){ | |
| 138 | + switch(dorpc(rpc, "read", nil, 0, getkey)){ | |
| 139 | + case ARdone: | |
| 140 | + free(buf); | |
| 141 | + a = auth_getinfo(rpc); | |
| 142 | + errstr(oerr, sizeof oerr); /* no error, restore whatever was there */ | |
| 143 | + return a; | |
| 144 | + case ARok: | |
| 145 | + if(write(fd, rpc->arg, rpc->narg) != rpc->narg){ | |
| 146 | + werrstr("auth_proxy write fd: %r"); | |
| 147 | + goto Error; | |
| 148 | + } | |
| 149 | + break; | |
| 150 | + case ARphase: | |
| 151 | + n = 0; | |
| 152 | + memset(buf, 0, AuthRpcMax); | |
| 153 | + while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){ | |
| 154 | + if(atoi(rpc->arg) > AuthRpcMax) | |
| 155 | + break; | |
| 156 | + m = read(fd, buf+n, atoi(rpc->arg)-n); | |
| 157 | + if(m <= 0){ | |
| 158 | + if(m == 0) | |
| 159 | + werrstr("auth_proxy short read: %s", buf); | |
| 160 | + goto Error; | |
| 161 | + } | |
| 162 | + n += m; | |
| 163 | + } | |
| 164 | + if(ret != ARok){ | |
| 165 | + werrstr("auth_proxy rpc write: %s: %r", buf); | |
| 166 | + goto Error; | |
| 167 | + } | |
| 168 | + break; | |
| 169 | + default: | |
| 170 | + werrstr("auth_proxy rpc: %r"); | |
| 171 | + goto Error; | |
| 172 | + } | |
| 173 | + } | |
| 174 | +Error: | |
| 175 | + free(buf); | |
| 176 | + return nil; | |
| 177 | +} | |
| 178 | + | |
| 179 | +AuthInfo* | |
| 180 | +auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...) | |
| 181 | +{ | |
| 182 | + int afd; | |
| 183 | + char *p; | |
| 184 | + va_list arg; | |
| 185 | + AuthInfo *ai; | |
| 186 | + AuthRpc *rpc; | |
| 187 | + | |
| 188 | + quotefmtinstall(); /* just in case */ | |
| 189 | + va_start(arg, fmt); | |
| 190 | + p = vsmprint(fmt, arg); | |
| 191 | + va_end(arg); | |
| 192 | + | |
| 193 | + afd = open("/mnt/factotum/rpc", ORDWR); | |
| 194 | + if(afd < 0){ | |
| 195 | + werrstr("opening /mnt/factotum/rpc: %r"); | |
| 196 | + free(p); | |
| 197 | + return nil; | |
| 198 | + } | |
| 199 | + | |
| 200 | + rpc = auth_allocrpc(afd); | |
| 201 | + if(rpc == nil){ | |
| 202 | + free(p); | |
| 203 | + return nil; | |
| 204 | + } | |
| 205 | + | |
| 206 | + ai = fauth_proxy(fd, rpc, getkey, p); | |
| 207 | + free(p); | |
| 208 | + auth_freerpc(rpc); | |
| 209 | + close(afd); | |
| 210 | + return ai; | |
| 211 | +} | |
| 212 | + | |
| @@ -0,0 +1,73 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <authsrv.h> | |
| 5 | +#include "authlocal.h" | |
| 6 | + | |
| 7 | +enum { | |
| 8 | + ARgiveup = 100, | |
| 9 | +}; | |
| 10 | + | |
| 11 | +static int | |
| 12 | +dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) | |
| 13 | +{ | |
| 14 | + int ret; | |
| 15 | + | |
| 16 | + for(;;){ | |
| 17 | + if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) | |
| 18 | + return ret; | |
| 19 | + if(getkey == nil) | |
| 20 | + return ARgiveup; /* don't know how */ | |
| 21 | + if((*getkey)(rpc->arg) < 0) | |
| 22 | + return ARgiveup; /* user punted */ | |
| 23 | + } | |
| 24 | +} | |
| 25 | + | |
| 26 | +int | |
| 27 | +auth_respond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...) | |
| 28 | +{ | |
| 29 | + char *p, *s; | |
| 30 | + va_list arg; | |
| 31 | + int afd; | |
| 32 | + AuthRpc *rpc; | |
| 33 | + Attr *a; | |
| 34 | + | |
| 35 | + if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0) | |
| 36 | + return -1; | |
| 37 | + | |
| 38 | + if((rpc = auth_allocrpc(afd)) == nil){ | |
| 39 | + close(afd); | |
| 40 | + return -1; | |
| 41 | + } | |
| 42 | + | |
| 43 | + quotefmtinstall(); /* just in case */ | |
| 44 | + va_start(arg, fmt); | |
| 45 | + p = vsmprint(fmt, arg); | |
| 46 | + va_end(arg); | |
| 47 | + | |
| 48 | + if(p==nil | |
| 49 | + || dorpc(rpc, "start", p, strlen(p), getkey) != ARok | |
| 50 | + || dorpc(rpc, "write", chal, nchal, getkey) != ARok | |
| 51 | + || dorpc(rpc, "read", nil, 0, getkey) != ARok){ | |
| 52 | + free(p); | |
| 53 | + close(afd); | |
| 54 | + auth_freerpc(rpc); | |
| 55 | + return -1; | |
| 56 | + } | |
| 57 | + free(p); | |
| 58 | + | |
| 59 | + if(rpc->narg < nresp) | |
| 60 | + nresp = rpc->narg; | |
| 61 | + memmove(resp, rpc->arg, nresp); | |
| 62 | + | |
| 63 | + if((a = auth_attr(rpc)) != nil | |
| 64 | + && (s = _strfindattr(a, "user")) != nil && strlen(s) < nuser) | |
| 65 | + strcpy(user, s); | |
| 66 | + else if(nuser > 0) | |
| 67 | + user[0] = '\0'; | |
| 68 | + | |
| 69 | + _freeattr(a); | |
| 70 | + close(afd); | |
| 71 | + auth_freerpc(rpc); | |
| 72 | + return nresp; | |
| 73 | +} | |
| @@ -0,0 +1,116 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include "authlocal.h" | |
| 5 | + | |
| 6 | +static struct { | |
| 7 | + char *verb; | |
| 8 | + int val; | |
| 9 | +} tab[] = { | |
| 10 | + "ok", ARok, | |
| 11 | + "done", ARdone, | |
| 12 | + "error", ARerror, | |
| 13 | + "needkey", ARneedkey, | |
| 14 | + "badkey", ARbadkey, | |
| 15 | + "phase", ARphase, | |
| 16 | + "toosmall", ARtoosmall, | |
| 17 | + "error", ARerror, | |
| 18 | +}; | |
| 19 | + | |
| 20 | +static int | |
| 21 | +classify(char *buf, uint n, AuthRpc *rpc) | |
| 22 | +{ | |
| 23 | + int i, len; | |
| 24 | + | |
| 25 | + for(i=0; i<nelem(tab); i++){ | |
| 26 | + len = strlen(tab[i].verb); | |
| 27 | + if(n >= len && memcmp(buf, tab[i].verb, len) == 0 && (n==len || buf[len]==' ')){ | |
| 28 | + if(n==len){ | |
| 29 | + rpc->narg = 0; | |
| 30 | + rpc->arg = ""; | |
| 31 | + }else{ | |
| 32 | + rpc->narg = n - (len+1); | |
| 33 | + rpc->arg = (char*)buf+len+1; | |
| 34 | + } | |
| 35 | + return tab[i].val; | |
| 36 | + } | |
| 37 | + } | |
| 38 | + werrstr("malformed rpc response: %s", buf); | |
| 39 | + return ARrpcfailure; | |
| 40 | +} | |
| 41 | + | |
| 42 | +AuthRpc* | |
| 43 | +auth_allocrpc(int afd) | |
| 44 | +{ | |
| 45 | + AuthRpc *rpc; | |
| 46 | + | |
| 47 | + rpc = mallocz(sizeof(*rpc), 1); | |
| 48 | + if(rpc == nil) | |
| 49 | + return nil; | |
| 50 | + rpc->afd = afd; | |
| 51 | + return rpc; | |
| 52 | +} | |
| 53 | + | |
| 54 | +void | |
| 55 | +auth_freerpc(AuthRpc *rpc) | |
| 56 | +{ | |
| 57 | + free(rpc); | |
| 58 | +} | |
| 59 | + | |
| 60 | +uint | |
| 61 | +auth_rpc(AuthRpc *rpc, char *verb, void *a, int na) | |
| 62 | +{ | |
| 63 | + int l, n, type; | |
| 64 | + char *f[4]; | |
| 65 | + | |
| 66 | + l = strlen(verb); | |
| 67 | + if(na+l+1 > AuthRpcMax){ | |
| 68 | + werrstr("rpc too big"); | |
| 69 | + return ARtoobig; | |
| 70 | + } | |
| 71 | + | |
| 72 | + memmove(rpc->obuf, verb, l); | |
| 73 | + rpc->obuf[l] = ' '; | |
| 74 | + memmove(rpc->obuf+l+1, a, na); | |
| 75 | + if((n=write(rpc->afd, rpc->obuf, l+1+na)) != l+1+na){ | |
| 76 | + if(n >= 0) | |
| 77 | + werrstr("auth_rpc short write"); | |
| 78 | + return ARrpcfailure; | |
| 79 | + } | |
| 80 | + | |
| 81 | + if((n=read(rpc->afd, rpc->ibuf, AuthRpcMax)) < 0) | |
| 82 | + return ARrpcfailure; | |
| 83 | + rpc->ibuf[n] = '\0'; | |
| 84 | + | |
| 85 | + /* | |
| 86 | + * Set error string for good default behavior. | |
| 87 | + */ | |
| 88 | + switch(type = classify(rpc->ibuf, n, rpc)){ | |
| 89 | + default: | |
| 90 | + werrstr("unknown rpc type %d (bug in auth_rpc.c)", type); | |
| 91 | + break; | |
| 92 | + case ARok: | |
| 93 | + break; | |
| 94 | + case ARrpcfailure: | |
| 95 | + break; | |
| 96 | + case ARerror: | |
| 97 | + if(rpc->narg == 0) | |
| 98 | + werrstr("unspecified rpc error"); | |
| 99 | + else | |
| 100 | + werrstr("%s", rpc->arg); | |
| 101 | + break; | |
| 102 | + case ARneedkey: | |
| 103 | + werrstr("needkey %s", rpc->arg); | |
| 104 | + break; | |
| 105 | + case ARbadkey: | |
| 106 | + if(getfields(rpc->arg, f, nelem(f), 0, "\n") < 2) | |
| 107 | + werrstr("badkey %s", rpc->arg); | |
| 108 | + else | |
| 109 | + werrstr("badkey %s", f[1]); | |
| 110 | + break; | |
| 111 | + case ARphase: | |
| 112 | + werrstr("phase error %s", rpc->arg); | |
| 113 | + break; | |
| 114 | + } | |
| 115 | + return type; | |
| 116 | +} | |
| @@ -0,0 +1,50 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <authsrv.h> | |
| 5 | +#include "authlocal.h" | |
| 6 | + | |
| 7 | +/* | |
| 8 | + * compute the proper response. We encrypt the ascii of | |
| 9 | + * challenge number, with trailing binary zero fill. | |
| 10 | + * This process was derived empirically. | |
| 11 | + * this was copied from inet's guard. | |
| 12 | + */ | |
| 13 | +static void | |
| 14 | +netresp(char *key, long chal, char *answer) | |
| 15 | +{ | |
| 16 | + uchar buf[8]; | |
| 17 | + | |
| 18 | + memset(buf, 0, 8); | |
| 19 | + sprint((char *)buf, "%lud", chal); | |
| 20 | + if(encrypt(key, buf, 8) < 0) | |
| 21 | + abort(); | |
| 22 | + chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3]; | |
| 23 | + sprint(answer, "%.8lux", chal); | |
| 24 | +} | |
| 25 | + | |
| 26 | +AuthInfo* | |
| 27 | +auth_userpasswd(char *user, char *passwd) | |
| 28 | +{ | |
| 29 | + char key[DESKEYLEN], resp[16]; | |
| 30 | + AuthInfo *ai; | |
| 31 | + Chalstate *ch; | |
| 32 | + | |
| 33 | + /* | |
| 34 | + * Probably we should have a factotum protocol | |
| 35 | + * to check a raw password. For now, we use | |
| 36 | + * p9cr, which is simplest to speak. | |
| 37 | + */ | |
| 38 | + if((ch = auth_challenge("user=%q proto=p9cr role=server", user)) == nil) | |
| 39 | + return nil; | |
| 40 | + | |
| 41 | + passtokey(key, passwd); | |
| 42 | + netresp(key, atol(ch->chal), resp); | |
| 43 | + memset(key, 0, sizeof key); | |
| 44 | + | |
| 45 | + ch->resp = resp; | |
| 46 | + ch->nresp = strlen(resp); | |
| 47 | + ai = auth_response(ch); | |
| 48 | + auth_freechal(ch); | |
| 49 | + return ai; | |
| 50 | +} | |
| @@ -0,0 +1 @@ | ||
| 1 | +extern AuthInfo* _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params); | |
| @@ -0,0 +1,51 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <authsrv.h> | |
| 5 | + | |
| 6 | +/* deprecated. | |
| 7 | + This is the mechanism that put entries in /sys/lib/httpd.rewrite | |
| 8 | + and passwords on the authserver in /sys/lib/httppasswords, which | |
| 9 | + was awkward to administer. Instead, use local .httplogin files, | |
| 10 | + which are implemented in sys/src/cmd/ip/httpd/authorize.c */ | |
| 11 | + | |
| 12 | +int | |
| 13 | +httpauth(char *name, char *password) | |
| 14 | +{ | |
| 15 | + int afd; | |
| 16 | + Ticketreq tr; | |
| 17 | + Ticket t; | |
| 18 | + char key[DESKEYLEN]; | |
| 19 | + char buf[512]; | |
| 20 | + | |
| 21 | + afd = authdial(nil, nil); | |
| 22 | + if(afd < 0) | |
| 23 | + return -1; | |
| 24 | + | |
| 25 | + /* send ticket request to AS */ | |
| 26 | + memset(&tr, 0, sizeof(tr)); | |
| 27 | + strcpy(tr.uid, name); | |
| 28 | + tr.type = AuthHttp; | |
| 29 | + convTR2M(&tr, buf); | |
| 30 | + if(write(afd, buf, TICKREQLEN) != TICKREQLEN){ | |
| 31 | + close(afd); | |
| 32 | + return -1; | |
| 33 | + } | |
| 34 | + if(_asrdresp(afd, buf, TICKETLEN) < 0){ | |
| 35 | + close(afd); | |
| 36 | + return -1; | |
| 37 | + } | |
| 38 | + close(afd); | |
| 39 | + | |
| 40 | + /* | |
| 41 | + * use password and try to decrypt the | |
| 42 | + * ticket. If it doesn't work we've got a bad password, | |
| 43 | + * give up. | |
| 44 | + */ | |
| 45 | + passtokey(key, password); | |
| 46 | + convM2T(buf, &t, key); | |
| 47 | + if(t.num != AuthHr || strcmp(t.cuid, tr.uid)) | |
| 48 | + return -1; | |
| 49 | + | |
| 50 | + return 0; | |
| 51 | +} | |
| @@ -36,6 +36,8 @@ main(int argc, char **argv) · 35 unmodified lines | ||
| 36 | 36 | char buf[1024], *s; |
| 37 | 37 | int n; |
| 38 | 38 | |
| 39 | + eve = getuser(); | |
| 40 | + | |
| 39 | 41 | sizebug(); |
| 40 | 42 | fmtinstall('r', errfmt); |
| 41 | 43 | |
| @@ -0,0 +1,107 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <sys/socket.h> | |
| 3 | +#include <sys/un.h> | |
| 4 | +#include <pwd.h> | |
| 5 | +#include <libc.h> | |
| 6 | +#include <auth.h> | |
| 7 | +#include <fcall.h> | |
| 8 | +#include <authsrv.h> | |
| 9 | +#include <libsec.h> | |
| 10 | +#include "drawterm.h" | |
| 11 | + | |
| 12 | +#undef socket | |
| 13 | +#undef connect | |
| 14 | +#undef getenv | |
| 15 | +#undef access | |
| 16 | + | |
| 17 | +char* | |
| 18 | +getuser(void) | |
| 19 | +{ | |
| 20 | + static char user[64]; | |
| 21 | + struct passwd *pw; | |
| 22 | + | |
| 23 | + pw = getpwuid(getuid()); | |
| 24 | + if(pw == nil) | |
| 25 | + return "none"; | |
| 26 | + strecpy(user, user+sizeof user, pw->pw_name); | |
| 27 | + return user; | |
| 28 | +} | |
| 29 | +/* | |
| 30 | + * Absent other hints, it works reasonably well to use | |
| 31 | + * the X11 display name as the name space identifier. | |
| 32 | + * This is how sam's B has worked since the early days. | |
| 33 | + * Since most programs using name spaces are also using X, | |
| 34 | + * this still seems reasonable. Terminal-only sessions | |
| 35 | + * can set $NAMESPACE. | |
| 36 | + */ | |
| 37 | +static char* | |
| 38 | +nsfromdisplay(void) | |
| 39 | +{ | |
| 40 | + int fd; | |
| 41 | + Dir *d; | |
| 42 | + char *disp, *p; | |
| 43 | + | |
| 44 | + if((disp = getenv("DISPLAY")) == nil){ | |
| 45 | + werrstr("$DISPLAY not set"); | |
| 46 | + return nil; | |
| 47 | + } | |
| 48 | + | |
| 49 | + /* canonicalize: xxx:0.0 => xxx:0 */ | |
| 50 | + p = strrchr(disp, ':'); | |
| 51 | + if(p){ | |
| 52 | + p++; | |
| 53 | + while(isdigit((uchar)*p)) | |
| 54 | + p++; | |
| 55 | + if(strcmp(p, ".0") == 0) | |
| 56 | + *p = 0; | |
| 57 | + } | |
| 58 | + | |
| 59 | + return smprint("/tmp/ns.%s.%s", getuser(), disp); | |
| 60 | +} | |
| 61 | + | |
| 62 | +char* | |
| 63 | +getns(void) | |
| 64 | +{ | |
| 65 | + char *ns; | |
| 66 | + | |
| 67 | + ns = getenv("NAMESPACE"); | |
| 68 | + if(ns == nil) | |
| 69 | + ns = nsfromdisplay(); | |
| 70 | + if(ns == nil){ | |
| 71 | + werrstr("$NAMESPACE not set, %r"); | |
| 72 | + return nil; | |
| 73 | + } | |
| 74 | + return ns; | |
| 75 | +} | |
| 76 | + | |
| 77 | +int | |
| 78 | +dialfactotum(void) | |
| 79 | +{ | |
| 80 | + int fd; | |
| 81 | + struct sockaddr_un su; | |
| 82 | + char *name; | |
| 83 | + | |
| 84 | + name = smprint("%s/factotum", getns()); | |
| 85 | + | |
| 86 | + if(name == nil || access(name, 0) < 0) | |
| 87 | + return -1; | |
| 88 | + memset(&su, 0, sizeof su); | |
| 89 | + su.sun_family = AF_UNIX; | |
| 90 | + if(strlen(name)+1 > sizeof su.sun_path){ | |
| 91 | + werrstr("socket name too long"); | |
| 92 | + return -1; | |
| 93 | + } | |
| 94 | + strcpy(su.sun_path, name); | |
| 95 | + if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){ | |
| 96 | + werrstr("socket: %r"); | |
| 97 | + return -1; | |
| 98 | + } | |
| 99 | + if(connect(fd, (struct sockaddr*)&su, sizeof su) < 0){ | |
| 100 | + werrstr("connect %s: %r", name); | |
| 101 | + close(fd); | |
| 102 | + return -1; | |
| 103 | + } | |
| 104 | + | |
| 105 | + return lfdfd(fd); | |
| 106 | +} | |
| 107 | + | |
| @@ -0,0 +1,22 @@ | ||
| 1 | +#include <u.h> | |
| 2 | +#include <libc.h> | |
| 3 | +#include <auth.h> | |
| 4 | +#include <fcall.h> | |
| 5 | +#include <authsrv.h> | |
| 6 | +#include <libsec.h> | |
| 7 | +#include "drawterm.h" | |
| 8 | + | |
| 9 | +#undef getenv | |
| 10 | + | |
| 11 | +char* | |
| 12 | +getuser(void) | |
| 13 | +{ | |
| 14 | + return getenv("USER"); | |
| 15 | +} | |
| 16 | + | |
| 17 | +int | |
| 18 | +dialfactotum(void) | |
| 19 | +{ | |
| 20 | + return -1; | |
| 21 | +} | |
| 22 | + | |