176 lines
3.8 KiB
C
176 lines
3.8 KiB
C
#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;
|
|
}
|