%PDF- %PDF-
Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/permission/ |
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/src/permission/fs_permission.cc |
#include "fs_permission.h" #include "base_object-inl.h" #include "debug_utils-inl.h" #include "path.h" #include "v8.h" #include <fcntl.h> #include <limits.h> #include <stdlib.h> #include <algorithm> #include <filesystem> #include <string> #include <string_view> #include <vector> namespace { std::string WildcardIfDir(const std::string& res) noexcept { uv_fs_t req; int rc = uv_fs_stat(nullptr, &req, res.c_str(), nullptr); if (rc == 0) { const uv_stat_t* const s = static_cast<const uv_stat_t*>(req.ptr); if (s->st_mode & S_IFDIR) { // add wildcard when directory if (res.back() == node::kPathSeparator) { return res + "*"; } return res + node::kPathSeparator + "*"; } } uv_fs_req_cleanup(&req); return res; } void FreeRecursivelyNode( node::permission::FSPermission::RadixTree::Node* node) { if (node == nullptr) { return; } if (node->children.size()) { for (auto& c : node->children) { FreeRecursivelyNode(c.second); } } if (node->wildcard_child != nullptr) { delete node->wildcard_child; } delete node; } bool is_tree_granted( const node::permission::FSPermission::RadixTree* granted_tree, const std::string_view& param) { #ifdef _WIN32 // is UNC file path if (param.rfind("\\\\", 0) == 0) { // return lookup with normalized param size_t starting_pos = 4; // "\\?\" if (param.rfind("\\\\?\\UNC\\") == 0) { starting_pos += 4; // "UNC\" } auto normalized = param.substr(starting_pos); return granted_tree->Lookup(normalized, true); } #endif return granted_tree->Lookup(param, true); } void PrintTree(const node::permission::FSPermission::RadixTree::Node* node, size_t spaces = 0) { std::string whitespace(spaces, ' '); if (node == nullptr) { return; } if (node->wildcard_child != nullptr) { node::per_process::Debug(node::DebugCategory::PERMISSION_MODEL, "%s Wildcard: %s\n", whitespace, node->prefix); } else { node::per_process::Debug(node::DebugCategory::PERMISSION_MODEL, "%s Prefix: %s\n", whitespace, node->prefix); if (node->children.size()) { size_t child = 0; for (const auto& pair : node->children) { ++child; node::per_process::Debug(node::DebugCategory::PERMISSION_MODEL, "%s Child(%s): %s\n", whitespace, child, std::string(1, pair.first)); PrintTree(pair.second, spaces + 2); } node::per_process::Debug(node::DebugCategory::PERMISSION_MODEL, "%s End of tree - child(%s)\n", whitespace, child); } else { node::per_process::Debug(node::DebugCategory::PERMISSION_MODEL, "%s End of tree: %s\n", whitespace, node->prefix); } } } } // namespace namespace node { namespace permission { // allow = '*' // allow = '/tmp/,/home/example.js' void FSPermission::Apply(Environment* env, const std::vector<std::string>& allow, PermissionScope scope) { for (const std::string& res : allow) { if (res == "*") { if (scope == PermissionScope::kFileSystemRead) { deny_all_in_ = false; allow_all_in_ = true; } else { deny_all_out_ = false; allow_all_out_ = true; } return; } GrantAccess(scope, PathResolve(env, {res})); } } void FSPermission::GrantAccess(PermissionScope perm, const std::string& res) { const std::string path = WildcardIfDir(res); if (perm == PermissionScope::kFileSystemRead) { granted_in_fs_.Insert(path); deny_all_in_ = false; } else if (perm == PermissionScope::kFileSystemWrite) { granted_out_fs_.Insert(path); deny_all_out_ = false; } } bool FSPermission::is_granted(PermissionScope perm, const std::string_view& param = "") const { switch (perm) { case PermissionScope::kFileSystem: return allow_all_in_ && allow_all_out_; case PermissionScope::kFileSystemRead: return !deny_all_in_ && ((param.empty() && allow_all_in_) || allow_all_in_ || is_tree_granted(&granted_in_fs_, param)); case PermissionScope::kFileSystemWrite: return !deny_all_out_ && ((param.empty() && allow_all_out_) || allow_all_out_ || is_tree_granted(&granted_out_fs_, param)); default: return false; } } FSPermission::RadixTree::RadixTree() : root_node_(new Node("")) {} FSPermission::RadixTree::~RadixTree() { FreeRecursivelyNode(root_node_); } bool FSPermission::RadixTree::Lookup(const std::string_view& s, bool when_empty_return) const { FSPermission::RadixTree::Node* current_node = root_node_; if (current_node->children.size() == 0) { return when_empty_return; } size_t parent_node_prefix_len = current_node->prefix.length(); const std::string path(s); auto path_len = path.length(); while (true) { if (parent_node_prefix_len == path_len && current_node->IsEndNode()) { return true; } auto node = current_node->NextNode(path, parent_node_prefix_len); if (node == nullptr) { return false; } current_node = node; parent_node_prefix_len += current_node->prefix.length(); if (current_node->wildcard_child != nullptr && path_len >= (parent_node_prefix_len - 2 /* slash* */)) { return true; } } } void FSPermission::RadixTree::Insert(const std::string& path) { FSPermission::RadixTree::Node* current_node = root_node_; size_t parent_node_prefix_len = current_node->prefix.length(); size_t path_len = path.length(); for (size_t i = 1; i <= path_len; ++i) { bool is_wildcard_node = path[i - 1] == '*'; bool is_last_char = i == path_len; if (is_wildcard_node || is_last_char) { std::string node_path = path.substr(parent_node_prefix_len, i); current_node = current_node->CreateChild(node_path); } if (is_wildcard_node) { current_node = current_node->CreateWildcardChild(); parent_node_prefix_len = i; } } if (UNLIKELY(per_process::enabled_debug_list.enabled( DebugCategory::PERMISSION_MODEL))) { per_process::Debug(DebugCategory::PERMISSION_MODEL, "Inserting %s\n", path); PrintTree(root_node_); } } } // namespace permission } // namespace node