19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <fcall.h>
49a747e4fSDavid du Colombier #include <auth.h>
59a747e4fSDavid du Colombier #include "authlocal.h"
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier enum {
89a747e4fSDavid du Colombier ARgiveup = 100,
99a747e4fSDavid du Colombier };
109a747e4fSDavid du Colombier
119a747e4fSDavid du Colombier static uchar*
gstring(uchar * p,uchar * ep,char ** s)129a747e4fSDavid du Colombier gstring(uchar *p, uchar *ep, char **s)
139a747e4fSDavid du Colombier {
149a747e4fSDavid du Colombier uint n;
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier if(p == nil)
179a747e4fSDavid du Colombier return nil;
189a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
199a747e4fSDavid du Colombier return nil;
209a747e4fSDavid du Colombier n = GBIT16(p);
219a747e4fSDavid du Colombier p += BIT16SZ;
229a747e4fSDavid du Colombier if(p+n > ep)
239a747e4fSDavid du Colombier return nil;
249a747e4fSDavid du Colombier *s = malloc(n+1);
259a747e4fSDavid du Colombier memmove((*s), p, n);
269a747e4fSDavid du Colombier (*s)[n] = '\0';
279a747e4fSDavid du Colombier p += n;
289a747e4fSDavid du Colombier return p;
299a747e4fSDavid du Colombier }
309a747e4fSDavid du Colombier
319a747e4fSDavid du Colombier static uchar*
gcarray(uchar * p,uchar * ep,uchar ** s,int * np)329a747e4fSDavid du Colombier gcarray(uchar *p, uchar *ep, uchar **s, int *np)
339a747e4fSDavid du Colombier {
349a747e4fSDavid du Colombier uint n;
359a747e4fSDavid du Colombier
369a747e4fSDavid du Colombier if(p == nil)
379a747e4fSDavid du Colombier return nil;
389a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
399a747e4fSDavid du Colombier return nil;
409a747e4fSDavid du Colombier n = GBIT16(p);
419a747e4fSDavid du Colombier p += BIT16SZ;
429a747e4fSDavid du Colombier if(p+n > ep)
439a747e4fSDavid du Colombier return nil;
449a747e4fSDavid du Colombier *s = malloc(n);
459a747e4fSDavid du Colombier if(*s == nil)
469a747e4fSDavid du Colombier return nil;
479a747e4fSDavid du Colombier memmove((*s), p, n);
489a747e4fSDavid du Colombier *np = n;
499a747e4fSDavid du Colombier p += n;
509a747e4fSDavid du Colombier return p;
519a747e4fSDavid du Colombier }
529a747e4fSDavid du Colombier
539a747e4fSDavid du Colombier void
auth_freeAI(AuthInfo * ai)549a747e4fSDavid du Colombier auth_freeAI(AuthInfo *ai)
559a747e4fSDavid du Colombier {
569a747e4fSDavid du Colombier if(ai == nil)
579a747e4fSDavid du Colombier return;
589a747e4fSDavid du Colombier free(ai->cuid);
599a747e4fSDavid du Colombier free(ai->suid);
609a747e4fSDavid du Colombier free(ai->cap);
619a747e4fSDavid du Colombier free(ai->secret);
629a1d0a06SDavid du Colombier free(ai);
639a747e4fSDavid du Colombier }
649a747e4fSDavid du Colombier
659a747e4fSDavid du Colombier static uchar*
convM2AI(uchar * p,int n,AuthInfo ** aip)669a747e4fSDavid du Colombier convM2AI(uchar *p, int n, AuthInfo **aip)
679a747e4fSDavid du Colombier {
689a747e4fSDavid du Colombier uchar *e = p+n;
699a747e4fSDavid du Colombier AuthInfo *ai;
709a747e4fSDavid du Colombier
719a747e4fSDavid du Colombier ai = mallocz(sizeof(*ai), 1);
729a747e4fSDavid du Colombier if(ai == nil)
739a747e4fSDavid du Colombier return nil;
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier p = gstring(p, e, &ai->cuid);
769a747e4fSDavid du Colombier p = gstring(p, e, &ai->suid);
779a747e4fSDavid du Colombier p = gstring(p, e, &ai->cap);
789a747e4fSDavid du Colombier p = gcarray(p, e, &ai->secret, &ai->nsecret);
799a747e4fSDavid du Colombier if(p == nil)
809a747e4fSDavid du Colombier auth_freeAI(ai);
819a747e4fSDavid du Colombier else
829a747e4fSDavid du Colombier *aip = ai;
839a747e4fSDavid du Colombier return p;
849a747e4fSDavid du Colombier }
859a747e4fSDavid du Colombier
869a747e4fSDavid du Colombier AuthInfo*
auth_getinfo(AuthRpc * rpc)879a747e4fSDavid du Colombier auth_getinfo(AuthRpc *rpc)
889a747e4fSDavid du Colombier {
899a747e4fSDavid du Colombier AuthInfo *a;
909a747e4fSDavid du Colombier
919a747e4fSDavid du Colombier if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
929a747e4fSDavid du Colombier return nil;
939a747e4fSDavid du Colombier if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
949a747e4fSDavid du Colombier werrstr("bad auth info from factotum");
959a747e4fSDavid du Colombier return nil;
969a747e4fSDavid du Colombier }
979a747e4fSDavid du Colombier return a;
989a747e4fSDavid du Colombier }
999a747e4fSDavid du Colombier
1009a747e4fSDavid du Colombier static int
dorpc(AuthRpc * rpc,char * verb,char * val,int len,AuthGetkey * getkey)1019a747e4fSDavid du Colombier dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
1029a747e4fSDavid du Colombier {
1039a747e4fSDavid du Colombier int ret;
1049a747e4fSDavid du Colombier
1059a747e4fSDavid du Colombier for(;;){
1069a747e4fSDavid du Colombier if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
1079a747e4fSDavid du Colombier return ret;
1089a747e4fSDavid du Colombier if(getkey == nil)
1099a747e4fSDavid du Colombier return ARgiveup; /* don't know how */
1109a747e4fSDavid du Colombier if((*getkey)(rpc->arg) < 0)
1119a747e4fSDavid du Colombier return ARgiveup; /* user punted */
1129a747e4fSDavid du Colombier }
1139a747e4fSDavid du Colombier }
1149a747e4fSDavid du Colombier
1159a747e4fSDavid du Colombier /*
1169a747e4fSDavid du Colombier * this just proxies what the factotum tells it to.
1179a747e4fSDavid du Colombier */
1189a747e4fSDavid du Colombier AuthInfo*
fauth_proxy(int fd,AuthRpc * rpc,AuthGetkey * getkey,char * params)1199a747e4fSDavid du Colombier fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params)
1209a747e4fSDavid du Colombier {
1219a747e4fSDavid du Colombier char *buf;
1229a747e4fSDavid du Colombier int m, n, ret;
1239a747e4fSDavid du Colombier AuthInfo *a;
1249a747e4fSDavid du Colombier char oerr[ERRMAX];
1259a747e4fSDavid du Colombier
126*f366f900SDavid du Colombier if(rpc == nil){
127*f366f900SDavid du Colombier werrstr("fauth_proxy - no factotum");
128*f366f900SDavid du Colombier return nil;
129*f366f900SDavid du Colombier }
130*f366f900SDavid du Colombier
1319a747e4fSDavid du Colombier rerrstr(oerr, sizeof oerr);
1329a747e4fSDavid du Colombier werrstr("UNKNOWN AUTH ERROR");
1339a747e4fSDavid du Colombier
1349a747e4fSDavid du Colombier if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
1359a747e4fSDavid du Colombier werrstr("fauth_proxy start: %r");
1369a747e4fSDavid du Colombier return nil;
1379a747e4fSDavid du Colombier }
1389a747e4fSDavid du Colombier
1399a747e4fSDavid du Colombier buf = malloc(AuthRpcMax);
1409a747e4fSDavid du Colombier if(buf == nil)
1419a747e4fSDavid du Colombier return nil;
1429a747e4fSDavid du Colombier for(;;){
1439a747e4fSDavid du Colombier switch(dorpc(rpc, "read", nil, 0, getkey)){
1449a747e4fSDavid du Colombier case ARdone:
1459a747e4fSDavid du Colombier free(buf);
1469a747e4fSDavid du Colombier a = auth_getinfo(rpc);
147*f366f900SDavid du Colombier /* no error, restore whatever was there */
148*f366f900SDavid du Colombier errstr(oerr, sizeof oerr);
1499a747e4fSDavid du Colombier return a;
1509a747e4fSDavid du Colombier case ARok:
1519a747e4fSDavid du Colombier if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
1529a747e4fSDavid du Colombier werrstr("auth_proxy write fd: %r");
1539a747e4fSDavid du Colombier goto Error;
1549a747e4fSDavid du Colombier }
1559a747e4fSDavid du Colombier break;
1569a747e4fSDavid du Colombier case ARphase:
1579a747e4fSDavid du Colombier n = 0;
1589a747e4fSDavid du Colombier memset(buf, 0, AuthRpcMax);
1599a747e4fSDavid du Colombier while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
1609a747e4fSDavid du Colombier if(atoi(rpc->arg) > AuthRpcMax)
1619a747e4fSDavid du Colombier break;
1629a747e4fSDavid du Colombier m = read(fd, buf + n, atoi(rpc->arg) - n);
1639a747e4fSDavid du Colombier if(m <= 0){
1649a747e4fSDavid du Colombier if(m == 0)
165*f366f900SDavid du Colombier werrstr("auth_proxy short read: %s",
166*f366f900SDavid du Colombier buf);
1679a747e4fSDavid du Colombier goto Error;
1689a747e4fSDavid du Colombier }
1699a747e4fSDavid du Colombier n += m;
1709a747e4fSDavid du Colombier }
1719a747e4fSDavid du Colombier if(ret != ARok){
1729a747e4fSDavid du Colombier werrstr("auth_proxy rpc write: %s: %r", buf);
1739a747e4fSDavid du Colombier goto Error;
1749a747e4fSDavid du Colombier }
1759a747e4fSDavid du Colombier break;
1769a747e4fSDavid du Colombier default:
1779a747e4fSDavid du Colombier werrstr("auth_proxy rpc: %r");
1789a747e4fSDavid du Colombier goto Error;
1799a747e4fSDavid du Colombier }
1809a747e4fSDavid du Colombier }
1819a747e4fSDavid du Colombier Error:
1829a747e4fSDavid du Colombier free(buf);
1839a747e4fSDavid du Colombier return nil;
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier AuthInfo*
auth_proxy(int fd,AuthGetkey * getkey,char * fmt,...)1879a747e4fSDavid du Colombier auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...)
1889a747e4fSDavid du Colombier {
1899a747e4fSDavid du Colombier int afd;
1909a747e4fSDavid du Colombier char *p;
1919a747e4fSDavid du Colombier va_list arg;
1929a747e4fSDavid du Colombier AuthInfo *ai;
1939a747e4fSDavid du Colombier AuthRpc *rpc;
1949a747e4fSDavid du Colombier
1959a747e4fSDavid du Colombier quotefmtinstall(); /* just in case */
1969a747e4fSDavid du Colombier va_start(arg, fmt);
1979a747e4fSDavid du Colombier p = vsmprint(fmt, arg);
1989a747e4fSDavid du Colombier va_end(arg);
1999a747e4fSDavid du Colombier
200*f366f900SDavid du Colombier ai = nil;
2019a747e4fSDavid du Colombier afd = open("/mnt/factotum/rpc", ORDWR);
2029a747e4fSDavid du Colombier if(afd < 0){
2039a747e4fSDavid du Colombier werrstr("opening /mnt/factotum/rpc: %r");
2049a747e4fSDavid du Colombier free(p);
2059a747e4fSDavid du Colombier return nil;
2069a747e4fSDavid du Colombier }
2079a747e4fSDavid du Colombier
2089a747e4fSDavid du Colombier rpc = auth_allocrpc(afd);
209*f366f900SDavid du Colombier if(rpc){
2109a747e4fSDavid du Colombier ai = fauth_proxy(fd, rpc, getkey, p);
2119a747e4fSDavid du Colombier auth_freerpc(rpc);
212*f366f900SDavid du Colombier }
2139a747e4fSDavid du Colombier close(afd);
214*f366f900SDavid du Colombier free(p);
2159a747e4fSDavid du Colombier return ai;
2169a747e4fSDavid du Colombier }
217