/* // File: /adm/obj/master/access.c // Purpose: Convert /adm/etc/access to a form the master.c can understand // Credits: // 92-12-21 Huthar wrote most of this, as part of TMI-2's distribution mudlib. // Please retain this header if you use any of this code. // 93-06-28 Pallando converted it to use domain_master() */ #include <uid.h> inherit "/adm/obj/master/groups"; #define ACCESS_FILE "/adm/etc/access" #define GROUP "/adm/obj/master" #define READ 1 #define WRITE 2 // #define DEBUG mapping access = ([]); void error_out( string msg, int line ) { write( "ERROR! " + ACCESS_FILE + " contains bad " + msg + " in line " + line + "\n" ); } mapping load_access() { string *lines; string file; int i, j; string *rest; int setbits; string path; string tmp, name; access = ([]); seteuid( ROOT_UID ); if( ( file = read_file( ACCESS_FILE ) ) == "" ) { write( "Error loading access file!\n" ); return copy( access ); } lines = explode( file, "\n" ); for( i = 0 ; i < sizeof( lines ) ; i++ ) { lines[i] = remove_whitespace( lines[i] ); if( lines[i][0] == '#' || lines[i] == "" ) continue; if( !sscanf( lines[i], "(%s)%s", path, lines[i] ) ) { error_out( "path", i + 1 ); return ([]); } rest = explode( lines[i], ":" ); for( j = 0; j <sizeof( rest ); j++ ) { if( !sscanf( rest[j], "%s[%s]", name, tmp ) ) { error_out( "name", i + 1 ); return 0; } if( name[0] == '(' && name[strlen( name ) - 1] == ')' ) name = "@" + name[1 .. strlen( name ) - 2]; if( !access[path] ) access[path] = ([]); if( !access[path][name] ) access[path] += ([ name : 0 ]); switch( tmp ) { case "w": access[path][name] |= WRITE; break; case "r": access[path][name] |= READ; break; case "wr": case "rw": access[path][name] |= READ | WRITE; break; } } } return copy( access ); } mapping query_access( string str ) { return copy( access[str] ); } int check_groups( mixed *grps, string eff_user, string path ) { int i, res, found; string tmp; for( i = 0 ; i < sizeof( grps ) ; i++ ) { if( grps[i][0] != '@' ) { if( grps[i] == eff_user ) { found = 1; res |= access[path][eff_user]; } } else { tmp = grps[i][1..strlen( grps[i] ) - 1]; if( tmp == "all" || GROUP-> query_member_group( eff_user, tmp ) ) { found = 1; res |= access[path][grps[i]]; } } } return found ? res : -1; } int check_access( string str, object act_ob ) { string *pth; string eff_user, tmp; int res; eff_user = geteuid( act_ob ); if( !eff_user ) return 0; // this is kind of important -Sulam if( sscanf( str, user_path( eff_user ) + "%s", tmp ) == 1 ) return( READ | WRITE ); pth = strsrch( str, "/" ) != -1 ? explode( str, "/" ) : ({str}); if( !pth ) pth = ({ }); // The following bit added by Pallando for domain-master-object hook: if( ( 1 < sizeof( pth ) ) && ( pth[0] == "d" ) && ( tmp = domain_master( pth[1] ) ) ) { if( eff_user == ROOT_UID ) return( READ | WRITE ); if( adminp(eff_user) ) return( READ | WRITE ); return (int)call_other( tmp, "valid_access", implode( pth[2 .. <1], "/" ), eff_user ); } if( eff_user == BACKBONE_UID && ( pth[0] == "obj" || pth[0] == "data" ) ) return( READ | WRITE ); while( 1 ) { if( !sizeof( pth ) ) str = "/"; else str = "/" + implode( pth, "/" ); if( access[str] ) { res = check_groups( keys( access[str] ), eff_user, str ); if( res >= 0 ) { return res; } } if( str == "/" ) break; pth = pth[0..<2]; } return 0; }