/src/node/src/permission/permission.h
Line | Count | Source |
1 | | #ifndef SRC_PERMISSION_PERMISSION_H_ |
2 | | #define SRC_PERMISSION_PERMISSION_H_ |
3 | | |
4 | | #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
5 | | |
6 | | #include "debug_utils.h" |
7 | | #include "node_options.h" |
8 | | #include "permission/addon_permission.h" |
9 | | #include "permission/child_process_permission.h" |
10 | | #include "permission/fs_permission.h" |
11 | | #include "permission/inspector_permission.h" |
12 | | #include "permission/net_permission.h" |
13 | | #include "permission/permission_base.h" |
14 | | #include "permission/wasi_permission.h" |
15 | | #include "permission/worker_permission.h" |
16 | | #include "v8.h" |
17 | | |
18 | | #include <string_view> |
19 | | #include <unordered_map> |
20 | | |
21 | | namespace node { |
22 | | |
23 | | class Environment; |
24 | | |
25 | | namespace fs { |
26 | | class FSReqBase; |
27 | | } |
28 | | |
29 | | namespace permission { |
30 | | |
31 | | #define THROW_IF_INSUFFICIENT_PERMISSIONS(env, perm, resource, ...) \ |
32 | 0 | do { \ |
33 | 0 | node::Environment* env__ = (env); \ |
34 | 0 | const node::permission::PermissionScope perm__ = (perm); \ |
35 | 0 | const auto resource__ = (resource); \ |
36 | 0 | if (!env__->permission()->is_granted(env__, perm__, resource__)) \ |
37 | 0 | [[unlikely]] { \ |
38 | 0 | node::permission::Permission::ThrowAccessDenied( \ |
39 | 0 | env__, perm__, resource__); \ |
40 | 0 | return __VA_ARGS__; \ |
41 | 0 | } \ |
42 | 0 | } while (0) |
43 | | |
44 | | #define ASYNC_THROW_IF_INSUFFICIENT_PERMISSIONS( \ |
45 | | env, wrap, perm, resource, ...) \ |
46 | 0 | do { \ |
47 | 0 | node::Environment* env__ = (env); \ |
48 | 0 | const node::permission::PermissionScope perm__ = (perm); \ |
49 | 0 | const auto resource__ = (resource); \ |
50 | 0 | if (!env__->permission()->is_granted(env__, perm__, resource__)) \ |
51 | 0 | [[unlikely]] { \ |
52 | 0 | node::permission::Permission::AsyncThrowAccessDenied( \ |
53 | 0 | env__, (wrap), perm__, resource__); \ |
54 | 0 | return __VA_ARGS__; \ |
55 | 0 | } \ |
56 | 0 | } while (0) |
57 | | |
58 | | #define ERR_ACCESS_DENIED_IF_INSUFFICIENT_PERMISSIONS( \ |
59 | | env, perm, resource, args, ...) \ |
60 | 0 | do { \ |
61 | 0 | node::Environment* env__ = (env); \ |
62 | 0 | const node::permission::PermissionScope perm__ = (perm); \ |
63 | 0 | const auto resource__ = (resource); \ |
64 | 0 | if (!env__->permission()->is_granted(env__, perm__, resource__)) \ |
65 | 0 | [[unlikely]] { \ |
66 | 0 | Local<Value> err_access; \ |
67 | 0 | if (node::permission::CreateAccessDeniedError(env__, perm__, resource__) \ |
68 | 0 | .ToLocal(&err_access)) { \ |
69 | 0 | args.GetReturnValue().Set(err_access); \ |
70 | 0 | } else { \ |
71 | 0 | args.GetReturnValue().Set(UV_EACCES); \ |
72 | 0 | } \ |
73 | 0 | return __VA_ARGS__; \ |
74 | 0 | } \ |
75 | 0 | } while (0) |
76 | | |
77 | | #define SET_INSUFFICIENT_PERMISSION_ERROR_CALLBACK(scope) \ |
78 | 0 | void InsufficientPermissionError(std::string_view resource) { \ |
79 | 0 | v8::HandleScope handle_scope(env()->isolate()); \ |
80 | 0 | v8::Context::Scope context_scope(env()->context()); \ |
81 | 0 | v8::Local<v8::Value> arg; \ |
82 | 0 | if (!permission::CreateAccessDeniedError(env(), (scope), resource) \ |
83 | 0 | .ToLocal(&arg)) { \ |
84 | 0 | } \ |
85 | 0 | MakeCallback(env()->oncomplete_string(), 1, &arg); \ |
86 | 0 | } Unexecuted instantiation: node::cares_wrap::GetNameInfoReqWrap::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::AnyTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::ATraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::AaaaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::CaaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::CnameTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::MxTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::NsTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::TlsaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::TxtTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::SrvTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::PtrTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::NaptrTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::SoaTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) Unexecuted instantiation: node::cares_wrap::QueryWrap<node::cares_wrap::ReverseTraits>::InsufficientPermissionError(std::__1::basic_string_view<char, std::__1::char_traits<char> >) |
87 | | |
88 | | class Permission { |
89 | | public: |
90 | | Permission(); |
91 | | |
92 | | FORCE_INLINE bool is_granted(Environment* env, |
93 | | const PermissionScope permission, |
94 | 0 | const std::string_view& res = "") const { |
95 | 0 | if (!enabled_) [[likely]] { |
96 | 0 | return true; |
97 | 0 | } |
98 | 0 | return is_scope_granted(env, permission, res); |
99 | 0 | } |
100 | | |
101 | 0 | FORCE_INLINE bool enabled() const { return enabled_; } |
102 | | |
103 | | static PermissionScope StringToPermission(const std::string& perm); |
104 | | static const char* PermissionToString(PermissionScope perm); |
105 | | static void ThrowAccessDenied(Environment* env, |
106 | | PermissionScope perm, |
107 | | const std::string_view& res); |
108 | | static void AsyncThrowAccessDenied(Environment* env, |
109 | | fs::FSReqBase* req_wrap, |
110 | | PermissionScope perm, |
111 | | const std::string_view& res); |
112 | | |
113 | | // CLI Call |
114 | | void Apply(Environment* env, |
115 | | const std::vector<std::string>& allow, |
116 | | PermissionScope scope); |
117 | | void EnablePermissions(); |
118 | | |
119 | | private: |
120 | | COLD_NOINLINE bool is_scope_granted(Environment* env, |
121 | | const PermissionScope permission, |
122 | 0 | const std::string_view& res = "") const { |
123 | 0 | auto perm_node = nodes_.find(permission); |
124 | 0 | if (perm_node != nodes_.end()) { |
125 | 0 | return perm_node->second->is_granted(env, permission, res); |
126 | 0 | } |
127 | 0 | return false; |
128 | 0 | } |
129 | | |
130 | | std::unordered_map<PermissionScope, std::shared_ptr<PermissionBase>> nodes_; |
131 | | bool enabled_; |
132 | | }; |
133 | | |
134 | | v8::MaybeLocal<v8::Value> CreateAccessDeniedError(Environment* env, |
135 | | PermissionScope perm, |
136 | | const std::string_view& res); |
137 | | |
138 | | } // namespace permission |
139 | | |
140 | | } // namespace node |
141 | | |
142 | | #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS |
143 | | #endif // SRC_PERMISSION_PERMISSION_H_ |