blob: 1f603ac7a0e6ed9218f29ae4ac36caaca18b5713 [file] [log] [blame]
#include "std.h"
#include "dat.h"
#include <9pclient.h>
int extrafactotumdir;
int debug;
int trysecstore = 1;
char *factname = "factotum";
char *service = "factotum";
char *owner;
char *authaddr;
void gflag(char*);
void
usage(void)
{
fprint(2, "usage: factotum [-Dd] [-a authaddr] [-m mtpt] [-s service]\n");
fprint(2, " or factotum -g keypattern\n");
fprint(2, " or factotum -g 'badkeyattr\\nmsg\\nkeypattern'\n");
threadexitsall("usage");
}
void
threadmain(int argc, char *argv[])
{
char *mtpt;
char err[ERRMAX];
/* mtpt = "/mnt"; */
mtpt = nil;
owner = getuser();
quotefmtinstall();
fmtinstall('A', attrfmt);
fmtinstall('H', encodefmt);
fmtinstall('N', attrnamefmt);
if(argc == 3 && strcmp(argv[1], "-g") == 0){
gflag(argv[2]);
threadexitsall(nil);
}
ARGBEGIN{
default:
usage();
case 'D':
chatty9p++;
break;
case 'a':
authaddr = EARGF(usage());
break;
case 'd':
debug = 1;
break;
case 'g':
usage();
case 'm':
mtpt = EARGF(usage());
break;
case 's':
service = EARGF(usage());
break;
case 'n':
trysecstore = 0;
break;
case 'x':
extrafactotumdir = 1;
break;
}ARGEND
if(argc != 0)
usage();
if(trysecstore && havesecstore()){
while(secstorefetch() < 0){
rerrstr(err, sizeof err);
if(strcmp(err, "cancel") == 0)
break;
fprint(2, "secstorefetch: %r\n");
fprint(2, "Enter an empty password to quit.\n");
}
}
rfork(RFNOTEG);
fsinit0();
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 rv;
char buf[8192];
CFid *fid;
fid = nsopen("factotum", nil, "ctl", OWRITE);
if(fid == nil)
sysfatal("opening factotum/ctl: %r");
snprint(buf, sizeof buf, "key %A\n", attr);
rv = fswrite(fid, buf, strlen(buf));
fsclose(fid);
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/tty", ORDWR)) < 0)
sysfatal("open /dev/tty: %r");
nf = getfields(s, f, nelem(f), 0, "\n");
if(nf == 1){ /* needkey or old badkey */
fprint(fd, "\n");
askuser(fd, s);
threadexitsall(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]);
threadexitsall(nil);
}
usage();
}