use mlua::{Function, Lua, Table, Value};
use crate::security::{DEFAULT_DENY_MODULES_LIST, DEFAULT_PRECISION_DENY_CONFIG};
use crate::security;
use std::collections::HashMap;
use log::{info, warn};
use crate::security::SAuthBasicCtrl;
pub type LuaApis = HashMap<String, Vec<String>>;
pub type Modules_no_suffix = Vec<String>;
pub fn deny_module_except(entity: &Lua, except_modules_list: LuaApis) -> Result<(), mlua::Error>{
let entity_globals = entity.globals();
for lib in &DEFAULT_DENY_MODULES_LIST {
if except_modules_list.contains_key(*lib) {
continue
} else {entity_globals.set(*lib, Value::Nil)?}
}
for (lib, apis) in DEFAULT_PRECISION_DENY_CONFIG {
let table = entity_globals.get::<Table>(*lib)?;
for api in *apis {
if except_modules_list.contains_key(*lib) {
if except_modules_list[*lib].contains( &String::from(*api) ) {
continue
}
}
table.set(*api, Value::Nil)?;
}
entity_globals.set(*lib, table)?;
}
Ok(())
}
pub type SHookApis = HashMap<String, (fn(module_api: &str), bool)>;
pub type S_YNHookTask = (LuaApis, SHookApis);
pub fn uni_hook_func_anonym(lua: &Lua, module: &str, target_func: &str, hook_func: fn()) -> Result<(), mlua::Error> {
let entity_globals = lua.globals();
let target_table = match module{
"global" => entity_globals,
_ => entity_globals.get::<Table>(module)?
};
let backup_func = target_table.get::<Function>(target_func)?;
let new_func = lua.create_function(move |_, args: mlua::MultiValue| {
hook_func();
let _: () = backup_func.call(args)?;
Ok(())
})?;
target_table.set(target_func, new_func)?;
Ok(())
}
pub fn batch_hook_sec(lua: &Lua, hook_task: S_YNHookTask) -> Result<(), mlua::Error> {
let target_apis = hook_task.0;
let hook_apis = hook_task.1; let global_table = lua.globals();
let lua_error: mlua::Function = lua.globals().get("error")?;
for (module, apis) in target_apis {
let target_module_result: Result<Table, mlua::Error> = match module.as_str() {
"global" => {
Ok(global_table.clone())
},
_ => {
global_table.get::<Table>(&*module)
}
};
let target_module = match target_module_result {
Ok(tbl) => tbl,
Err(_) => continue, };
for api in apis {
let backup_func_result: Result<Function, mlua::Error> = target_module.get(&*api);
let backup_func = match backup_func_result {
Ok(func) => func,
Err(_) => continue, }; let (hook_func, allow_or_not) = match hook_apis.get(&api) {
Some(hook) => *hook,
None => {
continue;
}
};
let whole_api = format!("{}.{}", module.clone(), api.clone());
let error_lua_api_to_func = lua_error.clone();
let new_func = lua.create_function(move |lua_ctx, args: mlua::MultiValue| -> Result<mlua::MultiValue, mlua::Error> {
hook_func(&whole_api);
if !allow_or_not {
info!("Denied {}", &whole_api);
error_lua_api_to_func.call::<_>("Rejected by mint.")?
}
warn!("Allowed {}", &whole_api);
backup_func.call::<mlua::MultiValue>(args)
})?; target_module.set(&*api, new_func)?; }
}
Ok(())
}
pub fn apply_security_sandbox(lua: &Lua) -> Result<(), mlua::Error> {
let security_config = security::get_default_auth_config();
security::security_audit_log(&security_config);
let (deny_list, _hook_callbacks) = security::generate_basic_ctrl_hook_task(&SAuthBasicCtrl::new());
deny_module_except(lua, deny_list)?;
Ok(())
}