securd.c

来自「C实现的MUD,对大家基本入门网络游戏很有帮助!」· C语言 代码 · 共 429 行 · 第 1/2 页

C
429
字号
                                        //不能识别的类型
                                        return 0;
                        }
                        break;
                default:
                        //权限设置操作不能识别!
                        return 0;
        }
        save();
        restore_list();
        return 1;
}

void create()
{
        //在wizlist属性里储存,而不再在/adm/etc/wizlist里存储!
        set("channel_id","安全精灵");
        restore();
        restore_list(); 
}

string *query_wizlist() { return keys(wiz_status); }

// 这个函数返回一个uid或者obj的status
string get_status(mixed ob)
{
        string euid;
        if( objectp(ob) ) 
        {
                euid = geteuid(ob);
                if( !euid ) euid = getuid(ob);
        }
        else if( stringp(ob) ) euid = ob;
        if( !undefinedp(wiz_status[euid]) ) return wiz_status[euid];
        else if( member_array(euid, wiz_levels)!=-1 ) return euid;
        else return "(player)";
}

int get_wiz_level(mixed ob)
{
        return member_array(get_status(ob), wiz_levels);
}

int set_status(mixed ob, string status)
{
        string uid;

        //应该检查一下status是否格式正确!
        if( geteuid(previous_object())!= ROOT_UID)
                if(!wiz_level(previous_object())>wiz_level("(admin)"))//允许admin设置巫师表
                        return 0;
        if( previous_object(0)!=find_object("/cmds/adm/access"))
        return 0;
        //这个地方应该严格审核是否有权进行提升操作!
        if( objectp(ob)&&userp(ob) )    
                uid = getuid(ob);
        else 
                if(stringp(ob))
                        uid = ob;
                else
                {
                        CHANNEL_D->do_channel(this_object(),"sys","非法设置巫师级别:"+ob+" "+status+"\n");
                        return 0;
                }
        if( status == "(player)" )
                map_delete(wiz_status, uid);
        else
                wiz_status[uid] = status;
        set("wiz_status",wiz_status);
        save();
        log_file( "static/promotion", capitalize(uid)
         + " 成为 " + status + " 时间:" + "/cmds/usr/rtime.c"->chinese_time(5,ctime(time())) + "\n" );
        return 1;
}

string *get_wizlist() { return keys(wiz_status); }

int valid_read(string file, mixed user, string func)
{
        string euid, status, *path, dir;
        int i;
        if( !objectp(user) )
                error("SECURITY_D->valid_read: user这个参数的值非法!\n");
        // Modify By JackyBoy
        if(file==query_save_file()) return 1;//如果是自身的存储文件,则任何人都可以读取!
        if( func=="restore_object" ) {
                if(sscanf(file,DATA_DIR+"SaveRoom/%*s"))
                        return 1;
                if( sscanf(base_name(user), "/clone/%*s")
                        && sscanf(file, "/data/%*s")
                        && file == (string)user->query_save_file()+__SAVE_EXTENSION__  )
                        return 1;
                if( sscanf(file,"/data/board/%*s"))
                        return 1;//允许无条件读取board数据
        }

        // 取得用户的euid和status
        euid = geteuid(user);
        if( !euid ) return 0;
        status = get_status(user);
        //"NONAME"在系统刚启动时经常遇到,所以这应该是安全的
        //不过这也是建立在没有人可以自己设置自己的euid这个基础上的。
        if( euid==ROOT_UID|| euid=="NONAME" ) return 1;
        //immortal以上的才可以进入/u目录!
        if((file=="/u/"||file=="/u")&&wiz_level(status)>wiz_level("(immortal)"))
        return 1;
        //对于/u下的可以读自己的目录!
        if( sscanf(file, "/u/" + euid + "/%*s") 
                ||file=="/u/"+euid)
return 1;
  if( sscanf(file, "/" + "/%*s") 
                ||file=="/")
return 1;

        path = explode(file, "/");

        // 检查读排除表!如果排除了,则直接返回1,否则继续判断!
        // 由于编码的关系,"/"被"\n"取代!
        for(i=sizeof(path)-1; i>=0; i--) {
                dir = implode(path[0..i], "\n");
                //此处如果exclude_read为空就出错!
                if( undefinedp(exclude_read[dir]) ) continue;
                if( member_array(euid, exclude_read[dir])!=-1 ) return 0;
                if( member_array(status, exclude_read[dir])!=-1 ) return 0;
        }

        // 检查读信任表,如果信任则返回1,否则失败
        if( member_array(euid, trusted_read["\n"])!=-1 ) return 1;
        if( member_array(status, trusted_read["\n"])!=-1 ) return 1;
        for(i=sizeof(path)-1; i>=0; i--) {
                dir = implode(path[0..i], "\n");
                if( undefinedp(trusted_read[dir]) ) continue;
                if( member_array(euid, trusted_read[dir])!=-1 ) return 1;
                if( member_array(status, trusted_read[dir])!=-1 ) return 1;
        }
        if(wizhood(user)!="(player)")
                log_file("wiz_read_fail.log", sprintf("%s(%s) 试图越权读取 %s !\n", 
                        geteuid(user), wizhood(user), file));
        else
                log_file("read_fail.log", sprintf("%s(%s) 试图调用 %s 失败。\n", 
                        geteuid(user), wizhood(user), file));
        return 0;
}

