blob: 04cd53e8b4aa8a6564b9d5a5708638530a78c18d [file] [log] [blame]
Zesstra3bee4f92019-11-28 20:17:36 +01001#pragma strict_types,rtt_checks,pedantic
MG Mud User88f12472016-06-24 23:31:02 +02002
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.
Zesstraccc58df2018-11-07 23:25:20 +010027string *path_array(string path) {
MG Mud User88f12472016-06-24 23:31:02 +020028
Zesstra3e9a6c92018-11-06 22:38:42 +010029 if (!sizeof(path))
MG Mud User88f12472016-06-24 23:31:02 +020030 return ({"",""}); // additional "" to yield "/" later.
31
Zesstra3e9a6c92018-11-06 22:38:42 +010032 // remove multiple '/'erstn gv
33 path = regreplace(path, "/+", "/", 1);
34
35 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
36 // rausschneiden.
Zesstraf7905352018-11-05 22:46:16 +010037 // Einschraenkungen der RegExp:
MG Mud User88f12472016-06-24 23:31:02 +020038 // /a/b/../../d wuerde nur durch Wiederholung aufgeloest.
39 // /../d wird nicht richtig aufgeloest.
40 //regreplace("/d/inseln/toeter/room/hoehle/../wald/bla.c","(.*)\/[^/]+/\.\.
41 // /(.*)", "\\1\/\\2", RE_GLOBAL)
Zesstraf7905352018-11-05 22:46:16 +010042
Zesstra3e9a6c92018-11-06 22:38:42 +010043 string *p_arr = explode(path, "/") - ({"."});
44
45 // /../ irgendwo im Pfad behandeln, das und vorheriges Element
46 // rausschneiden.
MG Mud User88f12472016-06-24 23:31:02 +020047 // dies sieht schlimmer aus als es ist (member ist O(n)), solange das Array
48 // nicht gross wird.
49 int p;
Zesstra3e9a6c92018-11-06 22:38:42 +010050 while((p=member(p_arr, "..")) != -1)
51 p_arr = p_arr[0..p-2]+p_arr[p+1..];
MG Mud User88f12472016-06-24 23:31:02 +020052
Zesstra3e9a6c92018-11-06 22:38:42 +010053 // Pfade absolutieren
54 // leeres Pfadarray fuehrt zur Rueckgabe von einem Array, was hinterher "/"
55 // ergibt, Arrays mit nur einem Element bekommen in jedem Fall ein Element
56 // "" an den Anfang, laengere Arrays kriegen falls noetig ein "".
57 switch(sizeof(p_arr))
58 {
59 case 0:
60 return ({"",""});
61 case 1:
MG Mud User88f12472016-06-24 23:31:02 +020062 p_arr = ({""}) + p_arr;
Zesstra3e9a6c92018-11-06 22:38:42 +010063 break;
64 default:
65 if (p_arr[0] != "")
66 p_arr = ({""}) + p_arr;
67 }
MG Mud User88f12472016-06-24 23:31:02 +020068
Zesstra3e9a6c92018-11-06 22:38:42 +010069 return p_arr;
70}
71
Zesstrab49624a2018-11-07 21:40:16 +010072// Pfadnormalisierung OHNE Ersetzungen von +, ~ und P_CURRENTDIR (war mal mit)
73// Eigentlich hier ziemlich unnuetz, aber nen Haufen Objekte im Mud ruft das.
Zesstra3e9a6c92018-11-06 22:38:42 +010074string _get_path(string path, string user) {
Zesstraccc58df2018-11-07 23:25:20 +010075 return implode(path_array(path),"/");
Zesstrab45f3b42018-11-07 21:54:07 +010076}
77
Zesstrab49624a2018-11-07 21:40:16 +010078// Diese Funktion wird vom Driver nur fuer den Editor ed gerufen, aber der
Zesstraccc58df2018-11-07 23:25:20 +010079// Rest vom MG ruft es teilweise auch.
Zesstrab45f3b42018-11-07 21:54:07 +010080string make_path_absolute(string path) {
Zesstraccc58df2018-11-07 23:25:20 +010081 return implode(path_array(path),"/");
MG Mud User88f12472016-06-24 23:31:02 +020082}
83
84static int project_access(string user, string project)
85{
86 mixed *lines;
87 string s;
88 mapping tmp;
89
90 if (!member(projects,project))
91 {
92 s=read_file(PROJECTDIR+"/"+project+"/ACCESS_RIGHTS");
93 if(!s||s=="")
94 return 0;
95 tmp=([]);
96 for (lines=explode(s,"\n")-({""});sizeof(lines);lines=lines[1..])
97 {
98 if (lines[0][0]=='*')
99 tmp[lines[0][1..]]=2;
100 else
101 tmp[lines[0]]=1;
102 }
103 projects[project]=({tmp,time()});
104 return tmp[user];
105 }
106 projects[project][1]=time();
107 return projects[project][0][user];
108}
109
110void OutdateProjectCache(string project)
111{
112 m_delete(projects,project);
113}
114
115static void _cleanup_projects() {
116 int i;
117 mixed *users;
118
119 for (users=m_indices(projects),i=sizeof(users)-1;i>=0;i--)
120 if((time()-projects[users[i]][1])>1800)
121 m_delete(projects,users[i]);
122}
123
124int access_rights(string *p_arr, string euid)
125{
Zesstrad872d182019-11-28 20:13:02 +0100126 int i = sizeof(p_arr) - 2;
MG Mud User88f12472016-06-24 23:31:02 +0200127
128 while ( i >= 0 &&
129 file_size( implode(p_arr[0..i], "/") + "/access_rights.c" ) < 0 )
130 i--;
131
132 if ( i < 0 )
133 return 0;
134
Zesstrad872d182019-11-28 20:13:02 +0100135 if ( !catch(i = ({int})call_other(
MG Mud User88f12472016-06-24 23:31:02 +0200136 implode(p_arr[0..i], "/") + "/access_rights",
137 "access_rights", euid,
138 implode(p_arr[i+1..], "/") ); publish) )
139 return i;
140
141 return 0;
142}
143
Zesstra078991b2013-01-26 11:56:45 +0100144// Hngl. Inkludieren aus /sys ist hier doof.
145#ifndef FSIZE_DIR
146#define FSIZE_DIR -2
147#endif
MG Mud User88f12472016-06-24 23:31:02 +0200148mixed valid_write(string path, string euid, string fun, object obj)
149{
150 int s,lvl;
151 string *strs;
152 int *date;
153
154 if (member(path,' ')!=-1) return 0;
155
156 // Unter LIBDATADIR (/data) sollen komplett identische Schreibrechte
Zesstra078991b2013-01-26 11:56:45 +0100157 // vergeben werden. Ausnahme ist jedoch fun=="mkdir": hier soll die
158 // Erstellung eines Verezeichnisses jedem erlaubt sein, wenn es das
159 // entsprechende Verzeichnis ausserhalb /data/ schon gibt.
MG Mud User88f12472016-06-24 23:31:02 +0200160 if (sizeof(path) > 6
Zesstraeb0ceb82018-02-28 21:31:07 +0100161 && path[0..5] == "/"LIBDATADIR"/")
162 {
Zesstra078991b2013-01-26 11:56:45 +0100163 if (fun=="mkdir")
Zesstraeb0ceb82018-02-28 21:31:07 +0100164 {
165 // wenn schon ausserhalb /data/ existent: erlauben
166 if (file_size(path[5..]) == FSIZE_DIR)
167 return 1;
168 // sonst fall-through und normale gucken, ob der Aufrufer ausserhalb
169 // /data/ denn duerfte.
170 }
MG Mud User88f12472016-06-24 23:31:02 +0200171 return valid_write(path[5..], euid, fun, obj) != 0;
Zesstra078991b2013-01-26 11:56:45 +0100172 }
MG Mud User88f12472016-06-24 23:31:02 +0200173
174 switch(fun) {
175 case "log_file":
Zesstraccc58df2018-11-07 23:25:20 +0100176 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200177 path = implode(strs, "/");
178 strs -= ({""}); // remove trailing and leading "/".
179 if (sizeof(strs)>1 && strs[0]=="log") return path;
180 return 0;
181 case "save_object":
Zesstraa43be352018-11-06 22:40:32 +0100182 if (!sizeof(path)) return 0;
Zesstraccc58df2018-11-07 23:25:20 +0100183 strs=path_array("/"+path);
MG Mud User88f12472016-06-24 23:31:02 +0200184 break;
185 case "ed_start":
Zesstraa43be352018-11-06 22:40:32 +0100186 if (sizeof(path))
Zesstraccc58df2018-11-07 23:25:20 +0100187 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100188 else
189 strs=({"players",euid,".err"});
MG Mud User88f12472016-06-24 23:31:02 +0200190 break;
191 default:
Zesstraccc58df2018-11-07 23:25:20 +0100192 strs=path_array(path);
MG Mud User88f12472016-06-24 23:31:02 +0200193 }
194
195 if (!euid || euid=="NOBODY" || euid=="ftp" || euid=="anonymous") return 0;
196
197 // Pfad soll ab jetzt auf jeden Fall absolut sein.
198 if (strs[0] != "")
199 path = "/" + implode(strs, "/");
200 else
201 path=implode(strs, "/");
202
203 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
204 strs -= ({""});
205
206 //Root-Objekte und Master duerfen immer.
207 if (euid == ROOTID || obj==TO) return path;
208
209 lvl=query_wiz_level(euid);
210
211 //Toplevel: nur EM+
212 if ((s=sizeof(strs))<=1) return lvl>=ARCH_LVL;
213
214 switch(strs[0]) {
215 case TMPDIR:
216 return 1;
217
218 case STDDIR:
219 case SYSDIR:
220 case LIBOBJDIR:
221 case ETCDIR:
222 case LIBROOMDIR:
223 return lvl>=ARCH_LVL;
224
225 case LIBITEMDIR:
226 return lvl>=ELDER_LVL;
227
228 case SPELLBOOKDIR:
229 // wenn unterhalb eines unterverzeichnisses des Stils "gilde", dann ists
230 // einfach
231 if (sizeof(strs) > 2
232 && guild_master(euid, strs[1]))
233 return 1;
234
235 // sonst nur EMs bzw. access_rights.c fragen.
236 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
237
238 case GUILDDIR:
239 // wenn unterhalb eines unterverzeichnisses des Stils "filde.gilde",
240 // dann ists einfach
241 if (sizeof(strs) > 2) {
242 string *tmp = explode(strs[1],"files.");
243 if (sizeof(tmp) == 2) {
244 if (guild_master(euid, tmp[1]))
245 return 1;
246 // Objekte dort sollen auch schreiben duerfen.
247 if (euid == ("GUILD."+tmp[1]))
248 return 1;
249 }
250 }
251 // sonst nur EMs bzw. access_rights.c fragen.
252 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
253
254 case DOCDIR:
255 if ( s > 1 && (strs[1] == "balance") )
256 return ((lvl>=ARCH_LVL) || access_rights(strs,euid));
257 else
258 return ((lvl>=SPECIAL_LVL) || access_rights(strs,euid));
259
260 case FTPDIR:
261 if ( s > 1 && (strs[1] == "incoming" || strs[1] == "tmp" ||
262 s == 3 && strs[1] == "News" && strs[2] == euid+".news") )
263 return 1;
264
265 if (lvl>=ELDER_LVL)
266 return 1;
267
268 return 0;
269
270 case MAILDIR:
271 if (euid==MAILID || strs[1]=="spool") break;
272 return 0;
273
Zesstra8a3f8682017-01-30 23:04:20 +0100274 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200275 if (lvl>=ARCH_LVL) return 1;
276 if (s==3 && strs[1] == euid[0..0] &&
277 (strs[2]==euid+".o" || strs[2]==euid)) break;
278 return 0;
279
280 case LIBLOGDIR:
281 /* auf /log/ARCH/ haben wirklich nur EMs Zugriff */
282 if (strs[1]=="ARCH" && lvl<ARCH_LVL) return 0;
283
284 /* alles andere duerfen auch Weise... */
285 if (lvl>=ELDER_LVL) return 1;
286
287 /* Allgemeine logfiles in /log duerfen wirklich nur geschrieben werden */
288 if (s==2 && strs[1][0]>='A' && strs[1][0]<='Z' && fun != "write_file")
289 return 0;
290
291 /* Unterhalb von /log/syslog darf nur geschrieben werden */
292 if (s>1 && strs[1]=="syslog" && fun != "write_file")
293 return 0;
294
295 /* loggen ins eigene repfile immer erlauben */
296 if (s==3 && strs[1]=="report" &&
297 strs[2]==explode(euid, ".")[<1]+".rep") break;
298
299 /* in fremden Verzeichnissen hat niemand was zu loggen */
300 if (get_wiz_level(strs[1]) >= WIZARD_LVL &&
301 strs[1] != efun::explode(euid, ".")[<1])
302 return 0;
303 break;
304
305 case WIZARDDIR:
306 /* kein Zugriff auf Objekte mit hoeheren Rechten */
307 if (query_wiz_level(strs[1]) > lvl) return 0;
308
309 /* Magier selbst oder Weise duerfen hier schreiben */
310 if ((IS_WIZARD(euid) && euid==strs[1])||(lvl>=ELDER_LVL)) break;
311
312 /* Es steht jedoch frei, auch anderen Schreibrechte zu geben... */
313 return access_rights(strs,euid);
314
315 case DOMAINDIR:
316 /* neue Regionen duerfen nur Erzmagier anlegen */
317 if (s<2 && lvl<ARCH_LVL) return 0;
318
319 /* kein Zugriff auf Objekte mit hoeheren Rechten */
320 if (s>2 && query_wiz_level(creator_file(path)) > lvl)
321 return 0;
322
323 /* Auf Regionfiles von erzmagier haben nur EMs Zugriff */
324 if (creator_file(path)=="erzmagier" && lvl<ARCH_LVL) return 0;
325
326 /* innerhalb der Region haben RMs und Weise volle Schreibrechte */
327 if (lvl>=ELDER_LVL || domain_master(euid,strs[1])) break;
328
329 /* neue Verzeichnisse in der Region kann nur RM+ anlegen */
330 if (s<=3 && (fun=="mkdir" || fun=="rmdir")) return 0;
331
332 /* Magier auf ihre eigenen Files... */
333 if (s>2 && strs[2]==euid) break;
334
335 /* Files der Magier in der Region in ihre eigenen Verzeichnisse... */
336 if (s>2 && euid==sprintf("d.%s.%s", strs[1], strs[2])) break;
337
338 /* Files mit Regionsuid */
339 if (euid==strs[1]) break;
340
341 /* Es ist moeglich anderen Magiern Rechte bei sich einzuraeumen. */
342 if (access_rights(strs,euid)>0) break;
343
344 /* Auf das Verzeichniss 'alle' haben alle Regionsmitglieder Zugriff.
345 Ausser, wenn sie ueber access_rights.c explizit ausgeschlossen
346 werden (Returncode < 0). */
347 if (s>2 && strs[2]=="alle" && domain_member(euid, strs[1]) &&
348 access_rights(strs,euid)>=0) break;
349 return 0;
350
351 case PROJECTDIR:
352 /* Nur Erzmagier duerfen neue Projektverzeichnisse anlegen... */
353 if (s<3 && lvl<ARCH_LVL) return 0;
354
355 /* alles weitere duerfen auch Weise tun */
356 if (lvl>=ELDER_LVL) break;
357
358 /* in den Serviceverzeichnissen muss lediglich der Name stimmen */
359 if (s>3 && strs[1]=="service" && euid==strs[2]) break;
360
361 /* Objekte eines Projektes haben Schreibzugriffe auf ihr Projekt */
362 if (s>3 && (implode(strs[0..1], ".") == euid
363 || implode(strs[0..2], ".") == euid) ) return 1;
364
365 /* Schreibrechte koennen natuerlich auch vergeben werden... */
366 if (project_access(euid,strs[1])) break;
367 // Alternativ besteht neben dem ACCESS_RIGHTS auch noch die
368 // Moeglichkeit, per access_rights.c Rechte einzuraeumen.
369 if (access_rights(strs,euid)>0) break;
370
371 return 0;
372
373 default: return 0;
374 }
375 return path;
376}
377
378mixed valid_read(string path, string euid, string fun, object obj)
379{
380 int s, lev;
381 string *strs, suf;
382
383 if (member(path,' ')!=-1) return 0;
384
385 // Unter LIBDATADIR (/data) sollen komplett identische Leserechte
386 // vergeben werden.
387 if (sizeof(path) > 6
388 && path[0..5] == "/"LIBDATADIR"/")
389 return valid_read(path[5..], euid, fun, obj) != 0;
390
391 if (!euid) euid="-";
392
Zesstraccc58df2018-11-07 23:25:20 +0100393 strs=path_array(path);
Zesstraa43be352018-11-06 22:40:32 +0100394 // Pfade sind ab jetzt auf jeden Fall absolut.
395 path=implode(strs, "/");
MG Mud User88f12472016-06-24 23:31:02 +0200396
397 // fuer die Rechtebestimmung "/" an Anfang und Ende entfernen
398 strs -= ({""});
399
400 if (!sizeof(strs) || !sizeof(path) || euid == ROOTID || obj==TO) return path;
401
402 if ((s=sizeof(strs)) <= 1) return path;
403
404 lev=query_wiz_level(euid);
405
406 switch(strs[0]) {
407 case "core":
408 case "wahl":
409 return 0;
410
411 case NEWSDIR:
412 if (strs[1] == "archiv.pub") // oeffentliches archiv
413 return path;
414 else if (strs[1] == "archiv.magier" // Magier-Archiv
415 && lev >= WIZARD_LVL)
416 return path;
417
418 return 0; // kein Zugriff auf /news/ oder alles andere.
419
420 case "maps":
421 if (lev<=WIZARD_LVL) return 0;
422
423 case "":
424 case ETCDIR:
425 case STDDIR:
426 case SYSDIR:
427 case DOCDIR:
428 case LIBOBJDIR:
429 case LIBROOMDIR:
430 case LIBITEMDIR:
431 case FTPDIR:
432 return path;
433
434 case MAILDIR:
435 return (euid==MAILID);
436
437 case SECUREDIR:
438 if (strs[1]=="save") return 0;
439 if (path[<2..]==".o" || path[<5..]==".dump") return 0;
440 if (strs[1]!="ARCH" || lev>=ARCH_LVL) return path;
441
442 case LIBLOGDIR:
443 if ( strs[1] == "ARCH" && !IS_DEPUTY(euid) )
444 return 0;
445
446 if ( strs[1] == "ARCH" && lev < ARCH_LVL && s == 3 &&
447 strs[2] != "*" && strs[2][0..2] != "bb." &&
448 member( deputy_files, strs[2] ) < 0 )
449 return 0;
450
451 if ( lev > WIZARD_LVL )
452 return path;
453
454 if ( s == 2 && (strs[1] == "report" || strs[1] == "error") )
455 return path; // fuer 'cd'
456
457 // /log sollte jeder auflisten koennen
458 if ( s == 2 && strs[1]=="*" && fun=="get_dir")
459 return path;
460
461 // unter /log/report/, /log/error und /log/warning/ duerfen alle lesen
462 if ( s==3 &&
463 (strs[1] == "report" || strs[1] == "error"
464 || strs[1] =="warning"))
465 return path;
466
467 // /log/<Magiername> darf von <Magiername> natuerlich auch
468 // gelesen werden
469 if ( s >= 2 && strs[1] == euid )
470 return path;
471
472 return 0;
473
474 case "backup":
Zesstra8a3f8682017-01-30 23:04:20 +0100475 case "save":
MG Mud User88f12472016-06-24 23:31:02 +0200476 if (lev>WIZARD_LVL) return path;
477
478 /* Objekte in /p/* haben bisher leider wizlevel 0 */
479 //if (lev==0) return path;
480
481 if (fun=="file_size") return path;
482
483 // das eigene Savefile darf man natuerlich immer. ;-)
484 if (s==3 && (strs[2]==euid+".o" || strs[2]==euid))
485 return path;
486 return 0;
487
488 case PROJECTDIR:
489 /* Pruefen ob ein File existiert darf jeder... */
490 if (fun=="file_size") return path;
491
492 /* Die Service-Verzeichnisse darf jeder lesen */
493 if (s>3 && strs[1]=="service") return path;
494
495 //Weise duerfen in /p/ schreiben, also auch lesen. (Zesstra, 04.11.06)
496 if (lev>=ELDER_LVL) return path;
497
498 /* wer hier schreiben darf, darf natuerlich auf jeden Fall lesen */
499 //Anmerkung v. Zesstra: das prueft nur, ob jemand in ACCESS_RIGHTS
500 //steht, nicht ob jemand (ggf. aus anderen Gruenden schreiben darf)
501 if (project_access(euid,strs[1])) return path;
502 //Alternativ kann man explizite Schreibrechte auch via access_rights.c
503 //vergeben. (und damit natuerlich auch Leserechte)
504 if (access_rights(strs,euid)>0) return path;
505
506 /* Objekte eines Projektes haben Lesezugriff auf ihr Projekt */
507 if (s>3 && (implode(strs[0..1], ".") == euid
508 || implode(strs[0..2], ".") == euid) ) return path;
509
510 /* Fall-Through */
511
512 case GUILDDIR:
513 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
514 if ( s > 3 && strs[<2] == "secure" && member( insecure, strs[1] ) < 0
515 && lev < ARCH_LVL && !access_rights(strs, euid) )
516 return 0;
517
518 /* Pruefen ob ein File existiert darf jeder... */
519 if (fun=="file_size") return path;
520
521 /* Fall-Through */
522
523 case SPELLBOOKDIR:
524 // Gildenpbjekte koennen hier lesen
525 if (lev==0 && euid[0..4]=="GUILD") return path;
526
527 // Mit Level <= 20 darf man hier nichts lesen
528 if ( lev<=WIZARD_LVL && sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
529 return 0;
530
531 return path;
532
533 case WIZARDDIR:
534 if (s==2) return path;
535 /* das eigene Verzeichniss darf man natuerlich immer lesen... */
536 if (strs[1]==euid && lev>=WIZARD_LVL) return path;
537
538 /* Pruefen ob ein File existiert darf jeder... */
539 if (fun=="file_size") return path;
540
541 /* fremde Verzeichnisse mit <= Level 20 noch nicht */
542 if (lev<=WIZARD_LVL) return 0;
543
544 /* wo man schreiben darf, darf man natuerlich auch lesen... */
545 if (lev>=ELDER_LVL) return path;
546
547 // kein Zugriff auf archivierten Code (wo z.B. secure/ drin sein
548 // koennen)
549 if (member(({"bz2","gz","zip"}), explode(strs[<1],".")[<1]) > -1)
550 return 0;
551
552 /* Files ohne Code sind nicht weiter interessant... */
553 if ( !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
554 return path;
555
556 /* folgende Funktionen sind natuerlich voellig uninteressant */
557 if (member(({"get_dir", "restore_object"}), fun)!=-1)
558 return path;
559
560 /* Zugriff erlaubt, aber mitloggen */
561 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
562 euid, path) );
563 return path;
564
565 case DOMAINDIR:
566 /* Mit Level 15 darf man hier _nichts_ lesen */
567 if ( fun!="file_size" && lev<WIZARD_LVL &&
568 sizeof(regexp( ({strs[<1]}), "\\.[och]" )) ) return 0;
569
570 /* den Verzeichnisbaum von /d/ darf man natuerlich sonst lesen */
571 if (s<=2) return path;
572
573 /* eigenen Code darf man natuerlich auch lesen */
574 if (euid==strs[2] || euid==sprintf("d.%s.%s", strs[1], strs[2]))
575 return path;
576
577 /* Deputies haben ein gemeinsames Verzeichnis unter /d/erzmagier */
578 if (strs[1]=="erzmagier" && strs[2]=="polizei" && IS_DEPUTY(euid))
579 return path;
580
581 /* d/erzmagier darf man nur als Erzmagier lesen */
582 if (strs[1]=="erzmagier" && lev<ARCH_LVL) return 0;
583
584 /* einige Regionen haben std-verzeichnisse, die darf man natuerlich
585 auch mit Level 20 bereits komplett lesen! */
586 if (strs[2]=="std") return path;
587
588 /* "secure"-Verzeichnisse darf nur lesen, wer da auch schreiben darf */
589 if ( s > 4 && strs[<2] == "secure" && member( insecure, strs[2] ) < 0 ){
590 if ( lev < ELDER_LVL && !domain_master(euid, strs[1])
591 && !access_rights(strs, euid) )
592 return 0;
593 else
594 return path;
595 }
596
597 /* Dokus, Infos und .readme darf man immer lesen... */
598 if ( fun=="file_size" || !sizeof(regexp( ({strs[<1]}), "\\.[och]" )) )
599 return path;
600
601 /* Mit Level 20 darf man noch keinen fremden Code lesen! */
602 if (lev<=WIZARD_LVL) return 0;
603
604 /* Weise duerfen natuerlich alles weitere lesen */
605 if (lev>=ELDER_LVL) return path;
606
607 /* Regionsmagier in ihren Regionen natuerlich auch */
608 if (lev>=LORD_LVL && domain_master(euid, strs[1])) return path;
609
610 /* folgende Funktionen sind natuerlich voellig uninteressant */
611 if (member(({"get_dir", "restore_object"}), fun)!=-1)
612 return path;
613
614 /* Zugriff erlaubt, aber mitloggen */
615 write_file( READ_FILE, sprintf("%O %s %s: %s\n", fun, ctime()[4..],
616 euid, path) );
617 return path;
618 }
619 if (lev<ARCH_LVL) return 0;
620 return path;
621}
622