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