xref: /plan9-contrib/sys/src/cmd/fossil/9auth.c (revision a6a9e07217f318acf170f99684a55fba5200524f)
1 #include "stdinc.h"
2 
3 #include "9.h"
4 
5 int
6 authRead(Fid* afid, void* data, int count)
7 {
8 	AuthInfo *ai;
9 	AuthRpc *rpc;
10 
11 	if((rpc = afid->rpc) == nil)
12 		return -1;
13 
14 	switch(auth_rpc(rpc, "read", nil, 0)){
15 	default:
16 		return -1;
17 	case ARdone:
18 		if((ai = auth_getinfo(rpc)) == nil)
19 			break;
20 		if(ai->cuid == nil || *ai->cuid == '\0'){
21 			auth_freeAI(ai);
22 			break;
23 		}
24 		assert(afid->cuname == nil);
25 		afid->cuname = vtStrDup(ai->cuid);
26 		auth_freeAI(ai);
27 		if(Dflag)
28 			fprint(2, "authRead cuname %s\n", afid->cuname);
29 		assert(afid->uid == nil);
30 		if((afid->uid = uidByUname(afid->cuname)) == nil)
31 			break;
32 		return 0;
33 	case ARok:
34 		if(count < rpc->narg)
35 			break;
36 		memmove(data, rpc->arg, rpc->narg);
37 		return rpc->narg;
38 	case ARphase:
39 		break;
40 	}
41 	return -1;
42 }
43 
44 int
45 authWrite(Fid* afid, void* data, int count)
46 {
47 	assert(afid->rpc != nil);
48 	if(auth_rpc(afid->rpc, "write", data, count) != ARok)
49 		return -1;
50 	return count;
51 }
52 
53 int
54 authCheck(Fcall* t, Fid* fid, Fs* fsys)
55 {
56 	Con *con;
57 	Fid *afid;
58 	uchar buf[1];
59 
60 	/*
61 	 * Can't lookup with FidWlock here as there may be
62 	 * protocol to do. Use a separate lock to protect altering
63 	 * the auth information inside afid.
64 	 */
65 	con = fid->con;
66 	if(t->afid == NOFID){
67 		/*
68 		 * If no authentication is asked for, allow
69 		 * "none" provided the connection has already
70 		 * been authenticatated.
71 		 *
72 		 * The console is allowed to attach without
73 		 * authentication.
74 		 */
75 		vtRLock(con->alock);
76 		if(!con->isconsole &&
77 		(strcmp(fid->uname, unamenone) != 0 || !con->aok)){
78 			vtRUnlock(con->alock);
79 			consPrint("attach %s as %s: connection not authenticated, not console\n", fsysGetName(fsys), fid->uname);
80 			return 0;
81 		}
82 		vtRUnlock(con->alock);
83 
84 		if((fid->uid = uidByUname(fid->uname)) == nil){
85 			consPrint("attach %s as %s: unknown uname\n", fsysGetName(fsys), fid->uname);
86 			return 0;
87 		}
88 		return 1;
89 	}
90 
91 	if((afid = fidGet(con, t->afid, 0)) == nil){
92 		consPrint("attach %s as %s: bad afid\n", fsysGetName(fsys), fid->uname);
93 		return 0;
94 	}
95 
96 	/*
97 	 * Check valid afid;
98 	 * check uname and aname match.
99 	 */
100 	if(!(afid->qid.type & QTAUTH)){
101 		consPrint("attach %s as %s: afid not an auth file\n", fsysGetName(fsys), fid->uname);
102 		fidPut(afid);
103 		return 0;
104 	}
105 	if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){
106 		consPrint("attach %s as %s: afid is for %s as %s\n", fsysGetName(fsys), fid->uname, fsysGetName(afid->fsys), afid->uname);
107 		fidPut(afid);
108 		return 0;
109 	}
110 
111 	vtLock(afid->alock);
112 	if(afid->cuname == nil){
113 		if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
114 			vtUnlock(afid->alock);
115 			consPrint("attach %s as %s: auth protocol not finished\n", fsysGetName(fsys), fid->uname);
116 			fidPut(afid);
117 			return 0;
118 		}
119 	}
120 	vtUnlock(afid->alock);
121 
122 	assert(fid->uid == nil);
123 	if((fid->uid = uidByUname(afid->cuname)) == nil){
124 		consPrint("attach %s as %s: unknown cuname %s\n", fsysGetName(fsys), fid->uname, afid->cuname);
125 		fidPut(afid);
126 		return 0;
127 	}
128 
129 	vtMemFree(fid->uname);
130 	fid->uname = vtStrDup(afid->cuname);
131 	fidPut(afid);
132 
133 	/*
134 	 * Allow "none" once the connection has been authenticated.
135 	 */
136 	vtLock(con->alock);
137 	con->aok = 1;
138 	vtUnlock(con->alock);
139 
140 	return 1;
141 }
142