e846b71f035903562258638bc6dcbd8279c451b5
[mirror_edk2.git] / SecurityPkg / UserIdentification / UserIdentifyManagerDxe / UserIdentifyManager.c
1 /** @file
2 This driver manages user information and produces user manager protocol.
3
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UserIdentifyManager.h"
16
17 //
18 // Default user name.
19 //
20 CHAR16 mUserName[] = L"Administrator";
21
22 //
23 // Points to the user profile database.
24 //
25 USER_PROFILE_DB *mUserProfileDb = NULL;
26
27 //
28 // Points to the credential providers found in system.
29 //
30 CREDENTIAL_PROVIDER_INFO *mProviderDb = NULL;
31
32 //
33 // Current user shared in multi function.
34 //
35 EFI_USER_PROFILE_HANDLE mCurrentUser = NULL;
36
37 //
38 // Flag indicates a user is identified.
39 //
40 BOOLEAN mIdentified = FALSE;
41 USER_MANAGER_CALLBACK_INFO *mCallbackInfo = NULL;
42 HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = {
43 {
44 {
45 HARDWARE_DEVICE_PATH,
46 HW_VENDOR_DP,
47 {
48 (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
49 (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
50 }
51 },
52 USER_IDENTIFY_MANAGER_GUID
53 },
54 {
55 END_DEVICE_PATH_TYPE,
56 END_ENTIRE_DEVICE_PATH_SUBTYPE,
57 {
58 (UINT8) (END_DEVICE_PATH_LENGTH),
59 (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
60 }
61 }
62 };
63
64
65 EFI_USER_MANAGER_PROTOCOL gUserIdentifyManager = {
66 UserProfileCreate,
67 UserProfileDelete,
68 UserProfileGetNext,
69 UserProfileCurrent,
70 UserProfileIdentify,
71 UserProfileFind,
72 UserProfileNotify,
73 UserProfileGetInfo,
74 UserProfileSetInfo,
75 UserProfileDeleteInfo,
76 UserProfileGetNextInfo,
77 };
78
79
80 /**
81 Find the specified user in the user database.
82
83 This function searches the specified user from the beginning of the user database.
84 And if NextUser is TRUE, return the next User in the user database.
85
86 @param[in, out] User On entry, points to the user profile entry to search.
87 On return, points to the user profile entry or NULL if not found.
88 @param[in] NextUser If FALSE, find the user in user profile database specifyed by User
89 If TRUE, find the next user in user profile database specifyed
90 by User.
91 @param[out] ProfileIndex A pointer to the index of user profile database that matches the
92 user specifyed by User.
93
94 @retval EFI_NOT_FOUND User was NULL, or User was not found, or the next user was not found.
95 @retval EFI_SUCCESS User or the next user are found in user profile database
96
97 **/
98 EFI_STATUS
99 FindUserProfile (
100 IN OUT USER_PROFILE_ENTRY **User,
101 IN BOOLEAN NextUser,
102 OUT UINTN *ProfileIndex OPTIONAL
103 )
104 {
105 UINTN Index;
106
107 //
108 // Check parameters
109 //
110 if ((mUserProfileDb == NULL) || (User == NULL)) {
111 return EFI_NOT_FOUND;
112 }
113
114 //
115 // Check whether the user profile is in the user profile database.
116 //
117 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
118 if (mUserProfileDb->UserProfile[Index] == *User) {
119 if (ProfileIndex != NULL) {
120 *ProfileIndex = Index;
121 }
122 break;
123 }
124 }
125
126 if (NextUser) {
127 //
128 // Find the next user profile.
129 //
130 Index++;
131 if (Index < mUserProfileDb->UserProfileNum) {
132 *User = mUserProfileDb->UserProfile[Index];
133 } else if (Index == mUserProfileDb->UserProfileNum) {
134 *User = NULL;
135 return EFI_NOT_FOUND;
136 } else {
137 if ((mUserProfileDb->UserProfileNum > 0) && (*User == NULL)) {
138 *User = mUserProfileDb->UserProfile[0];
139 } else {
140 *User = NULL;
141 return EFI_NOT_FOUND;
142 }
143 }
144 } else if (Index == mUserProfileDb->UserProfileNum) {
145 return EFI_NOT_FOUND;
146 }
147
148 return EFI_SUCCESS;
149 }
150
151 /**
152 Find the specified user information record in the specified User profile.
153
154 This function searches the specified user information record from the beginning of the user
155 profile. And if NextInfo is TRUE, return the next info in the user profile.
156
157 @param[in] User Points to the user profile entry.
158 @param[in, out] Info On entry, points to the user information record or NULL to start
159 searching with the first user information record.
160 On return, points to the user information record or NULL if not found.
161 @param[in] NextInfo If FALSE, find the user information record in profile specifyed by User.
162 If TRUE, find the next user information record in profile specifyed
163 by User.
164 @param[out] Offset A pointer to the offset of the information record in the user profile.
165
166 @retval EFI_INVALID_PARAMETER Info is NULL
167 @retval EFI_NOT_FOUND Info was not found, or the next Info was not found.
168 @retval EFI_SUCCESS Info or the next info are found in user profile.
169
170 **/
171 EFI_STATUS
172 FindUserInfo (
173 IN USER_PROFILE_ENTRY * User,
174 IN OUT EFI_USER_INFO **Info,
175 IN BOOLEAN NextInfo,
176 OUT UINTN *Offset OPTIONAL
177 )
178 {
179 EFI_STATUS Status;
180 EFI_USER_INFO *UserInfo;
181 UINTN InfoLen;
182
183 if (Info == NULL) {
184 return EFI_INVALID_PARAMETER;
185 }
186
187 //
188 // Check user profile entry
189 //
190 Status = FindUserProfile (&User, FALSE, NULL);
191 if (EFI_ERROR (Status)) {
192 return Status;
193 }
194
195 //
196 // Find user information in the specified user record.
197 //
198 InfoLen = 0;
199 while (InfoLen < User->UserProfileSize) {
200 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
201 if (UserInfo == *Info) {
202 if (Offset != NULL) {
203 *Offset = InfoLen;
204 }
205 break;
206 }
207 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
208 }
209
210 //
211 // Check whether to find the next user information.
212 //
213 if (NextInfo) {
214 if (InfoLen < User->UserProfileSize) {
215 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
216 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
217 if (InfoLen < User->UserProfileSize) {
218 *Info = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
219 if (Offset != NULL) {
220 *Offset = InfoLen;
221 }
222 } else if (InfoLen == User->UserProfileSize) {
223 *Info = NULL;
224 return EFI_NOT_FOUND;
225 }
226 } else {
227 if (*Info == NULL) {
228 *Info = (EFI_USER_INFO *) User->ProfileInfo;
229 if (Offset != NULL) {
230 *Offset = 0;
231 }
232 } else {
233 *Info = NULL;
234 return EFI_NOT_FOUND;
235 }
236 }
237 } else if (InfoLen == User->UserProfileSize) {
238 return EFI_NOT_FOUND;
239 }
240
241 return EFI_SUCCESS;
242 }
243
244 /**
245 Find a user infomation record by the information record type.
246
247 This function searches all user information records of User. The search starts with the
248 user information record following Info and continues until either the information is found
249 or there are no more user infomation record.
250 A match occurs when a Info.InfoType field matches the user information record type.
251
252 @param[in] User Points to the user profile record to search.
253 @param[in, out] Info On entry, points to the user information record or NULL to start
254 searching with the first user information record.
255 On return, points to the user information record or NULL if not found.
256 @param[in] InfoType The infomation type to be searched.
257
258 @retval EFI_SUCCESS User information was found. Info points to the user information record.
259 @retval EFI_NOT_FOUND User information was not found.
260 @retval EFI_INVALID_PARAMETER User is NULL or Info is NULL.
261
262 **/
263 EFI_STATUS
264 FindUserInfoByType (
265 IN USER_PROFILE_ENTRY *User,
266 IN OUT EFI_USER_INFO **Info,
267 IN UINT8 InfoType
268 )
269 {
270 EFI_STATUS Status;
271 EFI_USER_INFO *UserInfo;
272 UINTN InfoLen;
273
274 if (Info == NULL) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 //
279 // Check whether the user has the specified user information.
280 //
281 InfoLen = 0;
282 if (*Info == NULL) {
283 Status = FindUserProfile (&User, FALSE, NULL);
284 } else {
285 Status = FindUserInfo (User, Info, TRUE, &InfoLen);
286 }
287
288 if (EFI_ERROR (Status)) {
289 return EFI_NOT_FOUND;
290 }
291
292 while (InfoLen < User->UserProfileSize) {
293 UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen);
294 if (UserInfo->InfoType == InfoType) {
295 if (UserInfo != *Info) {
296 *Info = UserInfo;
297 return EFI_SUCCESS;
298 }
299 }
300
301 InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize);
302 }
303
304 *Info = NULL;
305 return EFI_NOT_FOUND;
306 }
307
308 /**
309 Find a user using a user information record.
310
311 This function searches all user profiles for the specified user information record. The
312 search starts with the user information record handle following UserInfo and continues
313 until either the information is found or there are no more user profiles.
314 A match occurs when the Info.InfoType field matches the user information record type and the
315 user information record data matches the portion of Info passed the EFI_USER_INFO header.
316
317 @param[in, out] User On entry, points to the previously returned user profile record,
318 or NULL to start searching with the first user profile.
319 On return, points to the user profile entry, or NULL if not found.
320 @param[in, out] UserInfo On entry, points to the previously returned user information record,
321 or NULL to start searching with the first.
322 On return, points to the user information record, or NULL if not found.
323 @param[in] Info Points to the buffer containing the user information to be compared
324 to the user information record.
325 @param[in] InfoSize The size of Info, in bytes. Same as Info->InfoSize.
326
327 @retval EFI_SUCCESS User information was found. User points to the user profile record,
328 and UserInfo points to the user information record.
329 @retval EFI_NOT_FOUND User information was not found.
330 @retval EFI_INVALID_PARAMETER User is NULL; Info is NULL; or, InfoSize is too small.
331
332 **/
333 EFI_STATUS
334 FindUserProfileByInfo (
335 IN OUT USER_PROFILE_ENTRY **User,
336 IN OUT EFI_USER_INFO **UserInfo, OPTIONAL
337 IN EFI_USER_INFO *Info,
338 IN UINTN InfoSize
339 )
340 {
341 EFI_STATUS Status;
342 EFI_USER_INFO *InfoEntry;
343
344
345 if ((User == NULL) || (Info == NULL)) {
346 return EFI_INVALID_PARAMETER;
347 }
348
349 if (InfoSize < sizeof (EFI_USER_INFO)) {
350 return EFI_INVALID_PARAMETER;
351 }
352
353 if (UserInfo != NULL) {
354 InfoEntry = *UserInfo;
355 } else {
356 InfoEntry = NULL;
357 }
358 //
359 // Find user profile according to information.
360 //
361 if (*User == NULL) {
362 *User = mUserProfileDb->UserProfile[0];
363 }
364
365 //
366 // Check user profile handle.
367 //
368 Status = FindUserProfile (User, FALSE, NULL);
369
370 while (!EFI_ERROR (Status)) {
371 //
372 // Find the user information in a user profile.
373 //
374 while (TRUE) {
375 Status = FindUserInfoByType (*User, &InfoEntry, Info->InfoType);
376 if (EFI_ERROR (Status)) {
377 break;
378 }
379
380 if (InfoSize == Info->InfoSize) {
381 if (CompareMem ((UINT8 *) (InfoEntry + 1), (UINT8 *) (Info + 1), InfoSize - sizeof (EFI_USER_INFO)) == 0) {
382 //
383 // Found the infomation record.
384 //
385 if (UserInfo != NULL) {
386 *UserInfo = InfoEntry;
387 }
388 return EFI_SUCCESS;
389 }
390 }
391 }
392
393 //
394 // Get next user profile.
395 //
396 InfoEntry = NULL;
397 Status = FindUserProfile (User, TRUE, NULL);
398 }
399
400 return EFI_NOT_FOUND;
401 }
402
403 /**
404 Find the credential provider in the specified identity policy.
405
406 @param[in] FindIdentity Point to the user identity policy.
407 @param[in] IdentifyInfo Point to the user information to be searched.
408
409 @retval TRUE The credential provider was found in the identity policy.
410 @retval FALSE The credential provider was not found.
411 **/
412 BOOLEAN
413 FindProvider (
414 IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity,
415 IN CONST EFI_USER_INFO *IdentifyInfo
416 )
417 {
418 UINTN TotalLen;
419 EFI_USER_INFO_IDENTITY_POLICY *Identity;
420
421 //
422 // Found the credential provider.
423 //
424 TotalLen = 0;
425 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
426 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
427 if ((Identity->Type == FindIdentity->Type) &&
428 (Identity->Length == FindIdentity->Length) &&
429 CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1))
430 ) {
431 return TRUE;
432 }
433
434 TotalLen += Identity->Length;
435 }
436
437 return FALSE;
438 }
439
440
441 /**
442 Check whether the access policy is valid.
443
444 @param[in] PolicyInfo Point to the access policy.
445 @param[in] InfoLen The policy length.
446
447 @retval TRUE The policy is a valid access policy.
448 @retval FALSE The access policy is not a valid access policy.
449
450 **/
451 BOOLEAN
452 CheckAccessPolicy (
453 IN UINT8 *PolicyInfo,
454 IN UINTN InfoLen
455 )
456 {
457 UINTN TotalLen;
458 UINTN ValueLen;
459 UINTN OffSet;
460 EFI_USER_INFO_ACCESS_CONTROL Access;
461 EFI_DEVICE_PATH_PROTOCOL *Path;
462 UINTN PathSize;
463
464 TotalLen = 0;
465 while (TotalLen < InfoLen) {
466 //
467 // Check access policy according to type.
468 //
469 CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access));
470 ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
471 switch (Access.Type) {
472 case EFI_USER_INFO_ACCESS_FORBID_LOAD:
473 case EFI_USER_INFO_ACCESS_PERMIT_LOAD:
474 case EFI_USER_INFO_ACCESS_FORBID_CONNECT:
475 case EFI_USER_INFO_ACCESS_PERMIT_CONNECT:
476 OffSet = 0;
477 while (OffSet < ValueLen) {
478 Path = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet);
479 PathSize = GetDevicePathSize (Path);
480 OffSet += PathSize;
481 }
482 if (OffSet != ValueLen) {
483 return FALSE;
484 }
485 break;
486
487 case EFI_USER_INFO_ACCESS_SETUP:
488 if (ValueLen % sizeof (EFI_GUID) != 0) {
489 return FALSE;
490 }
491 break;
492
493 case EFI_USER_INFO_ACCESS_BOOT_ORDER:
494 if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) {
495 return FALSE;
496 }
497 break;
498
499 case EFI_USER_INFO_ACCESS_ENROLL_SELF:
500 case EFI_USER_INFO_ACCESS_ENROLL_OTHERS:
501 case EFI_USER_INFO_ACCESS_MANAGE:
502 if (ValueLen != 0) {
503 return FALSE;
504 }
505 break;
506
507 default:
508 return FALSE;
509 break;
510 }
511
512 TotalLen += Access.Size;
513 }
514
515 if (TotalLen != InfoLen) {
516 return FALSE;
517 }
518
519 return TRUE;
520 }
521
522
523 /**
524 Check whether the identity policy is valid.
525
526 @param[in] PolicyInfo Point to the identity policy.
527 @param[in] InfoLen The policy length.
528
529 @retval TRUE The policy is a valid identity policy.
530 @retval FALSE The access policy is not a valid identity policy.
531
532 **/
533 BOOLEAN
534 CheckIdentityPolicy (
535 IN UINT8 *PolicyInfo,
536 IN UINTN InfoLen
537 )
538 {
539 UINTN TotalLen;
540 UINTN ValueLen;
541 EFI_USER_INFO_IDENTITY_POLICY *Identity;
542
543 TotalLen = 0;
544
545 //
546 // Check each part of policy expression.
547 //
548 while (TotalLen < InfoLen) {
549 //
550 // Check access polisy according to type.
551 //
552 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);
553 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
554 switch (Identity->Type) {
555 //
556 // Check False option.
557 //
558 case EFI_USER_INFO_IDENTITY_FALSE:
559 if (ValueLen != 0) {
560 return FALSE;
561 }
562 break;
563
564 //
565 // Check True option.
566 //
567 case EFI_USER_INFO_IDENTITY_TRUE:
568 if (ValueLen != 0) {
569 return FALSE;
570 }
571 break;
572
573 //
574 // Check negative operation.
575 //
576 case EFI_USER_INFO_IDENTITY_NOT:
577 if (ValueLen != 0) {
578 return FALSE;
579 }
580 break;
581
582 //
583 // Check and operation.
584 //
585 case EFI_USER_INFO_IDENTITY_AND:
586 if (ValueLen != 0) {
587 return FALSE;
588 }
589 break;
590
591 //
592 // Check or operation.
593 //
594 case EFI_USER_INFO_IDENTITY_OR:
595 if (ValueLen != 0) {
596 return FALSE;
597 }
598 break;
599
600 //
601 // Check credential provider by type.
602 //
603 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
604 if (ValueLen != sizeof (EFI_GUID)) {
605 return FALSE;
606 }
607 break;
608
609 //
610 // Check credential provider by ID.
611 //
612 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
613 if (ValueLen != sizeof (EFI_GUID)) {
614 return FALSE;
615 }
616 break;
617
618 default:
619 return FALSE;
620 break;
621 }
622
623 TotalLen += Identity->Length;
624 }
625
626 if (TotalLen != InfoLen) {
627 return FALSE;
628 }
629
630 return TRUE;
631 }
632
633
634 /**
635 Check whether the user information is a valid user information record.
636
637 @param[in] Info points to the user information.
638
639 @retval TRUE The info is a valid user information record.
640 @retval FALSE The info is not a valid user information record.
641
642 **/
643 BOOLEAN
644 CheckUserInfo (
645 IN CONST EFI_USER_INFO *Info
646 )
647 {
648 UINTN InfoLen;
649
650 if (Info == NULL) {
651 return FALSE;
652 }
653 //
654 // Check user information according to information type.
655 //
656 InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO);
657 switch (Info->InfoType) {
658 case EFI_USER_INFO_EMPTY_RECORD:
659 if (InfoLen != 0) {
660 return FALSE;
661 }
662 break;
663
664 case EFI_USER_INFO_NAME_RECORD:
665 case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD:
666 case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD:
667 break;
668
669 case EFI_USER_INFO_CREATE_DATE_RECORD:
670 case EFI_USER_INFO_USAGE_DATE_RECORD:
671 if (InfoLen != sizeof (EFI_TIME)) {
672 return FALSE;
673 }
674 break;
675
676 case EFI_USER_INFO_USAGE_COUNT_RECORD:
677 if (InfoLen != sizeof (UINT64)) {
678 return FALSE;
679 }
680 break;
681
682 case EFI_USER_INFO_IDENTIFIER_RECORD:
683 if (InfoLen != 16) {
684 return FALSE;
685 }
686 break;
687
688 case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD:
689 case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD:
690 case EFI_USER_INFO_GUID_RECORD:
691 if (InfoLen != sizeof (EFI_GUID)) {
692 return FALSE;
693 }
694 break;
695
696 case EFI_USER_INFO_PKCS11_RECORD:
697 case EFI_USER_INFO_CBEFF_RECORD:
698 break;
699
700 case EFI_USER_INFO_FAR_RECORD:
701 case EFI_USER_INFO_RETRY_RECORD:
702 if (InfoLen != 1) {
703 return FALSE;
704 }
705 break;
706
707 case EFI_USER_INFO_ACCESS_POLICY_RECORD:
708 if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) {
709 return FALSE;
710 }
711 break;
712
713 case EFI_USER_INFO_IDENTITY_POLICY_RECORD:
714 if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) {
715 return FALSE;
716 }
717 break;
718
719 default:
720 return FALSE;
721 break;
722 }
723
724 return TRUE;
725 }
726
727
728 /**
729 Check the user profile data format to be added.
730
731 @param[in] UserProfileInfo Points to the user profile data.
732 @param[in] UserProfileSize The length of user profile data.
733
734 @retval TRUE It is a valid user profile.
735 @retval FALSE It is not a valid user profile.
736
737 **/
738 BOOLEAN
739 CheckProfileInfo (
740 IN UINT8 *UserProfileInfo,
741 IN UINTN UserProfileSize
742 )
743 {
744 UINTN ChkLen;
745 EFI_USER_INFO *Info;
746
747 if (UserProfileInfo == NULL) {
748 return FALSE;
749 }
750
751 //
752 // Check user profile information length.
753 //
754 ChkLen = 0;
755 while (ChkLen < UserProfileSize) {
756 Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen);
757 //
758 // Check user information format.
759 //
760 if (!CheckUserInfo (Info)) {
761 return FALSE;
762 }
763
764 ChkLen += ALIGN_VARIABLE (Info->InfoSize);
765 }
766
767 if (ChkLen != UserProfileSize) {
768 return FALSE;
769 }
770
771 return TRUE;
772 }
773
774
775 /**
776 Find the specified RightType in current user profile.
777
778 @param[in] RightType Could be EFI_USER_INFO_ACCESS_MANAGE,
779 EFI_USER_INFO_ACCESS_ENROLL_OTHERS or
780 EFI_USER_INFO_ACCESS_ENROLL_SELF.
781
782 @retval TRUE Find the specified RightType in current user profile.
783 @retval FALSE Can't find the right in the profile.
784
785 **/
786 BOOLEAN
787 CheckCurrentUserAccessRight (
788 IN UINT32 RightType
789 )
790 {
791 EFI_STATUS Status;
792 EFI_USER_INFO *Info;
793 UINTN TotalLen;
794 UINTN CheckLen;
795 EFI_USER_INFO_ACCESS_CONTROL Access;
796
797 //
798 // Get user access right information.
799 //
800 Info = NULL;
801 Status = FindUserInfoByType (
802 (USER_PROFILE_ENTRY *) mCurrentUser,
803 &Info,
804 EFI_USER_INFO_ACCESS_POLICY_RECORD
805 );
806 if (EFI_ERROR (Status)) {
807 return FALSE;
808 }
809
810 ASSERT (Info != NULL);
811 TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO);
812 CheckLen = 0;
813 while (CheckLen < TotalLen) {
814 //
815 // Check right according to access type.
816 //
817 CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access));
818 if (Access.Type == RightType) {
819 return TRUE;;
820 }
821
822 CheckLen += Access.Size;
823 }
824
825 return FALSE;
826 }
827
828
829 /**
830 Create a unique user identifier.
831
832 @param[out] Identifier This points to the identifier.
833
834 **/
835 VOID
836 GenerateIdentifier (
837 OUT UINT8 *Identifier
838 )
839 {
840 EFI_TIME Time;
841 UINT64 MonotonicCount;
842 UINT32 *MonotonicPointer;
843 UINTN Index;
844
845 //
846 // Create a unique user identifier.
847 //
848 gRT->GetTime (&Time, NULL);
849 CopyMem (Identifier, &Time, sizeof (EFI_TIME));
850 //
851 // Remove zeros.
852 //
853 for (Index = 0; Index < sizeof (EFI_TIME); Index++) {
854 if (Identifier[Index] == 0) {
855 Identifier[Index] = 0x5a;
856 }
857 }
858
859 MonotonicPointer = (UINT32 *) Identifier;
860 gBS->GetNextMonotonicCount (&MonotonicCount);
861 MonotonicPointer[0] += (UINT32) MonotonicCount;
862 MonotonicPointer[1] += (UINT32) MonotonicCount;
863 MonotonicPointer[2] += (UINT32) MonotonicCount;
864 MonotonicPointer[3] += (UINT32) MonotonicCount;
865 }
866
867
868 /**
869 Generate unique user ID.
870
871 @param[out] UserId Points to the user identifer.
872
873 **/
874 VOID
875 GenerateUserId (
876 OUT UINT8 *UserId
877 )
878 {
879 EFI_STATUS Status;
880 USER_PROFILE_ENTRY *UserProfile;
881 EFI_USER_INFO *UserInfo;
882 UINTN Index;
883
884 //
885 // Generate unique user ID
886 //
887 while (TRUE) {
888 GenerateIdentifier (UserId);
889 //
890 // Check whether it's unique in user profile database.
891 //
892 if (mUserProfileDb == NULL) {
893 return ;
894 }
895
896 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
897 UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]);
898 UserInfo = NULL;
899 Status = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
900 if (EFI_ERROR (Status)) {
901 continue;
902 }
903
904 if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
905 break;
906 }
907 }
908
909 if (Index == mUserProfileDb->UserProfileNum) {
910 return ;
911 }
912 }
913 }
914
915
916 /**
917 Expand user profile database.
918
919 @retval TRUE Success to expand user profile database.
920 @retval FALSE Fail to expand user profile database.
921
922 **/
923 BOOLEAN
924 ExpandUsermUserProfileDb (
925 VOID
926 )
927 {
928 UINTN MaxNum;
929 USER_PROFILE_DB *NewDataBase;
930
931 //
932 // Create new user profile database.
933 //
934 if (mUserProfileDb == NULL) {
935 MaxNum = USER_NUMBER_INC;
936 } else {
937 MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC;
938 }
939
940 NewDataBase = AllocateZeroPool (
941 sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) +
942 MaxNum * sizeof (EFI_USER_PROFILE_HANDLE)
943 );
944 if (NewDataBase == NULL) {
945 return FALSE;
946 }
947
948 NewDataBase->MaxProfileNum = MaxNum;
949
950 //
951 // Copy old user profile database value
952 //
953 if (mUserProfileDb == NULL) {
954 NewDataBase->UserProfileNum = 0;
955 } else {
956 NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum;
957 CopyMem (
958 NewDataBase->UserProfile,
959 mUserProfileDb->UserProfile,
960 NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE)
961 );
962 FreePool (mUserProfileDb);
963 }
964
965 mUserProfileDb = NewDataBase;
966 return TRUE;
967 }
968
969
970 /**
971 Expand user profile
972
973 @param[in] User Points to user profile.
974 @param[in] ExpandSize The size of user profile.
975
976 @retval TRUE Success to expand user profile size.
977 @retval FALSE Fail to expand user profile size.
978
979 **/
980 BOOLEAN
981 ExpandUserProfile (
982 IN USER_PROFILE_ENTRY *User,
983 IN UINTN ExpandSize
984 )
985 {
986 UINT8 *Info;
987 UINTN InfoSizeInc;
988
989 //
990 // Allocate new memory.
991 //
992 InfoSizeInc = 128;
993 User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc;
994 Info = AllocateZeroPool (User->MaxProfileSize);
995 if (Info == NULL) {
996 return FALSE;
997 }
998
999 //
1000 // Copy exist information.
1001 //
1002 if (User->UserProfileSize > 0) {
1003 CopyMem (Info, User->ProfileInfo, User->UserProfileSize);
1004 FreePool (User->ProfileInfo);
1005 }
1006
1007 User->ProfileInfo = Info;
1008 return TRUE;
1009 }
1010
1011
1012 /**
1013 Add or delete the user's credential record in the provider.
1014
1015 @param[in] ProviderGuid Point to credential provider guid or class guid.
1016 @param[in] ByType If TRUE, Provider is credential class guid.
1017 If FALSE, Provider is provider guid.
1018 @param[in] User Points to user profile.
1019
1020 @retval EFI_SUCCESS Add or delete record successfully.
1021 @retval Others Fail to add or delete record.
1022
1023 **/
1024 EFI_STATUS
1025 ModifyProviderCredential (
1026 IN EFI_GUID *Provider,
1027 IN BOOLEAN ByType,
1028 IN USER_PROFILE_ENTRY *User
1029 )
1030 {
1031 UINTN Index;
1032 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
1033
1034 if (Provider == NULL) {
1035 return EFI_INVALID_PARAMETER;
1036 }
1037
1038
1039 //
1040 // Find the specified credential provider.
1041 //
1042 for (Index = 0; Index < mProviderDb->Count; Index++) {
1043 //
1044 // Check credential provider ID.
1045 //
1046 UserCredential = mProviderDb->Provider[Index];
1047 if (CompareGuid (&UserCredential->Identifier, Provider)) {
1048 return UserCredential->Enroll (UserCredential, User);
1049 }
1050 }
1051
1052 return EFI_NOT_FOUND;
1053 }
1054
1055
1056 /**
1057 Modify user's credential record in the providers.
1058
1059 Found the providers information in PolicyInfo, and then add or delete the user's credential
1060 record in the providers.
1061
1062 @param User Points to user profile.
1063 @param PolicyInfo Point to identification policy to be modified.
1064 @param InfoLen The length of PolicyInfo.
1065
1066 @retval EFI_SUCCESS Modify PolicyInfo successfully.
1067 @retval Others Fail to modify PolicyInfo.
1068
1069 **/
1070 EFI_STATUS
1071 ModifyCredentialInfo (
1072 IN USER_PROFILE_ENTRY *User,
1073 IN UINT8 *PolicyInfo,
1074 IN UINTN InfoLen
1075 )
1076 {
1077 EFI_STATUS Status;
1078 UINTN TotalLen;
1079 EFI_USER_INFO_IDENTITY_POLICY *Identity;
1080
1081 //
1082 // Modify user's credential.
1083 //
1084 TotalLen = 0;
1085 while (TotalLen < InfoLen) {
1086 //
1087 // Check identification policy according to type.
1088 //
1089 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);
1090 switch (Identity->Type) {
1091 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
1092 Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), TRUE, User);
1093 if (EFI_ERROR (Status)) {
1094 return Status;
1095 }
1096 break;
1097
1098 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
1099 Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), FALSE, User);
1100 if (EFI_ERROR (Status)) {
1101 return Status;
1102 }
1103 break;
1104
1105 default:
1106 break;
1107 }
1108
1109 TotalLen += Identity->Length;
1110 }
1111
1112 return EFI_SUCCESS;
1113 }
1114
1115
1116 /**
1117 Save the user profile to non-volatile memory, or delete it from non-volatile memory.
1118
1119 @param[in] User Point to the user profile
1120 @param[in] Delete If TRUE, delete the found user profile.
1121 If FALSE, save the user profile.
1122 @retval EFI_SUCCESS Save or delete user profile successfully.
1123 @retval Others Fail to change the profile.
1124
1125 **/
1126 EFI_STATUS
1127 SaveNvUserProfile (
1128 IN USER_PROFILE_ENTRY *User,
1129 IN BOOLEAN Delete
1130 )
1131 {
1132 EFI_STATUS Status;
1133
1134 //
1135 // Check user profile entry.
1136 //
1137 Status = FindUserProfile (&User, FALSE, NULL);
1138 if (EFI_ERROR (Status)) {
1139 return Status;
1140 }
1141
1142 //
1143 // Save the user profile to non-volatile memory.
1144 //
1145 Status = gRT->SetVariable (
1146 User->UserVarName,
1147 &gUserIdentifyManagerGuid,
1148 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1149 Delete ? 0 : User->UserProfileSize,
1150 User->ProfileInfo
1151 );
1152 return Status;
1153 }
1154
1155
1156 /**
1157 Replace the old identity info with NewInfo in NV Flash.
1158
1159 This function only replace the identity record in the user profile. Don't update
1160 the the information on the credential provider.
1161
1162 @param[in] User Point to the user profile.
1163 @param[in] NewInfo Point to the new identity policy info.
1164 @param[out] UserInfo Point to the new added identity info.
1165
1166 @retval EFI_SUCCESS Replace user identity successfully.
1167 @retval Others Fail to Replace user identity.
1168
1169 **/
1170 EFI_STATUS
1171 SaveUserIpInfo (
1172 IN USER_PROFILE_ENTRY * User,
1173 IN CONST EFI_USER_INFO * NewInfo,
1174 OUT EFI_USER_INFO **UserInfo OPTIONAL
1175 )
1176 {
1177 EFI_STATUS Status;
1178 EFI_USER_INFO *OldIpInfo;
1179 UINTN Offset;
1180 UINTN NextOffset;
1181
1182 if ((NewInfo == NULL) || (User == NULL)) {
1183 return EFI_INVALID_PARAMETER;
1184 }
1185
1186 //
1187 // Get user old identify policy information.
1188 //
1189 OldIpInfo = NULL;
1190 Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
1191 if (EFI_ERROR (Status)) {
1192 return Status;
1193 }
1194
1195 //
1196 // Get the old identity policy offset.
1197 //
1198 Status = FindUserInfo (User, &OldIpInfo, FALSE, &Offset);
1199 if (EFI_ERROR (Status)) {
1200 return Status;
1201 }
1202
1203 //
1204 // Delete the old identity policy information.
1205 //
1206 NextOffset = ALIGN_VARIABLE (OldIpInfo->InfoSize) + Offset;
1207 User->UserProfileSize -= ALIGN_VARIABLE (OldIpInfo->InfoSize);
1208 if (Offset < User->UserProfileSize) {
1209 CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);
1210 }
1211
1212 //
1213 // Add new user information.
1214 //
1215 if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (NewInfo->InfoSize)) {
1216 if (!ExpandUserProfile (User, ALIGN_VARIABLE (NewInfo->InfoSize))) {
1217 return EFI_OUT_OF_RESOURCES;
1218 }
1219 }
1220
1221 CopyMem (User->ProfileInfo + User->UserProfileSize, (VOID *) NewInfo, NewInfo->InfoSize);
1222 if (UserInfo != NULL) {
1223 *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);
1224 }
1225
1226 User->UserProfileSize += ALIGN_VARIABLE (NewInfo->InfoSize);
1227
1228 //
1229 // Save user profile information.
1230 //
1231 Status = SaveNvUserProfile (User, FALSE);
1232 return Status;
1233 }
1234
1235
1236 /**
1237 Remove the provider in FindIdentity from the user identification information record.
1238
1239 @param[in, out] NewInfo On entry, points to the user information to remove provider.
1240 On return, points to the user information the provider is removed.
1241 @param[in] FindIdentity Point to the user identity policy.
1242
1243 @retval TRUE The provider is removed successfully.
1244 @retval FALSE Fail to remove the provider.
1245
1246 **/
1247 BOOLEAN
1248 RemoveProvider (
1249 IN OUT EFI_USER_INFO **NewInfo,
1250 IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity
1251 )
1252 {
1253 UINTN TotalLen;
1254 EFI_USER_INFO_IDENTITY_POLICY *Identity;
1255 EFI_USER_INFO *IdentifyInfo;
1256 UINT8 *Buffer;
1257
1258 IdentifyInfo = *NewInfo;
1259 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);
1260 if (TotalLen == FindIdentity->Length) {
1261 //
1262 // Only one credential provider in the identification policy.
1263 // Set the new policy to be TRUE after removed the provider.
1264 //
1265 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentifyInfo + 1);
1266 Identity->Type = EFI_USER_INFO_IDENTITY_TRUE;
1267 Identity->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
1268 IdentifyInfo->InfoSize = sizeof (EFI_USER_INFO) + Identity->Length;
1269 return TRUE;
1270 }
1271
1272 //
1273 // Found the credential provider.
1274 //
1275 TotalLen = 0;
1276 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
1277 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
1278 if ((Identity->Type == FindIdentity->Type) &&
1279 (Identity->Length == FindIdentity->Length) &&
1280 CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1))
1281 ) {
1282 //
1283 // Found the credential provider to delete
1284 //
1285 if (Identity == (EFI_USER_INFO_IDENTITY_POLICY *)(IdentifyInfo + 1)) {
1286 //
1287 // It is the first item in the identification policy, delete it and the connector after it.
1288 //
1289 Buffer = (UINT8 *) Identity + Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);
1290 IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);
1291 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);
1292 CopyMem (Identity, Buffer, TotalLen);
1293 } else {
1294 //
1295 // It is not the first item in the identification policy, delete it and the connector before it.
1296 //
1297 Buffer = (UINT8 *) Identity + Identity->Length;
1298 TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO);
1299 TotalLen -= (Buffer - (UINT8 *)(IdentifyInfo + 1));
1300 IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);
1301 CopyMem ((UINT8 *) (Identity - 1), Buffer, TotalLen);
1302 }
1303 return TRUE;
1304 }
1305
1306 TotalLen += Identity->Length;
1307 }
1308 return FALSE;
1309 }
1310
1311
1312 /**
1313 This function replaces the old identity policy with a new identity policy.
1314
1315 This function changes user identity policy information.
1316 If enroll new credential failed, recover the old identity policy.
1317
1318 For new policy:
1319 a. For each credential, if it is newly added, try to enroll it.
1320 If enroll failed, try to delete the newly added ones.
1321
1322 b. For each credential, if it exists in the old policy, delete old one,
1323 and enroll new one. If failed to enroll the new one, removed it from new
1324 identification policy.
1325
1326 For old policy:
1327 a. For each credential, if it does not exist in new one, delete it.
1328
1329 @param[in] User Point to the user profile.
1330 @param[in] Info Points to the user identity information.
1331 @param[in] InfoSize The size of Info (Not used in this function).
1332 @param[out] IpInfo The new identification info after modify.
1333
1334 @retval EFI_SUCCESS Modify user identity policy successfully.
1335 @retval Others Fail to modify user identity policy.
1336
1337 **/
1338 EFI_STATUS
1339 ModifyUserIpInfo (
1340 IN USER_PROFILE_ENTRY *User,
1341 IN CONST EFI_USER_INFO *Info,
1342 IN UINTN InfoSize,
1343 OUT EFI_USER_INFO **IpInfo
1344 )
1345 {
1346 EFI_STATUS Status;
1347 EFI_USER_INFO *OldIpInfo;
1348 UINTN TotalLen;
1349 EFI_USER_INFO_IDENTITY_POLICY *Identity;
1350 UINT32 CredentialCount;
1351 EFI_USER_INFO *NewIpInfo;
1352
1353 //
1354 // Get user old identify policy information.
1355 //
1356 OldIpInfo = NULL;
1357 Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
1358 if (EFI_ERROR (Status)) {
1359 return Status;
1360 }
1361 ASSERT (OldIpInfo != NULL);
1362
1363 //
1364 // Enroll new added credential provider.
1365 //
1366 CredentialCount = 0;
1367 TotalLen = 0;
1368 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
1369 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);
1370 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
1371 if (!FindProvider (Identity, OldIpInfo)) {
1372 //
1373 // The credential is NOT found in the old identity policy; add it.
1374 //
1375 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);
1376 if (EFI_ERROR (Status)) {
1377 break;
1378 }
1379 CredentialCount++;
1380 }
1381 }
1382
1383 TotalLen += Identity->Length;
1384 }
1385
1386 if (EFI_ERROR (Status)) {
1387 //
1388 // Enroll new credential failed. Delete the newly enrolled credential, and return.
1389 //
1390 TotalLen = 0;
1391 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
1392 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);
1393 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
1394 if (!FindProvider (Identity, OldIpInfo)) {
1395 //
1396 // The credential is NOT found in the old identity policy. Delete it.
1397 //
1398 if (CredentialCount == 0) {
1399 break;
1400 }
1401
1402 ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);
1403 CredentialCount--;
1404 }
1405 }
1406 TotalLen += Identity->Length;
1407 }
1408
1409 return EFI_DEVICE_ERROR;
1410 }
1411
1412 //
1413 // Backup new identification policy
1414 //
1415 NewIpInfo = AllocateCopyPool (Info->InfoSize, Info);
1416 ASSERT (NewIpInfo != NULL);
1417
1418 //
1419 // Enroll the credential that existed in the old identity policy.
1420 //
1421 TotalLen = 0;
1422 while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) {
1423 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen);
1424 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
1425 if (FindProvider (Identity, OldIpInfo)) {
1426 //
1427 // The credential is found in the old identity policy, so delete the old credential first.
1428 //
1429 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);
1430 if (EFI_ERROR (Status)) {
1431 //
1432 // Failed to delete old credential.
1433 //
1434 FreePool (NewIpInfo);
1435 return EFI_DEVICE_ERROR;
1436 }
1437
1438 //
1439 // Add the new credential.
1440 //
1441 Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);
1442 if (EFI_ERROR (Status)) {
1443 //
1444 // Failed to enroll the user by new identification policy.
1445 // So removed the credential provider from the identification policy
1446 //
1447 RemoveProvider (&NewIpInfo, Identity);
1448 }
1449 }
1450 }
1451 TotalLen += Identity->Length;
1452 }
1453
1454 //
1455 // Delete old credential that didn't exist in the new identity policy.
1456 //
1457 TotalLen = 0;
1458 while (TotalLen < OldIpInfo->InfoSize - sizeof (EFI_USER_INFO)) {
1459 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (OldIpInfo + 1) + TotalLen);
1460 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
1461 if (!FindProvider (Identity, Info)) {
1462 //
1463 // The credential is NOT found in the new identity policy. Delete the old credential.
1464 //
1465 ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length);
1466 }
1467 }
1468 TotalLen += Identity->Length;
1469 }
1470
1471 *IpInfo = NewIpInfo;
1472 return EFI_SUCCESS;
1473 }
1474
1475
1476 /**
1477 Add one new user info into the user's profile.
1478
1479 @param[in] User point to the user profile
1480 @param[in] Info Points to the user information payload.
1481 @param[in] InfoSize The size of the user information payload, in bytes.
1482 @param[out] UserInfo Point to the new info in user profile
1483 @param[in] Save If TRUE, save the profile to NV flash.
1484 If FALSE, don't need to save the profile to NV flash.
1485
1486 @retval EFI_SUCCESS Add user info to user profile successfully.
1487 @retval Others Fail to add user info to user profile.
1488
1489 **/
1490 EFI_STATUS
1491 AddUserInfo (
1492 IN USER_PROFILE_ENTRY *User,
1493 IN UINT8 *Info,
1494 IN UINTN InfoSize,
1495 OUT EFI_USER_INFO **UserInfo, OPTIONAL
1496 IN BOOLEAN Save
1497 )
1498 {
1499 EFI_STATUS Status;
1500
1501 if ((Info == NULL) || (User == NULL)) {
1502 return EFI_INVALID_PARAMETER;
1503 }
1504
1505 //
1506 // Check user profile handle.
1507 //
1508 Status = FindUserProfile (&User, FALSE, NULL);
1509 if (EFI_ERROR (Status)) {
1510 return Status;
1511 }
1512
1513 //
1514 // Check user information memory size.
1515 //
1516 if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) {
1517 if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) {
1518 return EFI_OUT_OF_RESOURCES;
1519 }
1520 }
1521
1522 //
1523 // Add credential.
1524 //
1525 if (((EFI_USER_INFO *) Info)->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
1526 Status = ModifyCredentialInfo (
1527 User,
1528 (UINT8 *) ((EFI_USER_INFO *) Info + 1),
1529 InfoSize - sizeof (EFI_USER_INFO)
1530 );
1531 if (EFI_ERROR (Status)) {
1532 return Status;
1533 }
1534 }
1535
1536 //
1537 // Add new user information.
1538 //
1539 CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize);
1540 if (UserInfo != NULL) {
1541 *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);
1542 }
1543 User->UserProfileSize += ALIGN_VARIABLE (InfoSize);
1544
1545 //
1546 // Save user profile information.
1547 //
1548 if (Save) {
1549 Status = SaveNvUserProfile (User, FALSE);
1550 }
1551
1552 return Status;
1553 }
1554
1555
1556 /**
1557 Get the user info from the specified user info handle.
1558
1559 @param[in] User Point to the user profile.
1560 @param[in] UserInfo Point to the user information record to get.
1561 @param[out] Info On entry, points to a buffer of at least *InfoSize bytes.
1562 On exit, holds the user information.
1563 @param[in, out] InfoSize On entry, points to the size of Info.
1564 On return, points to the size of the user information.
1565 @param[in] ChkRight If TRUE, check the user info attribute.
1566 If FALSE, don't check the user info attribute.
1567
1568
1569 @retval EFI_ACCESS_DENIED The information cannot be accessed by the current user.
1570 @retval EFI_INVALID_PARAMETER InfoSize is NULL or UserInfo is NULL.
1571 @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the
1572 returned data. The actual size required is returned in *InfoSize.
1573 @retval EFI_SUCCESS Information returned successfully.
1574
1575 **/
1576 EFI_STATUS
1577 GetUserInfo (
1578 IN USER_PROFILE_ENTRY *User,
1579 IN EFI_USER_INFO *UserInfo,
1580 OUT EFI_USER_INFO *Info,
1581 IN OUT UINTN *InfoSize,
1582 IN BOOLEAN ChkRight
1583 )
1584 {
1585 EFI_STATUS Status;
1586
1587 if ((InfoSize == NULL) || (UserInfo == NULL)) {
1588 return EFI_INVALID_PARAMETER;
1589 }
1590
1591 if ((*InfoSize != 0) && (Info == NULL)) {
1592 return EFI_INVALID_PARAMETER;
1593 }
1594
1595 //
1596 // Find the user information to get.
1597 //
1598 Status = FindUserInfo (User, &UserInfo, FALSE, NULL);
1599 if (EFI_ERROR (Status)) {
1600 return Status;
1601 }
1602
1603 //
1604 // Check information attributes.
1605 //
1606 if (ChkRight) {
1607 switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) {
1608 case EFI_USER_INFO_PRIVATE:
1609 case EFI_USER_INFO_PROTECTED:
1610 if (User != mCurrentUser) {
1611 return EFI_ACCESS_DENIED;
1612 }
1613 break;
1614
1615 case EFI_USER_INFO_PUBLIC:
1616 break;
1617
1618 default:
1619 return EFI_INVALID_PARAMETER;
1620 break;
1621 }
1622 }
1623
1624 //
1625 // Get user information.
1626 //
1627 if (UserInfo->InfoSize > *InfoSize) {
1628 *InfoSize = UserInfo->InfoSize;
1629 return EFI_BUFFER_TOO_SMALL;
1630 }
1631
1632 *InfoSize = UserInfo->InfoSize;
1633 if (Info != NULL) {
1634 CopyMem (Info, UserInfo, *InfoSize);
1635 }
1636
1637 return EFI_SUCCESS;
1638 }
1639
1640
1641 /**
1642 Delete the specified user information from user profile.
1643
1644 @param[in] User Point to the user profile.
1645 @param[in] Info Point to the user information record to delete.
1646 @param[in] Save If TRUE, save the profile to NV flash.
1647 If FALSE, don't need to save the profile to NV flash.
1648
1649 @retval EFI_SUCCESS Delete user info from user profile successfully.
1650 @retval Others Fail to delete user info from user profile.
1651
1652 **/
1653 EFI_STATUS
1654 DelUserInfo (
1655 IN USER_PROFILE_ENTRY *User,
1656 IN EFI_USER_INFO *Info,
1657 IN BOOLEAN Save
1658 )
1659 {
1660 EFI_STATUS Status;
1661 UINTN Offset;
1662 UINTN NextOffset;
1663
1664 //
1665 // Check user information handle.
1666 //
1667 Status = FindUserInfo (User, &Info, FALSE, &Offset);
1668 if (EFI_ERROR (Status)) {
1669 return Status;
1670 }
1671
1672 if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
1673 return EFI_ACCESS_DENIED;
1674 } else if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
1675 Status = ModifyCredentialInfo (User, (UINT8 *) (Info + 1), Info->InfoSize - sizeof (EFI_USER_INFO));
1676 if (EFI_ERROR (Status)) {
1677 return Status;
1678 }
1679 }
1680
1681 //
1682 // Delete the specified user information.
1683 //
1684 NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize);
1685 User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize);
1686 if (Offset < User->UserProfileSize) {
1687 CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);
1688 }
1689
1690 if (Save) {
1691 Status = SaveNvUserProfile (User, FALSE);
1692 }
1693
1694 return Status;
1695 }
1696
1697
1698 /**
1699 Add or update user information.
1700
1701 @param[in] User Point to the user profile.
1702 @param[in, out] UserInfo On entry, points to the user information to modify,
1703 or NULL to add a new UserInfo.
1704 On return, points to the modified user information.
1705 @param[in] Info Points to the new user information.
1706 @param[in] InfoSize The size of Info,in bytes.
1707
1708 @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL.
1709 @retval EFI_ACCESS_DENIED The record is exclusive.
1710 @retval EFI_SUCCESS User information was successfully changed/added.
1711
1712 **/
1713 EFI_STATUS
1714 ModifyUserInfo (
1715 IN USER_PROFILE_ENTRY *User,
1716 IN OUT EFI_USER_INFO **UserInfo,
1717 IN CONST EFI_USER_INFO *Info,
1718 IN UINTN InfoSize
1719 )
1720 {
1721 EFI_STATUS Status;
1722 UINTN PayloadLen;
1723 EFI_USER_INFO *OldInfo;
1724 EFI_USER_INFO *IpInfo;
1725
1726 if ((UserInfo == NULL) || (Info == NULL)) {
1727 return EFI_INVALID_PARAMETER;
1728 }
1729
1730 if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) {
1731 return EFI_INVALID_PARAMETER;
1732 }
1733
1734 //
1735 // Check user information.
1736 //
1737 if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
1738 return EFI_ACCESS_DENIED;
1739 }
1740
1741 if (!CheckUserInfo (Info)) {
1742 return EFI_INVALID_PARAMETER;
1743 }
1744
1745
1746 if (*UserInfo == NULL) {
1747 //
1748 // Add new user information.
1749 //
1750 OldInfo = NULL;
1751 do {
1752 Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
1753 if (EFI_ERROR (Status)) {
1754 break;
1755 }
1756 ASSERT (OldInfo != NULL);
1757
1758 if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) ||
1759 ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) {
1760 //
1761 // Same type can not co-exist for exclusive information.
1762 //
1763 return EFI_ACCESS_DENIED;
1764 }
1765
1766 //
1767 // Check whether it exists in DB.
1768 //
1769 if (Info->InfoSize != OldInfo->InfoSize) {
1770 continue;
1771 }
1772
1773 if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) {
1774 continue;
1775 }
1776
1777 PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO);
1778 if (PayloadLen == 0) {
1779 continue;
1780 }
1781
1782 if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) {
1783 continue;
1784 }
1785
1786 //
1787 // Yes. The new info is as same as the one in profile.
1788 //
1789 return EFI_SUCCESS;
1790 } while (!EFI_ERROR (Status));
1791
1792 Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
1793 return Status;
1794 }
1795
1796 //
1797 // Modify existing user information.
1798 //
1799 OldInfo = *UserInfo;
1800 if (OldInfo->InfoType != Info->InfoType) {
1801 return EFI_INVALID_PARAMETER;
1802 }
1803
1804 if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) &&
1805 (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) {
1806 //
1807 // Try to add exclusive attrib in new info.
1808 // Check whether there is another information with the same type in profile.
1809 //
1810 OldInfo = NULL;
1811 do {
1812 Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
1813 if (EFI_ERROR (Status)) {
1814 break;
1815 }
1816 if (OldInfo != *UserInfo) {
1817 //
1818 // There is another information with the same type in profile.
1819 // Therefore, can't modify existing user information to add exclusive attribute.
1820 //
1821 return EFI_ACCESS_DENIED;
1822 }
1823 } while (TRUE);
1824 }
1825
1826 if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
1827 //
1828 // For user identification policy, need to update the info in credential provider.
1829 //
1830 IpInfo = NULL;
1831 Status = ModifyUserIpInfo (User, Info, InfoSize, &IpInfo);
1832 if (EFI_ERROR (Status)) {
1833 return Status;
1834 }
1835
1836 ASSERT (IpInfo != NULL);
1837 Status = SaveUserIpInfo (User, IpInfo, UserInfo);
1838 if (IpInfo->InfoSize != Info->InfoSize) {
1839 Status = EFI_DEVICE_ERROR;
1840 }
1841 FreePool (IpInfo);
1842 return Status;
1843 }
1844
1845 Status = DelUserInfo (User, *UserInfo, FALSE);
1846 if (EFI_ERROR (Status)) {
1847 return Status;
1848 }
1849
1850 return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
1851 }
1852
1853
1854 /**
1855 Delete the user profile from non-volatile memory and database.
1856
1857 @param[in] User Points to the user profile.
1858
1859 @retval EFI_SUCCESS Delete user from the user profile successfully.
1860 @retval Others Fail to delete user from user profile
1861
1862 **/
1863 EFI_STATUS
1864 DelUserProfile (
1865 IN USER_PROFILE_ENTRY *User
1866 )
1867 {
1868 EFI_STATUS Status;
1869 UINTN Index;
1870 EFI_USER_INFO *UserInfo;
1871
1872 //
1873 // Check whether it is in the user profile database.
1874 //
1875 Status = FindUserProfile (&User, FALSE, &Index);
1876 if (EFI_ERROR (Status)) {
1877 return EFI_INVALID_PARAMETER;
1878 }
1879
1880 //
1881 // Check whether it is the current user.
1882 //
1883 if (User == mCurrentUser) {
1884 return EFI_ACCESS_DENIED;
1885 }
1886
1887 //
1888 // Delete user credential information.
1889 //
1890 UserInfo = NULL;
1891 Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
1892 if (Status == EFI_SUCCESS) {
1893 Status = DelUserInfo (User, UserInfo, FALSE);
1894 if (EFI_ERROR (Status)) {
1895 return Status;
1896 }
1897 }
1898
1899 //
1900 // Delete user profile from the non-volatile memory.
1901 //
1902 Status = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE);
1903 if (EFI_ERROR (Status)) {
1904 return Status;
1905 }
1906 mUserProfileDb->UserProfileNum--;
1907
1908 //
1909 // Modify user profile database.
1910 //
1911 if (Index != mUserProfileDb->UserProfileNum) {
1912 mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum];
1913 CopyMem (
1914 ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName,
1915 User->UserVarName,
1916 sizeof (User->UserVarName)
1917 );
1918 Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE);
1919 if (EFI_ERROR (Status)) {
1920 return Status;
1921 }
1922 }
1923 //
1924 // Delete user profile information.
1925 //
1926 if (User->ProfileInfo != NULL) {
1927 FreePool (User->ProfileInfo);
1928 }
1929
1930 FreePool (User);
1931 return EFI_SUCCESS;
1932 }
1933
1934
1935 /**
1936 Add user profile to user profile database.
1937
1938 @param[out] UserProfile Point to the newly added user profile.
1939 @param[in] ProfileSize The size of the user profile.
1940 @param[in] ProfileInfo Point to the user profie data.
1941 @param[in] Save If TRUE, save the new added profile to NV flash.
1942 If FALSE, don't save the profile to NV flash.
1943
1944 @retval EFI_SUCCESS Add user profile to user profile database successfully.
1945 @retval Others Fail to add user profile to user profile database.
1946
1947 **/
1948 EFI_STATUS
1949 AddUserProfile (
1950 OUT USER_PROFILE_ENTRY **UserProfile, OPTIONAL
1951 IN UINTN ProfileSize,
1952 IN UINT8 *ProfileInfo,
1953 IN BOOLEAN Save
1954 )
1955 {
1956 EFI_STATUS Status;
1957 USER_PROFILE_ENTRY *User;
1958
1959 //
1960 // Check the data format to be added.
1961 //
1962 if (!CheckProfileInfo (ProfileInfo, ProfileSize)) {
1963 return EFI_SECURITY_VIOLATION;
1964 }
1965
1966 //
1967 // Create user profile entry.
1968 //
1969 User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY));
1970 if (User == NULL) {
1971 return EFI_OUT_OF_RESOURCES;
1972 }
1973 //
1974 // Add the entry to the user profile database.
1975 //
1976 if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) {
1977 if (!ExpandUsermUserProfileDb ()) {
1978 FreePool (User);
1979 return EFI_OUT_OF_RESOURCES;
1980 }
1981 }
1982
1983 UnicodeSPrint (
1984 User->UserVarName,
1985 sizeof (User->UserVarName),
1986 L"User%04x",
1987 mUserProfileDb->UserProfileNum
1988 );
1989 User->UserProfileSize = 0;
1990 User->MaxProfileSize = 0;
1991 User->ProfileInfo = NULL;
1992 mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User;
1993 mUserProfileDb->UserProfileNum++;
1994
1995 //
1996 // Add user profile information.
1997 //
1998 Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save);
1999 if (EFI_ERROR (Status)) {
2000 DelUserProfile (User);
2001 return Status;
2002 }
2003 //
2004 // Set new user profile handle.
2005 //
2006 if (UserProfile != NULL) {
2007 *UserProfile = User;
2008 }
2009
2010 return EFI_SUCCESS;
2011 }
2012
2013
2014 /**
2015 This function creates a new user profile with only a new user identifier
2016 attached and returns its handle. The user profile is non-volatile, but the
2017 handle User can change across reboots.
2018
2019 @param[out] User Handle of a new user profile.
2020
2021 @retval EFI_SUCCESS User profile was successfully created.
2022 @retval Others Fail to create user profile
2023
2024 **/
2025 EFI_STATUS
2026 CreateUserProfile (
2027 OUT USER_PROFILE_ENTRY **User
2028 )
2029 {
2030 EFI_STATUS Status;
2031 EFI_USER_INFO *UserInfo;
2032
2033 if (User == NULL) {
2034 return EFI_INVALID_PARAMETER;
2035 }
2036 //
2037 // Generate user id information.
2038 //
2039 UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
2040 if (UserInfo == NULL) {
2041 return EFI_OUT_OF_RESOURCES;
2042 }
2043
2044 UserInfo->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD;
2045 UserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
2046 UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2047 GenerateUserId ((UINT8 *) (UserInfo + 1));
2048
2049 //
2050 // Add user profile to the user profile database.
2051 //
2052 Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE);
2053 FreePool (UserInfo);
2054 return Status;
2055 }
2056
2057
2058 /**
2059 Add a default user profile to user profile database.
2060
2061 @retval EFI_SUCCESS A default user profile is added successfully.
2062 @retval Others Fail to add a default user profile
2063
2064 **/
2065 EFI_STATUS
2066 AddDefaultUserProfile (
2067 VOID
2068 )
2069 {
2070 EFI_STATUS Status;
2071 USER_PROFILE_ENTRY *User;
2072 EFI_USER_INFO *Info;
2073 EFI_USER_INFO *NewInfo;
2074 EFI_USER_INFO_CREATE_DATE CreateDate;
2075 EFI_USER_INFO_USAGE_COUNT UsageCount;
2076 EFI_USER_INFO_ACCESS_CONTROL *Access;
2077 EFI_USER_INFO_IDENTITY_POLICY *Policy;
2078
2079 //
2080 // Create a user profile.
2081 //
2082 Status = CreateUserProfile (&User);
2083 if (EFI_ERROR (Status)) {
2084 return Status;
2085 }
2086
2087 //
2088 // Allocate a buffer to add all default user information.
2089 //
2090 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE);
2091 if (Info == NULL) {
2092 return EFI_OUT_OF_RESOURCES;
2093 }
2094
2095 //
2096 // Add user name.
2097 //
2098 Info->InfoType = EFI_USER_INFO_NAME_RECORD;
2099 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2100 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (mUserName);
2101 CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName));
2102 NewInfo = NULL;
2103 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2104 if (EFI_ERROR (Status)) {
2105 goto Done;
2106 }
2107
2108 //
2109 // Add user profile create date record.
2110 //
2111 Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;
2112 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2113 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
2114 Status = gRT->GetTime (&CreateDate, NULL);
2115 if (EFI_ERROR (Status)) {
2116 goto Done;
2117 }
2118
2119 CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE));
2120 NewInfo = NULL;
2121 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2122 if (EFI_ERROR (Status)) {
2123 goto Done;
2124 }
2125
2126 //
2127 // Add user profile usage count record.
2128 //
2129 Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD;
2130 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2131 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
2132 UsageCount = 0;
2133 CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
2134 NewInfo = NULL;
2135 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2136 if (EFI_ERROR (Status)) {
2137 goto Done;
2138 }
2139
2140 //
2141 // Add user access right.
2142 //
2143 Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD;
2144 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2145 Access = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1);
2146 Access->Type = EFI_USER_INFO_ACCESS_MANAGE;
2147 Access->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL);
2148 Info->InfoSize = sizeof (EFI_USER_INFO) + Access->Size;
2149 NewInfo = NULL;
2150 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2151 if (EFI_ERROR (Status)) {
2152 goto Done;
2153 }
2154
2155 //
2156 // Add user identity policy.
2157 //
2158 Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
2159 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE;
2160 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1);
2161 Policy->Type = EFI_USER_INFO_IDENTITY_TRUE;
2162 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2163 Info->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length;
2164 NewInfo = NULL;
2165 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2166
2167 Done:
2168 FreePool (Info);
2169 return Status;
2170 }
2171
2172
2173 /**
2174 Publish current user information into EFI System Configuration Table.
2175
2176 By UEFI spec, the User Identity Manager will publish the current user profile
2177 into the EFI System Configuration Table. Currently, only the user identifier and user
2178 name are published.
2179
2180 @retval EFI_SUCCESS Current user information is published successfully.
2181 @retval Others Fail to publish current user information
2182
2183 **/
2184 EFI_STATUS
2185 PublishUserTable (
2186 VOID
2187 )
2188 {
2189 EFI_STATUS Status;
2190 EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
2191 EFI_USER_INFO_TABLE *UserInfoTable;
2192 EFI_USER_INFO *IdInfo;
2193 EFI_USER_INFO *NameInfo;
2194
2195 Status = EfiGetSystemConfigurationTable (
2196 &gEfiUserManagerProtocolGuid,
2197 (VOID **) &EfiConfigurationTable
2198 );
2199 if (!EFI_ERROR (Status)) {
2200 //
2201 // The table existed!
2202 //
2203 return EFI_SUCCESS;
2204 }
2205
2206 //
2207 // Get user ID information.
2208 //
2209 IdInfo = NULL;
2210 Status = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
2211 if (EFI_ERROR (Status)) {
2212 return Status;
2213
2214 }
2215 //
2216 // Get user name information.
2217 //
2218 NameInfo = NULL;
2219 Status = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD);
2220 if (EFI_ERROR (Status)) {
2221 return Status;
2222 }
2223
2224 //
2225 // Allocate a buffer for user information table.
2226 //
2227 UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool (
2228 sizeof (EFI_USER_INFO_TABLE) +
2229 IdInfo->InfoSize +
2230 NameInfo->InfoSize
2231 );
2232 if (UserInfoTable == NULL) {
2233 Status = EFI_OUT_OF_RESOURCES;
2234 return Status;
2235 }
2236
2237 UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE);
2238
2239 //
2240 // Append the user information to the user info table
2241 //
2242 CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize);
2243 UserInfoTable->Size += IdInfo->InfoSize;
2244
2245 CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize);
2246 UserInfoTable->Size += NameInfo->InfoSize;
2247
2248 Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable);
2249 return Status;
2250 }
2251
2252
2253 /**
2254 Get the user's identity type.
2255
2256 The identify manager only supports the identity policy in which the credential
2257 provider handles are connected by the operator 'AND' or 'OR'.
2258
2259
2260 @param[in] User Handle of a user profile.
2261 @param[out] PolicyType Point to the identity type.
2262
2263 @retval EFI_SUCCESS Get user's identity type successfully.
2264 @retval Others Fail to get user's identity type.
2265
2266 **/
2267 EFI_STATUS
2268 GetIdentifyType (
2269 IN EFI_USER_PROFILE_HANDLE User,
2270 OUT UINT8 *PolicyType
2271 )
2272 {
2273 EFI_STATUS Status;
2274 EFI_USER_INFO *IdentifyInfo;
2275 UINTN TotalLen;
2276 EFI_USER_INFO_IDENTITY_POLICY *Identity;
2277
2278 //
2279 // Get user identify policy information.
2280 //
2281 IdentifyInfo = NULL;
2282 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2283 if (EFI_ERROR (Status)) {
2284 return Status;
2285 }
2286 ASSERT (IdentifyInfo != NULL);
2287
2288 //
2289 // Search the user identify policy according to type.
2290 //
2291 TotalLen = 0;
2292 *PolicyType = EFI_USER_INFO_IDENTITY_FALSE;
2293 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2294 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2295 if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) {
2296 *PolicyType = EFI_USER_INFO_IDENTITY_AND;
2297 break;
2298 }
2299
2300 if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) {
2301 *PolicyType = EFI_USER_INFO_IDENTITY_OR;
2302 break;
2303 }
2304 TotalLen += Identity->Length;
2305 }
2306 return EFI_SUCCESS;
2307 }
2308
2309
2310 /**
2311 Identify the User by the specfied provider.
2312
2313 @param[in] User Handle of a user profile.
2314 @param[in] Provider Points to the identifier of credential provider.
2315
2316 @retval EFI_INVALID_PARAMETER Provider is NULL.
2317 @retval EFI_NOT_FOUND Fail to identify the specified user.
2318 @retval EFI_SUCCESS User is identified successfully.
2319
2320 **/
2321 EFI_STATUS
2322 IdentifyByProviderId (
2323 IN EFI_USER_PROFILE_HANDLE User,
2324 IN EFI_GUID *Provider
2325 )
2326 {
2327 EFI_STATUS Status;
2328 EFI_USER_INFO_IDENTIFIER UserId;
2329 UINTN Index;
2330 EFI_CREDENTIAL_LOGON_FLAGS AutoLogon;
2331 EFI_HII_HANDLE HiiHandle;
2332 EFI_GUID FormSetId;
2333 EFI_FORM_ID FormId;
2334 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
2335
2336 if (Provider == NULL) {
2337 return EFI_INVALID_PARAMETER;
2338 }
2339
2340 //
2341 // Check the user ID identified by the specified credential provider.
2342 //
2343 for (Index = 0; Index < mProviderDb->Count; Index++) {
2344 //
2345 // Check credential provider class.
2346 //
2347 UserCredential = mProviderDb->Provider[Index];
2348 if (CompareGuid (&UserCredential->Identifier, Provider)) {
2349 Status = UserCredential->Select (UserCredential, &AutoLogon);
2350 if (EFI_ERROR (Status)) {
2351 return Status;
2352 }
2353
2354 if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) {
2355 //
2356 // Get credential provider form.
2357 //
2358 Status = UserCredential->Form (
2359 UserCredential,
2360 &HiiHandle,
2361 &FormSetId,
2362 &FormId
2363 );
2364 if (!EFI_ERROR (Status)) {
2365 //
2366 // Send form to get user input.
2367 //
2368 Status = mCallbackInfo->FormBrowser2->SendForm (
2369 mCallbackInfo->FormBrowser2,
2370 &HiiHandle,
2371 1,
2372 &FormSetId,
2373 FormId,
2374 NULL,
2375 NULL
2376 );
2377 if (EFI_ERROR (Status)) {
2378 return Status;
2379 }
2380 }
2381 }
2382
2383 Status = UserCredential->User (UserCredential, User, &UserId);
2384 if (EFI_ERROR (Status)) {
2385 return Status;
2386 }
2387
2388 Status = UserCredential->Deselect (UserCredential);
2389 if (EFI_ERROR (Status)) {
2390 return Status;
2391 }
2392
2393 return EFI_SUCCESS;
2394 }
2395 }
2396
2397 return EFI_NOT_FOUND;
2398 }
2399
2400
2401 /**
2402 Update user information when user is logon on successfully.
2403
2404 @param[in] User Points to user profile.
2405
2406 @retval EFI_SUCCESS Update user information successfully.
2407 @retval Others Fail to update user information.
2408
2409 **/
2410 EFI_STATUS
2411 UpdateUserInfo (
2412 IN USER_PROFILE_ENTRY *User
2413 )
2414 {
2415 EFI_STATUS Status;
2416 EFI_USER_INFO *Info;
2417 EFI_USER_INFO *NewInfo;
2418 EFI_USER_INFO_CREATE_DATE Date;
2419 EFI_USER_INFO_USAGE_COUNT UsageCount;
2420 UINTN InfoLen;
2421
2422 //
2423 // Allocate a buffer to update user's date record and usage record.
2424 //
2425 InfoLen = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT));
2426 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen);
2427 if (Info == NULL) {
2428 return EFI_OUT_OF_RESOURCES;
2429 }
2430
2431 //
2432 // Check create date record.
2433 //
2434 NewInfo = NULL;
2435 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD);
2436 if (Status == EFI_NOT_FOUND) {
2437 Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD;
2438 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2439 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
2440 Status = gRT->GetTime (&Date, NULL);
2441 if (EFI_ERROR (Status)) {
2442 FreePool (Info);
2443 return Status;
2444 }
2445
2446 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));
2447 NewInfo = NULL;
2448 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2449 if (EFI_ERROR (Status)) {
2450 FreePool (Info);
2451 return Status;
2452 }
2453 }
2454
2455 //
2456 // Update usage date record.
2457 //
2458 NewInfo = NULL;
2459 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD);
2460 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
2461 Info->InfoType = EFI_USER_INFO_USAGE_DATE_RECORD;
2462 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2463 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE);
2464 Status = gRT->GetTime (&Date, NULL);
2465 if (EFI_ERROR (Status)) {
2466 FreePool (Info);
2467 return Status;
2468 }
2469
2470 CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE));
2471 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2472 if (EFI_ERROR (Status)) {
2473 FreePool (Info);
2474 return Status;
2475 }
2476 }
2477
2478 //
2479 // Update usage count record.
2480 //
2481 UsageCount = 0;
2482 NewInfo = NULL;
2483 Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD);
2484 //
2485 // Get usage count.
2486 //
2487 if (Status == EFI_SUCCESS) {
2488 CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT));
2489 }
2490
2491 UsageCount++;
2492 if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
2493 Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD;
2494 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
2495 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
2496 CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
2497 Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
2498 if (EFI_ERROR (Status)) {
2499 FreePool (Info);
2500 return Status;
2501 }
2502 }
2503
2504 FreePool (Info);
2505 return EFI_SUCCESS;
2506 }
2507
2508
2509 /**
2510 Add a credenetial provider item in form.
2511
2512 @param[in] ProviderGuid Points to the identifir of credential provider.
2513 @param[in] OpCodeHandle Points to container for dynamic created opcodes.
2514
2515 **/
2516 VOID
2517 AddProviderSelection (
2518 IN EFI_GUID *ProviderGuid,
2519 IN VOID *OpCodeHandle
2520 )
2521 {
2522 EFI_HII_HANDLE HiiHandle;
2523 EFI_STRING_ID ProvID;
2524 CHAR16 *ProvStr;
2525 UINTN Index;
2526 EFI_USER_CREDENTIAL_PROTOCOL *UserCredential;
2527
2528 for (Index = 0; Index < mProviderDb->Count; Index++) {
2529 UserCredential = mProviderDb->Provider[Index];
2530 if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) {
2531 //
2532 // Add credential provider selection.
2533 //
2534 UserCredential->Title (UserCredential, &HiiHandle, &ProvID);
2535 ProvStr = HiiGetString (HiiHandle, ProvID, NULL);
2536 if (ProvStr == NULL) {
2537 continue ;
2538 }
2539 ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);
2540 FreePool (ProvStr);
2541 HiiCreateActionOpCode (
2542 OpCodeHandle, // Container for dynamic created opcodes
2543 (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index), // Question ID
2544 ProvID, // Prompt text
2545 STRING_TOKEN (STR_NULL_STRING), // Help text
2546 EFI_IFR_FLAG_CALLBACK, // Question flag
2547 0 // Action String ID
2548 );
2549 break;
2550 }
2551 }
2552 }
2553
2554
2555 /**
2556 Add a username item in form.
2557
2558 @param[in] Index The index of the user in the user name list.
2559 @param[in] User Points to the user profile whose username is added.
2560 @param[in] OpCodeHandle Points to container for dynamic created opcodes.
2561
2562 @retval EFI_SUCCESS Add a username successfully.
2563 @retval Others Fail to add a username.
2564
2565 **/
2566 EFI_STATUS
2567 AddUserSelection (
2568 IN UINT16 Index,
2569 IN USER_PROFILE_ENTRY *User,
2570 IN VOID *OpCodeHandle
2571 )
2572 {
2573 EFI_STRING_ID UserName;
2574 EFI_STATUS Status;
2575 EFI_USER_INFO *UserInfo;
2576
2577 UserInfo = NULL;
2578 Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD);
2579 if (EFI_ERROR (Status)) {
2580 return Status;
2581 }
2582
2583 //
2584 // Add user name selection.
2585 //
2586 UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL);
2587 if (UserName == 0) {
2588 return EFI_OUT_OF_RESOURCES;
2589 }
2590
2591 HiiCreateGotoOpCode (
2592 OpCodeHandle, // Container for dynamic created opcodes
2593 FORMID_PROVIDER_FORM, // Target Form ID
2594 UserName, // Prompt text
2595 STRING_TOKEN (STR_NULL_STRING), // Help text
2596 EFI_IFR_FLAG_CALLBACK, // Question flag
2597 (UINT16) Index // Question ID
2598 );
2599
2600 return EFI_SUCCESS;
2601 }
2602
2603
2604 /**
2605 Identify the user whose identity policy does not contain the operator 'OR'.
2606
2607 @param[in] User Points to the user profile.
2608
2609 @retval EFI_SUCCESS The specified user is identified successfully.
2610 @retval Others Fail to identify the user.
2611
2612 **/
2613 EFI_STATUS
2614 IdentifyAndTypeUser (
2615 IN USER_PROFILE_ENTRY *User
2616 )
2617 {
2618 EFI_STATUS Status;
2619 EFI_USER_INFO *IdentifyInfo;
2620 BOOLEAN Success;
2621 UINTN TotalLen;
2622 UINTN ValueLen;
2623 EFI_USER_INFO_IDENTITY_POLICY *Identity;
2624
2625 //
2626 // Get user identify policy information.
2627 //
2628 IdentifyInfo = NULL;
2629 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2630 if (EFI_ERROR (Status)) {
2631 return Status;
2632 }
2633 ASSERT (IdentifyInfo != NULL);
2634
2635 //
2636 // Check each part of identification policy expression.
2637 //
2638 Success = FALSE;
2639 TotalLen = 0;
2640 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2641 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2642 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2643 switch (Identity->Type) {
2644
2645 case EFI_USER_INFO_IDENTITY_FALSE:
2646 //
2647 // Check False option.
2648 //
2649 Success = FALSE;
2650 break;
2651
2652 case EFI_USER_INFO_IDENTITY_TRUE:
2653 //
2654 // Check True option.
2655 //
2656 Success = TRUE;
2657 break;
2658
2659 case EFI_USER_INFO_IDENTITY_NOT:
2660 //
2661 // Check negative operation.
2662 //
2663 break;
2664
2665 case EFI_USER_INFO_IDENTITY_AND:
2666 //
2667 // Check and operation.
2668 //
2669 if (!Success) {
2670 return EFI_NOT_READY;
2671 }
2672
2673 Success = FALSE;
2674 break;
2675
2676 case EFI_USER_INFO_IDENTITY_OR:
2677 //
2678 // Check or operation.
2679 //
2680 if (Success) {
2681 return EFI_SUCCESS;
2682 }
2683 break;
2684
2685 case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
2686 //
2687 // Check credential provider by type.
2688 //
2689 break;
2690
2691 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
2692 //
2693 // Check credential provider by ID.
2694 //
2695 if (ValueLen != sizeof (EFI_GUID)) {
2696 return EFI_INVALID_PARAMETER;
2697 }
2698
2699 Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1));
2700 if (EFI_ERROR (Status)) {
2701 return Status;
2702 }
2703
2704 Success = TRUE;
2705 break;
2706
2707 default:
2708 return EFI_INVALID_PARAMETER;
2709 break;
2710 }
2711
2712 TotalLen += Identity->Length;
2713 }
2714
2715 if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2716 return EFI_INVALID_PARAMETER;
2717 }
2718
2719 if (!Success) {
2720 return EFI_NOT_READY;
2721 }
2722
2723 return EFI_SUCCESS;
2724 }
2725
2726
2727 /**
2728 Identify the user whose identity policy does not contain the operator 'AND'.
2729
2730 @param[in] User Points to the user profile.
2731
2732 @retval EFI_SUCCESS The specified user is identified successfully.
2733 @retval Others Fail to identify the user.
2734
2735 **/
2736 EFI_STATUS
2737 IdentifyOrTypeUser (
2738 IN USER_PROFILE_ENTRY *User
2739 )
2740 {
2741 EFI_STATUS Status;
2742 EFI_USER_INFO *IdentifyInfo;
2743 UINTN TotalLen;
2744 UINTN ValueLen;
2745 EFI_USER_INFO_IDENTITY_POLICY *Identity;
2746 VOID *StartOpCodeHandle;
2747 VOID *EndOpCodeHandle;
2748 EFI_IFR_GUID_LABEL *StartLabel;
2749 EFI_IFR_GUID_LABEL *EndLabel;
2750
2751 //
2752 // Get user identify policy information.
2753 //
2754 IdentifyInfo = NULL;
2755 Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2756 if (EFI_ERROR (Status)) {
2757 return Status;
2758 }
2759 ASSERT (IdentifyInfo != NULL);
2760
2761 //
2762 // Initialize the container for dynamic opcodes.
2763 //
2764 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2765 ASSERT (StartOpCodeHandle != NULL);
2766
2767 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2768 ASSERT (EndOpCodeHandle != NULL);
2769
2770 //
2771 // Create Hii Extend Label OpCode.
2772 //
2773 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2774 StartOpCodeHandle,
2775 &gEfiIfrTianoGuid,
2776 NULL,
2777 sizeof (EFI_IFR_GUID_LABEL)
2778 );
2779 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2780 StartLabel->Number = LABEL_PROVIDER_NAME;
2781
2782 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2783 EndOpCodeHandle,
2784 &gEfiIfrTianoGuid,
2785 NULL,
2786 sizeof (EFI_IFR_GUID_LABEL)
2787 );
2788 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2789 EndLabel->Number = LABEL_END;
2790
2791 //
2792 // Add the providers that exists in the user's policy.
2793 //
2794 TotalLen = 0;
2795 while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2796 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2797 ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2798 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
2799 AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle);
2800 }
2801
2802 TotalLen += Identity->Length;
2803 }
2804
2805 HiiUpdateForm (
2806 mCallbackInfo->HiiHandle, // HII handle
2807 &gUserIdentifyManagerGuid,// Formset GUID
2808 FORMID_PROVIDER_FORM, // Form ID
2809 StartOpCodeHandle, // Label for where to insert opcodes
2810 EndOpCodeHandle // Replace data
2811 );
2812
2813 HiiFreeOpCodeHandle (StartOpCodeHandle);
2814 HiiFreeOpCodeHandle (EndOpCodeHandle);
2815
2816 return EFI_SUCCESS;
2817 }
2818
2819
2820 /**
2821 This function processes the results of changes in configuration.
2822
2823 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2824 @param Action Specifies the type of action taken by the browser.
2825 @param QuestionId A unique value which is sent to the original
2826 exporting driver so that it can identify the type
2827 of data to expect.
2828 @param Type The type of value for the question.
2829 @param Value A pointer to the data being sent to the original
2830 exporting driver.
2831 @param ActionRequest On return, points to the action requested by the
2832 callback function.
2833
2834 @retval EFI_SUCCESS The callback successfully handled the action.
2835 @retval Others Fail to handle the action.
2836
2837 **/
2838 EFI_STATUS
2839 EFIAPI
2840 UserIdentifyManagerCallback (
2841 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
2842 IN EFI_BROWSER_ACTION Action,
2843 IN EFI_QUESTION_ID QuestionId,
2844 IN UINT8 Type,
2845 IN EFI_IFR_TYPE_VALUE *Value,
2846 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest
2847 )
2848 {
2849 EFI_STATUS Status;
2850 USER_PROFILE_ENTRY *User;
2851 UINT8 PolicyType;
2852 UINT16 Index;
2853 VOID *StartOpCodeHandle;
2854 VOID *EndOpCodeHandle;
2855 EFI_IFR_GUID_LABEL *StartLabel;
2856 EFI_IFR_GUID_LABEL *EndLabel;
2857
2858 Status = EFI_SUCCESS;
2859
2860 switch (Action) {
2861 case EFI_BROWSER_ACTION_FORM_OPEN:
2862 {
2863 //
2864 // Update user Form when user Form is opened.
2865 // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form.
2866 //
2867 if (QuestionId != FORM_OPEN_QUESTION_ID) {
2868 return EFI_SUCCESS;
2869 }
2870
2871 //
2872 // Initialize the container for dynamic opcodes.
2873 //
2874 StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2875 ASSERT (StartOpCodeHandle != NULL);
2876
2877 EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2878 ASSERT (EndOpCodeHandle != NULL);
2879
2880 //
2881 // Create Hii Extend Label OpCode.
2882 //
2883 StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2884 StartOpCodeHandle,
2885 &gEfiIfrTianoGuid,
2886 NULL,
2887 sizeof (EFI_IFR_GUID_LABEL)
2888 );
2889 StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2890 StartLabel->Number = LABEL_USER_NAME;
2891
2892 EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2893 EndOpCodeHandle,
2894 &gEfiIfrTianoGuid,
2895 NULL,
2896 sizeof (EFI_IFR_GUID_LABEL)
2897 );
2898 EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
2899 EndLabel->Number = LABEL_END;
2900
2901 //
2902 // Add all the user profile in the user profile database.
2903 //
2904 for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
2905 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index];
2906 AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle);
2907 }
2908
2909 HiiUpdateForm (
2910 mCallbackInfo->HiiHandle, // HII handle
2911 &gUserIdentifyManagerGuid,// Formset GUID
2912 FORMID_USER_FORM, // Form ID
2913 StartOpCodeHandle, // Label for where to insert opcodes
2914 EndOpCodeHandle // Replace data
2915 );
2916
2917 HiiFreeOpCodeHandle (StartOpCodeHandle);
2918 HiiFreeOpCodeHandle (EndOpCodeHandle);
2919
2920 return EFI_SUCCESS;
2921 }
2922 break;
2923
2924 case EFI_BROWSER_ACTION_FORM_CLOSE:
2925 Status = EFI_SUCCESS;
2926 break;
2927
2928 case EFI_BROWSER_ACTION_CHANGING:
2929 {
2930 if (QuestionId >= LABEL_PROVIDER_NAME) {
2931 //
2932 // QuestionId comes from the second Form (Select a Credential Provider if identity
2933 // policy is OR type). Identify the user by the selected provider.
2934 //
2935 Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier);
2936 if (Status == EFI_SUCCESS) {
2937 mIdentified = TRUE;
2938 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
2939 }
2940 return EFI_SUCCESS;
2941 }
2942
2943 //
2944 // QuestionId comes from the first Form (Select a user to identify).
2945 //
2946 User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF];
2947 Status = GetIdentifyType (User, &PolicyType);
2948 if (EFI_ERROR (Status)) {
2949 return Status;
2950 }
2951
2952 if (PolicyType == EFI_USER_INFO_IDENTITY_OR) {
2953 //
2954 // Identify the user by "OR" logical.
2955 //
2956 Status = IdentifyOrTypeUser (User);
2957 if (EFI_ERROR (Status)) {
2958 return Status;
2959 }
2960
2961 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
2962 } else {
2963 //
2964 // Identify the user by "AND" logical.
2965 //
2966 Status = IdentifyAndTypeUser (User);
2967 if (EFI_ERROR (Status)) {
2968 return Status;
2969 }
2970
2971 mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
2972 mIdentified = TRUE;
2973 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT;
2974 }
2975 }
2976 break;
2977
2978 default:
2979 //
2980 // All other action return unsupported.
2981 //
2982 Status = EFI_UNSUPPORTED;
2983 break;
2984 }
2985
2986
2987 return Status;
2988 }
2989
2990
2991 /**
2992 This function construct user profile database from user data saved in the Flash.
2993 If no user is found in Flash, add one default user "administrator" in the user
2994 profile database.
2995
2996 @retval EFI_SUCCESS Init user profile database successfully.
2997 @retval Others Fail to init user profile database.
2998
2999 **/
3000 EFI_STATUS
3001 InitUserProfileDb (
3002 VOID
3003 )
3004 {
3005 EFI_STATUS Status;
3006 UINT8 *VarData;
3007 UINTN VarSize;
3008 UINTN CurVarSize;
3009 CHAR16 VarName[10];
3010 UINTN Index;
3011 UINT32 VarAttr;
3012
3013 if (mUserProfileDb != NULL) {
3014 //
3015 // The user profiles had been already initialized.
3016 //
3017 return EFI_SUCCESS;
3018 }
3019
3020 //
3021 // Init user profile database structure.
3022 //
3023 if (!ExpandUsermUserProfileDb ()) {
3024 return EFI_OUT_OF_RESOURCES;
3025 }
3026
3027 CurVarSize = DEFAULT_PROFILE_SIZE;
3028 VarData = AllocateZeroPool (CurVarSize);
3029 if (VarData == NULL) {
3030 return EFI_OUT_OF_RESOURCES;
3031 }
3032
3033 //
3034 // Get all user proifle entries.
3035 //
3036 Index = 0;
3037 while (TRUE) {
3038 //
3039 // Get variable name.
3040 //
3041 UnicodeSPrint (
3042 VarName,
3043 sizeof (VarName),
3044 L"User%04x",
3045 Index
3046 );
3047 Index++;
3048
3049 //
3050 // Get variable value.
3051 //
3052 VarSize = CurVarSize;
3053 Status = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
3054 if (Status == EFI_BUFFER_TOO_SMALL) {
3055 FreePool (VarData);
3056 VarData = AllocatePool (VarSize);
3057 if (VarData == NULL) {
3058 Status = EFI_OUT_OF_RESOURCES;
3059 break;
3060 }
3061
3062 CurVarSize = VarSize;
3063 Status = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
3064 }
3065
3066 if (EFI_ERROR (Status)) {
3067 if (Status == EFI_NOT_FOUND) {
3068 Status = EFI_SUCCESS;
3069 }
3070 break;
3071 }
3072
3073 //
3074 // Check variable attributes.
3075 //
3076 if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
3077 Status = gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
3078 continue;
3079 }
3080
3081 //
3082 // Add user profile to the user profile database.
3083 //
3084 Status = AddUserProfile (NULL, VarSize, VarData, FALSE);
3085 if (EFI_ERROR (Status)) {
3086 if (Status == EFI_SECURITY_VIOLATION) {
3087 //
3088 // Delete invalid user profile
3089 //
3090 gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
3091 } else if (Status == EFI_OUT_OF_RESOURCES) {
3092 break;
3093 }
3094 } else {
3095 //
3096 // Delete and save the profile again if some invalid profiles are deleted.
3097 //
3098 if (mUserProfileDb->UserProfileNum < Index) {
3099 gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
3100 SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE);
3101 }
3102 }
3103 }
3104
3105 if (VarData != NULL) {
3106 FreePool (VarData);
3107 }
3108
3109 if (EFI_ERROR (Status)) {
3110 return Status;
3111 }
3112
3113 //
3114 // Check whether the user profile database is empty.
3115 //
3116 if (mUserProfileDb->UserProfileNum == 0) {
3117 Status = AddDefaultUserProfile ();
3118 }
3119
3120 return Status;
3121 }
3122
3123
3124 /**
3125 This function collects all the credential providers and saves to mProviderDb.
3126
3127 @retval EFI_SUCCESS Collect credential providers successfully.
3128 @retval Others Fail to collect credential providers.
3129
3130 **/
3131 EFI_STATUS
3132 InitProviderInfo (
3133 VOID
3134 )
3135 {
3136 EFI_STATUS Status;
3137 UINTN HandleCount;
3138 EFI_HANDLE *HandleBuf;
3139 UINTN Index;
3140
3141 if (mProviderDb != NULL) {
3142 //
3143 // The credential providers had been collected before.
3144 //
3145 return EFI_SUCCESS;
3146 }
3147
3148 //
3149 // Try to find all the user credential provider driver.
3150 //
3151 HandleCount = 0;
3152 HandleBuf = NULL;
3153 Status = gBS->LocateHandleBuffer (
3154 ByProtocol,
3155 &gEfiUserCredentialProtocolGuid,
3156 NULL,
3157 &HandleCount,
3158 &HandleBuf
3159 );
3160 if (EFI_ERROR (Status)) {
3161 return Status;
3162 }
3163
3164 //
3165 // Get provider infomation.
3166 //
3167 mProviderDb = AllocateZeroPool (
3168 sizeof (CREDENTIAL_PROVIDER_INFO) -
3169 sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) +
3170 HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *)
3171 );
3172 if (mProviderDb == NULL) {
3173 FreePool (HandleBuf);
3174 return EFI_OUT_OF_RESOURCES;
3175 }
3176
3177 mProviderDb->Count = HandleCount;
3178 for (Index = 0; Index < HandleCount; Index++) {
3179 Status = gBS->HandleProtocol (
3180 HandleBuf[Index],
3181 &gEfiUserCredentialProtocolGuid,
3182 (VOID **) &mProviderDb->Provider[Index]
3183 );
3184 if (EFI_ERROR (Status)) {
3185 FreePool (HandleBuf);
3186 FreePool (mProviderDb);
3187 mProviderDb = NULL;
3188 return Status;
3189 }
3190 }
3191
3192 FreePool (HandleBuf);
3193 return EFI_SUCCESS;
3194 }
3195
3196
3197 /**
3198 This function allows a caller to extract the current configuration for one
3199 or more named elements from the target driver.
3200
3201
3202 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3203 @param Request A null-terminated Unicode string in <ConfigRequest> format.
3204 @param Progress On return, points to a character in the Request string.
3205 Points to the string's null terminator if request was successful.
3206 Points to the most recent '&' before the first failing name/value
3207 pair (or the beginning of the string if the failure is in the
3208 first name/value pair) if the request was not successful.
3209 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
3210 has all values filled in for the names in the Request string.
3211 String to be allocated by the called function.
3212
3213 @retval EFI_SUCCESS The Results is filled with the requested values.
3214 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
3215 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
3216 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
3217
3218 **/
3219 EFI_STATUS
3220 EFIAPI
3221 FakeExtractConfig (
3222 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3223 IN CONST EFI_STRING Request,
3224 OUT EFI_STRING *Progress,
3225 OUT EFI_STRING *Results
3226 )
3227 {
3228 if (Progress == NULL || Results == NULL) {
3229 return EFI_INVALID_PARAMETER;
3230 }
3231 *Progress = Request;
3232 return EFI_NOT_FOUND;
3233 }
3234
3235 /**
3236 This function processes the results of changes in configuration.
3237
3238
3239 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
3240 @param Configuration A null-terminated Unicode string in <ConfigResp> format.
3241 @param Progress A pointer to a string filled in with the offset of the most
3242 recent '&' before the first failing name/value pair (or the
3243 beginning of the string if the failure is in the first
3244 name/value pair) or the terminating NULL if all was successful.
3245
3246 @retval EFI_SUCCESS The Results is processed successfully.
3247 @retval EFI_INVALID_PARAMETER Configuration is NULL.
3248 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
3249
3250 **/
3251 EFI_STATUS
3252 EFIAPI
3253 FakeRouteConfig (
3254 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,
3255 IN CONST EFI_STRING Configuration,
3256 OUT EFI_STRING *Progress
3257 )
3258 {
3259 if (Configuration == NULL || Progress == NULL) {
3260 return EFI_INVALID_PARAMETER;
3261 }
3262
3263 return EFI_NOT_FOUND;
3264 }
3265
3266
3267 /**
3268 This function initialize the data mainly used in form browser.
3269
3270 @retval EFI_SUCCESS Initialize form data successfully.
3271 @retval Others Fail to Initialize form data.
3272
3273 **/
3274 EFI_STATUS
3275 InitFormBrowser (
3276 VOID
3277 )
3278 {
3279 EFI_STATUS Status;
3280 USER_MANAGER_CALLBACK_INFO *CallbackInfo;
3281 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
3282 EFI_HII_STRING_PROTOCOL *HiiString;
3283 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;
3284
3285 //
3286 // Initialize driver private data.
3287 //
3288 CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO));
3289 if (CallbackInfo == NULL) {
3290 return EFI_OUT_OF_RESOURCES;
3291 }
3292
3293 CallbackInfo->Signature = USER_MANAGER_SIGNATURE;
3294 CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig;
3295 CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig;
3296 CallbackInfo->ConfigAccess.Callback = UserIdentifyManagerCallback;
3297
3298 //
3299 // Locate Hii Database protocol.
3300 //
3301 Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
3302 if (EFI_ERROR (Status)) {
3303 return Status;
3304 }
3305 CallbackInfo->HiiDatabase = HiiDatabase;
3306
3307 //
3308 // Locate HiiString protocol.
3309 //
3310 Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
3311 if (EFI_ERROR (Status)) {
3312 return Status;
3313 }
3314 CallbackInfo->HiiString = HiiString;
3315
3316 //
3317 // Locate Formbrowser2 protocol.
3318 //
3319 Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
3320 if (EFI_ERROR (Status)) {
3321 return Status;
3322 }
3323
3324 CallbackInfo->FormBrowser2 = FormBrowser2;
3325 CallbackInfo->DriverHandle = NULL;
3326
3327 //
3328 // Install Device Path Protocol and Config Access protocol to driver handle.
3329 //
3330 Status = gBS->InstallMultipleProtocolInterfaces (
3331 &CallbackInfo->DriverHandle,
3332 &gEfiDevicePathProtocolGuid,
3333 &mHiiVendorDevicePath,
3334 &gEfiHiiConfigAccessProtocolGuid,
3335 &CallbackInfo->ConfigAccess,
3336 NULL
3337 );
3338 ASSERT_EFI_ERROR (Status);
3339
3340 //
3341 // Publish HII data.
3342 //
3343 CallbackInfo->HiiHandle = HiiAddPackages (
3344 &gUserIdentifyManagerGuid,
3345 CallbackInfo->DriverHandle,
3346 UserIdentifyManagerStrings,
3347 UserIdentifyManagerVfrBin,
3348 NULL
3349 );
3350 if (CallbackInfo->HiiHandle == NULL) {
3351 return EFI_OUT_OF_RESOURCES;
3352 }
3353
3354 mCallbackInfo = CallbackInfo;
3355
3356 return EFI_SUCCESS;
3357 }
3358
3359
3360 /**
3361 Identify the user whose identification policy supports auto logon.
3362
3363 @param[in] ProviderIndex The provider index in the provider list.
3364 @param[out] User Points to user user profile if a user is identified successfully.
3365
3366 @retval EFI_SUCCESS Identify a user with the specified provider successfully.
3367 @retval Others Fail to identify a user.
3368
3369 **/
3370 EFI_STATUS
3371 IdentifyAutoLogonUser (
3372 IN UINTN ProviderIndex,
3373 OUT USER_PROFILE_ENTRY **User
3374 )
3375 {
3376 EFI_STATUS Status;
3377 EFI_USER_INFO *Info;
3378 UINT8 PolicyType;
3379
3380 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
3381 if (Info == NULL) {
3382 return EFI_OUT_OF_RESOURCES;
3383 }
3384
3385 Info->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD;
3386 Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
3387
3388 //
3389 // Identify the specified credential provider's auto logon user.
3390 //
3391 Status = mProviderDb->Provider[ProviderIndex]->User (
3392 mProviderDb->Provider[ProviderIndex],
3393 NULL,
3394 (EFI_USER_INFO_IDENTIFIER *) (Info + 1)
3395 );
3396 if (EFI_ERROR (Status)) {
3397 FreePool (Info);
3398 return Status;
3399 }
3400
3401 //
3402 // Find user with the specified user ID.
3403 //
3404 *User = NULL;
3405 Status = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize);
3406 FreePool (Info);
3407 if (EFI_ERROR (Status)) {
3408 return Status;
3409 }
3410
3411 Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType);
3412 if (PolicyType == EFI_USER_INFO_IDENTITY_AND) {
3413 //
3414 // The identified user need also identified by other credential provider.
3415 // This can handle through select user.
3416 //
3417 return EFI_NOT_READY;
3418 }
3419
3420 return Status;
3421 }
3422
3423
3424 /**
3425 Check whether the given console is ready.
3426
3427 @param[in] ProtocolGuid Points to the protocol guid of sonsole .
3428
3429 @retval TRUE The given console is ready.
3430 @retval FALSE The given console is not ready.
3431
3432 **/
3433 BOOLEAN
3434 CheckConsole (
3435 EFI_GUID *ProtocolGuid
3436 )
3437 {
3438 EFI_STATUS Status;
3439 UINTN HandleCount;