/** @file
  The functions for identification policy modification.

Copyright (c) 2009 - 2018, 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 "UserProfileManager.h"


/**
  Verify the new identity policy in the current implementation. The same credential
  provider can't appear twice in one identity policy.

  @param[in] NewGuid       Points to the credential provider guid.

  @retval TRUE     The NewGuid was found in the identity policy.
  @retval FALSE    The NewGuid was not found.

**/
BOOLEAN
ProviderAlreadyInPolicy (
  IN EFI_GUID                                      *NewGuid
  )
{
  UINTN                         Offset;
  EFI_USER_INFO_IDENTITY_POLICY *Identity;
  EFI_INPUT_KEY                 Key;

  Offset = 0;
  while (Offset < mUserInfo.NewIdentityPolicyLen) {
    Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset);
    if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
      if (CompareGuid (NewGuid, (EFI_GUID *) (Identity + 1))) {
        CreatePopUp (
          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
          &Key,
          L"This Credential Provider Are Already Used!",
          L"",
          L"Press Any Key to Continue ...",
          NULL
          );
        return TRUE;
      }
    }
    Offset += Identity->Length;
  }

  return FALSE;
}


/**
  Add the user's credential record in the provider.

  @param[in]  Identity     Identity policy item including credential provider.
  @param[in]  User         Points to user profile.

  @retval EFI_SUCCESS      Add or delete record successfully.
  @retval Others           Fail to add or delete record.

**/
EFI_STATUS
EnrollUserOnProvider (
  IN  EFI_USER_INFO_IDENTITY_POLICY              *Identity,
  IN  EFI_USER_PROFILE_HANDLE                    User
  )
{
  UINTN                          Index;
  EFI_USER_CREDENTIAL2_PROTOCOL  *UserCredential;

  //
  // Find the specified credential provider.
  //
  for (Index = 0; Index < mProviderInfo->Count; Index++) {
    UserCredential = mProviderInfo->Provider[Index];
    if (CompareGuid ((EFI_GUID *)(Identity + 1), &UserCredential->Identifier)) {
      return UserCredential->Enroll (UserCredential, User);
    }
  }

  return EFI_NOT_FOUND;
}


/**
  Delete the User's credential record on the provider.

  @param[in]  Identity     Point to EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER user info.
  @param[in]  User         Points to user profile.

  @retval EFI_SUCCESS      Delete User's credential record successfully.
  @retval Others           Fail to add or delete record.

**/
EFI_STATUS
DeleteUserOnProvider (
  IN  EFI_USER_INFO_IDENTITY_POLICY              *Identity,
  IN  EFI_USER_PROFILE_HANDLE                    User
  )
{
  UINTN                          Index;
  EFI_USER_CREDENTIAL2_PROTOCOL  *UserCredential;

  //
  // Find the specified credential provider.
  //
  for (Index = 0; Index < mProviderInfo->Count; Index++) {
    UserCredential = mProviderInfo->Provider[Index];
    if (CompareGuid ((EFI_GUID *)(Identity + 1), &UserCredential->Identifier)) {
      return UserCredential->Delete (UserCredential, User);
    }
  }

  return EFI_NOT_FOUND;
}


/**
  Delete User's credental from all the providers that exist in User's identity policy.

  @param[in]  IdentityPolicy     Point to User's identity policy.
  @param[in]  IdentityPolicyLen  The length of the identity policy.
  @param[in]  User               Points to user profile.

**/
VOID
DeleteCredentialFromProviders (
  IN     UINT8                                *IdentityPolicy,
  IN     UINTN                                 IdentityPolicyLen,
  IN     EFI_USER_PROFILE_HANDLE               User
  )
{
  EFI_USER_INFO_IDENTITY_POLICY    *Identity;
  UINTN                            Offset;

  Offset = 0;
  while (Offset < IdentityPolicyLen) {
    Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentityPolicy + Offset);
    if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
      //
      // Delete the user on this provider.
      //
      DeleteUserOnProvider (Identity, User);
    }
    Offset += Identity->Length;
  }

}


