blob: f810c06be81109ae3eddcf0e2ce6fb7827ca9a69 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001#pragma strict_types, no_warn_deprecated
2
3#include "/secure/master.h"
4
5static mapping projects=([]);
6static string *insecure,*deputy_files;
7
8int ReloadInsecureFile()
9{
10 insecure = efun::explode( read_file("/secure/INSECURE") || "", "\n" );
11 insecure -= ({""});
12 insecure = map( insecure, #'lower_case/*'*/ );
13 return(1);
14}
15
16void LoadDeputyFileList()
17{
18 // Leseberechtigungen fuer /log/ARCH/* setzen
19 deputy_files = efun::explode( read_file("/log/ARCH/DEPUTY_FILELIST") || "",
20 "\n" ) - ({""});
21 return;
22}
23
Zesstra3e9a6c92018-11-06 22:38:42 +010024// Normalisiert den Pfad und liefert ein Array mit Pfadelementen.
25// expand bestimmt, ob im Pfad +, ~ oder P_CURRENTDIR expandiert werden oder
26// nicht.
27string *path_array(string path, string user, int expand) {
Zesstrab45f3b42018-11-07 21:54:07 +010028 string cwd;
MG Mud User88f12472016-06-24 23:31:02 +020029
Zesstra3e9a6c92018-11-06 22:38:42 +010030 if (!sizeof(path))
MG Mud User88f12472016-06-24 23:31:02 +020031 return ({"",""}); // additional "" to yield "/" later.
32
Zesstra3e9a6c92018-11-06 22:38:42 +010033 // expand gibt es nur wenn angefordert
34 if (expand)
35 {
36 switch(path[0])
37 {
38 // expand nur fuer nicht-absolute Pfade
39 case '/':
40 break;
41 case '+':
42 if(sizeof(path)==1)
43 return ({"",DOMAINDIR});
44 path="/"DOMAINDIR"/" + path[1..];
45 break;
46 case '~':
47 if (sizeof(path)==1)
48 {
49 if(user)
50 return ({"",WIZARDDIR,user});
51 else
52 return ({"",WIZARDDIR});
53 }
Zesstraf7905352018-11-05 22:46:16 +010054 else
Zesstra3e9a6c92018-11-06 22:38:42 +010055 {
56 if(user && sizeof(path)>1 && path[1]=='/') // "~/"
57 path="/"WIZARDDIR"/" + user + "/" + path[2..];
58 else
59 path="/"WIZARDDIR"/" + path[1..];
60 }
61 break;
62 default:
63 if(user && TP && getuid(TP) == user
64 && (cwd=(string)TP->QueryProp(P_CURRENTDIR)))
65 path=cwd + "/" + path;
66 }
MG Mud User88f12472016-06-24 23:31:02 +020067 }
Zesstraf7905352018-11-05 22:46:16 +010068
Zesstra3e9a6c92018-11-06 22:38:42 +010069 // remove multiple '/'erstn gv
70 path = regreplace(path, "/+", "/", 1);
71
72 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
73 // rausschneiden.
Zesstraf7905352018-11-05 22:46:16 +010074 // Einschraenkungen der RegExp:
MG Mud User88f12472016-06-24 23:31:02 +020075 // /a/b/../../d wuerde nur durch Wiederholung aufgeloest.
76 // /../d wird nicht richtig aufgeloest.
77 //regreplace("/d/inseln/toeter/room/hoehle/../wald/bla.c","(.*)\/[^/]+/\.\.
78 // /(.*)", "\\1\/\\2", RE_GLOBAL)
Zesstraf7905352018-11-05 22:46:16 +010079
Zesstra3e9a6c92018-11-06 22:38:42 +010080 string *p_arr = explode(path, "/") - ({"."});
81
82 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
83 // rausschneiden.
MG Mud User88f12472016-06-24 23:31:02 +020084 // dies sieht schlimmer aus als es ist (member ist O(n)), solange das Array
85 // nicht gross wird.
86 int p;
Zesstra3e9a6c92018-11-06 22:38:42 +010087 while((p=member(p_arr, "..")) != -1)
88 p_arr = p_arr[0..p-2]+p_arr[p+1..];
MG Mud User88f12472016-06-24 23:31:02 +020089
Zesstra3e9a6c92018-11-06 22:38:42 +010090 // Pfade absolutieren
91 // leeres Pfadarray fuehrt zur Rueckgabe von einem Array, was hinterher "/"
92 // ergibt, Arrays mit nur einem Element bekommen in jedem Fall ein Element
93 // "" an den Anfang, laengere Arrays kriegen falls noetig ein "".
94 switch(sizeof(p_arr))
95 {
96 case 0:
97 return ({"",""});
98 case 1:
MG Mud User88f12472016-06-24 23:31:02 +020099 p_arr = ({""}) + p_arr;
Zesstra3e9a6c92018-11-06 22:38:42 +0100100 break;
101 default:
102 if (p_arr[0] != "")
103 p_arr = ({""}) + p_arr;
104 }
MG Mud User88f12472016-06-24 23:31:02 +0200105
Zesstra3e9a6c92018-11-06 22:38:42 +0100106 return p_arr;
107}
108
109// Pfadnormalisierung mit Ersetzungen von +, ~ und P_CURRENTDIR und Rueckgabe
110// als Pfadarray
111string *full_path_array(string path, string user) {
112 return path_array(path, user, 1);
113}
114
Zesstrab49624a2018-11-07 21:40:16 +0100115// Pfadnormalisierung OHNE Ersetzungen von +, ~ und P_CURRENTDIR (war mal mit)
116// Eigentlich hier ziemlich unnuetz, aber nen Haufen Objekte im Mud ruft das.
Zesstra3e9a6c92018-11-06 22:38:42 +0100117string _get_path(string path, string user) {
Zesstrab49624a2018-11-07 21:40:16 +0100118 return implode(path_array(path, user, 0),"/");
Zesstra3e9a6c92018-11-06 22:38:42 +0100119}
120
Zesstrab45f3b42018-11-07 21:54:07 +0100121// Besser benamste Version von _get_path().
122// Normalisiert den Pfad, expandiert Platzhalter auf Wunsch, benutzt ggf. TI
123// oder TP als User, wenn nicht angegeben.
124varargs string normalize_path(string path, string user, int expand) {
125 if (!user && (TI || TP))
126 user = getuid(TI || TP);
127 return implode(path_array(path, user, expand), "/");
128}
129
Zesstrab49624a2018-11-07 21:40:16 +0100130// Diese Funktion wird vom Driver nur fuer den Editor ed gerufen, aber der
131// Rest vom MG ruft es teilweise auch. Hier erfolgt eine Expansion von
132// Platzhaltern im Pfad.
Zesstrab45f3b42018-11-07 21:54:07 +0100133string make_path_absolute(string path) {
134 return normalize_path(path, getuid(TI || TP), 1);
MG Mud User88f12472016-06-24 23:31:02 +0200135}
136
137static int project_access(string user, string project)
138{
139 mixed *lines;
140 string s;
141 mapping tmp;
142
143 if (!member(projects,project))
144 {
145 s=read_file(PROJECTDIR+"/"+project+"/ACCESS_RIGHTS");
146 if(!s||s=="")
147 return 0;
148 tmp=([]);
149 for (lines=explode(s,"\n")-({""});sizeof(lines);lines=lines[1..])
150 {
151 if (lines[0][0]=='*')
152 tmp[lines[0][1..]]=2;
153 else
154 tmp[lines[0]]=1;
155 }
156 projects[project]=({tmp,time()});
157 return tmp[user];
158 }
159 projects[project][1]=time();
160 return projects[project][0][user];
161}
162
163void OutdateProjectCache(string project)
164{
165 m_delete(projects,project);
166}
167
168static void _cleanup_projects() {
169 int i;
170 mixed *users;
171
172 for (users=m_indices(projects),i=sizeof(users)-1;i>=0;i--)
173 if((time()-projects[users[i]][1])>1800)
174 m_delete(projects,users[i]);
175}
176
177int access_rights(string *p_arr, string euid)
178{
179 int i;
180
181 i = sizeof(p_arr) - 2;
182
183 while ( i >= 0 &&
184 file_size( implode(p_arr[0..i], "/") + "/access_rights.c" ) < 0 )
185 i--;
186
187 if ( i < 0 )
188 return 0;
189
190 if ( !catch(i = (int)call_other(
191 implode(p_arr[0..i], "/") + "/access_rights",
192 "access_rights", euid,
193 implode(p_arr[i+1..], "/") ); publish) )
194 return i;
195
196 return 0;
197}
198
Zesstra078991b2013-01-26 11:56:45 +0100199// Hngl. Inkludieren aus /sys ist hier doof.
200#ifndef FSIZE_DIR
201#define FSIZE_DIR -2
202#endif
MG Mud User88f12472016-06-24 23:31:02 +0200203mixed valid_write(string path, string euid, string fun, object obj)
204{
205 int s,lvl;
206 string *strs;
207 int *date;
208
209 if (member(path,' ')!=-1) return 0;
210
211 // Unter LIBDATADIR (/data) sollen komplett identische Schreibrechte
Zesstra078991b2013-01-26 11:56:45 +0100212 // vergeben werden. Ausnahme ist jedoch fun=="mkdir": hier soll die
213 // Erstellung eines Verezeichnisses jedem erlaubt sein, wenn es das
214 // entsprechende Verzeichnis ausserhalb /data/ schon gibt.
MG Mud User88f12472016-06-24 23:31:02 +0200215 if (sizeof(path) > 6
Zesstraeb0ceb82018-02-28 21:31:07 +0100216 && path[0..5] == "/"LIBDATADIR"/")
217 {
Zesstra078991b2013-01-26 11:56:45 +0100218 if (fun=="mkdir")
Zesstraeb0ceb82018-02-28 21:31:07 +0100219 {
220 // wenn schon ausserhalb /data/ existent: erlauben
221 if (file_size(path[5..]) == FSIZE_DIR)
222 return 1;
223 // sonst fall-through und normale gucken, ob der Aufrufer ausserhalb
224 // /data/ denn duerfte.
225 }
MG Mud User88f12472016-06-24 23:31:02 +0200226 return valid_write(path[5..], euid, fun, obj) != 0;
Zesstra078991b2013-01-26 11:56:45 +0100227 }
MG Mud User88f12472016-06-24 23:31:02 +0200228
229 switch(fun) {
230 case "log_file":
Zesstraa43be352018-11-06 22:40:32 +0100231 strs=path_array("/"+path, 0, 0);
MG Mud User88f12472016-06-24 23:31:02 +0200232 path = implode(strs, "/");
233 strs -= ({""}); // remove trailing and leading "/".
234 if (sizeof(strs)>1 && strs[0]=="log") return path;
235 return 0;
236 case "save_object":
Zesstraa43be352018-11-06 22:40:32 +0100237 if (!sizeof(path)) return 0;
238 strs=path_array("/"+path, 0, 0);
MG Mud User88f12472016-06-24 23:31:02 +0200239 break;
240 case "ed_start":
Zesstraa43be352018-11-06 22:40:32 +0100241 if (sizeof(path))
242 strs=path_array(path, euid, 1);
243 else
244 strs=({"players",euid,".err"});
MG Mud User88f12472016-06-24 23:31:02 +0200245 break;
246 default:
Zesstraa43be352018-11-06 22:40:32 +0100247 strs=path_array(path, euid, 1);
MG Mud User88f12472016-06-24 23:31:02 +0200248 }
249
250 if (!euid || euid=="NOBODY" || euid=="ftp" || euid=="anonymous") return 0;
251
252 // Pfad soll ab jetzt auf jeden Fall absolut sein.
253 if (strs[0] != "")
254 path = "/" + implode(strs, "/");
255 else
256 path=implode(strs, "/");
257
258 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
259 strs -= ({""});
260
261 //Root-Objekte und Master duerfen immer.
262 if (euid == ROOTID || obj==TO) return path;
263
264 lvl=query_wiz_level(euid);
265
266 //Toplevel: nur EM+
267 if ((s=sizeof(strs))<=1) return lvl>=ARCH_LVL;
268
269 switch(strs[0]) {
270 case TMPDIR:
271 return 1;
272
273 case STDDIR:
274 case SYSDIR:
275 case LIBOBJDIR:
276 case ETCDIR:
277 case LIBROOMDIR:
278 return lvl>=ARCH_LVL;
279
280 case LIBITEMDIR:
281 return lvl>=ELDER_LVL;
282
283 case SPELLBOOKDIR:
284 // wenn unterhalb eines unterverzeichnisses des Stils "gilde", dann ists
285 // einfach
286 if (sizeof(strs) > 2
287 && guild_master(euid, strs[1]))
288 return 1;
289
290 // sonst nur EMs bzw. access_rights.c fragen.
291 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
292
293 case GUILDDIR:
294 // wenn unterhalb eines unterverzeichnisses des Stils "filde.gilde",
295 // dann ists einfach
296 if (sizeof(strs) > 2) {
297 string *tmp = explode(strs[1],"files.");
298 if (sizeof(tmp) == 2) {
299 if (guild_master(euid, tmp[1]))
300 return 1;
301 // Objekte dort sollen auch schreiben duerfen.
302 if (euid == ("GUILD."+tmp[1]))
303 return 1;
304 }
305 }
306 // sonst nur EMs bzw. access_rights.c fragen.
307 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
308
309 case DOCDIR:
310 if ( s > 1 && (strs[1] == "balance") )
311 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
312 else
313 return ((lvl>=SPECIAL_LVL) || access_rights(strs,euid));
314
315 case FTPDIR:
316 if ( s > 1 && (strs[1] == "incoming" || strs[1] == "tmp" ||
317 s == 3 && strs[1] == "News" && strs[2] == euid+".news") )
318 return 1;
319
320 if (lvl>=ELDER_LVL)
321 return 1;
322
323 return 0;
324
325 case MAILDIR:
326 if (euid==MAILID || strs[1]=="spool") break;
327 return 0;
328
Zesstra8a3f8682017-01-30 23:04:20 +0100329 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200330 if (lvl>=ARCH_LVL) return 1;
331 if (s==3 && strs[1] == euid[0..0] &&
332 (strs[2]==euid+".o" || strs[2]==euid)) break;
333 return 0;
334
335 case LIBLOGDIR:
336 /* auf /log/ARCH/ haben wirklich nur EMs Zugriff */
337 if (strs[1]=="ARCH" && lvl<ARCH_LVL) return 0;
338
339 /* alles andere duerfen auch Weise... */
340 if (lvl>=ELDER_LVL) return 1;
341
342 /* Allgemeine logfiles in /log duerfen wirklich nur geschrieben werden */
343 if (s==2 && strs[1][0]>='A' && strs[1][0]<='Z' && fun != "write_file")
344 return 0;
345
346 /* Unterhalb von /log/syslog darf nur geschrieben werden */
347 if (s>1 && strs[1]=="syslog" && fun != "write_file")
348 return 0;
349
350 /* loggen ins eigene repfile immer erlauben */
351 if (s==3 && strs[1]=="report" &&
352 strs[2]==explode(euid, ".")[<1]+".rep") break;
353
354 /* in fremden Verzeichnissen hat niemand was zu loggen */
355 if (get_wiz_level(strs[1]) >= WIZARD_LVL &&
356 strs[1] != efun::explode(euid, ".")[<1])
357 return 0;
358 break;
359
360 case WIZARDDIR:
361 /* kein Zugriff auf Objekte mit hoeheren Rechten */
362 if (query_wiz_level(strs[1]) > lvl) return 0;
363
364 /* Magier selbst oder Weise duerfen hier schreiben */
365 if ((IS_WIZARD(euid) && euid==strs[1])||(lvl>=ELDER_LVL)) break;
366
367 /* Es steht jedoch frei, auch anderen Schreibrechte zu geben... */
368 return access_rights(strs,euid);
369
370 case DOMAINDIR:
371 /* neue Regionen duerfen nur Erzmagier anlegen */
372 if (s<2 && lvl<ARCH_LVL) return 0;
373
374 /* kein Zugriff auf Objekte mit hoeheren Rechten */
375 if (s>2 && query_wiz_level(creator_file(path)) > lvl)
376 return 0;
377
378 /* Auf Regionfiles von erzmagier haben nur EMs Zugriff */
379 if (creator_file(path)=="erzmagier" && lvl<ARCH_LVL) return 0;
380
381 /* innerhalb der Region haben RMs und Weise volle Schreibrechte */
382 if (lvl>=ELDER_LVL || domain_master(euid,strs[1])) break;
383
384 /* neue Verzeichnisse in der Region kann nur RM+ anlegen */
385 if (s<=3 && (fun=="mkdir" || fun=="rmdir")) return 0;
386
387 /* Magier auf ihre eigenen Files... */
388 if (s>2 && strs[2]==euid) break;
389
390 /* Files der Magier in der Region in ihre eigenen Verzeichnisse... */
391 if (s>2 && euid==sprintf("d.%s.%s", strs[1], strs[2])) break;
392
393 /* Files mit Regionsuid */
394 if (euid==strs[1]) break;
395
396 /* Es ist moeglich anderen Magiern Rechte bei sich einzuraeumen. */
397 if (access_rights(strs,euid)>0) break;
398
399 /* Auf das Verzeichniss 'alle' haben alle Regionsmitglieder Zugriff.
400 Ausser, wenn sie ueber access_rights.c explizit ausgeschlossen
401 werden (Returncode < 0). */
402 if (s>2 && strs[2]=="alle" && domain_member(euid, strs[1]) &&
403 access_rights(strs,euid)>=0) break;
404 return 0;
405
406 case PROJECTDIR:
407 /* Nur Erzmagier duerfen neue Projektverzeichnisse anlegen... */
408 if (s<3 && lvl<ARCH_LVL) return 0;
409
410 /* alles weitere duerfen auch Weise tun */
411 if (lvl>=ELDER_LVL) break;
412
413 /* in den Serviceverzeichnissen muss lediglich der Name stimmen */
414 if (s>3 && strs[1]=="service" && euid==strs[2]) break;
415
416 /* Objekte eines Projektes haben Schreibzugriffe auf ihr Projekt */
417 if (s>3 && (implode(strs[0..1], ".") == euid
418 || implode(strs[0..2], ".") == euid) ) return 1;
419
420 /* Schreibrechte koennen natuerlich auch vergeben werden... */
421 if (project_access(euid,strs[1])) break;
422 // Alternativ besteht neben dem ACCESS_RIGHTS auch noch die
423 // Moeglichkeit, per access_rights.c Rechte einzuraeumen.
424 if (access_rights(strs,euid)>0) break;
425
426 return 0;
427
428 default: return 0;
429 }
430 return path;
431}
432
433mixed valid_read(string path, string euid, string fun, object obj)
434{
435 int s, lev;
436 string *strs, suf;
437
438 if (member(path,' ')!=-1) return 0;
439
440 // Unter LIBDATADIR (/data) sollen komplett identische Leserechte
441 // vergeben werden.
442 if (sizeof(path) > 6
443 && path[0..5] == "/"LIBDATADIR"/")
444 return valid_read(path[5..], euid, fun, obj) != 0;
445
446 if (!euid) euid="-";
447
Zesstraa43be352018-11-06 22:40:32 +0100448 strs=path_array(path, euid, 1);
449 // Pfade sind ab jetzt auf jeden Fall absolut.
450 path=implode(strs, "/");
MG Mud User88f12472016-06-24 23:31:02 +0200451
452 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
453 strs -= ({""});
454
455 if (!sizeof(strs) || !sizeof(path) || euid == ROOTID || obj==TO) return path;
456
457 if ((s=sizeof(strs)) <= 1) return path;
458
459 lev=query_wiz_level(euid);
460
461 switch(strs[0]) {
462 case "core":
463 case "wahl":
464 return 0;
465
466 case NEWSDIR:
467 if (strs[1] == "archiv.pub") // oeffentliches archiv
468 return path;
469 else if (strs[1] == "archiv.magier" // Magier-Archiv
470 && lev >= WIZARD_LVL)
471 return path;
472
473 return 0; // kein Zugriff auf /news/ oder alles andere.
474
475 case "maps":
476 if (lev<=WIZARD_LVL) return 0;
477
478 case "":
479 case ETCDIR:
480 case STDDIR:
481 case SYSDIR:
482 case DOCDIR:
483 case LIBOBJDIR:
484 case LIBROOMDIR:
485 case LIBITEMDIR:
486 case FTPDIR:
487 return path;
488
489 case MAILDIR:
490 return (euid==MAILID);
491
492 case SECUREDIR:
493 if (strs[1]=="save") return 0;
494 if (path[<2..]==".o" || path[<5..]==".dump") return 0;
495 if (strs[1]!="ARCH" || lev>=ARCH_LVL) return path;
496
497 case LIBLOGDIR:
498 if ( strs[1] == "ARCH" && !IS_DEPUTY(euid) )
499 return 0;
500
501 if ( strs[1] == "ARCH" && lev < ARCH_LVL && s == 3 &&
502 strs[2] != "*" && strs[2][0..2] != "bb." &&
503 member( deputy_files, strs[2] ) < 0 )
504 return 0;
505
506 if ( lev > WIZARD_LVL )
507 return path;
508
509 if ( s == 2 && (strs[1] == "report" || strs[1] == "error") )
510 return path; // fuer 'cd'
511
512 // /log sollte jeder auflisten koennen
513 if ( s == 2 && strs[1]=="*" && fun=="get_dir")
514 return path;
515
516 // unter /log/report/, /log/error und /log/warning/ duerfen alle lesen
517 if ( s==3 &&
518 (strs[1] == "report" || strs[1] == "error"
519 || strs[1] =="warning"))
520 return path;
521
522 // /log/<Magiername> darf von <Magiername> natuerlich auch
523 // gelesen werden
524 if ( s >= 2 && strs[1] == euid )
525 return path;
526
527 return 0;
528
529 case "backup":
Zesstra8a3f8682017-01-30 23:04:20 +0100530 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200531 if (lev>WIZARD_LVL) return path;
532
533 /* Objekte in /p/* haben bisher leider wizlevel 0 */
534 //if (lev==0) return path;
535
536 if (fun=="file_size") return path;
537
538 // das eigene Savefile darf man natuerlich immer. ;-)
539 if (s==3 && (strs[2]==euid+".o" || strs[2]==euid))
540 return path;
541 return 0;
542
543 case PROJECTDIR:
544 /* Pruefen ob ein File existiert darf jeder... */
545 if (fun=="file_size") return path;
546
547 /* Die Service-Verzeichnisse darf jeder lesen */
548 if (s>3 && strs[1]=="service") return path;
549
550 //Weise duerfen in /p/ schreiben, also auch lesen. (Zesstra, 04.11.06)
551 if (lev>=ELDER_LVL) return path;
552
553 /* wer hier schreiben darf, darf natuerlich auf jeden Fall lesen */
554 //Anmerkung v. Zesstra: das prueft nur, ob jemand in ACCESS_RIGHTS
555 //steht, nicht ob jemand (ggf. aus anderen Gruenden schreiben darf)
556 if (project_access(euid,strs[1])) return path;
557 //Alternativ kann man explizite Schreibrechte auch via access_rights.c
558 //vergeben. (und damit natuerlich auch Leserechte)
559 if (access_rights(strs,euid)>0) return path;
560
561 /* Objekte eines Projektes haben Lesezugriff auf ihr Projekt */
562 if (s>3 && (implode(strs[0..1], ".") == euid
563 || implode(strs[0..2], ".") == euid) ) return path;
564
565 /* Fall-Through */
566
567 case GUILDDIR:
568 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
569 if ( s > 3 && strs[<2] == "secure" && member( insecure, strs[1] ) < 0
570 && lev < ARCH_LVL && !access_rights(strs, euid) )
571 return 0;
572
573 /* Pruefen ob ein File existiert darf jeder... */
574 if (fun=="file_size") return path;
575
576 /* Fall-Through */
577
578 case SPELLBOOKDIR:
579 // Gildenpbjekte koennen hier lesen
580 if (lev==0 && euid[0..4]=="GUILD") return path;
581
582 // Mit Level <= 20 darf man hier nichts lesen
583 if ( lev<=WIZARD_LVL && sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
584 return 0;
585
586 return path;
587
588 case WIZARDDIR:
589 if (s==2) return path;
590 /* das eigene Verzeichniss darf man natuerlich immer lesen... */
591 if (strs[1]==euid && lev>=WIZARD_LVL) return path;
592
593 /* Pruefen ob ein File existiert darf jeder... */
594 if (fun=="file_size") return path;
595
596 /* fremde Verzeichnisse mit <= Level 20 noch nicht */
597 if (lev<=WIZARD_LVL) return 0;
598
599 /* wo man schreiben darf, darf man natuerlich auch lesen... */
600 if (lev>=ELDER_LVL) return path;
601
602 // kein Zugriff auf archivierten Code (wo z.B. secure/ drin sein
603 // koennen)
604 if (member(({"bz2","gz","zip"}), explode(strs[<1],".")[<1]) > -1)
605 return 0;
606
607 /* Files ohne Code sind nicht weiter interessant... */
608 if ( !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
609 return path;
610
611 /* folgende Funktionen sind natuerlich voellig uninteressant */
612 if (member(({"get_dir", "restore_object"}), fun)!=-1)
613 return path;
614
615 /* Zugriff erlaubt, aber mitloggen */
616 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
617 euid, path) );
618 return path;
619
620 case DOMAINDIR:
621 /* Mit Level 15 darf man hier _nichts_ lesen */
622 if ( fun!="file_size" && lev<WIZARD_LVL &&
623 sizeof(regexp( ({strs[<1]}), "\\.[och]" )) ) return 0;
624
625 /* den Verzeichnisbaum von /d/ darf man natuerlich sonst lesen */
626 if (s<=2) return path;
627
628 /* eigenen Code darf man natuerlich auch lesen */
629 if (euid==strs[2] || euid==sprintf("d.%s.%s", strs[1], strs[2]))
630 return path;
631
632 /* Deputies haben ein gemeinsames Verzeichnis unter /d/erzmagier */
633 if (strs[1]=="erzmagier" && strs[2]=="polizei" && IS_DEPUTY(euid))
634 return path;
635
636 /* d/erzmagier darf man nur als Erzmagier lesen */
637 if (strs[1]=="erzmagier" && lev<ARCH_LVL) return 0;
638
639 /* einige Regionen haben std-verzeichnisse, die darf man natuerlich
640 auch mit Level 20 bereits komplett lesen! */
641 if (strs[2]=="std") return path;
642
643 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
644 if ( s > 4 && strs[<2] == "secure" && member( insecure, strs[2] ) < 0 ){
645 if ( lev < ELDER_LVL && !domain_master(euid, strs[1])
646 && !access_rights(strs, euid) )
647 return 0;
648 else
649 return path;
650 }
651
652 /* Dokus, Infos und .readme darf man immer lesen... */
653 if ( fun=="file_size" || !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
654 return path;
655
656 /* Mit Level 20 darf man noch keinen fremden Code lesen! */
657 if (lev<=WIZARD_LVL) return 0;
658
659 /* Weise duerfen natuerlich alles weitere lesen */
660 if (lev>=ELDER_LVL) return path;
661
662 /* Regionsmagier in ihren Regionen natuerlich auch */
663 if (lev>=LORD_LVL && domain_master(euid, strs[1])) return path;
664
665 /* folgende Funktionen sind natuerlich voellig uninteressant */
666 if (member(({"get_dir", "restore_object"}), fun)!=-1)
667 return path;
668
669 /* Zugriff erlaubt, aber mitloggen */
670 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
671 euid, path) );
672 return path;
673 }
674 if (lev<ARCH_LVL) return 0;
675 return path;
676}
677