From 0c18794ea4289f03fefc7117b56740414cc0536c Mon Sep 17 00:00:00 2001 From: gdong1 Date: Fri, 2 Sep 2011 07:49:32 +0000 Subject: Add security package to repository. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12261 6f19259b-4bc3-4df7-8a09-765794883524 --- .../PwdCredentialProvider.c | 1422 +++++++ .../PwdCredentialProvider.h | 354 ++ .../PwdCredentialProviderData.h | 33 + .../PwdCredentialProviderDxe.inf | 53 + .../PwdCredentialProviderStrings.uni | Bin 0 -> 5128 bytes .../PwdCredentialProviderVfr.Vfr | 35 + .../UsbCredentialProvider.c | 1407 +++++++ .../UsbCredentialProvider.h | 354 ++ .../UsbCredentialProviderDxe.inf | 58 + .../UsbCredentialProviderStrings.uni | Bin 0 -> 3556 bytes .../UserIdentifyManagerDxe/LoadDeferredImage.c | 148 + .../UserIdentifyManagerDxe/UserIdentifyManager.c | 4381 ++++++++++++++++++++ .../UserIdentifyManagerDxe/UserIdentifyManager.h | 413 ++ .../UserIdentifyManagerData.h | 42 + .../UserIdentifyManagerDxe.inf | 62 + .../UserIdentifyManagerStrings.uni | Bin 0 -> 2696 bytes .../UserIdentifyManagerVfr.Vfr | 44 + .../UserProfileManagerDxe/UserProfileAdd.c | 372 ++ .../UserProfileManagerDxe/UserProfileDelete.c | 314 ++ .../UserProfileManagerDxe/UserProfileManager.c | 806 ++++ .../UserProfileManagerDxe/UserProfileManager.h | 387 ++ .../UserProfileManagerDxe/UserProfileManagerData.h | 161 + .../UserProfileManagerDxe.inf | 60 + .../UserProfileManagerStrings.uni | Bin 0 -> 21532 bytes .../UserProfileManagerVfr.Vfr | 247 ++ .../UserProfileManagerDxe/UserProfileModify.c | 2511 +++++++++++ 26 files changed, 13664 insertions(+) create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni create mode 100644 SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr create mode 100644 SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c create mode 100644 SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h create mode 100644 SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf create mode 100644 SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni create mode 100644 SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr create mode 100644 SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c (limited to 'SecurityPkg/UserIdentification') diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c new file mode 100644 index 0000000000..ad1521040c --- /dev/null +++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.c @@ -0,0 +1,1422 @@ +/** @file + Password Credential Provider driver implementation. + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PwdCredentialProvider.h" + +CREDENTIAL_TABLE *mPwdTable = NULL; +PWD_PROVIDER_CALLBACK_INFO *mCallbackInfo = NULL; +PASSWORD_CREDENTIAL_INFO *mPwdInfoHandle = NULL; + +// +// Used for save password credential and form browser. +// Also used as provider identifier. +// +EFI_GUID mPwdCredentialGuid = PWD_CREDENTIAL_PROVIDER_GUID; + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + { 0xeba7fc2b, 0xa465, 0x4d96, { 0x85, 0xa9, 0xd2, 0xf6, 0x64, 0xdf, 0x9b, 0x45 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +EFI_USER_CREDENTIAL_PROTOCOL gPwdCredentialProviderDriver = { + PWD_CREDENTIAL_PROVIDER_GUID, + EFI_USER_CREDENTIAL_CLASS_PASSWORD, + CredentialEnroll, + CredentialForm, + CredentialTile, + CredentialTitle, + CredentialUser, + CredentialSelect, + CredentialDeselect, + CredentialDefault, + CredentialGetInfo, + CredentialGetNextInfo +}; + + +/** + Get string by string id from HII Interface. + + + @param[in] Id String ID to get the string from. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ) +{ + // + // Get the current string for the current Language. + // + return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL); +} + + +/** + Expand password table size. + +**/ +VOID +ExpandTableSize ( + VOID + ) +{ + CREDENTIAL_TABLE *NewTable; + UINTN Count; + + Count = mPwdTable->MaxCount + PASSWORD_TABLE_INC; + // + // Create new credential table. + // + NewTable = (CREDENTIAL_TABLE *) AllocateZeroPool ( + sizeof (CREDENTIAL_TABLE) + + (Count - 1) * sizeof (PASSWORD_INFO) + ); + ASSERT (NewTable != NULL); + + NewTable->MaxCount = Count; + NewTable->Count = mPwdTable->Count; + NewTable->ValidIndex = mPwdTable->ValidIndex; + // + // Copy old entries + // + CopyMem ( + &NewTable->UserInfo, + &mPwdTable->UserInfo, + mPwdTable->Count * sizeof (PASSWORD_INFO) + ); + FreePool (mPwdTable); + mPwdTable = NewTable; +} + + +/** + Add or delete info in table, and sync with NV variable. + + @param[in] Index The index of the password in table. The index begin from 1. + If index is found in table, delete the info, else add the + into to table. + @param[in] Info The new password info to add into table. + + @retval EFI_INVALID_PARAMETER Info is NULL when save the info. + @retval EFI_SUCCESS Modify the table successfully. + @retval Others Failed to modify the table. + +**/ +EFI_STATUS +ModifyTable ( + IN UINTN Index, + IN PASSWORD_INFO * Info OPTIONAL + ) +{ + EFI_STATUS Status; + + if (Index < mPwdTable->Count) { + // + // Delete the specified entry. + // + mPwdTable->Count--; + if (Index != mPwdTable->Count) { + CopyMem ( + &mPwdTable->UserInfo[Index], + &mPwdTable->UserInfo[mPwdTable->Count], + sizeof (PASSWORD_INFO) + ); + } + } else { + // + // Add a new entry. + // + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mPwdTable->Count >= mPwdTable->MaxCount) { + ExpandTableSize (); + } + + CopyMem ( + &mPwdTable->UserInfo[mPwdTable->Count], + Info, + sizeof (PASSWORD_INFO) + ); + mPwdTable->Count++; + } + + // + // Save the credential table. + // + Status = gRT->SetVariable ( + L"PwdCredential", + &mPwdCredentialGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + mPwdTable->Count * sizeof (PASSWORD_INFO), + &mPwdTable->UserInfo + ); + return Status; +} + + +/** + Create a password table. + + @retval EFI_SUCCESS Create a password table successfully. + @retval Others Failed to create a password. + +**/ +EFI_STATUS +InitCredentialTable ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 *Var; + UINTN VarSize; + + // + // Get Password credential data from NV variable. + // + VarSize = 0; + Var = NULL; + Status = gRT->GetVariable ( + L"PwdCredential", + &mPwdCredentialGuid, + NULL, + &VarSize, + Var + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Var = AllocateZeroPool (VarSize); + if (Var == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gRT->GetVariable ( + L"PwdCredential", + &mPwdCredentialGuid, + NULL, + &VarSize, + Var + ); + } + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + return Status; + } + + // + // Create the password credential table. + // + mPwdTable = AllocateZeroPool ( + sizeof (CREDENTIAL_TABLE) - sizeof (PASSWORD_INFO) + + PASSWORD_TABLE_INC * sizeof (PASSWORD_INFO) + + VarSize + ); + if (mPwdTable == NULL) { + FreePool (Var); + return EFI_OUT_OF_RESOURCES; + } + + mPwdTable->Count = VarSize / sizeof (PASSWORD_INFO); + mPwdTable->MaxCount = mPwdTable->Count + PASSWORD_TABLE_INC; + mPwdTable->ValidIndex = 0; + if (Var != NULL) { + CopyMem (mPwdTable->UserInfo, Var, VarSize); + FreePool (Var); + } + return EFI_SUCCESS; +} + + +/** + Hash the password to get credential. + + @param[in] Password Points to the input password. + @param[in] PasswordSize The size of password, in bytes. + @param[out] Credential Points to the hashed result. + + @retval TRUE Hash the password successfully. + @retval FALSE Failed to hash the password. + +**/ +BOOLEAN +GenerateCredential ( + IN CHAR16 *Password, + IN UINTN PasswordSize, + OUT UINT8 *Credential + ) +{ + BOOLEAN Status; + UINTN HashSize; + VOID *Hash; + + HashSize = Sha1GetContextSize (); + Hash = AllocatePool (HashSize); + ASSERT (Hash != NULL); + + Status = Sha1Init (Hash); + if (!Status) { + goto Done; + } + + Status = Sha1Update (Hash, Password, PasswordSize); + if (!Status) { + goto Done; + } + + Status = Sha1Final (Hash, Credential); + +Done: + FreePool (Hash); + return Status; +} + + +/** + Get password from user input. + + @param[in] FirstPwd If True, prompt to input the first password. + If False, prompt to input password again. + @param[out] Credential Points to the input password. + +**/ +VOID +GetPassword ( + IN BOOLEAN FirstPwd, + OUT CHAR8 *Credential + ) +{ + EFI_INPUT_KEY Key; + CHAR16 PasswordMask[CREDENTIAL_LEN + 1]; + CHAR16 Password[CREDENTIAL_LEN]; + UINTN PasswordLen; + CHAR16 *QuestionStr; + CHAR16 *LineStr; + + PasswordLen = 0; + while (TRUE) { + PasswordMask[PasswordLen] = L'_'; + PasswordMask[PasswordLen + 1] = L'\0'; + LineStr = GetStringById (STRING_TOKEN (STR_DRAW_A_LINE)); + if (FirstPwd) { + QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD)); + } else { + QuestionStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN)); + } + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + LineStr, + PasswordMask, + NULL + ); + FreePool (QuestionStr); + FreePool (LineStr); + + // + // Check key stroke + // + if (Key.ScanCode == SCAN_NULL) { + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + break; + } else if (Key.UnicodeChar == CHAR_BACKSPACE) { + if (PasswordLen > 0) { + PasswordLen--; + } + } else if ((Key.UnicodeChar == CHAR_NULL) || + (Key.UnicodeChar == CHAR_TAB) || + (Key.UnicodeChar == CHAR_LINEFEED)) { + continue; + } else { + Password[PasswordLen] = Key.UnicodeChar; + PasswordMask[PasswordLen] = L'*'; + PasswordLen++; + if (PasswordLen == CREDENTIAL_LEN) { + break; + } + } + } + } + + PasswordLen = PasswordLen * sizeof (CHAR16); + GenerateCredential (Password, PasswordLen, (UINT8 *)Credential); +} + +/** + Check whether the password can be found on this provider. + + @param[in] Password The password to be found. + + @retval EFI_SUCCESS Found password sucessfully. + @retval EFI_NOT_FOUND Fail to find the password. + +**/ +EFI_STATUS +CheckPassword ( + IN CHAR8 *Password + ) +{ + UINTN Index; + CHAR8 *Pwd; + + // + // Check password credential. + // + mPwdTable->ValidIndex = 0; + for (Index = 0; Index < mPwdTable->Count; Index++) { + Pwd = mPwdTable->UserInfo[Index].Password; + if (CompareMem (Pwd, Password, CREDENTIAL_LEN) == 0) { + mPwdTable->ValidIndex = Index + 1; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Find a user infomation record by the information record type. + + This function searches all user information records of User from beginning + until either the information is found, or there are no more user infomation + records. A match occurs when a Info.InfoType field matches the user information + record type. + + @param[in] User Points to the user profile record to search. + @param[in] InfoType The infomation type to be searched. + @param[out] Info Points to the user info found, the caller is responsible + to free. + + @retval EFI_SUCCESS Find the user information successfully. + @retval Others Fail to find the user information. + +**/ +EFI_STATUS +FindUserInfoByType ( + IN EFI_USER_PROFILE_HANDLE User, + IN UINT8 InfoType, + OUT EFI_USER_INFO **Info + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN UserInfoSize; + EFI_USER_INFO_HANDLE UserInfoHandle; + EFI_USER_MANAGER_PROTOCOL *UserManager; + + // + // Find user information by information type. + // + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol ( + &gEfiUserManagerProtocolGuid, + NULL, + (VOID **) &UserManager + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Get each user information. + // + + UserInfoHandle = NULL; + UserInfo = NULL; + UserInfoSize = 0; + while (TRUE) { + Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle); + if (EFI_ERROR (Status)) { + break; + } + // + // Get information. + // + Status = UserManager->GetInfo ( + UserManager, + User, + UserInfoHandle, + UserInfo, + &UserInfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + if (UserInfo != NULL) { + FreePool (UserInfo); + } + UserInfo = AllocateZeroPool (UserInfoSize); + if (UserInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = UserManager->GetInfo ( + UserManager, + User, + UserInfoHandle, + UserInfo, + &UserInfoSize + ); + } + if (EFI_ERROR (Status)) { + break; + } + + ASSERT (UserInfo != NULL); + if (UserInfo->InfoType == InfoType) { + *Info = UserInfo; + return EFI_SUCCESS; + } + } + + if (UserInfo != NULL) { + FreePool (UserInfo); + } + return Status; +} + + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by the + callback. + +**/ +EFI_STATUS +EFIAPI +CredentialDriverCallback ( + 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 + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + CHAR8 Password[CREDENTIAL_LEN]; + CHAR16 *PromptStr; + + if (Action == EFI_BROWSER_ACTION_CHANGING) { + if (QuestionId == KEY_GET_PASSWORD) { + // + // Get and check password. + // + GetPassword (TRUE, Password); + Status = CheckPassword (Password); + if (EFI_ERROR (Status)) { + PromptStr = GetStringById (STRING_TOKEN (STR_PASSWORD_INCORRECT)); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + PromptStr, + L"", + NULL + ); + FreePool (PromptStr); + return Status; + } + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + return EFI_SUCCESS; + } + + // + // All other action return unsupported. + // + return EFI_UNSUPPORTED; +} + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + +/** + This function initialize the data mainly used in form browser. + + @retval EFI_SUCCESS Initialize form data successfully. + @retval Others Fail to Initialize form data. + +**/ +EFI_STATUS +InitFormBrowser ( + VOID + ) +{ + EFI_STATUS Status; + PWD_PROVIDER_CALLBACK_INFO *CallbackInfo; + + // + // Initialize driver private data. + // + CallbackInfo = AllocateZeroPool (sizeof (PWD_PROVIDER_CALLBACK_INFO)); + if (CallbackInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CallbackInfo->Signature = PWD_PROVIDER_SIGNATURE; + CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig; + CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig; + CallbackInfo->ConfigAccess.Callback = CredentialDriverCallback; + CallbackInfo->DriverHandle = NULL; + + // + // Install Device Path Protocol and Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &CallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &CallbackInfo->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish HII data. + // + CallbackInfo->HiiHandle = HiiAddPackages ( + &mPwdCredentialGuid, + CallbackInfo->DriverHandle, + PwdCredentialProviderStrings, + PwdCredentialProviderVfrBin, + NULL + ); + if (CallbackInfo->HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + mCallbackInfo = CallbackInfo; + + return Status; +} + + +/** + Enroll a user on a credential provider. + + This function enrolls and deletes a user profile using this credential provider. + If a user profile is successfully enrolled, it calls the User Manager Protocol + function Notify() to notify the user manager driver that credential information + has changed. If an enrolled user does exist, delete the user on the credential + provider. + + @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the + user profile handle. Either the user profile cannot enroll + on any user profile or cannot enroll on a user profile + other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in + the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device + error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. + +**/ +EFI_STATUS +EFIAPI +CredentialEnroll ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + UINTN Index; + PASSWORD_INFO PwdInfo; + EFI_USER_INFO *UserInfo; + CHAR8 Password[CREDENTIAL_LEN]; + EFI_INPUT_KEY Key; + EFI_USER_MANAGER_PROTOCOL *UserManager; + UINT8 *UserId; + UINT8 *NewUserId; + CHAR16 *QuestionStr; + CHAR16 *PromptStr; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol ( + &gEfiUserManagerProtocolGuid, + NULL, + (VOID **) &UserManager + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Get User Identifier. + // + UserInfo = NULL; + Status = FindUserInfoByType ( + User, + EFI_USER_INFO_IDENTIFIER_RECORD, + &UserInfo + ); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // If User exists in mPwdTable, delete User. + // + for (Index = 0; Index < mPwdTable->Count; Index++) { + UserId = (UINT8 *) &mPwdTable->UserInfo[Index].UserId; + NewUserId = (UINT8 *) (UserInfo + 1); + if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + // + // Delete the existing password. + // + FreePool (UserInfo); + return ModifyTable (Index, NULL); + } + } + + // + // The User doesn't exist in mPwdTable; Enroll the new User. + // + while (TRUE) { + // + // Input password. + // + GetPassword (TRUE, PwdInfo.Password); + + // + // Input password again. + // + GetPassword (FALSE, Password); + + // + // Compare the two password consistency. + // + if (CompareMem (PwdInfo.Password, Password, CREDENTIAL_LEN) == 0) { + break; + } + + QuestionStr = GetStringById (STRING_TOKEN (STR_PASSWORD_MISMATCH)); + PromptStr = GetStringById (STRING_TOKEN (STR_INPUT_PASSWORD_AGAIN)); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + FreePool (QuestionStr); + FreePool (PromptStr); + } + + CopyMem ( + PwdInfo.UserId, + (UINT8 *) (UserInfo + 1), + sizeof (EFI_USER_INFO_IDENTIFIER) + ); + FreePool (UserInfo); + + // + // Save the new added entry. + // + Status = ModifyTable (mPwdTable->Count, &PwdInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify the user manager driver that credential information has changed. + // + UserManager->Notify (UserManager, mCallbackInfo->DriverHandle); + + return EFI_SUCCESS; +} + + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the + user during user identification. The form is the first enabled form in the form-set + class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this + function should return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialForm ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ) +{ + if ((This == NULL) || (Hii == NULL) || + (FormSetId == NULL) || (FormId == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *Hii = mCallbackInfo->HiiHandle; + *FormId = FORMID_GET_PASSWORD_FORM; + CopyGuid (FormSetId, &mPwdCredentialGuid); + + return EFI_SUCCESS; +} + + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap that is less than or equal to the number + of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND + is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no + bitmap information will be returned. On exit, points to the + width of the bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no + bitmap information will be returned. On exit, points to the + height of the bitmap returned + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTile ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ) +{ + if ((This == NULL) || (Hii == NULL) || (Image == NULL)) { + return EFI_INVALID_PARAMETER; + } + return EFI_NOT_FOUND; +} + + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no + such string exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTitle ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ) +{ + if ((This == NULL) || (Hii == NULL) || (String == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Set Hii handle and String ID. + // + *Hii = mCallbackInfo->HiiHandle; + *String = STRING_TOKEN (STR_CREDENTIAL_TITLE); + + return EFI_SUCCESS; +} + + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential + provider. This function is called after the credential-related information has been + submitted on a form, OR after a call to Default() has returned that this credential is + ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being + considered by the user identity manager. If NULL, then no user + profile is currently under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be + found in user profile database + +**/ +EFI_STATUS +EFIAPI +CredentialUser ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_USER_INFO *UserInfo; + UINT8 *UserId; + UINT8 *NewUserId; + CHAR8 *Pwd; + CHAR8 *NewPwd; + + if ((This == NULL) || (Identifier == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (mPwdTable->ValidIndex == 0) { + // + // No password input, or the input password doesn't match + // anyone in PwdTable. + // + return EFI_NOT_READY; + } + + if (User == NULL) { + // + // Return the user ID whose password matches the input password. + // + CopyMem ( + Identifier, + &mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].UserId, + sizeof (EFI_USER_INFO_IDENTIFIER) + ); + return EFI_SUCCESS; + } + + // + // Get the User's ID. + // + Status = FindUserInfoByType ( + User, + EFI_USER_INFO_IDENTIFIER_RECORD, + &UserInfo + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Check whether the input password matches one in PwdTable. + // + for (Index = 0; Index < mPwdTable->Count; Index++) { + UserId = (UINT8 *) &mPwdTable->UserInfo[Index].UserId; + NewUserId = (UINT8 *) (UserInfo + 1); + if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + Pwd = mPwdTable->UserInfo[Index].Password; + NewPwd = mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].Password; + if (CompareMem (Pwd, NewPwd, CREDENTIAL_LEN) == 0) { + CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER)); + FreePool (UserInfo); + return EFI_SUCCESS; + } + } + } + + // + // The User's password doesn't match the input password. + // Return the user ID whose password matches the input password. + // + CopyMem ( + Identifier, + &mPwdTable->UserInfo[mPwdTable->ValidIndex - 1].UserId, + sizeof (EFI_USER_INFO_IDENTIFIER) + ); + FreePool (UserInfo); + return EFI_SUCCESS; +} + + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If + AutoLogon returns FALSE, then the user interface will be constructed by the User + Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities + after the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialSelect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ) +{ + if ((This == NULL) || (AutoLogon == NULL)) { + return EFI_INVALID_PARAMETER; + } + *AutoLogon = 0; + + return EFI_SUCCESS; +} + + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. + +**/ +EFI_STATUS +EFIAPI +CredentialDeselect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This + ) +{ + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be used + by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialDefault ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ) +{ + if ((This == NULL) || (AutoLogon == NULL)) { + return EFI_INVALID_PARAMETER; + } + *AutoLogon = 0; + + return EFI_SUCCESS; +} + + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On + exit, holds the user information. If the buffer is too small + to hold the information, then EFI_BUFFER_TOO_SMALL is returned + and InfoSize is updated to contain the number of bytes actually + required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the + size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the + user information. The size required is returned in *InfoSize. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + +**/ +EFI_STATUS +EFIAPI +CredentialGetInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ) +{ + EFI_USER_INFO *CredentialInfo; + UINTN Index; + + if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((UserInfo == NULL) || (mPwdInfoHandle == NULL)) { + return EFI_NOT_FOUND; + } + + // + // Find information handle in credential info table. + // + for (Index = 0; Index < mPwdInfoHandle->Count; Index++) { + CredentialInfo = mPwdInfoHandle->Info[Index]; + if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) { + // + // The handle is found, copy the user info. + // + if (CredentialInfo->InfoSize > *InfoSize) { + *InfoSize = CredentialInfo->InfoSize; + return EFI_BUFFER_TOO_SMALL; + } + CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Enumerate all of the user informations on the credential provider. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] UserInfo On entry, points to the previous user information handle or NULL + to start enumeration. On exit, points to the next user information + handle or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialGetNextInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ) +{ + EFI_USER_INFO *Info; + CHAR16 *ProvNameStr; + UINTN InfoLen; + UINTN Index; + UINTN ProvStrLen; + + if ((This == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (mPwdInfoHandle == NULL) { + // + // Initilized user info table. There are 4 user info records in the table. + // + InfoLen = sizeof (PASSWORD_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *); + mPwdInfoHandle = AllocateZeroPool (InfoLen); + if (mPwdInfoHandle == NULL) { + *UserInfo = NULL; + return EFI_NOT_FOUND; + } + + // + // The first information, Credential Provider info. + // + InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID); + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mPwdCredentialGuid); + CopyGuid ((EFI_GUID *)(Info + 1), &mPwdCredentialGuid); + + mPwdInfoHandle->Info[0] = Info; + mPwdInfoHandle->Count++; + + // + // The second information, Credential Provider name info. + // + ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME)); + ProvStrLen = StrSize (ProvNameStr); + InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen; + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mPwdCredentialGuid); + CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen); + FreePool (ProvNameStr); + + mPwdInfoHandle->Info[1] = Info; + mPwdInfoHandle->Count++; + + // + // The third information, Credential Provider type info. + // + InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID); + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mPwdCredentialGuid); + CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassPasswordGuid); + + mPwdInfoHandle->Info[2] = Info; + mPwdInfoHandle->Count++; + + // + // The fourth information, Credential Provider type name info. + // + ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME)); + ProvStrLen = StrSize (ProvNameStr); + InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen; + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mPwdCredentialGuid); + CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen); + FreePool (ProvNameStr); + + mPwdInfoHandle->Info[3] = Info; + mPwdInfoHandle->Count++; + } + + if (*UserInfo == NULL) { + // + // Return the first info handle. + // + *UserInfo = (EFI_USER_INFO_HANDLE) mPwdInfoHandle->Info[0]; + return EFI_SUCCESS; + } + + // + // Find information handle in credential info table. + // + for (Index = 0; Index < mPwdInfoHandle->Count; Index++) { + Info = mPwdInfoHandle->Info[Index]; + if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) { + // + // The handle is found, get the next one. + // + if (Index == mPwdInfoHandle->Count - 1) { + // + // Already last one. + // + *UserInfo = NULL; + return EFI_NOT_FOUND; + } + + Index++; + *UserInfo = (EFI_USER_INFO_HANDLE)mPwdInfoHandle->Info[Index]; + return EFI_SUCCESS; + } + } + + *UserInfo = NULL; + return EFI_NOT_FOUND; +} + + +/** + Main entry for this driver. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +PasswordProviderInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Init credential table. + // + Status = InitCredentialTable (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Init Form Browser. + // + Status = InitFormBrowser (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install protocol interfaces for the password credential provider. + // + Status = gBS->InstallProtocolInterface ( + &mCallbackInfo->DriverHandle, + &gEfiUserCredentialProtocolGuid, + EFI_NATIVE_INTERFACE, + &gPwdCredentialProviderDriver + ); + return Status; +} diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h new file mode 100644 index 0000000000..9b5e7768ba --- /dev/null +++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProvider.h @@ -0,0 +1,354 @@ +/** @file + Password Credential Provider driver header file. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PASSWORD_CREDENTIAL_PROVIDER_H_ +#define _PASSWORD_CREDENTIAL_PROVIDER_H_ + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PwdCredentialProviderData.h" + +extern UINT8 PwdCredentialProviderStrings[]; +extern UINT8 PwdCredentialProviderVfrBin[]; + +#define PASSWORD_TABLE_INC 16 +#define CREDENTIAL_LEN 20 + +// +// Password credential information. +// +typedef struct { + EFI_USER_INFO_IDENTIFIER UserId; + CHAR8 Password[CREDENTIAL_LEN]; +} PASSWORD_INFO; + +// +// Password credential table. +// +typedef struct { + UINTN Count; + UINTN MaxCount; + UINTN ValidIndex; + PASSWORD_INFO UserInfo[1]; +} CREDENTIAL_TABLE; + +// +// The user information on the password provider. +// +typedef struct { + UINTN Count; + EFI_USER_INFO *Info[1]; +} PASSWORD_CREDENTIAL_INFO; + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#define PWD_PROVIDER_SIGNATURE SIGNATURE_32 ('P', 'W', 'D', 'P') + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + // + // Produced protocol. + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} PWD_PROVIDER_CALLBACK_INFO; + + +/** + Enroll a user on a credential provider. + + This function enrolls and deletes a user profile using this credential provider. + If a user profile is successfully enrolled, it calls the User Manager Protocol + function Notify() to notify the user manager driver that credential information + has changed. If an enrolled user does exist, delete the user on the credential + provider. + + @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the + user profile handle. Either the user profile cannot enroll + on any user profile or cannot enroll on a user profile + other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in + the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device + error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. + +**/ +EFI_STATUS +EFIAPI +CredentialEnroll ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the + user during user identification. The form is the first enabled form in the form-set + class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this + function should return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialForm ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ); + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap which is less than or equal to the number + of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND + is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no + bitmap information will be returned. On exit, points to the + width of the bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no + bitmap information will be returned. On exit, points to the + height of the bitmap returned + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTile ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ); + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no + such string exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTitle ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ); + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential + provider. This function is called after the credential-related information has been + submitted on a form OR after a call to Default() has returned that this credential is + ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being + considered by the user identity manager. If NULL, then no user + profile is currently under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be + found in user profile database + +**/ +EFI_STATUS +EFIAPI +CredentialUser ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ); + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If + AutoLogon returns FALSE, then the user interface will be constructed by the User + Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities + after the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialSelect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. + +**/ +EFI_STATUS +EFIAPI +CredentialDeselect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This + ); + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be used + by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialDefault ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On + exit, holds the user information. If the buffer is too small + to hold the information, then EFI_BUFFER_TOO_SMALL is returned + and InfoSize is updated to contain the number of bytes actually + required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the + size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the + user information. The size required is returned in *InfoSize. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + +**/ +EFI_STATUS +EFIAPI +CredentialGetInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + + +/** + Enumerate all of the user informations on the credential provider. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] UserInfo On entry, points to the previous user information handle or NULL + to start enumeration. On exit, points to the next user information + handle or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialGetNextInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +#endif diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h new file mode 100644 index 0000000000..ffe0adea20 --- /dev/null +++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderData.h @@ -0,0 +1,33 @@ +/** @file + Data structure used by the Password Credential Provider driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PWD_CREDENTIAL_PROVIDER_DATA_H_ +#define _PWD_CREDENTIAL_PROVIDER_DATA_H_ + +#define PWD_CREDENTIAL_PROVIDER_GUID \ + { \ + 0x78b9ec8b, 0xc000, 0x46c5, { 0xac, 0x93, 0x24, 0xa0, 0xc1, 0xbb, 0x0, 0xce } \ + } + +// +// Forms definition +// +#define FORMID_GET_PASSWORD_FORM 1 + +// +// Key defination +// +#define KEY_GET_PASSWORD 0x1000 + +#endif diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf new file mode 100644 index 0000000000..0ffc24e076 --- /dev/null +++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderDxe.inf @@ -0,0 +1,53 @@ +## @file +# Component description file for Password Credential Provider. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = PwdCredentialProvider + FILE_GUID = D6C589EA-DD29-49ef-97F6-1A9FE19A04E0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PasswordProviderInit + +[Sources] + PwdCredentialProvider.c + PwdCredentialProvider.h + PwdCredentialProviderData.h + PwdCredentialProviderVfr.Vfr + PwdCredentialProviderStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + DebugLib + HiiLib + UefiLib + BaseCryptLib + +[Guids] + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiUserCredentialClassPasswordGuid ## CONSUMES ## Guid + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiHiiConfigAccessProtocolGuid + gEfiUserCredentialProtocolGuid + gEfiUserManagerProtocolGuid \ No newline at end of file diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni new file mode 100644 index 0000000000..48573b6e8e Binary files /dev/null and b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderStrings.uni differ diff --git a/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr new file mode 100644 index 0000000000..69f4be8c23 --- /dev/null +++ b/SecurityPkg/UserIdentification/PwdCredentialProviderDxe/PwdCredentialProviderVfr.Vfr @@ -0,0 +1,35 @@ +/** @file + Password Credential Provider formset. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "PwdCredentialProviderData.h" + +formset + guid = PWD_CREDENTIAL_PROVIDER_GUID, + title = STRING_TOKEN(STR_CREDENTIAL_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = PWD_CREDENTIAL_PROVIDER_GUID, + + form formid = FORMID_GET_PASSWORD_FORM, + title = STRING_TOKEN(STR_FORM_TITLE); + + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_INPUT_PASSWORD), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_GET_PASSWORD; + + endform; + +endformset; \ No newline at end of file diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c new file mode 100644 index 0000000000..6c22bfb2bb --- /dev/null +++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.c @@ -0,0 +1,1407 @@ +/** @file + Usb Credential Provider driver implemenetation. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UsbCredentialProvider.h" + +CREDENTIAL_TABLE *mUsbTable = NULL; +USB_PROVIDER_CALLBACK_INFO *mCallbackInfo = NULL; +USB_CREDENTIAL_INFO *mUsbInfoHandle = NULL; + +// +// Used for save password credential and form browser +// And used as provider identifier +// +EFI_GUID mUsbCredentialGuid = USB_CREDENTIAL_PROVIDER_GUID; + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + { 0x9463f883, 0x48f6, 0x4a7a, { 0x97, 0x2d, 0x9f, 0x8f, 0x38, 0xf2, 0xdd, 0x91 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +EFI_USER_CREDENTIAL_PROTOCOL gUsbCredentialProviderDriver = { + USB_CREDENTIAL_PROVIDER_GUID, + EFI_USER_CREDENTIAL_CLASS_SECURE_CARD, + CredentialEnroll, + CredentialForm, + CredentialTile, + CredentialTitle, + CredentialUser, + CredentialSelect, + CredentialDeselect, + CredentialDefault, + CredentialGetInfo, + CredentialGetNextInfo +}; + + +/** + Get string by string id from HII Interface. + + + @param[in] Id String ID to get the string from. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ) +{ + // + // Get the current string for the current Language + // + return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL); +} + + +/** + Expand password table size. + +**/ +VOID +ExpandTableSize ( + VOID + ) +{ + CREDENTIAL_TABLE *NewTable; + UINTN Count; + + Count = mUsbTable->MaxCount + USB_TABLE_INC; + // + // Create new credential table. + // + NewTable = AllocateZeroPool ( + sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) + + Count * sizeof (USB_INFO) + ); + ASSERT (NewTable != NULL); + + NewTable->MaxCount = Count; + NewTable->Count = mUsbTable->Count; + + // + // Copy old entries. + // + CopyMem ( + &NewTable->UserInfo, + &mUsbTable->UserInfo, + mUsbTable->Count * sizeof (USB_INFO) + ); + FreePool (mUsbTable); + mUsbTable = NewTable; +} + + +/** + Add or delete info in table, and sync with NV variable. + + @param[in] Index The index of the password in table. The index begin from 1. + If index is found in table, delete the info, else add the + into to table. + @param[in] Info The new password info to add into table. + + @retval EFI_INVALID_PARAMETER Info is NULL when save the info. + @retval EFI_SUCCESS Modify the table successfully. + @retval Others Failed to modify the table. + +**/ +EFI_STATUS +ModifyTable ( + IN UINTN Index, + IN USB_INFO * Info OPTIONAL + ) +{ + EFI_STATUS Status; + + if (Index < mUsbTable->Count) { + // + // Delete the specified entry + // + mUsbTable->Count--; + if (Index != mUsbTable->Count) { + CopyMem ( + &mUsbTable->UserInfo[Index], + &mUsbTable->UserInfo[mUsbTable->Count], + sizeof (USB_INFO) + ); + } + } else { + // + // Add a new entry + // + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mUsbTable->Count >= mUsbTable->MaxCount) { + ExpandTableSize (); + } + + CopyMem ( + &mUsbTable->UserInfo[mUsbTable->Count], + Info, + sizeof (USB_INFO) + ); + mUsbTable->Count++; + } + + // + // Save the credential table. + // + Status = gRT->SetVariable ( + L"UsbCredential", + &mUsbCredentialGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + mUsbTable->Count * sizeof (USB_INFO), + &mUsbTable->UserInfo + ); + return Status; +} + + +/** + Create a credential table + + @retval EFI_SUCCESS Create a credential table successfully. + @retval Others Failed to create a password. + +**/ +EFI_STATUS +InitCredentialTable ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 *Var; + UINTN VarSize; + + // + // Get Usb credential data from NV variable. + // + VarSize = 0; + Var = NULL; + Status = gRT->GetVariable ( + L"UsbCredential", + &mUsbCredentialGuid, + NULL, + &VarSize, + Var + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Var = AllocateZeroPool (VarSize); + if (Var == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = gRT->GetVariable ( + L"UsbCredential", + &mUsbCredentialGuid, + NULL, + &VarSize, + Var + ); + } + if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) { + return Status; + } + + // + // Init Usb credential table. + // + mUsbTable = AllocateZeroPool ( + sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) + + USB_TABLE_INC * sizeof (USB_INFO) + + VarSize + ); + if (mUsbTable == NULL) { + FreePool (Var); + return EFI_OUT_OF_RESOURCES; + } + + mUsbTable->Count = VarSize / sizeof (USB_INFO); + mUsbTable->MaxCount = mUsbTable->Count + USB_TABLE_INC; + if (Var != NULL) { + CopyMem (mUsbTable->UserInfo, Var, VarSize); + FreePool (Var); + } + return EFI_SUCCESS; +} + + +/** + Read the specified file by FileName in the Usb key and return the file size in BufferSize + and file content in Buffer. + Note: the caller is responsible to free the buffer memory. + + @param FileName File to read. + @param Buffer Returned with data read from the file. + @param BufferSize Size of the data buffer. + + @retval EFI_SUCCESS The command completed successfully. + @retval EFI_OUT_OF_RESOURCES Resource allocation failed. + @retval EFI_NOT_FOUND File not found. + @retval EFI_DEVICE_ERROR Device I/O error. + +**/ +EFI_STATUS +GetFileData ( + IN CHAR16 *FileName, + OUT VOID **Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN HandleCount; + UINTN ScratchBufferSize; + EFI_HANDLE *HandleBuffer; + EFI_FILE *RootFs; + EFI_FILE *FileHandle; + EFI_FILE_INFO *FileInfo; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + + FileInfo = NULL; + FileHandle = NULL; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Can not Locate SimpleFileSystemProtocol\n")); + goto Done; + } + + // + // Find and open the file in removable media disk. + // + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (BlkIo->Media->RemovableMedia) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiSimpleFileSystemProtocolGuid, + (VOID **) &SimpleFileSystem + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status = SimpleFileSystem->OpenVolume ( + SimpleFileSystem, + &RootFs + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status = RootFs->Open ( + RootFs, + &FileHandle, + FileName, + EFI_FILE_MODE_READ, + 0 + ); + if (!EFI_ERROR (Status)) { + break; + } + } + } + + FreePool (HandleBuffer); + + if (Index >= HandleCount) { + DEBUG ((DEBUG_ERROR, "Can not found the token file!\n")); + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Figure out how big the file is. + // + ScratchBufferSize = 0; + Status = FileHandle->GetInfo ( + FileHandle, + &gEfiFileInfoGuid, + &ScratchBufferSize, + NULL + ); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + DEBUG ((DEBUG_ERROR, "Can not obtain file size info!\n")); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + FileInfo = AllocateZeroPool (ScratchBufferSize); + if (FileInfo == NULL) { + DEBUG ((DEBUG_ERROR, "Can not allocate enough memory for the token file!\n")); + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = FileHandle->GetInfo ( + FileHandle, + &gEfiFileInfoGuid, + &ScratchBufferSize, + FileInfo + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Can not obtain file info from the token file!\n")); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Allocate a buffer for the file. + // + *BufferSize = (UINT32) FileInfo->FileSize; + *Buffer = AllocateZeroPool (*BufferSize); + if (*Buffer == NULL) { + DEBUG ((DEBUG_ERROR, "Can not allocate a buffer for the file!\n")); + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Load file into the allocated memory. + // + Status = FileHandle->Read (FileHandle, BufferSize, *Buffer); + if (EFI_ERROR (Status)) { + FreePool (*Buffer); + DEBUG ((DEBUG_ERROR, "Can not read the token file!\n")); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + // + // Close file. + // + Status = FileHandle->Close (FileHandle); + if (EFI_ERROR (Status)) { + FreePool (*Buffer); + DEBUG ((DEBUG_ERROR, "Can not close the token file !\n")); + Status = EFI_DEVICE_ERROR; + } + +Done: + + if (FileInfo != NULL) { + FreePool (FileInfo); + } + + return Status; +} + + +/** + Hash the data to get credential. + + @param[in] Buffer Points to the data buffer + @param[in] BufferSize The size of data in buffer, in bytes. + @param[out] Credential Points to the hashed result + + @retval TRUE Hash the data successfully. + @retval FALSE Failed to hash the data. + +**/ +BOOLEAN +GenerateCredential ( + IN UINT8 *Buffer, + IN UINTN BufferSize, + OUT UINT8 *Credential + ) +{ + BOOLEAN Status; + UINTN HashSize; + VOID *Hash; + + HashSize = Sha1GetContextSize (); + Hash = AllocatePool (HashSize); + ASSERT (Hash != NULL); + + Status = Sha1Init (Hash); + if (!Status) { + goto Done; + } + + Status = Sha1Update (Hash, Buffer, BufferSize); + if (!Status) { + goto Done; + } + + Status = Sha1Final (Hash, Credential); + +Done: + FreePool (Hash); + return Status; +} + + +/** + Read the token file, and default the Token is saved at the begining of the file. + + @param[out] Token Token read from a Token file. + + @retval EFI_SUCCESS Read a Token successfully. + @retval Others Fails to read a Token. + +**/ +EFI_STATUS +GetToken ( + OUT UINT8 *Token + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufSize; + CHAR16 *TokenFile; + + BufSize = 0; + Buffer = NULL; + TokenFile = FixedPcdGetPtr (PcdFixedUsbCredentialProviderTokenFileName); + Status = GetFileData (TokenFile, (VOID *)&Buffer, &BufSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Read file %s from USB error! Status=(%r)\n", TokenFile, Status)); + return Status; + } + + if (!GenerateCredential (Buffer, BufSize, Token)) { + DEBUG ((DEBUG_ERROR, "Generate credential from read data failed!\n")); + FreePool (Buffer); + return EFI_SECURITY_VIOLATION; + } + + FreePool (Buffer); + return EFI_SUCCESS; +} + + +/** + Find a user infomation record by the information record type. + + This function searches all user information records of User from beginning + until either the information is found or there are no more user infomation + record. A match occurs when a Info.InfoType field matches the user information + record type. + + @param[in] User Points to the user profile record to search. + @param[in] InfoType The infomation type to be searched. + @param[out] Info Points to the user info found, the caller is responsible + to free. + + @retval EFI_SUCCESS Find the user information successfully. + @retval Others Fail to find the user information. + +**/ +EFI_STATUS +FindUserInfoByType ( + IN EFI_USER_PROFILE_HANDLE User, + IN UINT8 InfoType, + OUT EFI_USER_INFO **Info + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN UserInfoSize; + EFI_USER_INFO_HANDLE UserInfoHandle; + EFI_USER_MANAGER_PROTOCOL *UserManager; + + // + // Find user information by information type. + // + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol ( + &gEfiUserManagerProtocolGuid, + NULL, + (VOID **) &UserManager + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Get each user information. + // + + UserInfoHandle = NULL; + UserInfo = NULL; + UserInfoSize = 0; + while (TRUE) { + Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle); + if (EFI_ERROR (Status)) { + break; + } + // + // Get information. + // + Status = UserManager->GetInfo ( + UserManager, + User, + UserInfoHandle, + UserInfo, + &UserInfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + if (UserInfo != NULL) { + FreePool (UserInfo); + } + UserInfo = AllocateZeroPool (UserInfoSize); + if (UserInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = UserManager->GetInfo ( + UserManager, + User, + UserInfoHandle, + UserInfo, + &UserInfoSize + ); + } + if (EFI_ERROR (Status)) { + break; + } + + ASSERT (UserInfo != NULL); + if (UserInfo->InfoType == InfoType) { + *Info = UserInfo; + return EFI_SUCCESS; + } + } + + if (UserInfo != NULL) { + FreePool (UserInfo); + } + return Status; +} + + +/** + This function initialize the data mainly used in form browser. + + @retval EFI_SUCCESS Initialize form data successfully. + @retval Others Fail to Initialize form data. + +**/ +EFI_STATUS +InitFormBrowser ( + VOID + ) +{ + USB_PROVIDER_CALLBACK_INFO *CallbackInfo; + + // + // Initialize driver private data. + // + CallbackInfo = AllocateZeroPool (sizeof (USB_PROVIDER_CALLBACK_INFO)); + if (CallbackInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CallbackInfo->DriverHandle = NULL; + + // + // Publish HII data. + // + CallbackInfo->HiiHandle = HiiAddPackages ( + &mUsbCredentialGuid, + CallbackInfo->DriverHandle, + UsbCredentialProviderStrings, + NULL + ); + if (CallbackInfo->HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + mCallbackInfo = CallbackInfo; + + return EFI_SUCCESS; +} + + +/** + Enroll a user on a credential provider. + + This function enrolls and deletes a user profile using this credential provider. + If a user profile is successfully enrolled, it calls the User Manager Protocol + function Notify() to notify the user manager driver that credential information + has changed. If an enrolled user does exist, delete the user on the credential + provider. + + @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the + user profile handle. Either the user profile cannot enroll + on any user profile or cannot enroll on a user profile + other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in + the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device + error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. + +**/ +EFI_STATUS +EFIAPI +CredentialEnroll ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + UINTN Index; + USB_INFO UsbInfo; + EFI_USER_INFO *UserInfo; + EFI_INPUT_KEY Key; + EFI_USER_MANAGER_PROTOCOL *UserManager; + UINT8 *UserId; + UINT8 *NewUserId; + EFI_TPL OldTpl; + CHAR16 *QuestionStr; + CHAR16 *PromptStr; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->LocateProtocol ( + &gEfiUserManagerProtocolGuid, + NULL, + (VOID **) &UserManager + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Get User Identifier + // + UserInfo = NULL; + Status = FindUserInfoByType ( + User, + EFI_USER_INFO_IDENTIFIER_RECORD, + &UserInfo + ); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // If User exists in mUsbTable, delete User. + // + for (Index = 0; Index < mUsbTable->Count; Index++) { + UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId; + NewUserId = (UINT8 *) (UserInfo + 1); + if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + // + // Delete the exist Token. + // + FreePool (UserInfo); + return ModifyTable (Index, NULL); + } + } + + // + // Get Token and User ID to UsbInfo. + // + Status = GetToken (UsbInfo.Token); + if (EFI_ERROR (Status)) { + QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR)); + PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN)); + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + gBS->RestoreTPL (TPL_APPLICATION); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + gBS->RaiseTPL (OldTpl); + FreePool (QuestionStr); + FreePool (PromptStr); + FreePool (UserInfo); + return Status; + } + CopyMem ( + UsbInfo.UserId, + (UINT8 *) (UserInfo + 1), + sizeof (EFI_USER_INFO_IDENTIFIER) + ); + FreePool (UserInfo); + + // + // Save the new added entry. + // + Status = ModifyTable (mUsbTable->Count, &UsbInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify the user manager driver that credential information has changed. + // + UserManager->Notify (UserManager, mCallbackInfo->DriverHandle); + + return EFI_SUCCESS; +} + + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the + user during user identification. The form is the first enabled form in the form-set + class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this + function should return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialForm ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ) +{ + if ((This == NULL) || (Hii == NULL) || + (FormSetId == NULL) || (FormId == NULL)) { + return EFI_INVALID_PARAMETER; + } + return EFI_NOT_FOUND; +} + + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap which is less than or equal to the number + of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND + is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no + bitmap information will be returned. On exit, points to the + width of the bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no + bitmap information will be returned. On exit, points to the + height of the bitmap returned. + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTile ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ) +{ + if ((This == NULL) || (Hii == NULL) || (Image == NULL)) { + return EFI_INVALID_PARAMETER; + } + return EFI_NOT_FOUND; +} + + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no + such string exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTitle ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ) +{ + if ((This == NULL) || (Hii == NULL) || (String == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // Set Hii handle and String ID. + // + *Hii = mCallbackInfo->HiiHandle; + *String = STRING_TOKEN (STR_CREDENTIAL_TITLE); + + return EFI_SUCCESS; +} + + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential + provider. This function is called after the credential-related information has been + submitted on a form OR after a call to Default() has returned that this credential is + ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being + considered by the user identity manager. If NULL, then no user + profile is currently under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be + found in user profile database. + +**/ +EFI_STATUS +EFIAPI +CredentialUser ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_USER_INFO *UserInfo; + UINT8 *UserId; + UINT8 *NewUserId; + UINT8 *UserToken; + UINT8 ReadToken[HASHED_CREDENTIAL_LEN]; + EFI_INPUT_KEY Key; + EFI_TPL OldTpl; + CHAR16 *QuestionStr; + CHAR16 *PromptStr; + + if ((This == NULL) || (Identifier == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (User == NULL) { + // + // Verify the auto logon user, get user id by matched token. + // + if (mUsbTable->Count == 0) { + return EFI_NOT_READY; + } + + // + // No user selected, get token first and verify the user existed in user database. + // + Status = GetToken (ReadToken); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + for (Index = 0; Index < mUsbTable->Count; Index++) { + // + // find the specified credential in the Usb credential database. + // + UserToken = mUsbTable->UserInfo[Index].Token; + if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) { + UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId; + CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER)); + return EFI_SUCCESS; + } + } + + return EFI_NOT_READY; + } + + // + // User is not NULL here. Read a token, and check whether the token matches with + // the selected user's Token. If not, try to find a token in token DB to matches + // with read token. + // + + Status = GetToken (ReadToken); + if (EFI_ERROR (Status)) { + QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR)); + PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN)); + OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + gBS->RestoreTPL (TPL_APPLICATION); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + gBS->RaiseTPL (OldTpl); + FreePool (QuestionStr); + FreePool (PromptStr); + return EFI_NOT_FOUND; + } + + // + // Get the selected user's identifier. + // + Status = FindUserInfoByType (User, EFI_USER_INFO_IDENTIFIER_RECORD, &UserInfo); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Check the selected user's Token with the read token. + // + for (Index = 0; Index < mUsbTable->Count; Index++) { + UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId; + NewUserId = (UINT8 *) (UserInfo + 1); + if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + // + // The user's ID is found in the UsbTable. + // + UserToken = mUsbTable->UserInfo[Index].Token; + if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) { + // + // The read token matches with the one in UsbTable. + // + CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER)); + FreePool (UserInfo); + return EFI_SUCCESS; + } + } + } + FreePool (UserInfo); + + // + // The read token mismatch with the User's Token. + // Only check token. + // + for (Index = 0; Index < mUsbTable->Count; Index++) { + UserToken = mUsbTable->UserInfo[Index].Token; + if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) { + // + // The read token matches with the one in UsbTable. + // + UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId; + CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER)); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If + AutoLogon returns FALSE, then the user interface will be constructed by the User + Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities + after the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialSelect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ) +{ + if ((This == NULL) || (AutoLogon == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO; + + return EFI_SUCCESS; +} + + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. + +**/ +EFI_STATUS +EFIAPI +CredentialDeselect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This + ) +{ + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be used + by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialDefault ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ) +{ + if ((This == NULL) || (AutoLogon == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO; + return EFI_SUCCESS; +} + + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On + exit, holds the user information. If the buffer is too small + to hold the information, then EFI_BUFFER_TOO_SMALL is returned + and InfoSize is updated to contain the number of bytes actually + required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the + size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the + user information. The size required is returned in *InfoSize. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + +**/ +EFI_STATUS +EFIAPI +CredentialGetInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ) +{ + EFI_USER_INFO *CredentialInfo; + UINTN Index; + + if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((UserInfo == NULL) || (mUsbInfoHandle == NULL)) { + return EFI_NOT_FOUND; + } + + // + // Find information handle in credential info table. + // + for (Index = 0; Index < mUsbInfoHandle->Count; Index++) { + CredentialInfo = mUsbInfoHandle->Info[Index]; + if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) { + // + // The handle is found, copy the user info. + // + if (CredentialInfo->InfoSize > *InfoSize) { + *InfoSize = CredentialInfo->InfoSize; + return EFI_BUFFER_TOO_SMALL; + } + + CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize); + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Enumerate all of the user informations on the credential provider. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] UserInfo On entry, points to the previous user information handle or NULL + to start enumeration. On exit, points to the next user information + handle or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialGetNextInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ) +{ + EFI_USER_INFO *Info; + CHAR16 *ProvNameStr; + UINTN InfoLen; + UINTN Index; + UINTN ProvStrLen; + + if ((This == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (mUsbInfoHandle == NULL) { + // + // Initilized user info table. There are 4 user info records in the table. + // + InfoLen = sizeof (USB_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *); + mUsbInfoHandle = AllocateZeroPool (InfoLen); + if (mUsbInfoHandle == NULL) { + *UserInfo = NULL; + return EFI_NOT_FOUND; + } + + // + // The first information, Credential Provider info. + // + InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID); + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mUsbCredentialGuid); + CopyGuid ((EFI_GUID *)(Info + 1), &mUsbCredentialGuid); + + mUsbInfoHandle->Info[0] = Info; + mUsbInfoHandle->Count++; + + // + // The second information, Credential Provider name info. + // + ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME)); + ProvStrLen = StrSize (ProvNameStr); + InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen; + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mUsbCredentialGuid); + CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen); + FreePool (ProvNameStr); + + mUsbInfoHandle->Info[1] = Info; + mUsbInfoHandle->Count++; + + // + // The third information, Credential Provider type info. + // + InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID); + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mUsbCredentialGuid); + CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassSecureCardGuid); + + mUsbInfoHandle->Info[2] = Info; + mUsbInfoHandle->Count++; + + // + // The fourth information, Credential Provider type name info. + // + ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME)); + ProvStrLen = StrSize (ProvNameStr); + InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen; + Info = AllocateZeroPool (InfoLen); + ASSERT (Info != NULL); + + Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD; + Info->InfoSize = (UINT32) InfoLen; + Info->InfoAttribs = EFI_USER_INFO_PROTECTED; + CopyGuid (&Info->Credential, &mUsbCredentialGuid); + CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen); + FreePool (ProvNameStr); + + mUsbInfoHandle->Info[3] = Info; + mUsbInfoHandle->Count++; + } + + if (*UserInfo == NULL) { + // + // Return the first info handle. + // + *UserInfo = (EFI_USER_INFO_HANDLE) mUsbInfoHandle->Info[0]; + return EFI_SUCCESS; + } + + // + // Find information handle in credential info table. + // + for (Index = 0; Index < mUsbInfoHandle->Count; Index++) { + Info = mUsbInfoHandle->Info[Index]; + if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) { + // + // The handle is found, get the next one. + // + if (Index == mUsbInfoHandle->Count - 1) { + // + // Already last one. + // + *UserInfo = NULL; + return EFI_NOT_FOUND; + } + Index++; + *UserInfo = (EFI_USER_INFO_HANDLE)mUsbInfoHandle->Info[Index]; + return EFI_SUCCESS; + } + } + + *UserInfo = NULL; + return EFI_NOT_FOUND; +} + + +/** + Main entry for this driver. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +UsbProviderInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Init credential table. + // + Status = InitCredentialTable (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Init Form Browser + // + Status = InitFormBrowser (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install protocol interfaces for the Usb Credential Provider. + // + Status = gBS->InstallProtocolInterface ( + &mCallbackInfo->DriverHandle, + &gEfiUserCredentialProtocolGuid, + EFI_NATIVE_INTERFACE, + &gUsbCredentialProviderDriver + ); + return Status; +} diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h new file mode 100644 index 0000000000..1d43e9ac99 --- /dev/null +++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProvider.h @@ -0,0 +1,354 @@ +/** @file + Usb Credential Provider driver header file. + +Copyright (c) 2009, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USB_CREDENTIAL_PROVIDER_H_ +#define _USB_CREDENTIAL_PROVIDER_H_ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern UINT8 UsbCredentialProviderStrings[]; +extern UINT8 UsbCredentialProviderVfrBin[]; + +#define USB_TABLE_INC 16 +#define HASHED_CREDENTIAL_LEN 20 + +#define USB_CREDENTIAL_PROVIDER_GUID \ + { \ + 0xd0849ed1, 0xa88c, 0x4ba6, { 0xb1, 0xd6, 0xab, 0x50, 0xe2, 0x80, 0xb7, 0xa9 }\ + } + +// +// Save the enroll user credential Information. +// +typedef struct { + EFI_USER_INFO_IDENTIFIER UserId; + UINT8 Token[HASHED_CREDENTIAL_LEN]; +} USB_INFO; + +// +// USB Credential Table. +// +typedef struct { + UINTN Count; + UINTN MaxCount; + USB_INFO UserInfo[1]; +} CREDENTIAL_TABLE; + +// +// The user information on the USB provider. +// +typedef struct { + UINTN Count; + EFI_USER_INFO *Info[1]; +} USB_CREDENTIAL_INFO; + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#define USB_PROVIDER_SIGNATURE SIGNATURE_32 ('U', 'S', 'B', 'P') + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; +} USB_PROVIDER_CALLBACK_INFO; + +/** + Enroll a user on a credential provider. + + This function enrolls and deletes a user profile using this credential provider. + If a user profile is successfully enrolled, it calls the User Manager Protocol + function Notify() to notify the user manager driver that credential information + has changed. If an enrolled user does exist, delete the user on the credential + provider. + + @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile to enroll. + + @retval EFI_SUCCESS User profile was successfully enrolled. + @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the + user profile handle. Either the user profile cannot enroll + on any user profile or cannot enroll on a user profile + other than the current user profile. + @retval EFI_UNSUPPORTED This credential provider does not support enrollment in + the pre-OS. + @retval EFI_DEVICE_ERROR The new credential could not be created because of a device + error. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle. + +**/ +EFI_STATUS +EFIAPI +CredentialEnroll ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + +/** + Returns the user interface information used during user identification. + + This function returns information about the form used when interacting with the + user during user identification. The form is the first enabled form in the form-set + class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If + the user credential provider does not require a form to identify the user, then this + function should return EFI_NOT_FOUND. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] FormSetId On return, holds the identifier of the form set which contains + the form used during user identification. + @param[out] FormId On return, holds the identifier of the form used during user + identification. + + @retval EFI_SUCCESS Form returned successfully. + @retval EFI_NOT_FOUND Form not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialForm ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_GUID *FormSetId, + OUT EFI_FORM_ID *FormId + ); + +/** + Returns bitmap used to describe the credential provider type. + + This optional function returns a bitmap which is less than or equal to the number + of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND + is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no + bitmap information will be returned. On exit, points to the + width of the bitmap returned. + @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no + bitmap information will be returned. On exit, points to the + height of the bitmap returned. + @param[out] Hii On return, holds the HII database handle. + @param[out] Image On return, holds the HII image identifier. + + @retval EFI_SUCCESS Image identifier returned successfully. + @retval EFI_NOT_FOUND Image identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTile ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT UINTN *Width, + IN OUT UINTN *Height, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_IMAGE_ID *Image + ); + +/** + Returns string used to describe the credential provider type. + + This function returns a string which describes the credential provider. If no + such string exists, then EFI_NOT_FOUND is returned. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] Hii On return, holds the HII database handle. + @param[out] String On return, holds the HII string identifier. + + @retval EFI_SUCCESS String identifier returned successfully. + @retval EFI_NOT_FOUND String identifier not returned. + @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialTitle ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_HII_HANDLE *Hii, + OUT EFI_STRING_ID *String + ); + +/** + Return the user identifier associated with the currently authenticated user. + + This function returns the user identifier of the user authenticated by this credential + provider. This function is called after the credential-related information has been + submitted on a form OR after a call to Default() has returned that this credential is + ready to log on. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] User The user profile handle of the user profile currently being + considered by the user identity manager. If NULL, then no user + profile is currently under consideration. + @param[out] Identifier On return, points to the user identifier. + + @retval EFI_SUCCESS User identifier returned successfully. + @retval EFI_NOT_READY No user identifier can be returned. + @retval EFI_ACCESS_DENIED The user has been locked out of this user credential. + @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL. + @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be + found in user profile database. + +**/ +EFI_STATUS +EFIAPI +CredentialUser ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + OUT EFI_USER_INFO_IDENTIFIER *Identifier + ); + +/** + Indicate that user interface interaction has begun for the specified credential. + + This function is called when a credential provider is selected by the user. If + AutoLogon returns FALSE, then the user interface will be constructed by the User + Identity Manager. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, points to the credential provider's capabilities + after the credential provider has been selected by the user. + + @retval EFI_SUCCESS Credential provider successfully selected. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialSelect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Indicate that user interface interaction has ended for the specified credential. + + This function is called when a credential provider is deselected by the user. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + + @retval EFI_SUCCESS Credential provider successfully deselected. + +**/ +EFI_STATUS +EFIAPI +CredentialDeselect ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This + ); + +/** + Return the default logon behavior for this user credential. + + This function reports the default login behavior regarding this credential provider. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[out] AutoLogon On return, holds whether the credential provider should be used + by default to automatically log on the user. + + @retval EFI_SUCCESS Default information successfully returned. + @retval EFI_INVALID_PARAMETER AutoLogon is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialDefault ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon + ); + +/** + Return information attached to the credential provider. + + This function returns user information. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On + exit, holds the user information. If the buffer is too small + to hold the information, then EFI_BUFFER_TOO_SMALL is returned + and InfoSize is updated to contain the number of bytes actually + required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the + size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the + user information. The size required is returned in *InfoSize. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle. + +**/ +EFI_STATUS +EFIAPI +CredentialGetInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN EFI_USER_INFO_HANDLE UserInfo, + OUT EFI_USER_INFO *Info, + IN OUT UINTN *InfoSize + ); + +/** + Enumerate all of the user informations on the credential provider. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL. + @param[in, out] UserInfo On entry, points to the previous user information handle or NULL + to start enumeration. On exit, points to the next user information + handle or NULL if there is no more user information. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +CredentialGetNextInfo ( + IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +#endif diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf new file mode 100644 index 0000000000..2a45763566 --- /dev/null +++ b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderDxe.inf @@ -0,0 +1,58 @@ +## @file +# Component description file for USB Credential Provider. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UsbCredentialProvider + FILE_GUID = 672A0C68-2BF0-46f9-93C3-C4E7DC0FA555 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = UsbProviderInit + +[Sources] + UsbCredentialProvider.c + UsbCredentialProvider.h + UsbCredentialProviderStrings.uni + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + SecurityPkg/SecurityPkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + DebugLib + HiiLib + UefiLib + BaseCryptLib + +[Guids] + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiFileInfoGuid ## CONSUMES ## Guid + gEfiUserCredentialClassSecureCardGuid ## CONSUMES ## Guid + +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdFixedUsbCredentialProviderTokenFileName + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiUserCredentialProtocolGuid + gEfiUserManagerProtocolGuid + gEfiBlockIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + \ No newline at end of file diff --git a/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni new file mode 100644 index 0000000000..7c531f4230 Binary files /dev/null and b/SecurityPkg/UserIdentification/UsbCredentialProviderDxe/UsbCredentialProviderStrings.uni differ diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c new file mode 100644 index 0000000000..da1201a5f9 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/LoadDeferredImage.c @@ -0,0 +1,148 @@ +/** @file + Load the deferred images after user is identified. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManager.h" + +EFI_HANDLE mDeferredImageHandle; + +/** + The function will load all the deferred images again. If the deferred image is loaded + successfully, try to start it. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +LoadDeferredImage ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_DEFERRED_IMAGE_LOAD_PROTOCOL *DeferredImage; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + UINTN DriverIndex; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + VOID *DriverImage; + UINTN ImageSize; + BOOLEAN BootOption; + EFI_HANDLE ImageHandle; + UINTN ExitDataSize; + CHAR16 *ExitData; + + // + // Find all the deferred image load protocols. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDeferredImageLoadProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return ; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuf[Index], + &gEfiDeferredImageLoadProtocolGuid, + (VOID **) &DeferredImage + ); + if (EFI_ERROR (Status)) { + continue ; + } + + DriverIndex = 0; + do { + // + // Load all the deferred images in this protocol instance. + // + Status = DeferredImage->GetImageInfo( + DeferredImage, + DriverIndex, + &ImageDevicePath, + (VOID **) &DriverImage, + &ImageSize, + &BootOption + ); + if (EFI_ERROR (Status)) { + break; + } + + // + // Load and start the image. + // + Status = gBS->LoadImage ( + BootOption, + mDeferredImageHandle, + ImageDevicePath, + NULL, + 0, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + // + // Before calling the image, enable the Watchdog Timer for + // a 5 Minute period + // + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData); + + // + // Clear the Watchdog Timer after the image returns. + // + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + } + DriverIndex++; + } while (TRUE); + } + FreePool (HandleBuf); +} + + +/** + Register an event notification function for user profile changed. + + @param[in] ImageHandle Image handle this driver. + +**/ +VOID +LoadDeferredImageInit ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + mDeferredImageHandle = ImageHandle; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LoadDeferredImage, + NULL, + &gEfiEventUserProfileChangedGuid, + &Event + ); + + ASSERT (Status == EFI_SUCCESS); +} diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c new file mode 100644 index 0000000000..e105579115 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.c @@ -0,0 +1,4381 @@ +/** @file + This driver manages user information and produces user manager protocol. + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManager.h" + +// +// Guid used in user profile saving and in form browser. +// +EFI_GUID mUserManagerGuid = USER_IDENTIFY_MANAGER_GUID; + +// +// Default user name. +// +CHAR16 mUserName[] = L"Administrator"; + +// +// Points to the user profile database. +// +USER_PROFILE_DB *mUserProfileDb = NULL; + +// +// Points to the credential providers found in system. +// +CREDENTIAL_PROVIDER_INFO *mProviderDb = NULL; + +// +// Current user shared in multi function. +// +EFI_USER_PROFILE_HANDLE mCurrentUser = NULL; + +// +// Flag indicates a user is identified. +// +BOOLEAN mIdentified = FALSE; +USER_MANAGER_CALLBACK_INFO *mCallbackInfo = NULL; +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + // + // {ACA7C06F-743C-454f-9C6D-692138482498} + // + { 0xaca7c06f, 0x743c, 0x454f, { 0x9c, 0x6d, 0x69, 0x21, 0x38, 0x48, 0x24, 0x98 } } + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +EFI_USER_MANAGER_PROTOCOL gUserIdentifyManager = { + UserProfileCreate, + UserProfileDelete, + UserProfileGetNext, + UserProfileCurrent, + UserProfileIdentify, + UserProfileFind, + UserProfileNotify, + UserProfileGetInfo, + UserProfileSetInfo, + UserProfileDeleteInfo, + UserProfileGetNextInfo, +}; + + +/** + Find the specified user in the user database. + + This function searches the specified user from the beginning of the user database. + And if NextUser is TRUE, return the next User in the user database. + + @param[in, out] User On entry, points to the user profile entry to search. + On return, points to the user profile entry or NULL if not found. + @param[in] NextUser If FALSE, find the user in user profile database specifyed by User + If TRUE, find the next user in user profile database specifyed + by User. + @param[out] ProfileIndex A pointer to the index of user profile database that matches the + user specifyed by User. + + @retval EFI_NOT_FOUND User was NULL, or User was not found, or the next user was not found. + @retval EFI_SUCCESS User or the next user are found in user profile database + +**/ +EFI_STATUS +FindUserProfile ( + IN OUT USER_PROFILE_ENTRY **User, + IN BOOLEAN NextUser, + OUT UINTN *ProfileIndex OPTIONAL + ) +{ + UINTN Index; + + // + // Check parameters + // + if ((mUserProfileDb == NULL) || (User == NULL)) { + return EFI_NOT_FOUND; + } + + // + // Check whether the user profile is in the user profile database. + // + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + if (mUserProfileDb->UserProfile[Index] == *User) { + if (ProfileIndex != NULL) { + *ProfileIndex = Index; + } + break; + } + } + + if (NextUser) { + // + // Find the next user profile. + // + Index++; + if (Index < mUserProfileDb->UserProfileNum) { + *User = mUserProfileDb->UserProfile[Index]; + } else if (Index == mUserProfileDb->UserProfileNum) { + *User = NULL; + return EFI_NOT_FOUND; + } else { + if ((mUserProfileDb->UserProfileNum > 0) && (*User == NULL)) { + *User = mUserProfileDb->UserProfile[0]; + } else { + *User = NULL; + return EFI_NOT_FOUND; + } + } + } else if (Index == mUserProfileDb->UserProfileNum) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Find the specified user information record in the specified User profile. + + This function searches the specified user information record from the beginning of the user + profile. And if NextInfo is TRUE, return the next info in the user profile. + + @param[in] User Points to the user profile entry. + @param[in, out] Info On entry, points to the user information record or NULL to start + searching with the first user information record. + On return, points to the user information record or NULL if not found. + @param[in] NextInfo If FALSE, find the user information record in profile specifyed by User. + If TRUE, find the next user information record in profile specifyed + by User. + @param[out] Offset A pointer to the offset of the information record in the user profile. + + @retval EFI_INVALID_PARAMETER Info is NULL + @retval EFI_NOT_FOUND Info was not found, or the next Info was not found. + @retval EFI_SUCCESS Info or the next info are found in user profile. + +**/ +EFI_STATUS +FindUserInfo ( + IN USER_PROFILE_ENTRY * User, + IN OUT EFI_USER_INFO **Info, + IN BOOLEAN NextInfo, + OUT UINTN *Offset OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN InfoLen; + + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user profile entry + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find user information in the specified user record. + // + InfoLen = 0; + while (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (UserInfo == *Info) { + if (Offset != NULL) { + *Offset = InfoLen; + } + break; + } + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + } + + // + // Check whether to find the next user information. + // + if (NextInfo) { + if (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + if (InfoLen < User->UserProfileSize) { + *Info = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (Offset != NULL) { + *Offset = InfoLen; + } + } else if (InfoLen == User->UserProfileSize) { + *Info = NULL; + return EFI_NOT_FOUND; + } + } else { + if (*Info == NULL) { + *Info = (EFI_USER_INFO *) User->ProfileInfo; + if (Offset != NULL) { + *Offset = 0; + } + } else { + *Info = NULL; + return EFI_NOT_FOUND; + } + } + } else if (InfoLen == User->UserProfileSize) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +/** + Find a user infomation record by the information record type. + + This function searches all user information records of User. The search starts with the + user information record following Info and continues until either the information is found + or there are no more user infomation record. + A match occurs when a Info.InfoType field matches the user information record type. + + @param[in] User Points to the user profile record to search. + @param[in, out] Info On entry, points to the user information record or NULL to start + searching with the first user information record. + On return, points to the user information record or NULL if not found. + @param[in] InfoType The infomation type to be searched. + + @retval EFI_SUCCESS User information was found. Info points to the user information record. + @retval EFI_NOT_FOUND User information was not found. + @retval EFI_INVALID_PARAMETER User is NULL or Info is NULL. + +**/ +EFI_STATUS +FindUserInfoByType ( + IN USER_PROFILE_ENTRY *User, + IN OUT EFI_USER_INFO **Info, + IN UINT8 InfoType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + UINTN InfoLen; + + if (Info == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the user has the specified user information. + // + InfoLen = 0; + if (*Info == NULL) { + Status = FindUserProfile (&User, FALSE, NULL); + } else { + Status = FindUserInfo (User, Info, TRUE, &InfoLen); + } + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + while (InfoLen < User->UserProfileSize) { + UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + InfoLen); + if (UserInfo->InfoType == InfoType) { + if (UserInfo != *Info) { + *Info = UserInfo; + return EFI_SUCCESS; + } + } + + InfoLen += ALIGN_VARIABLE (UserInfo->InfoSize); + } + + *Info = NULL; + return EFI_NOT_FOUND; +} + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. The + search starts with the user information record handle following UserInfo and continues + until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record type and the + user information record data matches the portion of Info passed the EFI_USER_INFO header. + + @param[in, out] User On entry, points to the previously returned user profile record, + or NULL to start searching with the first user profile. + On return, points to the user profile entry, or NULL if not found. + @param[in, out] UserInfo On entry, points to the previously returned user information record, + or NULL to start searching with the first. + On return, points to the user information record, or NULL if not found. + @param[in] Info Points to the buffer containing the user information to be compared + to the user information record. + @param[in] InfoSize The size of Info, in bytes. Same as Info->InfoSize. + + @retval EFI_SUCCESS User information was found. User points to the user profile record, + and UserInfo points to the user information record. + @retval EFI_NOT_FOUND User information was not found. + @retval EFI_INVALID_PARAMETER User is NULL; Info is NULL; or, InfoSize is too small. + +**/ +EFI_STATUS +FindUserProfileByInfo ( + IN OUT USER_PROFILE_ENTRY **User, + IN OUT EFI_USER_INFO **UserInfo, OPTIONAL + IN EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *InfoEntry; + + + if ((User == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize < sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + + if (UserInfo != NULL) { + InfoEntry = *UserInfo; + } else { + InfoEntry = NULL; + } + // + // Find user profile according to information. + // + if (*User == NULL) { + *User = mUserProfileDb->UserProfile[0]; + } + + // + // Check user profile handle. + // + Status = FindUserProfile (User, FALSE, NULL); + + while (!EFI_ERROR (Status)) { + // + // Find the user information in a user profile. + // + while (TRUE) { + Status = FindUserInfoByType (*User, &InfoEntry, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + + if (InfoSize == Info->InfoSize) { + if (CompareMem ((UINT8 *) (InfoEntry + 1), (UINT8 *) (Info + 1), InfoSize - sizeof (EFI_USER_INFO)) == 0) { + // + // Found the infomation record. + // + if (UserInfo != NULL) { + *UserInfo = InfoEntry; + } + return EFI_SUCCESS; + } + } + } + + // + // Get next user profile. + // + InfoEntry = NULL; + Status = FindUserProfile (User, TRUE, NULL); + } + + return EFI_NOT_FOUND; +} + +/** + Find the credential provider in the specified identity policy. + + @param[in] FindIdentity Point to the user identity policy. + @param[in] IdentifyInfo Point to the user information to be searched. + + @retval TRUE The credential provider was found in the identity policy. + @retval FALSE The credential provider was not found. +**/ +BOOLEAN +FindProvider ( + IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity, + IN CONST EFI_USER_INFO *IdentifyInfo + ) +{ + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Found the credential provider. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if ((Identity->Type == FindIdentity->Type) && + (Identity->Length == FindIdentity->Length) && + CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1)) + ) { + return TRUE; + } + + TotalLen += Identity->Length; + } + + return FALSE; +} + + +/** + Check whether the access policy is valid. + + @param[in] PolicyInfo Point to the access policy. + @param[in] InfoLen The policy length. + + @retval TRUE The policy is a valid access policy. + @retval FALSE The access policy is not a valid access policy. + +**/ +BOOLEAN +CheckAccessPolicy ( + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + UINTN TotalLen; + UINTN ValueLen; + UINTN OffSet; + EFI_USER_INFO_ACCESS_CONTROL Access; + EFI_DEVICE_PATH_PROTOCOL *Path; + UINTN PathSize; + + TotalLen = 0; + while (TotalLen < InfoLen) { + // + // Check access policy according to type. + // + CopyMem (&Access, PolicyInfo + TotalLen, sizeof (Access)); + ValueLen = Access.Size - sizeof (EFI_USER_INFO_ACCESS_CONTROL); + switch (Access.Type) { + case EFI_USER_INFO_ACCESS_FORBID_LOAD: + case EFI_USER_INFO_ACCESS_PERMIT_LOAD: + case EFI_USER_INFO_ACCESS_FORBID_CONNECT: + case EFI_USER_INFO_ACCESS_PERMIT_CONNECT: + OffSet = 0; + while (OffSet < ValueLen) { + Path = (EFI_DEVICE_PATH_PROTOCOL *) (PolicyInfo + TotalLen + sizeof (Access) + OffSet); + PathSize = GetDevicePathSize (Path); + OffSet += PathSize; + } + if (OffSet != ValueLen) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_SETUP: + if (ValueLen % sizeof (EFI_GUID) != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_BOOT_ORDER: + if (ValueLen % sizeof (EFI_USER_INFO_ACCESS_BOOT_ORDER_HDR) != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_ENROLL_SELF: + case EFI_USER_INFO_ACCESS_ENROLL_OTHERS: + case EFI_USER_INFO_ACCESS_MANAGE: + if (ValueLen != 0) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + TotalLen += Access.Size; + } + + if (TotalLen != InfoLen) { + return FALSE; + } + + return TRUE; +} + + +/** + Check whether the identity policy is valid. + + @param[in] PolicyInfo Point to the identity policy. + @param[in] InfoLen The policy length. + + @retval TRUE The policy is a valid identity policy. + @retval FALSE The access policy is not a valid identity policy. + +**/ +BOOLEAN +CheckIdentityPolicy ( + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + TotalLen = 0; + + // + // Check each part of policy expression. + // + while (TotalLen < InfoLen) { + // + // Check access polisy according to type. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + switch (Identity->Type) { + // + // Check False option. + // + case EFI_USER_INFO_IDENTITY_FALSE: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check True option. + // + case EFI_USER_INFO_IDENTITY_TRUE: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check negative operation. + // + case EFI_USER_INFO_IDENTITY_NOT: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check and operation. + // + case EFI_USER_INFO_IDENTITY_AND: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check or operation. + // + case EFI_USER_INFO_IDENTITY_OR: + if (ValueLen != 0) { + return FALSE; + } + break; + + // + // Check credential provider by type. + // + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + if (ValueLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + // + // Check credential provider by ID. + // + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + if (ValueLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + TotalLen += Identity->Length; + } + + if (TotalLen != InfoLen) { + return FALSE; + } + + return TRUE; +} + + +/** + Check whether the user information is a valid user information record. + + @param[in] Info points to the user information. + + @retval TRUE The info is a valid user information record. + @retval FALSE The info is not a valid user information record. + +**/ +BOOLEAN +CheckUserInfo ( + IN CONST EFI_USER_INFO *Info + ) +{ + UINTN InfoLen; + + if (Info == NULL) { + return FALSE; + } + // + // Check user information according to information type. + // + InfoLen = Info->InfoSize - sizeof (EFI_USER_INFO); + switch (Info->InfoType) { + case EFI_USER_INFO_EMPTY_RECORD: + if (InfoLen != 0) { + return FALSE; + } + break; + + case EFI_USER_INFO_NAME_RECORD: + case EFI_USER_INFO_CREDENTIAL_TYPE_NAME_RECORD: + case EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD: + break; + + case EFI_USER_INFO_CREATE_DATE_RECORD: + case EFI_USER_INFO_USAGE_DATE_RECORD: + if (InfoLen != sizeof (EFI_TIME)) { + return FALSE; + } + break; + + case EFI_USER_INFO_USAGE_COUNT_RECORD: + if (InfoLen != sizeof (UINT64)) { + return FALSE; + } + break; + + case EFI_USER_INFO_IDENTIFIER_RECORD: + if (InfoLen != 16) { + return FALSE; + } + break; + + case EFI_USER_INFO_CREDENTIAL_TYPE_RECORD: + case EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD: + case EFI_USER_INFO_GUID_RECORD: + if (InfoLen != sizeof (EFI_GUID)) { + return FALSE; + } + break; + + case EFI_USER_INFO_PKCS11_RECORD: + case EFI_USER_INFO_CBEFF_RECORD: + break; + + case EFI_USER_INFO_FAR_RECORD: + case EFI_USER_INFO_RETRY_RECORD: + if (InfoLen != 1) { + return FALSE; + } + break; + + case EFI_USER_INFO_ACCESS_POLICY_RECORD: + if(!CheckAccessPolicy ((UINT8 *) (Info + 1), InfoLen)) { + return FALSE; + } + break; + + case EFI_USER_INFO_IDENTITY_POLICY_RECORD: + if (!CheckIdentityPolicy ((UINT8 *) (Info + 1), InfoLen)) { + return FALSE; + } + break; + + default: + return FALSE; + break; + } + + return TRUE; +} + + +/** + Check the user profile data format to be added. + + @param[in] UserProfileInfo Points to the user profile data. + @param[in] UserProfileSize The length of user profile data. + + @retval TRUE It is a valid user profile. + @retval FALSE It is not a valid user profile. + +**/ +BOOLEAN +CheckProfileInfo ( + IN UINT8 *UserProfileInfo, + IN UINTN UserProfileSize + ) +{ + UINTN ChkLen; + EFI_USER_INFO *Info; + + if (UserProfileInfo == NULL) { + return FALSE; + } + + // + // Check user profile information length. + // + ChkLen = 0; + while (ChkLen < UserProfileSize) { + Info = (EFI_USER_INFO *) (UserProfileInfo + ChkLen); + // + // Check user information format. + // + if (!CheckUserInfo (Info)) { + return FALSE; + } + + ChkLen += ALIGN_VARIABLE (Info->InfoSize); + } + + if (ChkLen != UserProfileSize) { + return FALSE; + } + + return TRUE; +} + + +/** + Find the specified RightType in current user profile. + + @param[in] RightType Could be EFI_USER_INFO_ACCESS_MANAGE, + EFI_USER_INFO_ACCESS_ENROLL_OTHERS or + EFI_USER_INFO_ACCESS_ENROLL_SELF. + + @retval TRUE Find the specified RightType in current user profile. + @retval FALSE Can't find the right in the profile. + +**/ +BOOLEAN +CheckCurrentUserAccessRight ( + IN UINT32 RightType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + UINTN TotalLen; + UINTN CheckLen; + EFI_USER_INFO_ACCESS_CONTROL Access; + + // + // Get user access right information. + // + Info = NULL; + Status = FindUserInfoByType ( + (USER_PROFILE_ENTRY *) mCurrentUser, + &Info, + EFI_USER_INFO_ACCESS_POLICY_RECORD + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + ASSERT (Info != NULL); + TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO); + CheckLen = 0; + while (CheckLen < TotalLen) { + // + // Check right according to access type. + // + CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access)); + if (Access.Type == RightType) { + return TRUE;; + } + + CheckLen += Access.Size; + } + + return FALSE; +} + + +/** + Create a unique user identifier. + + @param[out] Identifier This points to the identifier. + +**/ +VOID +GenerateIdentifier ( + OUT UINT8 *Identifier + ) +{ + EFI_TIME Time; + UINT64 MonotonicCount; + UINT32 *MonotonicPointer; + UINTN Index; + + // + // Create a unique user identifier. + // + gRT->GetTime (&Time, NULL); + CopyMem (Identifier, &Time, sizeof (EFI_TIME)); + // + // Remove zeros. + // + for (Index = 0; Index < sizeof (EFI_TIME); Index++) { + if (Identifier[Index] == 0) { + Identifier[Index] = 0x5a; + } + } + + MonotonicPointer = (UINT32 *) Identifier; + gBS->GetNextMonotonicCount (&MonotonicCount); + MonotonicPointer[0] += (UINT32) MonotonicCount; + MonotonicPointer[1] += (UINT32) MonotonicCount; + MonotonicPointer[2] += (UINT32) MonotonicCount; + MonotonicPointer[3] += (UINT32) MonotonicCount; +} + + +/** + Generate unique user ID. + + @param[out] UserId Points to the user identifer. + +**/ +VOID +GenerateUserId ( + OUT UINT8 *UserId + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *UserProfile; + EFI_USER_INFO *UserInfo; + UINTN Index; + + // + // Generate unique user ID + // + while (TRUE) { + GenerateIdentifier (UserId); + // + // Check whether it's unique in user profile database. + // + if (mUserProfileDb == NULL) { + return ; + } + + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + UserProfile = (USER_PROFILE_ENTRY *) (mUserProfileDb->UserProfile[Index]); + UserInfo = NULL; + Status = FindUserInfoByType (UserProfile, &UserInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + if (EFI_ERROR (Status)) { + continue; + } + + if (CompareMem ((UINT8 *) (UserInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) { + break; + } + } + + if (Index == mUserProfileDb->UserProfileNum) { + return ; + } + } +} + + +/** + Expand user profile database. + + @retval TRUE Success to expand user profile database. + @retval FALSE Fail to expand user profile database. + +**/ +BOOLEAN +ExpandUsermUserProfileDb ( + VOID + ) +{ + UINTN MaxNum; + USER_PROFILE_DB *NewDataBase; + + // + // Create new user profile database. + // + if (mUserProfileDb == NULL) { + MaxNum = USER_NUMBER_INC; + } else { + MaxNum = mUserProfileDb->MaxProfileNum + USER_NUMBER_INC; + } + + NewDataBase = AllocateZeroPool ( + sizeof (USER_PROFILE_DB) - sizeof (EFI_USER_PROFILE_HANDLE) + + MaxNum * sizeof (EFI_USER_PROFILE_HANDLE) + ); + if (NewDataBase == NULL) { + return FALSE; + } + + NewDataBase->MaxProfileNum = MaxNum; + + // + // Copy old user profile database value + // + if (mUserProfileDb == NULL) { + NewDataBase->UserProfileNum = 0; + } else { + NewDataBase->UserProfileNum = mUserProfileDb->UserProfileNum; + CopyMem ( + NewDataBase->UserProfile, + mUserProfileDb->UserProfile, + NewDataBase->UserProfileNum * sizeof (EFI_USER_PROFILE_HANDLE) + ); + FreePool (mUserProfileDb); + } + + mUserProfileDb = NewDataBase; + return TRUE; +} + + +/** + Expand user profile + + @param[in] User Points to user profile. + @param[in] ExpandSize The size of user profile. + + @retval TRUE Success to expand user profile size. + @retval FALSE Fail to expand user profile size. + +**/ +BOOLEAN +ExpandUserProfile ( + IN USER_PROFILE_ENTRY *User, + IN UINTN ExpandSize + ) +{ + UINT8 *Info; + UINTN InfoSizeInc; + + // + // Allocate new memory. + // + InfoSizeInc = 128; + User->MaxProfileSize += ((ExpandSize + InfoSizeInc - 1) / InfoSizeInc) * InfoSizeInc; + Info = AllocateZeroPool (User->MaxProfileSize); + if (Info == NULL) { + return FALSE; + } + + // + // Copy exist information. + // + if (User->UserProfileSize > 0) { + CopyMem (Info, User->ProfileInfo, User->UserProfileSize); + FreePool (User->ProfileInfo); + } + + User->ProfileInfo = Info; + return TRUE; +} + + +/** + Add or delete the user's credential record in the provider. + + @param[in] ProviderGuid Point to credential provider guid or class guid. + @param[in] ByType If TRUE, Provider is credential class guid. + If FALSE, Provider is provider guid. + @param[in] User Points to user profile. + + @retval EFI_SUCCESS Add or delete record successfully. + @retval Others Fail to add or delete record. + +**/ +EFI_STATUS +ModifyProviderCredential ( + IN EFI_GUID *Provider, + IN BOOLEAN ByType, + IN USER_PROFILE_ENTRY *User + ) +{ + UINTN Index; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + + if (Provider == NULL) { + return EFI_INVALID_PARAMETER; + } + + + // + // Find the specified credential provider. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + // + // Check credential provider ID. + // + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, Provider)) { + return UserCredential->Enroll (UserCredential, User); + } + } + + return EFI_NOT_FOUND; +} + + +/** + Modify user's credential record in the providers. + + Found the providers information in PolicyInfo, and then add or delete the user's credential + record in the providers. + + @param User Points to user profile. + @param PolicyInfo Point to identification policy to be modified. + @param InfoLen The length of PolicyInfo. + + @retval EFI_SUCCESS Modify PolicyInfo successfully. + @retval Others Fail to modify PolicyInfo. + +**/ +EFI_STATUS +ModifyCredentialInfo ( + IN USER_PROFILE_ENTRY *User, + IN UINT8 *PolicyInfo, + IN UINTN InfoLen + ) +{ + EFI_STATUS Status; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Modify user's credential. + // + TotalLen = 0; + while (TotalLen < InfoLen) { + // + // Check identification policy according to type. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + TotalLen); + switch (Identity->Type) { + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), TRUE, User); + if (EFI_ERROR (Status)) { + return Status; + } + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + Status = ModifyProviderCredential ((EFI_GUID *) (Identity + 1), FALSE, User); + if (EFI_ERROR (Status)) { + return Status; + } + break; + + default: + break; + } + + TotalLen += Identity->Length; + } + + return EFI_SUCCESS; +} + + +/** + Save the user profile to non-volatile memory, or delete it from non-volatile memory. + + @param[in] User Point to the user profile + @param[in] Delete If TRUE, delete the found user profile. + If FALSE, save the user profile. + @retval EFI_SUCCESS Save or delete user profile successfully. + @retval Others Fail to change the profile. + +**/ +EFI_STATUS +SaveNvUserProfile ( + IN USER_PROFILE_ENTRY *User, + IN BOOLEAN Delete + ) +{ + EFI_STATUS Status; + + // + // Check user profile entry. + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Save the user profile to non-volatile memory. + // + Status = gRT->SetVariable ( + User->UserVarName, + &mUserManagerGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + Delete ? 0 : User->UserProfileSize, + User->ProfileInfo + ); + return Status; +} + + +/** + Replace the old identity info with NewInfo in NV Flash. + + This function only replace the identity record in the user profile. Don't update + the the information on the credential provider. + + @param[in] User Point to the user profile. + @param[in] NewInfo Point to the new identity policy info. + @param[out] UserInfo Point to the new added identity info. + + @retval EFI_SUCCESS Replace user identity successfully. + @retval Others Fail to Replace user identity. + +**/ +EFI_STATUS +SaveUserIpInfo ( + IN USER_PROFILE_ENTRY * User, + IN CONST EFI_USER_INFO * NewInfo, + OUT EFI_USER_INFO **UserInfo OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *OldIpInfo; + UINTN Offset; + UINTN NextOffset; + + if ((NewInfo == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Get user old identify policy information. + // + OldIpInfo = NULL; + Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the old identity policy offset. + // + Status = FindUserInfo (User, &OldIpInfo, FALSE, &Offset); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Delete the old identity policy information. + // + NextOffset = ALIGN_VARIABLE (OldIpInfo->InfoSize) + Offset; + User->UserProfileSize -= ALIGN_VARIABLE (OldIpInfo->InfoSize); + if (Offset < User->UserProfileSize) { + CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset); + } + + // + // Add new user information. + // + if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (NewInfo->InfoSize)) { + if (!ExpandUserProfile (User, ALIGN_VARIABLE (NewInfo->InfoSize))) { + return EFI_OUT_OF_RESOURCES; + } + } + + CopyMem (User->ProfileInfo + User->UserProfileSize, (VOID *) NewInfo, NewInfo->InfoSize); + if (UserInfo != NULL) { + *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize); + } + + User->UserProfileSize += ALIGN_VARIABLE (NewInfo->InfoSize); + + // + // Save user profile information. + // + Status = SaveNvUserProfile (User, FALSE); + return Status; +} + + +/** + Remove the provider in FindIdentity from the user identification information record. + + @param[in, out] NewInfo On entry, points to the user information to remove provider. + On return, points to the user information the provider is removed. + @param[in] FindIdentity Point to the user identity policy. + + @retval TRUE The provider is removed successfully. + @retval FALSE Fail to remove the provider. + +**/ +BOOLEAN +RemoveProvider ( + IN OUT EFI_USER_INFO **NewInfo, + IN EFI_USER_INFO_IDENTITY_POLICY *FindIdentity + ) +{ + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_USER_INFO *IdentifyInfo; + UINT8 *Buffer; + + IdentifyInfo = *NewInfo; + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + if (TotalLen == FindIdentity->Length) { + // + // Only one credential provider in the identification policy. + // Set the new policy to be TRUE after removed the provider. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentifyInfo + 1); + Identity->Type = EFI_USER_INFO_IDENTITY_TRUE; + Identity->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + IdentifyInfo->InfoSize = sizeof (EFI_USER_INFO) + Identity->Length; + return TRUE; + } + + // + // Found the credential provider. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if ((Identity->Type == FindIdentity->Type) && + (Identity->Length == FindIdentity->Length) && + CompareGuid ((EFI_GUID *) (Identity + 1), (EFI_GUID *) (FindIdentity + 1)) + ) { + // + // Found the credential provider to delete + // + if (Identity == (EFI_USER_INFO_IDENTITY_POLICY *)(IdentifyInfo + 1)) { + // + // It is the first item in the identification policy, delete it and the connector after it. + // + Buffer = (UINT8 *) Identity + Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + CopyMem (Identity, Buffer, TotalLen); + } else { + // + // It is not the first item in the identification policy, delete it and the connector before it. + // + Buffer = (UINT8 *) Identity + Identity->Length; + TotalLen = IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO); + TotalLen -= (Buffer - (UINT8 *)(IdentifyInfo + 1)); + IdentifyInfo->InfoSize -= Identity->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); + CopyMem ((UINT8 *) (Identity - 1), Buffer, TotalLen); + } + return TRUE; + } + + TotalLen += Identity->Length; + } + return FALSE; +} + + +/** + This function replaces the old identity policy with a new identity policy. + + This function changes user identity policy information. + If enroll new credential failed, recover the old identity policy. + + For new policy: + a. For each credential, if it is newly added, try to enroll it. + If enroll failed, try to delete the newly added ones. + + b. For each credential, if it exists in the old policy, delete old one, + and enroll new one. If failed to enroll the new one, removed it from new + identification policy. + + For old policy: + a. For each credential, if it does not exist in new one, delete it. + + @param[in] User Point to the user profile. + @param[in] Info Points to the user identity information. + @param[in] InfoSize The size of Info (Not used in this function). + @param[out] IpInfo The new identification info after modify. + + @retval EFI_SUCCESS Modify user identity policy successfully. + @retval Others Fail to modify user identity policy. + +**/ +EFI_STATUS +ModifyUserIpInfo ( + IN USER_PROFILE_ENTRY *User, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize, + OUT EFI_USER_INFO **IpInfo + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *OldIpInfo; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + UINT32 CredentialCount; + EFI_USER_INFO *NewIpInfo; + + // + // Get user old identify policy information. + // + OldIpInfo = NULL; + Status = FindUserInfoByType (User, &OldIpInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (OldIpInfo != NULL); + + // + // Enroll new added credential provider. + // + CredentialCount = 0; + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, OldIpInfo)) { + // + // The credential is NOT found in the old identity policy; add it. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + break; + } + CredentialCount++; + } + } + + TotalLen += Identity->Length; + } + + if (EFI_ERROR (Status)) { + // + // Enroll new credential failed. Delete the newly enrolled credential, and return. + // + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, OldIpInfo)) { + // + // The credential is NOT found in the old identity policy. Delete it. + // + if (CredentialCount == 0) { + break; + } + + ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + CredentialCount--; + } + } + TotalLen += Identity->Length; + } + + return EFI_DEVICE_ERROR; + } + + // + // Backup new identification policy + // + NewIpInfo = AllocateCopyPool (Info->InfoSize, Info); + ASSERT (NewIpInfo != NULL); + + // + // Enroll the credential that existed in the old identity policy. + // + TotalLen = 0; + while (TotalLen < Info->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (Info + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (FindProvider (Identity, OldIpInfo)) { + // + // The credential is found in the old identity policy, so delete the old credential first. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + // + // Failed to delete old credential. + // + FreePool (NewIpInfo); + return EFI_DEVICE_ERROR; + } + + // + // Add the new credential. + // + Status = ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + if (EFI_ERROR (Status)) { + // + // Failed to enroll the user by new identification policy. + // So removed the credential provider from the identification policy + // + RemoveProvider (&NewIpInfo, Identity); + } + } + } + TotalLen += Identity->Length; + } + + // + // Delete old credential that didn't exist in the new identity policy. + // + TotalLen = 0; + while (TotalLen < OldIpInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (OldIpInfo + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + if (!FindProvider (Identity, Info)) { + // + // The credential is NOT found in the new identity policy. Delete the old credential. + // + ModifyCredentialInfo (User, (UINT8 *) Identity, Identity->Length); + } + } + TotalLen += Identity->Length; + } + + *IpInfo = NewIpInfo; + return EFI_SUCCESS; +} + + +/** + Add one new user info into the user's profile. + + @param[in] User point to the user profile + @param[in] Info Points to the user information payload. + @param[in] InfoSize The size of the user information payload, in bytes. + @param[out] UserInfo Point to the new info in user profile + @param[in] Save If TRUE, save the profile to NV flash. + If FALSE, don't need to save the profile to NV flash. + + @retval EFI_SUCCESS Add user info to user profile successfully. + @retval Others Fail to add user info to user profile. + +**/ +EFI_STATUS +AddUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN UINT8 *Info, + IN UINTN InfoSize, + OUT EFI_USER_INFO **UserInfo, OPTIONAL + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + + if ((Info == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user profile handle. + // + Status = FindUserProfile (&User, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check user information memory size. + // + if (User->MaxProfileSize - User->UserProfileSize < ALIGN_VARIABLE (InfoSize)) { + if (!ExpandUserProfile (User, ALIGN_VARIABLE (InfoSize))) { + return EFI_OUT_OF_RESOURCES; + } + } + + // + // Add credential. + // + if (((EFI_USER_INFO *) Info)->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + Status = ModifyCredentialInfo ( + User, + (UINT8 *) ((EFI_USER_INFO *) Info + 1), + InfoSize - sizeof (EFI_USER_INFO) + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Add new user information. + // + CopyMem (User->ProfileInfo + User->UserProfileSize, Info, InfoSize); + if (UserInfo != NULL) { + *UserInfo = (EFI_USER_INFO *) (User->ProfileInfo + User->UserProfileSize); + } + User->UserProfileSize += ALIGN_VARIABLE (InfoSize); + + // + // Save user profile information. + // + if (Save) { + Status = SaveNvUserProfile (User, FALSE); + } + + return Status; +} + + +/** + Get the user info from the specified user info handle. + + @param[in] User Point to the user profile. + @param[in] UserInfo Point to the user information record to get. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. + On exit, holds the user information. + @param[in, out] InfoSize On entry, points to the size of Info. + On return, points to the size of the user information. + @param[in] ChkRight If TRUE, check the user info attribute. + If FALSE, don't check the user info attribute. + + + @retval EFI_ACCESS_DENIED The information cannot be accessed by the current user. + @retval EFI_INVALID_PARAMETER InfoSize is NULL or UserInfo is NULL. + @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the + returned data. The actual size required is returned in *InfoSize. + @retval EFI_SUCCESS Information returned successfully. + +**/ +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 + ) +{ + EFI_STATUS Status; + + if ((InfoSize == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((*InfoSize != 0) && (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the user information to get. + // + Status = FindUserInfo (User, &UserInfo, FALSE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check information attributes. + // + if (ChkRight) { + switch (UserInfo->InfoAttribs & EFI_USER_INFO_ACCESS) { + case EFI_USER_INFO_PRIVATE: + case EFI_USER_INFO_PROTECTED: + if (User != mCurrentUser) { + return EFI_ACCESS_DENIED; + } + break; + + case EFI_USER_INFO_PUBLIC: + break; + + default: + return EFI_INVALID_PARAMETER; + break; + } + } + + // + // Get user information. + // + if (UserInfo->InfoSize > *InfoSize) { + *InfoSize = UserInfo->InfoSize; + return EFI_BUFFER_TOO_SMALL; + } + + *InfoSize = UserInfo->InfoSize; + if (Info != NULL) { + CopyMem (Info, UserInfo, *InfoSize); + } + + return EFI_SUCCESS; +} + + +/** + Delete the specified user information from user profile. + + @param[in] User Point to the user profile. + @param[in] Info Point to the user information record to delete. + @param[in] Save If TRUE, save the profile to NV flash. + If FALSE, don't need to save the profile to NV flash. + + @retval EFI_SUCCESS Delete user info from user profile successfully. + @retval Others Fail to delete user info from user profile. + +**/ +EFI_STATUS +DelUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN EFI_USER_INFO *Info, + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + UINTN Offset; + UINTN NextOffset; + + // + // Check user information handle. + // + Status = FindUserInfo (User, &Info, FALSE, &Offset); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) { + return EFI_ACCESS_DENIED; + } else if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + Status = ModifyCredentialInfo (User, (UINT8 *) (Info + 1), Info->InfoSize - sizeof (EFI_USER_INFO)); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Delete the specified user information. + // + NextOffset = Offset + ALIGN_VARIABLE (Info->InfoSize); + User->UserProfileSize -= ALIGN_VARIABLE (Info->InfoSize); + if (Offset < User->UserProfileSize) { + CopyMem (User->ProfileInfo + Offset, User->ProfileInfo + NextOffset, User->UserProfileSize - Offset); + } + + if (Save) { + Status = SaveNvUserProfile (User, FALSE); + } + + return Status; +} + + +/** + Add or update user information. + + @param[in] User Point to the user profile. + @param[in, out] UserInfo On entry, points to the user information to modify, + or NULL to add a new UserInfo. + On return, points to the modified user information. + @param[in] Info Points to the new user information. + @param[in] InfoSize The size of Info,in bytes. + + @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SUCCESS User information was successfully changed/added. + +**/ +EFI_STATUS +ModifyUserInfo ( + IN USER_PROFILE_ENTRY *User, + IN OUT EFI_USER_INFO **UserInfo, + IN CONST EFI_USER_INFO *Info, + IN UINTN InfoSize + ) +{ + EFI_STATUS Status; + UINTN PayloadLen; + EFI_USER_INFO *OldInfo; + EFI_USER_INFO *IpInfo; + + if ((UserInfo == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize < sizeof (EFI_USER_INFO) || InfoSize != Info->InfoSize) { + return EFI_INVALID_PARAMETER; + } + + // + // Check user information. + // + if (Info->InfoType == EFI_USER_INFO_IDENTIFIER_RECORD) { + return EFI_ACCESS_DENIED; + } + + if (!CheckUserInfo (Info)) { + return EFI_INVALID_PARAMETER; + } + + + if (*UserInfo == NULL) { + // + // Add new user information. + // + OldInfo = NULL; + do { + Status = FindUserInfoByType (User, &OldInfo, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + ASSERT (OldInfo != NULL); + + if (((OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) || + ((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0)) { + // + // Same type can not co-exist for exclusive information. + // + return EFI_ACCESS_DENIED; + } + + // + // Check whether it exists in DB. + // + if (Info->InfoSize != OldInfo->InfoSize) { + continue; + } + + if (!CompareGuid (&OldInfo->Credential, &Info->Credential)) { + continue; + } + + PayloadLen = Info->InfoSize - sizeof (EFI_USER_INFO); + if (PayloadLen == 0) { + continue; + } + + if (CompareMem ((UINT8 *)(OldInfo + 1), (UINT8 *)(Info + 1), PayloadLen) != 0) { + continue; + } + + // + // Yes. The new info is as same as the one in profile. + // + return EFI_SUCCESS; + } while (!EFI_ERROR (Status)); + + Status = AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE); + return Status; + } + + // + // Modify existing user information. + // + OldInfo = *UserInfo; + if (OldInfo->InfoType != Info->InfoType) { + return EFI_INVALID_PARAMETER; + } + + if (((Info->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) != 0) && + (OldInfo->InfoAttribs & EFI_USER_INFO_EXCLUSIVE) == 0) { + // + // Try to add exclusive attrib in new info. + // Check whether there is another information with the same type in profile. + // + OldInfo = NULL; + do { + Status = FindUserInfoByType (User, &OldInfo, Info->InfoType); + if (EFI_ERROR (Status)) { + break; + } + if (OldInfo != *UserInfo) { + // + // There is another information with the same type in profile. + // Therefore, can't modify existing user information to add exclusive attribute. + // + return EFI_ACCESS_DENIED; + } + } while (TRUE); + } + + if (Info->InfoType == EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + // + // For user identification policy, need to update the info in credential provider. + // + IpInfo = NULL; + Status = ModifyUserIpInfo (User, Info, InfoSize, &IpInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (IpInfo != NULL); + Status = SaveUserIpInfo (User, IpInfo, UserInfo); + if (IpInfo->InfoSize != Info->InfoSize) { + Status = EFI_DEVICE_ERROR; + } + FreePool (IpInfo); + return Status; + } + + Status = DelUserInfo (User, *UserInfo, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + return AddUserInfo (User, (UINT8 *) Info, InfoSize, UserInfo, TRUE); +} + + +/** + Delete the user profile from non-volatile memory and database. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS Delete user from the user profile successfully. + @retval Others Fail to delete user from user profile + +**/ +EFI_STATUS +DelUserProfile ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_USER_INFO *UserInfo; + + // + // Check whether it is in the user profile database. + // + Status = FindUserProfile (&User, FALSE, &Index); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether it is the current user. + // + if (User == mCurrentUser) { + return EFI_ACCESS_DENIED; + } + + // + // Delete user credential information. + // + UserInfo = NULL; + Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (Status == EFI_SUCCESS) { + Status = DelUserInfo (User, UserInfo, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Delete user profile from the non-volatile memory. + // + Status = SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + mUserProfileDb->UserProfileNum--; + + // + // Modify user profile database. + // + if (Index != mUserProfileDb->UserProfileNum) { + mUserProfileDb->UserProfile[Index] = mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum]; + CopyMem ( + ((USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index])->UserVarName, + User->UserVarName, + sizeof (User->UserVarName) + ); + Status = SaveNvUserProfile (mUserProfileDb->UserProfile[Index], FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Delete user profile information. + // + if (User->ProfileInfo != NULL) { + FreePool (User->ProfileInfo); + } + + FreePool (User); + return EFI_SUCCESS; +} + + +/** + Add user profile to user profile database. + + @param[out] UserProfile Point to the newly added user profile. + @param[in] ProfileSize The size of the user profile. + @param[in] ProfileInfo Point to the user profie data. + @param[in] Save If TRUE, save the new added profile to NV flash. + If FALSE, don't save the profile to NV flash. + + @retval EFI_SUCCESS Add user profile to user profile database successfully. + @retval Others Fail to add user profile to user profile database. + +**/ +EFI_STATUS +AddUserProfile ( + OUT USER_PROFILE_ENTRY **UserProfile, OPTIONAL + IN UINTN ProfileSize, + IN UINT8 *ProfileInfo, + IN BOOLEAN Save + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + + // + // Check the data format to be added. + // + if (!CheckProfileInfo (ProfileInfo, ProfileSize)) { + return EFI_SECURITY_VIOLATION; + } + + // + // Create user profile entry. + // + User = AllocateZeroPool (sizeof (USER_PROFILE_ENTRY)); + if (User == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Add the entry to the user profile database. + // + if (mUserProfileDb->UserProfileNum == mUserProfileDb->MaxProfileNum) { + if (!ExpandUsermUserProfileDb ()) { + FreePool (User); + return EFI_OUT_OF_RESOURCES; + } + } + + UnicodeSPrint ( + User->UserVarName, + sizeof (User->UserVarName), + L"User%04x", + mUserProfileDb->UserProfileNum + ); + User->UserProfileSize = 0; + User->MaxProfileSize = 0; + User->ProfileInfo = NULL; + mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum] = (EFI_USER_PROFILE_HANDLE) User; + mUserProfileDb->UserProfileNum++; + + // + // Add user profile information. + // + Status = AddUserInfo (User, ProfileInfo, ProfileSize, NULL, Save); + if (EFI_ERROR (Status)) { + DelUserProfile (User); + return Status; + } + // + // Set new user profile handle. + // + if (UserProfile != NULL) { + *UserProfile = User; + } + + return EFI_SUCCESS; +} + + +/** + This function creates a new user profile with only a new user identifier + attached and returns its handle. The user profile is non-volatile, but the + handle User can change across reboots. + + @param[out] User Handle of a new user profile. + + @retval EFI_SUCCESS User profile was successfully created. + @retval Others Fail to create user profile + +**/ +EFI_STATUS +CreateUserProfile ( + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + + if (User == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Generate user id information. + // + UserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER)); + if (UserInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UserInfo->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD; + UserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER); + UserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + GenerateUserId ((UINT8 *) (UserInfo + 1)); + + // + // Add user profile to the user profile database. + // + Status = AddUserProfile (User, UserInfo->InfoSize, (UINT8 *) UserInfo, TRUE); + FreePool (UserInfo); + return Status; +} + + +/** + Add a default user profile to user profile database. + + @retval EFI_SUCCESS A default user profile is added successfully. + @retval Others Fail to add a default user profile + +**/ +EFI_STATUS +AddDefaultUserProfile ( + VOID + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + EFI_USER_INFO *Info; + EFI_USER_INFO *NewInfo; + EFI_USER_INFO_CREATE_DATE CreateDate; + EFI_USER_INFO_USAGE_COUNT UsageCount; + EFI_USER_INFO_ACCESS_CONTROL *Access; + EFI_USER_INFO_IDENTITY_POLICY *Policy; + + // + // Create a user profile. + // + Status = CreateUserProfile (&User); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate a buffer to add all default user information. + // + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + INFO_PAYLOAD_SIZE); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Add user name. + // + Info->InfoType = EFI_USER_INFO_NAME_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (mUserName); + CopyMem ((UINT8 *) (Info + 1), mUserName, sizeof (mUserName)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user profile create date record. + // + Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE); + Status = gRT->GetTime (&CreateDate, NULL); + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem ((UINT8 *) (Info + 1), &CreateDate, sizeof (EFI_USER_INFO_CREATE_DATE)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user profile usage count record. + // + Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT); + UsageCount = 0; + CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user access right. + // + Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Access = (EFI_USER_INFO_ACCESS_CONTROL *) (Info + 1); + Access->Type = EFI_USER_INFO_ACCESS_MANAGE; + Access->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL); + Info->InfoSize = sizeof (EFI_USER_INFO) + Access->Size; + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Add user identity policy. + // + Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PRIVATE | EFI_USER_INFO_EXCLUSIVE; + Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (Info + 1); + Policy->Type = EFI_USER_INFO_IDENTITY_TRUE; + Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + Info->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length; + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + +Done: + FreePool (Info); + return Status; +} + + +/** + Publish current user information into EFI System Configuration Table. + + By UEFI spec, the User Identity Manager will publish the current user profile + into the EFI System Configuration Table. Currently, only the user identifier and user + name are published. + + @retval EFI_SUCCESS Current user information is published successfully. + @retval Others Fail to publish current user information + +**/ +EFI_STATUS +PublishUserTable ( + VOID + ) +{ + EFI_STATUS Status; + EFI_CONFIGURATION_TABLE *EfiConfigurationTable; + EFI_USER_INFO_TABLE *UserInfoTable; + EFI_USER_INFO *IdInfo; + EFI_USER_INFO *NameInfo; + + Status = EfiGetSystemConfigurationTable ( + &gEfiUserManagerProtocolGuid, + (VOID **) &EfiConfigurationTable + ); + if (!EFI_ERROR (Status)) { + // + // The table existed! + // + return EFI_SUCCESS; + } + + // + // Get user ID information. + // + IdInfo = NULL; + Status = FindUserInfoByType (mCurrentUser, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + if (EFI_ERROR (Status)) { + return Status; + + } + // + // Get user name information. + // + NameInfo = NULL; + Status = FindUserInfoByType (mCurrentUser, &NameInfo, EFI_USER_INFO_NAME_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate a buffer for user information table. + // + UserInfoTable = (EFI_USER_INFO_TABLE *) AllocateRuntimePool ( + sizeof (EFI_USER_INFO_TABLE) + + IdInfo->InfoSize + + NameInfo->InfoSize + ); + if (UserInfoTable == NULL) { + Status = EFI_OUT_OF_RESOURCES; + return Status; + } + + UserInfoTable->Size = sizeof (EFI_USER_INFO_TABLE); + + // + // Append the user information to the user info table + // + CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) IdInfo, IdInfo->InfoSize); + UserInfoTable->Size += IdInfo->InfoSize; + + CopyMem ((UINT8 *) UserInfoTable + UserInfoTable->Size, (UINT8 *) NameInfo, NameInfo->InfoSize); + UserInfoTable->Size += NameInfo->InfoSize; + + Status = gBS->InstallConfigurationTable (&gEfiUserManagerProtocolGuid, (VOID *) UserInfoTable); + return Status; +} + + +/** + Get the user's identity type. + + The identify manager only supports the identity policy in which the credential + provider handles are connected by the operator 'AND' or 'OR'. + + + @param[in] User Handle of a user profile. + @param[out] PolicyType Point to the identity type. + + @retval EFI_SUCCESS Get user's identity type successfully. + @retval Others Fail to get user's identity type. + +**/ +EFI_STATUS +GetIdentifyType ( + IN EFI_USER_PROFILE_HANDLE User, + OUT UINT8 *PolicyType + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + UINTN TotalLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Search the user identify policy according to type. + // + TotalLen = 0; + *PolicyType = EFI_USER_INFO_IDENTITY_FALSE; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + if (Identity->Type == EFI_USER_INFO_IDENTITY_AND) { + *PolicyType = EFI_USER_INFO_IDENTITY_AND; + break; + } + + if (Identity->Type == EFI_USER_INFO_IDENTITY_OR) { + *PolicyType = EFI_USER_INFO_IDENTITY_OR; + break; + } + TotalLen += Identity->Length; + } + return EFI_SUCCESS; +} + + +/** + Identify the User by the specfied provider. + + @param[in] User Handle of a user profile. + @param[in] Provider Points to the identifir of credential provider. + + @retval EFI_INVALID_PARAMETER Provider is NULL. + @retval EFI_NOT_FOUND Fail to identify the specified user. + @retval EFI_SUCCESS User is identified successfully. + +**/ +EFI_STATUS +IdentifyByProviderId ( + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_GUID *Provider + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_IDENTIFIER UserId; + UINTN Index; + EFI_CREDENTIAL_LOGON_FLAGS AutoLogon; + EFI_HII_HANDLE HiiHandle; + EFI_GUID FormSetId; + EFI_FORM_ID FormId; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + EFI_USER_INFO *IdInfo; + + if (Provider == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the user ID identified by the specified credential provider. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + // + // Check credential provider class. + // + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, Provider)) { + Status = UserCredential->Select (UserCredential, &AutoLogon); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((AutoLogon & EFI_CREDENTIAL_LOGON_FLAG_AUTO) == 0) { + // + // Get credential provider form. + // + Status = UserCredential->Form ( + UserCredential, + &HiiHandle, + &FormSetId, + &FormId + ); + if (!EFI_ERROR (Status)) { + // + // Send form to get user input. + // + Status = mCallbackInfo->FormBrowser2->SendForm ( + mCallbackInfo->FormBrowser2, + &HiiHandle, + 1, + &FormSetId, + FormId, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + Status = UserCredential->User (UserCredential, User, &UserId); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = UserCredential->Deselect (UserCredential); + if (EFI_ERROR (Status)) { + return Status; + } + + if (User == NULL) { + return EFI_SUCCESS; + } + + // + // Get user ID information. + // + IdInfo = NULL; + Status = FindUserInfoByType (User, &IdInfo, EFI_USER_INFO_IDENTIFIER_RECORD); + ASSERT (IdInfo != NULL); + + if (CompareMem ((UINT8 *) (IdInfo + 1), UserId, sizeof (EFI_USER_INFO_IDENTIFIER)) != 0) { + // + // One user name is selected, but the other's credential is given. Here no user passed. + // + break; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +/** + Update user information when user is logon on successfully. + + @param[in] User Points to user profile. + + @retval EFI_SUCCESS Update user information successfully. + @retval Others Fail to update user information. + +**/ +EFI_STATUS +UpdateUserInfo ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + EFI_USER_INFO *NewInfo; + EFI_USER_INFO_CREATE_DATE Date; + EFI_USER_INFO_USAGE_COUNT UsageCount; + UINTN InfoLen; + + // + // Allocate a buffer to update user's date record and usage record. + // + InfoLen = MAX (sizeof (EFI_USER_INFO_CREATE_DATE), sizeof (EFI_USER_INFO_USAGE_COUNT)); + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + InfoLen); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Check create date record. + // + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_CREATE_DATE_RECORD); + if (Status == EFI_NOT_FOUND) { + Info->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE); + Status = gRT->GetTime (&Date, NULL); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE)); + NewInfo = NULL; + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + // + // Update usage date record. + // + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_DATE_RECORD); + if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) { + Info->InfoType = EFI_USER_INFO_USAGE_DATE_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_DATE); + Status = gRT->GetTime (&Date, NULL); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + CopyMem ((UINT8 *) (Info + 1), &Date, sizeof (EFI_USER_INFO_USAGE_DATE)); + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + // + // Update usage count record. + // + UsageCount = 0; + NewInfo = NULL; + Status = FindUserInfoByType (User, &NewInfo, EFI_USER_INFO_USAGE_COUNT_RECORD); + // + // Get usage count. + // + if (Status == EFI_SUCCESS) { + CopyMem (&UsageCount, (UINT8 *) (NewInfo + 1), sizeof (EFI_USER_INFO_USAGE_COUNT)); + } + + UsageCount++; + if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_FOUND)) { + Info->InfoType = EFI_USER_INFO_USAGE_COUNT_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_USAGE_COUNT); + CopyMem ((UINT8 *) (Info + 1), &UsageCount, sizeof (EFI_USER_INFO_USAGE_COUNT)); + Status = ModifyUserInfo (User, &NewInfo, Info, Info->InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + } + + FreePool (Info); + return EFI_SUCCESS; +} + + +/** + Add a credenetial provider item in form. + + @param[in] ProviderGuid Points to the identifir of credential provider. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + +**/ +VOID +AddProviderSelection ( + IN EFI_GUID *ProviderGuid, + IN VOID *OpCodeHandle + ) +{ + EFI_HII_HANDLE HiiHandle; + EFI_STRING_ID ProvID; + CHAR16 *ProvStr; + UINTN Index; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + + for (Index = 0; Index < mProviderDb->Count; Index++) { + UserCredential = mProviderDb->Provider[Index]; + if (CompareGuid (&UserCredential->Identifier, ProviderGuid)) { + // + // Add credential provider selection. + // + UserCredential->Title (UserCredential, &HiiHandle, &ProvID); + ProvStr = HiiGetString (HiiHandle, ProvID, NULL); + if (ProvStr == NULL) { + continue ; + } + ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL); + FreePool (ProvStr); + HiiCreateActionOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + (EFI_QUESTION_ID)(LABEL_PROVIDER_NAME + Index), // Question ID + ProvID, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + 0 // Action String ID + ); + break; + } + } +} + + +/** + Add a username item in form. + + @param[in] Index The index of the user in the user name list. + @param[in] User Points to the user profile whose username is added. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + + @retval EFI_SUCCESS Add a username successfully. + @retval Others Fail to add a username. + +**/ +EFI_STATUS +AddUserSelection ( + IN UINT16 Index, + IN USER_PROFILE_ENTRY *User, + IN VOID *OpCodeHandle + ) +{ + EFI_STRING_ID UserName; + EFI_STATUS Status; + EFI_USER_INFO *UserInfo; + + UserInfo = NULL; + Status = FindUserInfoByType (User, &UserInfo, EFI_USER_INFO_NAME_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Add user name selection. + // + UserName = HiiSetString (mCallbackInfo->HiiHandle, 0, (EFI_STRING) (UserInfo + 1), NULL); + if (UserName == 0) { + return EFI_OUT_OF_RESOURCES; + } + + HiiCreateGotoOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + FORMID_PROVIDER_FORM, // Target Form ID + UserName, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + (UINT16) Index // Question ID + ); + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identity policy does not contain the operator 'OR'. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS The specified user is identified successfully. + @retval Others Fail to identify the user. + +**/ +EFI_STATUS +IdentifyAndTypeUser ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + BOOLEAN Success; + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Check each part of identification policy expression. + // + Success = FALSE; + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + switch (Identity->Type) { + + case EFI_USER_INFO_IDENTITY_FALSE: + // + // Check False option. + // + Success = FALSE; + break; + + case EFI_USER_INFO_IDENTITY_TRUE: + // + // Check True option. + // + Success = TRUE; + break; + + case EFI_USER_INFO_IDENTITY_NOT: + // + // Check negative operation. + // + break; + + case EFI_USER_INFO_IDENTITY_AND: + // + // Check and operation. + // + if (!Success) { + return EFI_NOT_READY; + } + + Success = FALSE; + break; + + case EFI_USER_INFO_IDENTITY_OR: + // + // Check or operation. + // + if (Success) { + return EFI_SUCCESS; + } + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + // + // Check credential provider by type. + // + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + // + // Check credential provider by ID. + // + if (ValueLen != sizeof (EFI_GUID)) { + return EFI_INVALID_PARAMETER; + } + + Status = IdentifyByProviderId (User, (EFI_GUID *) (Identity + 1)); + if (EFI_ERROR (Status)) { + return Status; + } + + Success = TRUE; + break; + + default: + return EFI_INVALID_PARAMETER; + break; + } + + TotalLen += Identity->Length; + } + + if (TotalLen != IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + + if (!Success) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identity policy does not contain the operator 'AND'. + + @param[in] User Points to the user profile. + + @retval EFI_SUCCESS The specified user is identified successfully. + @retval Others Fail to identify the user. + +**/ +EFI_STATUS +IdentifyOrTypeUser ( + IN USER_PROFILE_ENTRY *User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *IdentifyInfo; + UINTN TotalLen; + UINTN ValueLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Get user identify policy information. + // + IdentifyInfo = NULL; + Status = FindUserInfoByType (User, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_PROVIDER_NAME; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add the providers that exists in the user's policy. + // + TotalLen = 0; + while (TotalLen < IdentifyInfo->InfoSize - sizeof (EFI_USER_INFO)) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1) + TotalLen); + ValueLen = Identity->Length - sizeof (EFI_USER_INFO_IDENTITY_POLICY); + if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { + AddProviderSelection ((EFI_GUID *) (Identity + 1), StartOpCodeHandle); + } + + TotalLen += Identity->Length; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserManagerGuid, // Formset GUID + FORMID_PROVIDER_FORM, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; +} + + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval Others Fail to handle the action. + +**/ +EFI_STATUS +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 + ) +{ + EFI_STATUS Status; + USER_PROFILE_ENTRY *User; + UINT8 PolicyType; + UINT16 Index; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + Status = EFI_SUCCESS; + + switch (Action) { + case EFI_BROWSER_ACTION_FORM_OPEN: + { + // + // Update user Form when user Form is opened. + // This will be done only in FORM_OPEN CallBack of question with FORM_OPEN_QUESTION_ID from user Form. + // + if (QuestionId != FORM_OPEN_QUESTION_ID) { + return EFI_SUCCESS; + } + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_NAME; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add all the user profile in the user profile database. + // + for (Index = 0; Index < mUserProfileDb->UserProfileNum; Index++) { + User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[Index]; + AddUserSelection ((UINT16)(LABEL_USER_NAME + Index), User, StartOpCodeHandle); + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserManagerGuid, // Formset GUID + FORMID_USER_FORM, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; + } + break; + + case EFI_BROWSER_ACTION_FORM_CLOSE: + Status = EFI_SUCCESS; + break; + + case EFI_BROWSER_ACTION_CHANGING: + { + if (QuestionId >= LABEL_PROVIDER_NAME) { + // + // QuestionId comes from the second Form (Select a Credential Provider if identity + // policy is OR type). Identify the user by the selected provider. + // + Status = IdentifyByProviderId (mCurrentUser, &mProviderDb->Provider[QuestionId & 0xFFF]->Identifier); + if (Status == EFI_SUCCESS) { + mIdentified = TRUE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + return EFI_SUCCESS; + } + + // + // QuestionId comes from the first Form (Select a user to identify). + // + User = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[QuestionId & 0xFFF]; + Status = GetIdentifyType (User, &PolicyType); + if (EFI_ERROR (Status)) { + return Status; + } + + if (PolicyType == EFI_USER_INFO_IDENTITY_OR) { + // + // Identify the user by "OR" logical. + // + Status = IdentifyOrTypeUser (User); + if (EFI_ERROR (Status)) { + return Status; + } + + mCurrentUser = (EFI_USER_PROFILE_HANDLE) User; + } else { + // + // Identify the user by "AND" logical. + // + Status = IdentifyAndTypeUser (User); + if (EFI_ERROR (Status)) { + return Status; + } + + mCurrentUser = (EFI_USER_PROFILE_HANDLE) User; + mIdentified = TRUE; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + } + } + break; + + default: + // + // All other action return unsupported. + // + Status = EFI_UNSUPPORTED; + break; + } + + + return Status; +} + + +/** + This function construct user profile database from user data saved in the Flash. + If no user is found in Flash, add one default user "administrator" in the user + profile database. + + @retval EFI_SUCCESS Init user profile database successfully. + @retval Others Fail to init user profile database. + +**/ +EFI_STATUS +InitUserProfileDb ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 *VarData; + UINTN VarSize; + UINTN CurVarSize; + CHAR16 VarName[10]; + UINTN Index; + UINT32 VarAttr; + + if (mUserProfileDb != NULL) { + // + // The user profiles had been already initialized. + // + return EFI_SUCCESS; + } + + // + // Init user profile database structure. + // + if (!ExpandUsermUserProfileDb ()) { + return EFI_OUT_OF_RESOURCES; + } + + CurVarSize = DEFAULT_PROFILE_SIZE; + VarData = AllocateZeroPool (CurVarSize); + if (VarData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all user proifle entries. + // + Index = 0; + while (TRUE) { + // + // Get variable name. + // + UnicodeSPrint ( + VarName, + sizeof (VarName), + L"User%04x", + Index + ); + Index++; + + // + // Get variable value. + // + VarSize = CurVarSize; + Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData); + if (Status == EFI_BUFFER_TOO_SMALL) { + FreePool (VarData); + VarData = AllocatePool (VarSize); + if (VarData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + CurVarSize = VarSize; + Status = gRT->GetVariable (VarName, &mUserManagerGuid, &VarAttr, &VarSize, VarData); + } + + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + } + break; + } + + // + // Check variable attributes. + // + if (VarAttr != (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)) { + Status = gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + continue; + } + + // + // Add user profile to the user profile database. + // + Status = AddUserProfile (NULL, VarSize, VarData, FALSE); + if (EFI_ERROR (Status)) { + if (Status == EFI_SECURITY_VIOLATION) { + // + // Delete invalid user profile + // + gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + } else if (Status == EFI_OUT_OF_RESOURCES) { + break; + } + } else { + // + // Delete and save the profile again if some invalid profiles are deleted. + // + if (mUserProfileDb->UserProfileNum < Index) { + gRT->SetVariable (VarName, &mUserManagerGuid, VarAttr, 0, NULL); + SaveNvUserProfile (mUserProfileDb->UserProfile[mUserProfileDb->UserProfileNum - 1], FALSE); + } + } + } + + if (VarData != NULL) { + FreePool (VarData); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check whether the user profile database is empty. + // + if (mUserProfileDb->UserProfileNum == 0) { + Status = AddDefaultUserProfile (); + } + + return Status; +} + + +/** + This function collects all the credential providers and saves to mProviderDb. + + @retval EFI_SUCCESS Collect credential providers successfully. + @retval Others Fail to collect credential providers. + +**/ +EFI_STATUS +InitProviderInfo ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + + if (mProviderDb != NULL) { + // + // The credential providers had been collected before. + // + return EFI_SUCCESS; + } + + // + // Try to find all the user credential provider driver. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUserCredentialProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get provider infomation. + // + mProviderDb = AllocateZeroPool ( + sizeof (CREDENTIAL_PROVIDER_INFO) - + sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + + HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + ); + if (mProviderDb == NULL) { + FreePool (HandleBuf); + return EFI_OUT_OF_RESOURCES; + } + + mProviderDb->Count = HandleCount; + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuf[Index], + &gEfiUserCredentialProtocolGuid, + (VOID **) &mProviderDb->Provider[Index] + ); + if (EFI_ERROR (Status)) { + FreePool (HandleBuf); + FreePool (mProviderDb); + mProviderDb = NULL; + return Status; + } + } + + FreePool (HandleBuf); + return EFI_SUCCESS; +} + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + + +/** + This function initialize the data mainly used in form browser. + + @retval EFI_SUCCESS Initialize form data successfully. + @retval Others Fail to Initialize form data. + +**/ +EFI_STATUS +InitFormBrowser ( + VOID + ) +{ + EFI_STATUS Status; + USER_MANAGER_CALLBACK_INFO *CallbackInfo; + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + // + // Initialize driver private data. + // + CallbackInfo = AllocateZeroPool (sizeof (USER_MANAGER_CALLBACK_INFO)); + if (CallbackInfo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CallbackInfo->Signature = USER_MANAGER_SIGNATURE; + CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig; + CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig; + CallbackInfo->ConfigAccess.Callback = UserIdentifyManagerCallback; + + // + // Locate Hii Database protocol. + // + Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &HiiDatabase); + if (EFI_ERROR (Status)) { + return Status; + } + CallbackInfo->HiiDatabase = HiiDatabase; + + // + // Locate HiiString protocol. + // + Status = gBS->LocateProtocol (&gEfiHiiStringProtocolGuid, NULL, (VOID **) &HiiString); + if (EFI_ERROR (Status)) { + return Status; + } + CallbackInfo->HiiString = HiiString; + + // + // Locate Formbrowser2 protocol. + // + Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); + if (EFI_ERROR (Status)) { + return Status; + } + + CallbackInfo->FormBrowser2 = FormBrowser2; + CallbackInfo->DriverHandle = NULL; + + // + // Install Device Path Protocol and Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &CallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &CallbackInfo->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish HII data. + // + CallbackInfo->HiiHandle = HiiAddPackages ( + &mUserManagerGuid, + CallbackInfo->DriverHandle, + UserIdentifyManagerStrings, + UserIdentifyManagerVfrBin, + NULL + ); + if (CallbackInfo->HiiHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mCallbackInfo = CallbackInfo; + + return EFI_SUCCESS; +} + + +/** + Identify the user whose identification policy supports auto logon. + + @param[in] ProviderIndex The provider index in the provider list. + @param[out] User Points to user user profile if a user is identified successfully. + + @retval EFI_SUCCESS Identify a user with the specified provider successfully. + @retval Others Fail to identify a user. + +**/ +EFI_STATUS +IdentifyAutoLogonUser ( + IN UINTN ProviderIndex, + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + UINT8 PolicyType; + + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER)); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Info->InfoType = EFI_USER_INFO_IDENTIFIER_RECORD; + Info->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_IDENTIFIER); + + // + // Identify the specified credential provider's auto logon user. + // + Status = mProviderDb->Provider[ProviderIndex]->User ( + mProviderDb->Provider[ProviderIndex], + NULL, + (EFI_USER_INFO_IDENTIFIER *) (Info + 1) + ); + if (EFI_ERROR (Status)) { + FreePool (Info); + return Status; + } + + // + // Find user with the specified user ID. + // + *User = NULL; + Status = FindUserProfileByInfo (User, NULL, Info, Info->InfoSize); + FreePool (Info); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetIdentifyType ((EFI_USER_PROFILE_HANDLE) * User, &PolicyType); + if (PolicyType == EFI_USER_INFO_IDENTITY_AND) { + // + // The identified user need also identified by other credential provider. + // This can handle through select user. + // + return EFI_NOT_READY; + } + + return Status; +} + + +/** + Check whether the given console is ready. + + @param[in] ProtocolGuid Points to the protocol guid of sonsole . + + @retval TRUE The given console is ready. + @retval FALSE The given console is not ready. + +**/ +BOOLEAN +CheckConsole ( + EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Try to find all the handle driver. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + ProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + for (Index = 0; Index < HandleCount; Index++) { + DevicePath = DevicePathFromHandle (HandleBuf[Index]); + if (DevicePath != NULL) { + FreePool (HandleBuf); + return TRUE; + } + } + FreePool (HandleBuf); + return FALSE; +} + + +/** + Check whether the console is ready. + + @retval TRUE The console is ready. + @retval FALSE The console is not ready. + +**/ +BOOLEAN +IsConsoleReady ( + VOID + ) +{ + if (!CheckConsole (&gEfiSimpleTextOutProtocolGuid)) { + return FALSE; + } + + if (!CheckConsole (&gEfiSimpleTextInProtocolGuid)) { + if (!CheckConsole (&gEfiSimpleTextInputExProtocolGuid)) { + return FALSE; + } + } + + return TRUE; +} + + +/** + Identify a user to logon. + + @param[out] User Points to user user profile if a user is identified successfully. + + @retval EFI_SUCCESS Identify a user successfully. + +**/ +EFI_STATUS +IdentifyUser ( + OUT USER_PROFILE_ENTRY **User + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_CREDENTIAL_LOGON_FLAGS AutoLogon; + EFI_USER_INFO *IdentifyInfo; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + USER_PROFILE_ENTRY *UserEntry; + + // + // Initialize credential providers. + // + InitProviderInfo (); + + // + // Initialize user profile database. + // + InitUserProfileDb (); + + // + // If only one user in system, and its identify policy is TRUE, then auto logon. + // + if (mUserProfileDb->UserProfileNum == 1) { + UserEntry = (USER_PROFILE_ENTRY *) mUserProfileDb->UserProfile[0]; + IdentifyInfo = NULL; + Status = FindUserInfoByType (UserEntry, &IdentifyInfo, EFI_USER_INFO_IDENTITY_POLICY_RECORD); + if (EFI_ERROR (Status)) { + return Status; + } + ASSERT (IdentifyInfo != NULL); + + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) ((UINT8 *) (IdentifyInfo + 1)); + if (Identity->Type == EFI_USER_INFO_IDENTITY_TRUE) { + mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry; + UpdateUserInfo (UserEntry); + *User = UserEntry; + return EFI_SUCCESS; + } + } + + // + // Find and login the default & AutoLogon user. + // + for (Index = 0; Index < mProviderDb->Count; Index++) { + UserCredential = mProviderDb->Provider[Index]; + Status = UserCredential->Default (UserCredential, &AutoLogon); + if (EFI_ERROR (Status)) { + continue; + } + + if ((AutoLogon & (EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO)) != 0) { + Status = IdentifyAutoLogonUser (Index, &UserEntry); + if (Status == EFI_SUCCESS) { + mCurrentUser = (EFI_USER_PROFILE_HANDLE) UserEntry; + UpdateUserInfo (UserEntry); + *User = UserEntry; + return EFI_SUCCESS; + } + } + } + + if (!IsConsoleReady ()) { + // + // The console is still not ready for user selection. + // + return EFI_ACCESS_DENIED; + } + + // + // Select a user and identify it. + // + mCallbackInfo->FormBrowser2->SendForm ( + mCallbackInfo->FormBrowser2, + &mCallbackInfo->HiiHandle, + 1, + &mUserManagerGuid, + 0, + NULL, + NULL + ); + + if (mIdentified) { + *User = (USER_PROFILE_ENTRY *) mCurrentUser; + UpdateUserInfo (*User); + return EFI_SUCCESS; + } + + return EFI_ACCESS_DENIED; +} + + +/** + An empty function to pass error checking of CreateEventEx (). + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +InternalEmptyFuntion ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} + + +/** + Create, Signal, and Close the User Profile Changed event. + +**/ +VOID +SignalEventUserProfileChanged ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + InternalEmptyFuntion, + NULL, + &gEfiEventUserProfileChangedGuid, + &Event + ); + ASSERT_EFI_ERROR (Status); + gBS->SignalEvent (Event); + gBS->CloseEvent (Event); +} + + +/** + Create a new user profile. + + This function creates a new user profile with only a new user identifier attached and returns + its handle. The user profile is non-volatile, but the handle User can change across reboots. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the new user profile handle. + The user profile handle is unique only during this boot. + + @retval EFI_SUCCESS User profile was successfully created. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to create a + user profile. + @retval EFI_UNSUPPORTED Creation of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCreate ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) { + return EFI_ACCESS_DENIED; + } + } + + // + // Create new user profile + // + Status = CreateUserProfile ((USER_PROFILE_ENTRY **) User); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Delete an existing user profile. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User User profile handle. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions to delete a user + profile or there is only one user profile. + @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile. + +**/ +EFI_STATUS +EFIAPI +UserProfileDelete ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + return EFI_ACCESS_DENIED; + } + + // + // Delete user profile. + // + Status = DelUserProfile (User); + if (EFI_ERROR (Status)) { + if (Status != EFI_INVALID_PARAMETER) { + return EFI_ACCESS_DENIED; + } + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + + +/** + Enumerate all of the enrolled users on the platform. + + This function returns the next enrolled user profile. To retrieve the first user profile handle, + point User at a NULL. Each subsequent call will retrieve another user profile handle until there + are no more, at which point User will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previous user profile handle or NULL to + start enumeration. On exit, points to the next user profile handle + or NULL if there are no more user profiles. + + @retval EFI_SUCCESS Next enrolled user profile successfully returned. + @retval EFI_ACCESS_DENIED Next enrolled user profile was not successfully returned. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. +**/ +EFI_STATUS +EFIAPI +UserProfileGetNext ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Status = FindUserProfile ((USER_PROFILE_ENTRY **) User, TRUE, NULL); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Return the current user profile handle. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] CurrentUser On return, points to the current user profile handle. + + @retval EFI_SUCCESS Current user profile handle returned successfully. + @retval EFI_INVALID_PARAMETER The CurrentUser parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCurrent ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *CurrentUser + ) +{ + // + // Get current user profile. + // + if ((This == NULL) || (CurrentUser == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *CurrentUser = mCurrentUser; + return EFI_SUCCESS; +} + + +/** + Identify a user. + + Identify the user and, if authenticated, returns the user handle and changes the current + user profile. All user information marked as private in a previously selected profile + is no longer available for inspection. + Whenever the current user profile is changed then the an event with the GUID + EFI_EVENT_GROUP_USER_PROFILE_CHANGED is signaled. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[out] User On return, points to the user profile handle for the current + user profile. + + @retval EFI_SUCCESS User was successfully identified. + @retval EFI_ACCESS_DENIED User was not successfully identified. + @retval EFI_INVALID_PARAMETER The User parameter is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileIdentify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (mCurrentUser != NULL) { + *User = mCurrentUser; + return EFI_SUCCESS; + } + + // + // Identify user + // + Status = IdentifyUser ((USER_PROFILE_ENTRY **) User); + if (EFI_ERROR (Status)) { + return EFI_ACCESS_DENIED; + } + + // + // Publish the user info into the EFI system configuration table. + // + PublishUserTable (); + + // + // Signal User Profile Changed event. + // + SignalEventUserProfileChanged (); + return EFI_SUCCESS; +} + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. + The search starts with the user information record handle following UserInfo and + continues until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record + type and the user information record data matches the portion of Info. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previously returned user profile + handle, or NULL to start searching with the first user profile. + On return, points to the user profile handle, or NULL if not + found. + @param[in, out] UserInfo On entry, points to the previously returned user information + handle, or NULL to start searching with the first. On return, + points to the user information handle of the user information + record, or NULL if not found. Can be NULL, in which case only + one user information record per user can be returned. + @param[in] Info Points to the buffer containing the user information to be + compared to the user information record. If the user information + record data is empty, then only the user information record type + is compared. If InfoSize is 0, then the user information record + must be empty. + + @param[in] InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User information was found. User points to the user profile + handle, and UserInfo points to the user information handle. + @retval EFI_NOT_FOUND User information was not found. User points to NULL, and + UserInfo points to NULL. + @retval EFI_INVALID_PARAMETER User is NULL. Or Info is NULL. + +**/ +EFI_STATUS +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 + ) +{ + EFI_STATUS Status; + UINTN Size; + + if ((This == NULL) || (User == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (InfoSize == 0) { + // + // If InfoSize is 0, then the user information record must be empty. + // + if (Info->InfoSize != sizeof (EFI_USER_INFO)) { + return EFI_INVALID_PARAMETER; + } + } else { + if (InfoSize != Info->InfoSize) { + return EFI_INVALID_PARAMETER; + } + } + Size = Info->InfoSize; + + // + // Find user profile accdoring to user information. + // + Status = FindUserProfileByInfo ( + (USER_PROFILE_ENTRY **) User, + (EFI_USER_INFO **) UserInfo, + (EFI_USER_INFO *) Info, + Size + ); + if (EFI_ERROR (Status)) { + *User = NULL; + if (UserInfo != NULL) { + *UserInfo = NULL; + } + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + + +/** + Return information attached to the user. + + This function returns user information. The format of the information is described in User + Information. The function may return EFI_ACCESS_DENIED if the information is marked private + and the handle specified by User is not the current user profile. The function may return + EFI_ACCESS_DENIED if the information is marked protected and the information is associated + with a credential provider for which the user has not been authenticated. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in] UserInfo Handle of the user information data record. + @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, + holds the user information. If the buffer is too small to hold the + information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is + updated to contain the number of bytes actually required. + @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the size + of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The information about the specified user cannot be accessed by the + current user. + @retval EFI_BUFFER_TOO_SMALL The number of bytes specified by *InfoSize is too small to hold the + returned data. The actual size required is returned in *InfoSize. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not refer + to a valid user info handle. + @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL. + +**/ +EFI_STATUS +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 + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (InfoSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((*InfoSize != 0) && (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((User == NULL) || (UserInfo == NULL)) { + return EFI_NOT_FOUND; + } + + Status = GetUserInfo (User, UserInfo, Info, InfoSize, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + return EFI_BUFFER_TOO_SMALL; + } + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Add or update user information. + + This function changes user information. If NULL is pointed to by UserInfo, then a new user + information record is created and its handle is returned in UserInfo. Otherwise, the existing + one is replaced. + If EFI_USER_INFO_EXCLUSIVE is specified in Info and a user information record of the same + type already exists in the user profile, then EFI_ACCESS_DENIED will be returned and UserInfo + will point to the handle of the existing record. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose profile will be retrieved. + @param[in, out] UserInfo Handle of the user information data record. + @param[in] Info On entry, points to a buffer of at least *InfoSize bytes. On exit, + holds the user information. If the buffer is too small to hold the + information, then EFI_BUFFER_TOO_SMALL is returned and InfoSize is + updated to contain the number of bytes actually required. + @param[in] InfoSize On entry, points to the size of Info. On return, points to the size + of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SECURITY_VIOLATION The current user does not have permission to change the specified + user profile or user information record. + @retval EFI_NOT_FOUND User does not refer to a valid user profile or UserInfo does not + refer to a valid user info handle. + @retval EFI_INVALID_PARAMETER UserInfo is NULL or Info is NULL. +**/ +EFI_STATUS +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 + ) +{ + EFI_STATUS Status; + + if ((This == NULL) || (User == NULL) || (UserInfo == NULL) || (Info == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (User != mCurrentUser) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + if (*UserInfo != NULL) { + // + // Can't update info in other profiles without MANAGE right. + // + return EFI_SECURITY_VIOLATION; + } + + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_OTHERS)) { + // + // Can't add info into other profiles. + // + return EFI_SECURITY_VIOLATION; + } + } + } + + if (User == mCurrentUser) { + if (CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_ENROLL_SELF)) { + // + // Only identify policy can be added/updated. + // + if (Info->InfoType != EFI_USER_INFO_IDENTITY_POLICY_RECORD) { + return EFI_SECURITY_VIOLATION; + } + } + } + + // + // Modify user information. + // + Status = ModifyUserInfo (User, (EFI_USER_INFO **) UserInfo, Info, InfoSize); + if (EFI_ERROR (Status)) { + if (Status == EFI_ACCESS_DENIED) { + return EFI_ACCESS_DENIED; + } + return EFI_SECURITY_VIOLATION; + } + return EFI_SUCCESS; +} + + +/** + Called by credential provider to notify of information change. + + This function allows the credential provider to notify the User Identity Manager when user status + has changed while deselected. + If the User Identity Manager doesn't support asynchronous changes in credentials, then this function + should return EFI_UNSUPPORTED. + If the User Identity Manager supports this, it will call User() to get the user identifier and then + GetNextInfo() and GetInfo() in the User Credential Protocol to get all of the information from the + credential and add it. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] Changed Handle on which is installed an instance of the EFI_USER_CREDENTIAL_PROTOCOL + where the user has changed. + + @retval EFI_SUCCESS The User Identity Manager has handled the notification. + @retval EFI_NOT_READY The function was called while the specified credential provider was not selected. + @retval EFI_UNSUPPORTED The User Identity Manager doesn't support asynchronous notifications. + +**/ +EFI_STATUS +EFIAPI +UserProfileNotify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_HANDLE Changed + ) +{ + EFI_STATUS Status; + EFI_USER_CREDENTIAL_PROTOCOL *Provider; + EFI_USER_INFO_IDENTIFIER UserId; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO_HANDLE UserInfo2; + UINTN InfoSize; + EFI_USER_INFO *Info; + USER_PROFILE_ENTRY *User; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->HandleProtocol ( + Changed, + &gEfiUserCredentialProtocolGuid, + (VOID **) &Provider + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Provider->User (Provider, NULL, &UserId); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + // + // Find user with the UserId. + // + User = NULL; + while (TRUE) { + // + // Find next user profile. + // + Status = FindUserProfile (&User, TRUE, NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find the user information. + // + Info = NULL; + FindUserInfoByType (User, &Info, EFI_USER_INFO_IDENTIFIER_RECORD); + if (CompareMem ((UINT8 *) (Info + 1), UserId, sizeof (UserId)) == 0) { + // + // Found the infomation record. + // + break; + } + } + + UserInfo = NULL; + do { + // + // Get user info handle. + // + Status = Provider->GetNextInfo(Provider, &UserInfo); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Get the user information from the user info handle. + // + InfoSize = 0; + Status = Provider->GetInfo(Provider, UserInfo, NULL, &InfoSize); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + Info = AllocateZeroPool (InfoSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = Provider->GetInfo(Provider, UserInfo, Info, &InfoSize); + if (EFI_ERROR (Status)) { + FreePool (Info); + break; + } + } + break; + } + + // + // Save the user information. + // + UserInfo2 = NULL; + Status = UserProfileSetInfo (&gUserIdentifyManager, (EFI_USER_PROFILE_HANDLE)User, &UserInfo2, Info, InfoSize); + FreePool (Info); + if (EFI_ERROR (Status)) { + break; + } + } while (TRUE); + + return Status; +} + + +/** + Delete user information. + + Delete the user information attached to the user profile specified by the UserInfo. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information deleted successfully. + @retval EFI_NOT_FOUND User information record UserInfo does not exist in the user profile. + @retval EFI_ACCESS_DENIED The current user does not have permission to delete this user information. + +**/ +EFI_STATUS +EFIAPI +UserProfileDeleteInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo + ) +{ + EFI_STATUS Status; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the right of the current user. + // + if (User != mCurrentUser) { + if (!CheckCurrentUserAccessRight (EFI_USER_INFO_ACCESS_MANAGE)) { + return EFI_ACCESS_DENIED; + } + } + + // + // Delete user information. + // + Status = DelUserInfo (User, UserInfo, TRUE); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + return EFI_NOT_FOUND; + } + return EFI_ACCESS_DENIED; + } + return EFI_SUCCESS; +} + + +/** + Enumerate user information of all the enrolled users on the platform. + + This function returns the next user information record. To retrieve the first user + information record handle, point UserInfo at a NULL. Each subsequent call will retrieve + another user information record handle until there are no more, at which point UserInfo + will point to NULL. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in] User Handle of the user whose information will be deleted. + @param[in, out] UserInfo Handle of the user information to remove. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + @retval EFI_INVALID_PARAMETER UserInfo is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNextInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ) +{ + if ((This == NULL) || (UserInfo == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // Get next user information entry. + // + return FindUserInfo (User, (EFI_USER_INFO **) UserInfo, TRUE, NULL); +} + + +/** + Main entry for this driver. + + @param[in] ImageHandle Image handle this driver. + @param[in] SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +UserIdentifyManagerInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + + EFI_STATUS Status; + + // + // Initiate form browser. + // + InitFormBrowser (); + + // + // Install protocol interfaces for the User Identity Manager. + // + Status = gBS->InstallProtocolInterface ( + &mCallbackInfo->DriverHandle, + &gEfiUserManagerProtocolGuid, + EFI_NATIVE_INTERFACE, + &gUserIdentifyManager + ); + ASSERT_EFI_ERROR (Status); + + LoadDeferredImageInit (ImageHandle); + return EFI_SUCCESS; +} + + diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h new file mode 100644 index 0000000000..b1e078a03e --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManager.h @@ -0,0 +1,413 @@ +/** @file + The header file for User identify Manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USER_IDENTIFY_MANAGER_H_ +#define _USER_IDENTIFY_MANAGER_H_ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UserIdentifyManagerData.h" + +// +// This is the generated IFR binary data for each formset defined in VFR. +// This data array is ready to be used as input of HiiAddPackages() to +// create a packagelist. +// +extern UINT8 UserIdentifyManagerVfrBin[]; + +// +// This is the generated String package data for all .UNI files. +// This data array is ready to be used as input of HiiAddPackages() to +// create a packagelist. +// +extern UINT8 UserIdentifyManagerStrings[]; + +#define USER_NUMBER_INC 32 +#define DEFAULT_PROFILE_SIZE 512 +#define INFO_PAYLOAD_SIZE 64 + +// +// Credential Provider Information. +// +typedef struct { + UINTN Count; + EFI_USER_CREDENTIAL_PROTOCOL *Provider[1]; +} CREDENTIAL_PROVIDER_INFO; + +// +// Internal user profile entry. +// +typedef struct { + UINTN MaxProfileSize; + UINTN UserProfileSize; + CHAR16 UserVarName[9]; + UINT8 *ProfileInfo; +} USER_PROFILE_ENTRY; + +// +// Internal user profile database. +// +typedef struct { + UINTN UserProfileNum; + UINTN MaxProfileNum; + EFI_USER_PROFILE_HANDLE UserProfile[1]; +} USER_PROFILE_DB; + +#define USER_MANAGER_SIGNATURE SIGNATURE_32 ('U', 'I', 'M', 'S') + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + + // + // Consumed protocol. + // + EFI_HII_DATABASE_PROTOCOL *HiiDatabase; + EFI_HII_STRING_PROTOCOL *HiiString; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + + // + // Produced protocol. + // + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} USER_MANAGER_CALLBACK_INFO; + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +/** + Register an event notification function for the user profile changed. + + @param[in] ImageHandle Image handle this driver. + +**/ +VOID +LoadDeferredImageInit ( + IN EFI_HANDLE ImageHandle + ); + + +/** + This function creates a new user profile with only + a new user identifier attached and returns its handle. + The user profile is non-volatile, but the handle User + can change across reboots. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param[out] User Handle of a new user profile. + + @retval EFI_SUCCESS User profile was successfully created. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions + to create a user profile. + @retval EFI_UNSUPPORTED Creation of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCreate ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + Delete an existing user profile. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User User profile handle. + + @retval EFI_SUCCESS User profile was successfully deleted. + @retval EFI_ACCESS_DENIED Current user does not have sufficient permissions + to delete a user profile or there is only one + user profile. + @retval EFI_UNSUPPORTED Deletion of new user profiles is not supported. + @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile. + +**/ +EFI_STATUS +EFIAPI +UserProfileDelete ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User + ); + + +/** + Get next user profile from the user profile database. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param[in, out] User User profile handle. + + @retval EFI_SUCCESS Next enrolled user profile successfully returned. + @retval EFI_INVALID_PARAMETER User is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNext ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + This function returns the current user profile handle. + + @param[in] This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param[out] CurrentUser User profile handle. + + @retval EFI_SUCCESS Current user profile handle returned successfully. + @retval EFI_INVALID_PARAMETER CurrentUser is NULL. + +**/ +EFI_STATUS +EFIAPI +UserProfileCurrent ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *CurrentUser + ); + + +/** + Identify the user and, if authenticated, returns the user handle and changes + the current user profile. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param CurrentUser User profile handle. + + @retval EFI_SUCCESS User was successfully identified. + @retval EFI_INVALID_PARAMETER User is NULL. + @retval EFI_ACCESS_DENIED User was not successfully identified. + +**/ +EFI_STATUS +EFIAPI +UserProfileIdentify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + OUT EFI_USER_PROFILE_HANDLE *User + ); + + +/** + Find a user using a user information record. + + This function searches all user profiles for the specified user information record. + The search starts with the user information record handle following UserInfo and + continues until either the information is found or there are no more user profiles. + A match occurs when the Info.InfoType field matches the user information record + type and the user information record data matches the portion of Info passed the + EFI_USER_INFO header. + + @param[in] This Points to this instance of the EFI_USER_MANAGER_PROTOCOL. + @param[in, out] User On entry, points to the previously returned user profile + handle, or NULL to start searching with the first user profile. + On return, points to the user profile handle, or NULL if not + found. + @param[in, out] UserInfo On entry, points to the previously returned user information + handle, or NULL to start searching with the first. On return, + points to the user information handle of the user information + record, or NULL if not found. Can be NULL, in which case only + one user information record per user can be returned. + @param[in] Info Points to the buffer containing the user information to be + compared to the user information record. If NULL, then only + the user information record type is compared. If InfoSize is 0, + then the user information record must be empty. + + @param[in] InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User information was found. User points to the user profile handle, + and UserInfo points to the user information handle. + @retval EFI_NOT_FOUND User information was not found. User points to NULL and UserInfo + points to NULL. + +**/ +EFI_STATUS +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 + ); + + +/** + This function returns user information. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User Handle of the user whose profile will be + retrieved. + @param UserInfo Handle of the user information data record. + @param Info On entry, points to a buffer of at least + *InfoSize bytes. On exit, holds the user + information. + @param InfoSize On entry, points to the size of Info. On return, + points to the size of the user information. + + @retval EFI_SUCCESS Information returned successfully. + @retval EFI_ACCESS_DENIED The information about the specified user cannot + be accessed by the current user. + EFI_BUFFER_TOO_SMALL- The number of bytes + specified by *InfoSize is too small to hold the + returned data. + +**/ +EFI_STATUS +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 + ); + + +/** + This function changes user information. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param User Handle of the user whose profile will be + retrieved. + @param UserInfo Handle of the user information data record. + @param Info Points to the user information. + @param InfoSize The size of Info, in bytes. + + @retval EFI_SUCCESS User profile information was successfully + changed/added. + @retval EFI_ACCESS_DENIED The record is exclusive. + @retval EFI_SECURITY_VIOLATION The current user does not have permission to + change the specified user profile or user + information record. + +**/ +EFI_STATUS +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 + ); + + +/** + This function allows the credential provider to notify the User Identity Manager + when user status has changed while deselected. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance + pointer. + @param Changed Points to the instance of the + EFI_USER_CREDENTIAL_PROTOCOL where the user has + changed. + + @retval EFI_SUCCESS The User Identity Manager has handled the + notification. + @retval EFI_NOT_READY The function was called while the specified + credential provider was not selected. + @retval EFI_UNSUPPORTED The User Identity Manager doesn't support + asynchronous notifications. + +**/ +EFI_STATUS +EFIAPI +UserProfileNotify ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_HANDLE Changed + ); + + +/** + Delete the user information attached to the user profile specified by the UserInfo. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param User Handle of the user whose profile will be retrieved. + @param UserInfo Handle of the user information data record. + + @retval EFI_SUCCESS User information deleted successfully. + @retval EFI_ACCESS_DENIED The current user does not have permission to + delete this user in-formation. + @retval EFI_NOT_FOUND User information record UserInfo does not exist + in the user pro-file. + +**/ +EFI_STATUS +EFIAPI +UserProfileDeleteInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN EFI_USER_INFO_HANDLE UserInfo + ); + + +/** + This function returns the next user information record. + + @param This Protocol EFI_USER_MANAGER_PROTOCOL instance pointer. + @param User Handle of the user whose profile will be retrieved. + @param UserInfo Handle of the user information data record. + + @retval EFI_SUCCESS User information returned. + @retval EFI_NOT_FOUND No more user information found. + +**/ +EFI_STATUS +EFIAPI +UserProfileGetNextInfo ( + IN CONST EFI_USER_MANAGER_PROTOCOL *This, + IN EFI_USER_PROFILE_HANDLE User, + IN OUT EFI_USER_INFO_HANDLE *UserInfo + ); + +#endif diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h new file mode 100644 index 0000000000..d91de101f7 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerData.h @@ -0,0 +1,42 @@ +/** @file + Data structure used by the user identify manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _USER_IDENTIFY_MANAGER_DATA_H_ +#define _USER_IDENTIFY_MANAGER_DATA_H_ + +#include "UserIdentifyManagerStrDefs.h" + +// +// Guid used in user profile saving and in form browser. +// +#define USER_IDENTIFY_MANAGER_GUID \ + { \ + 0x3ccd3dd8, 0x8d45, 0x4fed, { 0x96, 0x2d, 0x2b, 0x38, 0xcd, 0x82, 0xb3, 0xc4 } \ + } + +// +// Forms definition. +// +#define FORMID_USER_FORM 1 +#define FORMID_PROVIDER_FORM 2 + +// +// Labels definition. +// +#define LABEL_USER_NAME 0x1000 +#define LABEL_PROVIDER_NAME 0x3000 +#define LABEL_END 0xffff +#define FORM_OPEN_QUESTION_ID 0xfffe + +#endif diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf new file mode 100644 index 0000000000..d5fccea342 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerDxe.inf @@ -0,0 +1,62 @@ +## @file +# Component description file for user identify manager driver. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[defines] + INF_VERSION = 0x00010005 + BASE_NAME = UserIdentifyManager + FILE_GUID = C5D3191B-27D5-4873-8DF2-628136991A21 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = UserIdentifyManagerInit + +[sources] + UserIdentifyManager.c + LoadDeferredImage.c + UserIdentifyManager.h + UserIdentifyManagerData.h + UserIdentifyManagerStrings.uni + UserIdentifyManagerVfr.Vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + DebugLib + HiiLib + UefiLib + +[Guids] + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiEventUserProfileChangedGuid ## CONSUMES ## Guid + +[Protocols] + gEfiFormBrowser2ProtocolGuid ## CONSUMES + gEfiHiiDatabaseProtocolGuid ## CONSUMES + gEfiUserCredentialProtocolGuid ## CONSUMES + gEfiDeferredImageLoadProtocolGuid ## CONSUMES + gEfiHiiConfigAccessProtocolGuid ## PRODUCES + gEfiUserManagerProtocolGuid ## PRODUCES + gEfiSimpleTextOutProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextInputExProtocolGuid + +[Depex] + gEfiHiiDatabaseProtocolGuid AND + gEfiHiiStringProtocolGuid AND + gEfiFormBrowser2ProtocolGuid diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni new file mode 100644 index 0000000000..8ae4489715 Binary files /dev/null and b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerStrings.uni differ diff --git a/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr new file mode 100644 index 0000000000..ebe8195c73 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserIdentifyManagerDxe/UserIdentifyManagerVfr.Vfr @@ -0,0 +1,44 @@ +/** @file + User identify manager formset. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserIdentifyManagerData.h" + +formset + guid = USER_IDENTIFY_MANAGER_GUID, + title = STRING_TOKEN(STR_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + classguid = USER_IDENTIFY_MANAGER_GUID, + + form formid = FORMID_USER_FORM, + title = STRING_TOKEN(STR_USER_SELECT); + + suppressif TRUE; + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = FORM_OPEN_QUESTION_ID; + endif; + + label LABEL_USER_NAME; + label LABEL_END; + endform; + + form formid = FORMID_PROVIDER_FORM, + title = STRING_TOKEN(STR_PROVIDER_SELECT); + label LABEL_PROVIDER_NAME; + label LABEL_END; + endform; +endformset; \ No newline at end of file diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c new file mode 100644 index 0000000000..eb96c8edf6 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileAdd.c @@ -0,0 +1,372 @@ +/** @file + The functions to add a user profile. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserProfileManager.h" + + +/** + Get user name from the popup windows. + + @param[in, out] UserNameLen On entry, point to UserName buffer lengh, in bytes. + On exit, point to input user name length, in bytes. + @param[out] UserName The buffer to hold the input user name. + + @retval EFI_ABORTED It is given up by pressing 'ESC' key. + @retval EFI_NOT_READY Not a valid input at all. + @retval EFI_SUCCESS Get a user name successfully. + +**/ +EFI_STATUS +GetUserNameInput ( + IN OUT UINTN *UserNameLen, + OUT CHAR16 *UserName + ) +{ + EFI_INPUT_KEY Key; + UINTN NameLen; + CHAR16 Name[USER_NAME_LENGTH]; + + NameLen = 0; + while (TRUE) { + Name[NameLen] = L'_'; + Name[NameLen + 1] = L'\0'; + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Input User Name", + L"---------------------", + Name, + NULL + ); + // + // Check key. + // + if (Key.ScanCode == SCAN_NULL) { + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + // + // Add the null terminator. + // + Name[NameLen] = 0; + NameLen++; + break; + } else if ((Key.UnicodeChar == CHAR_NULL) || + (Key.UnicodeChar == CHAR_TAB) || + (Key.UnicodeChar == CHAR_LINEFEED) + ) { + continue; + } else { + if (Key.UnicodeChar == CHAR_BACKSPACE) { + if (NameLen > 0) { + NameLen--; + } + } else { + Name[NameLen] = Key.UnicodeChar; + NameLen++; + if (NameLen + 1 == USER_NAME_LENGTH) { + // + // Add the null terminator. + // + Name[NameLen] = 0; + NameLen++; + break; + } + } + } + } + + if (Key.ScanCode == SCAN_ESC) { + return EFI_ABORTED; + } + } + + if (NameLen <= 1) { + return EFI_NOT_READY; + } + + if (*UserNameLen < NameLen * sizeof (CHAR16)) { + return EFI_NOT_READY; + } + + *UserNameLen = NameLen * sizeof (CHAR16); + CopyMem (UserName, Name, *UserNameLen); + + return EFI_SUCCESS; +} + +/** + Set a user's username. + + @param[in] User Handle of a user profile . + @param[in] UserNameLen The lengh of UserName. + @param[in] UserName Point to the buffer of user name. + + @retval EFI_NOT_READY The usernme in mAddUserName had been used. + @retval EFI_SUCCESS Change the user's username successfully with + username in mAddUserName. + +**/ +EFI_STATUS +SetUserName ( + IN EFI_USER_PROFILE_HANDLE User, + IN UINTN UserNameLen, + IN CHAR16 *UserName + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_PROFILE_HANDLE TempUser; + EFI_USER_INFO *NewUserInfo; + + NewUserInfo = AllocateZeroPool (sizeof (EFI_USER_INFO) + UserNameLen); + ASSERT (NewUserInfo != NULL); + + NewUserInfo->InfoType = EFI_USER_INFO_NAME_RECORD; + NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PUBLIC | + EFI_USER_INFO_EXCLUSIVE; + NewUserInfo->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + UserNameLen); + CopyMem ((UINT8 *) (NewUserInfo + 1), UserName, UserNameLen); + TempUser = NULL; + Status = mUserManager->Find ( + mUserManager, + &TempUser, + NULL, + NewUserInfo, + NewUserInfo->InfoSize + ); + if (!EFI_ERROR (Status)) { + // + // The user name had been used, return error. + // + FreePool (NewUserInfo); + return EFI_NOT_READY; + } + + UserInfo = NULL; + mUserManager->SetInfo ( + mUserManager, + User, + &UserInfo, + NewUserInfo, + NewUserInfo->InfoSize + ); + FreePool (NewUserInfo); + return EFI_SUCCESS; +} + + +/** + Set create date of the specified user. + + @param[in] User Handle of a user profile. + +**/ +VOID +SetCreateDate ( + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO_CREATE_DATE Date; + EFI_USER_INFO *NewUserInfo; + + NewUserInfo = AllocateZeroPool ( + sizeof (EFI_USER_INFO) + + sizeof (EFI_USER_INFO_CREATE_DATE) + ); + ASSERT (NewUserInfo != NULL); + + NewUserInfo->InfoType = EFI_USER_INFO_CREATE_DATE_RECORD; + NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PUBLIC | + EFI_USER_INFO_EXCLUSIVE; + NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + sizeof (EFI_USER_INFO_CREATE_DATE); + Status = gRT->GetTime (&Date, NULL); + if (EFI_ERROR (Status)) { + FreePool (NewUserInfo); + return ; + } + + CopyMem ((UINT8 *) (NewUserInfo + 1), &Date, sizeof (EFI_USER_INFO_CREATE_DATE)); + UserInfo = NULL; + mUserManager->SetInfo ( + mUserManager, + User, + &UserInfo, + NewUserInfo, + NewUserInfo->InfoSize + ); + FreePool (NewUserInfo); +} + + +/** + Set the default identity policy of the specified user. + + @param[in] User Handle of a user profile. + +**/ +VOID +SetIdentityPolicy ( + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_USER_INFO_IDENTITY_POLICY *Policy; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *NewUserInfo; + + NewUserInfo = AllocateZeroPool ( + sizeof (EFI_USER_INFO) + + sizeof (EFI_USER_INFO_IDENTITY_POLICY) + ); + ASSERT (NewUserInfo != NULL); + + Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewUserInfo + 1); + Policy->Type = EFI_USER_INFO_IDENTITY_TRUE; + Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + + NewUserInfo->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD; + NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PRIVATE | + EFI_USER_INFO_EXCLUSIVE; + NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + Policy->Length; + UserInfo = NULL; + mUserManager->SetInfo ( + mUserManager, + User, + &UserInfo, + NewUserInfo, + NewUserInfo->InfoSize + ); + FreePool (NewUserInfo); +} + + +/** + Set the default access policy of the specified user. + + @param[in] User Handle of a user profile. + +**/ +VOID +SetAccessPolicy ( + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_USER_INFO_ACCESS_CONTROL *Control; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *NewUserInfo; + + NewUserInfo = AllocateZeroPool ( + sizeof (EFI_USER_INFO) + + sizeof (EFI_USER_INFO_ACCESS_CONTROL) + ); + ASSERT (NewUserInfo != NULL); + + Control = (EFI_USER_INFO_ACCESS_CONTROL *) (NewUserInfo + 1); + Control->Type = EFI_USER_INFO_ACCESS_ENROLL_SELF; + Control->Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL); + + NewUserInfo->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD; + NewUserInfo->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PUBLIC | + EFI_USER_INFO_EXCLUSIVE; + NewUserInfo->InfoSize = sizeof (EFI_USER_INFO) + Control->Size; + UserInfo = NULL; + mUserManager->SetInfo ( + mUserManager, + User, + &UserInfo, + NewUserInfo, + NewUserInfo->InfoSize + ); + FreePool (NewUserInfo); +} + + +/** + Add a new user profile into the user profile database. + +**/ +VOID +CallAddUser ( + VOID + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_USER_PROFILE_HANDLE User; + UINTN UserNameLen; + CHAR16 UserName[USER_NAME_LENGTH]; + CHAR16 *QuestionStr; + CHAR16 *PromptStr; + + QuestionStr = NULL; + PromptStr = NULL; + + // + // Get user name to add. + // + UserNameLen = sizeof (UserName); + Status = GetUserNameInput (&UserNameLen, UserName); + if (EFI_ERROR (Status)) { + if (Status != EFI_ABORTED) { + QuestionStr = GetStringById (STRING_TOKEN (STR_GET_USERNAME_FAILED)); + PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); + goto Done; + } + return ; + } + + // + // Create a new user profile. + // + User = NULL; + Status = mUserManager->Create (mUserManager, &User); + if (EFI_ERROR (Status)) { + QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_FAILED)); + PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); + } else { + // + // Add default user information. + // + Status = SetUserName (User, UserNameLen, UserName); + if (EFI_ERROR (Status)) { + QuestionStr = GetStringById (STRING_TOKEN (STR_USER_ALREADY_EXISTED)); + PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); + goto Done; + } + + SetCreateDate (User); + SetIdentityPolicy (User); + SetAccessPolicy (User); + + QuestionStr = GetStringById (STRING_TOKEN (STR_CREATE_PROFILE_SUCCESS)); + PromptStr = GetStringById (STRING_TOKEN (STR_STROKE_KEY_CONTINUE)); + } + +Done: + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + FreePool (QuestionStr); + FreePool (PromptStr); +} + diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c new file mode 100644 index 0000000000..d0295b731b --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileDelete.c @@ -0,0 +1,314 @@ +/** @file + The functions to delete a user profile. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserProfileManager.h" + +/** + Get the username from the specified user. + + @param[in] User Handle of a user profile. + + @retval EFI_STRING_ID The String Id of the user's username. + +**/ +EFI_STRING_ID +GetUserName ( + IN EFI_USER_PROFILE_HANDLE User + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + UINTN InfoSize; + UINTN MemSize; + UINTN NameLen; + CHAR16 UserName[USER_NAME_LENGTH]; + EFI_STRING_ID UserId; + + // + // Allocate user information memory. + // + MemSize = sizeof (EFI_USER_INFO) + 63; + Info = AllocateZeroPool (MemSize); + ASSERT (Info != NULL); + + // + // Get user name information. + // + UserInfo = NULL; + while (TRUE) { + InfoSize = MemSize; + // + // Get next user information. + // + Status = mUserManager->GetNextInfo ( + mUserManager, + User, + &UserInfo + ); + if (EFI_ERROR (Status)) { + break; + } + + Status = mUserManager->GetInfo ( + mUserManager, + User, + UserInfo, + Info, + &InfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + MemSize = InfoSize; + FreePool (Info); + Info = AllocateZeroPool (MemSize); + ASSERT (Info != NULL); + + Status = mUserManager->GetInfo ( + mUserManager, + User, + UserInfo, + Info, + &InfoSize + ); + } + // + // Check user information. + // + if (Status == EFI_SUCCESS) { + if (Info->InfoType == EFI_USER_INFO_NAME_RECORD) { + NameLen = Info->InfoSize - sizeof (EFI_USER_INFO); + if (NameLen > USER_NAME_LENGTH * sizeof (CHAR16)) { + NameLen = USER_NAME_LENGTH * sizeof (CHAR16); + } + ASSERT (NameLen >= sizeof (CHAR16)); + CopyMem (UserName, (UINT8 *) (Info + 1), NameLen); + UserName[NameLen / sizeof (CHAR16) - 1] = 0; + UserId = HiiSetString ( + mCallbackInfo->HiiHandle, + 0, + UserName, + NULL + ); + if (UserId != 0) { + FreePool (Info); + return UserId; + } + } + } + } + + FreePool (Info); + return 0; +} + + +/** + Add a username item in form. + + @param[in] User Points to the user profile whose username is added. + @param[in] Index The index of the user in the user name list + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + +**/ +VOID +AddUserToForm ( + IN EFI_USER_PROFILE_HANDLE User, + IN UINT16 Index, + IN VOID *OpCodeHandle + ) +{ + EFI_STRING_ID NameId; + + // + // Get user name + // + NameId = GetUserName (User); + if (NameId == 0) { + return ; + } + + // + // Create user name option. + // + switch (Index & KEY_FIRST_FORM_MASK) { + case KEY_MODIFY_USER: + HiiCreateGotoOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + FORMID_USER_INFO, // Target Form ID + NameId, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + Index // Question ID + ); + break; + + case KEY_DEL_USER: + HiiCreateActionOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + Index, // Question ID + NameId, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + 0 // Action String ID + ); + break; + + default: + break; + } +} + + +/** + Delete the user specified by UserIndex in user profile database. + + @param[in] UserIndex The index of user in the user name list + to be deleted. + +**/ +VOID +DeleteUser ( + IN UINT8 UserIndex + ) +{ + EFI_STATUS Status; + EFI_USER_PROFILE_HANDLE User; + EFI_INPUT_KEY Key; + + // + // Find specified user profile and delete it. + // + User = NULL; + Status = mUserManager->GetNext (mUserManager, &User); + if (EFI_ERROR (Status)) { + goto Done; + } + + while (UserIndex > 1) { + Status = mUserManager->GetNext (mUserManager, &User); + if (EFI_ERROR (Status)) { + goto Done; + } + UserIndex--; + } + + if (UserIndex == 1) { + Status = mUserManager->Delete (mUserManager, User); + if (EFI_ERROR (Status)) { + goto Done; + } + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Delete User Succeed!", + L"", + L"Please Press Any Key to Continue ...", + NULL + ); + return ; + } + +Done: + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Delete User Failed!", + L"", + L"Please Press Any Key to Continue ...", + NULL + ); +} + + +/** + Display user select form, cab select a user to delete. + +**/ +VOID +SelectUserToDelete ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 Index; + EFI_USER_PROFILE_HANDLE User; + EFI_USER_PROFILE_HANDLE CurrentUser; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_DEL_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add each user can be deleted. + // + User = NULL; + Index = 1; + mUserManager->Current (mUserManager, &CurrentUser); + while (TRUE) { + Status = mUserManager->GetNext (mUserManager, &User); + if (EFI_ERROR (Status)) { + break; + } + + if (User != CurrentUser) { + AddUserToForm ( + User, + (UINT16)(KEY_DEL_USER | KEY_SELECT_USER | Index), + StartOpCodeHandle + ); + } + Index++; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_DEL_USER, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c new file mode 100644 index 0000000000..74c979d58e --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.c @@ -0,0 +1,806 @@ +/** @file + This driver is a configuration tool for adding, deleting or modifying user + profiles, including gathering the necessary information to ascertain their + identity in the future, updating user access policy and identification + policy, etc. + +Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserProfileManager.h" + +EFI_GUID mUserProfileManagerGuid = USER_PROFILE_MANAGER_GUID; +EFI_USER_MANAGER_PROTOCOL *mUserManager = NULL; +CREDENTIAL_PROVIDER_INFO *mProviderInfo = NULL; +UINT8 mProviderChoice; +UINT8 mConncetLogical; +USER_INFO_ACCESS mAccessInfo; +USER_INFO mUserInfo; +USER_PROFILE_MANAGER_CALLBACK_INFO *mCallbackInfo; +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + {0xad2e3474, 0x93e6, 0x488b, {0x93, 0x19, 0x64, 0x88, 0xfc, 0x68, 0x1f, 0x16}} + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +/** + Get string by string id from HII Interface. + + + @param[in] Id String ID to get the string from. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ) +{ + // + // Get the current string for the current Language. + // + return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL); +} + + +/** + This function gets all the credential providers in the system and saved them + to mProviderInfo. + + @retval EFI_SUCESS Init credential provider database successfully. + @retval Others Fail to init credential provider database. + +**/ +EFI_STATUS +InitProviderInfo ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuf; + UINTN Index; + + // + // Try to find all the user credential provider driver. + // + HandleCount = 0; + HandleBuf = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiUserCredentialProtocolGuid, + NULL, + &HandleCount, + &HandleBuf + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get provider infomation. + // + if (mProviderInfo != NULL) { + FreePool (mProviderInfo); + } + mProviderInfo = AllocateZeroPool ( + sizeof (CREDENTIAL_PROVIDER_INFO) - + sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + + HandleCount * sizeof (EFI_USER_CREDENTIAL_PROTOCOL *) + ); + if (mProviderInfo == NULL) { + FreePool (HandleBuf); + return EFI_OUT_OF_RESOURCES; + } + + mProviderInfo->Count = HandleCount; + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuf[Index], + &gEfiUserCredentialProtocolGuid, + (VOID **) &mProviderInfo->Provider[Index] + ); + if (EFI_ERROR (Status)) { + FreePool (HandleBuf); + FreePool (mProviderInfo); + mProviderInfo = NULL; + return Status; + } + } + + FreePool (HandleBuf); + return EFI_SUCCESS; +} + + +/** + This function processes changes in user profile configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action Specifies the type of action taken by the browser. + @param QuestionId A unique value which is sent to the original + exporting driver so that it can identify the type + of data to expect. + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original + exporting driver. + @param ActionRequest On return, points to the action requested by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the action. + @retval Others Fail to handle the action. + +**/ +EFI_STATUS +EFIAPI +UserProfileManagerCallback ( + 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 + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINT32 CurrentAccessRight; + CHAR16 *QuestionStr; + CHAR16 *PromptStr; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_USER_PROFILE_HANDLE CurrentUser; + + Status = EFI_SUCCESS; + + switch (Action) { + case EFI_BROWSER_ACTION_FORM_OPEN: + { + // + // Update user manage Form when user manage Form is opened. + // This will be done only in FORM_OPEN CallBack of question with QUESTIONID_USER_MANAGE from user manage Form. + // + if (QuestionId != QUESTIONID_USER_MANAGE) { + return EFI_SUCCESS; + } + + // + // Get current user + // + CurrentUser = NULL; + mUserManager->Current (mUserManager, &CurrentUser); + if (CurrentUser == NULL) { + DEBUG ((DEBUG_ERROR, "Error: current user does not exist!\n")); + return EFI_NOT_READY; + } + + // + // Get current user's right information. + // + Status = GetAccessRight (&CurrentAccessRight); + if (EFI_ERROR (Status)) { + CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; + } + + // + // Init credential provider information. + // + Status = InitProviderInfo (); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_MANAGE_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add user profile option. + // + if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) || + (CurrentAccessRight == EFI_USER_INFO_ACCESS_ENROLL_OTHERS) + ) { + HiiCreateActionOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_ADD_USER, // Question ID + STRING_TOKEN (STR_ADD_USER_TITLE), // Prompt text + STRING_TOKEN (STR_ADD_USER_HELP), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + 0 // Action String ID + ); + } + + // + // Add modify user profile option. + // + HiiCreateGotoOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + FORMID_MODIFY_USER, // Target Form ID + STRING_TOKEN (STR_MODIFY_USER_TITLE), // Prompt text + STRING_TOKEN (STR_MODIFY_USER_HELP), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + KEY_MODIFY_USER // Question ID + ); + + // + // Add delete user profile option + // + if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + FORMID_DEL_USER, // Target Form ID + STRING_TOKEN (STR_DELETE_USER_TITLE), // Prompt text + STRING_TOKEN (STR_DELETE_USER_HELP), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + KEY_DEL_USER // Question ID + ); + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_USER_MANAGE, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; + } + break; + + case EFI_BROWSER_ACTION_FORM_CLOSE: + Status = EFI_SUCCESS; + break; + + case EFI_BROWSER_ACTION_CHANGING: + { + // + // Handle the request from form. + // + if ((Value == NULL) || (ActionRequest == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Judge first 2 bits. + // + switch (QuestionId & KEY_FIRST_FORM_MASK) { + // + // Add user profile operation. + // + case KEY_ADD_USER: + CallAddUser (); + break; + + // + // Delete user profile operation. + // + case KEY_DEL_USER: + // + // Judge next 2 bits. + // + switch (QuestionId & KEY_SECOND_FORM_MASK) { + // + // Enter delete user profile form. + // + case KEY_ENTER_NEXT_FORM: + SelectUserToDelete (); + break; + + // + // Delete specified user profile. + // + case KEY_SELECT_USER: + DeleteUser ((UINT8) QuestionId); + // + // Update select user form after delete a user. + // + SelectUserToDelete (); + break; + + default: + break; + } + break; + + // + // Modify user profile operation. + // + case KEY_MODIFY_USER: + // + // Judge next 2 bits. + // + switch (QuestionId & KEY_SECOND_FORM_MASK) { + // + // Enter modify user profile form. + // + case KEY_ENTER_NEXT_FORM: + SelectUserToModify (); + break; + + // + // Enter user profile information form. + // + case KEY_SELECT_USER: + // + // Judge next 3 bits. + // + switch (QuestionId & KEY_MODIFY_INFO_MASK) { + // + // Display user information form. + // + case KEY_ENTER_NEXT_FORM: + ModifyUserInfo ((UINT8) QuestionId); + break; + + // + // Modify user name. + // + case KEY_MODIFY_NAME: + ModifyUserName (); + // + // Update username in parent form. + // + SelectUserToModify (); + break; + + // + // Modify identity policy. + // + case KEY_MODIFY_IP: + // + // Judge next 3 bits + // + switch (QuestionId & KEY_MODIFY_IP_MASK) { + // + // Display identity policy modify form. + // + case KEY_ENTER_NEXT_FORM: + ModifyIdentityPolicy (); + break; + + // + // Change credential provider option. + // + case KEY_MODIFY_PROV: + mProviderChoice = Value->u8; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + // + // Change logical connector. + // + case KEY_MODIFY_CONN: + mConncetLogical = Value->u8; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + // + // Save option. + // + case KEY_ADD_IP_OP: + AddIdentityPolicyItem (); + break; + + // + // Return to user profile information form. + // + case KEY_IP_RETURN_UIF: + SaveIdentityPolicy (); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + default: + break; + } + break; + + // + // Modify access policy. + // + case KEY_MODIFY_AP: + // + // Judge next 3 bits. + // + switch (QuestionId & KEY_MODIFY_AP_MASK) { + // + // Display access policy modify form. + // + case KEY_ENTER_NEXT_FORM: + ModidyAccessPolicy (); + break; + + // + // Change access right choice. + // + case KEY_MODIFY_RIGHT: + mAccessInfo.AccessRight = Value->u8; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + // + // Change setup choice. + // + case KEY_MODIFY_SETUP: + mAccessInfo.AccessSetup= Value->u8; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + // + // Change boot order choice. + // + case KEY_MODIFY_BOOT: + mAccessInfo.AccessBootOrder = Value->u32; + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + // + // Load device path form. + // + case KEY_MODIFY_LOAD: + // + // Judge next 2 bits. + // + switch (QuestionId & KEY_DISPLAY_DP_MASK) { + // + // Permit load device path. + // + case KEY_PERMIT_MODIFY: + DisplayLoadPermit (); + break; + + // + // Forbid load device path. + // + case KEY_FORBID_MODIFY: + DisplayLoadForbid (); + break; + + default: + break; + } + break; + + // + // Connect device path form. + // + case KEY_MODIFY_CONNECT: + // + // Judge next 2 bits. + // + switch (QuestionId & KEY_DISPLAY_DP_MASK) { + // + // Permit connect device path. + // + case KEY_PERMIT_MODIFY: + DisplayConnectPermit (); + break; + + // + // Forbid connect device path. + // + case KEY_FORBID_MODIFY: + DisplayConnectForbid (); + break; + + default: + break; + } + break; + + // + // Return to user profile information form. + // + case KEY_AP_RETURN_UIF: + SaveAccessPolicy (); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + break; + + default: + break; + } + break; + + default: + break; + } + break; + + // + // Access policy device path modified. + // + case KEY_MODIFY_AP_DP: + // + // Judge next 2 bits. + // + switch (QuestionId & KEY_MODIFY_DP_MASK) { + // + // Load permit device path modified. + // + case KEY_LOAD_PERMIT_MODIFY: + QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_FORBID_LIST)); + PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + FreePool (QuestionStr); + FreePool (PromptStr); + if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { + break; + } + + AddToForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); + DisplayLoadPermit (); + break; + + // + // Load forbid device path modified. + // + case KEY_LOAD_FORBID_MODIFY: + QuestionStr = GetStringById (STRING_TOKEN (STR_MOVE_TO_PERMIT_LIST)); + PromptStr = GetStringById (STRING_TOKEN (STR_PRESS_KEY_CONTINUE)); + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + QuestionStr, + L"", + PromptStr, + NULL + ); + FreePool (QuestionStr); + FreePool (PromptStr); + if (Key.UnicodeChar != CHAR_CARRIAGE_RETURN) { + break; + } + + DeleteFromForbidLoad ((UINT16)(QuestionId & (KEY_MODIFY_DP_MASK - 1))); + DisplayLoadForbid (); + break; + + // + // Connect permit device path modified. + // + case KEY_CONNECT_PERMIT_MODIFY: + break; + + // + // Connect forbid device path modified. + // + case KEY_CONNECT_FORBID_MODIFY: + break; + + default: + break; + } + break; + + default: + break; + } + break; + + default: + break; + } + } + break; + + default: + // + // All other action return unsupported. + // + Status = EFI_UNSUPPORTED; + break; + } + + + return Status; +} + + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + *Progress = Request; + return EFI_NOT_FOUND; +} + +/** + This function processes the results of changes in configuration. + + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +FakeRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_NOT_FOUND; +} + + +/** + Main entry for this driver. + + @param ImageHandle Image handle this driver. + @param SystemTable Pointer to SystemTable. + + @retval EFI_SUCESS This function always complete successfully. + +**/ +EFI_STATUS +EFIAPI +UserProfileManagerInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + USER_PROFILE_MANAGER_CALLBACK_INFO *CallbackInfo; + + Status = gBS->LocateProtocol ( + &gEfiUserManagerProtocolGuid, + NULL, + (VOID **) &mUserManager + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Initialize driver private data. + // + ZeroMem (&mUserInfo, sizeof (mUserInfo)); + ZeroMem (&mAccessInfo, sizeof (mAccessInfo)); + + CallbackInfo = AllocateZeroPool (sizeof (USER_PROFILE_MANAGER_CALLBACK_INFO)); + ASSERT (CallbackInfo != NULL); + + CallbackInfo->Signature = USER_PROFILE_MANAGER_SIGNATURE; + CallbackInfo->ConfigAccess.ExtractConfig = FakeExtractConfig; + CallbackInfo->ConfigAccess.RouteConfig = FakeRouteConfig; + CallbackInfo->ConfigAccess.Callback = UserProfileManagerCallback; + CallbackInfo->DriverHandle = NULL; + + // + // Install Device Path Protocol and Config Access protocol to driver handle. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &CallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &CallbackInfo->ConfigAccess, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Publish HII data. + // + CallbackInfo->HiiHandle = HiiAddPackages ( + &mUserProfileManagerGuid, + CallbackInfo->DriverHandle, + UserProfileManagerStrings, + UserProfileManagerVfrBin, + NULL + ); + ASSERT (CallbackInfo->HiiHandle != NULL); + mCallbackInfo = CallbackInfo; + + return Status; +} + + diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h new file mode 100644 index 0000000000..b7098dc7b6 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManager.h @@ -0,0 +1,387 @@ +/** @file + The header file for user profile manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __EFI_USER_PROFILE_MANAGER_H__ +#define __EFI_USER_PROFILE_MANAGER_H__ + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "UserProfileManagerData.h" + +#define USER_NAME_LENGTH 17 + +// +// Credential Provider Information. +// +typedef struct { + UINTN Count; + EFI_USER_CREDENTIAL_PROTOCOL *Provider[1]; +} CREDENTIAL_PROVIDER_INFO; + +// +// User profile information structure. +// +typedef struct { + UINT64 UsageCount; + EFI_TIME CreateDate; + EFI_TIME UsageDate; + UINTN AccessPolicyLen; + UINTN IdentityPolicyLen; + UINTN NewIdentityPolicyLen; + UINT8 *AccessPolicy; + UINT8 *IdentityPolicy; + UINT8 *NewIdentityPolicy; + CHAR16 UserName[USER_NAME_LENGTH]; + BOOLEAN CreateDateExist; + BOOLEAN UsageDateExist; + BOOLEAN AccessPolicyModified; + BOOLEAN IdentityPolicyModified; + BOOLEAN NewIdentityPolicyModified; +} USER_INFO; + +// +// User access information structure. +// +typedef struct { + UINTN LoadPermitLen; + UINTN LoadForbidLen; + UINTN ConnectPermitLen; + UINTN ConnectForbidLen; + UINT8 *LoadPermit; + UINT8 *LoadForbid; + UINT8 *ConnectPermit; + UINT8 *ConnectForbid; + UINT32 AccessBootOrder; + UINT8 AccessRight; + UINT8 AccessSetup; +} USER_INFO_ACCESS; + +#define USER_PROFILE_MANAGER_SIGNATURE SIGNATURE_32 ('U', 'P', 'M', 'S') + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE HiiHandle; + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; +} USER_PROFILE_MANAGER_CALLBACK_INFO; + +// +// HII specific Vendor Device Path definition. +// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +// +// This is the generated IFR binary data for each formset defined in VFR. +// +extern UINT8 UserProfileManagerVfrBin[]; + +// +// This is the generated String package data for .UNI file. +// +extern UINT8 UserProfileManagerStrings[]; + +// +// Guid used in the form browse. +// +extern EFI_GUID mUserProfileManagerGuid; + +// +// The user manager protocol, used in several function. +// +extern EFI_USER_MANAGER_PROTOCOL *mUserManager; + +// +// The credential providers database in system. +// +extern CREDENTIAL_PROVIDER_INFO *mProviderInfo; + +// +// The variables used to update identity policy. +// +extern UINT8 mProviderChoice; +extern UINT8 mConncetLogical; + +// +// The variables used to update access policy. +// +extern USER_INFO_ACCESS mAccessInfo; + +// +// The user information used to record all data in UI. +// +extern USER_INFO mUserInfo; + +extern USER_PROFILE_MANAGER_CALLBACK_INFO *mCallbackInfo; + + +/** + Get string by string id from HII Interface. + + + @param[in] Id String ID to get the string from. + + @retval CHAR16 * String from ID. + @retval NULL If error occurs. + +**/ +CHAR16 * +GetStringById ( + IN EFI_STRING_ID Id + ); + +/** + Add a new user profile into the user profile database. + +**/ +VOID +CallAddUser ( + VOID + ); + +/** + Display user select form; can select a user to modify. + +**/ +VOID +SelectUserToModify ( + VOID + ); + +/** + Display user select form, cab select a user to delete. + +**/ +VOID +SelectUserToDelete ( + VOID + ); + +/** + Delete the user specified by UserIndex in user profile database. + + @param[in] UserIndex The index of user in the user name list to be deleted. + +**/ +VOID +DeleteUser ( + IN UINT8 UserIndex + ); + +/** + Add a username item in form. + + @param[in] User Points to the user profile whose username is added. + @param[in] Index The index of the user in the user name list. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + +**/ +VOID +AddUserToForm ( + IN EFI_USER_PROFILE_HANDLE User, + IN UINT16 Index, + IN VOID *OpCodeHandle + ); + +/** + Display modify user information form + + In this form, username, create Date, usage date, usage count, identity policy, + and access policy are displayed. + + @param[in] UserIndex The index of the user in display list to modify. + +**/ +VOID +ModifyUserInfo ( + IN UINT8 UserIndex + ); + +/** + Get the username from user input and update username string in Hii + database with it. + +**/ +VOID +ModifyUserName ( + VOID + ); + +/** + Display the form of modifying user identity policy. + +**/ +VOID +ModifyIdentityPolicy ( + VOID + ); + +/** + Update the mUserInfo.NewIdentityPolicy and UI when 'add option' is pressed. + +**/ +VOID +AddIdentityPolicyItem ( + VOID + ); + +/** + Save the identity policy and update UI with it. + + This funciton will verify the new identity policy, in current implementation, + the identity policy can be: T, P & P & P & ..., P | P | P | ... + Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or". + Other identity policies are not supported. + +**/ +VOID +SaveIdentityPolicy ( + VOID + ); + +/** + Display modify user access policy form + + In this form, access right, access setu,p and access boot order are dynamically + added. Load devicepath and connect devicepath are displayed too. + +**/ +VOID +ModidyAccessPolicy ( + VOID + ); + +/** + Collect all the access policy data to mUserInfo.AccessPolicy, + and save it to user profile. + +**/ +VOID +SaveAccessPolicy ( + VOID + ); + +/** + Get current user's access rights. + + @param[out] AccessRight Points to the buffer used for user's access rights. + + @retval EFI_SUCCESS Get current user access rights successfully. + @retval others Fail to get current user access rights. + +**/ +EFI_STATUS +GetAccessRight ( + OUT UINT32 *AccessRight + ); + +/** + Display the permit load device path in the loadable device path list. + +**/ +VOID +DisplayLoadPermit( + VOID + ); + +/** + Display the forbid load device path list (mAccessInfo.LoadForbid). + +**/ +VOID +DisplayLoadForbid ( + VOID + ); + +/** + Display the permit connect device path. + +**/ +VOID +DisplayConnectPermit ( + VOID + ); + +/** + Display the forbid connect device path list. + +**/ +VOID +DisplayConnectForbid ( + VOID + ); + +/** + Delete the specified device path by DriverIndex from the forbid device path + list (mAccessInfo.LoadForbid). + + @param[in] DriverIndex The index of driver in a forbidden device path list. + +**/ +VOID +DeleteFromForbidLoad ( + IN UINT16 DriverIndex + ); + +/** + Add the specified device path by DriverIndex to the forbid device path + list (mAccessInfo.LoadForbid). + + @param[in] DriverIndex The index of driver saved in driver options. + +**/ +VOID +AddToForbidLoad ( + IN UINT16 DriverIndex + ); + +/** + Get user name from the popup windows. + + @param[in, out] UserNameLen On entry, point to the buffer lengh of UserName. + On exit, point to the input user name length. + @param[out] UserName The buffer to hold the input user name. + + @retval EFI_ABORTED It is given up by pressing 'ESC' key. + @retval EFI_NOT_READY Not a valid input at all. + @retval EFI_SUCCESS Get a user name successfully. + +**/ +EFI_STATUS +GetUserNameInput ( + IN OUT UINTN *UserNameLen, + OUT CHAR16 *UserName + ); + +#endif diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h new file mode 100644 index 0000000000..58b6cb8c1e --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerData.h @@ -0,0 +1,161 @@ +/** @file + The form data for user profile manager driver. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __USER_PROFILE_MANAGER_DATA_H__ +#define __USER_PROFILE_MANAGER_DATA_H__ + +#define USER_PROFILE_MANAGER_GUID \ + { \ + 0xc35f272c, 0x97c2, 0x465a, { 0xa2, 0x16, 0x69, 0x6b, 0x66, 0x8a, 0x8c, 0xfe } \ + } + +// +// Form ID +// +#define FORMID_USER_MANAGE 0x0001 +#define FORMID_MODIFY_USER 0x0002 +#define FORMID_DEL_USER 0x0003 +#define FORMID_USER_INFO 0x0004 +#define FORMID_MODIFY_IP 0x0005 +#define FORMID_MODIFY_AP 0x0006 +#define FORMID_LOAD_DP 0x0007 +#define FORMID_CONNECT_DP 0x0008 +#define FORMID_PERMIT_LOAD_DP 0x0009 +#define FORMID_FORBID_LOAD_DP 0x000A +#define FORMID_PERMIT_CONNECT_DP 0x000B +#define FORMID_FORBID_CONNECT_DP 0x000C + +// +// Label ID +// +#define LABEL_USER_MANAGE_FUNC 0x0010 +#define LABEL_USER_DEL_FUNC 0x0020 +#define LABEL_USER_MOD_FUNC 0x0030 +#define LABEL_USER_INFO_FUNC 0x0040 +#define LABEL_IP_MOD_FUNC 0x0050 +#define LABEL_AP_MOD_FUNC 0x0060 +#define LABEL_PERMIT_LOAD_FUNC 0x0070 +#define LABLE_FORBID_LOAD_FUNC 0x0080 +#define LABEL_END 0x00F0 + +// +// First form key (Add/modify/del user profile). +// First 2 bits (bit 16~15). +// +#define KEY_MODIFY_USER 0x4000 +#define KEY_DEL_USER 0x8000 +#define KEY_ADD_USER 0xC000 +#define KEY_FIRST_FORM_MASK 0xC000 + +// +// Second form key (Display new form /Select user / modify device path in access policy). +// Next 2 bits (bit 14~13). +// +#define KEY_ENTER_NEXT_FORM 0x0000 +#define KEY_SELECT_USER 0x1000 +#define KEY_MODIFY_AP_DP 0x2000 +#define KEY_OPEN_CLOSE_FORM_ACTION 0x3000 +#define KEY_SECOND_FORM_MASK 0x3000 + +// +// User profile information form key. +// Next 3 bits (bit 12~10). +// +#define KEY_MODIFY_NAME 0x0200 +#define KEY_MODIFY_IP 0x0400 +#define KEY_MODIFY_AP 0x0600 +#define KEY_MODIFY_INFO_MASK 0x0E00 + +// +// Specified key, used in VFR (KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_NAME). +// +#define KEY_MODIFY_USER_NAME 0x5200 + +// +// Modify identity policy form key. +// Next 3 bits (bit 9~7). +// +#define KEY_MODIFY_PROV 0x0040 +#define KEY_MODIFY_MTYPE 0x0080 +#define KEY_MODIFY_CONN 0x00C0 +#define KEY_ADD_IP_OP 0x0100 +#define KEY_IP_RETURN_UIF 0x0140 +#define KEY_MODIFY_IP_MASK 0x01C0 + +// +// Specified key. +// +#define KEY_ADD_LOGICAL_OP 0x5500 +#define KEY_IP_RETURN 0x5540 + +// +// Modify access policy form key. +// Next 3 bits (bit 9~7). +// +#define KEY_MODIFY_RIGHT 0x0040 +#define KEY_MODIFY_SETUP 0x0080 +#define KEY_MODIFY_BOOT 0x00C0 +#define KEY_MODIFY_LOAD 0x0100 +#define KEY_MODIFY_CONNECT 0x0140 +#define KEY_AP_RETURN_UIF 0x0180 +#define KEY_MODIFY_AP_MASK 0x01C0 + +// +// Specified key. +// +#define KEY_LOAD_DP 0x5700 +#define KEY_CONN_DP 0x5740 +#define KEY_AP_RETURN 0x5780 + +// +// Device path form key. +// Next 2 bits (bit 6~5). +// +#define KEY_PERMIT_MODIFY 0x0010 +#define KEY_FORBID_MODIFY 0x0020 +#define KEY_DISPLAY_DP_MASK 0x0030 + +// +// Specified key. +// +#define KEY_LOAD_PERMIT 0x5710 +#define KEY_LOAD_FORBID 0x5720 +#define KEY_CONNECT_PERMIT 0x5750 +#define KEY_CONNECT_FORBID 0x5760 + +// +// Device path modify key. +// 2 bits (bit 12~11). +// +#define KEY_LOAD_PERMIT_MODIFY 0x0000 +#define KEY_LOAD_FORBID_MODIFY 0x0400 +#define KEY_CONNECT_PERMIT_MODIFY 0x0800 +#define KEY_CONNECT_FORBID_MODIFY 0x0C00 +#define KEY_MODIFY_DP_MASK 0x0C00 + + +// +// The permissions usable when configuring the platform. +// +#define ACCESS_SETUP_RESTRICTED 1 +#define ACCESS_SETUP_NORMAL 2 +#define ACCESS_SETUP_ADMIN 3 + +// +// Question ID for the question used in each form (KEY_OPEN_CLOSE_FORM_ACTION | FORMID_FORM_USER_MANAGE) +// This ID is used in FORM OPEN/CLOSE CallBack action. +// +#define QUESTIONID_USER_MANAGE 0x3001 + +#endif diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf new file mode 100644 index 0000000000..27b3464dcf --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerDxe.inf @@ -0,0 +1,60 @@ +## @file +# Component description file for user profile manager driver. +# +# Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.
+# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = UserProfileManager + FILE_GUID = E38CB52D-A74D-45db-A8D0-290C9B21BBF2 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = UserProfileManagerInit + +[Sources] + UserProfileManager.c + UserProfileManager.h + UserProfileAdd.c + UserProfileDelete.c + UserProfileModify.c + UserProfileManagerData.h + UserProfileManagerStrings.uni + UserProfileManagerVfr.Vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + DebugLib + HiiLib + UefiLib + + [Guids] + gEfiIfrTianoGuid ## CONSUMES ## Guid + gEfiUserInfoAccessSetupAdminGuid ## CONSUMES ## Guid + gEfiUserInfoAccessSetupNormalGuid ## CONSUMES ## Guid + gEfiUserInfoAccessSetupRestrictedGuid ## CONSUMES ## Guid + +[Protocols] + gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED + gEfiHiiConfigAccessProtocolGuid + gEfiUserCredentialProtocolGuid + gEfiUserManagerProtocolGuid + gEfiDevicePathToTextProtocolGuid + +[Depex] + gEfiUserManagerProtocolGuid \ No newline at end of file diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni new file mode 100644 index 0000000000..64631bb921 Binary files /dev/null and b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerStrings.uni differ diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr new file mode 100644 index 0000000000..d094d78a76 --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileManagerVfr.Vfr @@ -0,0 +1,247 @@ +/** @file + User Profile Manager formset. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserProfileManagerData.h" + +#define USER_MANAGER_CLASS 0x00 +#define USER_MANAGER_SUBCLASS 0x04 + +formset + guid = USER_PROFILE_MANAGER_GUID, + title = STRING_TOKEN(STR_FORMSET_TITLE), + help = STRING_TOKEN(STR_TITLE_HELP), + class = USER_MANAGER_CLASS, + subclass = USER_MANAGER_SUBCLASS, + + // User manager form + form formid = FORMID_USER_MANAGE, + title = STRING_TOKEN(STR_USERMAN_TITLE); + + label LABEL_USER_MANAGE_FUNC; + label LABEL_END; + + suppressif TRUE; + text + help = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = QUESTIONID_USER_MANAGE; + endif; + + endform; + + // Modify user profile form + form formid = FORMID_MODIFY_USER, + title = STRING_TOKEN(STR_MODIFY_USER_TITLE); + + label LABEL_USER_MOD_FUNC; + label LABEL_END; + + endform; + + // Delete user profile form + form formid = FORMID_DEL_USER, + title = STRING_TOKEN(STR_DELETE_USER_TITLE); + + label LABEL_USER_DEL_FUNC; + label LABEL_END; + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + endform; + + // + // User profile information form + // + form formid = FORMID_USER_INFO, + title = STRING_TOKEN(STR_USER_INFO); + + text + help = STRING_TOKEN(STR_USER_NAME_VAL), + text = STRING_TOKEN(STR_USER_NAME), + flags = INTERACTIVE, + key = KEY_MODIFY_USER_NAME; + + text + help = STRING_TOKEN(STR_CREATE_DATE_VAL), + text = STRING_TOKEN(STR_CREATE_DATE); + + text + help = STRING_TOKEN(STR_USAGE_DATE_VAL), + text = STRING_TOKEN(STR_USAGE_DATE); + + text + help = STRING_TOKEN(STR_USAGE_COUNT_VAL), + text = STRING_TOKEN(STR_USAGE_COUNT); + + label LABEL_USER_INFO_FUNC; + label LABEL_END; + + endform; + + // + // Identify policy modify form + // + form formid = FORMID_MODIFY_IP, + title = STRING_TOKEN(STR_IDENTIFY_POLICY); + + text + help = STRING_TOKEN(STR_IDENTIFY_POLICY_HELP), + text = STRING_TOKEN(STR_IDENTIFY_POLICY), + text = STRING_TOKEN(STR_IDENTIFY_POLICY_VALUE); + + label LABEL_IP_MOD_FUNC; + label LABEL_END; + + text + help = STRING_TOKEN(STR_ADD_OPTION_HELP), + text = STRING_TOKEN(STR_ADD_OPTION), + flags = INTERACTIVE, + key = KEY_ADD_LOGICAL_OP; + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + goto FORMID_USER_INFO, + prompt = STRING_TOKEN(STR_SAVE), + help = STRING_TOKEN(STR_IDENTIFY_SAVE_HELP), + flags = INTERACTIVE, + key = KEY_IP_RETURN; + + endform; + + // + // Access policy modify form + // + form formid = FORMID_MODIFY_AP, + title = STRING_TOKEN(STR_ACCESS_POLICY); + + label LABEL_AP_MOD_FUNC; + label LABEL_END; + + goto FORMID_LOAD_DP, + prompt = STRING_TOKEN(STR_LOAD), + help = STRING_TOKEN(STR_LOAD_HELP), + flags = INTERACTIVE, + key = KEY_LOAD_DP; + + goto FORMID_CONNECT_DP, + prompt = STRING_TOKEN(STR_CONNECT), + help = STRING_TOKEN(STR_CONNECT_HELP), + flags = INTERACTIVE, + key = KEY_CONN_DP; + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + goto FORMID_USER_INFO, + prompt = STRING_TOKEN(STR_SAVE), + help = STRING_TOKEN(STR_ACCESS_SAVE_HELP), + flags = INTERACTIVE, + key = KEY_AP_RETURN; + + endform; + + // + // Load device path form + // + form formid = FORMID_LOAD_DP, + title = STRING_TOKEN(STR_LOAD); + + goto FORMID_PERMIT_LOAD_DP, + prompt = STRING_TOKEN(STR_LOAD_PERMIT), + help = STRING_TOKEN(STR_LOAD_PERMIT_HELP), + flags = INTERACTIVE, + key = KEY_LOAD_PERMIT; + + goto FORMID_FORBID_LOAD_DP, + prompt = STRING_TOKEN(STR_LOAD_FORBID), + help = STRING_TOKEN(STR_LOAD_FORBID_HELP), + flags = INTERACTIVE, + key = KEY_LOAD_FORBID; + + endform; + + // + // Permit load device path form + // + form formid = FORMID_PERMIT_LOAD_DP, + title = STRING_TOKEN(STR_LOAD_PERMIT); + + label LABEL_PERMIT_LOAD_FUNC; + label LABEL_END; + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + endform; + + // + // Forbid load device path form + // + form formid = FORMID_FORBID_LOAD_DP, + title = STRING_TOKEN(STR_LOAD_FORBID); + + label LABLE_FORBID_LOAD_FUNC; + label LABEL_END; + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + endform; + + // + // Connect device path form + // + form formid = FORMID_CONNECT_DP, + title = STRING_TOKEN(STR_CONNECT); + + goto FORMID_PERMIT_CONNECT_DP, + prompt = STRING_TOKEN(STR_CONNECT_PERMIT), + help = STRING_TOKEN(STR_CONNECT_PERMIT_HELP), + flags = INTERACTIVE, + key = KEY_CONNECT_PERMIT; + + goto FORMID_FORBID_CONNECT_DP, + prompt = STRING_TOKEN(STR_CONNECT_FORBID), + help = STRING_TOKEN(STR_CONNECT_FORBID_HELP), + flags = INTERACTIVE, + key = KEY_CONNECT_FORBID; + + endform; + + // + // Permit connect device path form + // + form formid = FORMID_PERMIT_CONNECT_DP, + title = STRING_TOKEN(STR_CONNECT_PERMIT); + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + endform; + + // + // Forbid connect device path form + // + form formid = FORMID_FORBID_CONNECT_DP, + title = STRING_TOKEN(STR_CONNECT_FORBID); + + subtitle + text = STRING_TOKEN(STR_NULL_STRING); + + endform; + +endformset; diff --git a/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c new file mode 100644 index 0000000000..156c155c2c --- /dev/null +++ b/SecurityPkg/UserIdentification/UserProfileManagerDxe/UserProfileModify.c @@ -0,0 +1,2511 @@ +/** @file + The functions to modify a user profile. + +Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "UserProfileManager.h" + +EFI_USER_PROFILE_HANDLE mModifyUser = NULL; + +/** + Display user select form, cab select a user to modify. + +**/ +VOID +SelectUserToModify ( + VOID + ) +{ + EFI_STATUS Status; + UINT8 Index; + EFI_USER_PROFILE_HANDLE User; + EFI_USER_PROFILE_HANDLE CurrentUser; + UINT32 CurrentAccessRight; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_MOD_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add each user can be modified. + // + User = NULL; + Index = 1; + mUserManager->Current (mUserManager, &CurrentUser); + while (TRUE) { + Status = mUserManager->GetNext (mUserManager, &User); + if (EFI_ERROR (Status)) { + break; + } + + Status = GetAccessRight (&CurrentAccessRight); + if (EFI_ERROR (Status)) { + CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; + } + + if ((CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) || (User == CurrentUser)) { + AddUserToForm (User, (UINT16)(KEY_MODIFY_USER | KEY_SELECT_USER | Index), StartOpCodeHandle); + } + Index++; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_MODIFY_USER, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + Get all the user info from mModifyUser in the user manager, and save on the + global variable. + +**/ +VOID +GetAllUserInfo ( + VOID + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + UINTN InfoSize; + UINTN MemSize; + UINTN DataLen; + + // + // Init variable to default value. + // + mProviderChoice = 0; + mConncetLogical = 0; + + mUserInfo.CreateDateExist = FALSE; + mUserInfo.UsageDateExist = FALSE; + mUserInfo.UsageCount = 0; + + mUserInfo.AccessPolicyLen = 0; + mUserInfo.AccessPolicyModified = FALSE; + if (mUserInfo.AccessPolicy != NULL) { + FreePool (mUserInfo.AccessPolicy); + mUserInfo.AccessPolicy = NULL; + } + mUserInfo.IdentityPolicyLen = 0; + mUserInfo.IdentityPolicyModified = FALSE; + if (mUserInfo.IdentityPolicy != NULL) { + FreePool (mUserInfo.IdentityPolicy); + mUserInfo.IdentityPolicy = NULL; + } + + // + // Allocate user information memory. + // + MemSize = sizeof (EFI_USER_INFO) + 63; + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return ; + } + + // + // Get each user information. + // + UserInfo = NULL; + while (TRUE) { + Status = mUserManager->GetNextInfo (mUserManager, mModifyUser, &UserInfo); + if (EFI_ERROR (Status)) { + break; + } + // + // Get information. + // + InfoSize = MemSize; + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + UserInfo, + Info, + &InfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + MemSize = InfoSize; + FreePool (Info); + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return ; + } + + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + UserInfo, + Info, + &InfoSize + ); + } + + if (Status == EFI_SUCCESS) { + // + // Deal with each information according to informaiton type. + // + DataLen = Info->InfoSize - sizeof (EFI_USER_INFO); + switch (Info->InfoType) { + case EFI_USER_INFO_NAME_RECORD: + CopyMem (&mUserInfo.UserName, (UINT8 *) (Info + 1), DataLen); + break; + + case EFI_USER_INFO_CREATE_DATE_RECORD: + CopyMem (&mUserInfo.CreateDate, (UINT8 *) (Info + 1), DataLen); + mUserInfo.CreateDateExist = TRUE; + break; + + case EFI_USER_INFO_USAGE_DATE_RECORD: + CopyMem (&mUserInfo.UsageDate, (UINT8 *) (Info + 1), DataLen); + mUserInfo.UsageDateExist = TRUE; + break; + + case EFI_USER_INFO_USAGE_COUNT_RECORD: + CopyMem (&mUserInfo.UsageCount, (UINT8 *) (Info + 1), DataLen); + break; + + case EFI_USER_INFO_ACCESS_POLICY_RECORD: + mUserInfo.AccessPolicy = AllocateZeroPool (DataLen); + if (mUserInfo.AccessPolicy == NULL) { + break; + } + + CopyMem (mUserInfo.AccessPolicy, (UINT8 *) (Info + 1), DataLen); + mUserInfo.AccessPolicyLen = DataLen; + break; + + case EFI_USER_INFO_IDENTITY_POLICY_RECORD: + mUserInfo.IdentityPolicy = AllocateZeroPool (DataLen); + if (mUserInfo.IdentityPolicy == NULL) { + break; + } + + CopyMem (mUserInfo.IdentityPolicy, (UINT8 *) (Info + 1), DataLen); + mUserInfo.IdentityPolicyLen = DataLen; + break; + + default: + break; + } + } + } + FreePool (Info); +} + + +/** + Convert the Date to a string, and update the Hii database DateID string with it. + + @param[in] Date Points to the date to be converted. + @param[in] DateId String ID in the HII database to be replaced. + +**/ +VOID +ResolveDate ( + IN EFI_TIME *Date, + IN EFI_STRING_ID DateId + ) +{ + CHAR16 *Str; + UINTN DateBufLen; + + // + // Convert date to string. + // + DateBufLen = 64; + Str = AllocateZeroPool (DateBufLen); + if (Str == NULL) { + return ; + } + + UnicodeSPrint ( + Str, + DateBufLen, + L"%4d-%2d-%2d ", + Date->Year, + Date->Month, + Date->Day + ); + + // + // Convert time to string. + // + DateBufLen -= StrLen (Str); + UnicodeSPrint ( + Str + StrLen (Str), + DateBufLen, + L"%2d:%2d:%2d", + Date->Hour, + Date->Minute, + Date->Second + ); + + HiiSetString (mCallbackInfo->HiiHandle, DateId, Str, NULL); + FreePool (Str); +} + + +/** + Convert the CountVal to a string, and update the Hii database CountId string + with it. + + @param[in] CountVal The hex value to convert. + @param[in] CountId String ID in the HII database to be replaced. + +**/ +VOID +ResolveCount ( + IN UINT32 CountVal, + IN EFI_STRING_ID CountId + ) +{ + CHAR16 Count[10]; + + UnicodeSPrint (Count, 20, L"%d", CountVal); + HiiSetString (mCallbackInfo->HiiHandle, CountId, Count, NULL); +} + + +/** + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string. + + @param[in, out] Source1 On entry, point to a Null-terminated Unicode string. + On exit, point to a new concatenated Unicode string + @param[in] Source2 Pointer to a Null-terminated Unicode string. + +**/ +VOID +AddStr ( + IN OUT CHAR16 **Source1, + IN CONST CHAR16 *Source2 + ) +{ + CHAR16 *TmpStr; + UINTN StrLength; + + ASSERT (Source1 != NULL); + ASSERT (Source2 != NULL); + + if (*Source1 == NULL) { + StrLength = StrSize (Source2); + } else { + StrLength = StrSize (*Source1); + StrLength += StrSize (Source2) -1; + } + + TmpStr = AllocateZeroPool (StrLength); + ASSERT (TmpStr != NULL); + + if (*Source1 == NULL) { + StrCpy (TmpStr, Source2);; + } else { + StrCpy (TmpStr, *Source1); + FreePool (*Source1); + StrCat (TmpStr, Source2); + } + + *Source1 = TmpStr; +} + + +/** + Convert the identity policy to a unicode string and update the Hii database + IpStringId string with it. + + @param[in] Ip Points to identity policy. + @param[in] IpLen The identity policy length. + @param[in] IpStringId String ID in the HII database to be replaced. + +**/ +VOID +ResolveIdentityPolicy ( + IN UINT8 *Ip, + IN UINTN IpLen, + IN EFI_STRING_ID IpStringId + ) +{ + CHAR16 *TmpStr; + UINTN ChkLen; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + UINT16 Index; + CHAR16 *ProvStr; + EFI_STRING_ID ProvId; + EFI_HII_HANDLE HiiHandle; + EFI_USER_CREDENTIAL_PROTOCOL *UserCredential; + + TmpStr = NULL; + + // + // Resolve each policy. + // + ChkLen = 0; + while (ChkLen < IpLen) { + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (Ip + ChkLen); + switch (Identity->Type) { + case EFI_USER_INFO_IDENTITY_FALSE: + AddStr (&TmpStr, L"False"); + break; + + case EFI_USER_INFO_IDENTITY_TRUE: + AddStr (&TmpStr, L"None"); + break; + + case EFI_USER_INFO_IDENTITY_NOT: + AddStr (&TmpStr, L"! "); + break; + + case EFI_USER_INFO_IDENTITY_AND: + AddStr (&TmpStr, L" && "); + break; + + case EFI_USER_INFO_IDENTITY_OR: + AddStr (&TmpStr, L" || "); + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_TYPE: + for (Index = 0; Index < mProviderInfo->Count; Index++) { + UserCredential = mProviderInfo->Provider[Index]; + if (CompareGuid ((EFI_GUID *) (Identity + 1), &UserCredential->Type)) { + UserCredential->Title ( + UserCredential, + &HiiHandle, + &ProvId + ); + ProvStr = HiiGetString (HiiHandle, ProvId, NULL); + if (ProvStr != NULL) { + AddStr (&TmpStr, ProvStr); + FreePool (ProvStr); + } + break; + } + } + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + for (Index = 0; Index < mProviderInfo->Count; Index++) { + UserCredential = mProviderInfo->Provider[Index]; + if (CompareGuid ((EFI_GUID *) (Identity + 1), &UserCredential->Identifier)) { + UserCredential->Title ( + UserCredential, + &HiiHandle, + &ProvId + ); + ProvStr = HiiGetString (HiiHandle, ProvId, NULL); + if (ProvStr != NULL) { + AddStr (&TmpStr, ProvStr); + FreePool (ProvStr); + } + break; + } + } + break; + } + + ChkLen += Identity->Length; + } + + if (TmpStr != NULL) { + HiiSetString (mCallbackInfo->HiiHandle, IpStringId, TmpStr, NULL); + FreePool (TmpStr); + } +} + + +/** + Display modify user information form. + + This form displays, username, create Date, usage date, usage count, identity policy, + and access policy. + + @param[in] UserIndex The index of the user in display list to modify. + +**/ +VOID +ModifyUserInfo ( + IN UINT8 UserIndex + ) +{ + EFI_STATUS Status; + EFI_USER_PROFILE_HANDLE CurrentUser; + UINT32 CurrentAccessRight; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_USER_INFO_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Find the user profile to be modified. + // + mModifyUser = NULL; + Status = mUserManager->GetNext (mUserManager, &mModifyUser); + if (EFI_ERROR (Status)) { + return ; + } + + while (UserIndex > 1) { + Status = mUserManager->GetNext (mUserManager, &mModifyUser); + if (EFI_ERROR (Status)) { + return ; + } + UserIndex--; + } + + // + // Get user profile information. + // + GetAllUserInfo (); + + // + // Update user name. + HiiSetString ( + mCallbackInfo->HiiHandle, + STRING_TOKEN (STR_USER_NAME_VAL), + mUserInfo.UserName, + NULL + ); + + // + // Update create date. + // + if (mUserInfo.CreateDateExist) { + ResolveDate (&mUserInfo.CreateDate, STRING_TOKEN (STR_CREATE_DATE_VAL)); + } else { + HiiSetString ( + mCallbackInfo->HiiHandle, + STRING_TOKEN (STR_CREATE_DATE_VAL), + L"", + NULL + ); + } + + // + // Add usage date. + // + if (mUserInfo.UsageDateExist) { + ResolveDate (&mUserInfo.UsageDate, STRING_TOKEN (STR_USAGE_DATE_VAL)); + } else { + HiiSetString ( + mCallbackInfo->HiiHandle, + STRING_TOKEN (STR_USAGE_DATE_VAL), + L"", + NULL + ); + } + + // + // Add usage count. + // + ResolveCount ((UINT32) mUserInfo.UsageCount, STRING_TOKEN (STR_USAGE_COUNT_VAL)); + + // + // Add identity policy. + // + mUserManager->Current (mUserManager, &CurrentUser); + if (mModifyUser == CurrentUser) { + ResolveIdentityPolicy ( + mUserInfo.IdentityPolicy, + mUserInfo.IdentityPolicyLen, + STRING_TOKEN (STR_IDENTIFY_POLICY_VAL) + ); + HiiCreateGotoOpCode ( + StartOpCodeHandle, // Container for opcodes + FORMID_MODIFY_IP, // Target Form ID + STRING_TOKEN (STR_IDENTIFY_POLICY), // Prompt text + STRING_TOKEN (STR_IDENTIFY_POLICY_VAL), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP // Question ID + ); + } + + // + // Add access policy. + // + Status = GetAccessRight (&CurrentAccessRight); + if (EFI_ERROR (Status)) { + CurrentAccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; + } + + if (CurrentAccessRight == EFI_USER_INFO_ACCESS_MANAGE) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, // Container for opcodes + FORMID_MODIFY_AP, // Target Form ID + STRING_TOKEN (STR_ACCESS_POLICY), // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP // Question ID + ); + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_USER_INFO, // Form ID + StartOpCodeHandle, // Label + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + Get all the access policy info from current user info, and save in the global + variable. + +**/ +VOID +ResolveAccessPolicy ( + VOID + ) +{ + UINTN OffSet; + EFI_USER_INFO_ACCESS_CONTROL Control; + UINTN ValLen; + UINT8 *AccessData; + + // + // Set default value + // + mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; + mAccessInfo.AccessSetup = ACCESS_SETUP_RESTRICTED; + mAccessInfo.AccessBootOrder = EFI_USER_INFO_ACCESS_BOOT_ORDER_INSERT; + + mAccessInfo.LoadPermitLen = 0; + mAccessInfo.LoadForbidLen = 0; + mAccessInfo.ConnectPermitLen = 0; + mAccessInfo.ConnectForbidLen = 0; + + // + // Get each user access policy. + // + OffSet = 0; + while (OffSet < mUserInfo.AccessPolicyLen) { + CopyMem (&Control, mUserInfo.AccessPolicy + OffSet, sizeof (Control)); + ValLen = Control.Size - sizeof (Control); + switch (Control.Type) { + case EFI_USER_INFO_ACCESS_ENROLL_SELF: + mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_SELF; + break; + + case EFI_USER_INFO_ACCESS_ENROLL_OTHERS: + mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_ENROLL_OTHERS; + break; + + case EFI_USER_INFO_ACCESS_MANAGE: + mAccessInfo.AccessRight = EFI_USER_INFO_ACCESS_MANAGE; + break; + + case EFI_USER_INFO_ACCESS_SETUP: + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupNormalGuid)) { + mAccessInfo.AccessSetup = ACCESS_SETUP_NORMAL; + } else if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupRestrictedGuid)) { + mAccessInfo.AccessSetup = ACCESS_SETUP_RESTRICTED; + } else if (CompareGuid ((EFI_GUID *) AccessData, &gEfiUserInfoAccessSetupAdminGuid)) { + mAccessInfo.AccessSetup = ACCESS_SETUP_ADMIN; + } + break; + + case EFI_USER_INFO_ACCESS_BOOT_ORDER: + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + CopyMem (&mAccessInfo.AccessBootOrder, AccessData, sizeof (UINT32)); + break; + + case EFI_USER_INFO_ACCESS_FORBID_LOAD: + if (mAccessInfo.LoadForbid != NULL) { + FreePool (mAccessInfo.LoadForbid); + } + + mAccessInfo.LoadForbid = AllocateZeroPool (ValLen); + if (mAccessInfo.LoadForbid != NULL) { + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + CopyMem (mAccessInfo.LoadForbid, AccessData, ValLen); + mAccessInfo.LoadForbidLen = ValLen; + } + break; + + case EFI_USER_INFO_ACCESS_PERMIT_LOAD: + if (mAccessInfo.LoadPermit != NULL) { + FreePool (mAccessInfo.LoadPermit); + } + + mAccessInfo.LoadPermit = AllocateZeroPool (ValLen); + if (mAccessInfo.LoadPermit != NULL) { + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + CopyMem (mAccessInfo.LoadPermit, AccessData, ValLen); + mAccessInfo.LoadPermitLen = ValLen; + } + break; + + case EFI_USER_INFO_ACCESS_FORBID_CONNECT: + if (mAccessInfo.ConnectForbid != NULL) { + FreePool (mAccessInfo.ConnectForbid); + } + + mAccessInfo.ConnectForbid = AllocateZeroPool (ValLen); + if (mAccessInfo.ConnectForbid != NULL) { + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + CopyMem (mAccessInfo.ConnectForbid, AccessData, ValLen); + mAccessInfo.ConnectForbidLen = ValLen; + } + break; + + case EFI_USER_INFO_ACCESS_PERMIT_CONNECT: + if (mAccessInfo.ConnectPermit != NULL) { + FreePool (mAccessInfo.ConnectPermit); + } + + mAccessInfo.ConnectPermit = AllocateZeroPool (ValLen); + if (mAccessInfo.ConnectPermit != NULL) { + AccessData = mUserInfo.AccessPolicy + OffSet + sizeof (Control); + CopyMem (mAccessInfo.ConnectPermit, AccessData, ValLen); + mAccessInfo.ConnectPermitLen = ValLen; + } + break; + } + + OffSet += Control.Size; + } +} + + +/** + Find the specified info in profile mModifyUser by the InfoType. + + @param[in] InfoType The user information type to find. + @param[out] UserInfo Points to user information handle found. + + @retval EFI_SUCCESS Find the user information successfully. + @retval Others Fail to find the user information. + +**/ +EFI_STATUS +FindInfoByType ( + IN UINT8 InfoType, + OUT EFI_USER_INFO_HANDLE *UserInfo + ) +{ + EFI_STATUS Status; + EFI_USER_INFO *Info; + UINTN InfoSize; + UINTN MemSize; + + if (UserInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + *UserInfo = NULL; + // + // Allocate user information memory. + // + MemSize = sizeof (EFI_USER_INFO) + 63; + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get each user information. + // + while (TRUE) { + Status = mUserManager->GetNextInfo (mUserManager, mModifyUser, UserInfo); + if (EFI_ERROR (Status)) { + break; + } + // + // Get information. + // + InfoSize = MemSize; + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + *UserInfo, + Info, + &InfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + MemSize = InfoSize; + FreePool (Info); + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + *UserInfo, + Info, + &InfoSize + ); + } + if (Status == EFI_SUCCESS) { + if (Info->InfoType == InfoType) { + break; + } + } + } + + FreePool (Info); + return Status; +} + + +/** + Display modify user access policy form. + + In this form, access right, access setup and access boot order are dynamically + added. Load devicepath and connect devicepath are displayed too. + +**/ +VOID +ModidyAccessPolicy ( + VOID + ) +{ + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + VOID *OptionsOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + VOID *DefaultOpCodeHandle; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_AP_MOD_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + + // + // Resolve access policy information. + // + ResolveAccessPolicy (); + + // + // Add access right one-of-code. + // + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NORMAL), + 0, + EFI_IFR_NUMERIC_SIZE_1, + EFI_USER_INFO_ACCESS_ENROLL_SELF + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_ENROLL), + 0, + EFI_IFR_NUMERIC_SIZE_1, + EFI_USER_INFO_ACCESS_ENROLL_OTHERS + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_MANAGE), + 0, + EFI_IFR_NUMERIC_SIZE_1, + EFI_USER_INFO_ACCESS_MANAGE + ); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_NUMERIC_SIZE_1, + mAccessInfo.AccessRight + ); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_RIGHT, // Question ID + 0, // VarStore ID + 0, // Offset in Buffer Storage + STRING_TOKEN (STR_ACCESS_RIGHT), // Question prompt text + STRING_TOKEN (STR_ACCESS_RIGHT_HELP), // Question help text + EFI_IFR_FLAG_CALLBACK, // Question flag + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value + OptionsOpCodeHandle, // Option Opcode list + DefaultOpCodeHandle // Default Opcode + ); + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + + // + // Add setup type one-of-code. + // + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_RESTRICTED), + 0, + EFI_IFR_NUMERIC_SIZE_1, + ACCESS_SETUP_RESTRICTED + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NORMAL), + 0, + EFI_IFR_NUMERIC_SIZE_1, + ACCESS_SETUP_NORMAL + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_ADMIN), + 0, + EFI_IFR_NUMERIC_SIZE_1, + ACCESS_SETUP_ADMIN + ); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_NUMERIC_SIZE_1, + mAccessInfo.AccessSetup + ); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_SETUP, // Question ID + 0, // VarStore ID + 0, // Offset in Buffer Storage + STRING_TOKEN (STR_ACCESS_SETUP), // Question prompt text + STRING_TOKEN (STR_ACCESS_SETUP_HELP), // Question help text + EFI_IFR_FLAG_CALLBACK, // Question flag + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value + OptionsOpCodeHandle, // Option Opcode list + DefaultOpCodeHandle // Default Opcode + ); + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + // + // Add boot order one-of-code. + // + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + DefaultOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (DefaultOpCodeHandle != NULL); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_INSERT), + 0, + EFI_IFR_NUMERIC_SIZE_4, + EFI_USER_INFO_ACCESS_BOOT_ORDER_INSERT + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_APPEND), + 0, + EFI_IFR_NUMERIC_SIZE_4, + EFI_USER_INFO_ACCESS_BOOT_ORDER_APPEND + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_REPLACE), + 0, + EFI_IFR_NUMERIC_SIZE_4, + EFI_USER_INFO_ACCESS_BOOT_ORDER_REPLACE + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_NODEFAULT), + 0, + EFI_IFR_NUMERIC_SIZE_4, + EFI_USER_INFO_ACCESS_BOOT_ORDER_NODEFAULT + ); + + HiiCreateDefaultOpCode ( + DefaultOpCodeHandle, + EFI_HII_DEFAULT_CLASS_STANDARD, + EFI_IFR_NUMERIC_SIZE_4, + mAccessInfo.AccessBootOrder + ); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_AP | KEY_MODIFY_BOOT, // Question ID + 0, // VarStore ID + 0, // Offset in Buffer Storage + STRING_TOKEN (STR_BOOR_ORDER), // Question prompt text + STRING_TOKEN (STR_BOOT_ORDER_HELP), // Question help text + EFI_IFR_FLAG_CALLBACK, // Question flag + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value + OptionsOpCodeHandle, // Option Opcode list + DefaultOpCodeHandle // Default Opcode + ); + HiiFreeOpCodeHandle (DefaultOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + // + // Update Form. + // + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_MODIFY_AP, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + Expand access policy memory size. + + @param[in] ValidLen The valid access policy length. + @param[in] ExpandLen The length that is needed to expand. + +**/ +VOID +ExpandMemory ( + IN UINTN ValidLen, + IN UINTN ExpandLen + ) +{ + UINT8 *Mem; + UINTN Len; + + // + // Expand memory. + // + Len = mUserInfo.AccessPolicyLen + (ExpandLen / 64 + 1) * 64; + Mem = AllocateZeroPool (Len); + ASSERT (Mem != NULL); + + if (mUserInfo.AccessPolicy != NULL) { + CopyMem (Mem, mUserInfo.AccessPolicy, ValidLen); + FreePool (mUserInfo.AccessPolicy); + } + + mUserInfo.AccessPolicy = Mem; + mUserInfo.AccessPolicyLen = Len; +} + + +/** + Collect all the access policy data to mUserInfo.AccessPolicy, + and save it to user profile. + +**/ +VOID +SaveAccessPolicy ( + VOID + ) +{ + EFI_STATUS Status; + UINTN OffSet; + UINTN Size; + EFI_USER_INFO_ACCESS_CONTROL Control; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + + if (mUserInfo.AccessPolicy != NULL) { + FreePool (mUserInfo.AccessPolicy); + } + mUserInfo.AccessPolicy = NULL; + mUserInfo.AccessPolicyLen = 0; + mUserInfo.AccessPolicyModified = TRUE; + OffSet = 0; + + // + // Save access right. + // + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL); + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = mAccessInfo.AccessRight; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + // + // Save access setup. + // + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (EFI_GUID); + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_SETUP; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + if (mAccessInfo.AccessSetup == ACCESS_SETUP_NORMAL) { + CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupNormalGuid); + } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_RESTRICTED) { + CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupRestrictedGuid); + } else if (mAccessInfo.AccessSetup == ACCESS_SETUP_ADMIN) { + CopyGuid ((EFI_GUID *) (mUserInfo.AccessPolicy + OffSet), &gEfiUserInfoAccessSetupAdminGuid); + } + OffSet += sizeof (EFI_GUID); + + // + // Save access of boot order. + // + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + sizeof (UINT32); + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_BOOT_ORDER; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + CopyMem ((UINT8 *) (mUserInfo.AccessPolicy + OffSet), &mAccessInfo.AccessBootOrder, sizeof (UINT32)); + OffSet += sizeof (UINT32); + + // + // Save permit load. + // + if (mAccessInfo.LoadPermitLen > 0) { + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadPermitLen; + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_PERMIT_LOAD; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadPermit, mAccessInfo.LoadPermitLen); + OffSet += mAccessInfo.LoadPermitLen; + } + + // + // Save forbid load. + // + if (mAccessInfo.LoadForbidLen > 0) { + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.LoadForbidLen; + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_FORBID_LOAD; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen); + OffSet += mAccessInfo.LoadForbidLen; + } + + // + // Save permit connect. + // + if (mAccessInfo.ConnectPermitLen > 0) { + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectPermitLen; + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_PERMIT_CONNECT; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectPermit, mAccessInfo.ConnectPermitLen); + OffSet += mAccessInfo.ConnectPermitLen; + } + + // + // Save forbid connect. + // + if (mAccessInfo.ConnectForbidLen > 0) { + Size = sizeof (EFI_USER_INFO_ACCESS_CONTROL) + mAccessInfo.ConnectForbidLen; + if (mUserInfo.AccessPolicyLen - OffSet < Size) { + ExpandMemory (OffSet, Size); + } + + Control.Type = EFI_USER_INFO_ACCESS_FORBID_CONNECT; + Control.Size = (UINT32) Size; + CopyMem (mUserInfo.AccessPolicy + OffSet, &Control, sizeof (Control)); + OffSet += sizeof (Control); + + CopyMem (mUserInfo.AccessPolicy + OffSet, mAccessInfo.ConnectForbid, mAccessInfo.ConnectForbidLen); + OffSet += mAccessInfo.ConnectForbidLen; + } + + mUserInfo.AccessPolicyLen = OffSet; + + // + // Save access policy. + // + if (mUserInfo.AccessPolicyModified && (mUserInfo.AccessPolicyLen > 0)) { + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen); + if (Info == NULL) { + return ; + } + + Status = FindInfoByType (EFI_USER_INFO_ACCESS_POLICY_RECORD, &UserInfo); + if (!EFI_ERROR (Status)) { + Info->InfoType = EFI_USER_INFO_ACCESS_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PUBLIC | + EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.AccessPolicyLen); + CopyMem ((UINT8 *) (Info + 1), mUserInfo.AccessPolicy, mUserInfo.AccessPolicyLen); + Status = mUserManager->SetInfo ( + mUserManager, + mModifyUser, + &UserInfo, + Info, + Info->InfoSize + ); + mUserInfo.AccessPolicyModified = FALSE; + } + FreePool (Info); + } + + if (mAccessInfo.ConnectForbid != NULL) { + FreePool (mAccessInfo.ConnectForbid); + mAccessInfo.ConnectForbid = NULL; + } + + if (mAccessInfo.ConnectPermit != NULL) { + FreePool (mAccessInfo.ConnectPermit); + mAccessInfo.ConnectPermit = NULL; + } + + if (mAccessInfo.LoadForbid != NULL) { + FreePool (mAccessInfo.LoadForbid); + mAccessInfo.LoadForbid = NULL; + } + + if (mAccessInfo.LoadPermit != NULL) { + FreePool (mAccessInfo.LoadPermit); + mAccessInfo.LoadPermit = NULL; + } +} + + +/** + Get the username from user input, and update username string in the Hii + database with it. + +**/ +VOID +ModifyUserName ( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 UserName[USER_NAME_LENGTH]; + UINTN Len; + EFI_INPUT_KEY Key; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + EFI_USER_PROFILE_HANDLE TempUser; + + // + // Get the new user name. + // + Len = sizeof (UserName); + Status = GetUserNameInput (&Len, UserName); + if (EFI_ERROR (Status)) { + if (Status != EFI_ABORTED) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Failed To Get User Name.", + L"", + L"Please Press Any Key to Continue ...", + NULL + ); + } + return ; + } + + // + // Check whether the username had been used or not. + // + Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + Len); + if (Info == NULL) { + return ; + } + + Info->InfoType = EFI_USER_INFO_NAME_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PUBLIC | + EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + Len); + CopyMem ((UINT8 *) (Info + 1), UserName, Len); + + TempUser = NULL; + Status = mUserManager->Find ( + mUserManager, + &TempUser, + NULL, + Info, + Info->InfoSize + ); + if (!EFI_ERROR (Status)) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"The User Name Had Been Used.", + L"", + L"Please Use Other User Name", + NULL + ); + FreePool (Info); + return ; + } + + // + // Update username display in the form. + // + CopyMem (mUserInfo.UserName, UserName, Len); + HiiSetString ( + mCallbackInfo->HiiHandle, + STRING_TOKEN (STR_USER_NAME_VAL), + mUserInfo.UserName, + NULL + ); + + // + // Save the user name. + // + Status = FindInfoByType (EFI_USER_INFO_NAME_RECORD, &UserInfo); + if (!EFI_ERROR (Status)) { + mUserManager->SetInfo ( + mUserManager, + mModifyUser, + &UserInfo, + Info, + Info->InfoSize + ); + } + FreePool (Info); +} + + +/** + Display the form of the modifying user identity policy. + +**/ +VOID +ModifyIdentityPolicy ( + VOID + ) +{ + UINTN Index; + CHAR16 *ProvStr; + EFI_STRING_ID ProvID; + EFI_HII_HANDLE HiiHandle; + VOID *OptionsOpCodeHandle; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_IP_MOD_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add credential providers + //. + if (mProviderInfo->Count > 0) { + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + // + // Add credential provider Option OpCode. + // + for (Index = 0; Index < mProviderInfo->Count; Index++) { + mProviderInfo->Provider[Index]->Title ( + mProviderInfo->Provider[Index], + &HiiHandle, + &ProvID + ); + ProvStr = HiiGetString (HiiHandle, ProvID, NULL); + ProvID = HiiSetString (mCallbackInfo->HiiHandle, 0, ProvStr, NULL); + FreePool (ProvStr); + if (ProvID == 0) { + return ; + } + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + ProvID, + 0, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) Index + ); + } + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP | KEY_MODIFY_PROV, // Question ID + 0, // VarStore ID + 0, // Offset in Buffer Storage + STRING_TOKEN (STR_PROVIDER), // Question prompt text + STRING_TOKEN (STR_PROVIDER_HELP), // Question help text + EFI_IFR_FLAG_CALLBACK, // Question flag + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value + OptionsOpCodeHandle, // Option Opcode list + NULL // Default Opcode is NULl + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + } + + // + // Add logical connector Option OpCode. + // + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_AND_CON), + 0, + EFI_IFR_NUMERIC_SIZE_1, + 0 + ); + + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + STRING_TOKEN (STR_OR_CON), + 0, + EFI_IFR_NUMERIC_SIZE_1, + 1 + ); + + HiiCreateOneOfOpCode ( + StartOpCodeHandle, // Container for dynamic created opcodes + KEY_MODIFY_USER | KEY_SELECT_USER | KEY_MODIFY_IP | KEY_MODIFY_CONN, // Question ID + 0, // VarStore ID + 0, // Offset in Buffer Storage + STRING_TOKEN (STR_CONNECTOR), // Question prompt text + STRING_TOKEN (STR_CONNECTOR_HELP), // Question help text + EFI_IFR_FLAG_CALLBACK, // Question flag + EFI_IFR_NUMERIC_SIZE_1, // Data type of Question Value + OptionsOpCodeHandle, // Option Opcode list + NULL // Default Opcode is NULl + ); + + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + // + // Update identity policy in the form. + // + ResolveIdentityPolicy ( + mUserInfo.IdentityPolicy, + mUserInfo.IdentityPolicyLen, + STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE) + ); + + if (mUserInfo.NewIdentityPolicy != NULL) { + FreePool (mUserInfo.NewIdentityPolicy); + mUserInfo.NewIdentityPolicy = NULL; + mUserInfo.NewIdentityPolicyLen = 0; + mUserInfo.NewIdentityPolicyModified = FALSE; + } + mProviderChoice = 0; + mConncetLogical = 0; + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_MODIFY_IP, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + Save the identity policy and update UI with it. + + This funciton will verify the new identity policy, in current implementation, + the identity policy can be: T, P & P & P & ..., P | P | P | ... + Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or". + Other identity policies are not supported. + +**/ +VOID +SaveIdentityPolicy ( + VOID + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + EFI_INPUT_KEY Key; + UINTN Offset; + UINT32 OpCode; + UINTN InfoSize; + + if (!mUserInfo.NewIdentityPolicyModified || (mUserInfo.NewIdentityPolicyLen == 0)) { + return; + } + + // + // Check policy expression. + // + OpCode = EFI_USER_INFO_IDENTITY_FALSE; + Offset = 0; + while (Offset < mUserInfo.NewIdentityPolicyLen) { + // + // Check access policy according to type + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset); + switch (Identity->Type) { + + case EFI_USER_INFO_IDENTITY_TRUE: + break; + + case EFI_USER_INFO_IDENTITY_OR: + if (OpCode == EFI_USER_INFO_IDENTITY_AND) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Invalid Identity Policy, Mixed Connector Unsupport!", + L"", + L"Press Any Key to Continue ...", + NULL + ); + return ; + } + + OpCode = EFI_USER_INFO_IDENTITY_OR; + break; + + case EFI_USER_INFO_IDENTITY_AND: + if (OpCode == EFI_USER_INFO_IDENTITY_OR) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Invalid Identity Policy, Mixed Connector Unsupport!", + L"", + L"Press Any Key to Continue ...", + NULL + ); + return ; + } + + OpCode = EFI_USER_INFO_IDENTITY_AND; + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + break; + + default: + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Unsupport parameter", + L"", + L"Press Any Key to Continue ...", + NULL + ); + return ; + } + Offset += Identity->Length; + } + + // + // Save identity policy. + // + Info = AllocateZeroPool ( + sizeof (EFI_USER_INFO) + + mUserInfo.NewIdentityPolicyLen + ); + if (Info == NULL) { + return ; + } + + Status = FindInfoByType (EFI_USER_INFO_IDENTITY_POLICY_RECORD, &UserInfo); + if (EFI_ERROR (Status)) { + FreePool (Info); + return ; + } + + Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD; + Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | + EFI_USER_INFO_PRIVATE | + EFI_USER_INFO_EXCLUSIVE; + Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen); + CopyMem ((UINT8 *) (Info + 1), mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen); + Status = mUserManager->SetInfo ( + mUserManager, + mModifyUser, + &UserInfo, + Info, + Info->InfoSize + ); + FreePool (Info); + if (EFI_ERROR (Status)) { + // + // Get the user information again, it may be changed during saving it. + // + InfoSize = 0; + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + UserInfo, + Info, + &InfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + Info = AllocateZeroPool (InfoSize); + ASSERT (Info != NULL); + Status = mUserManager->GetInfo ( + mUserManager, + mModifyUser, + UserInfo, + Info, + &InfoSize + ); + } + ASSERT_EFI_ERROR (Status); + + // + // Save current identification policy to mUserInfo.IdentityPolicy. + // + ASSERT (Info != NULL); + if (mUserInfo.IdentityPolicy != NULL) { + FreePool (mUserInfo.IdentityPolicy); + } + + mUserInfo.IdentityPolicyLen = Info->InfoSize - sizeof (EFI_USER_INFO); + mUserInfo.IdentityPolicy = AllocateCopyPool (mUserInfo.IdentityPolicyLen, Info + 1); + ASSERT (mUserInfo.IdentityPolicy != NULL); + + // + // Free the memory + // + FreePool (Info); + FreePool (mUserInfo.NewIdentityPolicy); + } else { + // + // Update the mUserInfo.IdentityPolicy by mUserInfo.NewIdentityPolicy + // + if (mUserInfo.IdentityPolicy != NULL) { + FreePool (mUserInfo.IdentityPolicy); + } + mUserInfo.IdentityPolicy = mUserInfo.NewIdentityPolicy; + mUserInfo.IdentityPolicyLen = mUserInfo.NewIdentityPolicyLen; + } + + mUserInfo.NewIdentityPolicy = NULL; + mUserInfo.NewIdentityPolicyLen = 0; + mUserInfo.NewIdentityPolicyModified = FALSE; + + // + // Update identity policy choice. + // + ResolveIdentityPolicy ( + mUserInfo.IdentityPolicy, + mUserInfo.IdentityPolicyLen, + STRING_TOKEN (STR_IDENTIFY_POLICY_VAL) + ); +} + + +/** + Verify the new identity policy in the current implementation. The same credential + provider can't appear twice in one identity policy. + + @param[in] NewGuid Points to the credential provider guid. + + @retval TRUE The NewGuid was found in the identity policy. + @retval FALSE The NewGuid was not found. + +**/ +BOOLEAN +CheckIdentityPolicy ( + IN EFI_GUID *NewGuid + ) +{ + UINTN Offset; + EFI_USER_INFO_IDENTITY_POLICY *Identity; + EFI_INPUT_KEY Key; + + Offset = 0; + while (Offset < mUserInfo.NewIdentityPolicyLen) { + // + // Check access policy according to type. + // + Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset); + switch (Identity->Type) { + + case EFI_USER_INFO_IDENTITY_TRUE: + case EFI_USER_INFO_IDENTITY_OR: + case EFI_USER_INFO_IDENTITY_AND: + break; + + case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: + if (CompareGuid (NewGuid, (EFI_GUID *) (Identity + 1))) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"This Credential Provider Are Already Used!", + L"", + L"Press Any Key to Continue ...", + NULL + ); + return FALSE; + } + break; + + default: + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Unsupport parameter", + L"", + L"Press Any Key to Continue ...", + NULL + ); + return FALSE; + } + + Offset += Identity->Length; + } + return TRUE; +} + + +/** + Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed. + +**/ +VOID +AddIdentityPolicyItem ( + VOID + ) +{ + UINT8 *NewInfo; + EFI_USER_INFO_IDENTITY_POLICY *Policy; + + if (mProviderInfo->Count == 0) { + return ; + } + + if (!mUserInfo.NewIdentityPolicyModified && (mUserInfo.NewIdentityPolicyLen > 0)) { + FreePool (mUserInfo.NewIdentityPolicy); + mUserInfo.NewIdentityPolicy = NULL; + mUserInfo.NewIdentityPolicyLen = 0; + } + // + // Expand the identity policy memory for the newly added policy info. + // + if (mUserInfo.NewIdentityPolicyLen > 0) { + // + // The new policy is not empty, expand space for connetor and provider. + // + if (!CheckIdentityPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier)) { + return ; + } + NewInfo = AllocateZeroPool ( + mUserInfo.NewIdentityPolicyLen + + sizeof (EFI_USER_INFO_IDENTITY_POLICY) * 2 + + sizeof (EFI_GUID) + ); + } else { + // + // The new policy is empty, only expand space for provider. + // + NewInfo = AllocateZeroPool ( + mUserInfo.NewIdentityPolicyLen + + sizeof (EFI_USER_INFO_IDENTITY_POLICY) + + sizeof (EFI_GUID) + ); + } + + if (NewInfo == NULL) { + return ; + } + + if (mUserInfo.NewIdentityPolicyLen > 0) { + CopyMem (NewInfo, mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen); + FreePool (mUserInfo.NewIdentityPolicy); + } + mUserInfo.NewIdentityPolicy = NewInfo; + + // + // Save logical connector. + // + if (mUserInfo.NewIdentityPolicyLen > 0) { + Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + + mUserInfo.NewIdentityPolicyLen); + if (mConncetLogical == 0) { + Policy->Type = EFI_USER_INFO_IDENTITY_AND; + } else { + Policy->Type = EFI_USER_INFO_IDENTITY_OR; + } + + Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); + mUserInfo.NewIdentityPolicyLen += Policy->Length; + } + + // + // Save credential provider. + // + Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + + mUserInfo.NewIdentityPolicyLen); + Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID); + Policy->Type = EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER; + CopyGuid ((EFI_GUID *) (Policy + 1), &mProviderInfo->Provider[mProviderChoice]->Identifier); + mUserInfo.NewIdentityPolicyLen += Policy->Length; + + // + // Update identity policy choice. + // + mUserInfo.NewIdentityPolicyModified = TRUE; + ResolveIdentityPolicy ( + mUserInfo.NewIdentityPolicy, + mUserInfo.NewIdentityPolicyLen, + STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE) + ); +} + + +/** + Create an action OpCode with QuestionID and DevicePath on a given OpCodeHandle. + + @param[in] QuestionID The question ID. + @param[in] DevicePath Points to device path. + @param[in] OpCodeHandle Points to container for dynamic created opcodes. + +**/ +VOID +AddDevicePath ( + IN UINTN QuestionID, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN VOID *OpCodeHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_STRING_ID NameID; + EFI_STRING DriverName; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevicePathText; + + // + // Locate device path to text protocol. + // + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevicePathText + ); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Get driver file name node. + // + Next = DevicePath; + while (!IsDevicePathEnd (Next)) { + DevicePath = Next; + Next = NextDevicePathNode (Next); + } + + // + // Display the device path in form. + // + DriverName = DevicePathText->ConvertDevicePathToText (DevicePath, FALSE, FALSE); + NameID = HiiSetString (mCallbackInfo->HiiHandle, 0, DriverName, NULL); + FreePool (DriverName); + if (NameID == 0) { + return ; + } + + HiiCreateActionOpCode ( + OpCodeHandle, // Container for dynamic created opcodes + (UINT16) QuestionID, // Question ID + NameID, // Prompt text + STRING_TOKEN (STR_NULL_STRING), // Help text + EFI_IFR_FLAG_CALLBACK, // Question flag + 0 // Action String ID + ); +} + + +/** + Check whether the DevicePath is in the device path forbid list + (mAccessInfo.LoadForbid). + + @param[in] DevicePath Points to device path. + + @retval TRUE The DevicePath is in the device path forbid list. + @retval FALSE The DevicePath is not in the device path forbid list. + +**/ +BOOLEAN +IsLoadForbidden ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN OffSet; + UINTN DPSize; + UINTN Size; + EFI_DEVICE_PATH_PROTOCOL *Dp; + + OffSet = 0; + Size = GetDevicePathSize (DevicePath); + // + // Check each device path. + // + while (OffSet < mAccessInfo.LoadForbidLen) { + Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); + DPSize = GetDevicePathSize (Dp); + // + // Compare device path. + // + if ((DPSize == Size) && (CompareMem (DevicePath, Dp, Size) == 0)) { + return TRUE; + } + OffSet += DPSize; + } + return FALSE; +} + + +/** + Display the permit load device path in the loadable device path list. + +**/ +VOID +DisplayLoadPermit( + VOID + ) +{ + EFI_STATUS Status; + CHAR16 *Order; + UINTN OrderSize; + UINTN ListCount; + UINTN Index; + UINT8 *Var; + UINT8 *VarPtr; + CHAR16 VarName[12]; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Get DriverOrder. + // + OrderSize = 0; + Status = gRT->GetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + NULL, + &OrderSize, + NULL + ); + if (Status != EFI_BUFFER_TOO_SMALL) { + return ; + } + + Order = AllocateZeroPool (OrderSize); + if (Order == NULL) { + return ; + } + + Status = gRT->GetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + NULL, + &OrderSize, + Order + ); + if (EFI_ERROR (Status)) { + return ; + } + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABEL_PERMIT_LOAD_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add each driver option. + // + Var = NULL; + ListCount = OrderSize / sizeof (UINT16); + for (Index = 0; Index < ListCount; Index++) { + // + // Get driver device path. + // + UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", Order[Index]); + Var = GetEfiGlobalVariable (VarName); + if (Var == NULL) { + continue; + } + + // + // Check whether the driver is already forbidden. + // + + VarPtr = Var; + // + // Skip attribute. + // + VarPtr += sizeof (UINT32); + + // + // Skip device path lenth. + // + VarPtr += sizeof (UINT16); + + // + // Skip descript string. + // + VarPtr += StrSize ((UINT16 *) VarPtr); + + if (IsLoadForbidden ((EFI_DEVICE_PATH_PROTOCOL *) VarPtr)) { + FreePool (Var); + Var = NULL; + continue; + } + + AddDevicePath ( + KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_PERMIT_MODIFY | Order[Index], + (EFI_DEVICE_PATH_PROTOCOL *) VarPtr, + StartOpCodeHandle + ); + FreePool (Var); + Var = NULL; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_PERMIT_LOAD_DP, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + // + // Clear Environment. + // + if (Var != NULL) { + FreePool (Var); + } + FreePool (Order); +} + + +/** + Display the forbid load device path list (mAccessInfo.LoadForbid). + +**/ +VOID +DisplayLoadForbid ( + VOID + ) +{ + UINTN Offset; + UINTN DPSize; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *Dp; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Initialize the container for dynamic opcodes. + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode. + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + StartOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = LABLE_FORBID_LOAD_FUNC; + + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( + EndOpCodeHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Add each forbid load drivers. + // + Offset = 0; + Index = 0; + while (Offset < mAccessInfo.LoadForbidLen) { + Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + Offset); + DPSize = GetDevicePathSize (Dp); + AddDevicePath ( + KEY_MODIFY_USER | KEY_MODIFY_AP_DP | KEY_LOAD_FORBID_MODIFY | Index, + Dp, + StartOpCodeHandle + ); + Index++; + Offset += DPSize; + } + + HiiUpdateForm ( + mCallbackInfo->HiiHandle, // HII handle + &mUserProfileManagerGuid, // Formset GUID + FORMID_FORBID_LOAD_DP, // Form ID + StartOpCodeHandle, // Label for where to insert opcodes + EndOpCodeHandle // Replace data + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); +} + + +/** + Display the permit connect device path. + +**/ +VOID +DisplayConnectPermit ( + VOID + ) +{ + // + // Note: + // As no architect protocol/interface to be called in ConnectController() + // to verify the device path, just add a place holder for permitted connect + // device path. + // +} + + +/** + Display the forbid connect device path list. + +**/ +VOID +DisplayConnectForbid ( + VOID + ) +{ + // + // Note: + // As no architect protocol/interface to be called in ConnectController() + // to verify the device path, just add a place holder for forbidden connect + // device path. + // +} + + +/** + Delete the specified device path by DriverIndex from the forbid device path + list (mAccessInfo.LoadForbid). + + @param[in] DriverIndex The index of driver in forbidden device path list. + +**/ +VOID +DeleteFromForbidLoad ( + IN UINT16 DriverIndex + ) +{ + UINTN OffSet; + UINTN DPSize; + UINTN OffLen; + EFI_DEVICE_PATH_PROTOCOL *Dp; + + OffSet = 0; + // + // Find the specified device path. + // + while ((OffSet < mAccessInfo.LoadForbidLen) && (DriverIndex > 0)) { + Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); + DPSize = GetDevicePathSize (Dp); + OffSet += DPSize; + DriverIndex--; + } + + // + // Specified device path found. + // + if (DriverIndex == 0) { + Dp = (EFI_DEVICE_PATH_PROTOCOL *) (mAccessInfo.LoadForbid + OffSet); + DPSize = GetDevicePathSize (Dp); + OffLen = mAccessInfo.LoadForbidLen - OffSet - DPSize; + if (OffLen > 0) { + CopyMem ( + mAccessInfo.LoadForbid + OffSet, + mAccessInfo.LoadForbid + OffSet + DPSize, + OffLen + ); + } + mAccessInfo.LoadForbidLen -= DPSize; + } +} + + +/** + Add the specified device path by DriverIndex to the forbid device path + list (mAccessInfo.LoadForbid). + + @param[in] DriverIndex The index of driver saved in driver options. + +**/ +VOID +AddToForbidLoad ( + IN UINT16 DriverIndex + ) +{ + UINTN DevicePathLen; + UINT8 *Var; + UINT8 *VarPtr; + UINTN NewLen; + UINT8 *NewFL; + CHAR16 VarName[13]; + + // + // Get loadable driver device path. + // + UnicodeSPrint (VarName, sizeof (VarName), L"Driver%04x", DriverIndex); + Var = GetEfiGlobalVariable (VarName); + if (Var == NULL) { + return; + } + + // + // Save forbid load driver. + // + + VarPtr = Var; + // + // Skip attribute. + // + VarPtr += sizeof (UINT32); + + DevicePathLen = *(UINT16 *) VarPtr; + // + // Skip device path length. + // + VarPtr += sizeof (UINT16); + + // + // Skip description string. + // + VarPtr += StrSize ((UINT16 *) VarPtr); + + NewLen = mAccessInfo.LoadForbidLen + DevicePathLen; + NewFL = AllocateZeroPool (NewLen); + if (NewFL == NULL) { + FreePool (Var); + return ; + } + + if (mAccessInfo.LoadForbidLen > 0) { + CopyMem (NewFL, mAccessInfo.LoadForbid, mAccessInfo.LoadForbidLen); + FreePool (mAccessInfo.LoadForbid); + } + + CopyMem (NewFL + mAccessInfo.LoadForbidLen, VarPtr, DevicePathLen); + mAccessInfo.LoadForbidLen = NewLen; + mAccessInfo.LoadForbid = NewFL; + FreePool (Var); +} + + +/** + Get current user's access right. + + @param[out] AccessRight Points to the buffer used for user's access right. + + @retval EFI_SUCCESS Get current user access right successfully. + @retval others Fail to get current user access right. + +**/ +EFI_STATUS +GetAccessRight ( + OUT UINT32 *AccessRight + ) +{ + EFI_STATUS Status; + EFI_USER_INFO_HANDLE UserInfo; + EFI_USER_INFO *Info; + UINTN InfoSize; + UINTN MemSize; + EFI_USER_INFO_ACCESS_CONTROL Access; + EFI_USER_PROFILE_HANDLE CurrentUser; + UINTN TotalLen; + UINTN CheckLen; + + // + // Allocate user information memory. + // + MemSize = sizeof (EFI_USER_INFO) + 63; + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get user access information. + // + UserInfo = NULL; + mUserManager->Current (mUserManager, &CurrentUser); + while (TRUE) { + InfoSize = MemSize; + // + // Get next user information. + // + Status = mUserManager->GetNextInfo (mUserManager, CurrentUser, &UserInfo); + if (EFI_ERROR (Status)) { + break; + } + + Status = mUserManager->GetInfo ( + mUserManager, + CurrentUser, + UserInfo, + Info, + &InfoSize + ); + if (Status == EFI_BUFFER_TOO_SMALL) { + MemSize = InfoSize; + FreePool (Info); + Info = AllocateZeroPool (MemSize); + if (Info == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Status = mUserManager->GetInfo ( + mUserManager, + CurrentUser, + UserInfo, + Info, + &InfoSize + ); + } + if (EFI_ERROR (Status)) { + break; + } + + // + // Check user information. + // + if (Info->InfoType == EFI_USER_INFO_ACCESS_POLICY_RECORD) { + TotalLen = Info->InfoSize - sizeof (EFI_USER_INFO); + CheckLen = 0; + // + // Get specified access information. + // + while (CheckLen < TotalLen) { + CopyMem (&Access, (UINT8 *) (Info + 1) + CheckLen, sizeof (Access)); + if ((Access.Type == EFI_USER_INFO_ACCESS_ENROLL_SELF) || + (Access.Type == EFI_USER_INFO_ACCESS_ENROLL_OTHERS) || + (Access.Type == EFI_USER_INFO_ACCESS_MANAGE) + ) { + *AccessRight = Access.Type; + FreePool (Info); + return EFI_SUCCESS; + } + CheckLen += Access.Size; + } + } + } + FreePool (Info); + return EFI_NOT_FOUND; +} + + + -- cgit v1.2.3