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
FreeTokenNode(NativeTokenList ** node)138 static void FreeTokenNode(NativeTokenList **node)
139 {
140 if (node == NULL || *node == NULL) {
141 return;
142 }
143 FreeStrArray(&(*node)->dcaps, (*node)->dcapsNum - 1);
144 FreeStrArray(&(*node)->perms, (*node)->permsNum - 1);
145 FreeStrArray(&(*node)->perms, (*node)->permsNum - 1);
146 free(*node);
147 *node = NULL;
148 }
149
RemoveNodeFromList(NativeTokenList ** node)150 static void RemoveNodeFromList(NativeTokenList **node)
151 {
152 if (node == NULL || *node == NULL || g_tokenListHead == NULL) {
153 return;
154 }
155 NativeTokenList *tmp = g_tokenListHead->next;
156 while (tmp != NULL) {
157 if (tmp->next == *node) {
158 tmp->next = (*node)->next;
159 FreeTokenNode(node);
160 return;
161 }
162 tmp = tmp->next;
163 }
164 }
165
FreeTokenList(void)166 static void FreeTokenList(void)
167 {
168 if (g_tokenListHead == NULL) {
169 return;
170 }
171 NativeTokenList *tmp = g_tokenListHead->next;
172 while (tmp != NULL) {
173 NativeTokenList *toFreeNode = tmp;
174 tmp = tmp->next;
175 FreeTokenNode(&toFreeNode);
176 }
177 g_tokenListHead->next = NULL;
178 }
179
GetTokenList(const cJSON * object)180 static int32_t GetTokenList(const cJSON *object)
181 {
182 NativeTokenList *tmp = NULL;
183
184 if (object == NULL) {
185 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:object is null.", __func__);
186 return ATRET_FAILED;
187 }
188 int32_t arraySize = cJSON_GetArraySize(object);
189 if (arraySize <= 0) {
190 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:array is empty.", __func__);
191 return ATRET_FAILED;
192 }
193
194 for (int32_t i = 0; i < arraySize; i++) {
195 tmp = (NativeTokenList *)malloc(sizeof(NativeTokenList));
196 if (tmp == NULL) {
197 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:memory alloc failed.", __func__);
198 FreeTokenList();
199 return ATRET_FAILED;
200 }
201 cJSON *cjsonItem = cJSON_GetArrayItem(object, i);
202 if (cjsonItem == NULL) {
203 free(tmp);
204 FreeTokenList();
205 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:cJSON_GetArrayItem failed.", __func__);
206 return ATRET_FAILED;
207 }
208 if (GetNativeTokenFromJson(cjsonItem, tmp) != ATRET_SUCCESS) {
209 free(tmp);
210 FreeTokenList();
211 return ATRET_FAILED;
212 }
213
214 tmp->next = g_tokenListHead->next;
215 g_tokenListHead->next = tmp;
216 }
217 return ATRET_SUCCESS;
218 }
219
ParseTokenInfo(void)220 static int32_t ParseTokenInfo(void)
221 {
222 char *fileBuff = NULL;
223 cJSON *record = NULL;
224 int32_t ret;
225
226 ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
227 if (ret != ATRET_SUCCESS) {
228 return ret;
229 }
230 if (fileBuff == NULL) {
231 return ATRET_SUCCESS;
232 }
233 record = cJSON_Parse(fileBuff);
234 free(fileBuff);
235 fileBuff = NULL;
236
237 ret = GetTokenList(record);
238 cJSON_Delete(record);
239
240 return ret;
241 }
242
ClearOrCreateCfgFile(void)243 static int32_t ClearOrCreateCfgFile(void)
244 {
245 int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
246 if (fd < 0) {
247 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:open failed.", __func__);
248 return ATRET_FAILED;
249 }
250
251 #ifdef WITH_SELINUX
252 Restorecon(TOKEN_ID_CFG_FILE_PATH);
253 #endif // WITH_SELINUX
254
255 close(fd);
256 fd = -1;
257
258 struct stat buf;
259 if (stat(TOKEN_ID_CFG_DIR_PATH, &buf) != 0) {
260 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:stat folder path is invalid %d.", __func__, errno);
261 return ATRET_FAILED;
262 }
263 if (chown(TOKEN_ID_CFG_FILE_PATH, buf.st_uid, buf.st_gid) != 0) {
264 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:chown failed, errno is %d.", __func__, errno);
265 return ATRET_FAILED;
266 }
267
268 return ATRET_SUCCESS;
269 }
270
AtlibInit(void)271 int32_t AtlibInit(void)
272 {
273 g_tokenListHead = (NativeTokenList *)malloc(sizeof(NativeTokenList));
274 if (g_tokenListHead == NULL) {
275 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:g_tokenListHead memory alloc failed.", __func__);
276 return ATRET_FAILED;
277 }
278 g_tokenListHead->next = NULL;
279 int32_t isClearOrCreate = 0;
280
281 int32_t ret = ParseTokenInfo();
282 if (ret != ATRET_SUCCESS) {
283 if (g_tokenListHead->next != NULL) {
284 return ATRET_FAILED;
285 }
286 ret = ClearOrCreateCfgFile();
287 if (ret != ATRET_SUCCESS) {
288 free(g_tokenListHead);
289 g_tokenListHead = NULL;
290 return ret;
291 }
292 isClearOrCreate = 1;
293 }
294
295 if (g_tokenListHead->next == NULL) {
296 if (isClearOrCreate == 0 && ClearOrCreateCfgFile() != ATRET_SUCCESS) {
297 free(g_tokenListHead);
298 g_tokenListHead = NULL;
299 return ATRET_FAILED;
300 }
301 }
302 g_isNativeTokenInited = 1;
303
304 return ATRET_SUCCESS;
305 }
306
GetRandomTokenId(uint32_t * randNum)307 static int32_t GetRandomTokenId(uint32_t *randNum)
308 {
309 uint32_t random;
310 ssize_t len;
311 int32_t fd = open("/dev/urandom", O_RDONLY);
312 if (fd < 0) {
313 return ATRET_FAILED;
314 }
315 len = read(fd, &random, sizeof(random));
316 (void)close(fd);
317
318 if (len != sizeof(random)) {
319 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:read failed.", __func__);
320 return ATRET_FAILED;
321 }
322 *randNum = random;
323 return ATRET_SUCCESS;
324 }
325
IsTokenUniqueIdExist(uint32_t tokenUniqueId)326 static int32_t IsTokenUniqueIdExist(uint32_t tokenUniqueId)
327 {
328 NativeTokenList *tokenNode = g_tokenListHead->next;
329 while (tokenNode != NULL) {
330 AtInnerInfo *existToken = (AtInnerInfo *)&(tokenNode->tokenId);
331 if (tokenUniqueId == existToken->tokenUniqueId) {
332 return 1;
333 }
334 tokenNode = tokenNode->next;
335 }
336 return 0;
337 }
338
CreateNativeTokenId(const char * processName)339 static NativeAtId CreateNativeTokenId(const char *processName)
340 {
341 uint32_t rand;
342 NativeAtId tokenId;
343 AtInnerInfo *innerId = (AtInnerInfo *)(&tokenId);
344 int32_t retry = MAX_RETRY_TIMES;
345
346 while (retry > 0) {
347 if (GetRandomTokenId(&rand) != ATRET_SUCCESS) {
348 return INVALID_TOKEN_ID;
349 }
350 if (IsTokenUniqueIdExist(rand & (TOKEN_RANDOM_MASK)) == 0) {
351 break;
352 }
353 retry--;
354 }
355 if (retry == 0) {
356 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:retry times is 0.", __func__);
357 return INVALID_TOKEN_ID;
358 }
359
360 innerId->reserved = 0;
361 innerId->tokenUniqueId = rand & (TOKEN_RANDOM_MASK);
362 innerId->version = 1;
363
364 if (strcmp(processName, HDC_PROCESS_NAME) == 0) {
365 innerId->type = TOKEN_SHELL_TYPE;
366 } else {
367 innerId->type = TOKEN_NATIVE_TYPE;
368 }
369
370 return tokenId;
371 }
372
GetAplLevel(const char * aplStr)373 static int32_t GetAplLevel(const char *aplStr)
374 {
375 if (aplStr == NULL) {
376 return 0;
377 }
378 if (strcmp(aplStr, "system_core") == 0) {
379 return SYSTEM_CORE; // system_core means apl level is 3
380 }
381 if (strcmp(aplStr, "system_basic") == 0) {
382 return SYSTEM_BASIC; // system_basic means apl level is 2
383 }
384 if (strcmp(aplStr, "normal") == 0) {
385 return NORMAL;
386 }
387 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:aplStr is invalid.", __func__);
388 return 0;
389 }
390
WriteToFile(const cJSON * root)391 static void WriteToFile(const cJSON *root)
392 {
393 char *jsonStr = NULL;
394 jsonStr = cJSON_PrintUnformatted(root);
395 if (jsonStr == NULL) {
396 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:cJSON_PrintUnformatted failed.", __func__);
397 return;
398 }
399
400 do {
401 int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT | O_TRUNC,
402 S_IRUSR | S_IWUSR | S_IRGRP);
403 if (fd < 0) {
404 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:open failed.", __func__);
405 break;
406 }
407 size_t strLen = strlen(jsonStr);
408 ssize_t writtenLen = write(fd, (void *)jsonStr, (size_t)strLen);
409 if (fsync(fd) != 0) {
410 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:fsync failed, errno is %d.", __func__, errno);
411 }
412 close(fd);
413 if (writtenLen < 0 || (size_t)writtenLen != strLen) {
414 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:write failed, writtenLen is %zu.", __func__, writtenLen);
415 break;
416 }
417 } while (0);
418
419 cJSON_free(jsonStr);
420 return;
421 }
422
SaveTokenIdToCfg(const NativeTokenList * curr)423 static void SaveTokenIdToCfg(const NativeTokenList *curr)
424 {
425 char *fileBuff = NULL;
426 cJSON *record = NULL;
427 int32_t ret;
428
429 ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
430 if (ret != ATRET_SUCCESS) {
431 return;
432 }
433
434 if (fileBuff == NULL) {
435 record = cJSON_CreateArray();
436 } else {
437 record = cJSON_Parse(fileBuff);
438 free(fileBuff);
439 fileBuff = NULL;
440 }
441
442 if (record == NULL) {
443 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:get record failed.", __func__);
444 return;
445 }
446
447 cJSON *node = CreateNativeTokenJsonObject(curr);
448 if (node == NULL) {
449 cJSON_Delete(record);
450 return;
451 }
452 cJSON_AddItemToArray(record, node);
453
454 WriteToFile(record);
455 cJSON_Delete(record);
456 return;
457 }
458
CheckStrArray(const char ** strArray,int32_t strNum,int32_t maxNum,uint32_t maxInfoLen)459 static uint32_t CheckStrArray(const char **strArray, int32_t strNum, int32_t maxNum, uint32_t maxInfoLen)
460 {
461 if (((strArray == NULL) && (strNum != 0)) ||
462 (strNum > maxNum) || (strNum < 0)) {
463 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strArray is null or strNum is invalid.", __func__);
464 return ATRET_FAILED;
465 }
466 for (int32_t i = 0; i < strNum; i++) {
467 if ((strArray[i] == NULL) || (strlen(strArray[i]) > maxInfoLen) || (strlen(strArray[i]) == 0)) {
468 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strArray[%d] length is invalid.", __func__, i);
469 return ATRET_FAILED;
470 }
471 }
472 return ATRET_SUCCESS;
473 }
474
CheckProcessInfo(NativeTokenInfoParams * tokenInfo,int32_t * aplRet)475 static uint32_t CheckProcessInfo(NativeTokenInfoParams *tokenInfo, int32_t *aplRet)
476 {
477 if ((tokenInfo->processName == NULL) || strlen(tokenInfo->processName) > MAX_PROCESS_NAME_LEN ||
478 strlen(tokenInfo->processName) == 0) {
479 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:processName is invalid.", __func__);
480 return ATRET_FAILED;
481 }
482 uint32_t retDcap = CheckStrArray(tokenInfo->dcaps, tokenInfo->dcapsNum, MAX_DCAPS_NUM, MAX_DCAP_LEN);
483 if (retDcap != ATRET_SUCCESS) {
484 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:dcaps is invalid.", __func__);
485 return ATRET_FAILED;
486 }
487 uint32_t retPerm = CheckStrArray(tokenInfo->perms, tokenInfo->permsNum, MAX_PERM_NUM, MAX_PERM_LEN);
488 if (retPerm != ATRET_SUCCESS) {
489 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:perms is invalid.", __func__);
490 return ATRET_FAILED;
491 }
492
493 uint32_t retAcl = CheckStrArray(tokenInfo->acls, tokenInfo->aclsNum, MAX_PERM_NUM, MAX_PERM_LEN);
494 if (retAcl != ATRET_SUCCESS) {
495 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:acls is invalid.", __func__);
496 return ATRET_FAILED;
497 }
498
499 if (tokenInfo->aclsNum > tokenInfo->permsNum) {
500 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:aclsNum is invalid.", __func__);
501 return ATRET_FAILED;
502 }
503 int32_t apl = GetAplLevel(tokenInfo->aplStr);
504 if (apl == 0) {
505 return ATRET_FAILED;
506 }
507 *aplRet = apl;
508 return ATRET_SUCCESS;
509 }
510
CreateStrArray(int32_t num,const char ** strArr,char *** strArrRes)511 static uint32_t CreateStrArray(int32_t num, const char **strArr, char ***strArrRes)
512 {
513 if (num > MAX_PERM_NUM) {
514 return ATRET_FAILED;
515 }
516 if (num == 0) {
517 *strArrRes = NULL;
518 return ATRET_SUCCESS;
519 }
520 *strArrRes = (char **)malloc(num * sizeof(char *));
521 if (*strArrRes == NULL) {
522 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]: strArrRes malloc failed.", __func__);
523 return ATRET_FAILED;
524 }
525 for (int32_t i = 0; i < num; i++) {
526 size_t length = strlen(strArr[i]);
527 (*strArrRes)[i] = (char *)malloc(sizeof(char) * length + 1);
528 if ((*strArrRes)[i] == NULL ||
529 (strcpy_s((*strArrRes)[i], length + 1, strArr[i]) != EOK)) {
530 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:copy strArr[%d] failed.", __func__, i);
531 FreeStrArray(strArrRes, i);
532 return ATRET_FAILED;
533 }
534 (*strArrRes)[i][length] = '\0';
535 }
536 return ATRET_SUCCESS;
537 }
538
AddNewTokenToListAndFile(const NativeTokenInfoParams * tokenInfo,int32_t aplIn,NativeAtId * tokenId)539 static uint32_t AddNewTokenToListAndFile(const NativeTokenInfoParams *tokenInfo,
540 int32_t aplIn, NativeAtId *tokenId)
541 {
542 NativeTokenList *tokenNode;
543 NativeAtId id;
544
545 id = CreateNativeTokenId(tokenInfo->processName);
546 if (id == INVALID_TOKEN_ID) {
547 return ATRET_FAILED;
548 }
549
550 tokenNode = (NativeTokenList *)malloc(sizeof(NativeTokenList));
551 if (tokenNode == NULL) {
552 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:memory alloc failed.", __func__);
553 return ATRET_FAILED;
554 }
555 tokenNode->tokenId = id;
556 tokenNode->apl = aplIn;
557 if (strcpy_s(tokenNode->processName, MAX_PROCESS_NAME_LEN + 1, tokenInfo->processName) != EOK) {
558 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strcpy_s failed.", __func__);
559 free(tokenNode);
560 return ATRET_FAILED;
561 }
562 tokenNode->dcapsNum = tokenInfo->dcapsNum;
563 tokenNode->permsNum = tokenInfo->permsNum;
564 tokenNode->aclsNum = tokenInfo->aclsNum;
565
566 if (CreateStrArray(tokenInfo->dcapsNum, tokenInfo->dcaps, &tokenNode->dcaps) != ATRET_SUCCESS) {
567 free(tokenNode);
568 return ATRET_FAILED;
569 }
570 if (CreateStrArray(tokenInfo->permsNum, tokenInfo->perms, &tokenNode->perms) != ATRET_SUCCESS) {
571 FreeStrArray(&tokenNode->dcaps, tokenInfo->dcapsNum - 1);
572 free(tokenNode);
573 return ATRET_FAILED;
574 }
575 if (CreateStrArray(tokenInfo->aclsNum, tokenInfo->acls, &tokenNode->acls) != ATRET_SUCCESS) {
576 FreeStrArray(&tokenNode->dcaps, tokenInfo->dcapsNum - 1);
577 FreeStrArray(&tokenNode->perms, tokenInfo->permsNum - 1);
578 free(tokenNode);
579 return ATRET_FAILED;
580 }
581
582 tokenNode->next = g_tokenListHead->next;
583 g_tokenListHead->next = tokenNode;
584
585 *tokenId = id;
586
587 SaveTokenIdToCfg(tokenNode);
588 return ATRET_SUCCESS;
589 }
590
CompareTokenInfo(const NativeTokenList * tokenNode,const char ** dcapsIn,int32_t dcapNumIn,int32_t aplIn)591 static int32_t CompareTokenInfo(const NativeTokenList *tokenNode,
592 const char **dcapsIn, int32_t dcapNumIn, int32_t aplIn)
593 {
594 if (tokenNode->apl != aplIn) {
595 return 1;
596 }
597 if (tokenNode->dcapsNum != dcapNumIn) {
598 return 1;
599 }
600 for (int32_t i = 0; i < dcapNumIn; i++) {
601 if (strcmp(tokenNode->dcaps[i], dcapsIn[i]) != 0) {
602 return 1;
603 }
604 }
605 return 0;
606 }
607
ComparePermsInfo(const NativeTokenList * tokenNode,const char ** permsIn,int32_t permsNumIn)608 static int32_t ComparePermsInfo(const NativeTokenList *tokenNode,
609 const char **permsIn, int32_t permsNumIn)
610 {
611 if (tokenNode->permsNum != permsNumIn) {
612 return 1;
613 }
614 for (int32_t i = 0; i < permsNumIn; i++) {
615 if (strcmp(tokenNode->perms[i], permsIn[i]) != 0) {
616 return 1;
617 }
618 }
619 return 0;
620 }
621
UpdateStrArrayInList(char ** strArr[],int32_t * strNum,const char ** strArrNew,int32_t strNumNew)622 static uint32_t UpdateStrArrayInList(char **strArr[], int32_t *strNum,
623 const char **strArrNew, int32_t strNumNew)
624 {
625 if (strNum == NULL) {
626 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:strNum length is invalid.", __func__);
627 return ATRET_FAILED;
628 }
629
630 FreeStrArray(strArr, *strNum - 1);
631
632 *strNum = strNumNew;
633
634 return CreateStrArray(strNumNew, strArrNew, strArr);
635 }
636
UpdateTokenInfoInList(NativeTokenList * tokenNode,const NativeTokenInfoParams * tokenInfo)637 static uint32_t UpdateTokenInfoInList(NativeTokenList *tokenNode,
638 const NativeTokenInfoParams *tokenInfo)
639 {
640 tokenNode->apl = GetAplLevel(tokenInfo->aplStr);
641
642 uint32_t ret = UpdateStrArrayInList(&tokenNode->dcaps, &(tokenNode->dcapsNum),
643 tokenInfo->dcaps, tokenInfo->dcapsNum);
644 if (ret != ATRET_SUCCESS) {
645 return ret;
646 }
647 ret = UpdateStrArrayInList(&tokenNode->perms, &(tokenNode->permsNum),
648 tokenInfo->perms, tokenInfo->permsNum);
649 if (ret != ATRET_SUCCESS) {
650 FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
651 return ret;
652 }
653 ret = UpdateStrArrayInList(&tokenNode->acls, &(tokenNode->aclsNum),
654 tokenInfo->acls, tokenInfo->aclsNum);
655 if (ret != ATRET_SUCCESS) {
656 FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
657 FreeStrArray(&tokenNode->perms, tokenNode->permsNum - 1);
658 }
659 return ret;
660 }
661
UpdateInfoInCfgFile(const NativeTokenList * tokenNode)662 static uint32_t UpdateInfoInCfgFile(const NativeTokenList *tokenNode)
663 {
664 cJSON *record = NULL;
665 char *fileBuffer = NULL;
666 uint32_t ret;
667
668 if (GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuffer) != ATRET_SUCCESS) {
669 return ATRET_FAILED;
670 }
671
672 if (fileBuffer == NULL) {
673 record = cJSON_CreateArray();
674 } else {
675 record = cJSON_Parse(fileBuffer);
676 free(fileBuffer);
677 fileBuffer = NULL;
678 }
679
680 if (record == NULL) {
681 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:get record failed.", __func__);
682 return ATRET_FAILED;
683 }
684
685 ret = UpdateGoalItemFromRecord(tokenNode, record);
686 if (ret != ATRET_SUCCESS) {
687 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]:UpdateGoalItemFromRecord failed.", __func__);
688 cJSON_Delete(record);
689 return ATRET_FAILED;
690 }
691
692 WriteToFile(record);
693 cJSON_Delete(record);
694 return ATRET_SUCCESS;
695 }
696
697
LockNativeTokenFile(int32_t * lockFileFd)698 static uint32_t LockNativeTokenFile(int32_t *lockFileFd)
699 {
700 int32_t fd = open(TOKEN_ID_CFG_FILE_LOCK_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
701 if (fd < 0) {
702 NativeTokenKmsg(NATIVETOKEN_KERROR,
703 "[%s]: Failed to open native token file, errno is %d.", __func__, errno);
704 return ATRET_FAILED;
705 }
706 #ifdef WITH_SELINUX
707 Restorecon(TOKEN_ID_CFG_FILE_LOCK_PATH);
708 #endif // WITH_SELINUX
709 struct flock lock;
710 lock.l_type = F_WRLCK;
711 lock.l_whence = SEEK_SET;
712 lock.l_start = 0;
713 lock.l_len = 0; // lock entire file
714 int32_t ret = -1;
715 for (int i = 0; i < MAX_RETRY_LOCK_TIMES; i++) {
716 ret = fcntl(fd, F_SETLK, &lock);
717 if (ret == -1) {
718 NativeTokenKmsg(NATIVETOKEN_KERROR,
719 "[%s]: Failed to lock the file, try %d time, errno is %d.", __func__, i, errno);
720 usleep(SLEEP_TIME);
721 } else {
722 break;
723 }
724 }
725 if (ret == -1) {
726 close(fd);
727 return ATRET_FAILED;
728 }
729 *lockFileFd = fd;
730 return ATRET_SUCCESS;
731 }
732
UnlockNativeTokenFile(int32_t lockFileFd)733 static void UnlockNativeTokenFile(int32_t lockFileFd)
734 {
735 struct flock lock;
736 lock.l_type = F_UNLCK;
737 lock.l_whence = SEEK_SET;
738 lock.l_start = 0;
739 lock.l_len = 0;
740
741 if (fcntl(lockFileFd, F_SETLK, &lock) == -1) {
742 NativeTokenKmsg(NATIVETOKEN_KERROR,
743 "[%s]: Failed to unlock file, errno is %d.", __func__, errno);
744 }
745 close(lockFileFd);
746 }
747
AddOrUpdateTokenInfo(NativeTokenInfoParams * tokenInfo,NativeTokenList * tokenNode,int32_t apl,NativeAtId * tokenId)748 static uint32_t AddOrUpdateTokenInfo(NativeTokenInfoParams *tokenInfo, NativeTokenList *tokenNode,
749 int32_t apl, NativeAtId *tokenId)
750 {
751 uint32_t ret = ATRET_SUCCESS;
752 if (tokenNode == NULL) {
753 ret = AddNewTokenToListAndFile(tokenInfo, apl, tokenId);
754 } else {
755 int32_t needTokenUpdate = CompareTokenInfo(tokenNode, tokenInfo->dcaps, tokenInfo->dcapsNum, apl);
756 int32_t needPermUpdate = ComparePermsInfo(tokenNode, tokenInfo->perms, tokenInfo->permsNum);
757 if ((needTokenUpdate != 0) || (needPermUpdate != 0)) {
758 ret = UpdateTokenInfoInList(tokenNode, tokenInfo);
759 if (ret != ATRET_SUCCESS) {
760 RemoveNodeFromList(&tokenNode);
761 return ATRET_FAILED;
762 }
763 ret = UpdateInfoInCfgFile(tokenNode);
764 }
765 }
766 return ret;
767 }
768
GetAccessTokenId(NativeTokenInfoParams * tokenInfo)769 uint64_t GetAccessTokenId(NativeTokenInfoParams *tokenInfo)
770 {
771 NativeAtId tokenId = 0;
772 uint64_t result = 0;
773 int32_t apl;
774 NativeAtIdEx *atPoint = (NativeAtIdEx *)(&result);
775 int32_t fd = -1;
776 uint32_t ret = LockNativeTokenFile(&fd);
777 if (ret != ATRET_SUCCESS) {
778 NativeTokenKmsg(NATIVETOKEN_KERROR, "[%s]: Failed to lock file", __func__);
779 return INVALID_TOKEN_ID;
780 }
781
782 if ((g_isNativeTokenInited == 0) && (AtlibInit() != ATRET_SUCCESS)) {
783 UnlockNativeTokenFile(fd);
784 return INVALID_TOKEN_ID;
785 }
786 ret = CheckProcessInfo(tokenInfo, &apl);
787 if (ret != ATRET_SUCCESS) {
788 UnlockNativeTokenFile(fd);
789 return INVALID_TOKEN_ID;
790 }
791
792 NativeTokenList *tokenNode = g_tokenListHead->next;
793 while (tokenNode != NULL) {
794 if (strcmp(tokenNode->processName, tokenInfo->processName) == 0) {
795 tokenId = tokenNode->tokenId;
796 break;
797 }
798 tokenNode = tokenNode->next;
799 }
800
801 ret = AddOrUpdateTokenInfo(tokenInfo, tokenNode, apl, &tokenId);
802 if (ret != ATRET_SUCCESS) {
803 UnlockNativeTokenFile(fd);
804 return INVALID_TOKEN_ID;
805 }
806
807 atPoint->tokenId = tokenId;
808 atPoint->tokenAttr = 0;
809 UnlockNativeTokenFile(fd);
810 return result;
811 }
812