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