plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

9auth.c (3921B)


      1 #include "stdinc.h"
      2 #include "9.h"
      3 
      4 int
      5 authRead(Fid* afid, void* data, int count)
      6 {
      7 	AuthInfo *ai;
      8 	AuthRpc *rpc;
      9 
     10 	if((rpc = afid->rpc) == nil){
     11 		werrstr("not an auth fid");
     12 		return -1;
     13 	}
     14 
     15 	switch(auth_rpc(rpc, "read", nil, 0)){
     16 	default:
     17 		werrstr("fossil authRead: auth protocol not finished");
     18 		return -1;
     19 	case ARdone:
     20 		if((ai = auth_getinfo(rpc)) == nil){
     21 			werrstr("%r");
     22 			break;
     23 		}
     24 		if(ai->cuid == nil || *ai->cuid == '\0'){
     25 			werrstr("auth with no cuid");
     26 			auth_freeAI(ai);
     27 			break;
     28 		}
     29 		assert(afid->cuname == nil);
     30 		afid->cuname = vtstrdup(ai->cuid);
     31 		auth_freeAI(ai);
     32 		if(Dflag)
     33 			fprint(2, "authRead cuname %s\n", afid->cuname);
     34 		assert(afid->uid == nil);
     35 		if((afid->uid = uidByUname(afid->cuname)) == nil){
     36 			werrstr("unknown user %#q", afid->cuname);
     37 			break;
     38 		}
     39 		return 0;
     40 	case ARok:
     41 		if(count < rpc->narg){
     42 			werrstr("not enough data in auth read");
     43 			break;
     44 		}
     45 		memmove(data, rpc->arg, rpc->narg);
     46 		return rpc->narg;
     47 	case ARphase:
     48 		werrstr("%r");
     49 		break;
     50 	}
     51 	return -1;
     52 }
     53 
     54 int
     55 authWrite(Fid* afid, void* data, int count)
     56 {
     57 	assert(afid->rpc != nil);
     58 	if(auth_rpc(afid->rpc, "write", data, count) != ARok)
     59 		return -1;
     60 	return count;
     61 }
     62 
     63 int
     64 authCheck(Fcall* t, Fid* fid, Fsys* fsys)
     65 {
     66 	Con *con;
     67 	Fid *afid;
     68 	uchar buf[1];
     69 
     70 	/*
     71 	 * Can't lookup with FidWlock here as there may be
     72 	 * protocol to do. Use a separate lock to protect altering
     73 	 * the auth information inside afid.
     74 	 */
     75 	con = fid->con;
     76 	if(t->afid == NOFID){
     77 		/*
     78 		 * If no authentication is asked for, allow
     79 		 * "none" provided the connection has already
     80 		 * been authenticatated.
     81 		 *
     82 		 * The console is allowed to attach without
     83 		 * authentication.
     84 		 */
     85 		rlock(&con->alock);
     86 		if(con->isconsole){
     87 			/* anything goes */
     88 		}else if((con->flags&ConNoneAllow) || con->aok){
     89 			static int noneprint;
     90 
     91 			if(noneprint++ < 10)
     92 				consPrint("attach %s as %s: allowing as none\n",
     93 					fsysGetName(fsys), fid->uname);
     94 			vtfree(fid->uname);
     95 			fid->uname = vtstrdup(unamenone);
     96 		}else{
     97 			runlock(&con->alock);
     98 			consPrint("attach %s as %s: connection not authenticated, not console\n",
     99 				fsysGetName(fsys), fid->uname);
    100 			werrstr("cannot attach as none before authentication");
    101 			return 0;
    102 		}
    103 		runlock(&con->alock);
    104 
    105 		if((fid->uid = uidByUname(fid->uname)) == nil){
    106 			consPrint("attach %s as %s: unknown uname\n",
    107 				fsysGetName(fsys), fid->uname);
    108 			werrstr("unknown user");
    109 			return 0;
    110 		}
    111 		return 1;
    112 	}
    113 
    114 	if((afid = fidGet(con, t->afid, 0)) == nil){
    115 		consPrint("attach %s as %s: bad afid\n",
    116 			fsysGetName(fsys), fid->uname);
    117 		werrstr("bad authentication fid");
    118 		return 0;
    119 	}
    120 
    121 	/*
    122 	 * Check valid afid;
    123 	 * check uname and aname match.
    124 	 */
    125 	if(!(afid->qid.type & QTAUTH)){
    126 		consPrint("attach %s as %s: afid not an auth file\n",
    127 			fsysGetName(fsys), fid->uname);
    128 		fidPut(afid);
    129 		werrstr("bad authentication fid");
    130 		return 0;
    131 	}
    132 	if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){
    133 		consPrint("attach %s as %s: afid is for %s as %s\n",
    134 			fsysGetName(fsys), fid->uname,
    135 			fsysGetName(afid->fsys), afid->uname);
    136 		fidPut(afid);
    137 		werrstr("attach/auth mismatch");
    138 		return 0;
    139 	}
    140 
    141 	qlock(&afid->alock);
    142 	if(afid->cuname == nil){
    143 		if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
    144 			qunlock(&afid->alock);
    145 			consPrint("attach %s as %s: %r\n",
    146 				fsysGetName(fsys), fid->uname);
    147 			fidPut(afid);
    148 			werrstr("fossil authCheck: auth protocol not finished");
    149 			return 0;
    150 		}
    151 	}
    152 	qunlock(&afid->alock);
    153 
    154 	assert(fid->uid == nil);
    155 	if((fid->uid = uidByUname(afid->cuname)) == nil){
    156 		consPrint("attach %s as %s: unknown cuname %s\n",
    157 			fsysGetName(fsys), fid->uname, afid->cuname);
    158 		fidPut(afid);
    159 		werrstr("unknown user");
    160 		return 0;
    161 	}
    162 
    163 	vtfree(fid->uname);
    164 	fid->uname = vtstrdup(afid->cuname);
    165 	fidPut(afid);
    166 
    167 	/*
    168 	 * Allow "none" once the connection has been authenticated.
    169 	 */
    170 	wlock(&con->alock);
    171 	con->aok = 1;
    172 	wunlock(&con->alock);
    173 
    174 	return 1;
    175 }