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