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