diff options
Diffstat (limited to 'src/cmd/factotum/main.c')
-rw-r--r-- | src/cmd/factotum/main.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/cmd/factotum/main.c b/src/cmd/factotum/main.c new file mode 100644 index 00000000..3e9f89f8 --- /dev/null +++ b/src/cmd/factotum/main.c @@ -0,0 +1,163 @@ +#include "std.h" +#include "dat.h" + +int debug; +char *factname = "factotum"; +char *service = nil; +char *owner; +char *authaddr; +void gflag(char*); + +void +usage(void) +{ + fprint(2, "usage: factotum [-Dd] [-a authaddr] [-m mtpt]\n"); + fprint(2, " or factotum -g keypattern\n"); + fprint(2, " or factotum -g 'badkeyattr\nmsg\nkeypattern'"); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + char *mtpt; + + mtpt = "/mnt"; + owner = getuser(); + quotefmtinstall(); + fmtinstall('A', attrfmt); + fmtinstall('H', encodefmt); + fmtinstall('N', attrnamefmt); + + if(argc == 3 && strcmp(argv[1], "-g") == 0){ + gflag(argv[2]); + exits(nil); + } + + ARGBEGIN{ + default: + usage(); + case 'D': + chatty9p++; + break; + case 'a': + authaddr = EARGF(usage()); + break; + case 'g': + usage(); + case 'm': + mtpt = EARGF(usage()); + break; + case 's': + service = EARGF(usage()); + break; + }ARGEND + + if(argc != 0) + usage(); + + threadpostmountsrv(&fs, service, mtpt, MBEFORE); + threadexits(nil); +} + +/* + * prompt user for a key. don't care about memory leaks, runs standalone + */ +static Attr* +promptforkey(int fd, char *params) +{ + char *v; + Attr *a, *attr; + char *def; + + attr = _parseattr(params); + fprint(fd, "!adding key:"); + for(a=attr; a; a=a->next) + if(a->type != AttrQuery && a->name[0] != '!') + fprint(fd, " %q=%q", a->name, a->val); + fprint(fd, "\n"); + + for(a=attr; a; a=a->next){ + v = a->name; + if(a->type != AttrQuery || v[0]=='!') + continue; + def = nil; + if(strcmp(v, "user") == 0) + def = getuser(); + a->val = readcons(v, def, 0); + if(a->val == nil) + sysfatal("user terminated key input"); + a->type = AttrNameval; + } + for(a=attr; a; a=a->next){ + v = a->name; + if(a->type != AttrQuery || v[0]!='!') + continue; + def = nil; + if(strcmp(v+1, "user") == 0) + def = getuser(); + a->val = readcons(v+1, def, 1); + if(a->val == nil) + sysfatal("user terminated key input"); + a->type = AttrNameval; + } + fprint(fd, "!\n"); + close(fd); + return attr; +} + +/* + * send a key to the mounted factotum + */ +static int +sendkey(Attr *attr) +{ + int fd, rv; + char buf[1024]; + + fd = open("/mnt/factotum/ctl", ORDWR); + if(fd < 0) + sysfatal("opening /mnt/factotum/ctl: %r"); + rv = fprint(fd, "key %A\n", attr); + read(fd, buf, sizeof buf); + close(fd); + return rv; +} + +static void +askuser(int fd, char *params) +{ + Attr *attr; + + attr = promptforkey(fd, params); + if(attr == nil) + sysfatal("no key supplied"); + if(sendkey(attr) < 0) + sysfatal("sending key to factotum: %r"); +} + +void +gflag(char *s) +{ + char *f[4]; + int nf; + int fd; + + if((fd = open("/dev/cons", ORDWR)) < 0) + sysfatal("open /dev/cons: %r"); + + nf = getfields(s, f, nelem(f), 0, "\n"); + if(nf == 1){ /* needkey or old badkey */ + fprint(fd, "\n"); + askuser(fd, s); + exits(nil); + } + if(nf == 3){ /* new badkey */ + fprint(fd, "\n"); + fprint(fd, "!replace: %s\n", f[0]); + fprint(fd, "!because: %s\n", f[1]); + askuser(fd, f[2]); + exits(nil); + } + usage(); +} |