xref: /plan9-contrib/sys/src/cmd/unix/drawterm/libauth/auth_proxy.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include <u.h>
2*8ccd4a63SDavid du Colombier #include <libc.h>
3*8ccd4a63SDavid du Colombier #include <fcall.h>
4*8ccd4a63SDavid du Colombier #include <auth.h>
5*8ccd4a63SDavid du Colombier #include "authlocal.h"
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier enum {
8*8ccd4a63SDavid du Colombier 	ARgiveup = 100,
9*8ccd4a63SDavid du Colombier };
10*8ccd4a63SDavid du Colombier 
11*8ccd4a63SDavid du Colombier static uchar*
12*8ccd4a63SDavid du Colombier gstring(uchar *p, uchar *ep, char **s)
13*8ccd4a63SDavid du Colombier {
14*8ccd4a63SDavid du Colombier 	uint n;
15*8ccd4a63SDavid du Colombier 
16*8ccd4a63SDavid du Colombier 	if(p == nil)
17*8ccd4a63SDavid du Colombier 		return nil;
18*8ccd4a63SDavid du Colombier 	if(p+BIT16SZ > ep)
19*8ccd4a63SDavid du Colombier 		return nil;
20*8ccd4a63SDavid du Colombier 	n = GBIT16(p);
21*8ccd4a63SDavid du Colombier 	p += BIT16SZ;
22*8ccd4a63SDavid du Colombier 	if(p+n > ep)
23*8ccd4a63SDavid du Colombier 		return nil;
24*8ccd4a63SDavid du Colombier 	*s = malloc(n+1);
25*8ccd4a63SDavid du Colombier 	memmove((*s), p, n);
26*8ccd4a63SDavid du Colombier 	(*s)[n] = '\0';
27*8ccd4a63SDavid du Colombier 	p += n;
28*8ccd4a63SDavid du Colombier 	return p;
29*8ccd4a63SDavid du Colombier }
30*8ccd4a63SDavid du Colombier 
31*8ccd4a63SDavid du Colombier static uchar*
32*8ccd4a63SDavid du Colombier gcarray(uchar *p, uchar *ep, uchar **s, int *np)
33*8ccd4a63SDavid du Colombier {
34*8ccd4a63SDavid du Colombier 	uint n;
35*8ccd4a63SDavid du Colombier 
36*8ccd4a63SDavid du Colombier 	if(p == nil)
37*8ccd4a63SDavid du Colombier 		return nil;
38*8ccd4a63SDavid du Colombier 	if(p+BIT16SZ > ep)
39*8ccd4a63SDavid du Colombier 		return nil;
40*8ccd4a63SDavid du Colombier 	n = GBIT16(p);
41*8ccd4a63SDavid du Colombier 	p += BIT16SZ;
42*8ccd4a63SDavid du Colombier 	if(p+n > ep)
43*8ccd4a63SDavid du Colombier 		return nil;
44*8ccd4a63SDavid du Colombier 	*s = malloc(n);
45*8ccd4a63SDavid du Colombier 	if(*s == nil)
46*8ccd4a63SDavid du Colombier 		return nil;
47*8ccd4a63SDavid du Colombier 	memmove((*s), p, n);
48*8ccd4a63SDavid du Colombier 	*np = n;
49*8ccd4a63SDavid du Colombier 	p += n;
50*8ccd4a63SDavid du Colombier 	return p;
51*8ccd4a63SDavid du Colombier }
52*8ccd4a63SDavid du Colombier 
53*8ccd4a63SDavid du Colombier void
54*8ccd4a63SDavid du Colombier auth_freeAI(AuthInfo *ai)
55*8ccd4a63SDavid du Colombier {
56*8ccd4a63SDavid du Colombier 	if(ai == nil)
57*8ccd4a63SDavid du Colombier 		return;
58*8ccd4a63SDavid du Colombier 	free(ai->cuid);
59*8ccd4a63SDavid du Colombier 	free(ai->suid);
60*8ccd4a63SDavid du Colombier 	free(ai->cap);
61*8ccd4a63SDavid du Colombier 	free(ai->secret);
62*8ccd4a63SDavid du Colombier 	free(ai);
63*8ccd4a63SDavid du Colombier }
64*8ccd4a63SDavid du Colombier 
65*8ccd4a63SDavid du Colombier static uchar*
66*8ccd4a63SDavid du Colombier convM2AI(uchar *p, int n, AuthInfo **aip)
67*8ccd4a63SDavid du Colombier {
68*8ccd4a63SDavid du Colombier 	uchar *e = p+n;
69*8ccd4a63SDavid du Colombier 	AuthInfo *ai;
70*8ccd4a63SDavid du Colombier 
71*8ccd4a63SDavid du Colombier 	ai = mallocz(sizeof(*ai), 1);
72*8ccd4a63SDavid du Colombier 	if(ai == nil)
73*8ccd4a63SDavid du Colombier 		return nil;
74*8ccd4a63SDavid du Colombier 
75*8ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->cuid);
76*8ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->suid);
77*8ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->cap);
78*8ccd4a63SDavid du Colombier 	p = gcarray(p, e, &ai->secret, &ai->nsecret);
79*8ccd4a63SDavid du Colombier 	if(p == nil)
80*8ccd4a63SDavid du Colombier 		auth_freeAI(ai);
81*8ccd4a63SDavid du Colombier 	else
82*8ccd4a63SDavid du Colombier 		*aip = ai;
83*8ccd4a63SDavid du Colombier 	return p;
84*8ccd4a63SDavid du Colombier }
85*8ccd4a63SDavid du Colombier 
86*8ccd4a63SDavid du Colombier AuthInfo*
87*8ccd4a63SDavid du Colombier auth_getinfo(AuthRpc *rpc)
88*8ccd4a63SDavid du Colombier {
89*8ccd4a63SDavid du Colombier 	AuthInfo *a;
90*8ccd4a63SDavid du Colombier 
91*8ccd4a63SDavid du Colombier 	if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
92*8ccd4a63SDavid du Colombier 		return nil;
93*8ccd4a63SDavid du Colombier 	if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
94*8ccd4a63SDavid du Colombier 		werrstr("bad auth info from factotum");
95*8ccd4a63SDavid du Colombier 		return nil;
96*8ccd4a63SDavid du Colombier 	}
97*8ccd4a63SDavid du Colombier 	return a;
98*8ccd4a63SDavid du Colombier }
99*8ccd4a63SDavid du Colombier 
100*8ccd4a63SDavid du Colombier static int
101*8ccd4a63SDavid du Colombier dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
102*8ccd4a63SDavid du Colombier {
103*8ccd4a63SDavid du Colombier 	int ret;
104*8ccd4a63SDavid du Colombier 
105*8ccd4a63SDavid du Colombier 	for(;;){
106*8ccd4a63SDavid du Colombier 		if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
107*8ccd4a63SDavid du Colombier 			return ret;
108*8ccd4a63SDavid du Colombier 		if(getkey == nil)
109*8ccd4a63SDavid du Colombier 			return ARgiveup;	/* don't know how */
110*8ccd4a63SDavid du Colombier 		if((*getkey)(rpc->arg) < 0)
111*8ccd4a63SDavid du Colombier 			return ARgiveup;	/* user punted */
112*8ccd4a63SDavid du Colombier 	}
113*8ccd4a63SDavid du Colombier }
114*8ccd4a63SDavid du Colombier 
115*8ccd4a63SDavid du Colombier /*
116*8ccd4a63SDavid du Colombier  *  this just proxies what the factotum tells it to.
117*8ccd4a63SDavid du Colombier  */
118*8ccd4a63SDavid du Colombier AuthInfo*
119*8ccd4a63SDavid du Colombier fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params)
120*8ccd4a63SDavid du Colombier {
121*8ccd4a63SDavid du Colombier 	char *buf;
122*8ccd4a63SDavid du Colombier 	int m, n, ret;
123*8ccd4a63SDavid du Colombier 	AuthInfo *a;
124*8ccd4a63SDavid du Colombier 	char oerr[ERRMAX];
125*8ccd4a63SDavid du Colombier 
126*8ccd4a63SDavid du Colombier 	rerrstr(oerr, sizeof oerr);
127*8ccd4a63SDavid du Colombier 	werrstr("UNKNOWN AUTH ERROR");
128*8ccd4a63SDavid du Colombier 
129*8ccd4a63SDavid du Colombier 	if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
130*8ccd4a63SDavid du Colombier 		werrstr("fauth_proxy start: %r");
131*8ccd4a63SDavid du Colombier 		return nil;
132*8ccd4a63SDavid du Colombier 	}
133*8ccd4a63SDavid du Colombier 
134*8ccd4a63SDavid du Colombier 	buf = malloc(AuthRpcMax);
135*8ccd4a63SDavid du Colombier 	if(buf == nil)
136*8ccd4a63SDavid du Colombier 		return nil;
137*8ccd4a63SDavid du Colombier 	for(;;){
138*8ccd4a63SDavid du Colombier 		switch(dorpc(rpc, "read", nil, 0, getkey)){
139*8ccd4a63SDavid du Colombier 		case ARdone:
140*8ccd4a63SDavid du Colombier 			free(buf);
141*8ccd4a63SDavid du Colombier 			a = auth_getinfo(rpc);
142*8ccd4a63SDavid du Colombier 			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */
143*8ccd4a63SDavid du Colombier 			return a;
144*8ccd4a63SDavid du Colombier 		case ARok:
145*8ccd4a63SDavid du Colombier 			if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
146*8ccd4a63SDavid du Colombier 				werrstr("auth_proxy write fd: %r");
147*8ccd4a63SDavid du Colombier 				goto Error;
148*8ccd4a63SDavid du Colombier 			}
149*8ccd4a63SDavid du Colombier 			break;
150*8ccd4a63SDavid du Colombier 		case ARphase:
151*8ccd4a63SDavid du Colombier 			n = 0;
152*8ccd4a63SDavid du Colombier 			memset(buf, 0, AuthRpcMax);
153*8ccd4a63SDavid du Colombier 			while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
154*8ccd4a63SDavid du Colombier 				if(atoi(rpc->arg) > AuthRpcMax)
155*8ccd4a63SDavid du Colombier 					break;
156*8ccd4a63SDavid du Colombier 				m = read(fd, buf+n, atoi(rpc->arg)-n);
157*8ccd4a63SDavid du Colombier 				if(m <= 0){
158*8ccd4a63SDavid du Colombier 					if(m == 0)
159*8ccd4a63SDavid du Colombier 						werrstr("auth_proxy short read: %s", buf);
160*8ccd4a63SDavid du Colombier 					goto Error;
161*8ccd4a63SDavid du Colombier 				}
162*8ccd4a63SDavid du Colombier 				n += m;
163*8ccd4a63SDavid du Colombier 			}
164*8ccd4a63SDavid du Colombier 			if(ret != ARok){
165*8ccd4a63SDavid du Colombier 				werrstr("auth_proxy rpc write: %s: %r", buf);
166*8ccd4a63SDavid du Colombier 				goto Error;
167*8ccd4a63SDavid du Colombier 			}
168*8ccd4a63SDavid du Colombier 			break;
169*8ccd4a63SDavid du Colombier 		default:
170*8ccd4a63SDavid du Colombier 			werrstr("auth_proxy rpc: %r");
171*8ccd4a63SDavid du Colombier 			goto Error;
172*8ccd4a63SDavid du Colombier 		}
173*8ccd4a63SDavid du Colombier 	}
174*8ccd4a63SDavid du Colombier Error:
175*8ccd4a63SDavid du Colombier 	free(buf);
176*8ccd4a63SDavid du Colombier 	return nil;
177*8ccd4a63SDavid du Colombier }
178*8ccd4a63SDavid du Colombier 
179*8ccd4a63SDavid du Colombier AuthInfo*
180*8ccd4a63SDavid du Colombier auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...)
181*8ccd4a63SDavid du Colombier {
182*8ccd4a63SDavid du Colombier 	int afd;
183*8ccd4a63SDavid du Colombier 	char *p;
184*8ccd4a63SDavid du Colombier 	va_list arg;
185*8ccd4a63SDavid du Colombier 	AuthInfo *ai;
186*8ccd4a63SDavid du Colombier 	AuthRpc *rpc;
187*8ccd4a63SDavid du Colombier 
188*8ccd4a63SDavid du Colombier 	quotefmtinstall();	/* just in case */
189*8ccd4a63SDavid du Colombier 	va_start(arg, fmt);
190*8ccd4a63SDavid du Colombier 	p = vsmprint(fmt, arg);
191*8ccd4a63SDavid du Colombier 	va_end(arg);
192*8ccd4a63SDavid du Colombier 
193*8ccd4a63SDavid du Colombier 	afd = open("/mnt/factotum/rpc", ORDWR);
194*8ccd4a63SDavid du Colombier 	if(afd < 0){
195*8ccd4a63SDavid du Colombier 		werrstr("opening /mnt/factotum/rpc: %r");
196*8ccd4a63SDavid du Colombier 		free(p);
197*8ccd4a63SDavid du Colombier 		return nil;
198*8ccd4a63SDavid du Colombier 	}
199*8ccd4a63SDavid du Colombier 
200*8ccd4a63SDavid du Colombier 	rpc = auth_allocrpc(afd);
201*8ccd4a63SDavid du Colombier 	if(rpc == nil){
202*8ccd4a63SDavid du Colombier 		free(p);
203*8ccd4a63SDavid du Colombier 		return nil;
204*8ccd4a63SDavid du Colombier 	}
205*8ccd4a63SDavid du Colombier 
206*8ccd4a63SDavid du Colombier 	ai = fauth_proxy(fd, rpc, getkey, p);
207*8ccd4a63SDavid du Colombier 	free(p);
208*8ccd4a63SDavid du Colombier 	auth_freerpc(rpc);
209*8ccd4a63SDavid du Colombier 	close(afd);
210*8ccd4a63SDavid du Colombier 	return ai;
211*8ccd4a63SDavid du Colombier }
212*8ccd4a63SDavid du Colombier 
213