Blob


1 #include "std.h"
2 #include "dat.h"
3 #include <9pclient.h>
5 int extrafactotumdir;
6 int debug;
7 int trysecstore = 1;
8 char *factname = "factotum";
9 char *service = "factotum";
10 char *owner;
11 char *authaddr;
12 void gflag(char*);
14 void
15 usage(void)
16 {
17 fprint(2, "usage: factotum [-Dd] [-a authaddr] [-m mtpt] [-s service]\n");
18 fprint(2, " or factotum -g keypattern\n");
19 fprint(2, " or factotum -g 'badkeyattr\\nmsg\\nkeypattern'\n");
20 threadexitsall("usage");
21 }
23 void
24 threadmain(int argc, char *argv[])
25 {
26 char *mtpt;
27 char err[ERRMAX];
29 /* mtpt = "/mnt"; */
30 mtpt = nil;
31 owner = getuser();
32 quotefmtinstall();
33 fmtinstall('A', attrfmt);
34 fmtinstall('H', encodefmt);
35 fmtinstall('N', attrnamefmt);
37 if(argc == 3 && strcmp(argv[1], "-g") == 0){
38 gflag(argv[2]);
39 threadexitsall(nil);
40 }
42 ARGBEGIN{
43 default:
44 usage();
45 case 'D':
46 chatty9p++;
47 break;
48 case 'a':
49 authaddr = EARGF(usage());
50 break;
51 case 'd':
52 debug = 1;
53 break;
54 case 'g':
55 usage();
56 case 'm':
57 mtpt = EARGF(usage());
58 break;
59 case 's':
60 service = EARGF(usage());
61 break;
62 case 'n':
63 trysecstore = 0;
64 break;
65 case 'x':
66 extrafactotumdir = 1;
67 break;
68 }ARGEND
70 if(argc != 0)
71 usage();
73 rfork(RFNOTEG);
75 if(trysecstore && havesecstore()){
76 while(secstorefetch() < 0){
77 rerrstr(err, sizeof err);
78 if(strcmp(err, "cancel") == 0)
79 break;
80 fprint(2, "secstorefetch: %r\n");
81 fprint(2, "Enter an empty password to quit.\n");
82 }
83 }
85 fsinit0();
86 threadpostmountsrv(&fs, service, mtpt, MBEFORE);
87 threadexits(nil);
88 }
90 /*
91 * prompt user for a key. don't care about memory leaks, runs standalone
92 */
93 static Attr*
94 promptforkey(int fd, char *params)
95 {
96 char *v;
97 Attr *a, *attr;
98 char *def;
100 attr = _parseattr(params);
101 fprint(fd, "!adding key:");
102 for(a=attr; a; a=a->next)
103 if(a->type != AttrQuery && a->name[0] != '!')
104 fprint(fd, " %q=%q", a->name, a->val);
105 fprint(fd, "\n");
107 for(a=attr; a; a=a->next){
108 v = a->name;
109 if(a->type != AttrQuery || v[0]=='!')
110 continue;
111 def = nil;
112 if(strcmp(v, "user") == 0)
113 def = getuser();
114 a->val = readcons(v, def, 0);
115 if(a->val == nil)
116 sysfatal("user terminated key input");
117 a->type = AttrNameval;
119 for(a=attr; a; a=a->next){
120 v = a->name;
121 if(a->type != AttrQuery || v[0]!='!')
122 continue;
123 def = nil;
124 if(strcmp(v+1, "user") == 0)
125 def = getuser();
126 a->val = readcons(v+1, def, 1);
127 if(a->val == nil)
128 sysfatal("user terminated key input");
129 a->type = AttrNameval;
131 fprint(fd, "!\n");
132 close(fd);
133 return attr;
136 /*
137 * send a key to the mounted factotum
138 */
139 static int
140 sendkey(Attr *attr)
142 int rv;
143 char buf[8192];
144 CFid *fid;
146 fid = nsopen("factotum", nil, "ctl", OWRITE);
147 if(fid == nil)
148 sysfatal("opening factotum/ctl: %r");
149 snprint(buf, sizeof buf, "key %A\n", attr);
150 rv = fswrite(fid, buf, strlen(buf));
151 fsclose(fid);
152 return rv;
155 static void
156 askuser(int fd, char *params)
158 Attr *attr;
160 attr = promptforkey(fd, params);
161 if(attr == nil)
162 sysfatal("no key supplied");
163 if(sendkey(attr) < 0)
164 sysfatal("sending key to factotum: %r");
167 void
168 gflag(char *s)
170 char *f[4];
171 int nf;
172 int fd;
174 if((fd = open("/dev/tty", ORDWR)) < 0)
175 sysfatal("open /dev/tty: %r");
177 nf = getfields(s, f, nelem(f), 0, "\n");
178 if(nf == 1){ /* needkey or old badkey */
179 fprint(fd, "\n");
180 askuser(fd, s);
181 threadexitsall(nil);
183 if(nf == 3){ /* new badkey */
184 fprint(fd, "\n");
185 fprint(fd, "!replace: %s\n", f[0]);
186 fprint(fd, "!because: %s\n", f[1]);
187 askuser(fd, f[2]);
188 threadexitsall(nil);
190 usage();