• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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