]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/asaudit.c
merge
[plan9front.git] / sys / src / cmd / auth / asaudit.c
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mp.h>
5 #include <libsec.h>
6 #include <auth.h>
7 #include <authsrv.h>
8 #include <ndb.h>
9
10 int havenvram, havekeyfs;
11 Nvrsafe nvr;
12 uchar keyfskey[AESKEYLEN];
13 char eve[128];
14 Ndb *db;
15
16 void
17 geteve(void)
18 {
19         int fd;
20         
21         fd = open("#c/hostowner", OREAD);
22         if(fd < 0) sysfatal("open: %r");
23         memset(eve, 0, sizeof(eve));
24         if(read(fd, eve, sizeof(eve)-1) < 0) sysfatal("read: %r");
25         close(fd);
26         if(strcmp(getuser(), eve) != 0) print("hostowner is %#q, but running as %#q\n", eve, getuser());
27 }
28
29 void
30 ndb(void)
31 {
32         db = ndbopen(nil);
33         if(db == nil){
34                 print("ndbopen: %r\n");
35                 return;
36         }
37 }
38
39 void
40 nvram(void)
41 {
42         char *auth;
43
44         if(readnvram(&nvr, 0) < 0){
45                 print("readnvram: %r\n");
46                 return;
47         }
48         havenvram = 1;
49         print("GOOD: found nvram key for user '%s@%s'\n", nvr.authid, nvr.authdom);
50         if(strcmp(eve, nvr.authid) != 0) print("BAD: nvram authid doesn't match hostowner %#q\n", eve);
51         if(db != nil){
52                 auth = ndbgetvalue(db, nil, "authdom", nvr.authdom, "auth", nil);
53                 if(auth == nil) print("BAD: authdom %#q not found in ndb\n", nvr.authdom);
54                 else{
55                         print("ndb says authdom %#q corresponds to auth server %#q\n", nvr.authdom, auth);
56                         free(auth);
57                 }
58         }
59 }
60
61 void
62 keyfs(void)
63 {
64         char *buf;
65         int fd;
66         char aes[AESKEYLEN];
67
68         if(!havenvram) return;
69         if(access("/adm/keys", AREAD) < 0){
70                 print("no access to /adm/keys\n");
71                 return;
72         }
73         print("starting keyfs\n");
74         rfork(RFNAMEG);
75         switch(fork()){
76         case -1:
77                 sysfatal("fork: %r");
78         case 0:
79                 if(execl("/bin/auth/keyfs", "auth/keyfs", "-r", nil) < 0)
80                         sysfatal("execl: %r");
81         }
82         waitpid();
83         buf = smprint("/mnt/keys/%s/aeskey", nvr.authid);
84         fd = open(buf, OREAD);
85         if(fd < 0){
86                 print("BAD: can't get key from keyfs: %r\n");
87                 return;
88         }
89         werrstr("short read");
90         if(read(fd, aes, sizeof(aes)) < sizeof(aes)){
91                 print("read: %r\n");
92                 close(fd);
93                 return;
94         }
95         havekeyfs = 1;
96         memmove(keyfskey, aes, AESKEYLEN);
97         if(memcmp(nvr.aesmachkey, aes, AESKEYLEN) != 0)
98                 print("BAD: key in keyfs does not match nvram\n");
99         else
100                 print("GOOD: key in keyfs matches nvram\n");
101         close(fd);
102 }
103
104 int
105 checkkey(void)
106 {
107         Biobuf *bp;
108         Attr *at, *ap;
109         char *l;
110         int proto, dom, user;
111
112         bp = Bopen("/mnt/factotum/ctl", OREAD);
113         if(bp == nil){
114                 print("can't open /mnt/factotum/ctl: %r\n");
115                 return 0;
116         }
117         proto = dom = user = 0;
118         while(l = Brdstr(bp, '\n', 1), l != nil){
119                 if(strncmp(l, "key ", 4) != 0) continue;
120                 at = _parseattr(l + 4);
121                 free(l);
122                 proto = dom = user = 0;
123                 for(ap = at; ap != nil; ap = ap->next){
124                         if(strcmp(ap->name, "proto") == 0 && strcmp(ap->val, "dp9ik") == 0)
125                                 proto++;
126                         if(strcmp(ap->name, "dom") == 0 && strcmp(ap->val, nvr.authdom) == 0)
127                                 dom++;
128                         if(strcmp(ap->name, "user") == 0 && strcmp(ap->val, nvr.authid) == 0)
129                                 user++;
130                         if(strcmp(ap->name, "disabled") == 0){
131                                 proto = dom = user = 0;
132                                 break;
133                         }
134                 }
135                 _freeattr(at);
136                 if(proto && dom && user)
137                         break;
138         }
139         Bterm(bp);
140         if(!proto || !dom || !user){
141                 print("can't test factotum key: no key for '%s@%s' in factotum\n", nvr.authdom, nvr.authid);
142                 return 0;
143         }
144         return 1;
145 }
146
147 int
148 trykey(int keyfs)
149 {
150         int fd, rc;
151         AuthRpc *rpc;
152         Authkey ak;
153         PAKpriv pr;
154         Ticketreq tr;
155         Ticket t;
156         Authenticator a;
157         char *s;
158         uchar chal[CHALLEN], paky[PAKYLEN];
159         char tick[MAXTICKETLEN+MAXAUTHENTLEN];
160         char errbuf[ERRMAX];
161         char *source;
162         
163         source = keyfs ? "keyfs" : "nvram";
164         fd = open("/mnt/factotum/rpc", ORDWR);
165         if(fd < 0){ print("open: %r\n"); return -1; }
166         print("trying %s key for %s@%s with factotum\n", source, nvr.authdom, nvr.authid);
167         rpc = auth_allocrpc(fd);
168         if(rpc == nil){ print("auth_allocrpc: %r\n"); return -1; }
169         
170         s = smprint("proto=dp9ik dom=%q user=%q role=server", nvr.authdom, nvr.authid);
171         if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){ print("auth_rpc start: %r\n"); goto err; } 
172         free(s);
173         
174         genrandom(chal, CHALLEN);
175         if(auth_rpc(rpc, "write", chal, CHALLEN) != ARok){ print("BAD: auth_rpc write challenge: %r\n"); goto err; }
176
177         if(auth_rpc(rpc, "read", nil, 0) != ARok){ print("BAD: auth_rpc read ticket request: %r\n"); goto err; }
178         rc = convM2TR(rpc->arg, rpc->narg, &tr);
179         memset(&ak, 0, sizeof(ak));
180         memmove(ak.aes, nvr.aesmachkey, AESKEYLEN);
181         
182         authpak_hash(&ak, nvr.authid);
183         authpak_new(&pr, &ak, paky, 0);
184         authpak_finish(&pr, &ak, (uchar *)rpc->arg + rc);
185         if(auth_rpc(rpc, "write", paky, PAKYLEN) != ARok){ print("BAD: auth_rpc write public key: %r\n"); goto err; }
186
187         t.num = AuthTs; 
188         memmove(t.chal, tr.chal, CHALLEN);
189         strcpy(t.cuid, nvr.authid);
190         strcpy(t.suid, nvr.authid);
191         genrandom(t.key, sizeof(t.key));
192         t.form = 1;
193         rc = convT2M(&t, tick, MAXTICKETLEN, &ak);
194         
195         a.num = AuthAc;
196         memmove(a.chal, tr.chal, CHALLEN);
197         genrandom(a.rand, NONCELEN);
198         rc += convA2M(&a, tick+rc, MAXAUTHENTLEN, &t);
199         if(auth_rpc(rpc, "write", tick, rc) != ARok){
200                 rerrstr(errbuf, sizeof(errbuf));
201                 if(strcmp(errbuf, "auth server protocol botch") == 0)
202                         print("BAD: factotum key doesn't seem to match %s (auth_rpc write ticket+authenticator: %r)\n", source);
203                 else
204                         print("BAD: auth_rpc write ticket+authenticator: %r\n");
205                 goto err;
206         }
207         
208         if(auth_rpc(rpc, "read", nil, 0) != ARok){ print("BAD: auth_rpc read authenticator: %r\n"); goto err; }
209         if(convM2A(rpc->arg, rpc->narg, &a, &t) <= 0) goto botch;
210         if(a.num != AuthAs || memcmp(a.chal, chal, CHALLEN) != 0) goto botch;
211         print("GOOD: key in factotum matches %s\n", source);
212         auth_freerpc(rpc);
213         close(fd);
214         return 0;
215 botch:
216         print("BAD: factotum: protocol botch\n");       
217 err:
218         auth_freerpc(rpc);
219         close(fd);
220         return -1;
221 }
222
223 void
224 factotum(void)
225 {
226         if(!havenvram || !checkkey()) return;
227         if(trykey(0) < 0 && havekeyfs && memcmp(keyfskey, nvr.aesmachkey, AESKEYLEN) != 0)
228                 trykey(1);
229 }
230
231 void
232 main()
233 {
234         quotefmtinstall();
235         geteve();
236         ndb();
237         nvram();
238         keyfs();
239         factotum();
240 }