|  | #include "stdinc.h" | 
|  | #include "9.h" | 
|  |  | 
|  | int | 
|  | authRead(Fid* afid, void* data, int count) | 
|  | { | 
|  | AuthInfo *ai; | 
|  | AuthRpc *rpc; | 
|  |  | 
|  | if((rpc = afid->rpc) == nil){ | 
|  | werrstr("not an auth fid"); | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | switch(auth_rpc(rpc, "read", nil, 0)){ | 
|  | default: | 
|  | werrstr("fossil authRead: auth protocol not finished"); | 
|  | return -1; | 
|  | case ARdone: | 
|  | if((ai = auth_getinfo(rpc)) == nil){ | 
|  | werrstr("%r"); | 
|  | break; | 
|  | } | 
|  | if(ai->cuid == nil || *ai->cuid == '\0'){ | 
|  | werrstr("auth with no cuid"); | 
|  | auth_freeAI(ai); | 
|  | break; | 
|  | } | 
|  | assert(afid->cuname == nil); | 
|  | afid->cuname = vtstrdup(ai->cuid); | 
|  | auth_freeAI(ai); | 
|  | if(Dflag) | 
|  | fprint(2, "authRead cuname %s\n", afid->cuname); | 
|  | assert(afid->uid == nil); | 
|  | if((afid->uid = uidByUname(afid->cuname)) == nil){ | 
|  | werrstr("unknown user %#q", afid->cuname); | 
|  | break; | 
|  | } | 
|  | return 0; | 
|  | case ARok: | 
|  | if(count < rpc->narg){ | 
|  | werrstr("not enough data in auth read"); | 
|  | break; | 
|  | } | 
|  | memmove(data, rpc->arg, rpc->narg); | 
|  | return rpc->narg; | 
|  | case ARphase: | 
|  | werrstr("%r"); | 
|  | break; | 
|  | } | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | int | 
|  | authWrite(Fid* afid, void* data, int count) | 
|  | { | 
|  | assert(afid->rpc != nil); | 
|  | if(auth_rpc(afid->rpc, "write", data, count) != ARok) | 
|  | return -1; | 
|  | return count; | 
|  | } | 
|  |  | 
|  | int | 
|  | authCheck(Fcall* t, Fid* fid, Fsys* fsys) | 
|  | { | 
|  | Con *con; | 
|  | Fid *afid; | 
|  | uchar buf[1]; | 
|  |  | 
|  | /* | 
|  | * Can't lookup with FidWlock here as there may be | 
|  | * protocol to do. Use a separate lock to protect altering | 
|  | * the auth information inside afid. | 
|  | */ | 
|  | con = fid->con; | 
|  | if(t->afid == NOFID){ | 
|  | /* | 
|  | * If no authentication is asked for, allow | 
|  | * "none" provided the connection has already | 
|  | * been authenticatated. | 
|  | * | 
|  | * The console is allowed to attach without | 
|  | * authentication. | 
|  | */ | 
|  | rlock(&con->alock); | 
|  | if(con->isconsole){ | 
|  | /* anything goes */ | 
|  | }else if((con->flags&ConNoneAllow) || con->aok){ | 
|  | static int noneprint; | 
|  |  | 
|  | if(noneprint++ < 10) | 
|  | consPrint("attach %s as %s: allowing as none\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | vtfree(fid->uname); | 
|  | fid->uname = vtstrdup(unamenone); | 
|  | }else{ | 
|  | runlock(&con->alock); | 
|  | consPrint("attach %s as %s: connection not authenticated, not console\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | werrstr("cannot attach as none before authentication"); | 
|  | return 0; | 
|  | } | 
|  | runlock(&con->alock); | 
|  |  | 
|  | if((fid->uid = uidByUname(fid->uname)) == nil){ | 
|  | consPrint("attach %s as %s: unknown uname\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | werrstr("unknown user"); | 
|  | return 0; | 
|  | } | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | if((afid = fidGet(con, t->afid, 0)) == nil){ | 
|  | consPrint("attach %s as %s: bad afid\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | werrstr("bad authentication fid"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check valid afid; | 
|  | * check uname and aname match. | 
|  | */ | 
|  | if(!(afid->qid.type & QTAUTH)){ | 
|  | consPrint("attach %s as %s: afid not an auth file\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | fidPut(afid); | 
|  | werrstr("bad authentication fid"); | 
|  | return 0; | 
|  | } | 
|  | if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){ | 
|  | consPrint("attach %s as %s: afid is for %s as %s\n", | 
|  | fsysGetName(fsys), fid->uname, | 
|  | fsysGetName(afid->fsys), afid->uname); | 
|  | fidPut(afid); | 
|  | werrstr("attach/auth mismatch"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | qlock(&afid->alock); | 
|  | if(afid->cuname == nil){ | 
|  | if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){ | 
|  | qunlock(&afid->alock); | 
|  | consPrint("attach %s as %s: %r\n", | 
|  | fsysGetName(fsys), fid->uname); | 
|  | fidPut(afid); | 
|  | werrstr("fossil authCheck: auth protocol not finished"); | 
|  | return 0; | 
|  | } | 
|  | } | 
|  | qunlock(&afid->alock); | 
|  |  | 
|  | assert(fid->uid == nil); | 
|  | if((fid->uid = uidByUname(afid->cuname)) == nil){ | 
|  | consPrint("attach %s as %s: unknown cuname %s\n", | 
|  | fsysGetName(fsys), fid->uname, afid->cuname); | 
|  | fidPut(afid); | 
|  | werrstr("unknown user"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | vtfree(fid->uname); | 
|  | fid->uname = vtstrdup(afid->cuname); | 
|  | fidPut(afid); | 
|  |  | 
|  | /* | 
|  | * Allow "none" once the connection has been authenticated. | 
|  | */ | 
|  | wlock(&con->alock); | 
|  | con->aok = 1; | 
|  | wunlock(&con->alock); | 
|  |  | 
|  | return 1; | 
|  | } |