/**
  Remove the provider specified by Offset from the new user identification record.

  @param[in]  IdentityPolicy    Point to user identity item in new identification policy.
  @param[in]  Offset            The item offset in the new identification policy.

**/
VOID
DeleteProviderFromPolicy (
  IN     EFI_USER_INFO_IDENTITY_POLICY         *IdentityPolicy,
  IN     UINTN                                 Offset
  )
{
  UINTN                         RemainingLen;
  UINTN                         DeleteLen;

  if (IdentityPolicy->Length == mUserInfo.NewIdentityPolicyLen) {
    //
    // Only one credential provider in the identification policy.
    // Set the new policy to be TRUE after removed the provider.
    //
    IdentityPolicy->Type           = EFI_USER_INFO_IDENTITY_TRUE;
    IdentityPolicy->Length         = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
    mUserInfo.NewIdentityPolicyLen = IdentityPolicy->Length;
    return ;
  }

  DeleteLen = IdentityPolicy->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);
  if ((Offset + IdentityPolicy->Length) != mUserInfo.NewIdentityPolicyLen) {
    //
    // This provider is not the last item in the identification policy, delete it and the connector.
    //
    RemainingLen = mUserInfo.NewIdentityPolicyLen - Offset - DeleteLen;
    CopyMem ((UINT8 *) IdentityPolicy, (UINT8 *) IdentityPolicy + DeleteLen, RemainingLen);
  }
  mUserInfo.NewIdentityPolicyLen -= DeleteLen;
}


/**
  Add a new provider to the mUserInfo.NewIdentityPolicy.

  It is invoked when 'add option' in UI is pressed.

  @param[in] NewGuid       Points to the credential provider guid.

**/
VOID
AddProviderToPolicy (
  IN  EFI_GUID                                  *NewGuid
  )
{
  UINT8                         *NewPolicyInfo;
  UINTN                         NewPolicyInfoLen;
  EFI_USER_INFO_IDENTITY_POLICY *Policy;

  //
  // Allocate memory for the new identity policy.
  //
  NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID);
  if (mUserInfo.NewIdentityPolicyLen > 0) {
    //
    // It is not the first provider in the policy. Add a connector before provider.
    //
    NewPolicyInfoLen += sizeof (EFI_USER_INFO_IDENTITY_POLICY);
  }
  NewPolicyInfo = AllocateZeroPool (NewPolicyInfoLen);
  if (NewPolicyInfo == NULL) {
    return ;
  }

  NewPolicyInfoLen = 0;
  if (mUserInfo.NewIdentityPolicyLen > 0) {
    //
    // Save orginal policy.
    //
    CopyMem (NewPolicyInfo, mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);

    //
    // Save logical connector.
    //
    Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + mUserInfo.NewIdentityPolicyLen);
    if (mConncetLogical == 0) {
      Policy->Type = EFI_USER_INFO_IDENTITY_AND;
    } else {
      Policy->Type = EFI_USER_INFO_IDENTITY_OR;
    }

    Policy->Length   = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
    NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + Policy->Length;
    FreePool (mUserInfo.NewIdentityPolicy);
  }

  //
  // Save credential provider.
  //
  Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + NewPolicyInfoLen);
  Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID);
  Policy->Type   = EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER;
  CopyGuid ((EFI_GUID *) (Policy + 1), NewGuid);
  NewPolicyInfoLen += Policy->Length;

  //
  // Update identity policy choice.
  //
  mUserInfo.NewIdentityPolicy         = NewPolicyInfo;
  mUserInfo.NewIdentityPolicyLen      = NewPolicyInfoLen;
  mUserInfo.NewIdentityPolicyModified = TRUE;
}


/**
  This function replaces the old identity policy with a new identity policy.

  This function delete the user identity policy information.
  If enroll new credential failed, recover the old identity policy.

  @retval EFI_SUCCESS      Modify user identity policy successfully.
  @retval Others           Fail to modify user identity policy.

**/
EFI_STATUS
UpdateCredentialProvider (
  )
{
  EFI_STATUS                    Status;
  EFI_USER_INFO_IDENTITY_POLICY *Identity;
  UINTN                         Offset;

  //
  // Delete the old identification policy.
  //
  DeleteCredentialFromProviders (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, mModifyUser);

  //
  // Add the new identification policy.
  //
  Offset  = 0;
  while (Offset < mUserInfo.NewIdentityPolicyLen) {
    Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset);
    if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
      //
      // Enroll the user on this provider
      //
      Status = EnrollUserOnProvider (Identity, mModifyUser);
      if (EFI_ERROR (Status)) {
        //
        // Failed to enroll the user by new identification policy.
        // So removed the credential provider from the identification policy
        //
        DeleteProviderFromPolicy (Identity, Offset);
        continue;
      }
    }
    Offset += Identity->Length;
  }

  return EFI_SUCCESS;
}


