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