1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
3 6f4d00ee 2013-09-23 0intro #include "9.h"
6 6f4d00ee 2013-09-23 0intro OMODE = 0x7, /* Topen/Tcreate mode */
10 6f4d00ee 2013-09-23 0intro PermX = 1,
11 6f4d00ee 2013-09-23 0intro PermW = 2,
12 6f4d00ee 2013-09-23 0intro PermR = 4,
15 6f4d00ee 2013-09-23 0intro static char EPermission[] = "permission denied";
17 6f4d00ee 2013-09-23 0intro static int
18 6f4d00ee 2013-09-23 0intro permFile(File* file, Fid* fid, int perm)
21 6f4d00ee 2013-09-23 0intro DirEntry de;
23 6f4d00ee 2013-09-23 0intro if(!fileGetDir(file, &de))
24 6f4d00ee 2013-09-23 0intro return -1;
27 6f4d00ee 2013-09-23 0intro * User none only gets other permissions.
29 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, unamenone) != 0){
31 6f4d00ee 2013-09-23 0intro * There is only one uid<->uname mapping
32 6f4d00ee 2013-09-23 0intro * and it's already cached in the Fid, but
33 6f4d00ee 2013-09-23 0intro * it might have changed during the lifetime
34 6f4d00ee 2013-09-23 0intro * if this Fid.
36 6f4d00ee 2013-09-23 0intro if((u = unameByUid(de.uid)) != nil){
37 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, u) == 0 && ((perm<<6) & de.mode)){
38 4b576658 2013-09-23 0intro vtfree(u);
39 6f4d00ee 2013-09-23 0intro deCleanup(&de);
42 4b576658 2013-09-23 0intro vtfree(u);
44 6f4d00ee 2013-09-23 0intro if(groupMember(de.gid, fid->uname) && ((perm<<3) & de.mode)){
45 6f4d00ee 2013-09-23 0intro deCleanup(&de);
49 6f4d00ee 2013-09-23 0intro if(perm & de.mode){
50 6f4d00ee 2013-09-23 0intro if(perm == PermX && (de.mode & ModeDir)){
51 6f4d00ee 2013-09-23 0intro deCleanup(&de);
54 6f4d00ee 2013-09-23 0intro if(!groupMember(uidnoworld, fid->uname)){
55 6f4d00ee 2013-09-23 0intro deCleanup(&de);
59 6f4d00ee 2013-09-23 0intro if(fsysNoPermCheck(fid->fsys) || (fid->con->flags&ConNoPermCheck)){
60 6f4d00ee 2013-09-23 0intro deCleanup(&de);
63 4b576658 2013-09-23 0intro werrstr(EPermission);
65 6f4d00ee 2013-09-23 0intro deCleanup(&de);
69 6f4d00ee 2013-09-23 0intro static int
70 6f4d00ee 2013-09-23 0intro permFid(Fid* fid, int p)
72 6f4d00ee 2013-09-23 0intro return permFile(fid->file, fid, p);
75 6f4d00ee 2013-09-23 0intro static int
76 6f4d00ee 2013-09-23 0intro permParent(Fid* fid, int p)
79 6f4d00ee 2013-09-23 0intro File *parent;
81 6f4d00ee 2013-09-23 0intro parent = fileGetParent(fid->file);
82 6f4d00ee 2013-09-23 0intro r = permFile(parent, fid, p);
83 6f4d00ee 2013-09-23 0intro fileDecRef(parent);
89 6f4d00ee 2013-09-23 0intro validFileName(char* name)
93 6f4d00ee 2013-09-23 0intro if(name == nil || name[0] == '\0'){
94 4b576658 2013-09-23 0intro werrstr("no file name");
97 6f4d00ee 2013-09-23 0intro if(name[0] == '.'){
98 6f4d00ee 2013-09-23 0intro if(name[1] == '\0' || (name[1] == '.' && name[2] == '\0')){
99 4b576658 2013-09-23 0intro werrstr(". and .. illegal as file name");
100 6f4d00ee 2013-09-23 0intro return 0;
104 6f4d00ee 2013-09-23 0intro for(p = name; *p != '\0'; p++){
105 6f4d00ee 2013-09-23 0intro if((*p & 0xFF) < 040){
106 4b576658 2013-09-23 0intro werrstr("bad character in file name");
107 6f4d00ee 2013-09-23 0intro return 0;
111 6f4d00ee 2013-09-23 0intro return 1;
114 6f4d00ee 2013-09-23 0intro static int
115 6f4d00ee 2013-09-23 0intro rTwstat(Msg* m)
118 6f4d00ee 2013-09-23 0intro Fid *fid;
119 6f4d00ee 2013-09-23 0intro ulong mode, oldmode;
120 6f4d00ee 2013-09-23 0intro DirEntry de;
121 6f4d00ee 2013-09-23 0intro char *gid, *strs, *uid;
122 6f4d00ee 2013-09-23 0intro int gl, op, retval, tsync, wstatallow;
124 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
125 6f4d00ee 2013-09-23 0intro return 0;
127 6f4d00ee 2013-09-23 0intro gid = uid = nil;
128 6f4d00ee 2013-09-23 0intro retval = 0;
130 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, unamenone) == 0 || (fid->qid.type & QTAUTH)){
131 4b576658 2013-09-23 0intro werrstr(EPermission);
132 6f4d00ee 2013-09-23 0intro goto error0;
134 6f4d00ee 2013-09-23 0intro if(fileIsRoFs(fid->file) || !groupWriteMember(fid->uname)){
135 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
136 6f4d00ee 2013-09-23 0intro goto error0;
139 6f4d00ee 2013-09-23 0intro if(!fileGetDir(fid->file, &de))
140 6f4d00ee 2013-09-23 0intro goto error0;
142 4b576658 2013-09-23 0intro strs = vtmalloc(m->t.nstat);
143 6f4d00ee 2013-09-23 0intro if(convM2D(m->t.stat, m->t.nstat, &dir, strs) == 0){
144 4b576658 2013-09-23 0intro werrstr("wstat -- protocol botch");
145 6f4d00ee 2013-09-23 0intro goto error;
149 6f4d00ee 2013-09-23 0intro * Run through each of the (sub-)fields in the provided Dir
150 6f4d00ee 2013-09-23 0intro * checking for validity and whether it's a default:
151 6f4d00ee 2013-09-23 0intro * .type, .dev and .atime are completely ignored and not checked;
152 6f4d00ee 2013-09-23 0intro * .qid.path, .qid.vers and .muid are checked for validity but
153 6f4d00ee 2013-09-23 0intro * any attempt to change them is an error.
154 6f4d00ee 2013-09-23 0intro * .qid.type/.mode, .mtime, .name, .length, .uid and .gid can
155 6f4d00ee 2013-09-23 0intro * possibly be changed.
157 6f4d00ee 2013-09-23 0intro * 'Op' flags there are changed fields, i.e. it's not a no-op.
158 6f4d00ee 2013-09-23 0intro * 'Tsync' flags all fields are defaulted.
160 6f4d00ee 2013-09-23 0intro tsync = 1;
161 6f4d00ee 2013-09-23 0intro if(dir.qid.path != ~0){
162 6f4d00ee 2013-09-23 0intro if(dir.qid.path != de.qid){
163 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change qid.path");
164 6f4d00ee 2013-09-23 0intro goto error;
166 6f4d00ee 2013-09-23 0intro tsync = 0;
168 3fcc209d 2013-09-26 0intro if(dir.qid.vers != (u32int)~0){
169 6f4d00ee 2013-09-23 0intro if(dir.qid.vers != de.mcount){
170 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change qid.vers");
171 6f4d00ee 2013-09-23 0intro goto error;
173 6f4d00ee 2013-09-23 0intro tsync = 0;
175 6f4d00ee 2013-09-23 0intro if(dir.muid != nil && *dir.muid != '\0'){
176 6f4d00ee 2013-09-23 0intro if((uid = uidByUname(dir.muid)) == nil){
177 4b576658 2013-09-23 0intro werrstr("wstat -- unknown muid");
178 6f4d00ee 2013-09-23 0intro goto error;
180 6f4d00ee 2013-09-23 0intro if(strcmp(uid, de.mid) != 0){
181 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change muid");
182 6f4d00ee 2013-09-23 0intro goto error;
184 4b576658 2013-09-23 0intro vtfree(uid);
185 6f4d00ee 2013-09-23 0intro uid = nil;
186 6f4d00ee 2013-09-23 0intro tsync = 0;
190 6f4d00ee 2013-09-23 0intro * Check .qid.type and .mode agree if neither is defaulted.
192 3fcc209d 2013-09-26 0intro if(dir.qid.type != (uchar)~0 && dir.mode != (u32int)~0){
193 6f4d00ee 2013-09-23 0intro if(dir.qid.type != ((dir.mode>>24) & 0xFF)){
194 4b576658 2013-09-23 0intro werrstr("wstat -- qid.type/mode mismatch");
195 6f4d00ee 2013-09-23 0intro goto error;
201 6f4d00ee 2013-09-23 0intro oldmode = de.mode;
202 3fcc209d 2013-09-26 0intro if(dir.qid.type != (uchar)~0 || dir.mode != (u32int)~0){
204 6f4d00ee 2013-09-23 0intro * .qid.type or .mode isn't defaulted, check for unknown bits.
206 6f4d00ee 2013-09-23 0intro if(dir.mode == ~0)
207 6f4d00ee 2013-09-23 0intro dir.mode = (dir.qid.type<<24)|(de.mode & 0777);
208 6f4d00ee 2013-09-23 0intro if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
209 4b576658 2013-09-23 0intro werrstr("wstat -- unknown bits in qid.type/mode");
210 6f4d00ee 2013-09-23 0intro goto error;
214 6f4d00ee 2013-09-23 0intro * Synthesise a mode to check against the current settings.
216 6f4d00ee 2013-09-23 0intro mode = dir.mode & 0777;
217 6f4d00ee 2013-09-23 0intro if(dir.mode & DMEXCL)
218 6f4d00ee 2013-09-23 0intro mode |= ModeExclusive;
219 6f4d00ee 2013-09-23 0intro if(dir.mode & DMAPPEND)
220 6f4d00ee 2013-09-23 0intro mode |= ModeAppend;
221 6f4d00ee 2013-09-23 0intro if(dir.mode & DMDIR)
222 6f4d00ee 2013-09-23 0intro mode |= ModeDir;
223 6f4d00ee 2013-09-23 0intro if(dir.mode & DMTMP)
224 6f4d00ee 2013-09-23 0intro mode |= ModeTemporary;
226 6f4d00ee 2013-09-23 0intro if((de.mode^mode) & ModeDir){
227 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change directory bit");
228 6f4d00ee 2013-09-23 0intro goto error;
231 6f4d00ee 2013-09-23 0intro if((de.mode & (ModeAppend|ModeExclusive|ModeTemporary|0777)) != mode){
232 6f4d00ee 2013-09-23 0intro de.mode &= ~(ModeAppend|ModeExclusive|ModeTemporary|0777);
233 6f4d00ee 2013-09-23 0intro de.mode |= mode;
236 6f4d00ee 2013-09-23 0intro tsync = 0;
239 3fcc209d 2013-09-26 0intro if(dir.mtime != (u32int)~0){
240 6f4d00ee 2013-09-23 0intro if(dir.mtime != de.mtime){
241 6f4d00ee 2013-09-23 0intro de.mtime = dir.mtime;
244 6f4d00ee 2013-09-23 0intro tsync = 0;
247 6f4d00ee 2013-09-23 0intro if(dir.length != ~0){
248 6f4d00ee 2013-09-23 0intro if(dir.length != de.size){
250 6f4d00ee 2013-09-23 0intro * Cannot change length on append-only files.
251 6f4d00ee 2013-09-23 0intro * If we're changing the append bit, it's okay.
253 6f4d00ee 2013-09-23 0intro if(de.mode & oldmode & ModeAppend){
254 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change length of append-only file");
255 6f4d00ee 2013-09-23 0intro goto error;
257 6f4d00ee 2013-09-23 0intro if(de.mode & ModeDir){
258 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change length of directory");
259 6f4d00ee 2013-09-23 0intro goto error;
261 6f4d00ee 2013-09-23 0intro de.size = dir.length;
264 6f4d00ee 2013-09-23 0intro tsync = 0;
268 6f4d00ee 2013-09-23 0intro * Check for permission to change .mode, .mtime or .length,
269 6f4d00ee 2013-09-23 0intro * must be owner or leader of either group, for which test gid
270 6f4d00ee 2013-09-23 0intro * is needed; permission checks on gid will be done later.
272 6f4d00ee 2013-09-23 0intro if(dir.gid != nil && *dir.gid != '\0'){
273 6f4d00ee 2013-09-23 0intro if((gid = uidByUname(dir.gid)) == nil){
274 4b576658 2013-09-23 0intro werrstr("wstat -- unknown gid");
275 6f4d00ee 2013-09-23 0intro goto error;
277 6f4d00ee 2013-09-23 0intro tsync = 0;
280 4b576658 2013-09-23 0intro gid = vtstrdup(de.gid);
282 6f4d00ee 2013-09-23 0intro wstatallow = (fsysWstatAllow(fid->fsys) || (m->con->flags&ConWstatAllow));
285 6f4d00ee 2013-09-23 0intro * 'Gl' counts whether neither, one or both groups are led.
287 6f4d00ee 2013-09-23 0intro gl = groupLeader(gid, fid->uname) != 0;
288 6f4d00ee 2013-09-23 0intro gl += groupLeader(de.gid, fid->uname) != 0;
290 6f4d00ee 2013-09-23 0intro if(op && !wstatallow){
291 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uid, de.uid) != 0 && !gl){
292 4b576658 2013-09-23 0intro werrstr("wstat -- not owner or group leader");
293 6f4d00ee 2013-09-23 0intro goto error;
298 6f4d00ee 2013-09-23 0intro * Check for permission to change group, must be
299 6f4d00ee 2013-09-23 0intro * either owner and in new group or leader of both groups.
300 6f4d00ee 2013-09-23 0intro * If gid is nil here then
302 6f4d00ee 2013-09-23 0intro if(strcmp(gid, de.gid) != 0){
303 6f4d00ee 2013-09-23 0intro if(!wstatallow
304 6f4d00ee 2013-09-23 0intro && !(strcmp(fid->uid, de.uid) == 0 && groupMember(gid, fid->uname))
305 6f4d00ee 2013-09-23 0intro && !(gl == 2)){
306 4b576658 2013-09-23 0intro werrstr("wstat -- not owner and not group leaders");
307 6f4d00ee 2013-09-23 0intro goto error;
309 4b576658 2013-09-23 0intro vtfree(de.gid);
310 6f4d00ee 2013-09-23 0intro de.gid = gid;
311 6f4d00ee 2013-09-23 0intro gid = nil;
313 6f4d00ee 2013-09-23 0intro tsync = 0;
317 6f4d00ee 2013-09-23 0intro * Rename.
318 6f4d00ee 2013-09-23 0intro * Check .name is valid and different to the current.
319 6f4d00ee 2013-09-23 0intro * If so, check write permission in parent.
321 6f4d00ee 2013-09-23 0intro if(dir.name != nil && *dir.name != '\0'){
322 6f4d00ee 2013-09-23 0intro if(!validFileName(dir.name))
323 6f4d00ee 2013-09-23 0intro goto error;
324 6f4d00ee 2013-09-23 0intro if(strcmp(dir.name, de.elem) != 0){
325 6f4d00ee 2013-09-23 0intro if(permParent(fid, PermW) <= 0)
326 6f4d00ee 2013-09-23 0intro goto error;
327 4b576658 2013-09-23 0intro vtfree(de.elem);
328 4b576658 2013-09-23 0intro de.elem = vtstrdup(dir.name);
331 6f4d00ee 2013-09-23 0intro tsync = 0;
335 6f4d00ee 2013-09-23 0intro * Check for permission to change owner - must be god.
337 6f4d00ee 2013-09-23 0intro if(dir.uid != nil && *dir.uid != '\0'){
338 6f4d00ee 2013-09-23 0intro if((uid = uidByUname(dir.uid)) == nil){
339 4b576658 2013-09-23 0intro werrstr("wstat -- unknown uid");
340 6f4d00ee 2013-09-23 0intro goto error;
342 6f4d00ee 2013-09-23 0intro if(strcmp(uid, de.uid) != 0){
343 6f4d00ee 2013-09-23 0intro if(!wstatallow){
344 4b576658 2013-09-23 0intro werrstr("wstat -- not owner");
345 6f4d00ee 2013-09-23 0intro goto error;
347 6f4d00ee 2013-09-23 0intro if(strcmp(uid, uidnoworld) == 0){
348 4b576658 2013-09-23 0intro werrstr(EPermission);
349 6f4d00ee 2013-09-23 0intro goto error;
351 4b576658 2013-09-23 0intro vtfree(de.uid);
352 6f4d00ee 2013-09-23 0intro de.uid = uid;
353 6f4d00ee 2013-09-23 0intro uid = nil;
356 6f4d00ee 2013-09-23 0intro tsync = 0;
360 6f4d00ee 2013-09-23 0intro retval = fileSetDir(fid->file, &de, fid->uid);
362 6f4d00ee 2013-09-23 0intro retval = 1;
364 6f4d00ee 2013-09-23 0intro if(tsync){
366 6f4d00ee 2013-09-23 0intro * All values were defaulted,
367 6f4d00ee 2013-09-23 0intro * make the state of the file exactly what it
368 6f4d00ee 2013-09-23 0intro * claims to be before returning...
370 6f4d00ee 2013-09-23 0intro USED(tsync);
374 6f4d00ee 2013-09-23 0intro deCleanup(&de);
375 4b576658 2013-09-23 0intro vtfree(strs);
376 6f4d00ee 2013-09-23 0intro if(gid != nil)
377 4b576658 2013-09-23 0intro vtfree(gid);
378 6f4d00ee 2013-09-23 0intro if(uid != nil)
379 4b576658 2013-09-23 0intro vtfree(uid);
381 6f4d00ee 2013-09-23 0intro fidPut(fid);
382 6f4d00ee 2013-09-23 0intro return retval;
385 6f4d00ee 2013-09-23 0intro static int
386 6f4d00ee 2013-09-23 0intro rTstat(Msg* m)
389 6f4d00ee 2013-09-23 0intro Fid *fid;
390 6f4d00ee 2013-09-23 0intro DirEntry de;
392 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
393 6f4d00ee 2013-09-23 0intro return 0;
394 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTAUTH){
395 6f4d00ee 2013-09-23 0intro memset(&dir, 0, sizeof(Dir));
396 6f4d00ee 2013-09-23 0intro dir.qid = fid->qid;
397 6f4d00ee 2013-09-23 0intro dir.mode = DMAUTH;
398 6f4d00ee 2013-09-23 0intro dir.atime = time(0L);
399 6f4d00ee 2013-09-23 0intro dir.mtime = dir.atime;
400 6f4d00ee 2013-09-23 0intro dir.length = 0;
401 6f4d00ee 2013-09-23 0intro dir.name = "#¿";
402 6f4d00ee 2013-09-23 0intro dir.uid = fid->uname;
403 6f4d00ee 2013-09-23 0intro dir.gid = fid->uname;
404 6f4d00ee 2013-09-23 0intro dir.muid = fid->uname;
406 6f4d00ee 2013-09-23 0intro if((m->r.nstat = convD2M(&dir, m->data, m->con->msize)) == 0){
407 4b576658 2013-09-23 0intro werrstr("stat QTAUTH botch");
408 6f4d00ee 2013-09-23 0intro fidPut(fid);
409 6f4d00ee 2013-09-23 0intro return 0;
411 6f4d00ee 2013-09-23 0intro m->r.stat = m->data;
413 6f4d00ee 2013-09-23 0intro fidPut(fid);
414 6f4d00ee 2013-09-23 0intro return 1;
416 6f4d00ee 2013-09-23 0intro if(!fileGetDir(fid->file, &de)){
417 6f4d00ee 2013-09-23 0intro fidPut(fid);
418 6f4d00ee 2013-09-23 0intro return 0;
420 6f4d00ee 2013-09-23 0intro fidPut(fid);
423 6f4d00ee 2013-09-23 0intro * TODO: optimise this copy (in convS2M) away somehow.
424 6f4d00ee 2013-09-23 0intro * This pettifoggery with m->data will do for the moment.
426 6f4d00ee 2013-09-23 0intro m->r.nstat = dirDe2M(&de, m->data, m->con->msize);
427 6f4d00ee 2013-09-23 0intro m->r.stat = m->data;
428 6f4d00ee 2013-09-23 0intro deCleanup(&de);
430 6f4d00ee 2013-09-23 0intro return 1;
433 6f4d00ee 2013-09-23 0intro static int
434 6f4d00ee 2013-09-23 0intro _rTclunk(Fid* fid, int remove)
438 6f4d00ee 2013-09-23 0intro if(fid->excl)
439 6f4d00ee 2013-09-23 0intro exclFree(fid);
442 6f4d00ee 2013-09-23 0intro if(remove && !(fid->qid.type & QTAUTH)){
443 6f4d00ee 2013-09-23 0intro if((rok = permParent(fid, PermW)) > 0)
444 6f4d00ee 2013-09-23 0intro rok = fileRemove(fid->file, fid->uid);
446 6f4d00ee 2013-09-23 0intro fidClunk(fid);
448 6f4d00ee 2013-09-23 0intro return rok;
451 6f4d00ee 2013-09-23 0intro static int
452 6f4d00ee 2013-09-23 0intro rTremove(Msg* m)
454 6f4d00ee 2013-09-23 0intro Fid *fid;
456 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
457 6f4d00ee 2013-09-23 0intro return 0;
458 6f4d00ee 2013-09-23 0intro return _rTclunk(fid, 1);
461 6f4d00ee 2013-09-23 0intro static int
462 6f4d00ee 2013-09-23 0intro rTclunk(Msg* m)
464 6f4d00ee 2013-09-23 0intro Fid *fid;
466 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
467 6f4d00ee 2013-09-23 0intro return 0;
468 6f4d00ee 2013-09-23 0intro _rTclunk(fid, (fid->open & FidORclose));
470 6f4d00ee 2013-09-23 0intro return 1;
473 6f4d00ee 2013-09-23 0intro static int
474 6f4d00ee 2013-09-23 0intro rTwrite(Msg* m)
476 6f4d00ee 2013-09-23 0intro Fid *fid;
477 6f4d00ee 2013-09-23 0intro int count, n;
479 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
480 6f4d00ee 2013-09-23 0intro return 0;
481 6f4d00ee 2013-09-23 0intro if(!(fid->open & FidOWrite)){
482 4b576658 2013-09-23 0intro werrstr("fid not open for write");
483 6f4d00ee 2013-09-23 0intro goto error;
486 6f4d00ee 2013-09-23 0intro count = m->t.count;
487 6f4d00ee 2013-09-23 0intro if(count < 0 || count > m->con->msize-IOHDRSZ){
488 4b576658 2013-09-23 0intro werrstr("write count too big");
489 6f4d00ee 2013-09-23 0intro goto error;
491 6f4d00ee 2013-09-23 0intro if(m->t.offset < 0){
492 4b576658 2013-09-23 0intro werrstr("write offset negative");
493 6f4d00ee 2013-09-23 0intro goto error;
495 6f4d00ee 2013-09-23 0intro if(fid->excl != nil && !exclUpdate(fid))
496 6f4d00ee 2013-09-23 0intro goto error;
498 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTDIR){
499 4b576658 2013-09-23 0intro werrstr("is a directory");
500 6f4d00ee 2013-09-23 0intro goto error;
502 6f4d00ee 2013-09-23 0intro else if(fid->qid.type & QTAUTH)
503 6f4d00ee 2013-09-23 0intro n = authWrite(fid, m->t.data, count);
505 6f4d00ee 2013-09-23 0intro n = fileWrite(fid->file, m->t.data, count, m->t.offset, fid->uid);
506 6f4d00ee 2013-09-23 0intro if(n < 0)
507 6f4d00ee 2013-09-23 0intro goto error;
510 6f4d00ee 2013-09-23 0intro m->r.count = n;
512 6f4d00ee 2013-09-23 0intro fidPut(fid);
513 6f4d00ee 2013-09-23 0intro return 1;
516 6f4d00ee 2013-09-23 0intro fidPut(fid);
517 6f4d00ee 2013-09-23 0intro return 0;
520 6f4d00ee 2013-09-23 0intro static int
521 6f4d00ee 2013-09-23 0intro rTread(Msg* m)
523 6f4d00ee 2013-09-23 0intro Fid *fid;
524 6f4d00ee 2013-09-23 0intro uchar *data;
525 6f4d00ee 2013-09-23 0intro int count, n;
527 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
528 6f4d00ee 2013-09-23 0intro return 0;
529 6f4d00ee 2013-09-23 0intro if(!(fid->open & FidORead)){
530 4b576658 2013-09-23 0intro werrstr("fid not open for read");
531 6f4d00ee 2013-09-23 0intro goto error;
534 6f4d00ee 2013-09-23 0intro count = m->t.count;
535 6f4d00ee 2013-09-23 0intro if(count < 0 || count > m->con->msize-IOHDRSZ){
536 4b576658 2013-09-23 0intro werrstr("read count too big");
537 6f4d00ee 2013-09-23 0intro goto error;
539 6f4d00ee 2013-09-23 0intro if(m->t.offset < 0){
540 4b576658 2013-09-23 0intro werrstr("read offset negative");
541 6f4d00ee 2013-09-23 0intro goto error;
543 6f4d00ee 2013-09-23 0intro if(fid->excl != nil && !exclUpdate(fid))
544 6f4d00ee 2013-09-23 0intro goto error;
547 6f4d00ee 2013-09-23 0intro * TODO: optimise this copy (in convS2M) away somehow.
548 6f4d00ee 2013-09-23 0intro * This pettifoggery with m->data will do for the moment.
550 6f4d00ee 2013-09-23 0intro data = m->data+IOHDRSZ;
551 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTDIR)
552 6f4d00ee 2013-09-23 0intro n = dirRead(fid, data, count, m->t.offset);
553 6f4d00ee 2013-09-23 0intro else if(fid->qid.type & QTAUTH)
554 6f4d00ee 2013-09-23 0intro n = authRead(fid, data, count);
556 6f4d00ee 2013-09-23 0intro n = fileRead(fid->file, data, count, m->t.offset);
557 6f4d00ee 2013-09-23 0intro if(n < 0)
558 6f4d00ee 2013-09-23 0intro goto error;
560 6f4d00ee 2013-09-23 0intro m->r.count = n;
561 6f4d00ee 2013-09-23 0intro m->r.data = (char*)data;
563 6f4d00ee 2013-09-23 0intro fidPut(fid);
564 6f4d00ee 2013-09-23 0intro return 1;
567 6f4d00ee 2013-09-23 0intro fidPut(fid);
568 6f4d00ee 2013-09-23 0intro return 0;
571 6f4d00ee 2013-09-23 0intro static int
572 6f4d00ee 2013-09-23 0intro rTcreate(Msg* m)
574 6f4d00ee 2013-09-23 0intro Fid *fid;
575 6f4d00ee 2013-09-23 0intro File *file;
576 6f4d00ee 2013-09-23 0intro ulong mode;
577 6f4d00ee 2013-09-23 0intro int omode, open, perm;
579 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
580 6f4d00ee 2013-09-23 0intro return 0;
581 6f4d00ee 2013-09-23 0intro if(fid->open){
582 4b576658 2013-09-23 0intro werrstr("fid open for I/O");
583 6f4d00ee 2013-09-23 0intro goto error;
585 6f4d00ee 2013-09-23 0intro if(fileIsRoFs(fid->file) || !groupWriteMember(fid->uname)){
586 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
587 6f4d00ee 2013-09-23 0intro goto error;
589 6f4d00ee 2013-09-23 0intro if(!fileIsDir(fid->file)){
590 4b576658 2013-09-23 0intro werrstr("not a directory");
591 6f4d00ee 2013-09-23 0intro goto error;
593 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermW) <= 0)
594 6f4d00ee 2013-09-23 0intro goto error;
595 6f4d00ee 2013-09-23 0intro if(!validFileName(m->t.name))
596 6f4d00ee 2013-09-23 0intro goto error;
597 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uid, uidnoworld) == 0){
598 4b576658 2013-09-23 0intro werrstr(EPermission);
599 6f4d00ee 2013-09-23 0intro goto error;
602 6f4d00ee 2013-09-23 0intro omode = m->t.mode & OMODE;
603 6f4d00ee 2013-09-23 0intro open = 0;
605 6f4d00ee 2013-09-23 0intro if(omode == OREAD || omode == ORDWR || omode == OEXEC)
606 6f4d00ee 2013-09-23 0intro open |= FidORead;
607 6f4d00ee 2013-09-23 0intro if(omode == OWRITE || omode == ORDWR)
608 6f4d00ee 2013-09-23 0intro open |= FidOWrite;
609 6f4d00ee 2013-09-23 0intro if((open & (FidOWrite|FidORead)) == 0){
610 4b576658 2013-09-23 0intro werrstr("unknown mode");
611 6f4d00ee 2013-09-23 0intro goto error;
613 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR){
614 6f4d00ee 2013-09-23 0intro if((m->t.mode & (ORCLOSE|OTRUNC)) || (open & FidOWrite)){
615 4b576658 2013-09-23 0intro werrstr("illegal mode");
616 6f4d00ee 2013-09-23 0intro goto error;
618 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMAPPEND){
619 4b576658 2013-09-23 0intro werrstr("illegal perm");
620 6f4d00ee 2013-09-23 0intro goto error;
624 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
625 6f4d00ee 2013-09-23 0intro perm = m->t.perm;
626 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR)
627 6f4d00ee 2013-09-23 0intro perm &= ~0777|(mode & 0777);
629 6f4d00ee 2013-09-23 0intro perm &= ~0666|(mode & 0666);
630 6f4d00ee 2013-09-23 0intro mode = perm & 0777;
631 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR)
632 6f4d00ee 2013-09-23 0intro mode |= ModeDir;
633 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMAPPEND)
634 6f4d00ee 2013-09-23 0intro mode |= ModeAppend;
635 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMEXCL)
636 6f4d00ee 2013-09-23 0intro mode |= ModeExclusive;
637 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMTMP)
638 6f4d00ee 2013-09-23 0intro mode |= ModeTemporary;
640 6f4d00ee 2013-09-23 0intro if((file = fileCreate(fid->file, m->t.name, mode, fid->uid)) == nil){
641 6f4d00ee 2013-09-23 0intro fidPut(fid);
642 6f4d00ee 2013-09-23 0intro return 0;
644 6f4d00ee 2013-09-23 0intro fileDecRef(fid->file);
646 6f4d00ee 2013-09-23 0intro fid->qid.vers = fileGetMcount(file);
647 6f4d00ee 2013-09-23 0intro fid->qid.path = fileGetId(file);
648 6f4d00ee 2013-09-23 0intro fid->file = file;
649 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
650 6f4d00ee 2013-09-23 0intro if(mode & ModeDir)
651 6f4d00ee 2013-09-23 0intro fid->qid.type = QTDIR;
653 6f4d00ee 2013-09-23 0intro fid->qid.type = QTFILE;
654 6f4d00ee 2013-09-23 0intro if(mode & ModeAppend)
655 6f4d00ee 2013-09-23 0intro fid->qid.type |= QTAPPEND;
656 6f4d00ee 2013-09-23 0intro if(mode & ModeExclusive){
657 6f4d00ee 2013-09-23 0intro fid->qid.type |= QTEXCL;
658 6f4d00ee 2013-09-23 0intro assert(exclAlloc(fid) != 0);
660 6f4d00ee 2013-09-23 0intro if(m->t.mode & ORCLOSE)
661 6f4d00ee 2013-09-23 0intro open |= FidORclose;
662 6f4d00ee 2013-09-23 0intro fid->open = open;
664 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
665 6f4d00ee 2013-09-23 0intro m->r.iounit = m->con->msize-IOHDRSZ;
667 6f4d00ee 2013-09-23 0intro fidPut(fid);
668 6f4d00ee 2013-09-23 0intro return 1;
671 6f4d00ee 2013-09-23 0intro fidPut(fid);
672 6f4d00ee 2013-09-23 0intro return 0;
675 6f4d00ee 2013-09-23 0intro static int
676 6f4d00ee 2013-09-23 0intro rTopen(Msg* m)
678 6f4d00ee 2013-09-23 0intro Fid *fid;
679 6f4d00ee 2013-09-23 0intro int isdir, mode, omode, open, rofs;
681 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
682 6f4d00ee 2013-09-23 0intro return 0;
683 6f4d00ee 2013-09-23 0intro if(fid->open){
684 4b576658 2013-09-23 0intro werrstr("fid open for I/O");
685 6f4d00ee 2013-09-23 0intro goto error;
688 6f4d00ee 2013-09-23 0intro isdir = fileIsDir(fid->file);
689 6f4d00ee 2013-09-23 0intro open = 0;
690 6f4d00ee 2013-09-23 0intro rofs = fileIsRoFs(fid->file) || !groupWriteMember(fid->uname);
692 6f4d00ee 2013-09-23 0intro if(m->t.mode & ORCLOSE){
693 6f4d00ee 2013-09-23 0intro if(isdir){
694 4b576658 2013-09-23 0intro werrstr("is a directory");
695 6f4d00ee 2013-09-23 0intro goto error;
697 6f4d00ee 2013-09-23 0intro if(rofs){
698 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
699 6f4d00ee 2013-09-23 0intro goto error;
701 6f4d00ee 2013-09-23 0intro if(permParent(fid, PermW) <= 0)
702 6f4d00ee 2013-09-23 0intro goto error;
704 6f4d00ee 2013-09-23 0intro open |= FidORclose;
707 6f4d00ee 2013-09-23 0intro omode = m->t.mode & OMODE;
708 6f4d00ee 2013-09-23 0intro if(omode == OREAD || omode == ORDWR){
709 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermR) <= 0)
710 6f4d00ee 2013-09-23 0intro goto error;
711 6f4d00ee 2013-09-23 0intro open |= FidORead;
713 6f4d00ee 2013-09-23 0intro if(omode == OWRITE || omode == ORDWR || (m->t.mode & OTRUNC)){
714 6f4d00ee 2013-09-23 0intro if(isdir){
715 4b576658 2013-09-23 0intro werrstr("is a directory");
716 6f4d00ee 2013-09-23 0intro goto error;
718 6f4d00ee 2013-09-23 0intro if(rofs){
719 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
720 6f4d00ee 2013-09-23 0intro goto error;
722 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermW) <= 0)
723 6f4d00ee 2013-09-23 0intro goto error;
724 6f4d00ee 2013-09-23 0intro open |= FidOWrite;
726 6f4d00ee 2013-09-23 0intro if(omode == OEXEC){
727 6f4d00ee 2013-09-23 0intro if(isdir){
728 4b576658 2013-09-23 0intro werrstr("is a directory");
729 6f4d00ee 2013-09-23 0intro goto error;
731 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermX) <= 0)
732 6f4d00ee 2013-09-23 0intro goto error;
733 6f4d00ee 2013-09-23 0intro open |= FidORead;
735 6f4d00ee 2013-09-23 0intro if((open & (FidOWrite|FidORead)) == 0){
736 4b576658 2013-09-23 0intro werrstr("unknown mode");
737 6f4d00ee 2013-09-23 0intro goto error;
740 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
741 6f4d00ee 2013-09-23 0intro if((mode & ModeExclusive) && exclAlloc(fid) == 0)
742 6f4d00ee 2013-09-23 0intro goto error;
745 6f4d00ee 2013-09-23 0intro * Everything checks out, try to commit any changes.
747 6f4d00ee 2013-09-23 0intro if((m->t.mode & OTRUNC) && !(mode & ModeAppend))
748 6f4d00ee 2013-09-23 0intro if(!fileTruncate(fid->file, fid->uid))
749 6f4d00ee 2013-09-23 0intro goto error;
751 6f4d00ee 2013-09-23 0intro if(isdir && fid->db != nil){
752 6f4d00ee 2013-09-23 0intro dirBufFree(fid->db);
753 6f4d00ee 2013-09-23 0intro fid->db = nil;
756 6f4d00ee 2013-09-23 0intro fid->qid.vers = fileGetMcount(fid->file);
757 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
758 6f4d00ee 2013-09-23 0intro m->r.iounit = m->con->msize-IOHDRSZ;
760 6f4d00ee 2013-09-23 0intro fid->open = open;
762 6f4d00ee 2013-09-23 0intro fidPut(fid);
763 6f4d00ee 2013-09-23 0intro return 1;
766 6f4d00ee 2013-09-23 0intro if(fid->excl != nil)
767 6f4d00ee 2013-09-23 0intro exclFree(fid);
768 6f4d00ee 2013-09-23 0intro fidPut(fid);
769 6f4d00ee 2013-09-23 0intro return 0;
772 6f4d00ee 2013-09-23 0intro static int
773 6f4d00ee 2013-09-23 0intro rTwalk(Msg* m)
776 6f4d00ee 2013-09-23 0intro Fcall *r, *t;
777 6f4d00ee 2013-09-23 0intro int nwname, wlock;
778 6f4d00ee 2013-09-23 0intro File *file, *nfile;
779 6f4d00ee 2013-09-23 0intro Fid *fid, *ofid, *nfid;
781 6f4d00ee 2013-09-23 0intro t = &m->t;
782 6f4d00ee 2013-09-23 0intro if(t->fid == t->newfid)
783 6f4d00ee 2013-09-23 0intro wlock = FidFWlock;
785 6f4d00ee 2013-09-23 0intro wlock = 0;
788 6f4d00ee 2013-09-23 0intro * The file identified by t->fid must be valid in the
789 6f4d00ee 2013-09-23 0intro * current session and must not have been opened for I/O
790 6f4d00ee 2013-09-23 0intro * by an open or create message.
792 6f4d00ee 2013-09-23 0intro if((ofid = fidGet(m->con, t->fid, wlock)) == nil)
793 6f4d00ee 2013-09-23 0intro return 0;
794 6f4d00ee 2013-09-23 0intro if(ofid->open){
795 4b576658 2013-09-23 0intro werrstr("file open for I/O");
796 6f4d00ee 2013-09-23 0intro fidPut(ofid);
797 6f4d00ee 2013-09-23 0intro return 0;
801 6f4d00ee 2013-09-23 0intro * If newfid is not the same as fid, allocate a new file;
802 6f4d00ee 2013-09-23 0intro * a side effect is checking newfid is not already in use (error);
803 6f4d00ee 2013-09-23 0intro * if there are no names to walk this will be equivalent to a
804 6f4d00ee 2013-09-23 0intro * simple 'clone' operation.
805 6f4d00ee 2013-09-23 0intro * It's a no-op if newfid is the same as fid and t->nwname is 0.
807 6f4d00ee 2013-09-23 0intro nfid = nil;
808 6f4d00ee 2013-09-23 0intro if(t->fid != t->newfid){
809 6f4d00ee 2013-09-23 0intro nfid = fidGet(m->con, t->newfid, FidFWlock|FidFCreate);
810 6f4d00ee 2013-09-23 0intro if(nfid == nil){
811 4b576658 2013-09-23 0intro werrstr("%s: walk: newfid 0x%ud in use",
812 6f4d00ee 2013-09-23 0intro argv0, t->newfid);
813 6f4d00ee 2013-09-23 0intro fidPut(ofid);
814 6f4d00ee 2013-09-23 0intro return 0;
816 6f4d00ee 2013-09-23 0intro nfid->open = ofid->open & ~FidORclose;
817 6f4d00ee 2013-09-23 0intro nfid->file = fileIncRef(ofid->file);
818 6f4d00ee 2013-09-23 0intro nfid->qid = ofid->qid;
819 4b576658 2013-09-23 0intro nfid->uid = vtstrdup(ofid->uid);
820 4b576658 2013-09-23 0intro nfid->uname = vtstrdup(ofid->uname);
821 6f4d00ee 2013-09-23 0intro nfid->fsys = fsysIncRef(ofid->fsys);
822 6f4d00ee 2013-09-23 0intro fid = nfid;
825 6f4d00ee 2013-09-23 0intro fid = ofid;
827 6f4d00ee 2013-09-23 0intro r = &m->r;
828 6f4d00ee 2013-09-23 0intro r->nwqid = 0;
830 6f4d00ee 2013-09-23 0intro if(t->nwname == 0){
831 6f4d00ee 2013-09-23 0intro if(nfid != nil)
832 6f4d00ee 2013-09-23 0intro fidPut(nfid);
833 6f4d00ee 2013-09-23 0intro fidPut(ofid);
835 6f4d00ee 2013-09-23 0intro return 1;
838 6f4d00ee 2013-09-23 0intro file = fid->file;
839 6f4d00ee 2013-09-23 0intro fileIncRef(file);
840 6f4d00ee 2013-09-23 0intro qid = fid->qid;
842 6f4d00ee 2013-09-23 0intro for(nwname = 0; nwname < t->nwname; nwname++){
844 6f4d00ee 2013-09-23 0intro * Walked elements must represent a directory and
845 6f4d00ee 2013-09-23 0intro * the implied user must have permission to search
846 6f4d00ee 2013-09-23 0intro * the directory. Walking .. is always allowed, so that
847 6f4d00ee 2013-09-23 0intro * you can't walk into a directory and then not be able
848 6f4d00ee 2013-09-23 0intro * to walk out of it.
850 6f4d00ee 2013-09-23 0intro if(!(qid.type & QTDIR)){
851 4b576658 2013-09-23 0intro werrstr("not a directory");
854 6f4d00ee 2013-09-23 0intro switch(permFile(file, fid, PermX)){
858 6f4d00ee 2013-09-23 0intro if(strcmp(t->wname[nwname], "..") == 0)
861 6f4d00ee 2013-09-23 0intro goto Out;
863 6f4d00ee 2013-09-23 0intro if((nfile = fileWalk(file, t->wname[nwname])) == nil)
865 6f4d00ee 2013-09-23 0intro fileDecRef(file);
866 6f4d00ee 2013-09-23 0intro file = nfile;
867 6f4d00ee 2013-09-23 0intro qid.type = QTFILE;
868 6f4d00ee 2013-09-23 0intro if(fileIsDir(file))
869 6f4d00ee 2013-09-23 0intro qid.type = QTDIR;
870 6f4d00ee 2013-09-23 0intro if(fileIsAppend(file))
871 6f4d00ee 2013-09-23 0intro qid.type |= QTAPPEND;
872 6f4d00ee 2013-09-23 0intro if(fileIsTemporary(file))
873 6f4d00ee 2013-09-23 0intro qid.type |= QTTMP;
874 6f4d00ee 2013-09-23 0intro if(fileIsExclusive(file))
875 6f4d00ee 2013-09-23 0intro qid.type |= QTEXCL;
876 6f4d00ee 2013-09-23 0intro qid.vers = fileGetMcount(file);
877 6f4d00ee 2013-09-23 0intro qid.path = fileGetId(file);
878 6f4d00ee 2013-09-23 0intro r->wqid[r->nwqid++] = qid;
881 6f4d00ee 2013-09-23 0intro if(nwname == t->nwname){
883 6f4d00ee 2013-09-23 0intro * Walked all elements. Update the target fid
884 6f4d00ee 2013-09-23 0intro * from the temporary qid used during the walk,
885 6f4d00ee 2013-09-23 0intro * and tidy up.
887 6f4d00ee 2013-09-23 0intro fid->qid = r->wqid[r->nwqid-1];
888 6f4d00ee 2013-09-23 0intro fileDecRef(fid->file);
889 6f4d00ee 2013-09-23 0intro fid->file = file;
891 6f4d00ee 2013-09-23 0intro if(nfid != nil)
892 6f4d00ee 2013-09-23 0intro fidPut(nfid);
894 6f4d00ee 2013-09-23 0intro fidPut(ofid);
895 6f4d00ee 2013-09-23 0intro return 1;
900 6f4d00ee 2013-09-23 0intro * Didn't walk all elements, 'clunk' nfid if it exists
901 6f4d00ee 2013-09-23 0intro * and leave fid untouched.
902 6f4d00ee 2013-09-23 0intro * It's not an error if some of the elements were walked OK.
904 6f4d00ee 2013-09-23 0intro fileDecRef(file);
905 6f4d00ee 2013-09-23 0intro if(nfid != nil)
906 6f4d00ee 2013-09-23 0intro fidClunk(nfid);
908 6f4d00ee 2013-09-23 0intro fidPut(ofid);
909 6f4d00ee 2013-09-23 0intro if(nwname == 0)
910 6f4d00ee 2013-09-23 0intro return 0;
911 6f4d00ee 2013-09-23 0intro return 1;
914 6f4d00ee 2013-09-23 0intro static int
915 6f4d00ee 2013-09-23 0intro rTflush(Msg* m)
917 6f4d00ee 2013-09-23 0intro if(m->t.oldtag != NOTAG)
918 6f4d00ee 2013-09-23 0intro msgFlush(m);
919 6f4d00ee 2013-09-23 0intro return 1;
922 6f4d00ee 2013-09-23 0intro static void
923 6f4d00ee 2013-09-23 0intro parseAname(char *aname, char **fsname, char **path)
927 6f4d00ee 2013-09-23 0intro if(aname && aname[0])
928 4b576658 2013-09-23 0intro s = vtstrdup(aname);
930 4b576658 2013-09-23 0intro s = vtstrdup("main/active");
931 6f4d00ee 2013-09-23 0intro *fsname = s;
932 6f4d00ee 2013-09-23 0intro if((*path = strchr(s, '/')) != nil)
933 6f4d00ee 2013-09-23 0intro *(*path)++ = '\0';
935 6f4d00ee 2013-09-23 0intro *path = "";
938 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
940 6f4d00ee 2013-09-23 0intro * Check remote IP address against /mnt/ipok.
941 6f4d00ee 2013-09-23 0intro * Sources.cs.bell-labs.com uses this to disallow
942 fa325e9b 2020-01-10 cross * network connections from Sudan, Libya, etc.,
943 6f4d00ee 2013-09-23 0intro * following U.S. cryptography export regulations.
945 6f4d00ee 2013-09-23 0intro static int
946 6f4d00ee 2013-09-23 0intro conIPCheck(Con* con)
948 6f4d00ee 2013-09-23 0intro char ok[256], *p;
951 6f4d00ee 2013-09-23 0intro if(con->flags&ConIPCheck){
952 6f4d00ee 2013-09-23 0intro if(con->remote[0] == 0){
953 4b576658 2013-09-23 0intro werrstr("cannot verify unknown remote address");
954 6f4d00ee 2013-09-23 0intro return 0;
956 6f4d00ee 2013-09-23 0intro if(access("/mnt/ipok/ok", AEXIST) < 0){
957 6f4d00ee 2013-09-23 0intro /* mount closes the fd on success */
958 fa325e9b 2020-01-10 cross if((fd = open("/srv/ipok", ORDWR)) >= 0
959 6f4d00ee 2013-09-23 0intro && mount(fd, -1, "/mnt/ipok", MREPL, "") < 0)
960 6f4d00ee 2013-09-23 0intro close(fd);
961 6f4d00ee 2013-09-23 0intro if(access("/mnt/ipok/ok", AEXIST) < 0){
962 4b576658 2013-09-23 0intro werrstr("cannot verify remote address");
963 6f4d00ee 2013-09-23 0intro return 0;
966 6f4d00ee 2013-09-23 0intro snprint(ok, sizeof ok, "/mnt/ipok/ok/%s", con->remote);
967 6f4d00ee 2013-09-23 0intro if((p = strchr(ok, '!')) != nil)
969 6f4d00ee 2013-09-23 0intro if(access(ok, AEXIST) < 0){
970 4b576658 2013-09-23 0intro werrstr("restricted remote address");
971 6f4d00ee 2013-09-23 0intro return 0;
974 6f4d00ee 2013-09-23 0intro return 1;
978 6f4d00ee 2013-09-23 0intro static int
979 6f4d00ee 2013-09-23 0intro rTattach(Msg* m)
981 6f4d00ee 2013-09-23 0intro Fid *fid;
982 6f4d00ee 2013-09-23 0intro Fsys *fsys;
983 6f4d00ee 2013-09-23 0intro char *fsname, *path;
985 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock|FidFCreate)) == nil)
986 6f4d00ee 2013-09-23 0intro return 0;
988 6f4d00ee 2013-09-23 0intro parseAname(m->t.aname, &fsname, &path);
989 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet(fsname)) == nil){
990 6f4d00ee 2013-09-23 0intro fidClunk(fid);
991 4b576658 2013-09-23 0intro vtfree(fsname);
992 6f4d00ee 2013-09-23 0intro return 0;
994 6f4d00ee 2013-09-23 0intro fid->fsys = fsys;
996 6f4d00ee 2013-09-23 0intro if(m->t.uname[0] != '\0')
997 4b576658 2013-09-23 0intro fid->uname = vtstrdup(m->t.uname);
999 4b576658 2013-09-23 0intro fid->uname = vtstrdup(unamenone);
1001 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1002 6f4d00ee 2013-09-23 0intro if((fid->con->flags&ConIPCheck) && !conIPCheck(fid->con)){
1003 4b576658 2013-09-23 0intro consPrint("reject %s from %s: %r\n", fid->uname, fid->con->remote);
1004 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1005 4b576658 2013-09-23 0intro vtfree(fsname);
1006 6f4d00ee 2013-09-23 0intro return 0;
1009 6f4d00ee 2013-09-23 0intro if(fsysNoAuthCheck(fsys) || (m->con->flags&ConNoAuthCheck)){
1010 6f4d00ee 2013-09-23 0intro if((fid->uid = uidByUname(fid->uname)) == nil)
1011 4b576658 2013-09-23 0intro fid->uid = vtstrdup(unamenone);
1013 6f4d00ee 2013-09-23 0intro else if(!authCheck(&m->t, fid, fsys)){
1014 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1015 4b576658 2013-09-23 0intro vtfree(fsname);
1016 6f4d00ee 2013-09-23 0intro return 0;
1019 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
1020 6f4d00ee 2013-09-23 0intro if((fid->file = fsysGetRoot(fsys, path)) == nil){
1021 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
1022 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1023 4b576658 2013-09-23 0intro vtfree(fsname);
1024 6f4d00ee 2013-09-23 0intro return 0;
1026 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
1027 4b576658 2013-09-23 0intro vtfree(fsname);
1029 6f4d00ee 2013-09-23 0intro fid->qid = (Qid){fileGetId(fid->file), 0, QTDIR};
1030 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
1032 6f4d00ee 2013-09-23 0intro fidPut(fid);
1033 6f4d00ee 2013-09-23 0intro return 1;
1036 6f4d00ee 2013-09-23 0intro static int
1037 6f4d00ee 2013-09-23 0intro rTauth(Msg* m)
1039 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1040 6f4d00ee 2013-09-23 0intro int afd;
1042 6f4d00ee 2013-09-23 0intro Con *con;
1043 6f4d00ee 2013-09-23 0intro Fid *afid;
1044 6f4d00ee 2013-09-23 0intro Fsys *fsys;
1045 6f4d00ee 2013-09-23 0intro char *fsname, *path;
1047 6f4d00ee 2013-09-23 0intro parseAname(m->t.aname, &fsname, &path);
1048 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet(fsname)) == nil){
1049 4b576658 2013-09-23 0intro vtfree(fsname);
1050 6f4d00ee 2013-09-23 0intro return 0;
1052 4b576658 2013-09-23 0intro vtfree(fsname);
1054 6f4d00ee 2013-09-23 0intro if(fsysNoAuthCheck(fsys) || (m->con->flags&ConNoAuthCheck)){
1055 6f4d00ee 2013-09-23 0intro m->con->aok = 1;
1056 4b576658 2013-09-23 0intro werrstr("authentication disabled");
1057 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1058 6f4d00ee 2013-09-23 0intro return 0;
1060 6f4d00ee 2013-09-23 0intro if(strcmp(m->t.uname, unamenone) == 0){
1061 4b576658 2013-09-23 0intro werrstr("user 'none' requires no authentication");
1062 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1063 6f4d00ee 2013-09-23 0intro return 0;
1066 6f4d00ee 2013-09-23 0intro con = m->con;
1067 6f4d00ee 2013-09-23 0intro if((afid = fidGet(con, m->t.afid, FidFWlock|FidFCreate)) == nil){
1068 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1069 6f4d00ee 2013-09-23 0intro return 0;
1071 6f4d00ee 2013-09-23 0intro afid->fsys = fsys;
1073 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1074 6f4d00ee 2013-09-23 0intro if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
1075 4b576658 2013-09-23 0intro werrstr("can't open \"/mnt/factotum/rpc\"");
1076 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1077 6f4d00ee 2013-09-23 0intro return 0;
1081 b32de4ae 2013-09-26 0intro #ifdef PLAN9PORT
1082 b32de4ae 2013-09-26 0intro if((afid->rpc = auth_allocrpc()) == nil){
1084 6f4d00ee 2013-09-23 0intro if((afid->rpc = auth_allocrpc(afd)) == nil){
1085 6f4d00ee 2013-09-23 0intro close(afd);
1087 4b576658 2013-09-23 0intro werrstr("can't auth_allocrpc");
1088 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1089 6f4d00ee 2013-09-23 0intro return 0;
1091 6f4d00ee 2013-09-23 0intro if(auth_rpc(afid->rpc, "start", "proto=p9any role=server", 23) != ARok){
1092 4b576658 2013-09-23 0intro werrstr("can't auth_rpc");
1093 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1094 6f4d00ee 2013-09-23 0intro return 0;
1097 6f4d00ee 2013-09-23 0intro afid->open = FidOWrite|FidORead;
1098 6f4d00ee 2013-09-23 0intro afid->qid.type = QTAUTH;
1099 6f4d00ee 2013-09-23 0intro afid->qid.path = m->t.afid;
1100 4b576658 2013-09-23 0intro afid->uname = vtstrdup(m->t.uname);
1102 6f4d00ee 2013-09-23 0intro m->r.qid = afid->qid;
1104 6f4d00ee 2013-09-23 0intro fidPut(afid);
1105 6f4d00ee 2013-09-23 0intro return 1;
1108 6f4d00ee 2013-09-23 0intro static int
1109 6f4d00ee 2013-09-23 0intro rTversion(Msg* m)
1112 6f4d00ee 2013-09-23 0intro Con *con;
1113 6f4d00ee 2013-09-23 0intro Fcall *r, *t;
1115 6f4d00ee 2013-09-23 0intro t = &m->t;
1116 6f4d00ee 2013-09-23 0intro r = &m->r;
1117 6f4d00ee 2013-09-23 0intro con = m->con;
1119 4b576658 2013-09-23 0intro qlock(&con->lock);
1120 6f4d00ee 2013-09-23 0intro if(con->state != ConInit){
1121 4b576658 2013-09-23 0intro qunlock(&con->lock);
1122 4b576658 2013-09-23 0intro werrstr("Tversion: down");
1123 6f4d00ee 2013-09-23 0intro return 0;
1125 6f4d00ee 2013-09-23 0intro con->state = ConNew;
1128 6f4d00ee 2013-09-23 0intro * Release the karma of past lives and suffering.
1129 6f4d00ee 2013-09-23 0intro * Should this be done before or after checking the
1130 6f4d00ee 2013-09-23 0intro * validity of the Tversion?
1132 6f4d00ee 2013-09-23 0intro fidClunkAll(con);
1134 6f4d00ee 2013-09-23 0intro if(t->tag != NOTAG){
1135 4b576658 2013-09-23 0intro qunlock(&con->lock);
1136 4b576658 2013-09-23 0intro werrstr("Tversion: invalid tag");
1137 6f4d00ee 2013-09-23 0intro return 0;
1140 6f4d00ee 2013-09-23 0intro if(t->msize < 256){
1141 4b576658 2013-09-23 0intro qunlock(&con->lock);
1142 4b576658 2013-09-23 0intro werrstr("Tversion: message size too small");
1143 6f4d00ee 2013-09-23 0intro return 0;
1145 6f4d00ee 2013-09-23 0intro if(t->msize < con->msize)
1146 6f4d00ee 2013-09-23 0intro r->msize = t->msize;
1148 6f4d00ee 2013-09-23 0intro r->msize = con->msize;
1150 6f4d00ee 2013-09-23 0intro r->version = "unknown";
1151 6f4d00ee 2013-09-23 0intro if(t->version[0] == '9' && t->version[1] == 'P'){
1153 6f4d00ee 2013-09-23 0intro * Currently, the only defined version
1154 6f4d00ee 2013-09-23 0intro * is "9P2000"; ignore any later versions.
1156 6f4d00ee 2013-09-23 0intro v = strtol(&t->version[2], 0, 10);
1157 6f4d00ee 2013-09-23 0intro if(v >= 2000){
1158 6f4d00ee 2013-09-23 0intro r->version = VERSION9P;
1159 6f4d00ee 2013-09-23 0intro con->msize = r->msize;
1160 6f4d00ee 2013-09-23 0intro con->state = ConUp;
1162 6f4d00ee 2013-09-23 0intro else if(strcmp(t->version, "9PEoF") == 0){
1163 6f4d00ee 2013-09-23 0intro r->version = "9PEoF";
1164 6f4d00ee 2013-09-23 0intro con->msize = r->msize;
1165 6f4d00ee 2013-09-23 0intro con->state = ConMoribund;
1168 6f4d00ee 2013-09-23 0intro * Don't want to attempt to write this
1169 6f4d00ee 2013-09-23 0intro * message as the connection may be already
1170 6f4d00ee 2013-09-23 0intro * closed.
1172 6f4d00ee 2013-09-23 0intro m->state = MsgF;
1175 4b576658 2013-09-23 0intro qunlock(&con->lock);
1177 6f4d00ee 2013-09-23 0intro return 1;
1180 6f4d00ee 2013-09-23 0intro int (*rFcall[Tmax])(Msg*) = {
1181 6f4d00ee 2013-09-23 0intro [Tversion] = rTversion,
1182 6f4d00ee 2013-09-23 0intro [Tauth] = rTauth,
1183 6f4d00ee 2013-09-23 0intro [Tattach] = rTattach,
1184 6f4d00ee 2013-09-23 0intro [Tflush] = rTflush,
1185 6f4d00ee 2013-09-23 0intro [Twalk] = rTwalk,
1186 6f4d00ee 2013-09-23 0intro [Topen] = rTopen,
1187 6f4d00ee 2013-09-23 0intro [Tcreate] = rTcreate,
1188 6f4d00ee 2013-09-23 0intro [Tread] = rTread,
1189 6f4d00ee 2013-09-23 0intro [Twrite] = rTwrite,
1190 6f4d00ee 2013-09-23 0intro [Tclunk] = rTclunk,
1191 6f4d00ee 2013-09-23 0intro [Tremove] = rTremove,
1192 6f4d00ee 2013-09-23 0intro [Tstat] = rTstat,
1193 6f4d00ee 2013-09-23 0intro [Twstat] = rTwstat,