1 /** @file
2   This driver manages user information and produces user manager protocol.
3 
4 Copyright (c) 2009 - 2014, 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
FindUserProfile(IN OUT USER_PROFILE_ENTRY ** User,IN BOOLEAN NextUser,OUT UINTN * ProfileIndex OPTIONAL)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
FindUserInfo(IN USER_PROFILE_ENTRY * User,IN OUT EFI_USER_INFO ** Info,IN BOOLEAN NextInfo,OUT UINTN * Offset OPTIONAL)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
FindUserInfoByType(IN USER_PROFILE_ENTRY * User,IN OUT EFI_USER_INFO ** Info,IN UINT8 InfoType)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
FindUserProfileByInfo(IN OUT USER_PROFILE_ENTRY ** User,IN OUT EFI_USER_INFO ** UserInfo,OPTIONAL IN EFI_USER_INFO * Info,IN UINTN InfoSize)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 /**
405   Check whether the access policy is valid.
406 
407   @param[in]  PolicyInfo          Point to the access policy.
408   @param[in]  InfoLen             The policy length.
409 
410   @retval TRUE     The policy is a valid access policy.
411   @retval FALSE    The access policy is not a valid access policy.
412 
413 **/
414 BOOLEAN
CheckAccessPolicy(IN UINT8 * PolicyInfo,IN UINTN InfoLen)415 CheckAccessPolicy (
416   IN  UINT8                                     *PolicyInfo,
417   IN  UINTN                                     InfoLen
418   )
419 {
420   UINTN                         TotalLen;
421   UINTN                         ValueLen;
422   UINTN                         OffSet;
423   EFI_USER_INFO_ACCESS_CONTROL  Access;
424   EFI_DEVICE_PATH_PROTOCOL      *Path;
425   UINTN                         PathSize;
426 
427   TotalLen = 0;
428   while (TotalLen < InfoLen) {
429     //
430     // Check access policy according to type.
431     //
432     CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access));
433     ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL);
434     switch (Access.Type) {
435     case EFI_USER_INFO_ACCESS_FORBID_LOAD:
436     case EFI_USER_INFO_ACCESS_PERMIT_LOAD:
437     case EFI_USER_INFO_ACCESS_FORBID_CONNECT:
438     case EFI_USER_INFO_ACCESS_PERMIT_CONNECT:
439       OffSet = 0;
440       while (OffSet < ValueLen) {
441         Path      = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet);
442         PathSize  = GetDevicePathSize (Path);
443         OffSet += PathSize;
444       }
445       if (OffSet != ValueLen) {
446         return FALSE;
447       }
448       break;
449 
450     case EFI_USER_INFO_ACCESS_SETUP:
451       if (ValueLen % sizeof (EFI_GUID) != 0) {
452         return FALSE;
453       }
454       break;
455 
456     case EFI_USER_INFO_ACCESS_BOOT_ORDER:
457       if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) {
458         return FALSE;
459       }
460       break;
461 
462     case EFI_USER_INFO_ACCESS_ENROLL_SELF:
463     case EFI_USER_INFO_ACCESS_ENROLL_OTHERS:
464     case EFI_USER_INFO_ACCESS_MANAGE:
465       if (ValueLen != 0) {
466         return FALSE;
467       }
468       break;
469 
470     default:
471       return FALSE;
472       break;
473     }
474 
475     TotalLen += Access.Size;
476   }
477 
478   if (TotalLen != InfoLen) {
479     return FALSE;
480   }
481 
482   return TRUE;
483 }
484 
485 
486 /**
487   Check whether the identity policy is valid.
488 
489   @param[in]  PolicyInfo          Point to the identity policy.
490   @param[in]  InfoLen             The policy length.
491 
492   @retval TRUE     The policy is a valid identity policy.
493   @retval FALSE    The access policy is not a valid identity policy.
494 
495 **/
496 BOOLEAN
CheckIdentityPolicy(IN UINT8 * PolicyInfo,IN UINTN InfoLen)497 CheckIdentityPolicy (
498   IN  UINT8                                     *PolicyInfo,
499   IN  UINTN                                     InfoLen
500   )
501 {
502   UINTN                         TotalLen;
503   UINTN                         ValueLen;
504   EFI_USER_INFO_IDENTITY_POLICY *Identity;
505 
506   TotalLen  = 0;
507 
508   //
509   // Check each part of policy expression.
510   //
511   while (TotalLen < InfoLen) {
512     //
513     // Check access polisy according to type.
514     //
515     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen);
516     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
517     switch (Identity->Type) {
518     //
519     // Check False option.
520     //
521     case EFI_USER_INFO_IDENTITY_FALSE:
522       if (ValueLen != 0) {
523         return FALSE;
524       }
525       break;
526 
527     //
528     // Check True option.
529     //
530     case EFI_USER_INFO_IDENTITY_TRUE:
531       if (ValueLen != 0) {
532         return FALSE;
533       }
534       break;
535 
536     //
537     // Check negative operation.
538     //
539     case EFI_USER_INFO_IDENTITY_NOT:
540       if (ValueLen != 0) {
541         return FALSE;
542       }
543       break;
544 
545     //
546     // Check and operation.
547     //
548     case EFI_USER_INFO_IDENTITY_AND:
549       if (ValueLen != 0) {
550         return FALSE;
551       }
552       break;
553 
554     //
555     // Check or operation.
556     //
557     case EFI_USER_INFO_IDENTITY_OR:
558       if (ValueLen != 0) {
559         return FALSE;
560       }
561       break;
562 
563     //
564     // Check credential provider by type.
565     //
566     case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
567       if (ValueLen != sizeof (EFI_GUID)) {
568         return FALSE;
569       }
570       break;
571 
572     //
573     // Check credential provider by ID.
574     //
575     case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
576       if (ValueLen != sizeof (EFI_GUID)) {
577         return FALSE;
578       }
579       break;
580 
581     default:
582       return FALSE;
583       break;
584     }
585 
586     TotalLen += Identity->Length;
587   }
588 
589   if (TotalLen != InfoLen) {
590     return FALSE;
591   }
592 
593   return TRUE;
594 }
595 
596 
597 /**
598   Check whether the user information is a valid user information record.
599 
600   @param[in]  Info points to the user information.
601 
602   @retval TRUE     The info is a valid user information record.
603   @retval FALSE    The info is not a valid user information record.
604 
605 **/
606 BOOLEAN
CheckUserInfo(IN CONST EFI_USER_INFO * Info)607 CheckUserInfo (
608   IN CONST  EFI_USER_INFO                       *Info
609   )
610 {
611   UINTN       InfoLen;
612 
613   if (Info == NULL) {
614     return FALSE;
615   }
616   //
617   // Check user information according to information type.
618   //
619   InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO);
620   switch (Info->InfoType) {
621   case EFI_USER_INFO_EMPTY_RECORD:
622     if (InfoLen != 0) {
623       return FALSE;
624     }
625     break;
626 
627   case EFI_USER_INFO_NAME_RECORD:
628   case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD:
629   case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD:
630     break;
631 
632   case EFI_USER_INFO_CREATE_DATE_RECORD:
633   case EFI_USER_INFO_USAGE_DATE_RECORD:
634     if (InfoLen != sizeof (EFI_TIME)) {
635       return FALSE;
636     }
637     break;
638 
639   case EFI_USER_INFO_USAGE_COUNT_RECORD:
640     if (InfoLen != sizeof (UINT64)) {
641       return FALSE;
642     }
643     break;
644 
645   case EFI_USER_INFO_IDENTIFIER_RECORD:
646     if (InfoLen != 16) {
647       return FALSE;
648     }
649     break;
650 
651   case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD:
652   case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD:
653   case EFI_USER_INFO_GUID_RECORD:
654     if (InfoLen != sizeof (EFI_GUID)) {
655       return FALSE;
656     }
657     break;
658 
659   case EFI_USER_INFO_PKCS11_RECORD:
660   case EFI_USER_INFO_CBEFF_RECORD:
661     break;
662 
663   case EFI_USER_INFO_FAR_RECORD:
664   case EFI_USER_INFO_RETRY_RECORD:
665     if (InfoLen != 1) {
666       return FALSE;
667     }
668     break;
669 
670   case EFI_USER_INFO_ACCESS_POLICY_RECORD:
671     if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) {
672       return FALSE;
673     }
674     break;
675 
676   case EFI_USER_INFO_IDENTITY_POLICY_RECORD:
677     if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) {
678       return FALSE;
679     }
680     break;
681 
682   default:
683     return FALSE;
684     break;
685   }
686 
687   return TRUE;
688 }
689 
690 
691 /**
692   Check the user profile data format to be added.
693 
694   @param[in]  UserProfileInfo     Points to the user profile data.
695   @param[in]  UserProfileSize     The length of user profile data.
696 
697   @retval TRUE     It is a valid user profile.
698   @retval FALSE    It is not a valid user profile.
699 
700 **/
701 BOOLEAN
CheckProfileInfo(IN UINT8 * UserProfileInfo,IN UINTN UserProfileSize)702 CheckProfileInfo (
703   IN  UINT8                                     *UserProfileInfo,
704   IN  UINTN                                     UserProfileSize
705   )
706 {
707   UINTN         ChkLen;
708   EFI_USER_INFO *Info;
709 
710   if (UserProfileInfo == NULL) {
711     return FALSE;
712   }
713 
714   //
715   // Check user profile information length.
716   //
717   ChkLen = 0;
718   while (ChkLen < UserProfileSize) {
719     Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen);
720     //
721     // Check user information format.
722     //
723     if (!CheckUserInfo (Info)) {
724       return FALSE;
725     }
726 
727     ChkLen += ALIGN_VARIABLE (Info->InfoSize);
728   }
729 
730   if (ChkLen != UserProfileSize) {
731     return FALSE;
732   }
733 
734   return TRUE;
735 }
736 
737 
738 /**
739   Find the specified RightType in current user profile.
740 
741   @param[in]  RightType      Could be EFI_USER_INFO_ACCESS_MANAGE,
742                              EFI_USER_INFO_ACCESS_ENROLL_OTHERS or
743                              EFI_USER_INFO_ACCESS_ENROLL_SELF.
744 
745   @retval TRUE     Find the specified RightType in current user profile.
746   @retval FALSE    Can't find the right in the profile.
747 
748 **/
749 BOOLEAN
CheckCurrentUserAccessRight(IN UINT32 RightType)750 CheckCurrentUserAccessRight (
751   IN        UINT32                              RightType
752   )
753 {
754   EFI_STATUS                    Status;
755   EFI_USER_INFO                 *Info;
756   UINTN                         TotalLen;
757   UINTN                         CheckLen;
758   EFI_USER_INFO_ACCESS_CONTROL  Access;
759 
760   //
761   // Get user access right information.
762   //
763   Info = NULL;
764   Status = FindUserInfoByType (
765             (USER_PROFILE_ENTRY *) mCurrentUser,
766             &Info,
767             EFI_USER_INFO_ACCESS_POLICY_RECORD
768             );
769   if (EFI_ERROR (Status)) {
770     return FALSE;
771   }
772 
773   ASSERT (Info != NULL);
774   TotalLen  = Info->InfoSize - sizeof (EFI_USER_INFO);
775   CheckLen  = 0;
776   while (CheckLen < TotalLen) {
777     //
778     // Check right according to access type.
779     //
780     CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access));
781     if (Access.Type == RightType) {
782       return TRUE;;
783     }
784 
785     CheckLen += Access.Size;
786   }
787 
788   return FALSE;
789 }
790 
791 
792 /**
793   Create a unique user identifier.
794 
795   @param[out]  Identifier     This points to the identifier.
796 
797 **/
798 VOID
GenerateIdentifier(OUT UINT8 * Identifier)799 GenerateIdentifier (
800    OUT    UINT8                               *Identifier
801   )
802 {
803   EFI_TIME  Time;
804   UINT64    MonotonicCount;
805   UINT32    *MonotonicPointer;
806   UINTN     Index;
807 
808   //
809   // Create a unique user identifier.
810   //
811   gRT->GetTime (&Time, NULL);
812   CopyMem (Identifier, &Time, sizeof (EFI_TIME));
813   //
814   // Remove zeros.
815   //
816   for (Index = 0; Index < sizeof (EFI_TIME); Index++) {
817     if (Identifier[Index] == 0) {
818       Identifier[Index] = 0x5a;
819     }
820   }
821 
822   MonotonicPointer = (UINT32 *) Identifier;
823   gBS->GetNextMonotonicCount (&MonotonicCount);
824   MonotonicPointer[0] += (UINT32) MonotonicCount;
825   MonotonicPointer[1] += (UINT32) MonotonicCount;
826   MonotonicPointer[2] += (UINT32) MonotonicCount;
827   MonotonicPointer[3] += (UINT32) MonotonicCount;
828 }
829 
830 
831 /**
832   Generate unique user ID.
833 
834   @param[out]  UserId                 Points to the user identifer.
835 
836 **/
837 VOID
GenerateUserId(OUT UINT8 * UserId)838 GenerateUserId (
839   OUT    UINT8                               *UserId
840   )
841 {
842   EFI_STATUS              Status;
843   USER_PROFILE_ENTRY      *UserProfile;
844   EFI_USER_INFO           *UserInfo;
845   UINTN                   Index;
846 
847   //
848   // Generate unique user ID
849   //
850   while (TRUE) {
851     GenerateIdentifier (UserId);
852     //
853     // Check whether it's unique in user profile database.
854     //
855     if (mUserProfileDb == NULL) {
856       return ;
857     }
858 
859     for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
860       UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]);
861       UserInfo    = NULL;
862       Status      = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
863       if (EFI_ERROR (Status)) {
864         continue;
865       }
866 
867       if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
868         break;
869       }
870     }
871 
872     if (Index == mUserProfileDb->UserProfileNum) {
873       return ;
874     }
875   }
876 }
877 
878 
879 /**
880   Expand user profile database.
881 
882   @retval TRUE     Success to expand user profile database.
883   @retval FALSE    Fail to expand user profile database.
884 
885 **/
886 BOOLEAN
ExpandUsermUserProfileDb(VOID)887 ExpandUsermUserProfileDb (
888   VOID
889   )
890 {
891   UINTN               MaxNum;
892   USER_PROFILE_DB     *NewDataBase;
893 
894   //
895   // Create new user profile database.
896   //
897   if (mUserProfileDb == NULL) {
898     MaxNum = USER_NUMBER_INC;
899   } else {
900     MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC;
901   }
902 
903   NewDataBase = AllocateZeroPool (
904                   sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) +
905                   MaxNum * sizeof (EFI_USER_PROFILE_HANDLE)
906                   );
907   if (NewDataBase == NULL) {
908     return FALSE;
909   }
910 
911   NewDataBase->MaxProfileNum = MaxNum;
912 
913   //
914   // Copy old user profile database value
915   //
916   if (mUserProfileDb == NULL) {
917     NewDataBase->UserProfileNum = 0;
918   } else {
919     NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum;
920     CopyMem (
921       NewDataBase->UserProfile,
922       mUserProfileDb->UserProfile,
923       NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE)
924       );
925     FreePool (mUserProfileDb);
926   }
927 
928   mUserProfileDb = NewDataBase;
929   return TRUE;
930 }
931 
932 
933 /**
934   Expand user profile
935 
936   @param[in]  User                    Points to user profile.
937   @param[in]  ExpandSize              The size of user profile.
938 
939   @retval TRUE     Success to expand user profile size.
940   @retval FALSE    Fail to expand user profile size.
941 
942 **/
943 BOOLEAN
ExpandUserProfile(IN USER_PROFILE_ENTRY * User,IN UINTN ExpandSize)944 ExpandUserProfile (
945   IN USER_PROFILE_ENTRY                         *User,
946   IN UINTN                                      ExpandSize
947   )
948 {
949   UINT8 *Info;
950   UINTN InfoSizeInc;
951 
952   //
953   // Allocate new memory.
954   //
955   InfoSizeInc = 128;
956   User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc;
957   Info = AllocateZeroPool (User->MaxProfileSize);
958   if (Info == NULL) {
959     return FALSE;
960   }
961 
962   //
963   // Copy exist information.
964   //
965   if (User->UserProfileSize > 0) {
966     CopyMem (Info, User->ProfileInfo, User->UserProfileSize);
967     FreePool (User->ProfileInfo);
968   }
969 
970   User->ProfileInfo = Info;
971   return TRUE;
972 }
973 
974 
975 /**
976   Save the user profile to non-volatile memory, or delete it from non-volatile memory.
977 
978   @param[in]  User         Point to the user profile
979   @param[in]  Delete       If TRUE, delete the found user profile.
980                            If FALSE, save the user profile.
981   @retval EFI_SUCCESS      Save or delete user profile successfully.
982   @retval Others           Fail to change the profile.
983 
984 **/
985 EFI_STATUS
SaveNvUserProfile(IN USER_PROFILE_ENTRY * User,IN BOOLEAN Delete)986 SaveNvUserProfile (
987   IN  USER_PROFILE_ENTRY                        *User,
988   IN  BOOLEAN                                   Delete
989   )
990 {
991   EFI_STATUS  Status;
992 
993   //
994   // Check user profile entry.
995   //
996   Status = FindUserProfile (&User, FALSE, NULL);
997   if (EFI_ERROR (Status)) {
998     return Status;
999   }
1000 
1001   //
1002   // Save the user profile to non-volatile memory.
1003   //
1004   Status = gRT->SetVariable (
1005                   User->UserVarName,
1006                   &gUserIdentifyManagerGuid,
1007                   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1008                   Delete ? 0 : User->UserProfileSize,
1009                   User->ProfileInfo
1010                   );
1011   return Status;
1012 }
1013 
1014 /**
1015   Add one new user info into the user's profile.
1016 
1017   @param[in]   User        point to the user profile
1018   @param[in]   Info        Points to the user information payload.
1019   @param[in]   InfoSize    The size of the user information payload, in bytes.
1020   @param[out]  UserInfo    Point to the new info in user profile
1021   @param[in]   Save        If TRUE, save the profile to NV flash.
1022                            If FALSE, don't need to save the profile to NV flash.
1023 
1024   @retval EFI_SUCCESS      Add user info to user profile successfully.
1025   @retval Others           Fail to add user info to user profile.
1026 
1027 **/
1028 EFI_STATUS
AddUserInfo(IN USER_PROFILE_ENTRY * User,IN UINT8 * Info,IN UINTN InfoSize,OUT EFI_USER_INFO ** UserInfo,OPTIONAL IN BOOLEAN Save)1029 AddUserInfo (
1030   IN  USER_PROFILE_ENTRY                        *User,
1031   IN  UINT8                                     *Info,
1032   IN  UINTN                                     InfoSize,
1033   OUT EFI_USER_INFO                             **UserInfo, OPTIONAL
1034   IN  BOOLEAN                                   Save
1035   )
1036 {
1037   EFI_STATUS  Status;
1038 
1039   if ((Info == NULL) || (User == NULL)) {
1040     return EFI_INVALID_PARAMETER;
1041   }
1042 
1043   //
1044   // Check user profile handle.
1045   //
1046   Status = FindUserProfile (&User, FALSE, NULL);
1047   if (EFI_ERROR (Status)) {
1048     return Status;
1049   }
1050 
1051   //
1052   // Check user information memory size.
1053   //
1054   if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) {
1055     if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) {
1056       return EFI_OUT_OF_RESOURCES;
1057     }
1058   }
1059 
1060   //
1061   // Add new user information.
1062   //
1063   CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize);
1064   if (UserInfo != NULL) {
1065     *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize);
1066   }
1067   User->UserProfileSize += ALIGN_VARIABLE (InfoSize);
1068 
1069   //
1070   // Save user profile information.
1071   //
1072   if (Save) {
1073     Status = SaveNvUserProfile (User, FALSE);
1074   }
1075 
1076   return Status;
1077 }
1078 
1079 
1080 /**
1081   Get the user info from the specified user info handle.
1082 
1083   @param[in]      User            Point to the user profile.
1084   @param[in]      UserInfo        Point to the user information record to get.
1085   @param[out]     Info            On entry, points to a buffer of at least *InfoSize bytes.
1086                                   On exit, holds the user information.
1087   @param[in, out] InfoSize        On entry, points to the size of Info.
1088                                   On return, points to the size of the user information.
1089   @param[in]      ChkRight        If TRUE, check the user info attribute.
1090                                   If FALSE, don't check the user info attribute.
1091 
1092 
1093   @retval EFI_ACCESS_DENIED       The information cannot be accessed by the current user.
1094   @retval EFI_INVALID_PARAMETER   InfoSize is NULL or UserInfo is NULL.
1095   @retval EFI_BUFFER_TOO_SMALL    The number of bytes specified by *InfoSize is too small to hold the
1096                                   returned data. The actual size required is returned in *InfoSize.
1097   @retval EFI_SUCCESS             Information returned successfully.
1098 
1099 **/
1100 EFI_STATUS
GetUserInfo(IN USER_PROFILE_ENTRY * User,IN EFI_USER_INFO * UserInfo,OUT EFI_USER_INFO * Info,IN OUT UINTN * InfoSize,IN BOOLEAN ChkRight)1101 GetUserInfo (
1102   IN        USER_PROFILE_ENTRY                  *User,
1103   IN        EFI_USER_INFO                       *UserInfo,
1104   OUT       EFI_USER_INFO                       *Info,
1105   IN OUT    UINTN                               *InfoSize,
1106   IN        BOOLEAN                             ChkRight
1107   )
1108 {
1109   EFI_STATUS  Status;
1110 
1111   if ((InfoSize == NULL) || (UserInfo == NULL)) {
1112     return EFI_INVALID_PARAMETER;
1113   }
1114 
1115   if ((*InfoSize != 0) && (Info == NULL)) {
1116     return EFI_INVALID_PARAMETER;
1117   }
1118 
1119   //
1120   // Find the user information to get.
1121   //
1122   Status = FindUserInfo (User, &UserInfo, FALSE, NULL);
1123   if (EFI_ERROR (Status)) {
1124     return Status;
1125   }
1126 
1127   //
1128   // Check information attributes.
1129   //
1130   if (ChkRight) {
1131     switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) {
1132     case EFI_USER_INFO_PRIVATE:
1133     case EFI_USER_INFO_PROTECTED:
1134       if (User != mCurrentUser) {
1135         return EFI_ACCESS_DENIED;
1136       }
1137       break;
1138 
1139     case EFI_USER_INFO_PUBLIC:
1140       break;
1141 
1142     default:
1143       return EFI_INVALID_PARAMETER;
1144       break;
1145     }
1146   }
1147 
1148   //
1149   // Get user information.
1150   //
1151   if (UserInfo->InfoSize > *InfoSize) {
1152     *InfoSize = UserInfo->InfoSize;
1153     return EFI_BUFFER_TOO_SMALL;
1154   }
1155 
1156   *InfoSize = UserInfo->InfoSize;
1157   if (Info != NULL) {
1158     CopyMem (Info, UserInfo, *InfoSize);
1159   }
1160 
1161   return EFI_SUCCESS;
1162 }
1163 
1164 
1165 /**
1166   Delete the specified user information from user profile.
1167 
1168   @param[in]  User        Point to the user profile.
1169   @param[in]  Info        Point to the user information record to delete.
1170   @param[in]  Save        If TRUE, save the profile to NV flash.
1171                           If FALSE, don't need to save the profile to NV flash.
1172 
1173   @retval EFI_SUCCESS     Delete user info from user profile successfully.
1174   @retval Others          Fail to delete user info from user profile.
1175 
1176 **/
1177 EFI_STATUS
DelUserInfo(IN USER_PROFILE_ENTRY * User,IN EFI_USER_INFO * Info,IN BOOLEAN Save)1178 DelUserInfo (
1179   IN  USER_PROFILE_ENTRY                        *User,
1180   IN  EFI_USER_INFO                             *Info,
1181   IN  BOOLEAN                                   Save
1182   )
1183 {
1184   EFI_STATUS  Status;
1185   UINTN       Offset;
1186   UINTN       NextOffset;
1187 
1188   //
1189   // Check user information handle.
1190   //
1191   Status = FindUserInfo (User, &Info, FALSE, &Offset);
1192   if (EFI_ERROR (Status)) {
1193     return Status;
1194   }
1195 
1196   if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
1197     return EFI_ACCESS_DENIED;
1198   }
1199 
1200   //
1201   // Delete the specified user information.
1202   //
1203   NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize);
1204   User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize);
1205   if (Offset < User->UserProfileSize) {
1206     CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset);
1207   }
1208 
1209   if (Save) {
1210     Status = SaveNvUserProfile (User, FALSE);
1211   }
1212 
1213   return Status;
1214 }
1215 
1216 
1217 /**
1218   Add or update user information.
1219 
1220   @param[in]      User           Point to the user profile.
1221   @param[in, out] UserInfo       On entry, points to the user information to modify,
1222                                  or NULL to add a new UserInfo.
1223                                  On return, points to the modified user information.
1224   @param[in]      Info           Points to the new user information.
1225   @param[in]      InfoSize       The size of Info,in bytes.
1226 
1227   @retval EFI_INVALID_PARAMETER  UserInfo is NULL or Info is NULL.
1228   @retval EFI_ACCESS_DENIED      The record is exclusive.
1229   @retval EFI_SUCCESS            User information was successfully changed/added.
1230 
1231 **/
1232 EFI_STATUS
ModifyUserInfo(IN USER_PROFILE_ENTRY * User,IN OUT EFI_USER_INFO ** UserInfo,IN CONST EFI_USER_INFO * Info,IN UINTN InfoSize)1233 ModifyUserInfo (
1234   IN        USER_PROFILE_ENTRY                  *User,
1235   IN OUT    EFI_USER_INFO                       **UserInfo,
1236   IN CONST  EFI_USER_INFO                       *Info,
1237   IN        UINTN                               InfoSize
1238   )
1239 {
1240   EFI_STATUS    Status;
1241   UINTN         PayloadLen;
1242   EFI_USER_INFO *OldInfo;
1243 
1244   if ((UserInfo == NULL) || (Info == NULL)) {
1245     return EFI_INVALID_PARAMETER;
1246   }
1247 
1248   if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) {
1249     return EFI_INVALID_PARAMETER;
1250   }
1251 
1252   //
1253   // Check user information.
1254   //
1255   if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) {
1256     return EFI_ACCESS_DENIED;
1257   }
1258 
1259   if (!CheckUserInfo (Info)) {
1260     return EFI_INVALID_PARAMETER;
1261   }
1262 
1263 
1264   if (*UserInfo == NULL) {
1265     //
1266     // Add new user information.
1267     //
1268     OldInfo = NULL;
1269     do {
1270       Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
1271       if (EFI_ERROR (Status)) {
1272         break;
1273       }
1274       ASSERT (OldInfo != NULL);
1275 
1276       if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) ||
1277            ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) {
1278         //
1279         //  Same type can not co-exist for exclusive information.
1280         //
1281         return EFI_ACCESS_DENIED;
1282       }
1283 
1284       //
1285       // Check whether it exists in DB.
1286       //
1287       if (Info->InfoSize != OldInfo->InfoSize) {
1288         continue;
1289       }
1290 
1291       if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) {
1292         continue;
1293       }
1294 
1295       PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO);
1296       if (PayloadLen == 0) {
1297         continue;
1298       }
1299 
1300       if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) {
1301         continue;
1302       }
1303 
1304       //
1305       // Yes. The new info is as same as the one in profile.
1306       //
1307       return EFI_SUCCESS;
1308     } while (!EFI_ERROR (Status));
1309 
1310     Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
1311     return Status;
1312   }
1313 
1314   //
1315   // Modify existing user information.
1316   //
1317   OldInfo = *UserInfo;
1318   if (OldInfo->InfoType != Info->InfoType) {
1319     return EFI_INVALID_PARAMETER;
1320   }
1321 
1322   if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) &&
1323        (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) {
1324     //
1325     // Try to add exclusive attrib in new info.
1326     // Check whether there is another information with the same type in profile.
1327     //
1328     OldInfo = NULL;
1329     do {
1330       Status = FindUserInfoByType (User, &OldInfo, Info->InfoType);
1331       if (EFI_ERROR (Status)) {
1332         break;
1333       }
1334       if (OldInfo != *UserInfo) {
1335         //
1336         // There is another information with the same type in profile.
1337         // Therefore, can't modify existing user information to add exclusive attribute.
1338         //
1339         return EFI_ACCESS_DENIED;
1340       }
1341     } while (TRUE);
1342   }
1343 
1344   Status = DelUserInfo (User, *UserInfo, FALSE);
1345   if (EFI_ERROR (Status)) {
1346     return Status;
1347   }
1348 
1349   return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE);
1350 }
1351 
1352 
1353 /**
1354   Delete the user profile from non-volatile memory and database.
1355 
1356   @param[in]  User              Points to the user profile.
1357 
1358   @retval EFI_SUCCESS      Delete user from the user profile successfully.
1359   @retval Others           Fail to delete user from user profile
1360 
1361 **/
1362 EFI_STATUS
DelUserProfile(IN USER_PROFILE_ENTRY * User)1363 DelUserProfile (
1364   IN  USER_PROFILE_ENTRY                        *User
1365   )
1366 {
1367   EFI_STATUS          Status;
1368   UINTN               Index;
1369 
1370   //
1371   // Check whether it is in the user profile database.
1372   //
1373   Status = FindUserProfile (&User, FALSE, &Index);
1374   if (EFI_ERROR (Status)) {
1375     return EFI_INVALID_PARAMETER;
1376   }
1377 
1378   //
1379   // Check whether it is the current user.
1380   //
1381   if (User == mCurrentUser) {
1382     return EFI_ACCESS_DENIED;
1383   }
1384 
1385   //
1386   // Delete user profile from the non-volatile memory.
1387   //
1388   Status    = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE);
1389   if (EFI_ERROR (Status)) {
1390     return Status;
1391   }
1392   mUserProfileDb->UserProfileNum--;
1393 
1394   //
1395   // Modify user profile database.
1396   //
1397   if (Index != mUserProfileDb->UserProfileNum) {
1398     mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum];
1399     CopyMem (
1400       ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName,
1401       User->UserVarName,
1402       sizeof (User->UserVarName)
1403       );
1404     Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE);
1405     if (EFI_ERROR (Status)) {
1406       return Status;
1407     }
1408   }
1409   //
1410   // Delete user profile information.
1411   //
1412   if (User->ProfileInfo != NULL) {
1413     FreePool (User->ProfileInfo);
1414   }
1415 
1416   FreePool (User);
1417   return EFI_SUCCESS;
1418 }
1419 
1420 
1421 /**
1422   Add user profile to user profile database.
1423 
1424   @param[out]   UserProfile   Point to the newly added user profile.
1425   @param[in]    ProfileSize   The size of the user profile.
1426   @param[in]    ProfileInfo   Point to the user profie data.
1427   @param[in]    Save          If TRUE, save the new added profile to NV flash.
1428                               If FALSE, don't save the profile to NV flash.
1429 
1430   @retval EFI_SUCCESS         Add user profile to user profile database successfully.
1431   @retval Others              Fail to add user profile to user profile database.
1432 
1433 **/
1434 EFI_STATUS
AddUserProfile(OUT USER_PROFILE_ENTRY ** UserProfile,OPTIONAL IN UINTN ProfileSize,IN UINT8 * ProfileInfo,IN BOOLEAN Save)1435 AddUserProfile (
1436      OUT  USER_PROFILE_ENTRY                    **UserProfile, OPTIONAL
1437   IN      UINTN                                 ProfileSize,
1438   IN      UINT8                                 *ProfileInfo,
1439   IN      BOOLEAN                               Save
1440   )
1441 {
1442   EFI_STATUS              Status;
1443   USER_PROFILE_ENTRY      *User;
1444 
1445   //
1446   // Check the data format to be added.
1447   //
1448   if (!CheckProfileInfo (ProfileInfo, ProfileSize)) {
1449     return EFI_SECURITY_VIOLATION;
1450   }
1451 
1452   //
1453   // Create user profile entry.
1454   //
1455   User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY));
1456   if (User == NULL) {
1457     return EFI_OUT_OF_RESOURCES;
1458   }
1459   //
1460   // Add the entry to the user profile database.
1461   //
1462   if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) {
1463     if (!ExpandUsermUserProfileDb ()) {
1464       FreePool (User);
1465       return EFI_OUT_OF_RESOURCES;
1466     }
1467   }
1468 
1469   UnicodeSPrint (
1470     User->UserVarName,
1471     sizeof (User->UserVarName),
1472     L"User%04x",
1473     mUserProfileDb->UserProfileNum
1474     );
1475   User->UserProfileSize = 0;
1476   User->MaxProfileSize  = 0;
1477   User->ProfileInfo     = NULL;
1478   mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User;
1479   mUserProfileDb->UserProfileNum++;
1480 
1481   //
1482   // Add user profile information.
1483   //
1484   Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save);
1485   if (EFI_ERROR (Status)) {
1486     DelUserProfile (User);
1487     return Status;
1488   }
1489   //
1490   // Set new user profile handle.
1491   //
1492   if (UserProfile != NULL) {
1493     *UserProfile = User;
1494   }
1495 
1496   return EFI_SUCCESS;
1497 }
1498 
1499 
1500 /**
1501   This function creates a new user profile with only a new user identifier
1502   attached and returns its handle. The user profile is non-volatile, but the
1503   handle User can change across reboots.
1504 
1505   @param[out]  User               Handle of a new user profile.
1506 
1507   @retval EFI_SUCCESS             User profile was successfully created.
1508   @retval Others                  Fail to create user profile
1509 
1510 **/
1511 EFI_STATUS
CreateUserProfile(OUT USER_PROFILE_ENTRY ** User)1512 CreateUserProfile (
1513   OUT USER_PROFILE_ENTRY                        **User
1514   )
1515 {
1516   EFI_STATUS    Status;
1517   EFI_USER_INFO *UserInfo;
1518 
1519   if (User == NULL) {
1520     return EFI_INVALID_PARAMETER;
1521   }
1522   //
1523   // Generate user id information.
1524   //
1525   UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
1526   if (UserInfo == NULL) {
1527     return EFI_OUT_OF_RESOURCES;
1528   }
1529 
1530   UserInfo->InfoType    = EFI_USER_INFO_IDENTIFIER_RECORD;
1531   UserInfo->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
1532   UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1533   GenerateUserId ((UINT8 *) (UserInfo + 1));
1534 
1535   //
1536   // Add user profile to the user profile database.
1537   //
1538   Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE);
1539   FreePool (UserInfo);
1540   return Status;
1541 }
1542 
1543 
1544 /**
1545   Add a default user profile to user profile database.
1546 
1547   @retval EFI_SUCCESS             A default user profile is added successfully.
1548   @retval Others                  Fail to add a default user profile
1549 
1550 **/
1551 EFI_STATUS
AddDefaultUserProfile(VOID)1552 AddDefaultUserProfile (
1553   VOID
1554   )
1555 {
1556   EFI_STATUS                    Status;
1557   USER_PROFILE_ENTRY            *User;
1558   EFI_USER_INFO                 *Info;
1559   EFI_USER_INFO                 *NewInfo;
1560   EFI_USER_INFO_CREATE_DATE     CreateDate;
1561   EFI_USER_INFO_USAGE_COUNT     UsageCount;
1562   EFI_USER_INFO_ACCESS_CONTROL  *Access;
1563   EFI_USER_INFO_IDENTITY_POLICY *Policy;
1564 
1565   //
1566   // Create a user profile.
1567   //
1568   Status = CreateUserProfile (&User);
1569   if (EFI_ERROR (Status)) {
1570     return Status;
1571   }
1572 
1573   //
1574   // Allocate a buffer to add all default user information.
1575   //
1576   Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE);
1577   if (Info == NULL) {
1578     return EFI_OUT_OF_RESOURCES;
1579   }
1580 
1581   //
1582   // Add user name.
1583   //
1584   Info->InfoType    = EFI_USER_INFO_NAME_RECORD;
1585   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1586   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (mUserName);
1587   CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName));
1588   NewInfo = NULL;
1589   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1590   if (EFI_ERROR (Status)) {
1591     goto Done;
1592   }
1593 
1594   //
1595   // Add user profile create date record.
1596   //
1597   Info->InfoType    = EFI_USER_INFO_CREATE_DATE_RECORD;
1598   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1599   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
1600   Status            = gRT->GetTime (&CreateDate, NULL);
1601   if (EFI_ERROR (Status)) {
1602     goto Done;
1603   }
1604 
1605   CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE));
1606   NewInfo = NULL;
1607   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1608   if (EFI_ERROR (Status)) {
1609     goto Done;
1610   }
1611 
1612   //
1613   // Add user profile usage count record.
1614   //
1615   Info->InfoType    = EFI_USER_INFO_USAGE_COUNT_RECORD;
1616   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1617   Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
1618   UsageCount        = 0;
1619   CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
1620   NewInfo = NULL;
1621   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1622   if (EFI_ERROR (Status)) {
1623     goto Done;
1624   }
1625 
1626   //
1627   // Add user access right.
1628   //
1629   Info->InfoType    = EFI_USER_INFO_ACCESS_POLICY_RECORD;
1630   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1631   Access            = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1);
1632   Access->Type      = EFI_USER_INFO_ACCESS_MANAGE;
1633   Access->Size      = sizeof (EFI_USER_INFO_ACCESS_CONTROL);
1634   Info->InfoSize    = sizeof (EFI_USER_INFO) + Access->Size;
1635   NewInfo = NULL;
1636   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1637   if (EFI_ERROR (Status)) {
1638     goto Done;
1639   }
1640 
1641   //
1642   // Add user identity policy.
1643   //
1644   Info->InfoType    = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
1645   Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE;
1646   Policy            = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1);
1647   Policy->Type      = EFI_USER_INFO_IDENTITY_TRUE;
1648   Policy->Length    = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
1649   Info->InfoSize    = sizeof (EFI_USER_INFO) + Policy->Length;
1650   NewInfo = NULL;
1651   Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1652 
1653 Done:
1654   FreePool (Info);
1655   return Status;
1656 }
1657 
1658 
1659 /**
1660   Publish current user information into EFI System Configuration Table.
1661 
1662   By UEFI spec, the User Identity Manager will publish the current user profile
1663   into the EFI System Configuration Table. Currently, only the user identifier and user
1664   name are published.
1665 
1666   @retval EFI_SUCCESS      Current user information is published successfully.
1667   @retval Others           Fail to publish current user information
1668 
1669 **/
1670 EFI_STATUS
PublishUserTable(VOID)1671 PublishUserTable (
1672   VOID
1673   )
1674 {
1675   EFI_STATUS              Status;
1676   EFI_CONFIGURATION_TABLE *EfiConfigurationTable;
1677   EFI_USER_INFO_TABLE     *UserInfoTable;
1678   EFI_USER_INFO           *IdInfo;
1679   EFI_USER_INFO           *NameInfo;
1680 
1681   Status = EfiGetSystemConfigurationTable (
1682              &gEfiUserManagerProtocolGuid,
1683              (VOID **) &EfiConfigurationTable
1684              );
1685   if (!EFI_ERROR (Status)) {
1686     //
1687     // The table existed!
1688     //
1689     return EFI_SUCCESS;
1690   }
1691 
1692   //
1693   // Get user ID information.
1694   //
1695   IdInfo  = NULL;
1696   Status  = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD);
1697   if (EFI_ERROR (Status)) {
1698     return Status;
1699 
1700   }
1701   //
1702   // Get user name information.
1703   //
1704   NameInfo  = NULL;
1705   Status    = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD);
1706   if (EFI_ERROR (Status)) {
1707     return Status;
1708   }
1709 
1710   //
1711   // Allocate a buffer for user information table.
1712   //
1713   UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool (
1714                                             sizeof (EFI_USER_INFO_TABLE) +
1715                                             IdInfo->InfoSize +
1716                                             NameInfo->InfoSize
1717                                             );
1718   if (UserInfoTable == NULL) {
1719     Status = EFI_OUT_OF_RESOURCES;
1720     return Status;
1721   }
1722 
1723   UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE);
1724 
1725   //
1726   // Append the user information to the user info table
1727   //
1728   CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize);
1729   UserInfoTable->Size += IdInfo->InfoSize;
1730 
1731   CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize);
1732   UserInfoTable->Size += NameInfo->InfoSize;
1733 
1734   Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable);
1735   return Status;
1736 }
1737 
1738 
1739 /**
1740   Get the user's identity type.
1741 
1742   The identify manager only supports the identity policy in which the credential
1743   provider handles are connected by the operator 'AND' or 'OR'.
1744 
1745 
1746   @param[in]   User              Handle of a user profile.
1747   @param[out]  PolicyType        Point to the identity type.
1748 
1749   @retval EFI_SUCCESS            Get user's identity type successfully.
1750   @retval Others                 Fail to get user's identity type.
1751 
1752 **/
1753 EFI_STATUS
GetIdentifyType(IN EFI_USER_PROFILE_HANDLE User,OUT UINT8 * PolicyType)1754 GetIdentifyType (
1755   IN      EFI_USER_PROFILE_HANDLE               User,
1756      OUT  UINT8                                 *PolicyType
1757   )
1758 {
1759   EFI_STATUS                    Status;
1760   EFI_USER_INFO                 *IdentifyInfo;
1761   UINTN                         TotalLen;
1762   EFI_USER_INFO_IDENTITY_POLICY *Identity;
1763 
1764   //
1765   // Get user identify policy information.
1766   //
1767   IdentifyInfo  = NULL;
1768   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
1769   if (EFI_ERROR (Status)) {
1770     return Status;
1771   }
1772   ASSERT (IdentifyInfo != NULL);
1773 
1774   //
1775   // Search the user identify policy according to type.
1776   //
1777   TotalLen    = 0;
1778   *PolicyType = EFI_USER_INFO_IDENTITY_FALSE;
1779   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
1780     Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
1781     if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) {
1782       *PolicyType = EFI_USER_INFO_IDENTITY_AND;
1783       break;
1784     }
1785 
1786     if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) {
1787       *PolicyType = EFI_USER_INFO_IDENTITY_OR;
1788       break;
1789     }
1790     TotalLen += Identity->Length;
1791   }
1792   return EFI_SUCCESS;
1793 }
1794 
1795 
1796 /**
1797   Identify the User by the specfied provider.
1798 
1799   @param[in]  User                Handle of a user profile.
1800   @param[in]  Provider            Points to the identifier of credential provider.
1801 
1802   @retval EFI_INVALID_PARAMETER   Provider is NULL.
1803   @retval EFI_NOT_FOUND           Fail to identify the specified user.
1804   @retval EFI_SUCCESS             User is identified successfully.
1805 
1806 **/
1807 EFI_STATUS
IdentifyByProviderId(IN EFI_USER_PROFILE_HANDLE User,IN EFI_GUID * Provider)1808 IdentifyByProviderId (
1809   IN  EFI_USER_PROFILE_HANDLE                   User,
1810   IN  EFI_GUID                                  *Provider
1811   )
1812 {
1813   EFI_STATUS                    Status;
1814   EFI_USER_INFO_IDENTIFIER      UserId;
1815   UINTN                         Index;
1816   EFI_CREDENTIAL_LOGON_FLAGS    AutoLogon;
1817   EFI_HII_HANDLE                HiiHandle;
1818   EFI_GUID                      FormSetId;
1819   EFI_FORM_ID                   FormId;
1820   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
1821 
1822   if (Provider == NULL) {
1823     return EFI_INVALID_PARAMETER;
1824   }
1825 
1826   //
1827   // Check the user ID identified by the specified credential provider.
1828   //
1829   for (Index = 0; Index < mProviderDb->Count; Index++) {
1830     //
1831     // Check credential provider class.
1832     //
1833     UserCredential = mProviderDb->Provider[Index];
1834     if (CompareGuid (&UserCredential->Identifier, Provider)) {
1835       Status = UserCredential->Select (UserCredential, &AutoLogon);
1836       if (EFI_ERROR (Status)) {
1837         return Status;
1838       }
1839 
1840       if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) {
1841         //
1842         // Get credential provider form.
1843         //
1844         Status = UserCredential->Form (
1845                                    UserCredential,
1846                                    &HiiHandle,
1847                                    &FormSetId,
1848                                    &FormId
1849                                    );
1850         if (!EFI_ERROR (Status)) {
1851           //
1852           // Send form to get user input.
1853           //
1854           Status = mCallbackInfo->FormBrowser2->SendForm (
1855                                                   mCallbackInfo->FormBrowser2,
1856                                                   &HiiHandle,
1857                                                   1,
1858                                                   &FormSetId,
1859                                                   FormId,
1860                                                   NULL,
1861                                                   NULL
1862                                                   );
1863           if (EFI_ERROR (Status)) {
1864             return Status;
1865           }
1866         }
1867       }
1868 
1869       Status = UserCredential->User (UserCredential, User, &UserId);
1870       if (EFI_ERROR (Status)) {
1871         return Status;
1872       }
1873 
1874       Status = UserCredential->Deselect (UserCredential);
1875       if (EFI_ERROR (Status)) {
1876         return Status;
1877       }
1878 
1879       return EFI_SUCCESS;
1880     }
1881   }
1882 
1883   return EFI_NOT_FOUND;
1884 }
1885 
1886 
1887 /**
1888   Update user information when user is logon on successfully.
1889 
1890   @param[in]  User         Points to user profile.
1891 
1892   @retval EFI_SUCCESS      Update user information successfully.
1893   @retval Others           Fail to update user information.
1894 
1895 **/
1896 EFI_STATUS
UpdateUserInfo(IN USER_PROFILE_ENTRY * User)1897 UpdateUserInfo (
1898   IN  USER_PROFILE_ENTRY                        *User
1899   )
1900 {
1901   EFI_STATUS                Status;
1902   EFI_USER_INFO             *Info;
1903   EFI_USER_INFO             *NewInfo;
1904   EFI_USER_INFO_CREATE_DATE Date;
1905   EFI_USER_INFO_USAGE_COUNT UsageCount;
1906   UINTN                     InfoLen;
1907 
1908   //
1909   // Allocate a buffer to update user's date record and usage record.
1910   //
1911   InfoLen  = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT));
1912   Info     = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen);
1913   if (Info == NULL) {
1914     return EFI_OUT_OF_RESOURCES;
1915   }
1916 
1917   //
1918   // Check create date record.
1919   //
1920   NewInfo = NULL;
1921   Status  = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD);
1922   if (Status == EFI_NOT_FOUND) {
1923     Info->InfoType    = EFI_USER_INFO_CREATE_DATE_RECORD;
1924     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1925     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE);
1926     Status            = gRT->GetTime (&Date, NULL);
1927     if (EFI_ERROR (Status)) {
1928       FreePool (Info);
1929       return Status;
1930     }
1931 
1932     CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE));
1933     NewInfo = NULL;
1934     Status  = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1935     if (EFI_ERROR (Status)) {
1936       FreePool (Info);
1937       return Status;
1938     }
1939   }
1940 
1941   //
1942   // Update usage date record.
1943   //
1944   NewInfo = NULL;
1945   Status  = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD);
1946   if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
1947     Info->InfoType    = EFI_USER_INFO_USAGE_DATE_RECORD;
1948     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1949     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE);
1950     Status            = gRT->GetTime (&Date, NULL);
1951     if (EFI_ERROR (Status)) {
1952       FreePool (Info);
1953       return Status;
1954     }
1955 
1956     CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE));
1957     Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1958     if (EFI_ERROR (Status)) {
1959       FreePool (Info);
1960       return Status;
1961     }
1962   }
1963 
1964   //
1965   // Update usage count record.
1966   //
1967   UsageCount  = 0;
1968   NewInfo     = NULL;
1969   Status      = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD);
1970   //
1971   // Get usage count.
1972   //
1973   if (Status == EFI_SUCCESS) {
1974     CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT));
1975   }
1976 
1977   UsageCount++;
1978   if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) {
1979     Info->InfoType    = EFI_USER_INFO_USAGE_COUNT_RECORD;
1980     Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
1981     Info->InfoSize    = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT);
1982     CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT));
1983     Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize);
1984     if (EFI_ERROR (Status)) {
1985       FreePool (Info);
1986       return Status;
1987     }
1988   }
1989 
1990   FreePool (Info);
1991   return EFI_SUCCESS;
1992 }
1993 
1994 
1995 /**
1996   Add a credenetial provider item in form.
1997 
1998   @param[in]  ProviderGuid        Points to the identifir of credential provider.
1999   @param[in]  OpCodeHandle        Points to container for dynamic created opcodes.
2000 
2001 **/
2002 VOID
AddProviderSelection(IN EFI_GUID * ProviderGuid,IN VOID * OpCodeHandle)2003 AddProviderSelection (
2004   IN     EFI_GUID                               *ProviderGuid,
2005   IN     VOID                                   *OpCodeHandle
2006   )
2007 {
2008   EFI_HII_HANDLE                HiiHandle;
2009   EFI_STRING_ID                 ProvID;
2010   CHAR16                        *ProvStr;
2011   UINTN                         Index;
2012   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
2013 
2014   for (Index = 0; Index < mProviderDb->Count; Index++) {
2015     UserCredential = mProviderDb->Provider[Index];
2016     if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) {
2017       //
2018       // Add credential provider selection.
2019       //
2020       UserCredential->Title (UserCredential, &HiiHandle, &ProvID);
2021       ProvStr = HiiGetString (HiiHandle, ProvID, NULL);
2022       if (ProvStr == NULL) {
2023         continue ;
2024       }
2025       ProvID  = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL);
2026       FreePool (ProvStr);
2027       HiiCreateActionOpCode (
2028         OpCodeHandle,                          // Container for dynamic created opcodes
2029         (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index),  // Question ID
2030         ProvID,                                // Prompt text
2031         STRING_TOKEN (STR_NULL_STRING),        // Help text
2032         EFI_IFR_FLAG_CALLBACK,                 // Question flag
2033         0                                      // Action String ID
2034         );
2035       break;
2036     }
2037   }
2038 }
2039 
2040 
2041 /**
2042   Add a username item in form.
2043 
2044   @param[in]  Index            The index of the user in the user name list.
2045   @param[in]  User             Points to the user profile whose username is added.
2046   @param[in]  OpCodeHandle     Points to container for dynamic created opcodes.
2047 
2048   @retval EFI_SUCCESS          Add a username successfully.
2049   @retval Others               Fail to add a username.
2050 
2051 **/
2052 EFI_STATUS
AddUserSelection(IN UINT16 Index,IN USER_PROFILE_ENTRY * User,IN VOID * OpCodeHandle)2053 AddUserSelection (
2054   IN     UINT16                                 Index,
2055   IN     USER_PROFILE_ENTRY                     *User,
2056   IN     VOID                                   *OpCodeHandle
2057   )
2058 {
2059   EFI_STRING_ID UserName;
2060   EFI_STATUS    Status;
2061   EFI_USER_INFO *UserInfo;
2062 
2063   UserInfo  = NULL;
2064   Status    = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD);
2065   if (EFI_ERROR (Status)) {
2066     return Status;
2067   }
2068 
2069   //
2070   // Add user name selection.
2071   //
2072   UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL);
2073   if (UserName == 0) {
2074     return EFI_OUT_OF_RESOURCES;
2075   }
2076 
2077   HiiCreateGotoOpCode (
2078     OpCodeHandle,                   // Container for dynamic created opcodes
2079     FORMID_PROVIDER_FORM,           // Target Form ID
2080     UserName,                       // Prompt text
2081     STRING_TOKEN (STR_NULL_STRING), // Help text
2082     EFI_IFR_FLAG_CALLBACK,          // Question flag
2083     (UINT16) Index                  // Question ID
2084     );
2085 
2086   return EFI_SUCCESS;
2087 }
2088 
2089 
2090 /**
2091   Identify the user whose identity policy does not contain the operator 'OR'.
2092 
2093   @param[in]  User             Points to the user profile.
2094 
2095   @retval EFI_SUCCESS          The specified user is identified successfully.
2096   @retval Others               Fail to identify the user.
2097 
2098 **/
2099 EFI_STATUS
IdentifyAndTypeUser(IN USER_PROFILE_ENTRY * User)2100 IdentifyAndTypeUser (
2101   IN  USER_PROFILE_ENTRY                        *User
2102   )
2103 {
2104   EFI_STATUS                    Status;
2105   EFI_USER_INFO                 *IdentifyInfo;
2106   BOOLEAN                       Success;
2107   UINTN                         TotalLen;
2108   UINTN                         ValueLen;
2109   EFI_USER_INFO_IDENTITY_POLICY *Identity;
2110 
2111   //
2112   // Get user identify policy information.
2113   //
2114   IdentifyInfo  = NULL;
2115   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2116   if (EFI_ERROR (Status)) {
2117     return Status;
2118   }
2119   ASSERT (IdentifyInfo != NULL);
2120 
2121   //
2122   // Check each part of identification policy expression.
2123   //
2124   Success   = FALSE;
2125   TotalLen  = 0;
2126   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2127     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2128     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2129     switch (Identity->Type) {
2130 
2131     case EFI_USER_INFO_IDENTITY_FALSE:
2132       //
2133       // Check False option.
2134       //
2135       Success = FALSE;
2136       break;
2137 
2138     case EFI_USER_INFO_IDENTITY_TRUE:
2139       //
2140       // Check True option.
2141       //
2142       Success = TRUE;
2143       break;
2144 
2145     case EFI_USER_INFO_IDENTITY_NOT:
2146       //
2147       // Check negative operation.
2148       //
2149       break;
2150 
2151     case EFI_USER_INFO_IDENTITY_AND:
2152       //
2153       // Check and operation.
2154       //
2155       if (!Success) {
2156         return EFI_NOT_READY;
2157       }
2158 
2159       Success = FALSE;
2160       break;
2161 
2162     case EFI_USER_INFO_IDENTITY_OR:
2163       //
2164       // Check or operation.
2165       //
2166       if (Success) {
2167         return EFI_SUCCESS;
2168       }
2169       break;
2170 
2171     case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE:
2172       //
2173       // Check credential provider by type.
2174       //
2175       break;
2176 
2177     case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
2178       //
2179       // Check credential provider by ID.
2180       //
2181       if (ValueLen != sizeof (EFI_GUID)) {
2182         return EFI_INVALID_PARAMETER;
2183       }
2184 
2185       Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1));
2186       if (EFI_ERROR (Status)) {
2187         return Status;
2188       }
2189 
2190       Success = TRUE;
2191       break;
2192 
2193     default:
2194       return EFI_INVALID_PARAMETER;
2195       break;
2196     }
2197 
2198     TotalLen += Identity->Length;
2199   }
2200 
2201   if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2202     return EFI_INVALID_PARAMETER;
2203   }
2204 
2205   if (!Success) {
2206     return EFI_NOT_READY;
2207   }
2208 
2209   return EFI_SUCCESS;
2210 }
2211 
2212 
2213 /**
2214   Identify the user whose identity policy does not contain the operator 'AND'.
2215 
2216   @param[in]  User             Points to the user profile.
2217 
2218   @retval EFI_SUCCESS          The specified user is identified successfully.
2219   @retval Others               Fail to identify the user.
2220 
2221 **/
2222 EFI_STATUS
IdentifyOrTypeUser(IN USER_PROFILE_ENTRY * User)2223 IdentifyOrTypeUser (
2224   IN  USER_PROFILE_ENTRY                        *User
2225   )
2226 {
2227   EFI_STATUS                    Status;
2228   EFI_USER_INFO                 *IdentifyInfo;
2229   UINTN                         TotalLen;
2230   UINTN                         ValueLen;
2231   EFI_USER_INFO_IDENTITY_POLICY *Identity;
2232   VOID                          *StartOpCodeHandle;
2233   VOID                          *EndOpCodeHandle;
2234   EFI_IFR_GUID_LABEL            *StartLabel;
2235   EFI_IFR_GUID_LABEL            *EndLabel;
2236 
2237   //
2238   // Get user identify policy information.
2239   //
2240   IdentifyInfo  = NULL;
2241   Status        = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
2242   if (EFI_ERROR (Status)) {
2243     return Status;
2244   }
2245   ASSERT (IdentifyInfo != NULL);
2246 
2247   //
2248   // Initialize the container for dynamic opcodes.
2249   //
2250   StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2251   ASSERT (StartOpCodeHandle != NULL);
2252 
2253   EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2254   ASSERT (EndOpCodeHandle != NULL);
2255 
2256   //
2257   // Create Hii Extend Label OpCode.
2258   //
2259   StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2260                                         StartOpCodeHandle,
2261                                         &gEfiIfrTianoGuid,
2262                                         NULL,
2263                                         sizeof (EFI_IFR_GUID_LABEL)
2264                                         );
2265   StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
2266   StartLabel->Number        = LABEL_PROVIDER_NAME;
2267 
2268   EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2269                                       EndOpCodeHandle,
2270                                       &gEfiIfrTianoGuid,
2271                                       NULL,
2272                                       sizeof (EFI_IFR_GUID_LABEL)
2273                                       );
2274   EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
2275   EndLabel->Number        = LABEL_END;
2276 
2277   //
2278   // Add the providers that exists in the user's policy.
2279   //
2280   TotalLen = 0;
2281   while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) {
2282     Identity  = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen);
2283     ValueLen  = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY);
2284     if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
2285       AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle);
2286     }
2287 
2288     TotalLen += Identity->Length;
2289   }
2290 
2291   HiiUpdateForm (
2292     mCallbackInfo->HiiHandle, // HII handle
2293     &gUserIdentifyManagerGuid,// Formset GUID
2294     FORMID_PROVIDER_FORM,     // Form ID
2295     StartOpCodeHandle,        // Label for where to insert opcodes
2296     EndOpCodeHandle           // Replace data
2297     );
2298 
2299   HiiFreeOpCodeHandle (StartOpCodeHandle);
2300   HiiFreeOpCodeHandle (EndOpCodeHandle);
2301 
2302   return EFI_SUCCESS;
2303 }
2304 
2305 
2306 /**
2307   This function processes the results of changes in configuration.
2308 
2309   @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2310   @param  Action                 Specifies the type of action taken by the browser.
2311   @param  QuestionId             A unique value which is sent to the original
2312                                  exporting driver so that it can identify the type
2313                                  of data to expect.
2314   @param  Type                   The type of value for the question.
2315   @param  Value                  A pointer to the data being sent to the original
2316                                  exporting driver.
2317   @param  ActionRequest          On return, points to the action requested by the
2318                                  callback function.
2319 
2320   @retval EFI_SUCCESS            The callback successfully handled the action.
2321   @retval Others                 Fail to handle the action.
2322 
2323 **/
2324 EFI_STATUS
2325 EFIAPI
UserIdentifyManagerCallback(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN EFI_BROWSER_ACTION Action,IN EFI_QUESTION_ID QuestionId,IN UINT8 Type,IN EFI_IFR_TYPE_VALUE * Value,OUT EFI_BROWSER_ACTION_REQUEST * ActionRequest)2326 UserIdentifyManagerCallback (
2327   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL      *This,
2328   IN  EFI_BROWSER_ACTION                        Action,
2329   IN  EFI_QUESTION_ID                           QuestionId,
2330   IN  UINT8                                     Type,
2331   IN  EFI_IFR_TYPE_VALUE                        *Value,
2332   OUT EFI_BROWSER_ACTION_REQUEST                *ActionRequest
2333   )
2334 {
2335   EFI_STATUS              Status;
2336   USER_PROFILE_ENTRY      *User;
2337   UINT8                   PolicyType;
2338   UINT16                  Index;
2339   VOID                    *StartOpCodeHandle;
2340   VOID                    *EndOpCodeHandle;
2341   EFI_IFR_GUID_LABEL      *StartLabel;
2342   EFI_IFR_GUID_LABEL      *EndLabel;
2343 
2344   Status = EFI_SUCCESS;
2345 
2346   switch (Action) {
2347   case EFI_BROWSER_ACTION_FORM_OPEN:
2348     {
2349       //
2350       // Update user Form when user Form is opened.
2351       // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form.
2352       //
2353       if (QuestionId != FORM_OPEN_QUESTION_ID) {
2354         return EFI_SUCCESS;
2355       }
2356 
2357       //
2358       // Initialize the container for dynamic opcodes.
2359       //
2360       StartOpCodeHandle = HiiAllocateOpCodeHandle ();
2361       ASSERT (StartOpCodeHandle != NULL);
2362 
2363       EndOpCodeHandle = HiiAllocateOpCodeHandle ();
2364       ASSERT (EndOpCodeHandle != NULL);
2365 
2366       //
2367       // Create Hii Extend Label OpCode.
2368       //
2369       StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2370                                             StartOpCodeHandle,
2371                                             &gEfiIfrTianoGuid,
2372                                             NULL,
2373                                             sizeof (EFI_IFR_GUID_LABEL)
2374                                             );
2375       StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
2376       StartLabel->Number        = LABEL_USER_NAME;
2377 
2378       EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
2379                                           EndOpCodeHandle,
2380                                           &gEfiIfrTianoGuid,
2381                                           NULL,
2382                                           sizeof (EFI_IFR_GUID_LABEL)
2383                                           );
2384       EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
2385       EndLabel->Number        = LABEL_END;
2386 
2387       //
2388       // Add all the user profile in the user profile database.
2389       //
2390       for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) {
2391         User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index];
2392         AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle);
2393       }
2394 
2395       HiiUpdateForm (
2396         mCallbackInfo->HiiHandle, // HII handle
2397         &gUserIdentifyManagerGuid,// Formset GUID
2398         FORMID_USER_FORM,         // Form ID
2399         StartOpCodeHandle,        // Label for where to insert opcodes
2400         EndOpCodeHandle           // Replace data
2401         );
2402 
2403       HiiFreeOpCodeHandle (StartOpCodeHandle);
2404       HiiFreeOpCodeHandle (EndOpCodeHandle);
2405 
2406       return EFI_SUCCESS;
2407     }
2408     break;
2409 
2410   case EFI_BROWSER_ACTION_FORM_CLOSE:
2411     Status = EFI_SUCCESS;
2412     break;
2413 
2414   case EFI_BROWSER_ACTION_CHANGED:
2415     if (QuestionId >= LABEL_PROVIDER_NAME) {
2416       //
2417       // QuestionId comes from the second Form (Select a Credential Provider if identity
2418       // policy is OR type). Identify the user by the selected provider.
2419       //
2420       Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier);
2421       if (Status == EFI_SUCCESS) {
2422         mIdentified     = TRUE;
2423         *ActionRequest  = EFI_BROWSER_ACTION_REQUEST_EXIT;
2424       }
2425       return EFI_SUCCESS;
2426     }
2427     break;
2428 
2429   case EFI_BROWSER_ACTION_CHANGING:
2430     //
2431     // QuestionId comes from the first Form (Select a user to identify).
2432     //
2433     if (QuestionId >= LABEL_PROVIDER_NAME) {
2434       return EFI_SUCCESS;
2435     }
2436 
2437     User   = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF];
2438     Status = GetIdentifyType (User, &PolicyType);
2439     if (EFI_ERROR (Status)) {
2440       return Status;
2441     }
2442 
2443     if (PolicyType == EFI_USER_INFO_IDENTITY_OR) {
2444       //
2445       // Identify the user by "OR" logical.
2446       //
2447       Status = IdentifyOrTypeUser (User);
2448       if (EFI_ERROR (Status)) {
2449         return Status;
2450       }
2451 
2452       mCurrentUser = (EFI_USER_PROFILE_HANDLE) User;
2453     } else {
2454       //
2455       // Identify the user by "AND" logical.
2456       //
2457       Status = IdentifyAndTypeUser (User);
2458       if (EFI_ERROR (Status)) {
2459         return Status;
2460       }
2461 
2462       mCurrentUser    = (EFI_USER_PROFILE_HANDLE) User;
2463       mIdentified     = TRUE;
2464       if (Type == EFI_IFR_TYPE_REF) {
2465         Value->ref.FormId = FORMID_INVALID_FORM;
2466       }
2467     }
2468   break;
2469 
2470   default:
2471     //
2472     // All other action return unsupported.
2473     //
2474     Status = EFI_UNSUPPORTED;
2475     break;
2476   }
2477 
2478 
2479   return Status;
2480 }
2481 
2482 
2483 /**
2484   This function construct user profile database from user data saved in the Flash.
2485   If no user is found in Flash, add one default user "administrator" in the user
2486   profile database.
2487 
2488   @retval EFI_SUCCESS            Init user profile database successfully.
2489   @retval Others                 Fail to init user profile database.
2490 
2491 **/
2492 EFI_STATUS
InitUserProfileDb(VOID)2493 InitUserProfileDb (
2494   VOID
2495   )
2496 {
2497   EFI_STATUS  Status;
2498   UINT8       *VarData;
2499   UINTN       VarSize;
2500   UINTN       CurVarSize;
2501   CHAR16      VarName[10];
2502   UINTN       Index;
2503   UINT32      VarAttr;
2504 
2505   if (mUserProfileDb != NULL) {
2506     //
2507     // The user profiles had been already initialized.
2508     //
2509     return EFI_SUCCESS;
2510   }
2511 
2512   //
2513   // Init user profile database structure.
2514   //
2515   if (!ExpandUsermUserProfileDb ()) {
2516     return EFI_OUT_OF_RESOURCES;
2517   }
2518 
2519   CurVarSize = DEFAULT_PROFILE_SIZE;
2520   VarData    = AllocateZeroPool (CurVarSize);
2521   if (VarData == NULL) {
2522     return EFI_OUT_OF_RESOURCES;
2523   }
2524 
2525   //
2526   // Get all user proifle entries.
2527   //
2528   Index = 0;
2529   while (TRUE) {
2530     //
2531     // Get variable name.
2532     //
2533     UnicodeSPrint (
2534       VarName,
2535       sizeof (VarName),
2536       L"User%04x",
2537       Index
2538       );
2539     Index++;
2540 
2541     //
2542     // Get variable value.
2543     //
2544     VarSize = CurVarSize;
2545     Status  = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
2546     if (Status == EFI_BUFFER_TOO_SMALL) {
2547       FreePool (VarData);
2548       VarData = AllocatePool (VarSize);
2549       if (VarData == NULL) {
2550         Status = EFI_OUT_OF_RESOURCES;
2551         break;
2552       }
2553 
2554       CurVarSize  = VarSize;
2555       Status      = gRT->GetVariable (VarName, &gUserIdentifyManagerGuid, &VarAttr, &VarSize, VarData);
2556     }
2557 
2558     if (EFI_ERROR (Status)) {
2559       if (Status == EFI_NOT_FOUND) {
2560         Status = EFI_SUCCESS;
2561       }
2562       break;
2563     }
2564 
2565     //
2566     // Check variable attributes.
2567     //
2568     if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) {
2569       Status = gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
2570       continue;
2571     }
2572 
2573     //
2574     // Add user profile to the user profile database.
2575     //
2576     Status = AddUserProfile (NULL, VarSize, VarData, FALSE);
2577     if (EFI_ERROR (Status)) {
2578       if (Status == EFI_SECURITY_VIOLATION) {
2579         //
2580         // Delete invalid user profile
2581         //
2582         gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
2583       } else if (Status == EFI_OUT_OF_RESOURCES) {
2584         break;
2585       }
2586     } else {
2587       //
2588       // Delete and save the profile again if some invalid profiles are deleted.
2589       //
2590       if (mUserProfileDb->UserProfileNum < Index) {
2591         gRT->SetVariable (VarName, &gUserIdentifyManagerGuid, VarAttr, 0, NULL);
2592         SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE);
2593       }
2594     }
2595   }
2596 
2597   if (VarData != NULL) {
2598     FreePool (VarData);
2599   }
2600 
2601   if (EFI_ERROR (Status)) {
2602     return Status;
2603   }
2604 
2605   //
2606   // Check whether the user profile database is empty.
2607   //
2608   if (mUserProfileDb->UserProfileNum == 0) {
2609     Status = AddDefaultUserProfile ();
2610   }
2611 
2612   return Status;
2613 }
2614 
2615 
2616 /**
2617   This function collects all the credential providers and saves to mProviderDb.
2618 
2619   @retval EFI_SUCCESS            Collect credential providers successfully.
2620   @retval Others                 Fail to collect credential providers.
2621 
2622 **/
2623 EFI_STATUS
InitProviderInfo(VOID)2624 InitProviderInfo (
2625   VOID
2626   )
2627 {
2628   EFI_STATUS  Status;
2629   UINTN       HandleCount;
2630   EFI_HANDLE  *HandleBuf;
2631   UINTN       Index;
2632 
2633   if (mProviderDb != NULL) {
2634     //
2635     // The credential providers had been collected before.
2636     //
2637     return EFI_SUCCESS;
2638   }
2639 
2640   //
2641   // Try to find all the user credential provider driver.
2642   //
2643   HandleCount = 0;
2644   HandleBuf   = NULL;
2645   Status = gBS->LocateHandleBuffer (
2646                   ByProtocol,
2647                   &gEfiUserCredential2ProtocolGuid,
2648                   NULL,
2649                   &HandleCount,
2650                   &HandleBuf
2651                   );
2652   if (EFI_ERROR (Status)) {
2653     return Status;
2654   }
2655 
2656   //
2657   // Get provider infomation.
2658   //
2659   mProviderDb = AllocateZeroPool (
2660                   sizeof (CREDENTIAL_PROVIDER_INFO) -
2661                   sizeof (EFI_USER_CREDENTIAL2_PROTOCOL *) +
2662                   HandleCount * sizeof (EFI_USER_CREDENTIAL2_PROTOCOL *)
2663                   );
2664   if (mProviderDb == NULL) {
2665     FreePool (HandleBuf);
2666     return EFI_OUT_OF_RESOURCES;
2667   }
2668 
2669  mProviderDb->Count = HandleCount;
2670   for (Index = 0; Index < HandleCount; Index++) {
2671     Status = gBS->HandleProtocol (
2672                     HandleBuf[Index],
2673                     &gEfiUserCredential2ProtocolGuid,
2674                     (VOID **) &mProviderDb->Provider[Index]
2675                     );
2676     if (EFI_ERROR (Status)) {
2677       FreePool (HandleBuf);
2678       FreePool (mProviderDb);
2679       mProviderDb = NULL;
2680       return Status;
2681     }
2682   }
2683 
2684   FreePool (HandleBuf);
2685   return EFI_SUCCESS;
2686 }
2687 
2688 
2689 /**
2690   This function allows a caller to extract the current configuration for one
2691   or more named elements from the target driver.
2692 
2693 
2694   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2695   @param Request         A null-terminated Unicode string in <ConfigRequest> format.
2696   @param Progress        On return, points to a character in the Request string.
2697                          Points to the string's null terminator if request was successful.
2698                          Points to the most recent '&' before the first failing name/value
2699                          pair (or the beginning of the string if the failure is in the
2700                          first name/value pair) if the request was not successful.
2701   @param Results         A null-terminated Unicode string in <ConfigAltResp> format which
2702                          has all values filled in for the names in the Request string.
2703                          String to be allocated by the called function.
2704 
2705   @retval  EFI_SUCCESS            The Results is filled with the requested values.
2706   @retval  EFI_OUT_OF_RESOURCES   Not enough memory to store the results.
2707   @retval  EFI_INVALID_PARAMETER  Request is illegal syntax, or unknown name.
2708   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
2709 
2710 **/
2711 EFI_STATUS
2712 EFIAPI
FakeExtractConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Request,OUT EFI_STRING * Progress,OUT EFI_STRING * Results)2713 FakeExtractConfig (
2714   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
2715   IN  CONST EFI_STRING                       Request,
2716   OUT EFI_STRING                             *Progress,
2717   OUT EFI_STRING                             *Results
2718   )
2719 {
2720   if (Progress == NULL || Results == NULL) {
2721     return EFI_INVALID_PARAMETER;
2722   }
2723   *Progress = Request;
2724   return EFI_NOT_FOUND;
2725 }
2726 
2727 /**
2728   This function processes the results of changes in configuration.
2729 
2730 
2731   @param This            Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2732   @param Configuration   A null-terminated Unicode string in <ConfigResp> format.
2733   @param Progress        A pointer to a string filled in with the offset of the most
2734                          recent '&' before the first failing name/value pair (or the
2735                          beginning of the string if the failure is in the first
2736                          name/value pair) or the terminating NULL if all was successful.
2737 
2738   @retval  EFI_SUCCESS            The Results is processed successfully.
2739   @retval  EFI_INVALID_PARAMETER  Configuration is NULL.
2740   @retval  EFI_NOT_FOUND          Routing data doesn't match any storage in this driver.
2741 
2742 **/
2743 EFI_STATUS
2744 EFIAPI
FakeRouteConfig(IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL * This,IN CONST EFI_STRING Configuration,OUT EFI_STRING * Progress)2745 FakeRouteConfig (
2746   IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
2747   IN  CONST EFI_STRING                       Configuration,
2748   OUT EFI_STRING                             *Progress
2749   )
2750 {
2751   if (Configuration == NULL || Progress == NULL) {
2752     return EFI_INVALID_PARAMETER;
2753   }
2754 
2755   return EFI_NOT_FOUND;
2756 }
2757 
2758 
2759 /**
2760   This function initialize the data mainly used in form browser.
2761 
2762   @retval EFI_SUCCESS          Initialize form data successfully.
2763   @retval Others               Fail to Initialize form data.
2764 
2765 **/
2766 EFI_STATUS
InitFormBrowser(VOID)2767 InitFormBrowser (
2768   VOID
2769   )
2770 {
2771   EFI_STATUS                  Status;
2772   USER_MANAGER_CALLBACK_INFO  *CallbackInfo;
2773   EFI_HII_DATABASE_PROTOCOL   *HiiDatabase;
2774   EFI_HII_STRING_PROTOCOL     *HiiString;
2775   EFI_FORM_BROWSER2_PROTOCOL  *FormBrowser2;
2776 
2777   //
2778   // Initialize driver private data.
2779   //
2780   CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO));
2781   if (CallbackInfo == NULL) {
2782     return EFI_OUT_OF_RESOURCES;
2783   }
2784 
2785   CallbackInfo->Signature                   = USER_MANAGER_SIGNATURE;
2786   CallbackInfo->ConfigAccess.ExtractConfig  = FakeExtractConfig;
2787   CallbackInfo->ConfigAccess.RouteConfig    = FakeRouteConfig;
2788   CallbackInfo->ConfigAccess.Callback       = UserIdentifyManagerCallback;
2789 
2790   //
2791   // Locate Hii Database protocol.
2792   //
2793   Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase);
2794   if (EFI_ERROR (Status)) {
2795     return Status;
2796   }
2797   CallbackInfo->HiiDatabase = HiiDatabase;
2798 
2799   //
2800   // Locate HiiString protocol.
2801   //
2802   Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString);
2803   if (EFI_ERROR (Status)) {
2804     return Status;
2805   }
2806   CallbackInfo->HiiString = HiiString;
2807 
2808   //
2809   // Locate Formbrowser2 protocol.
2810   //
2811   Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2);
2812   if (EFI_ERROR (Status)) {
2813     return Status;
2814   }
2815 
2816   CallbackInfo->FormBrowser2  = FormBrowser2;
2817   CallbackInfo->DriverHandle  = NULL;
2818 
2819   //
2820   // Install Device Path Protocol and Config Access protocol to driver handle.
2821   //
2822   Status = gBS->InstallMultipleProtocolInterfaces (
2823                   &CallbackInfo->DriverHandle,
2824                   &gEfiDevicePathProtocolGuid,
2825                   &mHiiVendorDevicePath,
2826                   &gEfiHiiConfigAccessProtocolGuid,
2827                   &CallbackInfo->ConfigAccess,
2828                   NULL
2829                   );
2830   ASSERT_EFI_ERROR (Status);
2831 
2832   //
2833   // Publish HII data.
2834   //
2835   CallbackInfo->HiiHandle = HiiAddPackages (
2836                               &gUserIdentifyManagerGuid,
2837                               CallbackInfo->DriverHandle,
2838                               UserIdentifyManagerStrings,
2839                               UserIdentifyManagerVfrBin,
2840                               NULL
2841                               );
2842   if (CallbackInfo->HiiHandle == NULL) {
2843     return EFI_OUT_OF_RESOURCES;
2844   }
2845 
2846   mCallbackInfo = CallbackInfo;
2847 
2848   return EFI_SUCCESS;
2849 }
2850 
2851 
2852 /**
2853   Identify the user whose identification policy supports auto logon.
2854 
2855   @param[in]   ProviderIndex   The provider index in the provider list.
2856   @param[out]  User            Points to user user profile if a user is identified successfully.
2857 
2858   @retval EFI_SUCCESS          Identify a user with the specified provider successfully.
2859   @retval Others               Fail to identify a user.
2860 
2861 **/
2862 EFI_STATUS
IdentifyAutoLogonUser(IN UINTN ProviderIndex,OUT USER_PROFILE_ENTRY ** User)2863 IdentifyAutoLogonUser (
2864   IN  UINTN                                     ProviderIndex,
2865   OUT USER_PROFILE_ENTRY                        **User
2866   )
2867 {
2868   EFI_STATUS    Status;
2869   EFI_USER_INFO *Info;
2870   UINT8         PolicyType;
2871 
2872   Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER));
2873   if (Info == NULL) {
2874     return EFI_OUT_OF_RESOURCES;
2875   }
2876 
2877   Info->InfoType  = EFI_USER_INFO_IDENTIFIER_RECORD;
2878   Info->InfoSize  = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER);
2879 
2880   //
2881   // Identify the specified credential provider's auto logon user.
2882   //
2883   Status = mProviderDb->Provider[ProviderIndex]->User (
2884                                                    mProviderDb->Provider[ProviderIndex],
2885                                                    NULL,
2886                                                    (EFI_USER_INFO_IDENTIFIER *) (Info + 1)
2887                                                    );
2888   if (EFI_ERROR (Status)) {
2889     FreePool (Info);
2890     return Status;
2891   }
2892 
2893   //
2894   // Find user with the specified user ID.
2895   //
2896   *User   = NULL;
2897   Status  = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize);
2898   FreePool (Info);
2899   if (EFI_ERROR (Status)) {
2900     return Status;
2901   }
2902 
2903   Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType);
2904   if (PolicyType == EFI_USER_INFO_IDENTITY_AND) {
2905     //
2906     // The identified user need also identified by other credential provider.
2907     // This can handle through select user.
2908     //
2909     return EFI_NOT_READY;
2910   }
2911 
2912   return Status;
2913 }
2914 
2915 
2916 /**
2917   Check whether the given console is ready.
2918 
2919   @param[in]   ProtocolGuid   Points to the protocol guid of sonsole .
2920 
2921   @retval TRUE     The given console is ready.
2922   @retval FALSE    The given console is not ready.
2923 
2924 **/
2925 BOOLEAN
CheckConsole(EFI_GUID * ProtocolGuid)2926 CheckConsole (
2927   EFI_GUID                     *ProtocolGuid
2928   )
2929 {
2930   EFI_STATUS                   Status;
2931   UINTN                        HandleCount;
2932   EFI_HANDLE                   *HandleBuf;
2933   UINTN                        Index;
2934   EFI_DEVICE_PATH_PROTOCOL     *DevicePath;
2935 
2936   //
2937   // Try to find all the handle driver.
2938   //
2939   HandleCount = 0;
2940   HandleBuf   = NULL;
2941   Status = gBS->LocateHandleBuffer (
2942                   ByProtocol,
2943                   ProtocolGuid,
2944                   NULL,
2945                   &HandleCount,
2946                   &HandleBuf
2947                   );
2948   if (EFI_ERROR (Status)) {
2949     return FALSE;
2950   }
2951 
2952   for (Index = 0; Index < HandleCount; Index++) {
2953     DevicePath = DevicePathFromHandle (HandleBuf[Index]);
2954     if (DevicePath != NULL) {
2955       FreePool (HandleBuf);
2956       return TRUE;
2957     }
2958   }
2959   FreePool (HandleBuf);
2960   return FALSE;
2961 }
2962 
2963 
2964 /**
2965   Check whether the console is ready.
2966 
2967   @retval TRUE     The console is ready.
2968   @retval FALSE    The console is not ready.
2969 
2970 **/
2971 BOOLEAN
IsConsoleReady(VOID)2972 IsConsoleReady (
2973   VOID
2974   )
2975 {
2976   if (!CheckConsole (&gEfiSimpleTextOutProtocolGuid)) {
2977     return FALSE;
2978   }
2979 
2980   if (!CheckConsole (&gEfiSimpleTextInProtocolGuid)) {
2981     if (!CheckConsole (&gEfiSimpleTextInputExProtocolGuid)) {
2982     return FALSE;
2983     }
2984   }
2985 
2986   return TRUE;
2987 }
2988 
2989 
2990 /**
2991   Identify a user to logon.
2992 
2993   @param[out]  User          Points to user user profile if a user is identified successfully.
2994 
2995   @retval EFI_SUCCESS        Identify a user successfully.
2996 
2997 **/
2998 EFI_STATUS
IdentifyUser(OUT USER_PROFILE_ENTRY ** User)2999 IdentifyUser (
3000   OUT USER_PROFILE_ENTRY                        **User
3001   )
3002 {
3003   EFI_STATUS                    Status;
3004   UINTN                         Index;
3005   EFI_CREDENTIAL_LOGON_FLAGS    AutoLogon;
3006   EFI_USER_INFO                 *IdentifyInfo;
3007   EFI_USER_INFO_IDENTITY_POLICY *Identity;
3008   EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential;
3009   USER_PROFILE_ENTRY            *UserEntry;
3010 
3011   //
3012   // Initialize credential providers.
3013   //
3014   InitProviderInfo ();
3015 
3016   //
3017   // Initialize user profile database.
3018   //
3019   InitUserProfileDb ();
3020 
3021   //
3022   // If only one user in system, and its identify policy is TRUE, then auto logon.
3023   //
3024   if (mUserProfileDb->UserProfileNum == 1) {
3025     UserEntry     = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[0];
3026     IdentifyInfo  = NULL;
3027     Status        = FindUserInfoByType (UserEntry, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD);
3028     if (EFI_ERROR (Status)) {
3029       return Status;
3030     }
3031     ASSERT (IdentifyInfo != NULL);
3032 
3033     Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1));
3034     if (Identity->Type == EFI_USER_INFO_IDENTITY_TRUE) {
3035       mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
3036       UpdateUserInfo (UserEntry);
3037       *User = UserEntry;
3038       return EFI_SUCCESS;
3039     }
3040   }
3041 
3042   //
3043   // Find and login the default & AutoLogon user.
3044   //
3045   for (Index = 0; Index < mProviderDb->Count; Index++) {
3046     UserCredential = mProviderDb->Provider[Index];
3047     Status = UserCredential->Default (UserCredential, &AutoLogon);
3048     if (EFI_ERROR (Status)) {
3049       continue;
3050     }
3051 
3052     if ((AutoLogon & (EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO)) != 0) {
3053       Status = IdentifyAutoLogonUser (Index, &UserEntry);
3054       if (Status == EFI_SUCCESS) {
3055         mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry;
3056         UpdateUserInfo (UserEntry);
3057         *User = UserEntry;
3058         return EFI_SUCCESS;
3059       }
3060     }
3061   }
3062 
3063   if (!IsConsoleReady ()) {
3064     //
3065     // The console is still not ready for user selection.
3066     //
3067     return EFI_ACCESS_DENIED;
3068   }
3069 
3070   //
3071   // Select a user and identify it.
3072   //
3073   mCallbackInfo->FormBrowser2->SendForm (
3074                                  mCallbackInfo->FormBrowser2,
3075                                  &mCallbackInfo->HiiHandle,
3076                                  1,
3077                                  &gUserIdentifyManagerGuid,
3078                                  0,
3079                                  NULL,
3080                                  NULL
3081                                  );
3082 
3083   if (mIdentified) {
3084     *User = (USER_PROFILE_ENTRY *) mCurrentUser;
3085     UpdateUserInfo (*User);
3086     return EFI_SUCCESS;
3087   }
3088 
3089   return EFI_ACCESS_DENIED;
3090 }
3091 
3092 
3093 /**
3094   An empty function to pass error checking of CreateEventEx ().
3095 
3096   @param  Event         Event whose notification function is being invoked.
3097   @param  Context       Pointer to the notification function's context,
3098                         which is implementation-dependent.
3099 
3100 **/
3101 VOID
3102 EFIAPI
InternalEmptyFuntion(IN EFI_EVENT Event,IN VOID * Context)3103 InternalEmptyFuntion (
3104   IN EFI_EVENT                Event,
3105   IN VOID                     *Context
3106   )
3107 {
3108 }
3109 
3110 
3111 /**
3112   Create, Signal, and Close the User Profile Changed event.
3113 
3114 **/
3115 VOID
SignalEventUserProfileChanged(VOID)3116 SignalEventUserProfileChanged (
3117   VOID
3118   )
3119 {
3120   EFI_STATUS    Status;
3121   EFI_EVENT     Event;
3122 
3123   Status = gBS->CreateEventEx (
3124                   EVT_NOTIFY_SIGNAL,
3125                   TPL_CALLBACK,
3126                   InternalEmptyFuntion,
3127                   NULL,
3128                   &gEfiEventUserProfileChangedGuid,
3129                   &Event
3130                   );
3131   ASSERT_EFI_ERROR (Status);
3132   gBS->SignalEvent (Event);
3133   gBS->CloseEvent (Event);
3134 }
3135 
3136 
3137 /**
3138   Create a new user profile.
3139 
3140   This function creates a new user profile with only a new user identifier attached and returns
3141   its handle. The user profile is non-volatile, but the handle User can change across reboots.
3142 
3143   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3144   @param[out] User               On return, points to the new user profile handle.
3145                                  The user profile handle is unique only during this boot.
3146 
3147   @retval EFI_SUCCESS            User profile was successfully created.
3148   @retval EFI_ACCESS_DENIED      Current user does not have sufficient permissions to create a
3149                                  user profile.
3150   @retval EFI_UNSUPPORTED        Creation of new user profiles is not supported.
3151   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
3152 
3153 **/
3154 EFI_STATUS
3155 EFIAPI
UserProfileCreate(IN CONST EFI_USER_MANAGER_PROTOCOL * This,OUT EFI_USER_PROFILE_HANDLE * User)3156 UserProfileCreate (
3157   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3158   OUT       EFI_USER_PROFILE_HANDLE             *User
3159   )
3160 {
3161   EFI_STATUS  Status;
3162 
3163   if ((This == NULL) || (User == NULL)) {
3164     return EFI_INVALID_PARAMETER;
3165   }
3166 
3167   //
3168   // Check the right of the current user.
3169   //
3170   if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3171     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
3172       return EFI_ACCESS_DENIED;
3173     }
3174   }
3175 
3176   //
3177   // Create new user profile
3178   //
3179   Status = CreateUserProfile ((USER_PROFILE_ENTRY **) User);
3180   if (EFI_ERROR (Status)) {
3181     return EFI_ACCESS_DENIED;
3182   }
3183   return EFI_SUCCESS;
3184 }
3185 
3186 
3187 /**
3188   Delete an existing user profile.
3189 
3190   @param[in] This                Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3191   @param[in] User                User profile handle.
3192 
3193   @retval EFI_SUCCESS            User profile was successfully deleted.
3194   @retval EFI_ACCESS_DENIED      Current user does not have sufficient permissions to delete a user
3195                                  profile or there is only one user profile.
3196   @retval EFI_UNSUPPORTED        Deletion of new user profiles is not supported.
3197   @retval EFI_INVALID_PARAMETER  User does not refer to a valid user profile.
3198 
3199 **/
3200 EFI_STATUS
3201 EFIAPI
UserProfileDelete(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_USER_PROFILE_HANDLE User)3202 UserProfileDelete (
3203   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3204   IN        EFI_USER_PROFILE_HANDLE             User
3205   )
3206 {
3207   EFI_STATUS  Status;
3208 
3209   if (This == NULL) {
3210     return EFI_INVALID_PARAMETER;
3211   }
3212 
3213   //
3214   // Check the right of the current user.
3215   //
3216   if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3217     return EFI_ACCESS_DENIED;
3218   }
3219 
3220   //
3221   // Delete user profile.
3222   //
3223   Status = DelUserProfile (User);
3224   if (EFI_ERROR (Status)) {
3225     if (Status != EFI_INVALID_PARAMETER) {
3226       return EFI_ACCESS_DENIED;
3227     }
3228     return EFI_INVALID_PARAMETER;
3229   }
3230 
3231   return EFI_SUCCESS;
3232 }
3233 
3234 
3235 /**
3236   Enumerate all of the enrolled users on the platform.
3237 
3238   This function returns the next enrolled user profile. To retrieve the first user profile handle,
3239   point User at a NULL. Each subsequent call will retrieve another user profile handle until there
3240   are no more, at which point User will point to NULL.
3241 
3242   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3243   @param[in, out] User           On entry, points to the previous user profile handle or NULL to
3244                                  start enumeration. On exit, points to the next user profile handle
3245                                  or NULL if there are no more user profiles.
3246 
3247   @retval EFI_SUCCESS            Next enrolled user profile successfully returned.
3248   @retval EFI_ACCESS_DENIED      Next enrolled user profile was not successfully returned.
3249   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
3250 **/
3251 EFI_STATUS
3252 EFIAPI
UserProfileGetNext(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN OUT EFI_USER_PROFILE_HANDLE * User)3253 UserProfileGetNext (
3254   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3255   IN OUT    EFI_USER_PROFILE_HANDLE             *User
3256   )
3257 {
3258   EFI_STATUS  Status;
3259 
3260   if ((This == NULL) || (User == NULL)) {
3261     return EFI_INVALID_PARAMETER;
3262   }
3263 
3264   Status = FindUserProfile ((USER_PROFILE_ENTRY **) User, TRUE, NULL);
3265   if (EFI_ERROR (Status)) {
3266     return EFI_ACCESS_DENIED;
3267   }
3268   return EFI_SUCCESS;
3269 }
3270 
3271 
3272 /**
3273   Return the current user profile handle.
3274 
3275   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3276   @param[out] CurrentUser        On return, points to the current user profile handle.
3277 
3278   @retval EFI_SUCCESS            Current user profile handle returned successfully.
3279   @retval EFI_INVALID_PARAMETER  The CurrentUser parameter is NULL.
3280 
3281 **/
3282 EFI_STATUS
3283 EFIAPI
UserProfileCurrent(IN CONST EFI_USER_MANAGER_PROTOCOL * This,OUT EFI_USER_PROFILE_HANDLE * CurrentUser)3284 UserProfileCurrent (
3285   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3286   OUT       EFI_USER_PROFILE_HANDLE             *CurrentUser
3287   )
3288 {
3289   //
3290   // Get current user profile.
3291   //
3292   if ((This == NULL) || (CurrentUser == NULL)) {
3293     return EFI_INVALID_PARAMETER;
3294   }
3295 
3296   *CurrentUser = mCurrentUser;
3297   return EFI_SUCCESS;
3298 }
3299 
3300 
3301 /**
3302   Identify a user.
3303 
3304   Identify the user and, if authenticated, returns the user handle and changes the current
3305   user profile. All user information marked as private in a previously selected profile
3306   is no longer available for inspection.
3307   Whenever the current user profile is changed then the an event with the GUID
3308   EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled.
3309 
3310   @param[in]  This               Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3311   @param[out] User               On return, points to the user profile handle for the current
3312                                  user profile.
3313 
3314   @retval EFI_SUCCESS            User was successfully identified.
3315   @retval EFI_ACCESS_DENIED      User was not successfully identified.
3316   @retval EFI_INVALID_PARAMETER  The User parameter is NULL.
3317 
3318 **/
3319 EFI_STATUS
3320 EFIAPI
UserProfileIdentify(IN CONST EFI_USER_MANAGER_PROTOCOL * This,OUT EFI_USER_PROFILE_HANDLE * User)3321 UserProfileIdentify (
3322   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3323   OUT       EFI_USER_PROFILE_HANDLE             *User
3324   )
3325 {
3326   EFI_STATUS  Status;
3327 
3328   if ((This == NULL) || (User == NULL)) {
3329     return EFI_INVALID_PARAMETER;
3330   }
3331 
3332   if (mCurrentUser != NULL) {
3333     *User = mCurrentUser;
3334     return EFI_SUCCESS;
3335   }
3336 
3337   //
3338   // Identify user
3339   //
3340   Status = IdentifyUser ((USER_PROFILE_ENTRY **) User);
3341   if (EFI_ERROR (Status)) {
3342     return EFI_ACCESS_DENIED;
3343   }
3344 
3345   //
3346   // Publish the user info into the EFI system configuration table.
3347   //
3348   PublishUserTable ();
3349 
3350   //
3351   // Signal User Profile Changed event.
3352   //
3353   SignalEventUserProfileChanged ();
3354   return EFI_SUCCESS;
3355 }
3356 
3357 /**
3358   Find a user using a user information record.
3359 
3360   This function searches all user profiles for the specified user information record.
3361   The search starts with the user information record handle following UserInfo and
3362   continues until either the information is found or there are no more user profiles.
3363   A match occurs when the Info.InfoType field matches the user information record
3364   type and the user information record data matches the portion of Info.
3365 
3366   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3367   @param[in, out] User           On entry, points to the previously returned user profile
3368                                  handle, or NULL to start searching with the first user profile.
3369                                  On return, points to the user profile handle, or NULL if not
3370                                  found.
3371   @param[in, out] UserInfo       On entry, points to the previously returned user information
3372                                  handle, or NULL to start searching with the first. On return,
3373                                  points to the user information handle of the user information
3374                                  record, or NULL if not found. Can be NULL, in which case only
3375                                  one user information record per user can be returned.
3376   @param[in]      Info           Points to the buffer containing the user information to be
3377                                  compared to the user information record. If the user information
3378                                  record data is empty, then only the user information record type
3379                                  is compared. If InfoSize is 0, then the user information record
3380                                  must be empty.
3381 
3382   @param[in]      InfoSize       The size of Info, in bytes.
3383 
3384   @retval EFI_SUCCESS            User information was found. User points to the user profile
3385                                  handle, and UserInfo points to the user information handle.
3386   @retval EFI_NOT_FOUND          User information was not found. User points to NULL, and
3387                                  UserInfo points to NULL.
3388   @retval EFI_INVALID_PARAMETER  User is NULL. Or Info is NULL.
3389 
3390 **/
3391 EFI_STATUS
3392 EFIAPI
UserProfileFind(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN OUT EFI_USER_PROFILE_HANDLE * User,IN OUT EFI_USER_INFO_HANDLE * UserInfo OPTIONAL,IN CONST EFI_USER_INFO * Info,IN UINTN InfoSize)3393 UserProfileFind (
3394   IN     CONST EFI_USER_MANAGER_PROTOCOL        *This,
3395   IN OUT EFI_USER_PROFILE_HANDLE                *User,
3396   IN OUT EFI_USER_INFO_HANDLE                   *UserInfo OPTIONAL,
3397   IN     CONST EFI_USER_INFO                    *Info,
3398   IN     UINTN                                  InfoSize
3399   )
3400 {
3401   EFI_STATUS  Status;
3402   UINTN       Size;
3403 
3404   if ((This == NULL) || (User == NULL) || (Info == NULL)) {
3405     return EFI_INVALID_PARAMETER;
3406   }
3407 
3408   if (InfoSize == 0) {
3409     //
3410     // If InfoSize is 0, then the user information record must be empty.
3411     //
3412     if (Info->InfoSize != sizeof (EFI_USER_INFO)) {
3413       return EFI_INVALID_PARAMETER;
3414     }
3415   } else {
3416     if (InfoSize != Info->InfoSize) {
3417       return EFI_INVALID_PARAMETER;
3418     }
3419   }
3420   Size = Info->InfoSize;
3421 
3422   //
3423   // Find user profile accdoring to user information.
3424   //
3425   Status = FindUserProfileByInfo (
3426             (USER_PROFILE_ENTRY **) User,
3427             (EFI_USER_INFO **) UserInfo,
3428             (EFI_USER_INFO *) Info,
3429             Size
3430             );
3431   if (EFI_ERROR (Status)) {
3432     *User = NULL;
3433     if (UserInfo != NULL) {
3434       *UserInfo = NULL;
3435     }
3436     return EFI_NOT_FOUND;
3437   }
3438 
3439   return EFI_SUCCESS;
3440 }
3441 
3442 
3443 /**
3444   Return information attached to the user.
3445 
3446   This function returns user information. The format of the information is described in User
3447   Information. The function may return EFI_ACCESS_DENIED if the information is marked private
3448   and the handle specified by User is not the current user profile. The function may return
3449   EFI_ACCESS_DENIED if the information is marked protected and the information is associated
3450   with a credential provider for which the user has not been authenticated.
3451 
3452   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3453   @param[in]      User           Handle of the user whose profile will be retrieved.
3454   @param[in]      UserInfo       Handle of the user information data record.
3455   @param[out]     Info           On entry, points to a buffer of at least *InfoSize bytes. On exit,
3456                                  holds the user information. If the buffer is too small to hold the
3457                                  information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
3458                                  updated to contain the number of bytes actually required.
3459   @param[in, out] InfoSize       On entry, points to the size of Info. On return, points to the size
3460                                  of the user information.
3461 
3462   @retval EFI_SUCCESS            Information returned successfully.
3463   @retval EFI_ACCESS_DENIED      The information about the specified user cannot be accessed by the
3464                                  current user.
3465   @retval EFI_BUFFER_TOO_SMALL   The number of bytes specified by *InfoSize is too small to hold the
3466                                  returned data. The actual size required is returned in *InfoSize.
3467   @retval EFI_NOT_FOUND          User does not refer to a valid user profile or UserInfo does not refer
3468                                  to a valid user info handle.
3469   @retval EFI_INVALID_PARAMETER  Info is NULL or InfoSize is NULL.
3470 
3471 **/
3472 EFI_STATUS
3473 EFIAPI
UserProfileGetInfo(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_USER_PROFILE_HANDLE User,IN EFI_USER_INFO_HANDLE UserInfo,OUT EFI_USER_INFO * Info,IN OUT UINTN * InfoSize)3474 UserProfileGetInfo (
3475   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3476   IN        EFI_USER_PROFILE_HANDLE             User,
3477   IN        EFI_USER_INFO_HANDLE                UserInfo,
3478   OUT       EFI_USER_INFO                       *Info,
3479   IN OUT    UINTN                               *InfoSize
3480   )
3481 {
3482   EFI_STATUS  Status;
3483 
3484   if ((This == NULL) || (InfoSize == NULL)) {
3485     return EFI_INVALID_PARAMETER;
3486   }
3487 
3488   if ((*InfoSize != 0) && (Info == NULL)) {
3489     return EFI_INVALID_PARAMETER;
3490   }
3491 
3492   if ((User == NULL) || (UserInfo == NULL)) {
3493     return EFI_NOT_FOUND;
3494   }
3495 
3496   Status = GetUserInfo (User, UserInfo, Info, InfoSize, TRUE);
3497   if (EFI_ERROR (Status)) {
3498     if (Status == EFI_BUFFER_TOO_SMALL) {
3499       return EFI_BUFFER_TOO_SMALL;
3500     }
3501     return EFI_ACCESS_DENIED;
3502   }
3503   return EFI_SUCCESS;
3504 }
3505 
3506 
3507 /**
3508   Add or update user information.
3509 
3510   This function changes user information.  If NULL is pointed to by UserInfo, then a new user
3511   information record is created and its handle is returned in UserInfo. Otherwise, the existing
3512   one is replaced.
3513   If EFI_USER_INFO_IDENITTY_POLICY_RECORD is changed, it is the caller's responsibility to keep
3514   it to be synced with the information on credential providers.
3515   If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same
3516   type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and UserInfo
3517   will point to the handle of the existing record.
3518 
3519   @param[in]      This            Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3520   @param[in]      User            Handle of the user whose profile will be retrieved.
3521   @param[in, out] UserInfo        Handle of the user information data record.
3522   @param[in]      Info            On entry, points to a buffer of at least *InfoSize bytes. On exit,
3523                                   holds the user information. If the buffer is too small to hold the
3524                                   information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is
3525                                   updated to contain the number of bytes actually required.
3526   @param[in]      InfoSize        On entry, points to the size of Info. On return, points to the size
3527                                   of the user information.
3528 
3529   @retval EFI_SUCCESS             Information returned successfully.
3530   @retval EFI_ACCESS_DENIED       The record is exclusive.
3531   @retval EFI_SECURITY_VIOLATION  The current user does not have permission to change the specified
3532                                   user profile or user information record.
3533   @retval EFI_NOT_FOUND           User does not refer to a valid user profile or UserInfo does not
3534                                   refer to a valid user info handle.
3535   @retval EFI_INVALID_PARAMETER   UserInfo is NULL or Info is NULL.
3536 **/
3537 EFI_STATUS
3538 EFIAPI
UserProfileSetInfo(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_USER_PROFILE_HANDLE User,IN OUT EFI_USER_INFO_HANDLE * UserInfo,IN CONST EFI_USER_INFO * Info,IN UINTN InfoSize)3539 UserProfileSetInfo (
3540   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3541   IN        EFI_USER_PROFILE_HANDLE             User,
3542   IN OUT    EFI_USER_INFO_HANDLE                *UserInfo,
3543   IN CONST  EFI_USER_INFO                       *Info,
3544   IN        UINTN                               InfoSize
3545   )
3546 {
3547   EFI_STATUS  Status;
3548 
3549   if ((This == NULL) || (User == NULL) || (UserInfo == NULL) || (Info == NULL)) {
3550     return EFI_INVALID_PARAMETER;
3551   }
3552 
3553   //
3554   // Check the right of the current user.
3555   //
3556   if (User != mCurrentUser) {
3557     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3558       if (*UserInfo != NULL) {
3559         //
3560         // Can't update info in other profiles without MANAGE right.
3561         //
3562         return EFI_SECURITY_VIOLATION;
3563       }
3564 
3565       if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) {
3566         //
3567         // Can't add info into other profiles.
3568         //
3569         return EFI_SECURITY_VIOLATION;
3570       }
3571     }
3572   }
3573 
3574   if (User == mCurrentUser) {
3575     if (CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_SELF)) {
3576       //
3577       // Only identify policy can be added/updated.
3578       //
3579       if (Info->InfoType != EFI_USER_INFO_IDENTITY_POLICY_RECORD) {
3580         return EFI_SECURITY_VIOLATION;
3581       }
3582     }
3583   }
3584 
3585   //
3586   // Modify user information.
3587   //
3588   Status = ModifyUserInfo (User, (EFI_USER_INFO **) UserInfo, Info, InfoSize);
3589   if (EFI_ERROR (Status)) {
3590     if (Status == EFI_ACCESS_DENIED) {
3591       return EFI_ACCESS_DENIED;
3592     }
3593     return EFI_SECURITY_VIOLATION;
3594   }
3595   return EFI_SUCCESS;
3596 }
3597 
3598 
3599 /**
3600   Called by credential provider to notify of information change.
3601 
3602   This function allows the credential provider to notify the User Identity Manager when user status
3603   has changed.
3604   If the User Identity Manager doesn't support asynchronous changes in credentials, then this function
3605   should return EFI_UNSUPPORTED.
3606   If current user does not exist, and the credential provider can identify a user, then make the user
3607   to be current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
3608   If current user already exists, and the credential provider can identify another user, then switch
3609   current user to the newly identified user, and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
3610   If current user was identified by this credential provider and now the credential provider cannot identify
3611   current user, then logout current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
3612 
3613   @param[in] This          Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3614   @param[in] Changed       Handle on which is installed an instance of the EFI_USER_CREDENTIAL2_PROTOCOL
3615                            where the user has changed.
3616 
3617   @retval EFI_SUCCESS      The User Identity Manager has handled the notification.
3618   @retval EFI_NOT_READY    The function was called while the specified credential provider was not selected.
3619   @retval EFI_UNSUPPORTED  The User Identity Manager doesn't support asynchronous notifications.
3620 
3621 **/
3622 EFI_STATUS
3623 EFIAPI
UserProfileNotify(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_HANDLE Changed)3624 UserProfileNotify (
3625   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3626   IN        EFI_HANDLE                          Changed
3627   )
3628 {
3629   return EFI_UNSUPPORTED;
3630 }
3631 
3632 
3633 /**
3634   Delete user information.
3635 
3636   Delete the user information attached to the user profile specified by the UserInfo.
3637 
3638   @param[in] This            Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3639   @param[in] User            Handle of the user whose information will be deleted.
3640   @param[in] UserInfo        Handle of the user information to remove.
3641 
3642   @retval EFI_SUCCESS        User information deleted successfully.
3643   @retval EFI_NOT_FOUND      User information record UserInfo does not exist in the user profile.
3644   @retval EFI_ACCESS_DENIED  The current user does not have permission to delete this user information.
3645 
3646 **/
3647 EFI_STATUS
3648 EFIAPI
UserProfileDeleteInfo(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_USER_PROFILE_HANDLE User,IN EFI_USER_INFO_HANDLE UserInfo)3649 UserProfileDeleteInfo (
3650   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3651   IN        EFI_USER_PROFILE_HANDLE             User,
3652   IN        EFI_USER_INFO_HANDLE                UserInfo
3653   )
3654 {
3655   EFI_STATUS  Status;
3656 
3657   if (This == NULL) {
3658     return EFI_INVALID_PARAMETER;
3659   }
3660 
3661   //
3662   // Check the right of the current user.
3663   //
3664   if (User != mCurrentUser) {
3665     if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) {
3666       return EFI_ACCESS_DENIED;
3667     }
3668   }
3669 
3670   //
3671   // Delete user information.
3672   //
3673   Status = DelUserInfo (User, UserInfo, TRUE);
3674   if (EFI_ERROR (Status)) {
3675     if (Status == EFI_NOT_FOUND) {
3676       return EFI_NOT_FOUND;
3677     }
3678     return EFI_ACCESS_DENIED;
3679   }
3680   return EFI_SUCCESS;
3681 }
3682 
3683 
3684 /**
3685   Enumerate user information of all the enrolled users on the platform.
3686 
3687   This function returns the next user information record. To retrieve the first user
3688   information record handle, point UserInfo at a NULL. Each subsequent call will retrieve
3689   another user information record handle until there are no more, at which point UserInfo
3690   will point to NULL.
3691 
3692   @param[in]      This           Points to this instance of the EFI_USER_MANAGER_PROTOCOL.
3693   @param[in]      User           Handle of the user whose information will be deleted.
3694   @param[in, out] UserInfo       Handle of the user information to remove.
3695 
3696   @retval EFI_SUCCESS            User information returned.
3697   @retval EFI_NOT_FOUND          No more user information found.
3698   @retval EFI_INVALID_PARAMETER  UserInfo is NULL.
3699 
3700 **/
3701 EFI_STATUS
3702 EFIAPI
UserProfileGetNextInfo(IN CONST EFI_USER_MANAGER_PROTOCOL * This,IN EFI_USER_PROFILE_HANDLE User,IN OUT EFI_USER_INFO_HANDLE * UserInfo)3703 UserProfileGetNextInfo (
3704   IN CONST  EFI_USER_MANAGER_PROTOCOL           *This,
3705   IN        EFI_USER_PROFILE_HANDLE             User,
3706   IN OUT    EFI_USER_INFO_HANDLE                *UserInfo
3707   )
3708 {
3709   if ((This == NULL) || (UserInfo == NULL)) {
3710     return EFI_INVALID_PARAMETER;
3711   }
3712   //
3713   // Get next user information entry.
3714   //
3715   return FindUserInfo (User, (EFI_USER_INFO **) UserInfo, TRUE, NULL);
3716 }
3717 
3718 
3719 /**
3720   Main entry for this driver.
3721 
3722   @param[in] ImageHandle     Image handle this driver.
3723   @param[in] SystemTable     Pointer to SystemTable.
3724 
3725   @retval EFI_SUCESS         This function always complete successfully.
3726 
3727 **/
3728 EFI_STATUS
3729 EFIAPI
UserIdentifyManagerInit(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)3730 UserIdentifyManagerInit (
3731   IN EFI_HANDLE        ImageHandle,
3732   IN EFI_SYSTEM_TABLE  *SystemTable
3733   )
3734 {
3735 
3736   EFI_STATUS  Status;
3737 
3738   //
3739   // It is NOT robust enough to be included in production.
3740   //
3741   #error "This implementation is just a sample, please comment this line if you really want to use this driver."
3742 
3743   //
3744   // Initiate form browser.
3745   //
3746   InitFormBrowser ();
3747 
3748   //
3749   // Install protocol interfaces for the User Identity Manager.
3750   //
3751   Status = gBS->InstallProtocolInterface (
3752                   &mCallbackInfo->DriverHandle,
3753                   &gEfiUserManagerProtocolGuid,
3754                   EFI_NATIVE_INTERFACE,
3755                   &gUserIdentifyManager
3756                   );
3757   ASSERT_EFI_ERROR (Status);
3758 
3759   LoadDeferredImageInit (ImageHandle);
3760   return EFI_SUCCESS;
3761 }
3762 
3763 
3764