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