1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "security_guard_napi.h"
16 #include <future>
17 #include <unistd.h>
18 #include <syscall.h>
19 #include <unordered_map>
20 #include <map>
21 #include <algorithm>
22
23 #include "napi_request_data_manager.h"
24 #include "napi_security_event_querier.h"
25 #include "security_event.h"
26 #include "security_config_update_info.h"
27 #include "security_event_ruler.h"
28 #include "security_guard_define.h"
29 #include "security_guard_log.h"
30 #include "security_guard_sdk_adaptor.h"
31 #include "i_collector_subscriber.h"
32 #include "uv.h"
33
34 #include "securec.h"
35
36 using namespace OHOS::Security::SecurityGuard;
37 using namespace OHOS::Security::SecurityCollector;
38 constexpr std::int32_t ARGS_SIZE_ONE = 1;
39 constexpr std::int32_t ARGS_SIZE_THREE = 3;
40 constexpr int PARAMZERO = 0;
41 constexpr int PARAMONE = 1;
42 constexpr char NAPI_EVENT_EVENT_ID_ATTR[] = "eventId";
43 constexpr char NAPI_EVENT_VERSION_ATTR[] = "version";
44 constexpr char NAPI_EVENT_CONTENT_ATTR[] = "content";
45
46 constexpr int NAPI_START_COLLECTOR_ARGS_CNT = 2;
47 constexpr int NAPI_STOP_COLLECTOR_ARGS_CNT = 1;
48 constexpr int NAPI_REPORT_EVENT_INFO_ARGS_CNT = 1;
49 constexpr int NAPI_UPDATE_POLICY_FILE_ARGS_CNT = 1;
50 constexpr int NAPI_GET_MODEL_RESULT_ARGS_CNT = 1;
51 constexpr int NAPI_QUERY_SECURITY_EVENT_ARGS_CNT = 2;
52
53 constexpr int TIME_MAX_LEN = 15;
54
55 using NAPI_QUERIER_PAIR = std::pair<pid_t, std::shared_ptr<NapiSecurityEventQuerier>>;
56 static std::unordered_map<napi_ref, NAPI_QUERIER_PAIR> queriers;
57 static std::mutex g_mutex;
58 std::map<napi_env, std::vector<SubscribeCBInfo *>> g_subscribers;
59
60 static const std::unordered_map<int32_t, std::pair<int32_t, std::string>> g_errorStringMap = {
61 { SUCCESS, { JS_ERR_SUCCESS, "The operation was successful" }},
62 { NO_PERMISSION, { JS_ERR_NO_PERMISSION, "check permission fail"} },
63 { BAD_PARAM, { JS_ERR_BAD_PARAM, "Parameter error, please make sure using the correct value"} },
64 { NO_SYSTEMCALL, { JS_ERR_NO_SYSTEMCALL, "non-system application uses the system API"} },
65 };
66
ConvertToJsErrMsg(int32_t code)67 static std::string ConvertToJsErrMsg(int32_t code)
68 {
69 auto iter = g_errorStringMap.find(code);
70 if (iter != g_errorStringMap.end()) {
71 return iter->second.second;
72 } else {
73 return "Unknown error, please reboot your device and try again";
74 }
75 }
76
ConvertToJsErrCode(int32_t code)77 static int32_t ConvertToJsErrCode(int32_t code)
78 {
79 auto iter = g_errorStringMap.find(code);
80 if (iter != g_errorStringMap.end()) {
81 return iter->second.first;
82 } else {
83 return JS_ERR_SYS_ERR;
84 }
85 }
86
NapiCreateObject(const napi_env env)87 static napi_value NapiCreateObject(const napi_env env)
88 {
89 napi_value result = nullptr;
90 napi_status status = napi_create_object(env, &result);
91 if (status != napi_ok || result == nullptr) {
92 SGLOGE("failed to create napi value of object type.");
93 }
94 return result;
95 }
96
NapiCreateString(const napi_env env,const std::string & value)97 static napi_value NapiCreateString(const napi_env env, const std::string &value)
98 {
99 napi_value result = nullptr;
100 napi_status status = napi_create_string_utf8(env, value.c_str(), NAPI_AUTO_LENGTH, &result);
101 SGLOGD("create napi value of string type, value is %{public}s.", value.c_str());
102 if (status != napi_ok || result == nullptr) {
103 SGLOGE("failed to create napi value of string type.");
104 }
105 return result;
106 }
107
NapiCreateInt64(const napi_env env,int64_t value)108 static napi_value NapiCreateInt64(const napi_env env, int64_t value)
109 {
110 napi_value result = nullptr;
111 napi_status status = napi_create_int64(env, value, &result);
112 SGLOGI("create napi value of int64 type, value is %{public}" PRId64 ".", value);
113 if (status != napi_ok || result == nullptr) {
114 SGLOGE("failed to create napi value of int64 type.");
115 }
116 return result;
117 }
118
NapiCreateInt32(const napi_env env,int32_t value)119 static napi_value NapiCreateInt32(const napi_env env, int32_t value)
120 {
121 napi_value result = nullptr;
122 napi_status status = napi_create_int32(env, value, &result);
123 SGLOGD("create napi value of int32 type, value is %{public}d.", value);
124 if (status != napi_ok || result == nullptr) {
125 SGLOGE("failed to create napi value of int32 type.");
126 }
127 return result;
128 }
129
NapiCreateUint32(const napi_env env,uint32_t value)130 static napi_value NapiCreateUint32(const napi_env env, uint32_t value)
131 {
132 napi_value result = nullptr;
133 napi_status status = napi_create_uint32(env, value, &result);
134 SGLOGI("create napi value of uint32 type, value is %{public}u.", value);
135 if (status != napi_ok || result == nullptr) {
136 SGLOGE("failed to create napi value of uint32 type.");
137 }
138 return result;
139 }
140
GenerateBusinessError(napi_env env,int32_t code)141 static napi_value GenerateBusinessError(napi_env env, int32_t code)
142 {
143 napi_value result;
144 SGLOGD("GenerateBusinessError code:%{public}d", code);
145 if (code == SUCCESS) {
146 napi_get_undefined(env, &result);
147 } else {
148 int32_t jsErrCode = ConvertToJsErrCode(code);
149 napi_value errCode = NapiCreateInt32(env, jsErrCode);
150
151 std::string errMsgStr = ConvertToJsErrMsg(code);
152 napi_value errMsg = NapiCreateString(env, errMsgStr);
153
154 napi_create_error(env, nullptr, errMsg, &result);
155 napi_set_named_property(env, result, "code", errCode);
156 napi_set_named_property(env, result, "message", errMsg);
157 }
158 return result;
159 }
160
GenerateBusinessError(napi_env env,int32_t code,const std::string & msg)161 static napi_value GenerateBusinessError(napi_env env, int32_t code, const std::string &msg)
162 {
163 napi_value result;
164 SGLOGD("GenerateBusinessError code:%{public}d", code);
165 if (code == SUCCESS) {
166 napi_get_undefined(env, &result);
167 } else {
168 int32_t jsErrCode = ConvertToJsErrCode(code);
169 napi_value errCode = NapiCreateInt32(env, jsErrCode);
170 napi_value errMsg = NapiCreateString(env, msg);
171
172 napi_create_error(env, nullptr, errMsg, &result);
173 napi_set_named_property(env, result, "code", errCode);
174 napi_set_named_property(env, result, "message", errMsg);
175 }
176 return result;
177 }
178
ParseInt64(napi_env env,napi_value object,const std::string & key,int64_t & value)179 static napi_value ParseInt64(napi_env env, napi_value object, const std::string &key, int64_t &value)
180 {
181 napi_value result;
182 bool hasProperty = false;
183 NAPI_CALL(env, napi_has_named_property(env, object, key.c_str(), &hasProperty));
184 if (!hasProperty) {
185 std::string msg = "no such param" + key;
186 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
187 return nullptr;
188 }
189 NAPI_CALL(env, napi_get_named_property(env, object, key.c_str(), &result));
190 if (result == nullptr) {
191 SGLOGE("get %{public}s failed", key.c_str());
192 return nullptr;
193 }
194
195 napi_valuetype type;
196 NAPI_CALL(env, napi_typeof(env, result, &type));
197 if (type != napi_number) {
198 SGLOGE("type of param %{public}s is not number", key.c_str());
199 return nullptr;
200 }
201
202 NAPI_CALL(env, napi_get_value_int64(env, result, &value));
203 return NapiCreateInt64(env, ConvertToJsErrCode(SUCCESS));
204 }
205
ParseInt32(napi_env env,napi_value object,const std::string & key,int32_t & value)206 static napi_value ParseInt32(napi_env env, napi_value object, const std::string &key, int32_t &value)
207 {
208 napi_value result;
209 bool hasProperty = false;
210 NAPI_CALL(env, napi_has_named_property(env, object, key.c_str(), &hasProperty));
211 if (!hasProperty) {
212 std::string msg = "no such param" + key;
213 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
214 return nullptr;
215 }
216 NAPI_CALL(env, napi_get_named_property(env, object, key.c_str(), &result));
217 if (result == nullptr) {
218 SGLOGE("get %{public}s failed", key.c_str());
219 return nullptr;
220 }
221
222 napi_valuetype type;
223 NAPI_CALL(env, napi_typeof(env, result, &type));
224 if (type != napi_number) {
225 SGLOGE("type of param %{public}s is not number", key.c_str());
226 return nullptr;
227 }
228
229 NAPI_CALL(env, napi_get_value_int32(env, result, &value));
230 return NapiCreateInt32(env, ConvertToJsErrCode(SUCCESS));
231 }
232
GetString(napi_env env,napi_value object,const std::string & key,char * value,size_t & maxLen)233 static napi_value GetString(napi_env env, napi_value object, const std::string &key, char *value, size_t &maxLen)
234 {
235 napi_valuetype type;
236 NAPI_CALL(env, napi_typeof(env, object, &type));
237 if (type != napi_string) {
238 std::string msg = "param " + key + " is not string";
239 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
240 return nullptr;
241 }
242
243 size_t size = 0;
244 NAPI_CALL(env, napi_get_value_string_utf8(env, object, nullptr, 0, &size));
245 if (size >= maxLen) {
246 std::string msg = "param " + key + " is too long";
247 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
248 return nullptr;
249 }
250
251 maxLen = size + 1;
252 NAPI_CALL(env, napi_get_value_string_utf8(env, object, value, maxLen, &maxLen));
253 return NapiCreateInt32(env, SUCCESS);
254 }
255
ParseString(napi_env env,napi_value object,const std::string & key,char * value,size_t & maxLen)256 static napi_value ParseString(napi_env env, napi_value object, const std::string &key, char *value, size_t &maxLen)
257 {
258 napi_value result;
259 NAPI_CALL(env, napi_get_named_property(env, object, key.c_str(), &result));
260 if (result == nullptr) {
261 std::string msg = "param " + key + " is not found";
262 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
263 return nullptr;
264 }
265
266 return GetString(env, result, key, value, maxLen);
267 }
268
ParseEventInfo(napi_env env,napi_value object,ReportSecurityEventInfoContext * context)269 static napi_value ParseEventInfo(napi_env env, napi_value object, ReportSecurityEventInfoContext *context)
270 {
271 napi_valuetype type = napi_undefined;
272 NAPI_CALL(env, napi_typeof(env, object, &type));
273 if (type != napi_object) {
274 GenerateBusinessError(env, BAD_PARAM, "type of param eventInfo is not object");
275 return nullptr;
276 }
277
278 if (ParseInt64(env, object, "eventId", context->eventId) == nullptr) {
279 return nullptr;
280 }
281
282 char version[VERSION_MAX_LEN] = {0};
283 size_t len = VERSION_MAX_LEN;
284 if (ParseString(env, object, "version", version, len) == nullptr) {
285 return nullptr;
286 }
287 context->version = version;
288
289 char content[CONTENT_MAX_LEN] = {0};
290 len = CONTENT_MAX_LEN;
291 if (ParseString(env, object, "content", content, len) == nullptr) {
292 return nullptr;
293 }
294 context->content = content;
295 return NapiCreateInt32(env, SUCCESS);
296 }
297
NapiReportSecurityInfo(napi_env env,napi_callback_info info)298 static napi_value NapiReportSecurityInfo(napi_env env, napi_callback_info info)
299 {
300 size_t argc = NAPI_REPORT_EVENT_INFO_ARGS_CNT;
301 napi_value argv[NAPI_REPORT_EVENT_INFO_ARGS_CNT] = {nullptr};
302 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
303 if (argc != NAPI_REPORT_EVENT_INFO_ARGS_CNT) {
304 SGLOGE("report eventInfo arguments count is not expected");
305 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
306 return nullptr;
307 }
308
309 ReportSecurityEventInfoContext context = {};
310 napi_value ret = ParseEventInfo(env, argv[0], &context);
311 if (ret == nullptr) {
312 SGLOGE("report eventInfo parse error");
313 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
314 return nullptr;
315 }
316
317 auto eventInfo = std::make_shared<EventInfo>(context.eventId, context.version, context.content);
318 int32_t code = SecurityGuardSdkAdaptor::ReportSecurityInfo(eventInfo);
319 if (code != SUCCESS) {
320 SGLOGE("report eventInfo error, code=%{public}d", code);
321 napi_throw(env, GenerateBusinessError(env, code));
322 return nullptr;
323 }
324 return NapiCreateInt32(env, SUCCESS);
325 }
326
IsNum(const std::string & s)327 static bool IsNum(const std::string &s)
328 {
329 return std::all_of(s.begin(), s.end(), isdigit);
330 }
331
GetConditionsTime(napi_env env,napi_value object,const std::string & key,std::string & value)332 static napi_value GetConditionsTime(napi_env env, napi_value object, const std::string &key, std::string &value)
333 {
334 char time[TIME_MAX_LEN] = {0};
335 size_t len = TIME_MAX_LEN;
336 bool hasProperty = false;
337 NAPI_CALL(env, napi_has_named_property(env, object, key.c_str(), &hasProperty));
338 if (!hasProperty) {
339 SGLOGE("no %{public}s param", key.c_str());
340 return NapiCreateInt32(env, SUCCESS);
341 }
342 napi_value result;
343 NAPI_CALL(env, napi_get_named_property(env, object, key.c_str(), &result));
344 if (result == nullptr) {
345 SGLOGE("get %{public}s failed", key.c_str());
346 return nullptr;
347 }
348
349 result = GetString(env, result, key, time, len);
350 if (result == nullptr) {
351 SGLOGE("get %{public}s failed", key.c_str());
352 return nullptr;
353 }
354 value = time;
355 if (!IsNum(value) || value.length() != (TIME_MAX_LEN - 1)) {
356 SGLOGE("time invalid %{public}s", key.c_str());
357 return nullptr;
358 }
359 return NapiCreateInt32(env, SUCCESS);
360 }
361
RequestSecurityModelResultExecute(napi_env env,void * data)362 static void RequestSecurityModelResultExecute(napi_env env, void *data)
363 {
364 if (data == nullptr) {
365 return;
366 }
367 auto *context = static_cast<RequestSecurityModelResultContext *>(data);
368 auto promise = std::make_shared<std::promise<SecurityModel>>();
369 auto future = promise->get_future();
370 auto func = [promise] (const std::string &devId, uint32_t modelId, const std::string &result) mutable -> int32_t {
371 SecurityModel model = {
372 .devId = devId,
373 .modelId = modelId,
374 .result = result
375 };
376 promise->set_value(model);
377 return SUCCESS;
378 };
379 context->ret = SecurityGuardSdkAdaptor::RequestSecurityModelResult(context->deviceId, context->modelId, "", func);
380 if (context->ret != SUCCESS) {
381 SGLOGE("RequestSecurityModelResultSync error, ret=%{public}d", context->ret);
382 return;
383 }
384 std::chrono::milliseconds span(TIMEOUT_REPLY);
385 if (future.wait_for(span) == std::future_status::timeout) {
386 SGLOGE("wait timeout");
387 context->ret = TIME_OUT;
388 return;
389 }
390 context->result = future.get();
391 }
392
GenerateSecurityModelResult(napi_env env,RequestSecurityModelResultContext * context)393 static napi_value GenerateSecurityModelResult(napi_env env, RequestSecurityModelResultContext *context)
394 {
395 napi_value ret = NapiCreateObject(env);
396 napi_value deviceId = NapiCreateString(env, context->result.devId.c_str());
397 napi_value modelId = NapiCreateUint32(env, context->result.modelId);
398 napi_value result = NapiCreateString(env, context->result.result.c_str());
399
400 napi_set_named_property(env, ret, NAPI_SECURITY_MODEL_RESULT_DEVICE_ID_ATTR, deviceId);
401 napi_set_named_property(env, ret, NAPI_SECURITY_MODEL_RESULT_MODEL_ID_ATTR, modelId);
402 napi_set_named_property(env, ret, NAPI_SECURITY_MODEL_RESULT_RESULT_ATTR, result);
403 return ret;
404 }
405
GenerateReturnValue(napi_env env,RequestSecurityModelResultContext * context)406 static napi_value GenerateReturnValue(napi_env env, RequestSecurityModelResultContext *context)
407 {
408 napi_value result;
409 if (context->ret == SUCCESS) {
410 result = GenerateSecurityModelResult(env, context);
411 } else {
412 napi_get_undefined(env, &result);
413 }
414 return result;
415 }
416
RequestSecurityModelResultComplete(napi_env env,napi_status status,void * data)417 static void RequestSecurityModelResultComplete(napi_env env, napi_status status, void *data)
418 {
419 if (data == nullptr) {
420 return;
421 }
422 auto *context = static_cast<RequestSecurityModelResultContext *>(data);
423 napi_value result[2] = {0};
424 result[0] = GenerateBusinessError(env, context->ret);
425 result[1] = GenerateReturnValue(env, context);
426 if (context->ref != nullptr) {
427 napi_value callbackfunc = nullptr;
428 napi_get_reference_value(env, context->ref, &callbackfunc);
429 napi_value returnVal;
430 napi_call_function(env, nullptr, callbackfunc, sizeof(result) / sizeof(result[0]), result, &returnVal);
431 napi_delete_reference(env, context->ref);
432 context->ref = nullptr;
433 } else {
434 if (context->ret == SUCCESS) {
435 napi_resolve_deferred(env, context->deferred, result[1]);
436 } else {
437 napi_reject_deferred(env, context->deferred, result[0]);
438 }
439 }
440 napi_delete_async_work(env, context->asyncWork);
441 delete context;
442 }
443
ParseModelId(napi_env env,std::string modelNameStr,uint32_t & modelId)444 static napi_value ParseModelId(napi_env env, std::string modelNameStr, uint32_t &modelId)
445 {
446 if (modelNameStr == "SecurityGuard_JailbreakCheck") {
447 modelId = ModelIdType::ROOT_SCAN_MODEL_ID;
448 } else if (modelNameStr == "SecurityGuard_IntegrityCheck") {
449 modelId = ModelIdType::DEVICE_COMPLETENESS_MODEL_ID;
450 } else if (modelNameStr == "SecurityGuard_SimulatorCheck") {
451 modelId = ModelIdType::PHYSICAL_MACHINE_DETECTION_MODEL_ID;
452 } else {
453 napi_throw(env, GenerateBusinessError(env, BAD_PARAM,
454 "Parameter error, please make sure using the correct model name"));
455 return nullptr;
456 }
457 return NapiCreateInt32(env, SUCCESS);
458 }
459
ParseOptionalString(napi_env env,napi_value object,const std::string & key,uint32_t maxLen)460 static std::string ParseOptionalString(napi_env env, napi_value object, const std::string &key, uint32_t maxLen)
461 {
462 bool hasProperty = false;
463 NAPI_CALL(env, napi_has_named_property(env, object, key.c_str(), &hasProperty));
464 if (!hasProperty) {
465 SGLOGE("no %{public}s param", key.c_str());
466 return "";
467 }
468 napi_value value = nullptr;
469 NAPI_CALL(env, napi_get_named_property(env, object, key.c_str(), &value));
470 if (value == nullptr) {
471 SGLOGE("get %{public}s failed", key.c_str());
472 return "";
473 }
474 size_t len = maxLen;
475 std::vector<char> str(len + 1, '\0');
476 napi_value result = GetString(env, value, key, str.data(), len);
477 if (result == nullptr) {
478 SGLOGE("get %{public}s failed", key.c_str());
479 return "";
480 }
481 return std::string{str.data()};
482 }
483
ParseModelRule(const napi_env & env,napi_value napiValue,ModelRule & modelRule)484 static bool ParseModelRule(const napi_env &env, napi_value napiValue, ModelRule &modelRule)
485 {
486 napi_valuetype type = napi_undefined;
487 NAPI_CALL_BASE(env, napi_typeof(env, napiValue, &type), false);
488 if (type != napi_object) {
489 std::string errMsg = "Parameter error. type of param ModelRule is not object.";
490 SGLOGE("Parameter error. type of param ModelRule is not object.");
491 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
492 return false;
493 }
494 char modelName[MODEL_NAME_MAX_LEN] = {0};
495 size_t len = MODEL_NAME_MAX_LEN;
496 if (ParseString(env, napiValue, "modelName", modelName, len) == nullptr) {
497 std::string errMsg = "Parameter error. type of param ModelRule.modelName is not string.";
498 SGLOGE("Parameter error. type of param ModelRule.modelName is not string.");
499 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
500 return false;
501 }
502 modelRule.modelName = std::string(modelName);
503 modelRule.param = ParseOptionalString(env, napiValue, "param", PARAM_MAX_LEN);
504 return true;
505 }
506
NapiGetModelResult(napi_env env,napi_callback_info info)507 static napi_value NapiGetModelResult(napi_env env, napi_callback_info info)
508 {
509 size_t argc = NAPI_GET_MODEL_RESULT_ARGS_CNT;
510 napi_value argv[NAPI_GET_MODEL_RESULT_ARGS_CNT] = {nullptr};
511 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
512 if (argc != NAPI_GET_MODEL_RESULT_ARGS_CNT) {
513 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "arguments count is not expected"));
514 return nullptr;
515 }
516 uint32_t modelId = 0;
517 ModelRule modelRule = {};
518 if (!ParseModelRule(env, argv[0], modelRule)) {
519 return nullptr;
520 }
521 if (ParseModelId(env, modelRule.modelName, modelId) == nullptr) {
522 return nullptr;
523 }
524
525 RequestSecurityModelResultContext *context = new (std::nothrow) RequestSecurityModelResultContext();
526 if (context == nullptr) {
527 napi_throw(env, GenerateBusinessError(env, NULL_OBJECT, "context new failed, no memory left."));
528 return nullptr;
529 }
530 context->modelId = modelId;
531 napi_value promise = nullptr;
532 NAPI_CALL(env, napi_create_promise(env, &context->deferred, &promise));
533 napi_value resourceName = NapiCreateString(env, "NapiGetModelResult");
534 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, RequestSecurityModelResultExecute,
535 RequestSecurityModelResultComplete, static_cast<void *>(context), &context->asyncWork));
536 NAPI_CALL(env, napi_queue_async_work(env, context->asyncWork));
537 return promise;
538 }
539
ParsePolicyFileInfo(napi_env env,napi_value object,NapiSecurityPolicyFileInfo * context)540 static napi_value ParsePolicyFileInfo(napi_env env, napi_value object, NapiSecurityPolicyFileInfo *context)
541 {
542 napi_valuetype type = napi_undefined;
543 NAPI_CALL(env, napi_typeof(env, object, &type));
544 if (type != napi_object) {
545 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "type of param eventInfo is not object"));
546 return nullptr;
547 }
548 if (ParseInt32(env, object, "fd", context->fd) == nullptr) {
549 return nullptr;
550 }
551 char name[FILE_NAME_MAX_LEN] = {0};
552 size_t len = FILE_NAME_MAX_LEN;
553 if (ParseString(env, object, "name", name, len) == nullptr) {
554 return nullptr;
555 }
556 context->fileName = name;
557 return NapiCreateInt32(env, SUCCESS);
558 }
559
UpdatePolicyExecute(napi_env env,void * data)560 static void UpdatePolicyExecute(napi_env env, void *data)
561 {
562 if (data == nullptr) {
563 return;
564 }
565 auto *context = static_cast<NapiSecurityPolicyFileInfo *>(data);
566 SecurityConfigUpdateInfo policyInfo(context->fd, context->fileName);
567 context->ret = SecurityGuardSdkAdaptor::ConfigUpdate(policyInfo);
568 if (context->ret != SUCCESS) {
569 SGLOGE("update policy file error, code=%{public}d", context->ret);
570 return;
571 }
572 }
573
UpdatePolicyComplete(napi_env env,napi_status status,void * data)574 static void UpdatePolicyComplete(napi_env env, napi_status status, void *data)
575 {
576 if (data == nullptr) {
577 return;
578 }
579 auto *context = static_cast<NapiSecurityPolicyFileInfo *>(data);
580 napi_value result {};
581 result = GenerateBusinessError(env, context->ret);
582 if (context->ret == SUCCESS) {
583 napi_resolve_deferred(env, context->deferred, result);
584 } else {
585 napi_reject_deferred(env, context->deferred, result);
586 }
587 napi_delete_async_work(env, context->asyncWork);
588 delete context;
589 }
590
NapiUpdatePolicyFile(napi_env env,napi_callback_info info)591 static napi_value NapiUpdatePolicyFile(napi_env env, napi_callback_info info)
592 {
593 SGLOGD("in NapiUpdatePolicyFile");
594 size_t argc = NAPI_UPDATE_POLICY_FILE_ARGS_CNT;
595 napi_value argv[NAPI_UPDATE_POLICY_FILE_ARGS_CNT] = {nullptr};
596 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
597 if (argc != NAPI_UPDATE_POLICY_FILE_ARGS_CNT) {
598 SGLOGE("update policy file count is not expected");
599 std::string msg = "update policy file count is not expected";
600 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, msg));
601 return nullptr;
602 }
603
604 NapiSecurityPolicyFileInfo *context = new (std::nothrow) NapiSecurityPolicyFileInfo();
605 if (context == nullptr) {
606 napi_throw(env, GenerateBusinessError(env, NULL_OBJECT, "context new failed, no memory left."));
607 return nullptr;
608 }
609
610 napi_value ret = ParsePolicyFileInfo(env, argv[0], context);
611 if (ret == nullptr) {
612 SGLOGE("policy file parse error");
613 delete context;
614 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
615 }
616
617 napi_value promise = nullptr;
618 NAPI_CALL(env, napi_create_promise(env, &context->deferred, &promise));
619 napi_value resourceName = NapiCreateString(env, "NapiUpdatePolicyFile");
620 NAPI_CALL(env, napi_create_async_work(env, nullptr, resourceName, UpdatePolicyExecute,
621 UpdatePolicyComplete, static_cast<void *>(context), &context->asyncWork));
622 NAPI_CALL(env, napi_queue_async_work(env, context->asyncWork));
623 return promise;
624 }
625
ParseEventForNotifyCollector(napi_env env,napi_value object,OHOS::Security::SecurityCollector::Event & event)626 static bool ParseEventForNotifyCollector(napi_env env, napi_value object,
627 OHOS::Security::SecurityCollector::Event &event)
628 {
629 napi_valuetype type = napi_undefined;
630 NAPI_CALL_BASE(env, napi_typeof(env, object, &type), false);
631 if (type != napi_object) {
632 SGLOGE("type of param event is not object");
633 return false;
634 }
635 int64_t eventId = 0;
636 if (ParseInt64(env, object, "eventId", eventId) == nullptr) {
637 return false;
638 }
639
640 event.eventId = eventId;
641 event.version = ParseOptionalString(env, object, "version", VERSION_MAX_LEN);
642 event.content = ParseOptionalString(env, object, "content", CONTENT_MAX_LEN);
643 event.extra = ParseOptionalString(env, object, "param", EXTRA_MAX_LEN);
644 SGLOGI("param extra end");
645 return true;
646 }
647
NapiStartSecurityEventCollector(napi_env env,napi_callback_info info)648 static napi_value NapiStartSecurityEventCollector(napi_env env, napi_callback_info info)
649 {
650 SGLOGD("===========================in NapiStartSecurityEventCollector");
651 size_t argc = NAPI_START_COLLECTOR_ARGS_CNT;
652 napi_value argv[NAPI_START_COLLECTOR_ARGS_CNT] = {nullptr};
653 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
654 if (argc != NAPI_START_COLLECTOR_ARGS_CNT && argc != NAPI_START_COLLECTOR_ARGS_CNT - 1) {
655 SGLOGE("notify arguments count is not expected");
656 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
657 return nullptr;
658 }
659
660 OHOS::Security::SecurityCollector::Event event{};
661 if (!ParseEventForNotifyCollector(env, argv[0], event)) {
662 SGLOGE("notify context parse error");
663 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "param event error"));
664 return nullptr;
665 }
666 NotifyCollectorContext context{event, -1};
667
668 if (argc == NAPI_START_COLLECTOR_ARGS_CNT) {
669 napi_valuetype type;
670 NAPI_CALL(env, napi_typeof(env, argv[1], &type));
671 if (type != napi_number) {
672 SGLOGE("type of param is not number");
673 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "param not number"));
674 return nullptr;
675 }
676 int64_t duration = -1;
677 napi_get_value_int64(env, argv[1], &duration);
678 if (duration <= 0) {
679 SGLOGE("duration of param is invalid");
680 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "param invalid"));
681 return nullptr;
682 }
683 context.duration = duration;
684 }
685
686 int32_t code = SecurityGuardSdkAdaptor::StartCollector(context.event, context.duration);
687 if (code != SUCCESS) {
688 SGLOGE("notify error, code=%{public}d", code);
689 napi_throw(env, GenerateBusinessError(env, code));
690 }
691 return NapiCreateInt32(env, ConvertToJsErrCode(code));
692 }
693
NapiStopSecurityEventCollector(napi_env env,napi_callback_info info)694 static napi_value NapiStopSecurityEventCollector(napi_env env, napi_callback_info info)
695 {
696 SGLOGD("===========================in NapiStopSecurityEventCollector");
697 size_t argc = NAPI_STOP_COLLECTOR_ARGS_CNT;
698 napi_value argv[NAPI_STOP_COLLECTOR_ARGS_CNT] = {nullptr};
699 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
700 if (argc != NAPI_STOP_COLLECTOR_ARGS_CNT) {
701 SGLOGE("notify arguments count is not expected");
702 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
703 return nullptr;
704 }
705
706 OHOS::Security::SecurityCollector::Event event{};
707 if (!ParseEventForNotifyCollector(env, argv[0], event)) {
708 SGLOGE("notify context parse error");
709 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "param event error"));
710 return nullptr;
711 }
712
713 int32_t code = SecurityGuardSdkAdaptor::StopCollector(event);
714 if (code != SUCCESS) {
715 SGLOGE("notify error, code=%{public}d", code);
716 napi_throw(env, GenerateBusinessError(env, code));
717 }
718 return NapiCreateInt32(env, ConvertToJsErrCode(code));
719 }
720
GetValueType(const napi_env env,const napi_value & value)721 static napi_valuetype GetValueType(const napi_env env, const napi_value& value)
722 {
723 napi_valuetype valueType = napi_undefined;
724 napi_status ret = napi_typeof(env, value, &valueType);
725 if (ret != napi_ok) {
726 SGLOGE("failed to parse the type of napi value.");
727 }
728 return valueType;
729 }
730
IsValueTypeValid(const napi_env env,const napi_value & object,const napi_valuetype typeName)731 static bool IsValueTypeValid(const napi_env env, const napi_value& object,
732 const napi_valuetype typeName)
733 {
734 napi_valuetype valueType = GetValueType(env, object);
735 if (valueType != typeName) {
736 SGLOGE("napi value type not match: valueType=%{public}d, typeName=%{public}d.", valueType, typeName);
737 return false;
738 }
739 return true;
740 }
741
CheckValueIsArray(const napi_env env,const napi_value & object)742 static bool CheckValueIsArray(const napi_env env, const napi_value& object)
743 {
744 if (!IsValueTypeValid(env, object, napi_valuetype::napi_object)) {
745 return false;
746 }
747 bool isArray = false;
748 napi_status ret = napi_is_array(env, object, &isArray);
749 if (ret != napi_ok) {
750 SGLOGE("failed to check array napi value.");
751 }
752 return isArray;
753 }
754
ParseSecurityEventRuler(const napi_env env,const napi_value & object)755 static SecurityEventRuler ParseSecurityEventRuler(const napi_env env, const napi_value& object)
756 {
757 SecurityEventRuler rule {};
758 if (!IsValueTypeValid(env, object, napi_valuetype::napi_object)) {
759 return rule;
760 }
761 napi_value result = nullptr;
762 int64_t eventId = 0;
763 result = ParseInt64(env, object, "eventId", eventId);
764 if (result == nullptr) {
765 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The eventId error."));
766 SGLOGE("get conditions beginTime error");
767 return rule;
768 }
769
770 std::string beginTime = "";
771 result = GetConditionsTime(env, object, "beginTime", beginTime);
772 if (result == nullptr) {
773 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The beginTime error."));
774 SGLOGE("get conditions beginTime error");
775 return rule;
776 }
777
778 std::string endTime = "";
779 result = GetConditionsTime(env, object, "endTime", endTime);
780 if (result == nullptr) {
781 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The endTime error."));
782 SGLOGE("get conditions endTime error");
783 return rule;
784 }
785 if (!beginTime.empty() && !endTime.empty() && beginTime > endTime) {
786 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The time matching error."));
787 SGLOGE("Time matching error");
788 return rule;
789 }
790
791 std::string param = ParseOptionalString(env, object, "param", EXTRA_MAX_LEN);
792 return { eventId, beginTime, endTime, param };
793 }
794
ParseSecurityEventRulers(const napi_env env,napi_value & object,std::vector<SecurityEventRuler> & rulers)795 static int32_t ParseSecurityEventRulers(const napi_env env, napi_value& object, std::vector<SecurityEventRuler>& rulers)
796 {
797 if (!CheckValueIsArray(env, object)) {
798 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The type of rulers must be array."));
799 return BAD_PARAM;
800 }
801 uint32_t len = 0;
802 napi_status status = napi_get_array_length(env, object, &len);
803 if (status != napi_ok) {
804 return BAD_PARAM;
805 }
806 napi_value element;
807 for (uint32_t i = 0; i < len; i++) {
808 status = napi_get_element(env, object, i, &element);
809 if (status != napi_ok) {
810 return BAD_PARAM;
811 }
812 if (IsValueTypeValid(env, element, napi_valuetype::napi_object)) {
813 auto ruler = ParseSecurityEventRuler(env, element);
814 rulers.emplace_back(ruler);
815 }
816 }
817 return SUCCESS;
818 }
819
820 template<typename T>
CompareAndReturnCacheItem(const napi_env env,napi_value & standard,std::unordered_map<napi_ref,std::pair<pid_t,std::shared_ptr<T>>> & resources)821 static typename std::unordered_map<napi_ref, std::pair<pid_t, std::shared_ptr<T>>>::iterator CompareAndReturnCacheItem(
822 const napi_env env, napi_value& standard,
823 std::unordered_map<napi_ref, std::pair<pid_t, std::shared_ptr<T>>>& resources)
824 {
825 bool found = false;
826 napi_status status;
827 auto iter = resources.begin();
828 for (; iter != resources.end(); iter++) {
829 if (iter->second.first != syscall(SYS_gettid)) { // avoid error caused by vm run in multi-thread
830 continue;
831 }
832 napi_value val = nullptr;
833 status = napi_get_reference_value(env, iter->first, &val);
834 if (status != napi_ok) {
835 continue;
836 }
837 status = napi_strict_equals(env, standard, val, &found);
838 if (status != napi_ok) {
839 continue;
840 }
841 if (found) {
842 break;
843 }
844 }
845 return iter;
846 }
847
NapiQuerySecurityEvent(napi_env env,napi_callback_info info)848 static napi_value NapiQuerySecurityEvent(napi_env env, napi_callback_info info)
849 {
850 size_t argc = NAPI_QUERY_SECURITY_EVENT_ARGS_CNT;
851 napi_value argv[NAPI_QUERY_SECURITY_EVENT_ARGS_CNT] = {nullptr};
852 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
853 if (argc != NAPI_QUERY_SECURITY_EVENT_ARGS_CNT) {
854 SGLOGE("query arguments count is not expected");
855 napi_throw(env, GenerateBusinessError(env, BAD_PARAM));
856 return nullptr;
857 }
858 size_t index = 0;
859 std::vector<SecurityEventRuler> rules;
860 if (auto ret = ParseSecurityEventRulers(env, argv[index], rules); ret != SUCCESS) {
861 SGLOGE("failed to parse query rules, result code is %{public}d.", ret);
862 return nullptr;
863 }
864 index++;
865 if (IsValueTypeValid(env, argv[index], napi_valuetype::napi_null) ||
866 IsValueTypeValid(env, argv[index], napi_valuetype::napi_undefined)) {
867 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Parameter error. The type of must querier be Querier."));
868 SGLOGE("querier is null or undefined.");
869 return nullptr;
870 }
871 auto context = new (std::nothrow) QuerySecurityEventContext;
872 if (context == nullptr) {
873 return nullptr;
874 }
875 context->env = env;
876 context->threadId = getproctid();
877 napi_create_reference(env, argv[index], 1, &context->ref);
878 auto querier = std::make_shared<NapiSecurityEventQuerier>(context, [] (const napi_env env, const napi_ref ref) {
879 napi_value querier = nullptr;
880 napi_get_reference_value(env, ref, &querier);
881 auto iter = CompareAndReturnCacheItem<NapiSecurityEventQuerier>(env, querier, queriers);
882 if (iter != queriers.end()) {
883 std::unique_lock<std::mutex> lock(g_mutex);
884 queriers.erase(iter->first);
885 NapiRequestDataManager::GetInstance().DelDataCallback(env);
886 }
887 SGLOGI("NapiSecurityEventQuerier OnFinsh Callback end.");
888 });
889 int32_t code = SecurityGuardSdkAdaptor::QuerySecurityEvent(rules, querier);
890 if (code != SUCCESS) {
891 SGLOGE("query error, code=%{public}d", code);
892 napi_throw(env, GenerateBusinessError(env, code));
893 }
894 queriers[context->ref] = std::make_pair(context->threadId, querier);
895 NapiRequestDataManager::GetInstance().AddDataCallback(env);
896 SGLOGI("NapiQuerySecurityEvent end.");
897 return nullptr;
898 }
899
GetCallbackProperty(napi_env env,napi_value obj,napi_ref & property,int argNum)900 static bool GetCallbackProperty(napi_env env, napi_value obj, napi_ref &property, int argNum)
901 {
902 napi_valuetype valueType = napi_undefined;
903 NAPI_CALL_BASE(env, napi_typeof(env, obj, &valueType), false);
904 if ((valueType == napi_undefined) || (valueType == napi_null)) {
905 SGLOGI("the callback is undefined or null");
906 return false;
907 } else if (valueType == napi_function) {
908 NAPI_CALL_BASE(env, napi_create_reference(env, obj, argNum, &property), false);
909 return true;
910 }
911 SGLOGE("the callback is not a napi_function");
912 return false;
913 }
914
GetStringProperty(napi_env env,napi_value obj,std::string & property)915 static bool GetStringProperty(napi_env env, napi_value obj, std::string &property)
916 {
917 napi_valuetype valuetype = napi_undefined;
918 NAPI_CALL_BASE(env, napi_typeof(env, obj, &valuetype), false);
919 if (valuetype != napi_string) {
920 return false;
921 }
922
923 size_t propLen;
924 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, nullptr, 0, &propLen), false);
925 property.reserve(propLen + 1);
926 property.resize(propLen);
927 NAPI_CALL_BASE(env, napi_get_value_string_utf8(env, obj, property.data(), propLen + 1, &propLen), false);
928 return true;
929 }
930
WrapVoidToJS(napi_env env)931 static napi_value WrapVoidToJS(napi_env env)
932 {
933 napi_value result = nullptr;
934 NAPI_CALL(env, napi_get_null(env, &result));
935 return result;
936 }
937
ParseAuditEventInfo(const napi_env & env,napi_value napi,SubscribeEventInfo & eventInfo)938 static napi_value ParseAuditEventInfo(const napi_env &env, napi_value napi, SubscribeEventInfo &eventInfo)
939 {
940 napi_valuetype type = napi_undefined;
941 NAPI_CALL_BASE(env, napi_typeof(env, napi, &type), nullptr);
942 if (type != napi_object) {
943 std::string errMsg = "Parameter error. type of param AuditEventInfo is not object.";
944 SGLOGE("Parameter error. type of param AuditEventInfo is not object.");
945 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
946 return nullptr;
947 }
948 int64_t eventId = 0;
949 if (ParseInt64(env, napi, "eventId", eventId) == nullptr) {
950 std::string errMsg = "Parameter error. type of param AuditEventInfo.eventId is not number.";
951 SGLOGE("Parameter error. type of param AuditEventInfo.eventId is not number.");
952 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
953 return nullptr;
954 }
955 eventInfo.eventId = eventId;
956 return NapiCreateInt64(env, ConvertToJsErrCode(SUCCESS));
957 }
958
ParseSubscribeForEventOccur(const napi_env & env,const std::string & type,SubscribeCBInfo * info,napi_value napiValue)959 static bool ParseSubscribeForEventOccur(const napi_env &env, const std::string &type,
960 SubscribeCBInfo *info, napi_value napiValue)
961 {
962 if (type != "securityEventOccur") {
963 std::string errMsg = "Parameter error. The param of type must be securityEventOccur.";
964 SGLOGE("Parameter error. The param of type must be securityEventOccur.");
965 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, "Type ERROR!"));
966 return false;
967 }
968 SubscribeEventInfo eventInfo;
969 if (ParseAuditEventInfo(env, napiValue, eventInfo) == nullptr) {
970 return false;
971 }
972 info->events.eventId = eventInfo.eventId;
973 return true;
974 }
975
ParseSubscribeParam(const napi_env & env,napi_callback_info cbInfo,SubscribeCBInfo * info,napi_value * thisVar)976 static bool ParseSubscribeParam(const napi_env &env, napi_callback_info cbInfo, SubscribeCBInfo *info,
977 napi_value *thisVar)
978 {
979 size_t argc = ARGS_SIZE_THREE;
980 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
981 napi_get_cb_info(env, cbInfo, &argc, argv, thisVar, NULL);
982 if (argc != ARGS_SIZE_THREE) {
983 SGLOGE("Parameter error. The parameters number must be three");
984 std::string errMsg = "Parameter error. The parameters number must be three";
985 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
986 return false;
987 }
988 if (!GetCallbackProperty(env, argv[argc - 1], info->callbackRef, 1)) {
989 SGLOGE("Get callbackRef failed");
990 std::string errMsg = "Parameter error. The type of arg " + std::to_string(argc) + " must be function";
991 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
992 return false;
993 }
994 std::string type;
995 if (!GetStringProperty(env, argv[PARAMZERO], type)) {
996 SGLOGE("Get type failed");
997 std::string errMsg = "The type of arg 1 must be string";
998 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
999 return false;
1000 }
1001 return ParseSubscribeForEventOccur(env, type, info, argv[PARAMONE]);
1002 }
1003
IsCurrentThread(std::thread::id threadId)1004 static bool IsCurrentThread(std::thread::id threadId)
1005 {
1006 std::thread::id currentThread = std::this_thread::get_id();
1007 if (threadId != currentThread) {
1008 SGLOGE("napi_ref can not be compared,different threadId");
1009 return false;
1010 }
1011 return true;
1012 }
1013
CompareOnAndOffRef(const napi_env env,napi_ref subscriberRef,napi_ref unsubscriberRef,std::thread::id threadId)1014 static bool CompareOnAndOffRef(const napi_env env, napi_ref subscriberRef, napi_ref unsubscriberRef,
1015 std::thread::id threadId)
1016 {
1017 if (!IsCurrentThread(threadId)) {
1018 return false;
1019 }
1020 napi_value subscriberCallback;
1021 napi_get_reference_value(env, subscriberRef, &subscriberCallback);
1022 napi_value unsubscriberCallback;
1023 napi_get_reference_value(env, unsubscriberRef, &unsubscriberCallback);
1024 bool result = false;
1025 napi_strict_equals(env, subscriberCallback, unsubscriberCallback, &result);
1026 return result;
1027 }
1028
IsSubscribeInMap(napi_env env,SubscribeCBInfo * info)1029 static bool IsSubscribeInMap(napi_env env, SubscribeCBInfo *info)
1030 {
1031 std::lock_guard<std::mutex> lock(g_mutex);
1032 auto subscribe = g_subscribers.find(env);
1033 if (subscribe == g_subscribers.end()) {
1034 return false;
1035 }
1036 auto it = subscribe->second.begin();
1037 while (it != subscribe->second.end()) {
1038 if (CompareOnAndOffRef(env, (*it)->callbackRef, info->callbackRef, (*it)->threadId)) {
1039 return true;
1040 }
1041 it++;
1042 }
1043 return false;
1044 }
1045
ParseUnsubscriberAuditEventInfo(const napi_env & env,napi_value napi)1046 static napi_value ParseUnsubscriberAuditEventInfo(const napi_env &env, napi_value napi)
1047 {
1048 napi_valuetype type = napi_undefined;
1049 NAPI_CALL_BASE(env, napi_typeof(env, napi, &type), nullptr);
1050 if (type != napi_object) {
1051 std::string errMsg = "Parameter error. type of param AuditEventInfo is not object.";
1052 SGLOGE("Parameter error. type of param AuditEventInfo is not object.");
1053 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1054 return nullptr;
1055 }
1056 int64_t eventId = 0;
1057 if (ParseInt64(env, napi, "eventId", eventId) == nullptr) {
1058 std::string errMsg = "Parameter error. type of param AuditEventInfo.eventId is not number.";
1059 SGLOGE("Parameter error. type of param AuditEventInfo.eventId is not number.");
1060 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1061 return nullptr;
1062 }
1063 return NapiCreateInt64(env, ConvertToJsErrCode(SUCCESS));
1064 }
1065
ParseParaToUnsubscriber(const napi_env & env,napi_callback_info cbInfo,UnsubscribeCBInfo * asyncContext,napi_value * thisVar)1066 static bool ParseParaToUnsubscriber(const napi_env &env, napi_callback_info cbInfo, UnsubscribeCBInfo *asyncContext,
1067 napi_value *thisVar)
1068 {
1069 size_t argc = ARGS_SIZE_THREE;
1070 napi_value argv[ARGS_SIZE_THREE] = {nullptr};
1071 napi_get_cb_info(env, cbInfo, &argc, argv, thisVar, NULL);
1072 if (argc != ARGS_SIZE_THREE) {
1073 SGLOGE("Parameter error. The parameters number must be three");
1074 std::string errMsg = "Parameter error. The parameters number must be three";
1075 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1076 return false;
1077 }
1078 if (!GetCallbackProperty(env, argv[argc - 1], asyncContext->callbackRef, 1)) {
1079 SGLOGE("Get callbackRef failed");
1080 std::string errMsg = "Parameter error. The type of arg " + std::to_string(argc) + " must be function";
1081 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1082 return false;
1083 }
1084 std::string type;
1085 if (!GetStringProperty(env, argv[PARAMZERO], type)) {
1086 std::string errMsg = "Parameter error. The type of arg 1 must be string";
1087 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1088 return false;
1089 }
1090 if (type != "securityEventOccur") {
1091 std::string errMsg = "Parameter error. arg 1 must be auditEventOccur";
1092 napi_throw(env, GenerateBusinessError(env, BAD_PARAM, errMsg));
1093 return false;
1094 }
1095 if (ParseUnsubscriberAuditEventInfo(env, argv[PARAMONE]) == nullptr) {
1096 return false;
1097 }
1098 return true;
1099 }
1100
GenerateEvent(napi_env env,const NapiSecurityEvent & event)1101 static napi_value GenerateEvent(napi_env env, const NapiSecurityEvent &event)
1102 {
1103 napi_value ret = NapiCreateObject(env);
1104 napi_value eventId = NapiCreateInt64(env, event.eventId);
1105 napi_value version = NapiCreateString(env, event.version.c_str());
1106 napi_value content = NapiCreateString(env, event.content.c_str());
1107
1108 napi_set_named_property(env, ret, NAPI_EVENT_EVENT_ID_ATTR, eventId);
1109 napi_set_named_property(env, ret, NAPI_EVENT_VERSION_ATTR, version);
1110 napi_set_named_property(env, ret, NAPI_EVENT_CONTENT_ATTR, content);
1111 return ret;
1112 }
1113
1114 class SubscriberPtr : public ICollectorSubscriber {
1115 public:
SubscriberPtr(const Event & event)1116 explicit SubscriberPtr(const Event &event) : ICollectorSubscriber(event) {};
1117 ~SubscriberPtr() override = default;
1118
OnNotify(const Event & event)1119 int32_t OnNotify(const Event &event) override
1120 {
1121 SGLOGI("OnNotify");
1122 uv_loop_s *loop = nullptr;
1123 napi_get_uv_event_loop(env_, &loop);
1124 if (loop == nullptr) {
1125 SGLOGE("loop instance is nullptr");
1126 return -1;
1127 }
1128 uv_work_t *work = new (std::nothrow) uv_work_t;
1129 if (work == nullptr) {
1130 SGLOGE("insufficient memory for work!");
1131 return -1;
1132 }
1133
1134 SubscriberOAWorker *subscriberOAWorker = new (std::nothrow) SubscriberOAWorker();
1135
1136 if (subscriberOAWorker == nullptr) {
1137 SGLOGE("insufficient memory for SubscriberAccountsWorker!");
1138 delete work;
1139 return -1;
1140 }
1141
1142 subscriberOAWorker->event.eventId = event.eventId;
1143 subscriberOAWorker->event.version = event.version;
1144 subscriberOAWorker->event.content = event.content;
1145 subscriberOAWorker->event.timestamp = event.timestamp;
1146 subscriberOAWorker->env = env_;
1147 subscriberOAWorker->ref = ref_;
1148 subscriberOAWorker->subscriber = this;
1149 work->data = reinterpret_cast<void *>(subscriberOAWorker);
1150 uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, UvQueueWorkOnAccountsChanged, uv_qos_default);
1151 return 0;
1152 };
1153
InitUvWorkCallbackEnv(uv_work_t * work,napi_handle_scope & scope)1154 static bool InitUvWorkCallbackEnv(uv_work_t *work, napi_handle_scope &scope)
1155 {
1156 if (work == nullptr) {
1157 SGLOGE("work is nullptr");
1158 return false;
1159 }
1160 if (work->data == nullptr) {
1161 SGLOGE("data is nullptr");
1162 return false;
1163 }
1164 CommonAsyncContext *data = reinterpret_cast<CommonAsyncContext *>(work->data);
1165 napi_open_handle_scope(data->env, &scope);
1166 if (scope == nullptr) {
1167 SGLOGE("fail to open scope");
1168 delete data;
1169 work->data = nullptr;
1170 return false;
1171 }
1172 return true;
1173 }
1174
UvQueueWorkOnAccountsChanged(uv_work_t * work,int status)1175 static void UvQueueWorkOnAccountsChanged(uv_work_t *work, int status)
1176 {
1177 SGLOGI("UvQueueWorkOnAccountsChanged");
1178 std::unique_ptr<uv_work_t> workPtr(work);
1179 napi_handle_scope scope = nullptr;
1180 if (!InitUvWorkCallbackEnv(work, scope)) {
1181 return;
1182 }
1183 std::unique_ptr<SubscriberOAWorker> subscriberOAWorkerData(reinterpret_cast<SubscriberOAWorker *>(work->data));
1184 bool isFound = false;
1185 {
1186 std::lock_guard<std::mutex> lock(g_mutex);
1187 SubscriberPtr *subscriber = subscriberOAWorkerData->subscriber;
1188 for (auto subscriberInstance : g_subscribers) {
1189 isFound = std::any_of(subscriberInstance.second.begin(), subscriberInstance.second.end(),
1190 [subscriber](const SubscribeCBInfo *item) {
1191 return item->subscriber.get() == subscriber;
1192 });
1193 if (isFound) {
1194 SGLOGI("subscriber has been found.");
1195 break;
1196 }
1197 }
1198 }
1199 if (isFound) {
1200 napi_value result[ARGS_SIZE_ONE] = {nullptr};
1201 result[PARAMZERO] = GenerateEvent(subscriberOAWorkerData->env, subscriberOAWorkerData->event);
1202 napi_value undefined = nullptr;
1203 napi_get_undefined(subscriberOAWorkerData->env, &undefined);
1204 napi_value callback = nullptr;
1205 napi_get_reference_value(subscriberOAWorkerData->env, subscriberOAWorkerData->ref, &callback);
1206 napi_value resultOut = nullptr;
1207 napi_status ok = napi_call_function(subscriberOAWorkerData->env, undefined, callback, ARGS_SIZE_ONE,
1208 &result[0], &resultOut);
1209 SGLOGI("isOk=%{public}d", ok);
1210 }
1211 napi_close_handle_scope(subscriberOAWorkerData->env, scope);
1212 }
1213
SetEnv(const napi_env & env)1214 void SetEnv(const napi_env &env) { env_ = env; }
SetCallbackRef(const napi_ref & ref)1215 void SetCallbackRef(const napi_ref &ref) { ref_ = ref; }
1216
1217 private:
1218 napi_env env_ = nullptr;
1219 napi_ref ref_ = nullptr;
1220 };
1221
Subscribe(napi_env env,napi_callback_info cbInfo)1222 static napi_value Subscribe(napi_env env, napi_callback_info cbInfo)
1223 {
1224 SubscribeCBInfo *info = new (std::nothrow) SubscribeCBInfo(env, std::this_thread::get_id());
1225 if (info == nullptr) {
1226 napi_throw(env, GenerateBusinessError(env, NULL_OBJECT, "No memory!"));
1227 return nullptr;
1228 }
1229
1230 napi_value thisVar = nullptr;
1231 if (!ParseSubscribeParam(env, cbInfo, info, &thisVar)) {
1232 delete info;
1233 SGLOGE("Parse subscribe failed");
1234 return nullptr;
1235 }
1236 info->subscriber = std::make_shared<SubscriberPtr>(info->events);
1237 info->subscriber->SetEnv(env);
1238 info->subscriber->SetCallbackRef(info->callbackRef);
1239 if (IsSubscribeInMap(env, info)) {
1240 delete info;
1241 return WrapVoidToJS(env);
1242 }
1243 int32_t errCode = SecurityGuardSdkAdaptor::Subscribe(info->subscriber);
1244 if (errCode != 0) {
1245 delete info;
1246 napi_throw(env, GenerateBusinessError(env, errCode, "Subscribe failed!"));
1247 return WrapVoidToJS(env);
1248 } else {
1249 std::lock_guard<std::mutex> lock(g_mutex);
1250 g_subscribers[env].emplace_back(info);
1251 }
1252 return WrapVoidToJS(env);
1253 }
1254
UnsubscribeSync(napi_env env,UnsubscribeCBInfo * unsubscribeCBInfo)1255 static void UnsubscribeSync(napi_env env, UnsubscribeCBInfo *unsubscribeCBInfo)
1256 {
1257 std::lock_guard<std::mutex> lock(g_mutex);
1258 auto subscribe = g_subscribers.find(env);
1259 if (subscribe == g_subscribers.end()) {
1260 return;
1261 }
1262 auto item = subscribe->second.begin();
1263 while (item != subscribe->second.end()) {
1264 if ((unsubscribeCBInfo->callbackRef != nullptr) &&
1265 (!CompareOnAndOffRef(env, (*item)->callbackRef, unsubscribeCBInfo->callbackRef, (*item)->threadId))) {
1266 item++;
1267 continue;
1268 }
1269 int errCode = SecurityGuardSdkAdaptor::Unsubscribe((*item)->subscriber);
1270 if (errCode != 0) {
1271 std::string errMsg = "unsubscrube failed";
1272 napi_throw(env, GenerateBusinessError(env, errCode, errMsg));
1273 return;
1274 }
1275 delete (*item);
1276 item = subscribe->second.erase(item);
1277 if (unsubscribeCBInfo->callbackRef != nullptr) {
1278 break;
1279 }
1280 }
1281 if (subscribe->second.empty()) {
1282 g_subscribers.erase(subscribe->first);
1283 }
1284 }
1285
Unsubscribe(napi_env env,napi_callback_info cbInfo)1286 static napi_value Unsubscribe(napi_env env, napi_callback_info cbInfo)
1287 {
1288 UnsubscribeCBInfo *unsubscribeCBInfo = new (std::nothrow) UnsubscribeCBInfo(env, std::this_thread::get_id());
1289 if (unsubscribeCBInfo == nullptr) {
1290 SGLOGE("insufficient memory for unsubscribeCBInfo!");
1291 napi_throw(env, GenerateBusinessError(env, NULL_OBJECT, "No memory!"));
1292 return WrapVoidToJS(env);
1293 }
1294 unsubscribeCBInfo->callbackRef = nullptr;
1295 unsubscribeCBInfo->throwErr = true;
1296
1297 napi_value thisVar = nullptr;
1298
1299 if (!ParseParaToUnsubscriber(env, cbInfo, unsubscribeCBInfo, &thisVar)) {
1300 delete unsubscribeCBInfo;
1301 SGLOGE("Parse unsubscribe failed");
1302 return nullptr;
1303 }
1304
1305 UnsubscribeSync(env, unsubscribeCBInfo);
1306 SGLOGI("UnsubscribeSync success");
1307 delete unsubscribeCBInfo;
1308 return WrapVoidToJS(env);
1309 }
1310
1311 EXTERN_C_START
SecurityGuardNapiRegister(napi_env env,napi_value exports)1312 static napi_value SecurityGuardNapiRegister(napi_env env, napi_value exports)
1313 {
1314 napi_property_descriptor desc[] = {
1315 DECLARE_NAPI_FUNCTION("startSecurityEventCollector", NapiStartSecurityEventCollector),
1316 DECLARE_NAPI_FUNCTION("stopSecurityEventCollector", NapiStopSecurityEventCollector),
1317 DECLARE_NAPI_FUNCTION("querySecurityEvent", NapiQuerySecurityEvent),
1318 DECLARE_NAPI_FUNCTION("reportSecurityEvent", NapiReportSecurityInfo),
1319 DECLARE_NAPI_FUNCTION("on", Subscribe),
1320 DECLARE_NAPI_FUNCTION("off", Unsubscribe),
1321 DECLARE_NAPI_FUNCTION("getModelResult", NapiGetModelResult),
1322 DECLARE_NAPI_FUNCTION("updatePolicyFile", NapiUpdatePolicyFile),
1323 };
1324 NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
1325 return exports;
1326 }
1327 EXTERN_C_END
1328
1329 static napi_module g_module = {
1330 .nm_version = 1,
1331 .nm_flags = 0,
1332 .nm_filename = nullptr,
1333 .nm_register_func = SecurityGuardNapiRegister,
1334 .nm_modname = "security.securityGuard",
1335 .nm_priv = reinterpret_cast<void *>(0),
1336 .reserved = { 0 },
1337 };
1338
RegisterModule(void)1339 extern "C" __attribute__((constructor)) void RegisterModule(void)
1340 {
1341 napi_module_register(&g_module);
1342 }