• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 
16 #include "cm_napi_dialog_common.h"
17 
18 #include <unordered_map>
19 #include "securec.h"
20 
21 #include "cm_log.h"
22 #include "cm_type.h"
23 #include "iservice_registry.h"
24 #include "bundle_mgr_proxy.h"
25 #include "system_ability_definition.h"
26 
27 #define BYTE_SHIFT_16           0x10
28 #define BYTE_SHIFT_8            0x08
29 #define BYTE_SHIFT_6            0x06
30 #define BASE64_URL_TABLE_SIZE   0x3F
31 #define BASE64_GROUP_NUM        3
32 #define BYTE_INDEX_ZONE         0
33 #define BYTE_INDEX_ONE          1
34 #define BYTE_INDEX_TWO          2
35 #define BYTE_INDEX_THREE        3
36 #define BASE64_PADDING          "="
37 #define BYTE_END_ONE            1
38 #define BYTE_END_TWO            2
39 
40 static const char g_base64Table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
41 namespace CMNapi {
42 namespace {
43 constexpr int CM_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M
44 
45 static const std::string DIALOG_NO_PERMISSION_MSG = "the caller has no permission";
46 static const std::string DIALOG_INVALID_PARAMS_MSG = "the input parameters is invalid";
47 static const std::string DIALOG_GENERIC_MSG = "there is an internal error";
48 static const std::string DIALOG_OPERATION_CANCELS_MSG = "the user cancels the installation operation";
49 static const std::string DIALOG_INSTALL_FAILED_MSG = "the user install certificate failed"
50     " in the certificate manager dialog";
51 static const std::string DIALOG_NOT_SUPPORTED_MSG = "the API is not supported on this device";
52 
53 static const std::string DIALOG_OPERATION_FAILED_MSG = "the user operation failed "
54     "in the certification manager dialog: ";
55 static const std::string PARSE_CERT_FAILED_MSG = "parse the certificate failed.";
56 static const std::string ADVANCED_SECURITY_MSG = "the device enters advanced security mode.";
57 static const std::string INCORRECT_FORMAT_MSG = "the certificate is in an invalid format.";
58 static const std::string MAX_QUANTITY_REACHED_MSG = "the number of certificates or credentials "
59     "reaches the maxinum allowed.";
60 static const std::string SA_INTERNAL_ERROR_MSG = "sa internal error.";
61 static const std::string NOT_EXIST_MSG = "the certificate dose not exist.";
62 static const std::string NOT_ENTERPRISE_DEVICE_MSG = "The operation does not comply with the device security policy,"
63     "such as the device does not allow users to manage the ca certificate of the global user.";
64 
65 static const std::unordered_map<int32_t, int32_t> DIALOG_CODE_TO_JS_CODE_MAP = {
66     // no permission
67     { CMR_DIALOG_ERROR_PERMISSION_DENIED, HAS_NO_PERMISSION },
68     // internal error
69     { CMR_DIALOG_ERROR_INTERNAL, DIALOG_ERROR_GENERIC },
70     // the user cancels the installation operation
71     { CMR_DIALOG_ERROR_OPERATION_CANCELS, DIALOG_ERROR_OPERATION_CANCELED },
72     // the user install certificate failed in the certificate manager dialog
73     { CMR_DIALOG_ERROR_INSTALL_FAILED, DIALOG_ERROR_INSTALL_FAILED },
74     // the API is not supported on this device
75     { CMR_DIALOG_ERROR_NOT_SUPPORTED, DIALOG_ERROR_NOT_SUPPORTED },
76     // The input parameter is invalid
77     { CMR_DIALOG_ERROR_PARAM_INVALID, PARAM_ERROR },
78 
79     { CMR_DIALOG_ERROR_PARSE_CERT_FAILED, DIALOG_ERROR_INSTALL_FAILED },
80     { CMR_DIALOG_ERROR_ADVANCED_SECURITY, DIALOG_ERROR_INSTALL_FAILED },
81     { CMR_DIALOG_ERROR_INCORRECT_FORMAT, DIALOG_ERROR_INSTALL_FAILED },
82     { CMR_DIALOG_ERROR_MAX_QUANTITY_REACHED, DIALOG_ERROR_INSTALL_FAILED },
83     { CMR_DIALOG_ERROR_SA_INTERNAL_ERROR, DIALOG_ERROR_INSTALL_FAILED },
84     { CMR_DIALOG_ERROR_NOT_EXIST, DIALOG_ERROR_INSTALL_FAILED },
85     { CMR_DIALOG_ERROR_NOT_ENTERPRISE_DEVICE, DIALOG_ERROR_NOT_COMPLY_SECURITY_POLICY },
86 };
87 
88 static const std::unordered_map<int32_t, std::string> DIALOG_CODE_TO_MSG_MAP = {
89     { CMR_DIALOG_ERROR_PERMISSION_DENIED, DIALOG_NO_PERMISSION_MSG },
90     { CMR_DIALOG_ERROR_INTERNAL, DIALOG_GENERIC_MSG },
91     { CMR_DIALOG_ERROR_OPERATION_CANCELS, DIALOG_OPERATION_CANCELS_MSG },
92     { CMR_DIALOG_ERROR_INSTALL_FAILED, DIALOG_INSTALL_FAILED_MSG },
93     { CMR_DIALOG_ERROR_NOT_SUPPORTED, DIALOG_NOT_SUPPORTED_MSG },
94     { CMR_DIALOG_ERROR_NOT_ENTERPRISE_DEVICE, NOT_ENTERPRISE_DEVICE_MSG },
95     { CMR_DIALOG_ERROR_PARAM_INVALID, DIALOG_INVALID_PARAMS_MSG },
96 
97     { CMR_DIALOG_ERROR_PARSE_CERT_FAILED, DIALOG_OPERATION_FAILED_MSG + PARSE_CERT_FAILED_MSG },
98     { CMR_DIALOG_ERROR_ADVANCED_SECURITY, DIALOG_OPERATION_FAILED_MSG + ADVANCED_SECURITY_MSG },
99     { CMR_DIALOG_ERROR_INCORRECT_FORMAT, DIALOG_OPERATION_FAILED_MSG + INCORRECT_FORMAT_MSG },
100     { CMR_DIALOG_ERROR_MAX_QUANTITY_REACHED, DIALOG_OPERATION_FAILED_MSG + MAX_QUANTITY_REACHED_MSG },
101     { CMR_DIALOG_ERROR_SA_INTERNAL_ERROR, DIALOG_OPERATION_FAILED_MSG + SA_INTERNAL_ERROR_MSG },
102     { CMR_DIALOG_ERROR_NOT_EXIST, DIALOG_OPERATION_FAILED_MSG + NOT_EXIST_MSG },
103 };
104 }  // namespace
105 
StartUIExtensionAbility(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,OHOS::AAFwk::Want want,std::shared_ptr<CmUIExtensionCallback> uiExtCallback)106 void StartUIExtensionAbility(std::shared_ptr<CmUIExtensionRequestContext> asyncContext,
107     OHOS::AAFwk::Want want, std::shared_ptr<CmUIExtensionCallback> uiExtCallback)
108 {
109     CM_LOG_D("begin StartUIExtensionAbility");
110     auto abilityContext = asyncContext->context;
111     if (abilityContext == nullptr) {
112         CM_LOG_E("abilityContext is null");
113         ThrowError(asyncContext->env, PARAM_ERROR, "abilityContext is null");
114         return;
115     }
116     auto uiContent = abilityContext->GetUIContent();
117     if (uiContent == nullptr) {
118         CM_LOG_E("uiContent is null");
119         ThrowError(asyncContext->env, PARAM_ERROR, "uiContent is null");
120         return;
121     }
122 
123     OHOS::Ace::ModalUIExtensionCallbacks extensionCallbacks = {
124         [uiExtCallback](int32_t releaseCode) { uiExtCallback->OnRelease(releaseCode); },
125         [uiExtCallback](int32_t resultCode, const OHOS::AAFwk::Want& result) {
126             uiExtCallback->OnResult(resultCode, result); },
127         [uiExtCallback](const OHOS::AAFwk::WantParams& request) { uiExtCallback->OnReceive(request); },
128         [uiExtCallback](int32_t errorCode, const std::string& name, const std::string& message) {
129             uiExtCallback->OnError(errorCode, name, message); },
130         [uiExtCallback](const std::shared_ptr<OHOS::Ace::ModalUIExtensionProxy>& uiProxy) {
131             uiExtCallback->OnRemoteReady(uiProxy); },
132         [uiExtCallback]() { uiExtCallback->OnDestroy(); }
133     };
134 
135     OHOS::Ace::ModalUIExtensionConfig uiExtConfig;
136     uiExtConfig.isProhibitBack = false;
137     int32_t sessionId = uiContent->CreateModalUIExtension(want, extensionCallbacks, uiExtConfig);
138     CM_LOG_I("end CreateModalUIExtension");
139     if (sessionId == 0) {
140         CM_LOG_E("CreateModalUIExtension failed");
141         ThrowError(asyncContext->env, PARAM_ERROR, "CreateModalUIExtension failed");
142     }
143     uiExtCallback->SetSessionId(sessionId);
144     return;
145 }
146 
EncodeBase64(const uint8_t * indata,const uint32_t length)147 static std::string EncodeBase64(const uint8_t *indata, const uint32_t length)
148 {
149     std::string encodeStr("");
150     if (indata == nullptr) {
151         CM_LOG_E("input param is invalid");
152         return encodeStr;
153     }
154     int i = 0;
155     while (i < (int)length) {
156         unsigned int octeta = i < (int)length ? *(indata + (i++)) : 0;
157         unsigned int octetb = i < (int)length ? *(indata + (i++)) : 0;
158         unsigned int octetc = i < (int)length ? *(indata + (i++)) : 0;
159 
160         unsigned int triple = (octeta << BYTE_SHIFT_16) + (octetb << BYTE_SHIFT_8) + octetc;
161 
162         encodeStr += g_base64Table[(triple >> BYTE_INDEX_THREE * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE];
163         encodeStr += g_base64Table[(triple >> BYTE_INDEX_TWO   * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE];
164         encodeStr += g_base64Table[(triple >> BYTE_INDEX_ONE   * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE];
165         encodeStr += g_base64Table[(triple >> BYTE_INDEX_ZONE  * BYTE_SHIFT_6) & BASE64_URL_TABLE_SIZE];
166     }
167 
168     switch (BASE64_GROUP_NUM - (i % BASE64_GROUP_NUM)) {
169         case BYTE_END_TWO:
170             encodeStr.replace(encodeStr.length() - BYTE_END_TWO, 1, BASE64_PADDING);
171             encodeStr.replace(encodeStr.length() - BYTE_END_ONE, 1, BASE64_PADDING);
172             break;
173         case BYTE_END_ONE:
174             encodeStr.replace(encodeStr.length() - BYTE_END_ONE, 1, BASE64_PADDING);
175             break;
176         default:
177             break;
178     }
179     return encodeStr;
180 }
181 
ParseCmUIAbilityContextReq(napi_env env,const napi_value & obj,std::shared_ptr<OHOS::AbilityRuntime::AbilityContext> & abilityContext)182 bool ParseCmUIAbilityContextReq(
183     napi_env env, const napi_value& obj, std::shared_ptr<OHOS::AbilityRuntime::AbilityContext>& abilityContext)
184 {
185     bool stageMode = false;
186     napi_status status = OHOS::AbilityRuntime::IsStageContext(env, obj, stageMode);
187     if (status != napi_ok || !stageMode) {
188         CM_LOG_E("not stage mode");
189         return false;
190     }
191 
192     auto context = OHOS::AbilityRuntime::GetStageModeContext(env, obj);
193     if (context == nullptr) {
194         CM_LOG_E("get context failed");
195         return false;
196     }
197 
198     abilityContext = OHOS::AbilityRuntime::Context::ConvertTo<OHOS::AbilityRuntime::AbilityContext>(context);
199     if (abilityContext == nullptr) {
200         CM_LOG_E("get abilityContext failed");
201         return false;
202     }
203     CM_LOG_I("end ParseUIAbilityContextReq");
204     return true;
205 }
206 
ParseUint32(napi_env env,napi_value object,uint32_t & store)207 napi_value ParseUint32(napi_env env, napi_value object, uint32_t &store)
208 {
209     napi_valuetype type;
210     napi_typeof(env, object, &type);
211     if (type != napi_number) {
212         CM_LOG_E("param type is not number");
213         return nullptr;
214     }
215     uint32_t temp = 0;
216     napi_get_value_uint32(env, object, &temp);
217     store = temp;
218     return GetInt32(env, 0);
219 }
220 
ParseBoolean(napi_env env,napi_value object,bool & status)221 napi_value ParseBoolean(napi_env env, napi_value object, bool &status)
222 {
223     napi_valuetype type;
224     napi_typeof(env, object, &type);
225     if (type != napi_boolean) {
226         CM_LOG_E("param type is not bool");
227         return nullptr;
228     }
229     bool temp = false;
230     napi_get_value_bool(env, object, &temp);
231     status = temp;
232     return GetInt32(env, 0);
233 }
234 
ParseString(napi_env env,napi_value obj,CmBlob * & blob)235 napi_value ParseString(napi_env env, napi_value obj, CmBlob *&blob)
236 {
237     napi_valuetype type = napi_undefined;
238     NAPI_CALL(env, napi_typeof(env, obj, &type));
239     if (type != napi_string) {
240         CM_LOG_E("the type of param is not string");
241         return nullptr;
242     }
243     size_t length = 0;
244     napi_status status = napi_get_value_string_utf8(env, obj, nullptr, 0, &length);
245     if (status != napi_ok) {
246         GET_AND_THROW_LAST_ERROR((env));
247         CM_LOG_E("could not get string length");
248         return nullptr;
249     }
250 
251     if ((length == 0) || (length > CM_MAX_DATA_LEN)) {
252         CM_LOG_E("input string length is 0 or too large, length: %d", length);
253         return nullptr;
254     }
255 
256     char *data = static_cast<char *>(CmMalloc(length + 1));
257     if (data == nullptr) {
258         napi_throw_error(env, nullptr, "could not alloc memory");
259         CM_LOG_E("could not alloc memory");
260         return nullptr;
261     }
262     (void)memset_s(data, length + 1, 0, length + 1);
263 
264     size_t res = 0;
265     status = napi_get_value_string_utf8(env, obj, data, length + 1, &res);
266     if (status != napi_ok) {
267         CmFree(data);
268         GET_AND_THROW_LAST_ERROR((env));
269         CM_LOG_E("could not get string");
270         return nullptr;
271     }
272 
273     blob = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
274     if (blob == nullptr) {
275         CmFree(data);
276         napi_throw_error(env, nullptr, "could not alloc memory");
277         CM_LOG_E("could not alloc memory");
278         return nullptr;
279     }
280     blob->data = reinterpret_cast<uint8_t *>(data);
281     blob->size = static_cast<uint32_t>((length + 1) & UINT32_MAX);
282 
283     return GetInt32(env, 0);
284 }
285 
GetUint8ArrayToBase64Str(napi_env env,napi_value object,std::string & certArray)286 napi_value GetUint8ArrayToBase64Str(napi_env env, napi_value object, std::string &certArray)
287 {
288     napi_typedarray_type arrayType;
289     napi_value arrayBuffer = nullptr;
290     size_t length = 0;
291     size_t offset = 0;
292     void *certData = nullptr;
293 
294     napi_status status = napi_get_typedarray_info(
295         env, object, &arrayType, &length, static_cast<void **>(&certData), &arrayBuffer, &offset);
296     if (arrayType != napi_uint8_array) {
297         return nullptr;
298     }
299     if (status != napi_ok) {
300         CM_LOG_E("the type of param is not uint8_array");
301         return nullptr;
302     }
303     if (length > CM_MAX_DATA_LEN) {
304         CM_LOG_E("certData is too large, length = %x", length);
305         return nullptr;
306     }
307     uint8_t *data = nullptr;
308     if (length == 0) {
309         CM_LOG_D("The memory length created is only 1 Byte");
310         // The memory length created is only 1 Byte
311         data = static_cast<uint8_t *>(CmMalloc(1));
312     } else {
313         data = static_cast<uint8_t *>(CmMalloc(length));
314     }
315     if (data == nullptr) {
316         CM_LOG_E("Malloc failed");
317         return nullptr;
318     }
319     (void)memset_s(data, length, 0, length);
320     if (memcpy_s(data, length, certData, length) != EOK) {
321         CmFree(data);
322         CM_LOG_E("memcpy_s fail, length = %x", length);
323         return nullptr;
324     }
325     std::string encode = EncodeBase64(data, length);
326     certArray = encode;
327     CmFree(data);
328     return GetInt32(env, 0);
329 }
330 
GetJsErrorMsg(int32_t errCode)331 static const char *GetJsErrorMsg(int32_t errCode)
332 {
333     auto iter = DIALOG_CODE_TO_MSG_MAP.find(errCode);
334     if (iter != DIALOG_CODE_TO_MSG_MAP.end()) {
335         return (iter->second).c_str();
336     }
337     return DIALOG_GENERIC_MSG.c_str();
338 }
339 
TranformErrorCode(int32_t errorCode)340 int32_t TranformErrorCode(int32_t errorCode)
341 {
342     auto iter = DIALOG_CODE_TO_JS_CODE_MAP.find(errorCode);
343     if (iter != DIALOG_CODE_TO_JS_CODE_MAP.end()) {
344         return iter->second;
345     }
346     return DIALOG_ERROR_GENERIC;
347 }
348 
GenerateBusinessError(napi_env env,int32_t errorCode)349 napi_value GenerateBusinessError(napi_env env, int32_t errorCode)
350 {
351     const char *errorMessage = GetJsErrorMsg(errorCode);
352     if (errorMessage == nullptr) {
353         return nullptr;
354     }
355 
356     napi_value code = nullptr;
357     int32_t outputCode = TranformErrorCode(errorCode);
358     NAPI_CALL(env, napi_create_int32(env, outputCode, &code));
359     napi_value message = nullptr;
360     NAPI_CALL(env, napi_create_string_utf8(env, errorMessage, NAPI_AUTO_LENGTH, &message));
361 
362     napi_value businessErrorMsg = nullptr;
363     NAPI_CALL(env, napi_create_error(env, nullptr, message, &businessErrorMsg));
364     NAPI_CALL(env, napi_set_named_property(env, businessErrorMsg, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code));
365     return businessErrorMsg;
366 }
367 
ThrowError(napi_env env,int32_t errorCode,const std::string errMsg)368 void ThrowError(napi_env env, int32_t errorCode, const std::string errMsg)
369 {
370     napi_value paramsError = nullptr;
371     napi_value outCode = nullptr;
372     napi_value message = nullptr;
373     NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, errorCode, &outCode));
374     NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message));
375     NAPI_CALL_RETURN_VOID(env, napi_create_error(env, nullptr, message, &paramsError));
376     NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, paramsError,
377         BUSINESS_ERROR_PROPERTY_CODE.c_str(), outCode));
378     NAPI_CALL_RETURN_VOID(env, napi_throw(env, paramsError));
379 }
380 
GeneratePromise(napi_env env,napi_deferred deferred,int32_t resultCode,napi_value * result,int32_t length)381 void GeneratePromise(napi_env env, napi_deferred deferred, int32_t resultCode,
382     napi_value *result, int32_t length)
383 {
384     if (length < RESULT_NUMBER) {
385         return;
386     }
387     if (resultCode == CM_SUCCESS) {
388         NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result[1]));
389     } else {
390         NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, result[0]));
391     }
392 }
393 
GetBundleMgrProxy()394 static OHOS::sptr<OHOS::AppExecFwk::BundleMgrProxy> GetBundleMgrProxy()
395 {
396     auto systemAbilityManager = OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
397     if (!systemAbilityManager) {
398         CM_LOG_E("fail to get system ability mgr.");
399         return nullptr;
400     }
401 
402     auto remoteObject = systemAbilityManager->GetSystemAbility(OHOS::BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
403     if (!remoteObject) {
404         CM_LOG_E("fail to get bundle manager proxy.");
405         return nullptr;
406     }
407     return OHOS::iface_cast<OHOS::AppExecFwk::BundleMgrProxy>(remoteObject);
408 }
409 
GetCallerLabelName(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)410 int32_t GetCallerLabelName(std::shared_ptr<CmUIExtensionRequestContext> asyncContext)
411 {
412     OHOS::sptr<OHOS::AppExecFwk::BundleMgrProxy> bundleMgrProxy = GetBundleMgrProxy();
413     if (bundleMgrProxy == nullptr) {
414         CM_LOG_E("Failed to get bundle manager proxy.");
415         return CM_FAILURE;
416     }
417 
418     OHOS::AppExecFwk::BundleInfo bundleInfo;
419     int32_t flags = static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_DEFAULT) |
420         static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) |
421         static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE) |
422         static_cast<int32_t>(OHOS::AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_ABILITY);
423     int32_t resCode = bundleMgrProxy->GetBundleInfoForSelf(flags, bundleInfo);
424     if (resCode != CM_SUCCESS) {
425         CM_LOG_E("Failed to get bundleInfo, resCode is %d", resCode);
426         return CM_FAILURE;
427     }
428 
429     if (asyncContext->context->GetResourceManager() == nullptr) {
430         CM_LOG_E("context get resourcemanager faild");
431         return CMR_ERROR_NULL_POINTER;
432     }
433 
434     resCode = asyncContext->context->GetResourceManager()->GetStringById(bundleInfo.applicationInfo.labelId,
435         asyncContext->labelName);
436     if (resCode != CM_SUCCESS) {
437         CM_LOG_E("getStringById is faild, resCode is %d", resCode);
438         return CM_FAILURE;
439     }
440     return CM_SUCCESS;
441 }
442 
443 
444 }  // namespace CertManagerNapi
445