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(¶ms);
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