1 #include "stdinc.h"
2 #include "9.h"
3
4 int
authRead(Fid * afid,void * data,int count)5 authRead(Fid* afid, void* data, int count)
6 {
7 AuthInfo *ai;
8 AuthRpc *rpc;
9
10 if((rpc = afid->rpc) == nil){
11 vtSetError("not an auth fid");
12 return -1;
13 }
14
15 switch(auth_rpc(rpc, "read", nil, 0)){
16 default:
17 vtSetError("fossil authRead: auth protocol not finished");
18 return -1;
19 case ARdone:
20 if((ai = auth_getinfo(rpc)) == nil){
21 vtSetError("%r");
22 break;
23 }
24 if(ai->cuid == nil || *ai->cuid == '\0'){
25 vtSetError("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 vtSetError("unknown user %#q", afid->cuname);
37 break;
38 }
39 return 0;
40 case ARok:
41 if(count < rpc->narg){
42 vtSetError("not enough data in auth read");
43 break;
44 }
45 memmove(data, rpc->arg, rpc->narg);
46 return rpc->narg;
47 case ARphase:
48 vtSetError("%r");
49 break;
50 }
51 return -1;
52 }
53
54 int
authWrite(Fid * afid,void * data,int count)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
authCheck(Fcall * t,Fid * fid,Fsys * fsys)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 vtRLock(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 vtMemFree(fid->uname);
95 fid->uname = vtStrDup(unamenone);
96 }else{
97 vtRUnlock(con->alock);
98 consPrint("attach %s as %s: connection not authenticated, not console\n",
99 fsysGetName(fsys), fid->uname);
100 vtSetError("cannot attach as none before authentication");
101 return 0;
102 }
103 vtRUnlock(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 vtSetError("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 vtSetError("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 vtSetError("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 vtSetError("attach/auth mismatch");
138 return 0;
139 }
140
141 vtLock(afid->alock);
142 if(afid->cuname == nil){
143 if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
144 vtUnlock(afid->alock);
145 consPrint("attach %s as %s: %R\n",
146 fsysGetName(fsys), fid->uname);
147 fidPut(afid);
148 vtSetError("fossil authCheck: auth protocol not finished");
149 return 0;
150 }
151 }
152 vtUnlock(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 vtSetError("unknown user");
160 return 0;
161 }
162
163 vtMemFree(fid->uname);
164 fid->uname = vtStrDup(afid->cuname);
165 fidPut(afid);
166
167 /*
168 * Allow "none" once the connection has been authenticated.
169 */
170 vtLock(con->alock);
171 con->aok = 1;
172 vtUnlock(con->alock);
173
174 return 1;
175 }
176