/**
  Check whether the identity policy is valid.

  @param[in]  PolicyInfo          Point to the identity policy.
  @param[in]  PolicyInfoLen       The policy length.

  @retval TRUE     The policy is a valid identity policy.
  @retval FALSE    The policy is not a valid identity policy.

**/
BOOLEAN
CheckNewIdentityPolicy (
  IN  UINT8                                     *PolicyInfo,
  IN  UINTN                                     PolicyInfoLen
  )
{
  EFI_USER_INFO_IDENTITY_POLICY *Identity;
  EFI_INPUT_KEY                 Key;
  UINTN                         Offset;
  UINT32                        OpCode;

  //
  // Check policy expression.
  //
  OpCode  = EFI_USER_INFO_IDENTITY_FALSE;
  Offset  = 0;
  while (Offset < PolicyInfoLen) {
    //
    // Check identification policy according to type
    //
    Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + Offset);
    switch (Identity->Type) {

    case EFI_USER_INFO_IDENTITY_TRUE:
      break;

    case EFI_USER_INFO_IDENTITY_OR:
      if (OpCode == EFI_USER_INFO_IDENTITY_AND) {
        CreatePopUp (
          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
          &Key,
          L"Invalid Identity Policy, Mixed Connector Unsupport!",
          L"",
          L"Press Any Key to Continue ...",
          NULL
          );
        return FALSE;
      }

      OpCode = EFI_USER_INFO_IDENTITY_OR;
      break;

    case EFI_USER_INFO_IDENTITY_AND:
      if (OpCode == EFI_USER_INFO_IDENTITY_OR) {
        CreatePopUp (
          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
          &Key,
          L"Invalid Identity Policy, Mixed Connector Unsupport!",
          L"",
          L"Press Any Key to Continue ...",
          NULL
          );
        return FALSE;
      }

      OpCode = EFI_USER_INFO_IDENTITY_AND;
      break;

    case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
      break;

    default:
      CreatePopUp (
        EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
        &Key,
        L"Unsupport parameter",
        L"",
        L"Press Any Key to Continue ...",
        NULL
        );
      return FALSE;
    }
    Offset += Identity->Length;
  }

  return TRUE;
}


/**
  Save the identity policy and update UI with it.

  This function will verify the new identity policy, in current implementation,
  the identity policy can be:  T, P & P & P & ..., P | P | P | ...
  Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or".
  Other identity policies are not supported.

**/
VOID
SaveIdentityPolicy (
  VOID
  )
{
  EFI_STATUS                    Status;
  EFI_USER_INFO_HANDLE          UserInfo;
  EFI_USER_INFO                 *Info;

  if (!mUserInfo.NewIdentityPolicyModified || (mUserInfo.NewIdentityPolicyLen == 0)) {
    return;
  }

  //
  // Check policy expression.
  //
  if (!CheckNewIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen)) {
    return;
  }

  Status = FindInfoByType (mModifyUser, EFI_USER_INFO_IDENTITY_POLICY_RECORD, &UserInfo);
  if (EFI_ERROR (Status)) {
    return ;
  }

  //
  // Update the informantion on credential provider.
  //
  Status = UpdateCredentialProvider ();
  if (EFI_ERROR (Status)) {
    return ;
  }

  //
  // Save new identification policy.
  //
  Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen);
  ASSERT (Info != NULL);

  Info->InfoType    = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
  Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
  Info->InfoSize    = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen);
  CopyMem ((UINT8 *) (Info + 1), mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);

  Status = mUserManager->SetInfo (mUserManager, mModifyUser, &UserInfo, Info, Info->InfoSize);
  FreePool (Info);

  //
  // Update the mUserInfo.IdentityPolicy by mUserInfo.NewIdentityPolicy
  //
  if (mUserInfo.IdentityPolicy != NULL) {
    FreePool (mUserInfo.IdentityPolicy);
  }
  mUserInfo.IdentityPolicy    = mUserInfo.NewIdentityPolicy;
  mUserInfo.IdentityPolicyLen = mUserInfo.NewIdentityPolicyLen;

  mUserInfo.NewIdentityPolicy         = NULL;
  mUserInfo.NewIdentityPolicyLen      = 0;
  mUserInfo.NewIdentityPolicyModified = FALSE;

  //
  // Update identity policy choice.
  //
  ResolveIdentityPolicy (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VAL));
}


/**
  Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed.

**/
VOID
AddIdentityPolicyItem (
  VOID
  )
{
  if (mProviderInfo->Count == 0) {
    return ;
  }

  //
  // Check the identity policy.
  //
  if (ProviderAlreadyInPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier)) {
    return;
  }

  //
  // Add it to identification policy
  //
  AddProviderToPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier);

  //
  // Update identity policy choice.
  //
  ResolveIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE));
}


