• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022-2023 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 "context_manager.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_log.h"
21 #include "auth_level.h"
22 #include "coauth.h"
23 #include "idm_database.h"
24 
25 #ifdef IAM_TEST_ENABLE
26 #define IAM_STATIC
27 #else
28 #define IAM_STATIC static
29 #endif
30 
31 IAM_STATIC bool IsContextDuplicate(uint64_t contextId);
32 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode);
33 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule);
34 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule);
35 IAM_STATIC void DestroyContextNode(void *data);
36 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context);
37 
38 // Stores information about the current user authentication schedule.
39 IAM_STATIC LinkedList *g_contextList = NULL;
40 
InitUserAuthContextList(void)41 ResultCode InitUserAuthContextList(void)
42 {
43     if (g_contextList != NULL) {
44         return RESULT_SUCCESS;
45     }
46     g_contextList = CreateLinkedList(DestroyContextNode);
47     if (g_contextList == NULL) {
48         return RESULT_GENERAL_ERROR;
49     }
50     return RESULT_SUCCESS;
51 }
52 
DestoryUserAuthContextList(void)53 void DestoryUserAuthContextList(void)
54 {
55     DestroyLinkedList(g_contextList);
56     g_contextList = NULL;
57 }
58 
InitAuthContext(AuthSolutionHal params)59 IAM_STATIC UserAuthContext *InitAuthContext(AuthSolutionHal params)
60 {
61     UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
62     if (context == NULL) {
63         LOG_ERROR("context malloc failed");
64         return NULL;
65     }
66     (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
67     if (memcpy_s(context->challenge, CHALLENGE_LEN, params.challenge, CHALLENGE_LEN) != EOK) {
68         LOG_ERROR("failed to copy challenge");
69         Free(context);
70         return NULL;
71     }
72     context->contextId = params.contextId;
73     context->userId = params.userId;
74     context->authType = params.authType;
75     context->authTrustLevel = params.authTrustLevel;
76     context->collectorSensorHint = params.executorSensorHint;
77     context->scheduleList = CreateLinkedList(DestroyScheduleNode);
78     if (context->scheduleList == NULL) {
79         LOG_ERROR("schedule list create failed");
80         Free(context);
81         return NULL;
82     }
83     return context;
84 }
85 
GenerateAuthContext(AuthSolutionHal params,UserAuthContext ** context)86 ResultCode GenerateAuthContext(AuthSolutionHal params, UserAuthContext **context)
87 {
88     LOG_INFO("start");
89     if (context == NULL) {
90         LOG_ERROR("context is null");
91         return RESULT_BAD_PARAM;
92     }
93     if (g_contextList == NULL) {
94         LOG_ERROR("need init");
95         return RESULT_NEED_INIT;
96     }
97     if (IsContextDuplicate(params.contextId)) {
98         LOG_ERROR("contextId is duplicate");
99         return RESULT_DUPLICATE_CHECK_FAILED;
100     }
101     *context = InitAuthContext(params);
102     if (*context == NULL) {
103         LOG_ERROR("init context failed");
104         return RESULT_GENERAL_ERROR;
105     }
106     ResultCode ret = CreateAndInsertSchedules(*context, SCHEDULE_MODE_AUTH);
107     if (ret != RESULT_SUCCESS) {
108         LOG_ERROR("create schedule failed %{public}d", ret);
109         DestroyContextNode(*context);
110         *context = NULL;
111         return ret;
112     }
113     ret = g_contextList->insert(g_contextList, *context);
114     if (ret != RESULT_SUCCESS) {
115         LOG_ERROR("create schedule failed");
116         DestroyContextNode(*context);
117         *context = NULL;
118         return RESULT_GENERAL_ERROR;
119     }
120     return RESULT_SUCCESS;
121 }
122 
CreateIdentifySchedule(const UserAuthContext * context,CoAuthSchedule ** schedule)123 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule)
124 {
125     ScheduleParam scheduleParam = {};
126     scheduleParam.associateId.contextId = context->contextId;
127     scheduleParam.authType = context->authType;
128     scheduleParam.collectorSensorHint = context->collectorSensorHint;
129     scheduleParam.verifierSensorHint = context->collectorSensorHint;
130     scheduleParam.scheduleMode = SCHEDULE_MODE_IDENTIFY;
131     *schedule = GenerateSchedule(&scheduleParam);
132     if (*schedule == NULL) {
133         LOG_ERROR("GenerateSchedule failed");
134         return RESULT_GENERAL_ERROR;
135     }
136     return RESULT_SUCCESS;
137 }
138 
InitIdentifyContext(const IdentifyParam * params)139 IAM_STATIC UserAuthContext *InitIdentifyContext(const IdentifyParam *params)
140 {
141     UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
142     if (context == NULL) {
143         LOG_ERROR("context malloc failed");
144         return NULL;
145     }
146     (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
147     if (memcpy_s(context->challenge, CHALLENGE_LEN, params->challenge, CHALLENGE_LEN) != EOK) {
148         LOG_ERROR("failed to copy challenge");
149         Free(context);
150         return NULL;
151     }
152     context->contextId = params->contextId;
153     context->authType = params->authType;
154     context->collectorSensorHint = params->executorSensorHint;
155     context->scheduleList = CreateLinkedList(DestroyScheduleNode);
156     if (context->scheduleList == NULL) {
157         LOG_ERROR("schedule list create failed");
158         Free(context);
159         return NULL;
160     }
161     return context;
162 }
163 
GenerateIdentifyContext(IdentifyParam params)164 UserAuthContext *GenerateIdentifyContext(IdentifyParam params)
165 {
166     LOG_INFO("start");
167     if (g_contextList == NULL) {
168         LOG_ERROR("need init");
169         return NULL;
170     }
171     if (IsContextDuplicate(params.contextId)) {
172         LOG_ERROR("contextId is duplicate");
173         return NULL;
174     }
175 
176     UserAuthContext *context = InitIdentifyContext(&params);
177     if (context == NULL) {
178         LOG_ERROR("init context failed");
179         return NULL;
180     }
181     ResultCode ret = CreateAndInsertSchedules(context, SCHEDULE_MODE_IDENTIFY);
182     if (ret != RESULT_SUCCESS) {
183         LOG_ERROR("create schedule failed");
184         DestroyContextNode(context);
185         return NULL;
186     }
187     ret = g_contextList->insert(g_contextList, context);
188     if (ret != RESULT_SUCCESS) {
189         LOG_ERROR("create schedule failed");
190         DestroyContextNode(context);
191         return NULL;
192     }
193     return context;
194 }
195 
GetContext(uint64_t contextId)196 UserAuthContext *GetContext(uint64_t contextId)
197 {
198     if (g_contextList == NULL) {
199         LOG_ERROR("context list is null");
200         return NULL;
201     }
202     uint32_t num = g_contextList->getSize(g_contextList);
203     LinkedListNode *tempNode = g_contextList->head;
204     UserAuthContext *contextRet = NULL;
205     for (uint32_t index = 0; index < num; index++) {
206         if (tempNode == NULL) {
207             LOG_ERROR("node is null");
208             return NULL;
209         }
210         contextRet = (UserAuthContext *)tempNode->data;
211         if (contextRet != NULL && contextRet->contextId == contextId) {
212             return contextRet;
213         }
214         tempNode = tempNode->next;
215     }
216     return NULL;
217 }
218 
InsertScheduleToContext(CoAuthSchedule * schedule,UserAuthContext * context)219 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context)
220 {
221     LinkedList *scheduleList = context->scheduleList;
222     return scheduleList->insert(scheduleList, schedule);
223 }
224 
CreateAndInsertSchedules(UserAuthContext * context,uint32_t authMode)225 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode)
226 {
227     LOG_INFO("start");
228     CoAuthSchedule *schedule = NULL;
229     ResultCode result = RESULT_BAD_PARAM;
230     if (authMode == SCHEDULE_MODE_AUTH) {
231         result = CreateAuthSchedule(context, &schedule);
232     } else if (authMode == SCHEDULE_MODE_IDENTIFY) {
233         result = CreateIdentifySchedule(context, &schedule);
234     } else {
235         LOG_ERROR("authMode is invalid");
236         return result;
237     }
238     if (result != RESULT_SUCCESS) {
239         LOG_INFO("create schedule fail %{public}d", result);
240         return result;
241     }
242     if (AddCoAuthSchedule(schedule) != RESULT_SUCCESS) {
243         LOG_ERROR("AddCoAuthSchedule failed");
244         DestroyCoAuthSchedule(schedule);
245         return RESULT_UNKNOWN;
246     }
247     if (InsertScheduleToContext(schedule, context) != RESULT_SUCCESS) {
248         RemoveCoAuthSchedule(schedule->scheduleId);
249         DestroyCoAuthSchedule(schedule);
250         LOG_ERROR("insert failed");
251         return RESULT_UNKNOWN;
252     }
253     return RESULT_SUCCESS;
254 }
255 
GetAuthCredentialList(const UserAuthContext * context)256 IAM_STATIC LinkedList *GetAuthCredentialList(const UserAuthContext *context)
257 {
258     CredentialCondition condition = {};
259     SetCredentialConditionAuthType(&condition, context->authType);
260     SetCredentialConditionUserId(&condition, context->userId);
261     if (context->collectorSensorHint != INVALID_SENSOR_HINT) {
262         uint32_t executorMatcher;
263         ResultCode ret = QueryCollecterMatcher(context->authType, context->collectorSensorHint, &executorMatcher);
264         if (ret != RESULT_SUCCESS) {
265             LOG_ERROR("query collect matcher failed");
266             return NULL;
267         }
268         SetCredentialConditionExecutorMatcher(&condition, executorMatcher);
269     }
270     return QueryCredentialLimit(&condition);
271 }
272 
CheckCredentialSize(LinkedList * credList)273 IAM_STATIC ResultCode CheckCredentialSize(LinkedList *credList)
274 {
275     uint32_t credNum = credList->getSize(credList);
276     if (credNum == 0) {
277         LOG_ERROR("credNum is 0");
278         return RESULT_NOT_ENROLLED;
279     }
280     if (credNum > MAX_CREDENTIAL) {
281         LOG_ERROR("credNum exceed limit");
282         return RESULT_EXCEED_LIMIT;
283     }
284     return RESULT_SUCCESS;
285 }
286 
QueryAuthTempletaInfo(UserAuthContext * context,Uint64Array * templateIds,uint32_t * sensorHint,uint32_t * matcher,uint32_t * acl)287 IAM_STATIC ResultCode QueryAuthTempletaInfo(UserAuthContext *context, Uint64Array *templateIds,
288     uint32_t *sensorHint, uint32_t *matcher, uint32_t *acl)
289 {
290     LinkedList *credList = GetAuthCredentialList(context);
291     if (credList == NULL) {
292         LOG_ERROR("query credential failed");
293         return RESULT_UNKNOWN;
294     }
295     ResultCode checkResult = CheckCredentialSize(credList);
296     if (checkResult != RESULT_SUCCESS) {
297         LOG_ERROR("CheckCredentialSize failed %{public}d", checkResult);
298         DestroyLinkedList(credList);
299         return checkResult;
300     }
301     templateIds->data = (uint64_t *)Malloc(sizeof(uint64_t) * credList->getSize(credList));
302     if (templateIds->data == NULL) {
303         LOG_ERROR("value malloc failed");
304         DestroyLinkedList(credList);
305         return RESULT_NO_MEMORY;
306     }
307     templateIds->len = 0;
308     LinkedListNode *temp = credList->head;
309     if (temp == NULL || temp->data == NULL) {
310         LOG_ERROR("link node is invalid");
311         goto FAIL;
312     }
313     CredentialInfoHal *credentialHal = (CredentialInfoHal *)temp->data;
314     *sensorHint = credentialHal->executorSensorHint;
315     *matcher = credentialHal->executorMatcher;
316     *acl = credentialHal->capabilityLevel;
317     while (temp != NULL) {
318         if (temp->data == NULL) {
319             LOG_ERROR("link node is invalid");
320             goto FAIL;
321         }
322         credentialHal = (CredentialInfoHal *)temp->data;
323         if (credentialHal->executorSensorHint == *sensorHint) {
324             templateIds->data[templateIds->len] = credentialHal->templateId;
325             ++(templateIds->len);
326         }
327         temp = temp->next;
328     }
329     DestroyLinkedList(credList);
330     return RESULT_SUCCESS;
331 
332 FAIL:
333     Free(templateIds->data);
334     templateIds->data = NULL;
335     DestroyLinkedList(credList);
336     return RESULT_UNKNOWN;
337 }
338 
CreateAuthSchedule(UserAuthContext * context,CoAuthSchedule ** schedule)339 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule)
340 {
341     Uint64Array templateIds = {};
342     uint32_t verifierSensorHint;
343     uint32_t executorMatcher;
344     uint32_t acl;
345     ResultCode ret = QueryAuthTempletaInfo(context, &templateIds, &verifierSensorHint, &executorMatcher, &acl);
346     if (ret != RESULT_SUCCESS) {
347         LOG_ERROR("QueryAuthTempletaInfo failed %{public}d", ret);
348         return ret;
349     }
350     ScheduleParam scheduleParam = {};
351     scheduleParam.associateId.contextId = context->contextId;
352     scheduleParam.authType = context->authType;
353     scheduleParam.collectorSensorHint = context->collectorSensorHint;
354     scheduleParam.verifierSensorHint = verifierSensorHint;
355     scheduleParam.templateIds = &templateIds;
356     scheduleParam.executorMatcher = executorMatcher;
357     scheduleParam.scheduleMode = SCHEDULE_MODE_AUTH;
358     *schedule = GenerateSchedule(&scheduleParam);
359     if (*schedule == NULL) {
360         LOG_ERROR("schedule is null");
361         Free(templateIds.data);
362         return RESULT_GENERAL_ERROR;
363     }
364     uint32_t scheduleAtl;
365     ret = QueryScheduleAtl(*schedule, acl, &scheduleAtl);
366     if (ret != RESULT_SUCCESS || context->authTrustLevel > scheduleAtl) {
367         Free(templateIds.data);
368         DestroyCoAuthSchedule(*schedule);
369         *schedule = NULL;
370         return ret;
371     }
372     Free(templateIds.data);
373     return RESULT_SUCCESS;
374 }
375 
IsContextDuplicate(uint64_t contextId)376 IAM_STATIC bool IsContextDuplicate(uint64_t contextId)
377 {
378     if (g_contextList == NULL) {
379         LOG_ERROR("context list is null");
380         return false;
381     }
382     LinkedListNode *tempNode = g_contextList->head;
383     while (tempNode != NULL) {
384         UserAuthContext *context = (UserAuthContext *)tempNode->data;
385         if (context == NULL) {
386             LOG_ERROR("context is null, please check");
387             tempNode = tempNode->next;
388             continue;
389         }
390         if (context->contextId == contextId) {
391             return true;
392         }
393         tempNode = tempNode->next;
394     }
395     return false;
396 }
397 
CopySchedules(UserAuthContext * context,LinkedList ** schedules)398 ResultCode CopySchedules(UserAuthContext *context, LinkedList **schedules)
399 {
400     if (context == NULL || context->scheduleList == NULL || schedules == NULL) {
401         LOG_ERROR("param is null");
402         return RESULT_BAD_PARAM;
403     }
404     LinkedList *scheduleList = context->scheduleList;
405     uint32_t scheduleNum = scheduleList->getSize(scheduleList);
406     if (scheduleNum > AUTH_MAX_SCHEDULING_NUM) {
407         LOG_ERROR("scheduleNum is invalid, scheduleNum is %{public}u", scheduleNum);
408         return RESULT_UNKNOWN;
409     }
410     *schedules = CreateLinkedList(DestroyScheduleNode);
411     if (*schedules == NULL) {
412         LOG_ERROR("schedules malloc failed");
413         return RESULT_NO_MEMORY;
414     }
415     if (scheduleNum == 0) {
416         LOG_INFO("scheduleNum is zero");
417         return RESULT_SUCCESS;
418     }
419 
420     LinkedListNode *temp = scheduleList->head;
421     while (temp != NULL) {
422         if (temp->data == NULL) {
423             LOG_ERROR("node data is wrong, please check");
424             goto ERROR;
425         }
426         CoAuthSchedule *schedule = CopyCoAuthSchedule((CoAuthSchedule *)temp->data);
427         if (schedule == NULL) {
428             LOG_ERROR("data is null");
429             goto ERROR;
430         }
431         if ((*schedules)->insert(*schedules, schedule) != RESULT_SUCCESS) {
432             LOG_ERROR("insert schedule failed");
433             DestroyCoAuthSchedule(schedule);
434             goto ERROR;
435         }
436         temp = temp->next;
437     }
438     return RESULT_SUCCESS;
439 
440 ERROR:
441     DestroyLinkedList(*schedules);
442     *schedules = NULL;
443     return RESULT_GENERAL_ERROR;
444 }
445 
MatchSchedule(void * data,void * condition)446 IAM_STATIC bool MatchSchedule(void *data, void *condition)
447 {
448     if (data == NULL || condition == NULL) {
449         LOG_ERROR("param is null");
450         return false;
451     }
452     CoAuthSchedule *schedule = (CoAuthSchedule *)data;
453     if (schedule->scheduleId == *(uint64_t *)condition) {
454         return true;
455     }
456     return false;
457 }
458 
ScheduleOnceFinish(UserAuthContext * context,uint64_t scheduleId)459 ResultCode ScheduleOnceFinish(UserAuthContext *context, uint64_t scheduleId)
460 {
461     if (context == NULL || context->scheduleList == NULL) {
462         LOG_ERROR("param is null");
463         return RESULT_BAD_PARAM;
464     }
465     RemoveCoAuthSchedule(scheduleId);
466     return context->scheduleList->remove(context->scheduleList, &scheduleId, MatchSchedule, true);
467 }
468 
MatchContextSelf(void * data,void * condition)469 IAM_STATIC bool MatchContextSelf(void *data, void *condition)
470 {
471     return data == condition;
472 }
473 
DestoryContext(UserAuthContext * context)474 void DestoryContext(UserAuthContext *context)
475 {
476     if (context == NULL) {
477         LOG_ERROR("context is null");
478         return;
479     }
480     if (g_contextList == NULL) {
481         LOG_ERROR("context list is null");
482         return;
483     }
484     g_contextList->remove(g_contextList, context, MatchContextSelf, true);
485 }
486 
DestroyContextNode(void * data)487 IAM_STATIC void DestroyContextNode(void *data)
488 {
489     if (data == NULL) {
490         return;
491     }
492     LinkedList *schedules = ((UserAuthContext *)data)->scheduleList;
493     if (schedules == NULL) {
494         LOG_ERROR("schedules is null");
495         return;
496     }
497     LinkedListNode *tempNode = schedules->head;
498     while (tempNode != NULL) {
499         CoAuthSchedule *schedule = tempNode->data;
500         if (schedule == NULL) {
501             LOG_ERROR("schedule is null, please check");
502             tempNode = tempNode->next;
503             continue;
504         }
505         RemoveCoAuthSchedule(schedule->scheduleId);
506         tempNode = tempNode->next;
507     }
508     DestroyLinkedList(schedules);
509     Free(data);
510 }
511 
DestoryContextbyId(uint64_t contextId)512 ResultCode DestoryContextbyId(uint64_t contextId)
513 {
514     UserAuthContext *authContext = GetContext(contextId);
515     if (authContext == NULL) {
516         LOG_ERROR("get context failed");
517         return RESULT_NOT_FOUND;
518     }
519     DestoryContext(authContext);
520     return RESULT_SUCCESS;
521 }
522 
FillInContext(UserAuthContext * context,uint64_t * credentialId,ExecutorResultInfo * info,uint32_t authMode)523 ResultCode FillInContext(UserAuthContext *context, uint64_t *credentialId, ExecutorResultInfo *info,
524     uint32_t authMode)
525 {
526     if (context == NULL || credentialId == NULL  || info == NULL) {
527         LOG_ERROR("param is null");
528         return RESULT_BAD_PARAM;
529     }
530     const CoAuthSchedule *schedule = GetCoAuthSchedule(info->scheduleId);
531     if (schedule == NULL) {
532         LOG_ERROR("GetCoAuthSchedule failed");
533         return RESULT_GENERAL_ERROR;
534     }
535     ResultCode ret = QueryScheduleAtl(schedule, info->capabilityLevel, &context->authTrustLevel);
536     if (ret != RESULT_SUCCESS) {
537         LOG_ERROR("QueryScheduleAtl failed");
538         return ret;
539     }
540     ret = RESULT_UNKNOWN;
541     uint32_t veriferSensorHint = GetScheduleVeriferSensorHint(schedule);
542     CredentialCondition condition = {};
543     SetCredentialConditionAuthType(&condition, context->authType);
544     SetCredentialConditionTemplateId(&condition, info->templateId);
545     SetCredentialConditionExecutorSensorHint(&condition, veriferSensorHint);
546     LinkedList *credList = QueryCredentialLimit(&condition);
547     if (credList == NULL || credList->getSize(credList) != 1) {
548         LOG_ERROR("query credential failed");
549         goto EXIT;
550     }
551     if (credList->head == NULL || credList->head->data == NULL) {
552         LOG_ERROR("list node is invalid");
553         goto EXIT;
554     }
555     CredentialInfoHal *credentialNode = (CredentialInfoHal *)credList->head->data;
556     int32_t userId = 0;
557     ret = QueryCredentialUserId(credentialNode->credentialId, &userId);
558     if (ret != RESULT_SUCCESS) {
559         LOG_ERROR("query userId failed");
560         goto EXIT;
561     }
562     if (authMode == SCHEDULE_MODE_IDENTIFY) {
563         context->userId = userId;
564     }
565     if (userId != context->userId) {
566         LOG_ERROR("userId is not matched");
567         ret = RESULT_GENERAL_ERROR;
568         goto EXIT;
569     }
570     *credentialId = credentialNode->credentialId;
571 EXIT:
572     DestroyLinkedList(credList);
573     return ret;
574 }
575