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 if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){ 94 werrstr("bad auth info from factotum"); 95 return nil; 96 } 97 return a; 98 } 99 100 static int 101 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) 102 { 103 int ret; 104 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 } 114 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]; 125 126 rerrstr(oerr, sizeof oerr); 127 werrstr("UNKNOWN AUTH ERROR"); 128 129 if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ 130 werrstr("fauth_proxy start: %r"); 131 return nil; 132 } 133 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 } 178 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; 187 188 quotefmtinstall(); /* just in case */ 189 va_start(arg, fmt); 190 p = vsmprint(fmt, arg); 191 va_end(arg); 192 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 } 199 200 rpc = auth_allocrpc(afd); 201 if(rpc == nil){ 202 free(p); 203 return nil; 204 } 205 206 ai = fauth_proxy(fd, rpc, getkey, p); 207 free(p); 208 auth_freerpc(rpc); 209 close(afd); 210 return ai; 211 } 212 213