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