1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <auth.h> 5 #include "authlocal.h" 6 7 enum { 8 ARgiveup = 100, 9 }; 10 11 static uchar* 12 gstring(uchar *p, uchar *ep, char **s) 13 { 14 uint n; 15 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 } 30 31 static uchar* 32 gcarray(uchar *p, uchar *ep, uchar **s, int *np) 33 { 34 uint n; 35 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 } 52 53 void 54 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 } 64 65 static uchar* 66 convM2AI(uchar *p, int n, AuthInfo **aip) 67 { 68 uchar *e = p+n; 69 AuthInfo *ai; 70 71 ai = mallocz(sizeof(*ai), 1); 72 if(ai == nil) 73 return nil; 74 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 else 82 *aip = ai; 83 return p; 84 } 85 86 AuthInfo* 87 auth_getinfo(AuthRpc *rpc) 88 { 89 AuthInfo *a; 90 91 if(auth_rpc(rpc, "authinfo", nil, 0) != ARok) 92 return nil; 93 a = nil; 94 if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){ 95 werrstr("bad auth info from factotum"); 96 return nil; 97 } 98 return a; 99 } 100 101 static int 102 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) 103 { 104 int ret; 105 106 for(;;){ 107 if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) 108 return ret; 109 if(getkey == 0) 110 return ARgiveup; /* don't know how */ 111 if((*getkey)(rpc->arg) < 0) 112 return ARgiveup; /* user punted */ 113 } 114 } 115 116 /* 117 * this just proxies what the factotum tells it to. 118 */ 119 AuthInfo* 120 fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params) 121 { 122 char *buf; 123 int m, n, ret; 124 AuthInfo *a; 125 char oerr[ERRMAX]; 126 127 rerrstr(oerr, sizeof oerr); 128 werrstr("UNKNOWN AUTH ERROR"); 129 130 if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ 131 werrstr("fauth_proxy start: %r"); 132 return nil; 133 } 134 135 buf = malloc(AuthRpcMax); 136 if(buf == nil) 137 return nil; 138 for(;;){ 139 switch(dorpc(rpc, "read", nil, 0, getkey)){ 140 case ARdone: 141 free(buf); 142 a = auth_getinfo(rpc); 143 errstr(oerr, sizeof oerr); /* no error, restore whatever was there */ 144 return a; 145 case ARok: 146 if(write(fd, rpc->arg, rpc->narg) != rpc->narg){ 147 werrstr("auth_proxy write fd: %r"); 148 goto Error; 149 } 150 break; 151 case ARphase: 152 n = 0; 153 memset(buf, 0, AuthRpcMax); 154 while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){ 155 if(atoi(rpc->arg) > AuthRpcMax) 156 break; 157 m = read(fd, buf+n, atoi(rpc->arg)-n); 158 if(m <= 0){ 159 if(m == 0) 160 werrstr("auth_proxy short read: %s", buf); 161 goto Error; 162 } 163 n += m; 164 } 165 if(ret != ARok){ 166 werrstr("auth_proxy rpc write: %s: %r", buf); 167 goto Error; 168 } 169 break; 170 default: 171 werrstr("auth_proxy rpc: %r"); 172 goto Error; 173 } 174 } 175 Error: 176 free(buf); 177 return nil; 178 } 179 180 AuthInfo* 181 auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...) 182 { 183 int afd; 184 char *p; 185 va_list arg; 186 AuthInfo *ai; 187 AuthRpc *rpc; 188 189 quotefmtinstall(); /* just in case */ 190 va_start(arg, fmt); 191 p = vsmprint(fmt, arg); 192 va_end(arg); 193 194 afd = open("/mnt/factotum/rpc", ORDWR); 195 if(afd < 0){ 196 werrstr("opening /mnt/factotum/rpc: %r"); 197 free(p); 198 return nil; 199 } 200 201 rpc = auth_allocrpc(afd); 202 if(rpc == nil){ 203 free(p); 204 return nil; 205 } 206 207 ai = fauth_proxy(fd, rpc, getkey, p); 208 free(p); 209 auth_freerpc(rpc); 210 close(afd); 211 return ai; 212 } 213 214