1 #include "all.h" 2 3 enum { 4 ARgiveup = 100, 5 }; 6 7 static uchar* 8 gstring(uchar *p, uchar *ep, char **s) 9 { 10 uint n; 11 12 if(p == nil) 13 return nil; 14 if(p+BIT16SZ > ep) 15 return nil; 16 n = GBIT16(p); 17 p += BIT16SZ; 18 if(p+n > ep) 19 return nil; 20 *s = malloc(n+1); 21 memmove((*s), p, n); 22 (*s)[n] = '\0'; 23 p += n; 24 return p; 25 } 26 27 static uchar* 28 gcarray(uchar *p, uchar *ep, uchar **s, int *np) 29 { 30 uint n; 31 32 if(p == nil) 33 return nil; 34 if(p+BIT16SZ > ep) 35 return nil; 36 n = GBIT16(p); 37 p += BIT16SZ; 38 if(p+n > ep) 39 return nil; 40 *s = malloc(n); 41 if(*s == nil) 42 return nil; 43 memmove((*s), p, n); 44 *np = n; 45 p += n; 46 return p; 47 } 48 49 static uchar* 50 convM2AI(uchar *p, int n, AuthInfo **aip) 51 { 52 uchar *e = p+n; 53 AuthInfo *ai; 54 55 ai = mallocz(sizeof(*ai), 1); 56 if(ai == nil) 57 return nil; 58 59 p = gstring(p, e, &ai->cuid); 60 p = gstring(p, e, &ai->suid); 61 p = gstring(p, e, &ai->cap); 62 p = gcarray(p, e, &ai->secret, &ai->nsecret); 63 if(p == nil) 64 auth_freeAI(ai); 65 else 66 *aip = ai; 67 return p; 68 } 69 70 static int 71 dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey) 72 { 73 int ret; 74 75 for(;;){ 76 if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey) 77 return ret; 78 if(getkey == nil) 79 return ARgiveup; /* don't know how */ 80 if((*getkey)(rpc->arg) < 0) 81 return ARgiveup; /* user punted */ 82 } 83 } 84 85 static int 86 doread(Session *s, Fid *f, void *buf, int n) 87 { 88 s->f.fid = f - s->fids; 89 s->f.offset = 0; 90 s->f.count = n; 91 if(xmesg(s, Tread) < 0) 92 return -1; 93 n = s->f.count; 94 memmove(buf, s->f.data, n); 95 return n; 96 } 97 98 static int 99 dowrite(Session *s, Fid *f, void *buf, int n) 100 { 101 s->f.fid = f - s->fids; 102 s->f.offset = 0; 103 s->f.count = n; 104 s->f.data = (char *)buf; 105 if(xmesg(s, Twrite) < 0) 106 return -1; 107 return n; 108 } 109 110 /* 111 * this just proxies what the factotum tells it to. 112 */ 113 AuthInfo* 114 authproto(Session *s, Fid *f, AuthRpc *rpc, AuthGetkey *getkey, char *params) 115 { 116 char *buf; 117 int m, n, ret; 118 AuthInfo *a; 119 char oerr[ERRMAX]; 120 121 rerrstr(oerr, sizeof oerr); 122 werrstr("UNKNOWN AUTH ERROR"); 123 124 if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){ 125 werrstr("fauth_proxy start: %r"); 126 return nil; 127 } 128 129 buf = malloc(AuthRpcMax); 130 if(buf == nil) 131 return nil; 132 for(;;){ 133 switch(dorpc(rpc, "read", nil, 0, getkey)){ 134 case ARdone: 135 free(buf); 136 a = auth_getinfo(rpc); 137 errstr(oerr, sizeof oerr); /* no error, restore whatever was there */ 138 return a; 139 case ARok: 140 if(dowrite(s, f, rpc->arg, rpc->narg) != rpc->narg){ 141 werrstr("auth_proxy write fd: %r"); 142 goto Error; 143 } 144 break; 145 case ARphase: 146 n = 0; 147 memset(buf, 0, AuthRpcMax); 148 while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){ 149 if(atoi(rpc->arg) > AuthRpcMax) 150 break; 151 m = doread(s, f, buf+n, atoi(rpc->arg)-n); 152 if(m <= 0){ 153 if(m == 0) 154 werrstr("auth_proxy short read: %s", buf); 155 goto Error; 156 } 157 n += m; 158 } 159 if(ret != ARok){ 160 werrstr("auth_proxy rpc write: %s: %r", buf); 161 goto Error; 162 } 163 break; 164 default: 165 werrstr("auth_proxy rpc: %r"); 166 goto Error; 167 } 168 } 169 Error: 170 free(buf); 171 return nil; 172 } 173 174 /* returns 0 if auth succeeded (or unneeded), -1 otherwise */ 175 int 176 authhostowner(Session *s) 177 { 178 Fid *af, *f; 179 int rv = -1; 180 int afd; 181 AuthInfo *ai; 182 AuthRpc *rpc; 183 184 /* get a fid to authenticate over */ 185 f = nil; 186 af = newfid(s); 187 s->f.afid = af - s->fids; 188 s->f.uname = getuser(); 189 s->f.aname = s->spec; 190 if(xmesg(s, Tauth)){ 191 /* not needed */ 192 rv = 0; 193 goto out; 194 } 195 196 quotefmtinstall(); /* just in case */ 197 198 afd = open("/mnt/factotum/rpc", ORDWR); 199 if(afd < 0){ 200 werrstr("opening /mnt/factotum/rpc: %r"); 201 goto out; 202 } 203 204 rpc = auth_allocrpc(afd); 205 if(rpc == nil) 206 goto out; 207 208 ai = authproto(s, af, rpc, auth_getkey, "proto=p9any role=client"); 209 if(ai != nil){ 210 rv = 0; 211 auth_freeAI(ai); 212 } 213 auth_freerpc(rpc); 214 close(afd); 215 216 /* try attaching with the afid */ 217 chat("attaching as hostowner..."); 218 f = newfid(s); 219 s->f.fid = f - s->fids; 220 s->f.afid = af - s->fids;; 221 s->f.uname = getuser(); 222 s->f.aname = s->spec; 223 if(xmesg(s, Tattach) == 0) 224 rv = 0; 225 out: 226 if(af != nil){ 227 putfid(s, af); 228 s->f.fid = af - s->fids; 229 xmesg(s, Tclunk); 230 } 231 if(f != nil){ 232 putfid(s, f); 233 s->f.fid = f - s->fids; 234 xmesg(s, Tclunk); 235 } 236 237 return rv; 238 } 239 240