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