/* file access control room */ #include <access.h> #include "path.h" inherit "/std/room/basic_room"; #define LOGIN "/secure/login" #define READ_MASK 1 #define WRITE_MASK 2 #define GRANT_MASK 4 #define LOCK_MASK 8 int do_read(string euid, string path); int do_write(string euid, string path); int do_grant(string euid, string path); int do_lock(string path); int do_noread(string euid, string path); int do_nowrite(string euid, string path); int do_nogrant(string euid, string path); int do_unlock(string path); int do_summary(string str); int do_tidy(); void setup() { set_light(100); set_short("file-access control room"); add_property("determinate", "the "); set_long( "You are in a room full of filing cabinets. There are filing " "cabinets everywhere, they are all packed full of papers and look " "in a horrible mess.\n" "Available commands:\n" " read <euid> <path> : add read permission to the path.\n" " write <euid> <path> : add write permission to the path.\n" " grant <euid> <path> : add granting privileges to the path.\n" " lock <path> : restrict access to the path.\n" " noread <euid> <path> : remove read permission from the path.\n" " nowrite <euid> <path> : remove write permission from the path.\n" " nogrant <euid> <path> : remove granting privileges to the path.\n" " unlock <path> : remove restrictions to path.\n" " summary [path|euid] : give a list of all the read/write perms.\n" " tidy : tidy away unnecessary perms.\n" ); add_exit("east", ROOM+"domain_control", "corridor"); } /* setup() */ void init() { ::init(); this_player()->add_command("read", this_object(), "<string'euid'> <string'path'>", (: do_read($4[0], $4[1]) :) ); this_player()->add_command("write", this_object(), "<string'euid'> <string'path'>", (: do_write($4[0], $4[1]) :) ); this_player()->add_command("grant", this_object(), "<string'euid'> <string'path'>", (: do_grant($4[0], $4[1]) :) ); this_player()->add_command("lock", this_object(), "<string'path'>", (: do_lock($4[0]) :) ); this_player()->add_command("noread", this_object(), "<string'euid'> <string'path'>", (: do_noread($4[0], $4[1]) :) ); this_player()->add_command("nowrite", this_object(), "<string'euid'> <string'path'>", (: do_nowrite($4[0], $4[1]) :) ); this_player()->add_command("nogrant", this_object(), "<string'euid'> <string'path'>", (: do_nogrant($4[0], $4[1]) :) ); this_player()->add_command("unlock", this_object(), "<string'path'>", (: do_unlock($4[0]) :) ); this_player()->add_command("summary", this_object(), "<string'path or euid'>", (: do_summary($4[0]) :) ); this_player()->add_command("tidy", this_object(), "", (: do_tidy() :) ); } /* init() */ int do_read(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_read("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_read("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, READ_MASK)) { notify_fail("You do not have permission to add read access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->add_read_permission(euid, path); } /* do_read() */ int do_write(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_write("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_write("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, WRITE_MASK)) { notify_fail("You do not have permission to add write access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->add_write_permission(euid, path); } /* do_write() */ int do_grant(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_grant("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_grant("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, GRANT_MASK)) { notify_fail("You do not have permission to add grant access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->add_grant_permission(euid, path); } /* do_grant() */ int do_lock(string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_lock("+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_lock("+path+").\nBacktrace: "+ back_trace() :)); return 0; } if (!path) return notify_fail("Syntax: "+query_verb()+" <path>\n"); if (!master()->query_lord(previous_object(-1))) return notify_fail("You don't have permission to lock paths.\n"); if ((path[0..2] != "/d/") && !master()->high_programmer(previous_object(-1))) return notify_fail("You don't have permission to lock paths there.\n"); notify_fail("Something went wrong.\n"); return (int)master()->lock_path(path); } int do_noread(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_noread("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_noread("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, READ_MASK)) { notify_fail("You do not have permission to remove read access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->remove_read_permission(euid, path); } /* do_noread() */ int do_nowrite(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_nowrite("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_nowrite("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, WRITE_MASK)) { notify_fail("You do not have permission to remove write access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->remove_write_permission(euid, path); } /* do_nowrite() */ int do_nogrant(string euid, string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_nogrant("+euid+", "+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_nogrant("+euid+", "+path+").\nBacktrace: "+ back_trace() :)); return 0; } path = (string)this_player()->get_path(path); if (!master()->high_programmer(previous_object(-1)) && !master()->valid_grant(previous_object(), path, GRANT_MASK)) { notify_fail("You do not have permission to remove grant access.\n"); return 0; } notify_fail("Something went wrong.\n"); return (int)master()->remove_grant_permission(euid, path); } /* do_nogrant() */ int do_unlock(string path) { if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event(users(), "inform", "Illegal attempt to call do_unlock("+path+") by "+ this_player()->one_short(), "cheat"); unguarded((: write_file, "/log/CHEAT", ctime(time())+": Illegal attempt " "to call do_unlock("+path+").\nBacktrace: "+ back_trace() :)); return 0; } if (!path) return notify_fail("Syntax: "+query_verb()+" <path>\n"); if (!master()->query_lord(previous_object(-1))) return notify_fail("You don't have permission to lock paths.\n"); if ((path[0..2] != "/d/") && !master()->high_programmer(previous_object(-1))) return notify_fail("You don't have permission to lock paths there.\n"); notify_fail("Something went wrong.\n"); return (int)master()->unlock_path(path); } int list_before( string first, string second ) { if ( first < second ) return -1; if ( first > second ) return 1; return 0; } /* list_before() */ int do_summary(string str) { mapping perms; string *paths, *euids, ret, creator; int i, j, k; perms = (mapping)master()->query_permissions(); if (str) { if (!perms[str]) { if (!LOGIN->test_user(str) && !master()->valid_euid(str)) { write("There are no permissions for "+str+".\n"); return 1; } else { creator = str; } } else { perms = ([ str : perms[str] ]); } } paths = sort_array( m_indices( perms ), "list_before", this_object() ); if (!sizeof(paths)) ret = "No permissions set.\n"; else ret = sprintf("%11-s Path\n", "Euid"); for (i=0;i<sizeof(paths);i++) { euids = m_indices(perms[paths[i]]); for (j=0;j<sizeof(euids);j++) { if (!creator || (euids[j] == creator ) ) { k = perms[paths[i]][euids[j]]; if (k & LOCK_MASK) ret += sprintf("%11-s LCK %s\n", euids[j], paths[i]); else ret += sprintf("%11-s %c%c%c %s\n", euids[j],(k & READ_MASK?'R':' '), (k & WRITE_MASK?'W':' '), (k & GRANT_MASK?'G':' '), paths[i]); } } } this_player()->more_string( ret, "Permissions", 1 ); return 1; } /* do_summary() */ int do_tidy() { int i, j, perm, same; string path, creator, *bits; mapping perms, euids, others; if (!sizeof(filter(previous_object(-1), (: interactive($1) :)))) { event( users(), "inform", "illegal attempt to call do_tidy() by "+ (string)this_player()->query_name(), "cheat" ); unguarded((: write_file, "/log/CHEAT", ctime( time() ) +": illegal " "attempt to call do_tidy() by "+ (string)this_player()->query_name() +"\n" :)); return notify_fail( "Failed.\n" ); } perms = (mapping)master()->query_permissions(); foreach( path in keys( perms ) ) { euids = perms[ path ]; foreach( creator in keys( euids ) ) { perm = euids[ creator ]; if ( !LOGIN->test_creator( creator ) && !master()->valid_euid( creator ) ) { write( "No creator: "+ creator +".\n" ); if ( perm & READ_MASK ) master()->remove_read_permission( creator, path ); if ( perm & WRITE_MASK ) master()->remove_write_permission( creator, path ); if ( perm & GRANT_MASK ) master()->remove_grant_permission( creator, path ); continue; } if ( path == "/" ) continue; same = perms[ "/" ][ creator ] & perm; if ( same ) { write( "Access to / supercedes "+ path +" for "+ creator +".\n" ); if ( same & READ_MASK ) master()->remove_read_permission( creator, path ); if ( same & WRITE_MASK ) master()->remove_write_permission( creator, path ); if ( same & GRANT_MASK ) master()->remove_grant_permission( creator, path ); continue; } bits = explode( path, "/" ); j = sizeof( bits ) - 1; for ( i = 0; i < j; i++ ) { others = perms[ "/"+ implode( bits[ 0 .. i ], "/" ) ]; if ( !others ) continue; same = others[ creator ] & perm; if ( same ) { write( "Access to /"+ implode( bits[ 0 .. i ], "/" ) + " supercedes "+ path +" for "+ creator +".\n" ); if ( same & READ_MASK ) master()->remove_read_permission( creator, path ); if ( same & WRITE_MASK ) master()->remove_write_permission( creator, path ); if ( same & GRANT_MASK ) master()->remove_grant_permission( creator, path ); break; } } } } return 1; } /* do_tidy() */