1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <thread.h>
6 #include <9p.h>
7
8 typedef struct Afid Afid;
9
10 struct Afid
11 {
12 AuthRpc *rpc;
13 char *uname;
14 char *aname;
15 int authok;
16 int afd;
17 };
18
19 static uvlong authgen = 1ULL<<63;
20
21 void
auth9p(Req * r)22 auth9p(Req *r)
23 {
24 char *spec;
25 Afid *afid;
26
27 afid = emalloc9p(sizeof(Afid));
28 afid->afd = open("/mnt/factotum/rpc", ORDWR);
29 if(afid->afd < 0)
30 goto error;
31
32 if((afid->rpc = auth_allocrpc(afid->afd)) == nil)
33 goto error;
34
35 if(r->ifcall.uname[0] == 0)
36 goto error;
37 afid->uname = estrdup9p(r->ifcall.uname);
38 afid->aname = estrdup9p(r->ifcall.aname);
39
40 spec = r->srv->keyspec;
41 if(spec == nil)
42 spec = "proto=p9any role=server";
43
44 if(auth_rpc(afid->rpc, "start", spec, strlen(spec)) != ARok)
45 goto error;
46
47 r->afid->qid.type = QTAUTH;
48 r->afid->qid.path = ++authgen;
49 r->afid->qid.vers = 0;
50 r->afid->omode = ORDWR;
51 r->ofcall.qid = r->afid->qid;
52 r->afid->aux = afid;
53 respond(r, nil);
54 return;
55
56 error:
57 if(afid->rpc)
58 auth_freerpc(afid->rpc);
59 if(afid->uname)
60 free(afid->uname);
61 if(afid->aname)
62 free(afid->aname);
63 if(afid->afd >= 0)
64 close(afid->afd);
65 free(afid);
66 responderror(r);
67 }
68
69 static int
_authread(Afid * afid,void * data,int count)70 _authread(Afid *afid, void *data, int count)
71 {
72 AuthInfo *ai;
73
74 switch(auth_rpc(afid->rpc, "read", nil, 0)){
75 case ARdone:
76 ai = auth_getinfo(afid->rpc);
77 if(ai == nil)
78 return -1;
79 auth_freeAI(ai);
80 if(chatty9p)
81 fprint(2, "authenticate %s/%s: ok\n", afid->uname, afid->aname);
82 afid->authok = 1;
83 return 0;
84
85 case ARok:
86 if(count < afid->rpc->narg){
87 werrstr("authread count too small");
88 return -1;
89 }
90 count = afid->rpc->narg;
91 memmove(data, afid->rpc->arg, count);
92 return count;
93
94 case ARphase:
95 default:
96 werrstr("authrpc botch");
97 return -1;
98 }
99 }
100
101 void
authread(Req * r)102 authread(Req *r)
103 {
104 int n;
105 Afid *afid;
106 Fid *fid;
107
108 fid = r->fid;
109 afid = fid->aux;
110 if(afid == nil || r->fid->qid.type != QTAUTH){
111 respond(r, "not an auth fid");
112 return;
113 }
114 n = _authread(afid, r->ofcall.data, r->ifcall.count);
115 if(n < 0){
116 responderror(r);
117 return;
118 }
119 r->ofcall.count = n;
120 respond(r, nil);
121 }
122
123 void
authwrite(Req * r)124 authwrite(Req *r)
125 {
126 Afid *afid;
127 Fid *fid;
128
129 fid = r->fid;
130 afid = fid->aux;
131 if(afid == nil || r->fid->qid.type != QTAUTH){
132 respond(r, "not an auth fid");
133 return;
134 }
135 if(auth_rpc(afid->rpc, "write", r->ifcall.data, r->ifcall.count) != ARok){
136 responderror(r);
137 return;
138 }
139 r->ofcall.count = r->ifcall.count;
140 respond(r, nil);
141 }
142
143 void
authdestroy(Fid * fid)144 authdestroy(Fid *fid)
145 {
146 Afid *afid;
147
148 if((fid->qid.type & QTAUTH) && (afid = fid->aux) != nil){
149 if(afid->rpc)
150 auth_freerpc(afid->rpc);
151 close(afid->afd);
152 free(afid->uname);
153 free(afid->aname);
154 free(afid);
155 fid->aux = nil;
156 }
157 }
158
159 int
authattach(Req * r)160 authattach(Req *r)
161 {
162 Afid *afid;
163 char buf[ERRMAX];
164
165 if(r->afid == nil){
166 respond(r, "not authenticated");
167 return -1;
168 }
169
170 afid = r->afid->aux;
171 if((r->afid->qid.type&QTAUTH) == 0 || afid == nil){
172 respond(r, "not an auth fid");
173 return -1;
174 }
175
176 if(!afid->authok){
177 if(_authread(afid, buf, 0) < 0){
178 responderror(r);
179 return -1;
180 }
181 }
182
183 if(strcmp(afid->uname, r->ifcall.uname) != 0){
184 snprint(buf, sizeof buf, "auth uname mismatch: %s vs %s",
185 afid->uname, r->ifcall.uname);
186 respond(r, buf);
187 return -1;
188 }
189
190 if(strcmp(afid->aname, r->ifcall.aname) != 0){
191 snprint(buf, sizeof buf, "auth aname mismatch: %s vs %s",
192 afid->aname, r->ifcall.aname);
193 respond(r, buf);
194 return -1;
195 }
196 return 0;
197 }
198
199