xref: /plan9/sys/src/cmd/unix/drawterm/libauth/auth_proxy.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
18ccd4a63SDavid du Colombier #include <u.h>
28ccd4a63SDavid du Colombier #include <libc.h>
38ccd4a63SDavid du Colombier #include <fcall.h>
48ccd4a63SDavid du Colombier #include <auth.h>
58ccd4a63SDavid du Colombier #include "authlocal.h"
68ccd4a63SDavid du Colombier 
78ccd4a63SDavid du Colombier enum {
88ccd4a63SDavid du Colombier 	ARgiveup = 100,
98ccd4a63SDavid du Colombier };
108ccd4a63SDavid du Colombier 
118ccd4a63SDavid du Colombier static uchar*
gstring(uchar * p,uchar * ep,char ** s)128ccd4a63SDavid du Colombier gstring(uchar *p, uchar *ep, char **s)
138ccd4a63SDavid du Colombier {
148ccd4a63SDavid du Colombier 	uint n;
158ccd4a63SDavid du Colombier 
168ccd4a63SDavid du Colombier 	if(p == nil)
178ccd4a63SDavid du Colombier 		return nil;
188ccd4a63SDavid du Colombier 	if(p+BIT16SZ > ep)
198ccd4a63SDavid du Colombier 		return nil;
208ccd4a63SDavid du Colombier 	n = GBIT16(p);
218ccd4a63SDavid du Colombier 	p += BIT16SZ;
228ccd4a63SDavid du Colombier 	if(p+n > ep)
238ccd4a63SDavid du Colombier 		return nil;
248ccd4a63SDavid du Colombier 	*s = malloc(n+1);
258ccd4a63SDavid du Colombier 	memmove((*s), p, n);
268ccd4a63SDavid du Colombier 	(*s)[n] = '\0';
278ccd4a63SDavid du Colombier 	p += n;
288ccd4a63SDavid du Colombier 	return p;
298ccd4a63SDavid du Colombier }
308ccd4a63SDavid du Colombier 
318ccd4a63SDavid du Colombier static uchar*
gcarray(uchar * p,uchar * ep,uchar ** s,int * np)328ccd4a63SDavid du Colombier gcarray(uchar *p, uchar *ep, uchar **s, int *np)
338ccd4a63SDavid du Colombier {
348ccd4a63SDavid du Colombier 	uint n;
358ccd4a63SDavid du Colombier 
368ccd4a63SDavid du Colombier 	if(p == nil)
378ccd4a63SDavid du Colombier 		return nil;
388ccd4a63SDavid du Colombier 	if(p+BIT16SZ > ep)
398ccd4a63SDavid du Colombier 		return nil;
408ccd4a63SDavid du Colombier 	n = GBIT16(p);
418ccd4a63SDavid du Colombier 	p += BIT16SZ;
428ccd4a63SDavid du Colombier 	if(p+n > ep)
438ccd4a63SDavid du Colombier 		return nil;
448ccd4a63SDavid du Colombier 	*s = malloc(n);
458ccd4a63SDavid du Colombier 	if(*s == nil)
468ccd4a63SDavid du Colombier 		return nil;
478ccd4a63SDavid du Colombier 	memmove((*s), p, n);
488ccd4a63SDavid du Colombier 	*np = n;
498ccd4a63SDavid du Colombier 	p += n;
508ccd4a63SDavid du Colombier 	return p;
518ccd4a63SDavid du Colombier }
528ccd4a63SDavid du Colombier 
538ccd4a63SDavid du Colombier void
auth_freeAI(AuthInfo * ai)548ccd4a63SDavid du Colombier auth_freeAI(AuthInfo *ai)
558ccd4a63SDavid du Colombier {
568ccd4a63SDavid du Colombier 	if(ai == nil)
578ccd4a63SDavid du Colombier 		return;
588ccd4a63SDavid du Colombier 	free(ai->cuid);
598ccd4a63SDavid du Colombier 	free(ai->suid);
608ccd4a63SDavid du Colombier 	free(ai->cap);
618ccd4a63SDavid du Colombier 	free(ai->secret);
628ccd4a63SDavid du Colombier 	free(ai);
638ccd4a63SDavid du Colombier }
648ccd4a63SDavid du Colombier 
658ccd4a63SDavid du Colombier static uchar*
convM2AI(uchar * p,int n,AuthInfo ** aip)668ccd4a63SDavid du Colombier convM2AI(uchar *p, int n, AuthInfo **aip)
678ccd4a63SDavid du Colombier {
688ccd4a63SDavid du Colombier 	uchar *e = p+n;
698ccd4a63SDavid du Colombier 	AuthInfo *ai;
708ccd4a63SDavid du Colombier 
718ccd4a63SDavid du Colombier 	ai = mallocz(sizeof(*ai), 1);
728ccd4a63SDavid du Colombier 	if(ai == nil)
738ccd4a63SDavid du Colombier 		return nil;
748ccd4a63SDavid du Colombier 
758ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->cuid);
768ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->suid);
778ccd4a63SDavid du Colombier 	p = gstring(p, e, &ai->cap);
788ccd4a63SDavid du Colombier 	p = gcarray(p, e, &ai->secret, &ai->nsecret);
798ccd4a63SDavid du Colombier 	if(p == nil)
808ccd4a63SDavid du Colombier 		auth_freeAI(ai);
818ccd4a63SDavid du Colombier 	else
828ccd4a63SDavid du Colombier 		*aip = ai;
838ccd4a63SDavid du Colombier 	return p;
848ccd4a63SDavid du Colombier }
858ccd4a63SDavid du Colombier 
868ccd4a63SDavid du Colombier AuthInfo*
auth_getinfo(AuthRpc * rpc)878ccd4a63SDavid du Colombier auth_getinfo(AuthRpc *rpc)
888ccd4a63SDavid du Colombier {
898ccd4a63SDavid du Colombier 	AuthInfo *a;
908ccd4a63SDavid du Colombier 
918ccd4a63SDavid du Colombier 	if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
928ccd4a63SDavid du Colombier 		return nil;
93*ec59a3ddSDavid du Colombier 	a = nil;
948ccd4a63SDavid du Colombier 	if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
958ccd4a63SDavid du Colombier 		werrstr("bad auth info from factotum");
968ccd4a63SDavid du Colombier 		return nil;
978ccd4a63SDavid du Colombier 	}
988ccd4a63SDavid du Colombier 	return a;
998ccd4a63SDavid du Colombier }
1008ccd4a63SDavid du Colombier 
1018ccd4a63SDavid du Colombier static int
dorpc(AuthRpc * rpc,char * verb,char * val,int len,AuthGetkey * getkey)1028ccd4a63SDavid du Colombier dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
1038ccd4a63SDavid du Colombier {
1048ccd4a63SDavid du Colombier 	int ret;
1058ccd4a63SDavid du Colombier 
1068ccd4a63SDavid du Colombier 	for(;;){
1078ccd4a63SDavid du Colombier 		if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
1088ccd4a63SDavid du Colombier 			return ret;
109*ec59a3ddSDavid du Colombier 		if(getkey == 0)
1108ccd4a63SDavid du Colombier 			return ARgiveup;	/* don't know how */
1118ccd4a63SDavid du Colombier 		if((*getkey)(rpc->arg) < 0)
1128ccd4a63SDavid du Colombier 			return ARgiveup;	/* user punted */
1138ccd4a63SDavid du Colombier 	}
1148ccd4a63SDavid du Colombier }
1158ccd4a63SDavid du Colombier 
1168ccd4a63SDavid du Colombier /*
1178ccd4a63SDavid du Colombier  *  this just proxies what the factotum tells it to.
1188ccd4a63SDavid du Colombier  */
1198ccd4a63SDavid du Colombier AuthInfo*
fauth_proxy(int fd,AuthRpc * rpc,AuthGetkey * getkey,char * params)1208ccd4a63SDavid du Colombier fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params)
1218ccd4a63SDavid du Colombier {
1228ccd4a63SDavid du Colombier 	char *buf;
1238ccd4a63SDavid du Colombier 	int m, n, ret;
1248ccd4a63SDavid du Colombier 	AuthInfo *a;
1258ccd4a63SDavid du Colombier 	char oerr[ERRMAX];
1268ccd4a63SDavid du Colombier 
1278ccd4a63SDavid du Colombier 	rerrstr(oerr, sizeof oerr);
1288ccd4a63SDavid du Colombier 	werrstr("UNKNOWN AUTH ERROR");
1298ccd4a63SDavid du Colombier 
1308ccd4a63SDavid du Colombier 	if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
1318ccd4a63SDavid du Colombier 		werrstr("fauth_proxy start: %r");
1328ccd4a63SDavid du Colombier 		return nil;
1338ccd4a63SDavid du Colombier 	}
1348ccd4a63SDavid du Colombier 
1358ccd4a63SDavid du Colombier 	buf = malloc(AuthRpcMax);
1368ccd4a63SDavid du Colombier 	if(buf == nil)
1378ccd4a63SDavid du Colombier 		return nil;
1388ccd4a63SDavid du Colombier 	for(;;){
1398ccd4a63SDavid du Colombier 		switch(dorpc(rpc, "read", nil, 0, getkey)){
1408ccd4a63SDavid du Colombier 		case ARdone:
1418ccd4a63SDavid du Colombier 			free(buf);
1428ccd4a63SDavid du Colombier 			a = auth_getinfo(rpc);
1438ccd4a63SDavid du Colombier 			errstr(oerr, sizeof oerr);	/* no error, restore whatever was there */
1448ccd4a63SDavid du Colombier 			return a;
1458ccd4a63SDavid du Colombier 		case ARok:
1468ccd4a63SDavid du Colombier 			if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
1478ccd4a63SDavid du Colombier 				werrstr("auth_proxy write fd: %r");
1488ccd4a63SDavid du Colombier 				goto Error;
1498ccd4a63SDavid du Colombier 			}
1508ccd4a63SDavid du Colombier 			break;
1518ccd4a63SDavid du Colombier 		case ARphase:
1528ccd4a63SDavid du Colombier 			n = 0;
1538ccd4a63SDavid du Colombier 			memset(buf, 0, AuthRpcMax);
1548ccd4a63SDavid du Colombier 			while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
1558ccd4a63SDavid du Colombier 				if(atoi(rpc->arg) > AuthRpcMax)
1568ccd4a63SDavid du Colombier 					break;
1578ccd4a63SDavid du Colombier 				m = read(fd, buf+n, atoi(rpc->arg)-n);
1588ccd4a63SDavid du Colombier 				if(m <= 0){
1598ccd4a63SDavid du Colombier 					if(m == 0)
1608ccd4a63SDavid du Colombier 						werrstr("auth_proxy short read: %s", buf);
1618ccd4a63SDavid du Colombier 					goto Error;
1628ccd4a63SDavid du Colombier 				}
1638ccd4a63SDavid du Colombier 				n += m;
1648ccd4a63SDavid du Colombier 			}
1658ccd4a63SDavid du Colombier 			if(ret != ARok){
1668ccd4a63SDavid du Colombier 				werrstr("auth_proxy rpc write: %s: %r", buf);
1678ccd4a63SDavid du Colombier 				goto Error;
1688ccd4a63SDavid du Colombier 			}
1698ccd4a63SDavid du Colombier 			break;
1708ccd4a63SDavid du Colombier 		default:
1718ccd4a63SDavid du Colombier 			werrstr("auth_proxy rpc: %r");
1728ccd4a63SDavid du Colombier 			goto Error;
1738ccd4a63SDavid du Colombier 		}
1748ccd4a63SDavid du Colombier 	}
1758ccd4a63SDavid du Colombier Error:
1768ccd4a63SDavid du Colombier 	free(buf);
1778ccd4a63SDavid du Colombier 	return nil;
1788ccd4a63SDavid du Colombier }
1798ccd4a63SDavid du Colombier 
1808ccd4a63SDavid du Colombier AuthInfo*
auth_proxy(int fd,AuthGetkey * getkey,char * fmt,...)1818ccd4a63SDavid du Colombier auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...)
1828ccd4a63SDavid du Colombier {
1838ccd4a63SDavid du Colombier 	int afd;
1848ccd4a63SDavid du Colombier 	char *p;
1858ccd4a63SDavid du Colombier 	va_list arg;
1868ccd4a63SDavid du Colombier 	AuthInfo *ai;
1878ccd4a63SDavid du Colombier 	AuthRpc *rpc;
1888ccd4a63SDavid du Colombier 
1898ccd4a63SDavid du Colombier 	quotefmtinstall();	/* just in case */
1908ccd4a63SDavid du Colombier 	va_start(arg, fmt);
1918ccd4a63SDavid du Colombier 	p = vsmprint(fmt, arg);
1928ccd4a63SDavid du Colombier 	va_end(arg);
1938ccd4a63SDavid du Colombier 
1948ccd4a63SDavid du Colombier 	afd = open("/mnt/factotum/rpc", ORDWR);
1958ccd4a63SDavid du Colombier 	if(afd < 0){
1968ccd4a63SDavid du Colombier 		werrstr("opening /mnt/factotum/rpc: %r");
1978ccd4a63SDavid du Colombier 		free(p);
1988ccd4a63SDavid du Colombier 		return nil;
1998ccd4a63SDavid du Colombier 	}
2008ccd4a63SDavid du Colombier 
2018ccd4a63SDavid du Colombier 	rpc = auth_allocrpc(afd);
2028ccd4a63SDavid du Colombier 	if(rpc == nil){
2038ccd4a63SDavid du Colombier 		free(p);
2048ccd4a63SDavid du Colombier 		return nil;
2058ccd4a63SDavid du Colombier 	}
2068ccd4a63SDavid du Colombier 
2078ccd4a63SDavid du Colombier 	ai = fauth_proxy(fd, rpc, getkey, p);
2088ccd4a63SDavid du Colombier 	free(p);
2098ccd4a63SDavid du Colombier 	auth_freerpc(rpc);
2108ccd4a63SDavid du Colombier 	close(afd);
2118ccd4a63SDavid du Colombier 	return ai;
2128ccd4a63SDavid du Colombier }
2138ccd4a63SDavid du Colombier 
214