1 /*
2 * Copyright (c) 2021-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 #include "nativetoken.h"
16
17 #ifdef WITH_SELINUX
18 #include <policycoreutils.h>
19 #endif // WITH_SELINUX
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include "securec.h"
29 #include "nativetoken_json_oper.h"
30 #include "nativetoken_kit.h"
31 #include "nativetoken_klog.h"
32
33
34 NativeTokenList *g_tokenListHead;
35 int32_t g_isNativeTokenInited = 0;
36
GetFileBuff(const char * cfg,char ** retBuff)37 int32_t GetFileBuff(const char *cfg, char **retBuff)
38 {
39 struct stat fileStat;
40
41 char filePath[PATH_MAX_LEN + 1] = {0};
42 if (realpath(cfg, filePath) == NULL) {
43 if (errno == ENOENT) {
44 /* file doesn't exist */
45 *retBuff = NULL;
46 return ATRET_SUCCESS;
47 }
48 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:invalid filePath.", __func__);
49 return ATRET_FAILED;
50 }
51
52 if (stat(filePath, &fileStat) != 0) {
53 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:stat file failed.", __func__);
54 return ATRET_FAILED;
55 }
56
57 if (fileStat.st_size == 0) {
58 NativeTokenKmsg(NATIVETOKEN_KINFO, "[%s]: file is empty", __func__);
59 *retBuff = NULL;
60 return ATRET_SUCCESS;
61 }
62
63 if (fileStat.st_size > MAX_JSON_FILE_LEN) {
64 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:stat file size is invalid.", __func__);
65 return ATRET_FAILED;
66 }
67
68 size_t fileSize = (unsigned)fileStat.st_size;
69
70 FILE *cfgFd = fopen(filePath, "r");
71 if (cfgFd == NULL) {
72 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:fopen file failed.", __func__);
73 return ATRET_FAILED;
74 }
75
76 char *buff = (char *)malloc((size_t)(fileSize + 1));
77 if (buff == NULL) {
78 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:memory alloc failed.", __func__);
79 (void)fclose(cfgFd);
80 return ATRET_FAILED;
81 }
82
83 if (fread(buff, fileSize, 1, cfgFd) != 1) {
84 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:fread failed.", __func__);
85 free(buff);
86 buff = NULL;
87 (void)fclose(cfgFd);
88 return ATRET_FAILED;
89 }
90 buff[fileSize] = '\0';
91 *retBuff = buff;
92 (void)fclose(cfgFd);
93 return ATRET_SUCCESS;
94 }
95
StrAttrSet(StrArrayAttr * attr,uint32_t maxStrLen,int32_t maxStrNum,const char * strKey)96 static void StrAttrSet(StrArrayAttr *attr, uint32_t maxStrLen, int32_t maxStrNum, const char *strKey)
97 {
98 attr->maxStrLen = maxStrLen;
99 attr->maxStrNum = maxStrNum;
100 attr->strKey = strKey;
101 }
102
GetNativeTokenFromJson(cJSON * cjsonItem,NativeTokenList * tokenNode)103 static int32_t GetNativeTokenFromJson(cJSON *cjsonItem, NativeTokenList *tokenNode)
104 {
105 uint32_t ret;
106 StrArrayAttr attr;
107
108 ret = GetProcessNameFromJson(cjsonItem, tokenNode);
109 ret |= GetTokenIdFromJson(cjsonItem, tokenNode);
110 ret |= GetAplFromJson(cjsonItem, tokenNode);
111
112 StrAttrSet(&attr, MAX_DCAP_LEN, MAX_DCAPS_NUM, DCAPS_KEY_NAME);
113 ret |= GetInfoArrFromJson(cjsonItem, tokenNode->dcaps, &(tokenNode->dcapsNum), &attr);
114 if (ret != ATRET_SUCCESS) {
115 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:GetInfoArrFromJson failed for dcaps.", __func__);
116 return ATRET_FAILED;
117 }
118
119 StrAttrSet(&attr, MAX_PERM_LEN, MAX_PERM_NUM, PERMS_KEY_NAME);
120 ret = GetInfoArrFromJson(cjsonItem, tokenNode->perms, &(tokenNode->permsNum), &attr);
121 if (ret != ATRET_SUCCESS) {
122 FreeStrArray(tokenNode->dcaps, tokenNode->dcapsNum - 1);
123 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:GetInfoArrFromJson failed for perms.", __func__);
124 return ATRET_FAILED;
125 }
126
127 StrAttrSet(&attr, MAX_PERM_LEN, MAX_PERM_NUM, ACLS_KEY_NAME);
128 ret = GetInfoArrFromJson(cjsonItem, tokenNode->acls, &(tokenNode->aclsNum), &attr);
129 if (ret != ATRET_SUCCESS) {
130 FreeStrArray(tokenNode->dcaps, tokenNode->dcapsNum - 1);
131 FreeStrArray(tokenNode->perms, tokenNode->permsNum - 1);
132 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:GetInfoArrFromJson failed for acls.", __func__);
133 return ATRET_FAILED;
134 }
135 return ATRET_SUCCESS;
136 }
137
GetTokenList(const cJSON * object)138 static int32_t GetTokenList(const cJSON *object)
139 {
140 NativeTokenList *tmp = NULL;
141
142 if (object == NULL) {
143 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:object is null.", __func__);
144 return ATRET_FAILED;
145 }
146 int32_t arraySize = cJSON_GetArraySize(object);
147
148 for (int32_t i = 0; i < arraySize; i++) {
149 tmp = (NativeTokenList *)malloc(sizeof(NativeTokenList));
150 if (tmp == NULL) {
151 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:memory alloc failed.", __func__);
152 return ATRET_FAILED;
153 }
154 cJSON *cjsonItem = cJSON_GetArrayItem(object, i);
155 if (cjsonItem == NULL) {
156 free(tmp);
157 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:cJSON_GetArrayItem failed.", __func__);
158 return ATRET_FAILED;
159 }
160 if (GetNativeTokenFromJson(cjsonItem, tmp) != ATRET_SUCCESS) {
161 free(tmp);
162 return ATRET_FAILED;
163 }
164
165 tmp->next = g_tokenListHead->next;
166 g_tokenListHead->next = tmp;
167 }
168 return ATRET_SUCCESS;
169 }
170
ParseTokenInfo(void)171 static int32_t ParseTokenInfo(void)
172 {
173 char *fileBuff = NULL;
174 cJSON *record = NULL;
175 int32_t ret;
176
177 ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
178 if (ret != ATRET_SUCCESS) {
179 return ret;
180 }
181 if (fileBuff == NULL) {
182 return ATRET_SUCCESS;
183 }
184 record = cJSON_Parse(fileBuff);
185 free(fileBuff);
186 fileBuff = NULL;
187
188 ret = GetTokenList(record);
189 cJSON_Delete(record);
190
191 return ret;
192 }
193
CreateCfgFile(void)194 static int32_t CreateCfgFile(void)
195 {
196 int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
197 if (fd < 0) {
198 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:open failed.", __func__);
199 return ATRET_FAILED;
200 }
201
202 #ifdef WITH_SELINUX
203 Restorecon(TOKEN_ID_CFG_FILE_PATH);
204 #endif // WITH_SELINUX
205
206 close(fd);
207 fd = -1;
208
209 struct stat buf;
210 if (stat(TOKEN_ID_CFG_DIR_PATH, &buf) != 0) {
211 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:stat folder path is invalid %d.", __func__, errno);
212 return ATRET_FAILED;
213 }
214 if (chown(TOKEN_ID_CFG_FILE_PATH, buf.st_uid, buf.st_gid) != 0) {
215 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:chown failed, errno is %d.", __func__, errno);
216 return ATRET_FAILED;
217 }
218
219 return ATRET_SUCCESS;
220 }
221
AtlibInit(void)222 int32_t AtlibInit(void)
223 {
224 g_tokenListHead = (NativeTokenList *)malloc(sizeof(NativeTokenList));
225 if (g_tokenListHead == NULL) {
226 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:g_tokenListHead memory alloc failed.", __func__);
227 return ATRET_FAILED;
228 }
229 g_tokenListHead->next = NULL;
230
231 int32_t ret = ParseTokenInfo();
232 if (ret != ATRET_SUCCESS) {
233 free(g_tokenListHead);
234 g_tokenListHead = NULL;
235 return ret;
236 }
237
238 if (g_tokenListHead->next == NULL) {
239 if (CreateCfgFile() != ATRET_SUCCESS) {
240 free(g_tokenListHead);
241 g_tokenListHead = NULL;
242 return ATRET_FAILED;
243 }
244 }
245 g_isNativeTokenInited = 1;
246
247 return ATRET_SUCCESS;
248 }
249
GetRandomTokenId(uint32_t * randNum)250 static int32_t GetRandomTokenId(uint32_t *randNum)
251 {
252 uint32_t random;
253 ssize_t len;
254 int32_t fd = open("/dev/urandom", O_RDONLY);
255 if (fd < 0) {
256 return ATRET_FAILED;
257 }
258 len = read(fd, &random, sizeof(random));
259 (void)close(fd);
260
261 if (len != sizeof(random)) {
262 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:read failed.", __func__);
263 return ATRET_FAILED;
264 }
265 *randNum = random;
266 return ATRET_SUCCESS;
267 }
268
IsTokenUniqueIdExist(uint32_t tokenUniqueId)269 static int32_t IsTokenUniqueIdExist(uint32_t tokenUniqueId)
270 {
271 NativeTokenList *tokenNode = g_tokenListHead->next;
272 while (tokenNode != NULL) {
273 AtInnerInfo *existToken = (AtInnerInfo *)&(tokenNode->tokenId);
274 if (tokenUniqueId == existToken->tokenUniqueId) {
275 return 1;
276 }
277 tokenNode = tokenNode->next;
278 }
279 return 0;
280 }
281
CreateNativeTokenId(const char * processName)282 static NativeAtId CreateNativeTokenId(const char *processName)
283 {
284 uint32_t rand;
285 NativeAtId tokenId;
286 AtInnerInfo *innerId = (AtInnerInfo *)(&tokenId);
287 int32_t retry = MAX_RETRY_TIMES;
288
289 while (retry > 0) {
290 if (GetRandomTokenId(&rand) != ATRET_SUCCESS) {
291 return INVALID_TOKEN_ID;
292 }
293 if (IsTokenUniqueIdExist(rand & (TOKEN_RANDOM_MASK)) == 0) {
294 break;
295 }
296 retry--;
297 }
298 if (retry == 0) {
299 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:retry times is 0.", __func__);
300 return INVALID_TOKEN_ID;
301 }
302
303 innerId->reserved = 0;
304 innerId->tokenUniqueId = rand & (TOKEN_RANDOM_MASK);
305 innerId->version = 1;
306
307 if (strcmp(processName, HDC_PROCESS_NAME) == 0) {
308 innerId->type = TOKEN_SHELL_TYPE;
309 } else {
310 innerId->type = TOKEN_NATIVE_TYPE;
311 }
312
313 return tokenId;
314 }
315
GetAplLevel(const char * aplStr)316 static int32_t GetAplLevel(const char *aplStr)
317 {
318 if (aplStr == NULL) {
319 return 0;
320 }
321 if (strcmp(aplStr, "system_core") == 0) {
322 return SYSTEM_CORE; // system_core means apl level is 3
323 }
324 if (strcmp(aplStr, "system_basic") == 0) {
325 return SYSTEM_BASIC; // system_basic means apl level is 2
326 }
327 if (strcmp(aplStr, "normal") == 0) {
328 return NORMAL;
329 }
330 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:aplStr is invalid.", __func__);
331 return 0;
332 }
333
WriteToFile(const cJSON * root)334 static void WriteToFile(const cJSON *root)
335 {
336 char *jsonStr = NULL;
337 jsonStr = cJSON_PrintUnformatted(root);
338 if (jsonStr == NULL) {
339 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:cJSON_PrintUnformatted failed.", __func__);
340 return;
341 }
342
343 do {
344 int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT | O_TRUNC,
345 S_IRUSR | S_IWUSR | S_IRGRP);
346 if (fd < 0) {
347 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:open failed.", __func__);
348 break;
349 }
350 size_t strLen = strlen(jsonStr);
351 ssize_t writtenLen = write(fd, (void *)jsonStr, (size_t)strLen);
352 if (fsync(fd) != 0) {
353 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:fsync failed, errno is %d.", __func__, errno);
354 }
355 close(fd);
356 if (writtenLen < 0 || (size_t)writtenLen != strLen) {
357 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:write failed, writtenLen is %zu.", __func__, writtenLen);
358 break;
359 }
360 } while (0);
361
362 cJSON_free(jsonStr);
363 return;
364 }
365
SaveTokenIdToCfg(const NativeTokenList * curr)366 static void SaveTokenIdToCfg(const NativeTokenList *curr)
367 {
368 char *fileBuff = NULL;
369 cJSON *record = NULL;
370 int32_t ret;
371
372 ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
373 if (ret != ATRET_SUCCESS) {
374 return;
375 }
376
377 if (fileBuff == NULL) {
378 record = cJSON_CreateArray();
379 } else {
380 record = cJSON_Parse(fileBuff);
381 free(fileBuff);
382 fileBuff = NULL;
383 }
384
385 if (record == NULL) {
386 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:get record failed.", __func__);
387 return;
388 }
389
390 cJSON *node = CreateNativeTokenJsonObject(curr);
391 if (node == NULL) {
392 cJSON_Delete(record);
393 return;
394 }
395 cJSON_AddItemToArray(record, node);
396
397 WriteToFile(record);
398 cJSON_Delete(record);
399 return;
400 }
401
CheckStrArray(const char ** strArray,int32_t strNum,int32_t maxNum,uint32_t maxInfoLen)402 static uint32_t CheckStrArray(const char **strArray, int32_t strNum, int32_t maxNum, uint32_t maxInfoLen)
403 {
404 if (((strArray == NULL) && (strNum != 0)) ||
405 (strNum > maxNum) || (strNum < 0)) {
406 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strArray is null or strNum is invalid.", __func__);
407 return ATRET_FAILED;
408 }
409 for (int32_t i = 0; i < strNum; i++) {
410 if ((strArray[i] == NULL) || (strlen(strArray[i]) > maxInfoLen) || (strlen(strArray[i]) == 0)) {
411 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strArray[%d] length is invalid.", __func__, i);
412 return ATRET_FAILED;
413 }
414 }
415 return ATRET_SUCCESS;
416 }
417
CheckProcessInfo(NativeTokenInfoParams * tokenInfo,int32_t * aplRet)418 static uint32_t CheckProcessInfo(NativeTokenInfoParams *tokenInfo, int32_t *aplRet)
419 {
420 if ((tokenInfo->processName == NULL) || strlen(tokenInfo->processName) > MAX_PROCESS_NAME_LEN ||
421 strlen(tokenInfo->processName) == 0) {
422 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:processName is invalid.", __func__);
423 return ATRET_FAILED;
424 }
425 uint32_t retDcap = CheckStrArray(tokenInfo->dcaps, tokenInfo->dcapsNum, MAX_DCAPS_NUM, MAX_DCAP_LEN);
426 if (retDcap != ATRET_SUCCESS) {
427 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:dcaps is invalid.", __func__);
428 return ATRET_FAILED;
429 }
430 uint32_t retPerm = CheckStrArray(tokenInfo->perms, tokenInfo->permsNum, MAX_PERM_NUM, MAX_PERM_LEN);
431 if (retPerm != ATRET_SUCCESS) {
432 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:perms is invalid.", __func__);
433 return ATRET_FAILED;
434 }
435
436 uint32_t retAcl = CheckStrArray(tokenInfo->acls, tokenInfo->aclsNum, MAX_PERM_NUM, MAX_PERM_LEN);
437 if (retAcl != ATRET_SUCCESS) {
438 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:acls is invalid.", __func__);
439 return ATRET_FAILED;
440 }
441
442 if (tokenInfo->aclsNum > tokenInfo->permsNum) {
443 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:aclsNum is invalid.", __func__);
444 return ATRET_FAILED;
445 }
446 int32_t apl = GetAplLevel(tokenInfo->aplStr);
447 if (apl == 0) {
448 return ATRET_FAILED;
449 }
450 *aplRet = apl;
451 return ATRET_SUCCESS;
452 }
453
CreateStrArray(int32_t num,const char ** strArr,char ** strArrRes)454 static uint32_t CreateStrArray(int32_t num, const char **strArr, char **strArrRes)
455 {
456 for (int32_t i = 0; i < num; i++) {
457 strArrRes[i] = (char *)malloc(sizeof(char) * (strlen(strArr[i]) + 1));
458 if (strArrRes[i] == NULL ||
459 (strcpy_s(strArrRes[i], strlen(strArr[i]) + 1, strArr[i]) != EOK)) {
460 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:copy strArr[%d] failed.", __func__, i);
461 FreeStrArray(strArrRes, i);
462 return ATRET_FAILED;
463 }
464 }
465 return ATRET_SUCCESS;
466 }
467
AddNewTokenToListAndFile(const NativeTokenInfoParams * tokenInfo,int32_t aplIn,NativeAtId * tokenId)468 static uint32_t AddNewTokenToListAndFile(const NativeTokenInfoParams *tokenInfo,
469 int32_t aplIn, NativeAtId *tokenId)
470 {
471 NativeTokenList *tokenNode;
472 NativeAtId id;
473
474 id = CreateNativeTokenId(tokenInfo->processName);
475 if (id == INVALID_TOKEN_ID) {
476 return ATRET_FAILED;
477 }
478
479 tokenNode = (NativeTokenList *)malloc(sizeof(NativeTokenList));
480 if (tokenNode == NULL) {
481 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:memory alloc failed.", __func__);
482 return ATRET_FAILED;
483 }
484 tokenNode->tokenId = id;
485 tokenNode->apl = aplIn;
486 if (strcpy_s(tokenNode->processName, MAX_PROCESS_NAME_LEN + 1, tokenInfo->processName) != EOK) {
487 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strcpy_s failed.", __func__);
488 free(tokenNode);
489 return ATRET_FAILED;
490 }
491 tokenNode->dcapsNum = tokenInfo->dcapsNum;
492 tokenNode->permsNum = tokenInfo->permsNum;
493 tokenNode->aclsNum = tokenInfo->aclsNum;
494
495 if (CreateStrArray(tokenInfo->dcapsNum, tokenInfo->dcaps, tokenNode->dcaps) != ATRET_SUCCESS) {
496 free(tokenNode);
497 return ATRET_FAILED;
498 }
499 if (CreateStrArray(tokenInfo->permsNum, tokenInfo->perms, tokenNode->perms) != ATRET_SUCCESS) {
500 FreeStrArray(tokenNode->dcaps, tokenInfo->dcapsNum - 1);
501 free(tokenNode);
502 return ATRET_FAILED;
503 }
504 if (CreateStrArray(tokenInfo->aclsNum, tokenInfo->acls, tokenNode->acls) != ATRET_SUCCESS) {
505 FreeStrArray(tokenNode->dcaps, tokenInfo->dcapsNum - 1);
506 FreeStrArray(tokenNode->perms, tokenInfo->permsNum - 1);
507 free(tokenNode);
508 return ATRET_FAILED;
509 }
510
511 tokenNode->next = g_tokenListHead->next;
512 g_tokenListHead->next = tokenNode;
513
514 *tokenId = id;
515
516 SaveTokenIdToCfg(tokenNode);
517 return ATRET_SUCCESS;
518 }
519
CompareTokenInfo(const NativeTokenList * tokenNode,const char ** dcapsIn,int32_t dcapNumIn,int32_t aplIn)520 static int32_t CompareTokenInfo(const NativeTokenList *tokenNode,
521 const char **dcapsIn, int32_t dcapNumIn, int32_t aplIn)
522 {
523 if (tokenNode->apl != aplIn) {
524 return 1;
525 }
526 if (tokenNode->dcapsNum != dcapNumIn) {
527 return 1;
528 }
529 for (int32_t i = 0; i < dcapNumIn; i++) {
530 if (strcmp(tokenNode->dcaps[i], dcapsIn[i]) != 0) {
531 return 1;
532 }
533 }
534 return 0;
535 }
536
ComparePermsInfo(const NativeTokenList * tokenNode,const char ** permsIn,int32_t permsNumIn)537 static int32_t ComparePermsInfo(const NativeTokenList *tokenNode,
538 const char **permsIn, int32_t permsNumIn)
539 {
540 if (tokenNode->permsNum != permsNumIn) {
541 return 1;
542 }
543 for (int32_t i = 0; i < permsNumIn; i++) {
544 if (strcmp(tokenNode->perms[i], permsIn[i]) != 0) {
545 return 1;
546 }
547 }
548 return 0;
549 }
550
UpdateStrArrayInList(char * strArr[],int32_t * strNum,const char ** strArrNew,int32_t strNumNew)551 static uint32_t UpdateStrArrayInList(char *strArr[], int32_t *strNum,
552 const char **strArrNew, int32_t strNumNew)
553 {
554 if (strNum == NULL) {
555 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strNum length is invalid.", __func__);
556 return ATRET_FAILED;
557 }
558 for (int32_t i = 0; i < *strNum; i++) {
559 free(strArr[i]);
560 strArr[i] = NULL;
561 }
562
563 *strNum = strNumNew;
564 for (int32_t i = 0; i < strNumNew; i++) {
565 size_t len = strlen(strArrNew[i]) + 1;
566 strArr[i] = (char *)malloc(sizeof(char) * len);
567 if (strArr[i] == NULL || (strcpy_s(strArr[i], len, strArrNew[i]) != EOK)) {
568 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:copy strArr[%d] failed.", __func__, i);
569 FreeStrArray(strArr, i);
570 return ATRET_FAILED;
571 }
572 }
573 return ATRET_SUCCESS;
574 }
575
UpdateTokenInfoInList(NativeTokenList * tokenNode,const NativeTokenInfoParams * tokenInfo)576 static uint32_t UpdateTokenInfoInList(NativeTokenList *tokenNode,
577 const NativeTokenInfoParams *tokenInfo)
578 {
579 tokenNode->apl = GetAplLevel(tokenInfo->aplStr);
580
581 uint32_t ret = UpdateStrArrayInList(tokenNode->dcaps, &(tokenNode->dcapsNum),
582 tokenInfo->dcaps, tokenInfo->dcapsNum);
583 if (ret != ATRET_SUCCESS) {
584 return ret;
585 }
586 ret = UpdateStrArrayInList(tokenNode->perms, &(tokenNode->permsNum),
587 tokenInfo->perms, tokenInfo->permsNum);
588 if (ret != ATRET_SUCCESS) {
589 FreeStrArray(tokenNode->dcaps, tokenNode->dcapsNum - 1);
590 }
591 ret = UpdateStrArrayInList(tokenNode->acls, &(tokenNode->aclsNum),
592 tokenInfo->acls, tokenInfo->aclsNum);
593 if (ret != ATRET_SUCCESS) {
594 FreeStrArray(tokenNode->dcaps, tokenNode->dcapsNum - 1);
595 FreeStrArray(tokenNode->perms, tokenNode->permsNum - 1);
596 }
597 return ret;
598 }
599
UpdateInfoInCfgFile(const NativeTokenList * tokenNode)600 static uint32_t UpdateInfoInCfgFile(const NativeTokenList *tokenNode)
601 {
602 cJSON *record = NULL;
603 char *fileBuffer = NULL;
604 uint32_t ret;
605
606 if (GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuffer) != ATRET_SUCCESS) {
607 return ATRET_FAILED;
608 }
609
610 if (fileBuffer == NULL) {
611 record = cJSON_CreateArray();
612 } else {
613 record = cJSON_Parse(fileBuffer);
614 free(fileBuffer);
615 fileBuffer = NULL;
616 }
617
618 if (record == NULL) {
619 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:get record failed.", __func__);
620 return ATRET_FAILED;
621 }
622
623 ret = UpdateGoalItemFromRecord(tokenNode, record);
624 if (ret != ATRET_SUCCESS) {
625 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:UpdateGoalItemFromRecord failed.", __func__);
626 cJSON_Delete(record);
627 return ATRET_FAILED;
628 }
629
630 WriteToFile(record);
631 cJSON_Delete(record);
632 return ATRET_SUCCESS;
633 }
634
635
LockNativeTokenFile(int32_t * lockFileFd)636 static uint32_t LockNativeTokenFile(int32_t *lockFileFd)
637 {
638 int32_t fd = open(TOKEN_ID_CFG_FILE_LOCK_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
639 if (fd < 0) {
640 NativeTokenKmsg(NATIVETOKEN_KERROR,
641 "[%s]: Failed to open native token file, errno is %d.", __func__, errno);
642 return ATRET_FAILED;
643 }
644 #ifdef WITH_SELINUX
645 Restorecon(TOKEN_ID_CFG_FILE_LOCK_PATH);
646 #endif // WITH_SELINUX
647 struct flock lock;
648 lock.l_type = F_WRLCK;
649 lock.l_whence = SEEK_SET;
650 lock.l_start = 0;
651 lock.l_len = 0; // lock entire file
652 int32_t ret = -1;
653 for (int i = 0; i < MAX_RETRY_LOCK_TIMES; i++) {
654 ret = fcntl(fd, F_SETLK, &lock);
655 if (ret == -1) {
656 NativeTokenKmsg(NATIVETOKEN_KERROR,
657 "[%s]: Failed to lock the file, try %d time, errno is %d.", __func__, i, errno);
658 usleep(SLEEP_TIME);
659 } else {
660 break;
661 }
662 }
663 if (ret == -1) {
664 close(fd);
665 return ATRET_FAILED;
666 }
667 *lockFileFd = fd;
668 return ATRET_SUCCESS;
669 }
670
UnlockNativeTokenFile(int32_t lockFileFd)671 static void UnlockNativeTokenFile(int32_t lockFileFd)
672 {
673 struct flock lock;
674 lock.l_type = F_UNLCK;
675 lock.l_whence = SEEK_SET;
676 lock.l_start = 0;
677 lock.l_len = 0;
678
679 if (fcntl(lockFileFd, F_SETLK, &lock) == -1) {
680 NativeTokenKmsg(NATIVETOKEN_KERROR,
681 "[%s]: Failed to unlock file, errno is %d.", __func__, errno);
682 }
683 close(lockFileFd);
684 }
685
AddOrUpdateTokenInfo(NativeTokenInfoParams * tokenInfo,NativeTokenList * tokenNode,int32_t apl,NativeAtId * tokenId)686 static uint32_t AddOrUpdateTokenInfo(NativeTokenInfoParams *tokenInfo, NativeTokenList *tokenNode,
687 int32_t apl, NativeAtId *tokenId)
688 {
689 uint32_t ret = ATRET_SUCCESS;
690 if (tokenNode == NULL) {
691 ret = AddNewTokenToListAndFile(tokenInfo, apl, tokenId);
692 } else {
693 int32_t needTokenUpdate = CompareTokenInfo(tokenNode, tokenInfo->dcaps, tokenInfo->dcapsNum, apl);
694 int32_t needPermUpdate = ComparePermsInfo(tokenNode, tokenInfo->perms, tokenInfo->permsNum);
695 if ((needTokenUpdate != 0) || (needPermUpdate != 0)) {
696 ret = UpdateTokenInfoInList(tokenNode, tokenInfo);
697 ret |= UpdateInfoInCfgFile(tokenNode);
698 }
699 }
700 return ret;
701 }
702
GetAccessTokenId(NativeTokenInfoParams * tokenInfo)703 uint64_t GetAccessTokenId(NativeTokenInfoParams *tokenInfo)
704 {
705 NativeAtId tokenId = 0;
706 uint64_t result = 0;
707 int32_t apl;
708 NativeAtIdEx *atPoint = (NativeAtIdEx *)(&result);
709 int32_t fd = -1;
710 uint32_t ret = LockNativeTokenFile(&fd);
711 if (ret != ATRET_SUCCESS) {
712 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]: Failed to lock file", __func__);
713 return INVALID_TOKEN_ID;
714 }
715
716 if ((g_isNativeTokenInited == 0) && (AtlibInit() != ATRET_SUCCESS)) {
717 UnlockNativeTokenFile(fd);
718 return INVALID_TOKEN_ID;
719 }
720 ret = CheckProcessInfo(tokenInfo, &apl);
721 if (ret != ATRET_SUCCESS) {
722 UnlockNativeTokenFile(fd);
723 return INVALID_TOKEN_ID;
724 }
725
726 NativeTokenList *tokenNode = g_tokenListHead->next;
727 while (tokenNode != NULL) {
728 if (strcmp(tokenNode->processName, tokenInfo->processName) == 0) {
729 tokenId = tokenNode->tokenId;
730 break;
731 }
732 tokenNode = tokenNode->next;
733 }
734 ret = AddOrUpdateTokenInfo(tokenInfo, tokenNode, apl, &tokenId);
735 if (ret != ATRET_SUCCESS) {
736 UnlockNativeTokenFile(fd);
737 return INVALID_TOKEN_ID;
738 }
739
740 atPoint->tokenId = tokenId;
741 atPoint->tokenAttr = 0;
742 UnlockNativeTokenFile(fd);
743 return result;
744 }
745