#include #include #include #include "session.h" #include "db/database_manager.h" #include "i_network_bridge.h" #include "lua_api.h" #include "lua_processor.h" #include "machine.h" #include "vfs.h" #include "util.h" vfs_node* find_node_by_id(vfs_node* root, long long id) { if(root->id == id) { return root; } for(auto const& [name, child] : root->children) { vfs_node* found = find_node_by_id(child, id); if(found) { return found; } } return nullptr; } Session::Session(Machine* home_machine, DatabaseManager* db_manager, MachineManager* machine_manager, INetworkBridge* network_bridge) : _machine_manager(machine_manager), _db_manager(db_manager), _network_bridge(network_bridge), _home_machine(home_machine), _session_machine(home_machine) { if(home_machine) _current_dir = home_machine->vfs_root; } Session::~Session(void) { } vfs_node* Session::get_current_dir(void) { return _current_dir; } Machine* Session::get_home_machine(void) { return _home_machine; } Machine* Session::get_session_machine(void) { return _session_machine; } DatabaseManager* Session::get_db_manager(void) { return _db_manager; } MachineManager* Session::get_machine_manager(void) { return _machine_manager; } INetworkBridge* Session::get_network_bridge(void) { return _network_bridge; } void Session::set_current_dir(vfs_node* node) { _current_dir = node; } void Session::set_session_machine(Machine* machine) { _session_machine = machine; if(_session_machine) { _current_dir = _session_machine->vfs_root; } } uint32_t Session::get_current_uid(void) { return _home_machine->owner_id; } uint32_t Session::get_current_gid(void) { return _home_machine->owner_id; } std::string Session::process_command(const std::string& command) { /* * Creating the Lua processor on-demand to ensure it exists on the same * thread that will execute the script. */ LuaProcessor lua(*this); /* Trim trailing whitespace. */ std::string cmd = command; size_t end = cmd.find_last_not_of(" \t\n\r"); cmd = (end == std::string::npos) ? "" : cmd.substr(0, end+1); /* === Generic script executer. === */ /* Parse the command and it's arguments. */ std::stringstream ss(cmd); std::string command_name; ss >> command_name; std::vector args; std::string arg; while(ss >> arg) { args.push_back(arg); } vfs_node* command_node = nullptr; if(command_name.find('/') != std::string::npos) { /* Path provided, find node directly. */ command_node = find_node_by_path(_session_machine->vfs_root, command_name); } else { /* No path, search current dir then /bin. */ vfs_node* current_dir = get_current_dir(); if(current_dir->children.count(command_name)) { command_node = current_dir->children.at(command_name); } else { vfs_node* bin_dir = find_node_by_path(_session_machine->vfs_root, "/bin"); if(bin_dir && bin_dir->children.count(command_name)) { command_node = bin_dir->children.at(command_name); } } } if(command_node) { if(command_node->type == EXEC_NODE) { if(!has_permission(command_node, *this, EXEC_PERM)) { return "Cannot execute '" + command_name + "': Permission denied."; } bool is_remote = (_session_machine != _home_machine); std::string deobfuscated_content = util::xor_string(command_node->content); sol::object result = lua.execute(deobfuscated_content, *this, args, is_remote); return result.is() ? result.as() : "[Script returned non-string value]"; } else if(command_node->type == DIR_NODE) { return "Cannot execute '" + command_name + "' It is a directory."; } else { return "Cannot execute '" + command_name + "': Not an executable file."; } } return "Unknown command: " + command_name; } std::string Session::write_file(const std::string& path, const std::string& content) { return api::write_file(*this, path, content); } std::string Session::read_file(const std::string& path) { vfs_node* root = get_session_machine()->vfs_root; vfs_node* node = nullptr; if(path[0] == '/') { node = find_node_by_path(root, path); } else { /* Relative path. */ vfs_node* current_dir = get_current_dir(); if(current_dir->children.count(path)) { node = current_dir->children.at(path); } } if(node && (node->type == FILE_NODE || node->type == EXEC_NODE)) { return node->content; } return "Error: file not found."; } std::string Session::get_username(void) { if(!_home_machine || !_home_machine->vfs_root) { return "unknown"; } vfs_node* passwd_node = find_node_by_path(_home_machine->vfs_root, "/etc/passwd"); if(!passwd_node || passwd_node->type != FILE_NODE) { return "unknown"; } std::stringstream ss(passwd_node->content); std::string line; uint32_t player_id = _home_machine->owner_id; while(std::getline(ss, line)) { std::vector parts; std::stringstream line_ss(line); std::string part; while(std::getline(line_ss, part, ':')) { parts.push_back(part); } if(parts.size() >= 3) { if(std::to_string(player_id) == parts[2]) { return parts[0]; /* Username. */ } } } return "unknown"; }