mirror of https://github.com/acidanthera/audk.git
3764 lines
110 KiB
C
3764 lines
110 KiB
C
/** @file
|
|
This driver manages user information and produces user manager protocol.
|
|
|
|
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
|
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"
|
|
|
|
//
|
|
// 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)
|
|
}
|
|
},
|
|
USER_IDENTIFY_MANAGER_GUID
|
|
},
|
|
{
|
|
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;
|
|
}
|
|
|
|
|
|
/**
|
|
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;
|
|
}
|
|
|
|
|
|
/**
|
|
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,
|
|
&gUserIdentifyManagerGuid,
|
|
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
|
Delete ? 0 : User->UserProfileSize,
|
|
User->ProfileInfo
|
|
);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
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 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;
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
|
|
//
|
|
// 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 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 identifier 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_CREDENTIAL2_PROTOCOL *UserCredential;
|
|
|
|
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;
|
|
}
|
|
|
|
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_CREDENTIAL2_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
|
|
&gUserIdentifyManagerGuid,// 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
|
|
&gUserIdentifyManagerGuid,// 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_CHANGED:
|
|
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;
|
|
}
|
|
break;
|
|
|
|
case EFI_BROWSER_ACTION_CHANGING:
|
|
//
|
|
// QuestionId comes from the first Form (Select a user to identify).
|
|
//
|
|
if (QuestionId >= LABEL_PROVIDER_NAME) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
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;
|
|
if (Type == EFI_IFR_TYPE_REF) {
|
|
Value->ref.FormId = FORMID_INVALID_FORM;
|
|
}
|
|
}
|
|
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, &gUserIdentifyManagerGuid, &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, &gUserIdentifyManagerGuid, &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, &gUserIdentifyManagerGuid, 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, &gUserIdentifyManagerGuid, 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, &gUserIdentifyManagerGuid, 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,
|
|
&gEfiUserCredential2ProtocolGuid,
|
|
NULL,
|
|
&HandleCount,
|
|
&HandleBuf
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get provider infomation.
|
|
//
|
|
mProviderDb = AllocateZeroPool (
|
|
sizeof (CREDENTIAL_PROVIDER_INFO) -
|
|
sizeof (EFI_USER_CREDENTIAL2_PROTOCOL *) +
|
|
HandleCount * sizeof (EFI_USER_CREDENTIAL2_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],
|
|
&gEfiUserCredential2ProtocolGuid,
|
|
(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 <ConfigRequest> 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 <ConfigAltResp> 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 <ConfigResp> 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 (
|
|
&gUserIdentifyManagerGuid,
|
|
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_CREDENTIAL2_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,
|
|
&gUserIdentifyManagerGuid,
|
|
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_IDENITTY_POLICY_RECORD is changed, it is the caller's responsibility to keep
|
|
it to be synced with the information on credential providers.
|
|
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.
|
|
If the User Identity Manager doesn't support asynchronous changes in credentials, then this function
|
|
should return EFI_UNSUPPORTED.
|
|
If current user does not exist, and the credential provider can identify a user, then make the user
|
|
to be current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
|
|
If current user already exists, and the credential provider can identify another user, then switch
|
|
current user to the newly identified user, and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
|
|
If current user was identified by this credential provider and now the credential provider cannot identify
|
|
current user, then logout current user and signal the EFI_EVENT_GROUP_USER_PROFILE_CHANGED event.
|
|
|
|
@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_CREDENTIAL2_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
|
|
)
|
|
{
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
|
|
/**
|
|
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;
|
|
|
|
//
|
|
// It is NOT robust enough to be included in production.
|
|
//
|
|
#error "This implementation is just a sample, please comment this line if you really want to use this driver."
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
|