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