int valid_write(string file, mixed user, string func)
{
        string euid, status, *path, dir;
        int i;

        if( !objectp(user) )
                error("SECURITY_D->valid_write: 参数user的值非法!\n");

        if( sscanf(file, LOG_DIR + "%*s") && func=="write_file" ) return 1;
        
        // 让用户和可存储对象能存储自己的
        // 或许可以使用这样的算法:如果USERP(user),那么如果file==user->query_save_file()就可以写?
        if( func=="save_object" )
        {
                if( sscanf(base_name(user), "/clone/%*s")
                        &&      sscanf(file, "/data/%*s")
                        &&      file == (string)user->query_save_file()+__SAVE_EXTENSION__  )
                    return 1;
            log_file("dpm.log","错误存储:\n"+user->name(1)+geteuid(user)+get_status(user)+
                "file:"+file+"\n");
        }

        // Get the euid and status of the user.
        euid = geteuid(user);

        if( !euid ) return 0;
        if( euid==ROOT_UID || euid=="NONAME") return 1;
        //不可读就不可写 add by jackyboy
        if(valid_read(file,user,func)==0)
                return 0;
        status = get_status(user);

        path = explode(file, "/");

        // 检查写排除表,如果被排除则返回0,否则继续判断
        // 编码的关系,在"/"分离后再用"\n"合并判断!
        for(i=sizeof(path)-1; i>=0; i--) {
                dir = implode(path[0..i], "\n");
                if( undefinedp(exclude_write[dir]) ) continue;
                if( member_array(euid, exclude_write[dir])!=-1 ) return 0;
                if( member_array(status, exclude_write[dir])!=-1 ) return 0;
        }

        // 检查新信任表,如果信任则返回1,否则不允许写!
        if( member_array(euid, trusted_write["\n"])!=-1 ) return 1;
        if( member_array(status, trusted_write["\n"])!=-1 ) return 1;
        for(i=sizeof(path)-1; i>=0; i--) {
                dir = implode(path[0..i], "\n");
                if( undefinedp(trusted_write[dir]) ) continue;
                if( member_array(euid, trusted_write[dir])!=-1 ) return 1;
                if( member_array(status, trusted_write[dir])!=-1 ) return 1;
        }

        log_file("write_fail.log", sprintf("%s(%s) 试图写入 %s 失败。\n", geteuid(user), wizhood(user), file));
        return 0;
}

int valid_seteuid( object ob, string uid )
{
        if( uid==0 ) return 1;
        if( uid==getuid(ob) ) return 1;
        if( getuid(ob)==ROOT_UID ) return 1;
        if( sscanf(file_name(ob), "/adm/%*s") ) return 1;
        if( wiz_status[uid] != "(admin)"
        &&      wiz_status[getuid(ob)] == "(admin)" )
                return 1;
        return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?