• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "idm_database.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_algorithm.h"
21 #include "adaptor_log.h"
22 #include "idm_file_manager.h"
23 
24 #define MAX_DUPLICATE_CHECK 100
25 #define PRE_APPLY_NUM 5
26 #define MEM_GROWTH_FACTOR 2
27 #define MAX_CREDENTIAL_RETURN 5000
28 
29 #ifdef IAM_TEST_ENABLE
30 #define IAM_STATIC
31 #else
32 #define IAM_STATIC static
33 #endif
34 
35 // Caches IDM user information.
36 IAM_STATIC LinkedList *g_userInfoList = NULL;
37 
38 // Caches the current user to reduce the number of user list traversal times.
39 IAM_STATIC UserInfo *g_currentUser = NULL;
40 
41 typedef bool (*DuplicateCheckFunc)(LinkedList *collection, uint64_t value);
42 
43 IAM_STATIC UserInfo *QueryUserInfo(int32_t userId);
44 IAM_STATIC ResultCode GetAllEnrolledInfoFromUser(UserInfo *userInfo, EnrolledInfoHal **enrolledInfos, uint32_t *num);
45 IAM_STATIC ResultCode DeleteUser(int32_t userId);
46 IAM_STATIC CredentialInfoHal *QueryCredentialById(uint64_t credentialId, LinkedList *credentialList);
47 IAM_STATIC CredentialInfoHal *QueryCredentialByAuthType(uint32_t authType, LinkedList *credentialList);
48 IAM_STATIC bool MatchCredentialById(const void *data, const void *condition);
49 IAM_STATIC ResultCode GenerateDeduplicateUint64(LinkedList *collection, uint64_t *destValue, DuplicateCheckFunc func);
50 IAM_STATIC bool IsUserValid(UserInfo *user);
51 IAM_STATIC ResultCode GetInvalidUser(int32_t *invalidUserId, uint32_t maxUserCount, uint32_t *userCount);
52 IAM_STATIC ResultCode ClearInvalidUser(void);
53 
InitUserInfoList(void)54 ResultCode InitUserInfoList(void)
55 {
56     LOG_INFO("InitUserInfoList start");
57     if (g_userInfoList != NULL) {
58         DestroyUserInfoList();
59         g_userInfoList = NULL;
60     }
61     g_userInfoList = LoadFileInfo();
62     if (g_userInfoList == NULL) {
63         LOG_ERROR("load file info failed");
64         return RESULT_NEED_INIT;
65     }
66     ResultCode ret = ClearInvalidUser();
67     if (ret != RESULT_SUCCESS) {
68         LOG_ERROR("clear invalid user failed");
69         DestroyUserInfoList();
70         return ret;
71     }
72     LOG_INFO("InitUserInfoList end");
73     return RESULT_SUCCESS;
74 }
75 
DestroyUserInfoList(void)76 void DestroyUserInfoList(void)
77 {
78     DestroyLinkedList(g_userInfoList);
79     g_userInfoList = NULL;
80 }
81 
MatchUserInfo(const void * data,const void * condition)82 IAM_STATIC bool MatchUserInfo(const void *data, const void *condition)
83 {
84     if (data == NULL || condition == NULL) {
85         LOG_ERROR("please check invalid node");
86         return false;
87     }
88     const UserInfo *userInfo = (const UserInfo *)data;
89     int32_t userId = *(const int32_t *)condition;
90     if (userInfo->userId == userId) {
91         return true;
92     }
93     return false;
94 }
95 
IsUserInfoValid(UserInfo * userInfo)96 IAM_STATIC bool IsUserInfoValid(UserInfo *userInfo)
97 {
98     if (userInfo == NULL) {
99         LOG_ERROR("userInfo is null");
100         return false;
101     }
102     if (userInfo->credentialInfoList == NULL) {
103         LOG_ERROR("credentialInfoList is null");
104         return false;
105     }
106     if (userInfo->enrolledInfoList == NULL) {
107         LOG_ERROR("enrolledInfoList is null");
108         return false;
109     }
110     return true;
111 }
112 
GetSecureUid(int32_t userId,uint64_t * secUid)113 ResultCode GetSecureUid(int32_t userId, uint64_t *secUid)
114 {
115     if (secUid == NULL) {
116         LOG_ERROR("secUid is null");
117         return RESULT_BAD_PARAM;
118     }
119     UserInfo *user = QueryUserInfo(userId);
120     if (user == NULL) {
121         LOG_ERROR("can't find this user");
122         return RESULT_NOT_FOUND;
123     }
124     *secUid = user->secUid;
125     return RESULT_SUCCESS;
126 }
127 
GetEnrolledInfoAuthType(int32_t userId,uint32_t authType,EnrolledInfoHal * enrolledInfo)128 ResultCode GetEnrolledInfoAuthType(int32_t userId, uint32_t authType, EnrolledInfoHal *enrolledInfo)
129 {
130     if (enrolledInfo == NULL) {
131         LOG_ERROR("enrolledInfo is null");
132         return RESULT_BAD_PARAM;
133     }
134     UserInfo *user = QueryUserInfo(userId);
135     if (user == NULL) {
136         LOG_ERROR("can't find this user");
137         return RESULT_NOT_FOUND;
138     }
139     if (user->enrolledInfoList == NULL) {
140         LOG_ERROR("enrolledInfoList is null");
141         return RESULT_UNKNOWN;
142     }
143 
144     LinkedListNode *temp = user->enrolledInfoList->head;
145     while (temp != NULL) {
146         EnrolledInfoHal *nodeInfo = temp->data;
147         if (nodeInfo != NULL && nodeInfo->authType == authType) {
148             *enrolledInfo = *nodeInfo;
149             return RESULT_SUCCESS;
150         }
151         temp = temp->next;
152     }
153 
154     return RESULT_NOT_FOUND;
155 }
156 
GetEnrolledInfo(int32_t userId,EnrolledInfoHal ** enrolledInfos,uint32_t * num)157 ResultCode GetEnrolledInfo(int32_t userId, EnrolledInfoHal **enrolledInfos, uint32_t *num)
158 {
159     if (enrolledInfos == NULL || num == NULL) {
160         LOG_ERROR("param is invalid");
161         return RESULT_BAD_PARAM;
162     }
163     UserInfo *user = QueryUserInfo(userId);
164     if (!IsUserInfoValid(user)) {
165         LOG_ERROR("can't find this user");
166         return RESULT_NOT_FOUND;
167     }
168     return GetAllEnrolledInfoFromUser(user, enrolledInfos, num);
169 }
170 
DeleteUserInfo(int32_t userId,LinkedList ** creds)171 ResultCode DeleteUserInfo(int32_t userId, LinkedList **creds)
172 {
173     if (creds == NULL) {
174         LOG_ERROR("param is invalid");
175         return RESULT_BAD_PARAM;
176     }
177     UserInfo *user = QueryUserInfo(userId);
178     if (!IsUserInfoValid(user)) {
179         LOG_ERROR("can't find this user");
180         return RESULT_NOT_FOUND;
181     }
182     CredentialCondition condition = {};
183     SetCredentialConditionUserId(&condition, userId);
184     *creds = QueryCredentialLimit(&condition);
185     if (*creds == NULL) {
186         LOG_ERROR("query credential failed");
187         return RESULT_UNKNOWN;
188     }
189     g_currentUser = NULL;
190 
191     ResultCode ret = DeleteUser(userId);
192     if (ret != RESULT_SUCCESS) {
193         LOG_ERROR("deleteUser failed");
194         DestroyLinkedList(*creds);
195         *creds = NULL;
196         return ret;
197     }
198     ret = UpdateFileInfo(g_userInfoList);
199     if (ret != RESULT_SUCCESS) {
200         LOG_ERROR("update file info failed");
201         DestroyLinkedList(*creds);
202         *creds = NULL;
203         return ret;
204     }
205     return ret;
206 }
207 
QueryUserInfo(int32_t userId)208 IAM_STATIC UserInfo *QueryUserInfo(int32_t userId)
209 {
210     UserInfo *user = g_currentUser;
211     if (user != NULL && user->userId == userId) {
212         return user;
213     }
214     if (g_userInfoList == NULL) {
215         return NULL;
216     }
217     LinkedListNode *temp = g_userInfoList->head;
218     while (temp != NULL) {
219         user = (UserInfo *)temp->data;
220         if (user != NULL && user->userId == userId) {
221             break;
222         }
223         temp = temp->next;
224     }
225     if (temp == NULL) {
226         return NULL;
227     }
228     if (IsUserInfoValid(user)) {
229         g_currentUser = user;
230         return user;
231     }
232     return NULL;
233 }
234 
GetAllEnrolledInfoFromUser(UserInfo * userInfo,EnrolledInfoHal ** enrolledInfos,uint32_t * num)235 IAM_STATIC ResultCode GetAllEnrolledInfoFromUser(UserInfo *userInfo, EnrolledInfoHal **enrolledInfos, uint32_t *num)
236 {
237     LinkedList *enrolledInfoList = userInfo->enrolledInfoList;
238     uint32_t size = enrolledInfoList->getSize(enrolledInfoList);
239     *enrolledInfos = Malloc(sizeof(EnrolledInfoHal) * size);
240     if (*enrolledInfos == NULL) {
241         LOG_ERROR("enrolledInfos malloc failed");
242         return RESULT_NO_MEMORY;
243     }
244     (void)memset_s(*enrolledInfos, sizeof(EnrolledInfoHal) * size, 0, sizeof(EnrolledInfoHal) * size);
245     LinkedListNode *temp = enrolledInfoList->head;
246     ResultCode result = RESULT_SUCCESS;
247     for (*num = 0; *num < size; (*num)++) {
248         if (temp == NULL) {
249             LOG_ERROR("temp node is null, something wrong");
250             result = RESULT_BAD_PARAM;
251             goto EXIT;
252         }
253         EnrolledInfoHal *tempInfo = (EnrolledInfoHal *)temp->data;
254         if (memcpy_s(*enrolledInfos + *num, sizeof(EnrolledInfoHal) * (size - *num),
255             tempInfo, sizeof(EnrolledInfoHal)) != EOK) {
256             LOG_ERROR("copy the %u information failed", *num);
257             result = RESULT_NO_MEMORY;
258             goto EXIT;
259         }
260         temp = temp->next;
261     }
262 
263 EXIT:
264     if (result != RESULT_SUCCESS) {
265         Free(*enrolledInfos);
266         *enrolledInfos = NULL;
267         *num = 0;
268     }
269     return result;
270 }
271 
IsSecureUidDuplicate(LinkedList * userInfoList,uint64_t secureUid)272 IAM_STATIC bool IsSecureUidDuplicate(LinkedList *userInfoList, uint64_t secureUid)
273 {
274     if (userInfoList == NULL) {
275         LOG_ERROR("the user list is empty, and the branch is abnormal");
276         return false;
277     }
278 
279     LinkedListNode *temp = userInfoList->head;
280     UserInfo *userInfo = NULL;
281     while (temp != NULL) {
282         userInfo = (UserInfo *)temp->data;
283         if (userInfo != NULL && userInfo->secUid == secureUid) {
284             return true;
285         }
286         temp = temp->next;
287     }
288 
289     return false;
290 }
291 
CreateUser(int32_t userId)292 IAM_STATIC UserInfo *CreateUser(int32_t userId)
293 {
294     UserInfo *user = InitUserInfoNode();
295     if (!IsUserInfoValid(user)) {
296         LOG_ERROR("user is invalid");
297         DestroyUserInfoNode(user);
298         return NULL;
299     }
300     user->userId = userId;
301     ResultCode ret = GenerateDeduplicateUint64(g_userInfoList, &user->secUid, IsSecureUidDuplicate);
302     if (ret != RESULT_SUCCESS) {
303         LOG_ERROR("generate secureUid failed");
304         DestroyUserInfoNode(user);
305         return NULL;
306     }
307     return user;
308 }
309 
DeleteUser(int32_t userId)310 IAM_STATIC ResultCode DeleteUser(int32_t userId)
311 {
312     if (g_userInfoList == NULL) {
313         return RESULT_BAD_PARAM;
314     }
315     return g_userInfoList->remove(g_userInfoList, &userId, MatchUserInfo, true);
316 }
317 
IsCredentialIdDuplicate(LinkedList * userInfoList,uint64_t credentialId)318 IAM_STATIC bool IsCredentialIdDuplicate(LinkedList *userInfoList, uint64_t credentialId)
319 {
320     (void)userInfoList;
321     CredentialCondition condition = {};
322     SetCredentialConditionCredentialId(&condition, credentialId);
323     LinkedList *credList = QueryCredentialLimit(&condition);
324     if (credList == NULL) {
325         LOG_ERROR("query failed");
326         return true;
327     }
328     if (credList->getSize(credList) != 0) {
329         LOG_ERROR("duplicate credential id");
330         DestroyLinkedList(credList);
331         return true;
332     }
333     DestroyLinkedList(credList);
334     return false;
335 }
336 
IsEnrolledIdDuplicate(LinkedList * enrolledList,uint64_t enrolledId)337 IAM_STATIC bool IsEnrolledIdDuplicate(LinkedList *enrolledList, uint64_t enrolledId)
338 {
339     LinkedListNode *temp = enrolledList->head;
340     EnrolledInfoHal *enrolledInfo = NULL;
341     while (temp != NULL) {
342         enrolledInfo = (EnrolledInfoHal *)temp->data;
343         if (enrolledInfo != NULL && enrolledInfo->enrolledId == enrolledId) {
344             return true;
345         }
346         temp = temp->next;
347     }
348 
349     return false;
350 }
351 
GenerateDeduplicateUint64(LinkedList * collection,uint64_t * destValue,DuplicateCheckFunc func)352 IAM_STATIC ResultCode GenerateDeduplicateUint64(LinkedList *collection, uint64_t *destValue, DuplicateCheckFunc func)
353 {
354     if (collection == NULL || destValue == NULL || func == NULL) {
355         LOG_ERROR("param is null");
356         return RESULT_BAD_PARAM;
357     }
358 
359     for (uint32_t i = 0; i < MAX_DUPLICATE_CHECK; ++i) {
360         uint64_t tempRandom;
361         if (SecureRandom((uint8_t *)&tempRandom, sizeof(uint64_t)) != RESULT_SUCCESS) {
362             LOG_ERROR("get random failed");
363             return RESULT_GENERAL_ERROR;
364         }
365         if (!func(collection, tempRandom)) {
366             *destValue = tempRandom;
367             return RESULT_SUCCESS;
368         }
369     }
370 
371     LOG_ERROR("generate random failed");
372     return RESULT_GENERAL_ERROR;
373 }
374 
UpdateEnrolledId(LinkedList * enrolledList,uint32_t authType)375 IAM_STATIC ResultCode UpdateEnrolledId(LinkedList *enrolledList, uint32_t authType)
376 {
377     LinkedListNode *temp = enrolledList->head;
378     EnrolledInfoHal *enrolledInfo = NULL;
379     while (temp != NULL) {
380         EnrolledInfoHal *nodeData = (EnrolledInfoHal *)temp->data;
381         if (nodeData != NULL && nodeData->authType == authType) {
382             enrolledInfo = nodeData;
383             break;
384         }
385         temp = temp->next;
386     }
387 
388     if (enrolledInfo != NULL) {
389         return GenerateDeduplicateUint64(enrolledList, &enrolledInfo->enrolledId, IsEnrolledIdDuplicate);
390     }
391 
392     enrolledInfo = Malloc(sizeof(EnrolledInfoHal));
393     if (enrolledInfo == NULL) {
394         LOG_ERROR("enrolledInfo malloc failed");
395         return RESULT_NO_MEMORY;
396     }
397     enrolledInfo->authType = authType;
398     ResultCode ret = GenerateDeduplicateUint64(enrolledList, &enrolledInfo->enrolledId, IsEnrolledIdDuplicate);
399     if (ret != RESULT_SUCCESS) {
400         LOG_ERROR("generate enrolledId failed");
401         Free(enrolledInfo);
402         return ret;
403     }
404     ret = enrolledList->insert(enrolledList, enrolledInfo);
405     if (ret != RESULT_SUCCESS) {
406         LOG_ERROR("enrolledInfo insert failed");
407         Free(enrolledInfo);
408     }
409     return ret;
410 }
411 
AddCredentialToUser(UserInfo * user,CredentialInfoHal * credentialInfo)412 IAM_STATIC ResultCode AddCredentialToUser(UserInfo *user, CredentialInfoHal *credentialInfo)
413 {
414     if (g_userInfoList == NULL) {
415         LOG_ERROR("g_userInfoList is uninitialized");
416         return RESULT_NEED_INIT;
417     }
418     LinkedList *credentialList = user->credentialInfoList;
419     LinkedList *enrolledList = user->enrolledInfoList;
420     if (credentialList->getSize(credentialList) >= MAX_CREDENTIAL) {
421         LOG_ERROR("the number of credentials reaches the maximum");
422         return RESULT_EXCEED_LIMIT;
423     }
424 
425     ResultCode ret = UpdateEnrolledId(enrolledList, credentialInfo->authType);
426     if (ret != RESULT_SUCCESS) {
427         LOG_ERROR("update enrolledId failed");
428         return ret;
429     }
430     ret = GenerateDeduplicateUint64(g_userInfoList, &credentialInfo->credentialId, IsCredentialIdDuplicate);
431     if (ret != RESULT_SUCCESS) {
432         LOG_ERROR("GenerateDeduplicateUint64 failed");
433         return ret;
434     }
435     CredentialInfoHal *credential = Malloc(sizeof(CredentialInfoHal));
436     if (credential == NULL) {
437         LOG_ERROR("credential malloc failed");
438         return RESULT_NO_MEMORY;
439     }
440     if (memcpy_s(credential, sizeof(CredentialInfoHal), credentialInfo, sizeof(CredentialInfoHal)) != EOK) {
441         LOG_ERROR("credential copy failed");
442         Free(credential);
443         return RESULT_BAD_COPY;
444     }
445     ret = credentialList->insert(credentialList, credential);
446     if (ret != RESULT_SUCCESS) {
447         LOG_ERROR("insert credential failed");
448         Free(credential);
449     }
450     return ret;
451 }
452 
AddUser(int32_t userId,CredentialInfoHal * credentialInfo)453 IAM_STATIC ResultCode AddUser(int32_t userId, CredentialInfoHal *credentialInfo)
454 {
455     if (g_userInfoList == NULL) {
456         LOG_ERROR("please init");
457         return RESULT_NEED_INIT;
458     }
459     if (g_userInfoList->getSize(g_userInfoList) >= MAX_USER) {
460         LOG_ERROR("the number of users reaches the maximum");
461         return RESULT_EXCEED_LIMIT;
462     }
463 
464     UserInfo *user = QueryUserInfo(userId);
465     if (user != NULL) {
466         LOG_ERROR("Please check pin");
467         return RESULT_BAD_PARAM;
468     }
469 
470     user = CreateUser(userId);
471     if (user == NULL) {
472         LOG_ERROR("create user failed");
473         return RESULT_UNKNOWN;
474     }
475 
476     ResultCode ret = AddCredentialToUser(user, credentialInfo);
477     if (ret != RESULT_SUCCESS) {
478         LOG_ERROR("add credential to user failed");
479         goto FAIL;
480     }
481 
482     ret = g_userInfoList->insert(g_userInfoList, user);
483     if (ret != RESULT_SUCCESS) {
484         LOG_ERROR("insert failed");
485         goto FAIL;
486     }
487     return ret;
488 
489 FAIL:
490     DestroyUserInfoNode(user);
491     return ret;
492 }
493 
AddCredentialInfo(int32_t userId,CredentialInfoHal * credentialInfo)494 ResultCode AddCredentialInfo(int32_t userId, CredentialInfoHal *credentialInfo)
495 {
496     if (credentialInfo == NULL) {
497         LOG_ERROR("credentialInfo is null");
498         return RESULT_BAD_PARAM;
499     }
500     UserInfo *user = QueryUserInfo(userId);
501     if (user == NULL && credentialInfo->authType == PIN_AUTH) {
502         ResultCode ret = AddUser(userId, credentialInfo);
503         if (ret != RESULT_SUCCESS) {
504             LOG_ERROR("add user failed");
505             return ret;
506         }
507         ret = UpdateFileInfo(g_userInfoList);
508         if (ret != RESULT_SUCCESS) {
509             LOG_ERROR("updateFileInfo failed");
510         }
511         return ret;
512     }
513     if (user == NULL) {
514         LOG_ERROR("user is null");
515         return RESULT_BAD_PARAM;
516     }
517     if (credentialInfo->authType == PIN_AUTH) {
518         CredentialCondition condition = {};
519         SetCredentialConditionAuthType(&condition, PIN_AUTH);
520         SetCredentialConditionUserId(&condition, userId);
521         LinkedList *credList = QueryCredentialLimit(&condition);
522         if (credList == NULL) {
523             LOG_ERROR("query credential failed");
524             return RESULT_UNKNOWN;
525         }
526         if (credList->getSize(credList) != 0) {
527             LOG_ERROR("double pin");
528             DestroyLinkedList(credList);
529             return RESULT_BAD_PARAM;
530         }
531         DestroyLinkedList(credList);
532     }
533     ResultCode ret = AddCredentialToUser(user, credentialInfo);
534     if (ret != RESULT_SUCCESS) {
535         LOG_ERROR("add credential to user failed");
536         return ret;
537     }
538     ret = UpdateFileInfo(g_userInfoList);
539     if (ret != RESULT_SUCCESS) {
540         LOG_ERROR("updateFileInfo failed");
541     }
542     return ret;
543 }
544 
MatchCredentialById(const void * data,const void * condition)545 IAM_STATIC bool MatchCredentialById(const void *data, const void *condition)
546 {
547     if (data == NULL || condition == NULL) {
548         return false;
549     }
550     const CredentialInfoHal *credentialInfo = (const CredentialInfoHal *)data;
551     uint64_t credentialId = *(const uint64_t *)condition;
552     if (credentialInfo->credentialId == credentialId) {
553         return true;
554     }
555     return false;
556 }
557 
MatchEnrolledInfoByType(const void * data,const void * condition)558 IAM_STATIC bool MatchEnrolledInfoByType(const void *data, const void *condition)
559 {
560     if (data == NULL || condition == NULL) {
561         return false;
562     }
563     const EnrolledInfoHal *enrolledInfo = (const EnrolledInfoHal *)data;
564     uint32_t authType = *(const uint32_t *)condition;
565     if (enrolledInfo->authType == authType) {
566         return true;
567     }
568     return false;
569 }
570 
DeleteCredentialInfo(int32_t userId,uint64_t credentialId,CredentialInfoHal * credentialInfo)571 ResultCode DeleteCredentialInfo(int32_t userId, uint64_t credentialId, CredentialInfoHal *credentialInfo)
572 {
573     if (credentialInfo == NULL) {
574         LOG_ERROR("param is invalid");
575         return RESULT_BAD_PARAM;
576     }
577 
578     UserInfo *user = QueryUserInfo(userId);
579     if (user == NULL) {
580         LOG_ERROR("can't find this user");
581         return RESULT_BAD_PARAM;
582     }
583 
584     LinkedList *credentialList = user->credentialInfoList;
585     CredentialInfoHal *credentialQuery = QueryCredentialById(credentialId, credentialList);
586     if (credentialQuery == NULL) {
587         LOG_ERROR("credentialQuery is null");
588         return RESULT_UNKNOWN;
589     }
590     if (memcpy_s(credentialInfo, sizeof(CredentialInfoHal), credentialQuery, sizeof(CredentialInfoHal)) != EOK) {
591         LOG_ERROR("copy failed");
592         return RESULT_BAD_COPY;
593     }
594     ResultCode ret = credentialList->remove(credentialList, &credentialId, MatchCredentialById, true);
595     if (ret != RESULT_SUCCESS) {
596         LOG_ERROR("remove credential failed");
597         return ret;
598     }
599     credentialQuery = QueryCredentialByAuthType(credentialInfo->authType, credentialList);
600     if (credentialQuery != NULL) {
601         return UpdateFileInfo(g_userInfoList);
602     }
603 
604     LinkedList *enrolledInfoList = user->enrolledInfoList;
605     if (enrolledInfoList == NULL) {
606         LOG_ERROR("enrolledInfoList is null");
607         return RESULT_UNKNOWN;
608     }
609     ret = enrolledInfoList->remove(enrolledInfoList, &credentialInfo->authType, MatchEnrolledInfoByType, true);
610     if (ret != RESULT_SUCCESS) {
611         LOG_ERROR("remove enrolledInfo failed");
612         return ret;
613     }
614 
615     return UpdateFileInfo(g_userInfoList);
616 }
617 
QueryCredentialById(uint64_t credentialId,LinkedList * credentialList)618 IAM_STATIC CredentialInfoHal *QueryCredentialById(uint64_t credentialId, LinkedList *credentialList)
619 {
620     if (credentialList == NULL) {
621         return NULL;
622     }
623     LinkedListNode *temp = credentialList->head;
624     CredentialInfoHal *credentialInfo = NULL;
625     while (temp != NULL) {
626         CredentialInfoHal *nodeData = (CredentialInfoHal *)temp->data;
627         if (nodeData != NULL && nodeData->credentialId == credentialId) {
628             credentialInfo = nodeData;
629             break;
630         }
631         temp = temp->next;
632     }
633     return credentialInfo;
634 }
635 
QueryCredentialByAuthType(uint32_t authType,LinkedList * credentialList)636 IAM_STATIC CredentialInfoHal *QueryCredentialByAuthType(uint32_t authType, LinkedList *credentialList)
637 {
638     if (credentialList == NULL) {
639         return NULL;
640     }
641     LinkedListNode *temp = credentialList->head;
642     CredentialInfoHal *credentialInfo = NULL;
643     while (temp != NULL) {
644         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
645         if (nodeData != NULL && nodeData->authType == authType) {
646             credentialInfo = nodeData;
647             break;
648         }
649         temp = temp->next;
650     }
651     return credentialInfo;
652 }
653 
IsCredMatch(const CredentialCondition * limit,const CredentialInfoHal * credentialInfo)654 IAM_STATIC bool IsCredMatch(const CredentialCondition *limit, const CredentialInfoHal *credentialInfo)
655 {
656     if ((limit->conditionFactor & CREDENTIAL_CONDITION_CREDENTIAL_ID) != 0 &&
657         limit->credentialId != credentialInfo->credentialId) {
658         return false;
659     }
660     if ((limit->conditionFactor & CREDENTIAL_CONDITION_AUTH_TYPE) != 0 && limit->authType != credentialInfo->authType) {
661         return false;
662     }
663     if ((limit->conditionFactor & CREDENTIAL_CONDITION_TEMPLATE_ID) != 0 &&
664         limit->templateId != credentialInfo->templateId) {
665         return false;
666     }
667     if ((limit->conditionFactor & CREDENTIAL_CONDITION_SENSOR_HINT) != 0 &&
668         limit->executorSensorHint != INVALID_SENSOR_HINT &&
669         limit->executorSensorHint != credentialInfo->executorSensorHint) {
670         return false;
671     }
672     if ((limit->conditionFactor & CREDENTIAL_CONDITION_EXECUTOR_MATCHER) != 0 &&
673         limit->executorMatcher != credentialInfo->executorMatcher) {
674         return false;
675     }
676     return true;
677 }
678 
IsUserMatch(const CredentialCondition * limit,const UserInfo * user)679 IAM_STATIC bool IsUserMatch(const CredentialCondition *limit, const UserInfo *user)
680 {
681     if ((limit->conditionFactor & CREDENTIAL_CONDITION_USER_ID) != 0 && limit->userId != user->userId) {
682         return false;
683     }
684     return true;
685 }
686 
TraverseCredentialList(const CredentialCondition * limit,const LinkedList * credentialList,LinkedList * credListGet)687 IAM_STATIC ResultCode TraverseCredentialList(const CredentialCondition *limit, const LinkedList *credentialList,
688     LinkedList *credListGet)
689 {
690     if (credentialList == NULL) {
691         LOG_ERROR("credentialList is null");
692         return RESULT_GENERAL_ERROR;
693     }
694     LinkedListNode *temp = credentialList->head;
695     while (temp != NULL) {
696         CredentialInfoHal *nodeData = (CredentialInfoHal*)temp->data;
697         if (nodeData == NULL) {
698             LOG_ERROR("nodeData is null");
699             return RESULT_UNKNOWN;
700         }
701         if (!IsCredMatch(limit, nodeData)) {
702             temp = temp->next;
703             continue;
704         }
705         CredentialInfoHal *copy = (CredentialInfoHal *)Malloc(sizeof(CredentialInfoHal));
706         if (copy == NULL) {
707             LOG_ERROR("copy malloc failed");
708             return RESULT_NO_MEMORY;
709         }
710         *copy = *nodeData;
711         ResultCode ret = credListGet->insert(credListGet, copy);
712         if (ret != RESULT_SUCCESS) {
713             LOG_ERROR("insert failed");
714             Free(copy);
715             return ret;
716         }
717         temp = temp->next;
718     }
719     return RESULT_SUCCESS;
720 }
721 
QueryCredentialLimit(const CredentialCondition * limit)722 LinkedList *QueryCredentialLimit(const CredentialCondition *limit)
723 {
724     if (limit == NULL) {
725         LOG_ERROR("limit is null");
726         return NULL;
727     }
728     if (g_userInfoList == NULL) {
729         LOG_ERROR("g_userInfoList is null");
730         return NULL;
731     }
732     LinkedList *credList = CreateLinkedList(DestroyCredentialNode);
733     if (credList == NULL) {
734         LOG_ERROR("credList is null");
735         return NULL;
736     }
737     LinkedListNode *temp = g_userInfoList->head;
738     while (temp != NULL) {
739         UserInfo *user = (UserInfo *)temp->data;
740         if (user == NULL) {
741             LOG_ERROR("node data is null");
742             DestroyLinkedList(credList);
743             return NULL;
744         }
745         if (IsUserMatch(limit, user)) {
746             ResultCode ret = TraverseCredentialList(limit, user->credentialInfoList, credList);
747             if (ret != RESULT_SUCCESS) {
748                 LOG_ERROR("TraverseCredentialList failed");
749                 DestroyLinkedList(credList);
750                 return NULL;
751             }
752         }
753         temp = temp->next;
754     }
755     return credList;
756 }
757 
QueryCredentialUserId(uint64_t credentialId,int32_t * userId)758 ResultCode QueryCredentialUserId(uint64_t credentialId, int32_t *userId)
759 {
760     if (userId == NULL) {
761         LOG_ERROR("userId is null");
762         return RESULT_BAD_PARAM;
763     }
764     if (g_userInfoList == NULL) {
765         LOG_ERROR("g_userInfoList is null");
766         return RESULT_NEED_INIT;
767     }
768     LinkedList *credList = CreateLinkedList(DestroyCredentialNode);
769     if (credList == NULL) {
770         LOG_ERROR("credList is null");
771         return RESULT_NO_MEMORY;
772     }
773     LinkedListNode *temp = g_userInfoList->head;
774     CredentialCondition condition = {};
775     SetCredentialConditionCredentialId(&condition, credentialId);
776     while (temp != NULL) {
777         UserInfo *user = (UserInfo *)temp->data;
778         if (user == NULL) {
779             LOG_ERROR("user is null");
780             DestroyLinkedList(credList);
781             return RESULT_UNKNOWN;
782         }
783         ResultCode ret = TraverseCredentialList(&condition, user->credentialInfoList, credList);
784         if (ret != RESULT_SUCCESS) {
785             LOG_ERROR("TraverseCredentialList failed");
786             DestroyLinkedList(credList);
787             return RESULT_UNKNOWN;
788         }
789         if (credList->getSize(credList) != 0) {
790             DestroyLinkedList(credList);
791             *userId = user->userId;
792             return RESULT_SUCCESS;
793         }
794         temp = temp->next;
795     }
796     DestroyLinkedList(credList);
797     LOG_ERROR("can't find this credential");
798     return RESULT_NOT_FOUND;
799 }
800 
SetPinSubType(int32_t userId,uint64_t pinSubType)801 ResultCode SetPinSubType(int32_t userId, uint64_t pinSubType)
802 {
803     UserInfo *user = QueryUserInfo(userId);
804     if (user == NULL) {
805         LOG_ERROR("can't find this user");
806         return RESULT_NOT_FOUND;
807     }
808     user->pinSubType = pinSubType;
809     return RESULT_SUCCESS;
810 }
811 
GetPinSubType(int32_t userId,uint64_t * pinSubType)812 ResultCode GetPinSubType(int32_t userId, uint64_t *pinSubType)
813 {
814     if (pinSubType == NULL) {
815         LOG_ERROR("pinSubType is null");
816         return RESULT_BAD_PARAM;
817     }
818     UserInfo *user = QueryUserInfo(userId);
819     if (user == NULL) {
820         LOG_ERROR("can't find this user");
821         return RESULT_NOT_FOUND;
822     }
823     *pinSubType = user->pinSubType;
824     return RESULT_SUCCESS;
825 }
826 
SetCredentialConditionCredentialId(CredentialCondition * condition,uint64_t credentialId)827 void SetCredentialConditionCredentialId(CredentialCondition *condition, uint64_t credentialId)
828 {
829     if (condition == NULL) {
830         LOG_ERROR("condition is null");
831         return;
832     }
833     condition->credentialId = credentialId;
834     condition->conditionFactor |= CREDENTIAL_CONDITION_CREDENTIAL_ID;
835 }
836 
SetCredentialConditionTemplateId(CredentialCondition * condition,uint64_t templateId)837 void SetCredentialConditionTemplateId(CredentialCondition *condition, uint64_t templateId)
838 {
839     if (condition == NULL) {
840         LOG_ERROR("condition is null");
841         return;
842     }
843     condition->templateId = templateId;
844     condition->conditionFactor |= CREDENTIAL_CONDITION_TEMPLATE_ID;
845 }
846 
SetCredentialConditionAuthType(CredentialCondition * condition,uint32_t authType)847 void SetCredentialConditionAuthType(CredentialCondition *condition, uint32_t authType)
848 {
849     if (condition == NULL) {
850         LOG_ERROR("condition is null");
851         return;
852     }
853     condition->authType = authType;
854     condition->conditionFactor |= CREDENTIAL_CONDITION_AUTH_TYPE;
855 }
856 
SetCredentialConditionExecutorSensorHint(CredentialCondition * condition,uint32_t executorSensorHint)857 void SetCredentialConditionExecutorSensorHint(CredentialCondition *condition, uint32_t executorSensorHint)
858 {
859     if (condition == NULL) {
860         LOG_ERROR("condition is null");
861         return;
862     }
863     condition->executorSensorHint = executorSensorHint;
864     condition->conditionFactor |= CREDENTIAL_CONDITION_SENSOR_HINT;
865 }
866 
SetCredentialConditionExecutorMatcher(CredentialCondition * condition,uint32_t executorMatcher)867 void SetCredentialConditionExecutorMatcher(CredentialCondition *condition, uint32_t executorMatcher)
868 {
869     if (condition == NULL) {
870         LOG_ERROR("condition is null");
871         return;
872     }
873     condition->executorMatcher = executorMatcher;
874     condition->conditionFactor |= CREDENTIAL_CONDITION_EXECUTOR_MATCHER;
875 }
876 
SetCredentialConditionUserId(CredentialCondition * condition,int32_t userId)877 void SetCredentialConditionUserId(CredentialCondition *condition, int32_t userId)
878 {
879     if (condition == NULL) {
880         LOG_ERROR("condition is null");
881         return;
882     }
883     condition->userId = userId;
884     condition->conditionFactor |= CREDENTIAL_CONDITION_USER_ID;
885 }
886 
IsUserValid(UserInfo * user)887 IAM_STATIC bool IsUserValid(UserInfo *user)
888 {
889     LinkedList *credentialInfoList = user->credentialInfoList;
890     CredentialInfoHal *pinCredential = QueryCredentialByAuthType(PIN_AUTH, credentialInfoList);
891     if (pinCredential == NULL) {
892         LOG_INFO("user is invalid, userId: %{public}d", user->userId);
893         return false;
894     }
895     return true;
896 }
897 
GetInvalidUser(int32_t * invalidUserId,uint32_t maxUserCount,uint32_t * userCount)898 IAM_STATIC ResultCode GetInvalidUser(int32_t *invalidUserId, uint32_t maxUserCount, uint32_t *userCount)
899 {
900     LOG_INFO("get invalid user start");
901     if (g_userInfoList == NULL) {
902         LOG_ERROR("g_userInfoList is null");
903         return RESULT_GENERAL_ERROR;
904     }
905 
906     LinkedListIterator *iterator = g_userInfoList->createIterator(g_userInfoList);
907     if (iterator == NULL) {
908         LOG_ERROR("create iterator failed");
909         return RESULT_NO_MEMORY;
910     }
911 
912     UserInfo *user = NULL;
913     *userCount = 0;
914     while (iterator->hasNext(iterator)) {
915         user = (UserInfo *)iterator->next(iterator);
916         if (user == NULL) {
917             LOG_ERROR("userinfo list node is null, please check");
918             continue;
919         }
920 
921         if (*userCount >= maxUserCount) {
922             LOG_ERROR("too many users");
923             break;
924         }
925 
926         if (!IsUserValid(user)) {
927             invalidUserId[*userCount] = user->userId;
928             (*userCount)++;
929         }
930     }
931 
932     g_userInfoList->destroyIterator(iterator);
933     return RESULT_SUCCESS;
934 }
935 
ClearInvalidUser(void)936 IAM_STATIC ResultCode ClearInvalidUser(void)
937 {
938     LOG_INFO("clear invalid user start");
939     int32_t invalidUserId[MAX_USER] = {0};
940     uint32_t userCount = 0;
941     if (GetInvalidUser(invalidUserId, MAX_USER, &userCount) != RESULT_SUCCESS) {
942         LOG_ERROR("GetInvalidUser fail");
943         return RESULT_GENERAL_ERROR;
944     }
945     ResultCode ret = RESULT_SUCCESS;
946     for (uint32_t i = 0; i < userCount; ++i) {
947         ret = DeleteUser(invalidUserId[i]);
948         if (ret != RESULT_SUCCESS) {
949             LOG_ERROR("delete invalid user fail, userId: %{public}d, ret: %{public}d", invalidUserId[i], ret);
950             return ret;
951         }
952         LOG_INFO("delete invalid user success, userId: %{public}d, ret: %{public}d", invalidUserId[i], ret);
953     }
954     if (userCount != 0) {
955         ret = UpdateFileInfo(g_userInfoList);
956         if (ret != RESULT_SUCCESS) {
957             LOG_ERROR("UpdateFileInfo fail, ret: %{public}d", ret);
958             return ret;
959         }
960     }
961     return RESULT_SUCCESS;
962 }
963 
GetAllExtUserInfo(UserInfoResult * userInfos,uint32_t userInfoLen,uint32_t * userInfocount)964 ResultCode GetAllExtUserInfo(UserInfoResult *userInfos, uint32_t userInfoLen, uint32_t *userInfocount)
965 {
966     LOG_INFO("get all user info start");
967     if (userInfos == NULL || userInfocount == NULL || g_userInfoList == NULL) {
968         LOG_ERROR("param is null");
969         return RESULT_BAD_PARAM;
970     }
971 
972     LinkedListIterator *iterator = g_userInfoList->createIterator(g_userInfoList);
973     if (iterator == NULL) {
974         LOG_ERROR("create iterator failed");
975         return RESULT_NO_MEMORY;
976     }
977 
978     UserInfo *user = NULL;
979     EnrolledInfoHal *enrolledInfoHal = NULL;
980     *userInfocount = 0;
981     while (iterator->hasNext(iterator)) {
982         user = (UserInfo *)iterator->next(iterator);
983         if (user == NULL) {
984             LOG_ERROR("userinfo list node is null, please check");
985             continue;
986         }
987 
988         if (*userInfocount >= userInfoLen) {
989             LOG_ERROR("too many users");
990             goto ERROR;
991         }
992 
993         userInfos[*userInfocount].userId = user->userId;
994         userInfos[*userInfocount].secUid = user->secUid;
995         userInfos[*userInfocount].pinSubType = (uint32_t)user->pinSubType;
996 
997         ResultCode ret = GetAllEnrolledInfoFromUser(user, &enrolledInfoHal, &(userInfos[*userInfocount].enrollNum));
998         if (ret != RESULT_SUCCESS) {
999             LOG_ERROR("get enrolled info fail");
1000             goto ERROR;
1001         }
1002         if (userInfos[*userInfocount].enrollNum > MAX_ENROLL_OUTPUT) {
1003             LOG_ERROR("too many elements");
1004             free(enrolledInfoHal);
1005             goto ERROR;
1006         }
1007 
1008         for (uint32_t i = 0; i < userInfos[*userInfocount].enrollNum; i++) {
1009             userInfos[*userInfocount].enrolledInfo[i].authType = enrolledInfoHal[i].authType;
1010             userInfos[*userInfocount].enrolledInfo[i].enrolledId = enrolledInfoHal[i].enrolledId;
1011         }
1012 
1013         free(enrolledInfoHal);
1014         (*userInfocount)++;
1015     }
1016 
1017     g_userInfoList->destroyIterator(iterator);
1018     return RESULT_SUCCESS;
1019 
1020 ERROR:
1021     g_userInfoList->destroyIterator(iterator);
1022     return RESULT_GENERAL_ERROR;
1023 }