xref: /plan9/sys/src/lib9p/auth.c (revision 22a127bbfe4dd304949cc596400de973c0138e31)
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