xref: /plan9/sys/src/cmd/9nfs/authhostowner.c (revision b985bfb93fd5edd3aa9271759b21e6c0fbf43d68)
1 #include "all.h"
2 
3 enum {
4 	ARgiveup = 100,
5 };
6 
7 static uchar*
gstring(uchar * p,uchar * ep,char ** s)8 gstring(uchar *p, uchar *ep, char **s)
9 {
10 	uint n;
11 
12 	if(p == nil)
13 		return nil;
14 	if(p+BIT16SZ > ep)
15 		return nil;
16 	n = GBIT16(p);
17 	p += BIT16SZ;
18 	if(p+n > ep)
19 		return nil;
20 	*s = malloc(n+1);
21 	memmove((*s), p, n);
22 	(*s)[n] = '\0';
23 	p += n;
24 	return p;
25 }
26 
27 static uchar*
gcarray(uchar * p,uchar * ep,uchar ** s,int * np)28 gcarray(uchar *p, uchar *ep, uchar **s, int *np)
29 {
30 	uint n;
31 
32 	if(p == nil)
33 		return nil;
34 	if(p+BIT16SZ > ep)
35 		return nil;
36 	n = GBIT16(p);
37 	p += BIT16SZ;
38 	if(p+n > ep)
39 		return nil;
40 	*s = malloc(n);
41 	if(*s == nil)
42 		return nil;
43 	memmove((*s), p, n);
44 	*np = n;
45 	p += n;
46 	return p;
47 }
48 
49 static uchar*
convM2AI(uchar * p,int n,AuthInfo ** aip)50 convM2AI(uchar *p, int n, AuthInfo **aip)
51 {
52 	uchar *e = p+n;
53 	AuthInfo *ai;
54 
55 	ai = mallocz(sizeof(*ai), 1);
56 	if(ai == nil)
57 		return nil;
58 
59 	p = gstring(p, e, &ai->cuid);
60 	p = gstring(p, e, &ai->suid);
61 	p = gstring(p, e, &ai->cap);
62 	p = gcarray(p, e, &ai->secret, &ai->nsecret);
63 	if(p == nil)
64 		auth_freeAI(ai);
65 	else
66 		*aip = ai;
67 	return p;
68 }
69 
70 static int
dorpc(AuthRpc * rpc,char * verb,char * val,int len,AuthGetkey * getkey)71 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
72 {
73 	int ret;
74 
75 	for(;;){
76 		if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
77 			return ret;
78 		if(getkey == nil)
79 			return ARgiveup;	/* don't know how */
80 		if((*getkey)(rpc->arg) < 0)
81 			return ARgiveup;	/* user punted */
82 	}
83 }
84 
85 static int
doread(Session * s,Fid * f,void * buf,int n)86 doread(Session *s, Fid *f, void *buf, int n)
87 {
88 	s->f.fid = f - s->fids;
89 	s->f.offset = 0;
90 	s->f.count = n;
91 	if(xmesg(s, Tread) < 0)
92 		return -1;
93 	n = s->f.count;
94 	memmove(buf, s->f.data, n);
95 	return n;
96 }
97 
98 static int
dowrite(Session * s,Fid * f,void * buf,int n)99 dowrite(Session *s, Fid *f, void *buf, int n)
100 {
101 	s->f.fid = f - s->fids;
102 	s->f.offset = 0;
103 	s->f.count = n;
104 	s->f.data = (char *)buf;
105 	if(xmesg(s, Twrite) < 0)
106 		return -1;
107 	return n;
108 }
109 
110 /*
111  *  this just proxies what the factotum tells it to.
112  */
113 AuthInfo*
authproto(Session * s,Fid * f,AuthRpc * rpc,AuthGetkey * getkey,char * params)114 authproto(Session *s, Fid *f, AuthRpc *rpc, AuthGetkey *getkey, char *params)
115 {
116 	char *buf;
117 	int m, n, ret;
118 	AuthInfo *a;
119 	char oerr[ERRMAX];
120 
121 	rerrstr(oerr, sizeof oerr);
122 	werrstr("UNKNOWN AUTH ERROR");
123 
124 	if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
125 		werrstr("fauth_proxy start: %r");
126 		return nil;
127 	}
128 
129 	buf = malloc(AuthRpcMax);
130 	if(buf == nil)
131 		return nil;
132 	for(;;){
133 		switch(dorpc(rpc, "read", nil, 0, getkey)){
134 		case ARdone:
135 			free(buf);
136 			a = auth_getinfo(rpc);
137 			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */
138 			return a;
139 		case ARok:
140 			if(dowrite(s, f, rpc->arg, rpc->narg) != rpc->narg){
141 				werrstr("auth_proxy write fd: %r");
142 				goto Error;
143 			}
144 			break;
145 		case ARphase:
146 			n = 0;
147 			memset(buf, 0, AuthRpcMax);
148 			while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
149 				if(atoi(rpc->arg) > AuthRpcMax)
150 					break;
151 				m = doread(s, f, buf+n, atoi(rpc->arg)-n);
152 				if(m <= 0){
153 					if(m == 0)
154 						werrstr("auth_proxy short read: %s", buf);
155 					goto Error;
156 				}
157 				n += m;
158 			}
159 			if(ret != ARok){
160 				werrstr("auth_proxy rpc write: %s: %r", buf);
161 				goto Error;
162 			}
163 			break;
164 		default:
165 			werrstr("auth_proxy rpc: %r");
166 			goto Error;
167 		}
168 	}
169 Error:
170 	free(buf);
171 	return nil;
172 }
173 
174 /* returns 0 if auth succeeded (or unneeded), -1 otherwise */
175 int
authhostowner(Session * s)176 authhostowner(Session *s)
177 {
178 	Fid *af, *f;
179 	int rv = -1;
180 	int afd;
181 	AuthInfo *ai;
182 	AuthRpc *rpc;
183 
184 	/* get a fid to authenticate over */
185 	f = nil;
186 	af = newfid(s);
187 	s->f.afid = af - s->fids;
188 	s->f.uname = getuser();
189 	s->f.aname = s->spec;
190 	if(xmesg(s, Tauth)){
191 		/* not needed */
192 		rv = 0;
193 		goto out;
194 	}
195 
196 	quotefmtinstall();	/* just in case */
197 
198 	afd = open("/mnt/factotum/rpc", ORDWR);
199 	if(afd < 0){
200 		werrstr("opening /mnt/factotum/rpc: %r");
201 		goto out;
202 	}
203 
204 	rpc = auth_allocrpc(afd);
205 	if(rpc == nil)
206 		goto out;
207 
208 	ai = authproto(s, af, rpc, auth_getkey, "proto=p9any role=client");
209 	if(ai != nil){
210 		rv = 0;
211 		auth_freeAI(ai);
212 	}
213 	auth_freerpc(rpc);
214 	close(afd);
215 
216 	/* try attaching with the afid */
217 	chat("attaching as hostowner...");
218 	f = newfid(s);
219 	s->f.fid = f - s->fids;
220 	s->f.afid = af - s->fids;;
221 	s->f.uname = getuser();
222 	s->f.aname = s->spec;
223 	if(xmesg(s, Tattach) == 0)
224 		rv = 0;
225 out:
226 	if(af != nil){
227 		putfid(s, af);
228 		s->f.fid = af - s->fids;
229 		xmesg(s, Tclunk);
230 	}
231 	if(f != nil){
232 		putfid(s, f);
233 		s->f.fid = f - s->fids;
234 		xmesg(s, Tclunk);
235 	}
236 
237 	return rv;
238 }
239 
240