xref: /plan9-contrib/sys/src/cmd/fossil/9auth.c (revision d7aba6c3b511bc618cf0c53345848188fc02611a)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier #include "9.h"
35e96a66cSDavid du Colombier 
45e96a66cSDavid du Colombier int
authRead(Fid * afid,void * data,int count)55e96a66cSDavid du Colombier authRead(Fid* afid, void* data, int count)
65e96a66cSDavid du Colombier {
75e96a66cSDavid du Colombier 	AuthInfo *ai;
85e96a66cSDavid du Colombier 	AuthRpc *rpc;
95e96a66cSDavid du Colombier 
1081cf8742SDavid du Colombier 	if((rpc = afid->rpc) == nil){
11*d7aba6c3SDavid du Colombier 		werrstr("not an auth fid");
125e96a66cSDavid du Colombier 		return -1;
1381cf8742SDavid du Colombier 	}
145e96a66cSDavid du Colombier 
155e96a66cSDavid du Colombier 	switch(auth_rpc(rpc, "read", nil, 0)){
165e96a66cSDavid du Colombier 	default:
17*d7aba6c3SDavid du Colombier 		werrstr("fossil authRead: auth protocol not finished");
185e96a66cSDavid du Colombier 		return -1;
195e96a66cSDavid du Colombier 	case ARdone:
2081cf8742SDavid du Colombier 		if((ai = auth_getinfo(rpc)) == nil){
21*d7aba6c3SDavid du Colombier 			werrstr("%r");
225e96a66cSDavid du Colombier 			break;
2381cf8742SDavid du Colombier 		}
245e96a66cSDavid du Colombier 		if(ai->cuid == nil || *ai->cuid == '\0'){
25*d7aba6c3SDavid du Colombier 			werrstr("auth with no cuid");
265e96a66cSDavid du Colombier 			auth_freeAI(ai);
275e96a66cSDavid du Colombier 			break;
285e96a66cSDavid du Colombier 		}
295e96a66cSDavid du Colombier 		assert(afid->cuname == nil);
30*d7aba6c3SDavid du Colombier 		afid->cuname = vtstrdup(ai->cuid);
315e96a66cSDavid du Colombier 		auth_freeAI(ai);
325e96a66cSDavid du Colombier 		if(Dflag)
335e96a66cSDavid du Colombier 			fprint(2, "authRead cuname %s\n", afid->cuname);
345e96a66cSDavid du Colombier 		assert(afid->uid == nil);
3581cf8742SDavid du Colombier 		if((afid->uid = uidByUname(afid->cuname)) == nil){
36*d7aba6c3SDavid du Colombier 			werrstr("unknown user %#q", afid->cuname);
375e96a66cSDavid du Colombier 			break;
3881cf8742SDavid du Colombier 		}
395e96a66cSDavid du Colombier 		return 0;
405e96a66cSDavid du Colombier 	case ARok:
4181cf8742SDavid du Colombier 		if(count < rpc->narg){
42*d7aba6c3SDavid du Colombier 			werrstr("not enough data in auth read");
435e96a66cSDavid du Colombier 			break;
4481cf8742SDavid du Colombier 		}
455e96a66cSDavid du Colombier 		memmove(data, rpc->arg, rpc->narg);
465e96a66cSDavid du Colombier 		return rpc->narg;
475e96a66cSDavid du Colombier 	case ARphase:
48*d7aba6c3SDavid du Colombier 		werrstr("%r");
495e96a66cSDavid du Colombier 		break;
505e96a66cSDavid du Colombier 	}
515e96a66cSDavid du Colombier 	return -1;
525e96a66cSDavid du Colombier }
535e96a66cSDavid du Colombier 
545e96a66cSDavid du Colombier int
authWrite(Fid * afid,void * data,int count)555e96a66cSDavid du Colombier authWrite(Fid* afid, void* data, int count)
565e96a66cSDavid du Colombier {
575e96a66cSDavid du Colombier 	assert(afid->rpc != nil);
585e96a66cSDavid du Colombier 	if(auth_rpc(afid->rpc, "write", data, count) != ARok)
595e96a66cSDavid du Colombier 		return -1;
605e96a66cSDavid du Colombier 	return count;
615e96a66cSDavid du Colombier }
625e96a66cSDavid du Colombier 
635e96a66cSDavid du Colombier int
authCheck(Fcall * t,Fid * fid,Fsys * fsys)6400580da5SDavid du Colombier authCheck(Fcall* t, Fid* fid, Fsys* fsys)
655e96a66cSDavid du Colombier {
6634e04225SDavid du Colombier 	Con *con;
675e96a66cSDavid du Colombier 	Fid *afid;
685e96a66cSDavid du Colombier 	uchar buf[1];
695e96a66cSDavid du Colombier 
705e96a66cSDavid du Colombier 	/*
715e96a66cSDavid du Colombier 	 * Can't lookup with FidWlock here as there may be
725e96a66cSDavid du Colombier 	 * protocol to do. Use a separate lock to protect altering
735e96a66cSDavid du Colombier 	 * the auth information inside afid.
745e96a66cSDavid du Colombier 	 */
7534e04225SDavid du Colombier 	con = fid->con;
7661201b97SDavid du Colombier 	if(t->afid == NOFID){
775e96a66cSDavid du Colombier 		/*
785e96a66cSDavid du Colombier 		 * If no authentication is asked for, allow
795e96a66cSDavid du Colombier 		 * "none" provided the connection has already
805e96a66cSDavid du Colombier 		 * been authenticatated.
8161201b97SDavid du Colombier 		 *
825e96a66cSDavid du Colombier 		 * The console is allowed to attach without
835e96a66cSDavid du Colombier 		 * authentication.
845e96a66cSDavid du Colombier 		 */
85*d7aba6c3SDavid du Colombier 		rlock(&con->alock);
862cca75a1SDavid du Colombier 		if(con->isconsole){
872cca75a1SDavid du Colombier 			/* anything goes */
882cca75a1SDavid du Colombier 		}else if((con->flags&ConNoneAllow) || con->aok){
89208510e1SDavid du Colombier 			static int noneprint;
90208510e1SDavid du Colombier 
91208510e1SDavid du Colombier 			if(noneprint++ < 10)
92208510e1SDavid du Colombier 				consPrint("attach %s as %s: allowing as none\n",
93208510e1SDavid du Colombier 					fsysGetName(fsys), fid->uname);
94*d7aba6c3SDavid du Colombier 			vtfree(fid->uname);
95*d7aba6c3SDavid du Colombier 			fid->uname = vtstrdup(unamenone);
962cca75a1SDavid du Colombier 		}else{
97*d7aba6c3SDavid du Colombier 			runlock(&con->alock);
98208510e1SDavid du Colombier 			consPrint("attach %s as %s: connection not authenticated, not console\n",
99208510e1SDavid du Colombier 				fsysGetName(fsys), fid->uname);
100*d7aba6c3SDavid du Colombier 			werrstr("cannot attach as none before authentication");
1015e96a66cSDavid du Colombier 			return 0;
10261201b97SDavid du Colombier 		}
103*d7aba6c3SDavid du Colombier 		runlock(&con->alock);
10461201b97SDavid du Colombier 
10561201b97SDavid du Colombier 		if((fid->uid = uidByUname(fid->uname)) == nil){
106208510e1SDavid du Colombier 			consPrint("attach %s as %s: unknown uname\n",
107208510e1SDavid du Colombier 				fsysGetName(fsys), fid->uname);
108*d7aba6c3SDavid du Colombier 			werrstr("unknown user");
1095e96a66cSDavid du Colombier 			return 0;
11061201b97SDavid du Colombier 		}
1115e96a66cSDavid du Colombier 		return 1;
1125e96a66cSDavid du Colombier 	}
1135e96a66cSDavid du Colombier 
11434e04225SDavid du Colombier 	if((afid = fidGet(con, t->afid, 0)) == nil){
11500580da5SDavid du Colombier 		consPrint("attach %s as %s: bad afid\n",
11600580da5SDavid du Colombier 			fsysGetName(fsys), fid->uname);
117*d7aba6c3SDavid du Colombier 		werrstr("bad authentication fid");
11861201b97SDavid du Colombier 		return 0;
11961201b97SDavid du Colombier 	}
12061201b97SDavid du Colombier 
1215e96a66cSDavid du Colombier 	/*
1225e96a66cSDavid du Colombier 	 * Check valid afid;
1235e96a66cSDavid du Colombier 	 * check uname and aname match.
1245e96a66cSDavid du Colombier 	 */
1255e96a66cSDavid du Colombier 	if(!(afid->qid.type & QTAUTH)){
12600580da5SDavid du Colombier 		consPrint("attach %s as %s: afid not an auth file\n",
12700580da5SDavid du Colombier 			fsysGetName(fsys), fid->uname);
1285e96a66cSDavid du Colombier 		fidPut(afid);
129*d7aba6c3SDavid du Colombier 		werrstr("bad authentication fid");
1305e96a66cSDavid du Colombier 		return 0;
1315e96a66cSDavid du Colombier 	}
1325e96a66cSDavid du Colombier 	if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){
13300580da5SDavid du Colombier 		consPrint("attach %s as %s: afid is for %s as %s\n",
13400580da5SDavid du Colombier 			fsysGetName(fsys), fid->uname,
13500580da5SDavid du Colombier 			fsysGetName(afid->fsys), afid->uname);
1365e96a66cSDavid du Colombier 		fidPut(afid);
137*d7aba6c3SDavid du Colombier 		werrstr("attach/auth mismatch");
1385e96a66cSDavid du Colombier 		return 0;
1395e96a66cSDavid du Colombier 	}
1405e96a66cSDavid du Colombier 
141*d7aba6c3SDavid du Colombier 	qlock(&afid->alock);
1425e96a66cSDavid du Colombier 	if(afid->cuname == nil){
1435e96a66cSDavid du Colombier 		if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
144*d7aba6c3SDavid du Colombier 			qunlock(&afid->alock);
145*d7aba6c3SDavid du Colombier 			consPrint("attach %s as %s: %r\n",
14600580da5SDavid du Colombier 				fsysGetName(fsys), fid->uname);
1475e96a66cSDavid du Colombier 			fidPut(afid);
148*d7aba6c3SDavid du Colombier 			werrstr("fossil authCheck: auth protocol not finished");
1495e96a66cSDavid du Colombier 			return 0;
1505e96a66cSDavid du Colombier 		}
1515e96a66cSDavid du Colombier 	}
152*d7aba6c3SDavid du Colombier 	qunlock(&afid->alock);
1535e96a66cSDavid du Colombier 
1545e96a66cSDavid du Colombier 	assert(fid->uid == nil);
1555e96a66cSDavid du Colombier 	if((fid->uid = uidByUname(afid->cuname)) == nil){
15600580da5SDavid du Colombier 		consPrint("attach %s as %s: unknown cuname %s\n",
15700580da5SDavid du Colombier 			fsysGetName(fsys), fid->uname, afid->cuname);
1585e96a66cSDavid du Colombier 		fidPut(afid);
159*d7aba6c3SDavid du Colombier 		werrstr("unknown user");
1605e96a66cSDavid du Colombier 		return 0;
1615e96a66cSDavid du Colombier 	}
1625e96a66cSDavid du Colombier 
163*d7aba6c3SDavid du Colombier 	vtfree(fid->uname);
164*d7aba6c3SDavid du Colombier 	fid->uname = vtstrdup(afid->cuname);
1655e96a66cSDavid du Colombier 	fidPut(afid);
1665e96a66cSDavid du Colombier 
1675e96a66cSDavid du Colombier 	/*
1685e96a66cSDavid du Colombier 	 * Allow "none" once the connection has been authenticated.
1695e96a66cSDavid du Colombier 	 */
170*d7aba6c3SDavid du Colombier 	wlock(&con->alock);
17134e04225SDavid du Colombier 	con->aok = 1;
172*d7aba6c3SDavid du Colombier 	wunlock(&con->alock);
1735e96a66cSDavid du Colombier 
1745e96a66cSDavid du Colombier 	return 1;
1755e96a66cSDavid du Colombier }
176