1 /*
2 * Copyright (c) 2022 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_grant.h"
17
18 #include "securec.h"
19
20 #include "cert_manager_api.h"
21 #include "cm_log.h"
22 #include "cm_mem.h"
23 #include "cm_type.h"
24 #include "cm_napi_common.h"
25
26 namespace CMNapi {
27 namespace {
28 constexpr int CM_NAPI_GRANT_ARGS_CNT = 3;
29 constexpr int CM_NAPI_IS_AUTHED_ARGS_CNT = 2;
30 constexpr int CM_NAPI_CALLBACK_ARG_CNT = 1;
31
32 constexpr uint32_t OUT_AUTH_URI_SIZE = 1000;
33 constexpr uint32_t OUT_AUTH_LIST_SIZE = 512;
34 constexpr uint32_t OUT_UINT32_STRING_SIZE = 16;
35 } // namespace
36
37 struct GrantAsyncContextT {
38 napi_async_work asyncWork = nullptr;
39 napi_deferred deferred = nullptr;
40 napi_ref callback = nullptr;
41
42 int32_t errCode = 0;
43 uint32_t appUid = 0;
44 struct CmBlob *keyUri = nullptr;
45 struct CmBlob *authUri = nullptr;
46 struct CmAppUidList *uidList = nullptr;
47 };
48 using GrantAsyncContext = GrantAsyncContextT *;
49
InitGrantAsyncContext(void)50 static GrantAsyncContext InitGrantAsyncContext(void)
51 {
52 GrantAsyncContext context = static_cast<GrantAsyncContext>(CmMalloc(sizeof(GrantAsyncContextT)));
53 if (context != nullptr) {
54 (void)memset_s(context, sizeof(GrantAsyncContextT), 0, sizeof(GrantAsyncContextT));
55 }
56 return context;
57 }
58
FreeGrantAsyncContext(napi_env env,GrantAsyncContext & context)59 static void FreeGrantAsyncContext(napi_env env, GrantAsyncContext &context)
60 {
61 if (context == nullptr) {
62 return;
63 }
64
65 DeleteNapiContext(env, context->asyncWork, context->callback);
66 FreeCmBlob(context->keyUri);
67 FreeCmBlob(context->authUri);
68 if (context->uidList != nullptr) {
69 CM_FREE_PTR(context->uidList->appUid);
70 CM_FREE_PTR(context->uidList);
71 }
72 CM_FREE_PTR(context);
73 }
74
ParseString2Uint32(napi_env env,napi_value object,uint32_t & value)75 static napi_value ParseString2Uint32(napi_env env, napi_value object, uint32_t &value)
76 {
77 struct CmBlob *blob = nullptr;
78 napi_value result = ParseString(env, object, blob);
79 if (result == nullptr) {
80 CM_LOG_E("parse string to blob failed");
81 if (blob != nullptr) {
82 CM_FREE_PTR(blob->data);
83 CmFree(blob);
84 }
85 return nullptr;
86 }
87
88 value = static_cast<uint32_t>(atoi(reinterpret_cast<char *>(blob->data)));
89 CM_FREE_PTR(blob->data);
90 CM_FREE_PTR(blob);
91 return GetInt32(env, 0);
92 }
93
ParseGrantUidParams(napi_env env,napi_callback_info info,GrantAsyncContext context)94 static napi_value ParseGrantUidParams(napi_env env, napi_callback_info info, GrantAsyncContext context)
95 {
96 size_t argc = CM_NAPI_GRANT_ARGS_CNT;
97 napi_value argv[CM_NAPI_GRANT_ARGS_CNT] = { nullptr };
98 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
99
100 if ((argc != CM_NAPI_GRANT_ARGS_CNT) && (argc != (CM_NAPI_GRANT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
101 ThrowParamsError(env, PARAM_ERROR, "arguments count invalid when grant or remove uid");
102 CM_LOG_E("arguments count is not expected when grant or remove uid");
103 return nullptr;
104 }
105
106 size_t index = 0;
107 napi_value result = ParseString(env, argv[index], context->keyUri);
108 if (result == nullptr) {
109 ThrowParamsError(env, PARAM_ERROR, "keyUri type error");
110 CM_LOG_E("get uri failed when grant or remove uid");
111 return nullptr;
112 }
113
114 index++;
115 result = ParseString2Uint32(env, argv[index], context->appUid);
116 if (result == nullptr) {
117 ThrowParamsError(env, PARAM_ERROR, "appUid type error");
118 CM_LOG_E("get app uid failed when grant or remove uid ");
119 return nullptr;
120 }
121
122 index++;
123 if (index < argc) {
124 context->callback = GetCallback(env, argv[index]);
125 if (context->callback == nullptr) {
126 ThrowParamsError(env, PARAM_ERROR, "Get callback type error");
127 CM_LOG_E("get callback function failed when grant or remove uid");
128 return nullptr;
129 }
130 }
131
132 return GetInt32(env, 0);
133 }
134
ParseRemoveUidParams(napi_env env,napi_callback_info info,GrantAsyncContext context)135 static napi_value ParseRemoveUidParams(napi_env env, napi_callback_info info, GrantAsyncContext context)
136 {
137 return ParseGrantUidParams(env, info, context);
138 }
139
ParseIsAuthedParams(napi_env env,napi_callback_info info,GrantAsyncContext context)140 static napi_value ParseIsAuthedParams(napi_env env, napi_callback_info info, GrantAsyncContext context)
141 {
142 size_t argc = CM_NAPI_IS_AUTHED_ARGS_CNT;
143 napi_value argv[CM_NAPI_IS_AUTHED_ARGS_CNT] = { nullptr };
144 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
145
146 if ((argc != CM_NAPI_IS_AUTHED_ARGS_CNT) && (argc != (CM_NAPI_IS_AUTHED_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
147 ThrowParamsError(env, PARAM_ERROR, "arguments count invalid when using isAuthed");
148 CM_LOG_E("arguments count is not expected when using isAuthed");
149 return nullptr;
150 }
151
152 size_t index = 0;
153 napi_value result = ParseString(env, argv[index], context->keyUri);
154 if (result == nullptr) {
155 ThrowParamsError(env, PARAM_ERROR, "keyUri type error");
156 CM_LOG_E("get uri failed when using isAuthed");
157 return nullptr;
158 }
159
160 index++;
161 if (index < argc) {
162 context->callback = GetCallback(env, argv[index]);
163 if (context->callback == nullptr) {
164 ThrowParamsError(env, PARAM_ERROR, "Get callback type error");
165 CM_LOG_E("get callback function failed when using isAuthed");
166 return nullptr;
167 }
168 }
169
170 return GetInt32(env, 0);
171 }
172
173
ParseGetUidListParams(napi_env env,napi_callback_info info,GrantAsyncContext context)174 static napi_value ParseGetUidListParams(napi_env env, napi_callback_info info, GrantAsyncContext context)
175 {
176 return ParseIsAuthedParams(env, info, context);
177 }
178
GrantUidExecute(napi_env env,void * data)179 static void GrantUidExecute(napi_env env, void *data)
180 {
181 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
182 context->authUri = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
183 if (context->authUri == nullptr) {
184 CM_LOG_E("malloc authUri failed");
185 context->errCode = CMR_ERROR_MALLOC_FAIL;
186 return;
187 }
188 (void)memset_s(context->authUri, sizeof(CmBlob), 0, sizeof(CmBlob));
189
190 context->authUri->data = static_cast<uint8_t *>(CmMalloc(OUT_AUTH_URI_SIZE));
191 if (context->authUri->data == nullptr) {
192 CM_LOG_E("malloc authUri.data failed");
193 context->errCode = CMR_ERROR_MALLOC_FAIL;
194 return;
195 }
196 (void)memset_s(context->authUri->data, OUT_AUTH_URI_SIZE, 0, OUT_AUTH_URI_SIZE);
197 context->authUri->size = OUT_AUTH_URI_SIZE;
198
199 context->errCode = CmGrantAppCertificate(context->keyUri, context->appUid, context->authUri);
200 }
201
ConvertResultAuthUri(napi_env env,const CmBlob * authUri)202 static napi_value ConvertResultAuthUri(napi_env env, const CmBlob *authUri)
203 {
204 napi_value result = nullptr;
205 NAPI_CALL(env, napi_create_object(env, &result));
206
207 napi_value authUriNapi = nullptr;
208 NAPI_CALL(env, napi_create_string_latin1(env,
209 reinterpret_cast<const char *>(authUri->data), NAPI_AUTO_LENGTH, &authUriNapi));
210 NAPI_CALL(env, napi_set_named_property(env, result, "uri", authUriNapi));
211
212 return result;
213 }
214
GrantUidComplete(napi_env env,napi_status status,void * data)215 static void GrantUidComplete(napi_env env, napi_status status, void *data)
216 {
217 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
218 napi_value result[RESULT_NUMBER] = { nullptr };
219 if (context->errCode == CM_SUCCESS) {
220 napi_create_uint32(env, 0, &result[0]);
221 result[1] = ConvertResultAuthUri(env, context->authUri);
222 } else {
223 result[0] = GenerateBusinessError(env, context->errCode, "grant uid failed");
224 napi_get_undefined(env, &result[1]);
225 }
226
227 if (context->deferred != nullptr) {
228 GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
229 } else {
230 GenerateCallback(env, context->callback, result, sizeof(result));
231 }
232 FreeGrantAsyncContext(env, context);
233 }
234
RemoveUidExecute(napi_env env,void * data)235 static void RemoveUidExecute(napi_env env, void *data)
236 {
237 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
238 context->errCode = CmRemoveGrantedApp(context->keyUri, context->appUid);
239 }
240
RemoveOrIsAuthedComplete(napi_env env,napi_status status,void * data)241 static void RemoveOrIsAuthedComplete(napi_env env, napi_status status, void *data)
242 {
243 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
244 napi_value result[RESULT_NUMBER] = { nullptr };
245 if (context->errCode == CM_SUCCESS) {
246 napi_create_uint32(env, 0, &result[0]);
247 napi_get_boolean(env, true, &result[1]);
248 } else {
249 result[0] = GenerateBusinessError(env, context->errCode, "remove or check is authed process failed");
250 napi_get_undefined(env, &result[1]);
251 }
252
253 if (context->deferred != nullptr) {
254 GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
255 } else {
256 GenerateCallback(env, context->callback, result, sizeof(result));
257 }
258 FreeGrantAsyncContext(env, context);
259 }
260
IsAuthedExecute(napi_env env,void * data)261 static void IsAuthedExecute(napi_env env, void *data)
262 {
263 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
264 context->errCode = CmIsAuthorizedApp(context->keyUri);
265 }
266
GetUidListExecute(napi_env env,void * data)267 static void GetUidListExecute(napi_env env, void *data)
268 {
269 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
270 context->uidList = static_cast<CmAppUidList *>(CmMalloc(sizeof(CmAppUidList)));
271 if (context->uidList == nullptr) {
272 CM_LOG_E("malloc uid list failed");
273 context->errCode = CMR_ERROR_MALLOC_FAIL;
274 return;
275 }
276 (void)memset_s(context->uidList, sizeof(CmAppUidList), 0, sizeof(CmAppUidList));
277
278 uint32_t uidListSize = OUT_AUTH_LIST_SIZE * sizeof(uint32_t);
279 context->uidList->appUid = static_cast<uint32_t *>(CmMalloc(uidListSize));
280 if (context->uidList->appUid == nullptr) {
281 CM_LOG_E("malloc uid_list.appUid failed");
282 context->errCode = CMR_ERROR_MALLOC_FAIL;
283 return;
284 }
285 (void)memset_s(context->uidList->appUid, uidListSize, 0, uidListSize);
286 context->uidList->appUidCount = OUT_AUTH_LIST_SIZE;
287
288 context->errCode = CmGetAuthorizedAppList(context->keyUri, context->uidList);
289 }
290
ConvertResultAuthList(napi_env env,const CmAppUidList * appUidList)291 static napi_value ConvertResultAuthList(napi_env env, const CmAppUidList *appUidList)
292 {
293 napi_value result = nullptr;
294 NAPI_CALL(env, napi_create_object(env, &result));
295
296 napi_value uidListArray = nullptr;
297 NAPI_CALL(env, napi_create_array(env, &uidListArray));
298
299 for (uint32_t i = 0; i < appUidList->appUidCount; ++i) {
300 char uidStr[OUT_UINT32_STRING_SIZE] = {0};
301 if (snprintf_s(uidStr, sizeof(uidStr), sizeof(uidStr) - 1, "%u", appUidList->appUid[i]) < 0) {
302 CM_LOG_E("uid to string failed");
303 return result;
304 }
305
306 napi_value element = nullptr;
307 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(uidStr), NAPI_AUTO_LENGTH, &element));
308 NAPI_CALL(env, napi_set_element(env, uidListArray, i, element));
309 }
310
311 NAPI_CALL(env, napi_set_named_property(env, result, "appUidList", uidListArray));
312 return result;
313 }
314
GetUidListComplete(napi_env env,napi_status status,void * data)315 static void GetUidListComplete(napi_env env, napi_status status, void *data)
316 {
317 GrantAsyncContext context = static_cast<GrantAsyncContext>(data);
318 napi_value result[RESULT_NUMBER] = { nullptr };
319 if (context->errCode == CM_SUCCESS) {
320 napi_create_uint32(env, 0, &result[0]);
321 result[1] = ConvertResultAuthList(env, context->uidList);
322 } else {
323 result[0] = GenerateBusinessError(env, context->errCode, "get authed uid list failed");
324 napi_get_undefined(env, &result[1]);
325 }
326
327 if (context->deferred != nullptr) {
328 GeneratePromise(env, context->deferred, context->errCode, result, sizeof(result));
329 } else {
330 GenerateCallback(env, context->callback, result, sizeof(result));
331 }
332 FreeGrantAsyncContext(env, context);
333 }
334
GrantUidAsyncWork(napi_env env,GrantAsyncContext context)335 static napi_value GrantUidAsyncWork(napi_env env, GrantAsyncContext context)
336 {
337 napi_value promise = nullptr;
338 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
339
340 napi_value resourceName = nullptr;
341 NAPI_CALL(env, napi_create_string_latin1(env, "grantAppCertificate", NAPI_AUTO_LENGTH, &resourceName));
342
343 NAPI_CALL(env, napi_create_async_work(
344 env, nullptr, resourceName,
345 GrantUidExecute,
346 GrantUidComplete,
347 static_cast<void *>(context),
348 &context->asyncWork));
349
350 napi_status status = napi_queue_async_work(env, context->asyncWork);
351 if (status != napi_ok) {
352 ThrowParamsError(env, PARAM_ERROR, "queue asyncWork error");
353 CM_LOG_E("get async work failed when granting uid");
354 return nullptr;
355 }
356 return promise;
357 }
358
RemoveUidAsyncWork(napi_env env,GrantAsyncContext context)359 static napi_value RemoveUidAsyncWork(napi_env env, GrantAsyncContext context)
360 {
361 napi_value promise = nullptr;
362 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
363
364 napi_value resourceName = nullptr;
365 NAPI_CALL(env, napi_create_string_latin1(env, "removeGrantedAppCertificate", NAPI_AUTO_LENGTH, &resourceName));
366
367 NAPI_CALL(env, napi_create_async_work(
368 env, nullptr, resourceName,
369 RemoveUidExecute,
370 RemoveOrIsAuthedComplete,
371 static_cast<void *>(context),
372 &context->asyncWork));
373
374 napi_status status = napi_queue_async_work(env, context->asyncWork);
375 if (status != napi_ok) {
376 ThrowParamsError(env, PARAM_ERROR, "queue asyncWork error");
377 CM_LOG_E("queue async work failed when removing uid");
378 return nullptr;
379 }
380 return promise;
381 }
382
IsAuthedAsyncWork(napi_env env,GrantAsyncContext context)383 static napi_value IsAuthedAsyncWork(napi_env env, GrantAsyncContext context)
384 {
385 napi_value promise = nullptr;
386 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
387
388 napi_value resourceName = nullptr;
389 NAPI_CALL(env, napi_create_string_latin1(env, "isAuthorizedApp", NAPI_AUTO_LENGTH, &resourceName));
390
391 NAPI_CALL(env, napi_create_async_work(
392 env, nullptr, resourceName,
393 IsAuthedExecute,
394 RemoveOrIsAuthedComplete,
395 static_cast<void *>(context),
396 &context->asyncWork));
397
398 napi_status status = napi_queue_async_work(env, context->asyncWork);
399 if (status != napi_ok) {
400 ThrowParamsError(env, PARAM_ERROR, "queue asyncWork error");
401 CM_LOG_E("queue async work failed when using isAuthed");
402 return nullptr;
403 }
404 return promise;
405 }
406
GetUidListAsyncWork(napi_env env,GrantAsyncContext context)407 static napi_value GetUidListAsyncWork(napi_env env, GrantAsyncContext context)
408 {
409 napi_value promise = nullptr;
410 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
411
412 napi_value resourceName = nullptr;
413 NAPI_CALL(env, napi_create_string_latin1(env, "getAuthorizedAppList", NAPI_AUTO_LENGTH, &resourceName));
414
415 NAPI_CALL(env, napi_create_async_work(
416 env, nullptr, resourceName,
417 GetUidListExecute,
418 GetUidListComplete,
419 static_cast<void *>(context),
420 &context->asyncWork));
421
422 napi_status status = napi_queue_async_work(env, context->asyncWork);
423 if (status != napi_ok) {
424 ThrowParamsError(env, PARAM_ERROR, "queue asyncWork error");
425 CM_LOG_E("queue async work failed when getting authed uid list");
426 return nullptr;
427 }
428 return promise;
429 }
430
CMNapiGrantAppCertificate(napi_env env,napi_callback_info info)431 napi_value CMNapiGrantAppCertificate(napi_env env, napi_callback_info info)
432 {
433 GrantAsyncContext context = InitGrantAsyncContext();
434 if (context == nullptr) {
435 CM_LOG_E("init grant uid context failed");
436 return nullptr;
437 }
438
439 napi_value result = ParseGrantUidParams(env, info, context);
440 if (result == nullptr) {
441 CM_LOG_E("parse grant uid params failed");
442 FreeGrantAsyncContext(env, context);
443 return nullptr;
444 }
445
446 result = GrantUidAsyncWork(env, context);
447 if (result == nullptr) {
448 CM_LOG_E("start grant uid async work failed");
449 FreeGrantAsyncContext(env, context);
450 return nullptr;
451 }
452
453 return result;
454 }
455
CMNapiIsAuthorizedApp(napi_env env,napi_callback_info info)456 napi_value CMNapiIsAuthorizedApp(napi_env env, napi_callback_info info)
457 {
458 GrantAsyncContext context = InitGrantAsyncContext();
459 if (context == nullptr) {
460 CM_LOG_E("init is authed uid context failed");
461 return nullptr;
462 }
463
464 napi_value result = ParseIsAuthedParams(env, info, context);
465 if (result == nullptr) {
466 CM_LOG_E("parse is authed uid params failed");
467 FreeGrantAsyncContext(env, context);
468 return nullptr;
469 }
470
471 result = IsAuthedAsyncWork(env, context);
472 if (result == nullptr) {
473 CM_LOG_E("start is authed uid async work failed");
474 FreeGrantAsyncContext(env, context);
475 return nullptr;
476 }
477
478 return result;
479 }
480
CMNapiGetAuthorizedAppList(napi_env env,napi_callback_info info)481 napi_value CMNapiGetAuthorizedAppList(napi_env env, napi_callback_info info)
482 {
483 GrantAsyncContext context = InitGrantAsyncContext();
484 if (context == nullptr) {
485 CM_LOG_E("init get authed uid list context failed");
486 return nullptr;
487 }
488
489 napi_value result = ParseGetUidListParams(env, info, context);
490 if (result == nullptr) {
491 CM_LOG_E("parse get uid list params failed");
492 FreeGrantAsyncContext(env, context);
493 return nullptr;
494 }
495
496 result = GetUidListAsyncWork(env, context);
497 if (result == nullptr) {
498 CM_LOG_E("start get uid list async work failed");
499 FreeGrantAsyncContext(env, context);
500 return nullptr;
501 }
502
503 return result;
504 }
505
CMNapiRemoveGrantedApp(napi_env env,napi_callback_info info)506 napi_value CMNapiRemoveGrantedApp(napi_env env, napi_callback_info info)
507 {
508 GrantAsyncContext context = InitGrantAsyncContext();
509 if (context == nullptr) {
510 CM_LOG_E("init remove uid context failed");
511 return nullptr;
512 }
513
514 napi_value result = ParseRemoveUidParams(env, info, context);
515 if (result == nullptr) {
516 CM_LOG_E("parse remove uid params failed");
517 FreeGrantAsyncContext(env, context);
518 return nullptr;
519 }
520
521 result = RemoveUidAsyncWork(env, context);
522 if (result == nullptr) {
523 CM_LOG_E("start remove uid async work failed");
524 FreeGrantAsyncContext(env, context);
525 return nullptr;
526 }
527
528 return result;
529 }
530 } // namespace CMNapi
531
532