1 /** @file 2 The functions for identification policy modification. 3 4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "UserProfileManager.h" 16 17 18 /** 19 Verify the new identity policy in the current implementation. The same credential 20 provider can't appear twice in one identity policy. 21 22 @param[in] NewGuid Points to the credential provider guid. 23 24 @retval TRUE The NewGuid was found in the identity policy. 25 @retval FALSE The NewGuid was not found. 26 27 **/ 28 BOOLEAN 29 ProviderAlreadyInPolicy ( 30 IN EFI_GUID *NewGuid 31 ) 32 { 33 UINTN Offset; 34 EFI_USER_INFO_IDENTITY_POLICY *Identity; 35 EFI_INPUT_KEY Key; 36 37 Offset = 0; 38 while (Offset < mUserInfo.NewIdentityPolicyLen) { 39 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset); 40 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { 41 if (CompareGuid (NewGuid, (EFI_GUID *) (Identity + 1))) { 42 CreatePopUp ( 43 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 44 &Key, 45 L"This Credential Provider Are Already Used!", 46 L"", 47 L"Press Any Key to Continue ...", 48 NULL 49 ); 50 return TRUE; 51 } 52 } 53 Offset += Identity->Length; 54 } 55 56 return FALSE; 57 } 58 59 60 /** 61 Add the user's credential record in the provider. 62 63 @param[in] Identity Identity policy item including credential provider. 64 @param[in] User Points to user profile. 65 66 @retval EFI_SUCCESS Add or delete record successfully. 67 @retval Others Fail to add or delete record. 68 69 **/ 70 EFI_STATUS 71 EnrollUserOnProvider ( 72 IN EFI_USER_INFO_IDENTITY_POLICY *Identity, 73 IN EFI_USER_PROFILE_HANDLE User 74 ) 75 { 76 UINTN Index; 77 EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential; 78 79 // 80 // Find the specified credential provider. 81 // 82 for (Index = 0; Index < mProviderInfo->Count; Index++) { 83 UserCredential = mProviderInfo->Provider[Index]; 84 if (CompareGuid ((EFI_GUID *)(Identity + 1), &UserCredential->Identifier)) { 85 return UserCredential->Enroll (UserCredential, User); 86 } 87 } 88 89 return EFI_NOT_FOUND; 90 } 91 92 93 /** 94 Delete the User's credential record on the provider. 95 96 @param[in] Identity Point to EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER user info. 97 @param[in] User Points to user profile. 98 99 @retval EFI_SUCCESS Delete User's credential record successfully. 100 @retval Others Fail to add or delete record. 101 102 **/ 103 EFI_STATUS 104 DeleteUserOnProvider ( 105 IN EFI_USER_INFO_IDENTITY_POLICY *Identity, 106 IN EFI_USER_PROFILE_HANDLE User 107 ) 108 { 109 UINTN Index; 110 EFI_USER_CREDENTIAL2_PROTOCOL *UserCredential; 111 112 // 113 // Find the specified credential provider. 114 // 115 for (Index = 0; Index < mProviderInfo->Count; Index++) { 116 UserCredential = mProviderInfo->Provider[Index]; 117 if (CompareGuid ((EFI_GUID *)(Identity + 1), &UserCredential->Identifier)) { 118 return UserCredential->Delete (UserCredential, User); 119 } 120 } 121 122 return EFI_NOT_FOUND; 123 } 124 125 126 /** 127 Delete User's credental from all the providers that exist in User's identity policy. 128 129 @param[in] IdentityPolicy Point to User's identity policy. 130 @param[in] IdentityPolicyLen The length of the identity policy. 131 @param[in] User Points to user profile. 132 133 **/ 134 VOID 135 DeleteCredentialFromProviders ( 136 IN UINT8 *IdentityPolicy, 137 IN UINTN IdentityPolicyLen, 138 IN EFI_USER_PROFILE_HANDLE User 139 ) 140 { 141 EFI_USER_INFO_IDENTITY_POLICY *Identity; 142 UINTN Offset; 143 144 Offset = 0; 145 while (Offset < IdentityPolicyLen) { 146 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (IdentityPolicy + Offset); 147 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { 148 // 149 // Delete the user on this provider. 150 // 151 DeleteUserOnProvider (Identity, User); 152 } 153 Offset += Identity->Length; 154 } 155 156 } 157 158 159 /** 160 Remove the provider specified by Offset from the new user identification record. 161 162 @param[in] IdentityPolicy Point to user identity item in new identification policy. 163 @param[in] Offset The item offset in the new identification policy. 164 165 **/ 166 VOID 167 DeleteProviderFromPolicy ( 168 IN EFI_USER_INFO_IDENTITY_POLICY *IdentityPolicy, 169 IN UINTN Offset 170 ) 171 { 172 UINTN RemainingLen; 173 UINTN DeleteLen; 174 175 if (IdentityPolicy->Length == mUserInfo.NewIdentityPolicyLen) { 176 // 177 // Only one credential provider in the identification policy. 178 // Set the new policy to be TRUE after removed the provider. 179 // 180 IdentityPolicy->Type = EFI_USER_INFO_IDENTITY_TRUE; 181 IdentityPolicy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); 182 mUserInfo.NewIdentityPolicyLen = IdentityPolicy->Length; 183 return ; 184 } 185 186 DeleteLen = IdentityPolicy->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY); 187 if ((Offset + IdentityPolicy->Length) != mUserInfo.NewIdentityPolicyLen) { 188 // 189 // This provider is not the last item in the identification policy, delete it and the connector. 190 // 191 RemainingLen = mUserInfo.NewIdentityPolicyLen - Offset - DeleteLen; 192 CopyMem ((UINT8 *) IdentityPolicy, (UINT8 *) IdentityPolicy + DeleteLen, RemainingLen); 193 } 194 mUserInfo.NewIdentityPolicyLen -= DeleteLen; 195 } 196 197 198 /** 199 Add a new provider to the mUserInfo.NewIdentityPolicy. 200 201 It is invoked when 'add option' in UI is pressed. 202 203 @param[in] NewGuid Points to the credential provider guid. 204 205 **/ 206 VOID 207 AddProviderToPolicy ( 208 IN EFI_GUID *NewGuid 209 ) 210 { 211 UINT8 *NewPolicyInfo; 212 UINTN NewPolicyInfoLen; 213 EFI_USER_INFO_IDENTITY_POLICY *Policy; 214 215 // 216 // Allocate memory for the new identity policy. 217 // 218 NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID); 219 if (mUserInfo.NewIdentityPolicyLen > 0) { 220 // 221 // It is not the first provider in the policy. Add a connector before provider. 222 // 223 NewPolicyInfoLen += sizeof (EFI_USER_INFO_IDENTITY_POLICY); 224 } 225 NewPolicyInfo = AllocateZeroPool (NewPolicyInfoLen); 226 if (NewPolicyInfo == NULL) { 227 return ; 228 } 229 230 NewPolicyInfoLen = 0; 231 if (mUserInfo.NewIdentityPolicyLen > 0) { 232 // 233 // Save orginal policy. 234 // 235 CopyMem (NewPolicyInfo, mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen); 236 237 // 238 // Save logical connector. 239 // 240 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + mUserInfo.NewIdentityPolicyLen); 241 if (mConncetLogical == 0) { 242 Policy->Type = EFI_USER_INFO_IDENTITY_AND; 243 } else { 244 Policy->Type = EFI_USER_INFO_IDENTITY_OR; 245 } 246 247 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY); 248 NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + Policy->Length; 249 FreePool (mUserInfo.NewIdentityPolicy); 250 } 251 252 // 253 // Save credential provider. 254 // 255 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + NewPolicyInfoLen); 256 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID); 257 Policy->Type = EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER; 258 CopyGuid ((EFI_GUID *) (Policy + 1), NewGuid); 259 NewPolicyInfoLen += Policy->Length; 260 261 // 262 // Update identity policy choice. 263 // 264 mUserInfo.NewIdentityPolicy = NewPolicyInfo; 265 mUserInfo.NewIdentityPolicyLen = NewPolicyInfoLen; 266 mUserInfo.NewIdentityPolicyModified = TRUE; 267 } 268 269 270 /** 271 This function replaces the old identity policy with a new identity policy. 272 273 This function delete the user identity policy information. 274 If enroll new credential failed, recover the old identity policy. 275 276 @retval EFI_SUCCESS Modify user identity policy successfully. 277 @retval Others Fail to modify user identity policy. 278 279 **/ 280 EFI_STATUS 281 UpdateCredentialProvider ( 282 ) 283 { 284 EFI_STATUS Status; 285 EFI_USER_INFO_IDENTITY_POLICY *Identity; 286 UINTN Offset; 287 288 // 289 // Delete the old identification policy. 290 // 291 DeleteCredentialFromProviders (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, mModifyUser); 292 293 // 294 // Add the new identification policy. 295 // 296 Offset = 0; 297 while (Offset < mUserInfo.NewIdentityPolicyLen) { 298 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset); 299 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) { 300 // 301 // Enroll the user on this provider 302 // 303 Status = EnrollUserOnProvider (Identity, mModifyUser); 304 if (EFI_ERROR (Status)) { 305 // 306 // Failed to enroll the user by new identification policy. 307 // So removed the credential provider from the identification policy 308 // 309 DeleteProviderFromPolicy (Identity, Offset); 310 continue; 311 } 312 } 313 Offset += Identity->Length; 314 } 315 316 return EFI_SUCCESS; 317 } 318 319 320 /** 321 Check whether the identity policy is valid. 322 323 @param[in] PolicyInfo Point to the identity policy. 324 @param[in] PolicyInfoLen The policy length. 325 326 @retval TRUE The policy is a valid identity policy. 327 @retval FALSE The policy is not a valid identity policy. 328 329 **/ 330 BOOLEAN 331 CheckNewIdentityPolicy ( 332 IN UINT8 *PolicyInfo, 333 IN UINTN PolicyInfoLen 334 ) 335 { 336 EFI_USER_INFO_IDENTITY_POLICY *Identity; 337 EFI_INPUT_KEY Key; 338 UINTN Offset; 339 UINT32 OpCode; 340 341 // 342 // Check policy expression. 343 // 344 OpCode = EFI_USER_INFO_IDENTITY_FALSE; 345 Offset = 0; 346 while (Offset < PolicyInfoLen) { 347 // 348 // Check identification policy according to type 349 // 350 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + Offset); 351 switch (Identity->Type) { 352 353 case EFI_USER_INFO_IDENTITY_TRUE: 354 break; 355 356 case EFI_USER_INFO_IDENTITY_OR: 357 if (OpCode == EFI_USER_INFO_IDENTITY_AND) { 358 CreatePopUp ( 359 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 360 &Key, 361 L"Invalid Identity Policy, Mixed Connector Unsupport!", 362 L"", 363 L"Press Any Key to Continue ...", 364 NULL 365 ); 366 return FALSE; 367 } 368 369 OpCode = EFI_USER_INFO_IDENTITY_OR; 370 break; 371 372 case EFI_USER_INFO_IDENTITY_AND: 373 if (OpCode == EFI_USER_INFO_IDENTITY_OR) { 374 CreatePopUp ( 375 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 376 &Key, 377 L"Invalid Identity Policy, Mixed Connector Unsupport!", 378 L"", 379 L"Press Any Key to Continue ...", 380 NULL 381 ); 382 return FALSE; 383 } 384 385 OpCode = EFI_USER_INFO_IDENTITY_AND; 386 break; 387 388 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER: 389 break; 390 391 default: 392 CreatePopUp ( 393 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, 394 &Key, 395 L"Unsupport parameter", 396 L"", 397 L"Press Any Key to Continue ...", 398 NULL 399 ); 400 return FALSE; 401 } 402 Offset += Identity->Length; 403 } 404 405 return TRUE; 406 } 407 408 409 /** 410 Save the identity policy and update UI with it. 411 412 This function will verify the new identity policy, in current implementation, 413 the identity policy can be: T, P & P & P & ..., P | P | P | ... 414 Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or". 415 Other identity policies are not supported. 416 417 **/ 418 VOID 419 SaveIdentityPolicy ( 420 VOID 421 ) 422 { 423 EFI_STATUS Status; 424 EFI_USER_INFO_HANDLE UserInfo; 425 EFI_USER_INFO *Info; 426 427 if (!mUserInfo.NewIdentityPolicyModified || (mUserInfo.NewIdentityPolicyLen == 0)) { 428 return; 429 } 430 431 // 432 // Check policy expression. 433 // 434 if (!CheckNewIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen)) { 435 return; 436 } 437 438 Status = FindInfoByType (mModifyUser, EFI_USER_INFO_IDENTITY_POLICY_RECORD, &UserInfo); 439 if (EFI_ERROR (Status)) { 440 return ; 441 } 442 443 // 444 // Update the informantion on credential provider. 445 // 446 Status = UpdateCredentialProvider (); 447 if (EFI_ERROR (Status)) { 448 return ; 449 } 450 451 // 452 // Save new identification policy. 453 // 454 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen); 455 ASSERT (Info != NULL); 456 457 Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD; 458 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE; 459 Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen); 460 CopyMem ((UINT8 *) (Info + 1), mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen); 461 462 Status = mUserManager->SetInfo (mUserManager, mModifyUser, &UserInfo, Info, Info->InfoSize); 463 FreePool (Info); 464 465 // 466 // Update the mUserInfo.IdentityPolicy by mUserInfo.NewIdentityPolicy 467 // 468 if (mUserInfo.IdentityPolicy != NULL) { 469 FreePool (mUserInfo.IdentityPolicy); 470 } 471 mUserInfo.IdentityPolicy = mUserInfo.NewIdentityPolicy; 472 mUserInfo.IdentityPolicyLen = mUserInfo.NewIdentityPolicyLen; 473 474 mUserInfo.NewIdentityPolicy = NULL; 475 mUserInfo.NewIdentityPolicyLen = 0; 476 mUserInfo.NewIdentityPolicyModified = FALSE; 477 478 // 479 // Update identity policy choice. 480 // 481 ResolveIdentityPolicy (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VAL)); 482 } 483 484 485 /** 486 Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed. 487 488 **/ 489 VOID 490 AddIdentityPolicyItem ( 491 VOID 492 ) 493 { 494 if (mProviderInfo->Count == 0) { 495 return ; 496 } 497 498 // 499 // Check the identity policy. 500 // 501 if (ProviderAlreadyInPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier)) { 502 return; 503 } 504 505 // 506 // Add it to identification policy 507 // 508 AddProviderToPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier); 509 510 // 511 // Update identity policy choice. 512 // 513 ResolveIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE)); 514 } 515 516 517