1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <fcall.h> 5 #include <thread.h> 6 #include <9p.h> 7 8 typedef struct Afid Afid; 9 10 struct Afid 11 { 12 AuthRpc *rpc; 13 char *uname; 14 char *aname; 15 int authok; 16 int afd; 17 }; 18 19 static uvlong authgen = 1ULL<<63; 20 21 void 22 auth9p(Req *r) 23 { 24 char *spec; 25 Afid *afid; 26 27 afid = emalloc9p(sizeof(Afid)); 28 afid->afd = open("/mnt/factotum/rpc", ORDWR); 29 if(afid->afd < 0) 30 goto error; 31 32 if((afid->rpc = auth_allocrpc(afid->afd)) == nil) 33 goto error; 34 35 if(r->ifcall.uname[0] == 0) 36 goto error; 37 afid->uname = estrdup9p(r->ifcall.uname); 38 afid->aname = estrdup9p(r->ifcall.aname); 39 40 spec = r->srv->keyspec; 41 if(spec == nil) 42 spec = "proto=p9any role=server"; 43 44 if(auth_rpc(afid->rpc, "start", spec, strlen(spec)) != ARok) 45 goto error; 46 47 r->afid->qid.type = QTAUTH; 48 r->afid->qid.path = ++authgen; 49 r->afid->qid.vers = 0; 50 r->afid->omode = ORDWR; 51 r->ofcall.qid = r->afid->qid; 52 r->afid->aux = afid; 53 respond(r, nil); 54 return; 55 56 error: 57 if(afid->rpc) 58 auth_freerpc(afid->rpc); 59 if(afid->uname) 60 free(afid->uname); 61 if(afid->aname) 62 free(afid->aname); 63 if(afid->afd >= 0) 64 close(afid->afd); 65 free(afid); 66 responderror(r); 67 } 68 69 static int 70 _authread(Afid *afid, void *data, int count) 71 { 72 AuthInfo *ai; 73 74 switch(auth_rpc(afid->rpc, "read", nil, 0)){ 75 case ARdone: 76 ai = auth_getinfo(afid->rpc); 77 if(ai == nil) 78 return -1; 79 auth_freeAI(ai); 80 if(chatty9p) 81 fprint(2, "authenticate %s/%s: ok\n", afid->uname, afid->aname); 82 afid->authok = 1; 83 return 0; 84 85 case ARok: 86 if(count < afid->rpc->narg){ 87 werrstr("authread count too small"); 88 return -1; 89 } 90 count = afid->rpc->narg; 91 memmove(data, afid->rpc->arg, count); 92 return count; 93 94 case ARphase: 95 default: 96 werrstr("authrpc botch"); 97 return -1; 98 } 99 } 100 101 void 102 authread(Req *r) 103 { 104 int n; 105 Afid *afid; 106 Fid *fid; 107 108 fid = r->fid; 109 afid = fid->aux; 110 if(afid == nil || r->fid->qid.type != QTAUTH){ 111 respond(r, "not an auth fid"); 112 return; 113 } 114 n = _authread(afid, r->ofcall.data, r->ifcall.count); 115 if(n < 0){ 116 responderror(r); 117 return; 118 } 119 r->ofcall.count = n; 120 respond(r, nil); 121 } 122 123 void 124 authwrite(Req *r) 125 { 126 Afid *afid; 127 Fid *fid; 128 129 fid = r->fid; 130 afid = fid->aux; 131 if(afid == nil || r->fid->qid.type != QTAUTH){ 132 respond(r, "not an auth fid"); 133 return; 134 } 135 if(auth_rpc(afid->rpc, "write", r->ifcall.data, r->ifcall.count) != ARok){ 136 responderror(r); 137 return; 138 } 139 r->ofcall.count = r->ifcall.count; 140 respond(r, nil); 141 } 142 143 void 144 authdestroy(Fid *fid) 145 { 146 Afid *afid; 147 148 if((fid->qid.type & QTAUTH) && (afid = fid->aux) != nil){ 149 if(afid->rpc) 150 auth_freerpc(afid->rpc); 151 close(afid->afd); 152 free(afid->uname); 153 free(afid->aname); 154 free(afid); 155 fid->aux = nil; 156 } 157 } 158 159 int 160 authattach(Req *r) 161 { 162 Afid *afid; 163 char buf[ERRMAX]; 164 165 if(r->afid == nil){ 166 respond(r, "not authenticated"); 167 return -1; 168 } 169 170 afid = r->afid->aux; 171 if((r->afid->qid.type&QTAUTH) == 0 || afid == nil){ 172 respond(r, "not an auth fid"); 173 return -1; 174 } 175 176 if(!afid->authok){ 177 if(_authread(afid, buf, 0) < 0){ 178 responderror(r); 179 return -1; 180 } 181 } 182 183 if(strcmp(afid->uname, r->ifcall.uname) != 0){ 184 snprint(buf, sizeof buf, "auth uname mismatch: %s vs %s", 185 afid->uname, r->ifcall.uname); 186 respond(r, buf); 187 return -1; 188 } 189 190 if(strcmp(afid->aname, r->ifcall.aname) != 0){ 191 snprint(buf, sizeof buf, "auth aname mismatch: %s vs %s", 192 afid->aname, r->ifcall.aname); 193 respond(r, buf); 194 return -1; 195 } 196 return 0; 197 } 198 199