/src/node/src/permission/permission.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include "permission.h" |
2 | | #include "base_object-inl.h" |
3 | | #include "env-inl.h" |
4 | | #include "memory_tracker-inl.h" |
5 | | #include "node.h" |
6 | | #include "node_errors.h" |
7 | | #include "node_external_reference.h" |
8 | | |
9 | | #include "v8.h" |
10 | | |
11 | | #include <memory> |
12 | | #include <string> |
13 | | #include <vector> |
14 | | |
15 | | namespace node { |
16 | | |
17 | | using v8::Context; |
18 | | using v8::FunctionCallbackInfo; |
19 | | using v8::Local; |
20 | | using v8::Object; |
21 | | using v8::String; |
22 | | using v8::Value; |
23 | | |
24 | | namespace permission { |
25 | | |
26 | | namespace { |
27 | | |
28 | | // permission.has('fs.in', '/tmp/') |
29 | | // permission.has('fs.in') |
30 | 0 | static void Has(const FunctionCallbackInfo<Value>& args) { |
31 | 0 | Environment* env = Environment::GetCurrent(args); |
32 | 0 | v8::Isolate* isolate = env->isolate(); |
33 | 0 | CHECK(args[0]->IsString()); |
34 | | |
35 | 0 | String::Utf8Value utf8_deny_scope(isolate, args[0]); |
36 | 0 | if (*utf8_deny_scope == nullptr) { |
37 | 0 | return; |
38 | 0 | } |
39 | | |
40 | 0 | const std::string deny_scope = *utf8_deny_scope; |
41 | 0 | PermissionScope scope = Permission::StringToPermission(deny_scope); |
42 | 0 | if (scope == PermissionScope::kPermissionsRoot) { |
43 | 0 | return args.GetReturnValue().Set(false); |
44 | 0 | } |
45 | | |
46 | 0 | if (args.Length() > 1 && !args[1]->IsUndefined()) { |
47 | 0 | String::Utf8Value utf8_arg(isolate, args[1]); |
48 | 0 | if (*utf8_arg == nullptr) { |
49 | 0 | return; |
50 | 0 | } |
51 | 0 | return args.GetReturnValue().Set( |
52 | 0 | env->permission()->is_granted(scope, *utf8_arg)); |
53 | 0 | } |
54 | | |
55 | 0 | return args.GetReturnValue().Set(env->permission()->is_granted(scope)); |
56 | 0 | } |
57 | | |
58 | | } // namespace |
59 | | |
60 | | #define V(Name, label, _) \ |
61 | 0 | if (perm == PermissionScope::k##Name) return #Name; |
62 | 0 | const char* Permission::PermissionToString(const PermissionScope perm) { |
63 | 0 | PERMISSIONS(V) |
64 | 0 | return nullptr; |
65 | 0 | } |
66 | | #undef V |
67 | | |
68 | | #define V(Name, label, _) \ |
69 | 0 | if (perm == label) return PermissionScope::k##Name; |
70 | 0 | PermissionScope Permission::StringToPermission(const std::string& perm) { |
71 | 0 | PERMISSIONS(V) |
72 | 0 | return PermissionScope::kPermissionsRoot; |
73 | 0 | } |
74 | | #undef V |
75 | | |
76 | 126k | Permission::Permission() : enabled_(false) { |
77 | 126k | std::shared_ptr<PermissionBase> fs = std::make_shared<FSPermission>(); |
78 | 126k | std::shared_ptr<PermissionBase> child_p = |
79 | 126k | std::make_shared<ChildProcessPermission>(); |
80 | 126k | std::shared_ptr<PermissionBase> worker_t = |
81 | 126k | std::make_shared<WorkerPermission>(); |
82 | 126k | std::shared_ptr<PermissionBase> inspector = |
83 | 126k | std::make_shared<InspectorPermission>(); |
84 | 126k | #define V(Name, _, __) \ |
85 | 380k | nodes_.insert(std::make_pair(PermissionScope::k##Name, fs)); |
86 | 380k | FILESYSTEM_PERMISSIONS(V) |
87 | 126k | #undef V |
88 | 126k | #define V(Name, _, __) \ |
89 | 126k | nodes_.insert(std::make_pair(PermissionScope::k##Name, child_p)); |
90 | 126k | CHILD_PROCESS_PERMISSIONS(V) |
91 | 126k | #undef V |
92 | 126k | #define V(Name, _, __) \ |
93 | 126k | nodes_.insert(std::make_pair(PermissionScope::k##Name, worker_t)); |
94 | 126k | WORKER_THREADS_PERMISSIONS(V) |
95 | 126k | #undef V |
96 | 126k | #define V(Name, _, __) \ |
97 | 126k | nodes_.insert(std::make_pair(PermissionScope::k##Name, inspector)); |
98 | 126k | INSPECTOR_PERMISSIONS(V) |
99 | 126k | #undef V |
100 | 126k | } |
101 | | |
102 | | void Permission::ThrowAccessDenied(Environment* env, |
103 | | PermissionScope perm, |
104 | 0 | const std::string_view& res) { |
105 | 0 | Local<Value> err = ERR_ACCESS_DENIED(env->isolate()); |
106 | 0 | CHECK(err->IsObject()); |
107 | 0 | if (err.As<Object>() |
108 | 0 | ->Set(env->context(), |
109 | 0 | env->permission_string(), |
110 | 0 | v8::String::NewFromUtf8(env->isolate(), |
111 | 0 | PermissionToString(perm), |
112 | 0 | v8::NewStringType::kNormal) |
113 | 0 | .ToLocalChecked()) |
114 | 0 | .IsNothing() || |
115 | 0 | err.As<Object>() |
116 | 0 | ->Set(env->context(), |
117 | 0 | env->resource_string(), |
118 | 0 | v8::String::NewFromUtf8(env->isolate(), |
119 | 0 | std::string(res).c_str(), |
120 | 0 | v8::NewStringType::kNormal) |
121 | 0 | .ToLocalChecked()) |
122 | 0 | .IsNothing()) |
123 | 0 | return; |
124 | 0 | env->isolate()->ThrowException(err); |
125 | 0 | } |
126 | | |
127 | 0 | void Permission::EnablePermissions() { |
128 | 0 | if (!enabled_) { |
129 | 0 | enabled_ = true; |
130 | 0 | } |
131 | 0 | } |
132 | | |
133 | | void Permission::Apply(Environment* env, |
134 | | const std::vector<std::string>& allow, |
135 | 0 | PermissionScope scope) { |
136 | 0 | auto permission = nodes_.find(scope); |
137 | 0 | if (permission != nodes_.end()) { |
138 | 0 | permission->second->Apply(env, allow, scope); |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | void Initialize(Local<Object> target, |
143 | | Local<Value> unused, |
144 | | Local<Context> context, |
145 | 126k | void* priv) { |
146 | 126k | SetMethodNoSideEffect(context, target, "has", Has); |
147 | | |
148 | 126k | target->SetIntegrityLevel(context, v8::IntegrityLevel::kFrozen).FromJust(); |
149 | 126k | } |
150 | | |
151 | 0 | void RegisterExternalReferences(ExternalReferenceRegistry* registry) { |
152 | 0 | registry->Register(Has); |
153 | 0 | } |
154 | | |
155 | | } // namespace permission |
156 | | } // namespace node |
157 | | |
158 | | NODE_BINDING_CONTEXT_AWARE_INTERNAL(permission, node::permission::Initialize) |
159 | | NODE_BINDING_EXTERNAL_REFERENCE(permission, |
160 | | node::permission::RegisterExternalReferences) |