Update UID drivers to align with latest UEFI spec 2.3.1.
[mirror_edk2.git] / SecurityPkg / UserIdentification / UserProfileManagerDxe / ModifyIdentityPolicy.c
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 or delete the user's credential record in the provider.
62
63 @param[in] ProviderGuid Point to credential provider guid.
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 in FindIdentity from the user identification information record.
161
162 @param[in, out] NewInfo On entry, points to the user information to remove provider.
163 On return, points to the user information the provider is removed.
164 @param[in] FindIdentity Point to the user identity policy.
165
166 @retval TRUE The provider is removed successfully.
167 @retval FALSE Fail to remove the provider.
168
169 **/
170 BOOLEAN
171 DeleteProviderFromPolicy (
172 IN EFI_USER_INFO_IDENTITY_POLICY *IdentityPolicy,
173 IN UINTN Offset
174 )
175 {
176 UINTN RemainingLen;
177 UINTN DeleteLen;
178
179 if (IdentityPolicy->Length == mUserInfo.NewIdentityPolicyLen) {
180 //
181 // Only one credential provider in the identification policy.
182 // Set the new policy to be TRUE after removed the provider.
183 //
184 IdentityPolicy->Type = EFI_USER_INFO_IDENTITY_TRUE;
185 IdentityPolicy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
186 mUserInfo.NewIdentityPolicyLen = IdentityPolicy->Length;
187 return TRUE;
188 }
189
190 DeleteLen = IdentityPolicy->Length + sizeof(EFI_USER_INFO_IDENTITY_POLICY);
191 if ((Offset + IdentityPolicy->Length) != mUserInfo.NewIdentityPolicyLen) {
192 //
193 // This provider is not the last item in the identification policy, delete it and the connector.
194 //
195 RemainingLen = mUserInfo.NewIdentityPolicyLen - Offset - DeleteLen;
196 CopyMem ((UINT8 *) IdentityPolicy, (UINT8 *) IdentityPolicy + DeleteLen, RemainingLen);
197 }
198 mUserInfo.NewIdentityPolicyLen -= DeleteLen;
199
200 return FALSE;
201 }
202
203
204 /**
205 Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed.
206
207 **/
208 VOID
209 AddProviderToPolicy (
210 IN EFI_GUID *NewGuid
211 )
212 {
213 UINT8 *NewPolicyInfo;
214 UINTN NewPolicyInfoLen;
215 EFI_USER_INFO_IDENTITY_POLICY *Policy;
216
217 //
218 // Allocate memory for the new identity policy.
219 //
220 NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID);
221 if (mUserInfo.NewIdentityPolicyLen > 0) {
222 //
223 // It is not the first provider in the policy. Add a connector before provider.
224 //
225 NewPolicyInfoLen += sizeof (EFI_USER_INFO_IDENTITY_POLICY);
226 }
227 NewPolicyInfo = AllocateZeroPool (NewPolicyInfoLen);
228 if (NewPolicyInfo == NULL) {
229 return ;
230 }
231
232 NewPolicyInfoLen = 0;
233 if (mUserInfo.NewIdentityPolicyLen > 0) {
234 //
235 // Save orginal policy.
236 //
237 CopyMem (NewPolicyInfo, mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);
238
239 //
240 // Save logical connector.
241 //
242 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + mUserInfo.NewIdentityPolicyLen);
243 if (mConncetLogical == 0) {
244 Policy->Type = EFI_USER_INFO_IDENTITY_AND;
245 } else {
246 Policy->Type = EFI_USER_INFO_IDENTITY_OR;
247 }
248
249 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY);
250 NewPolicyInfoLen = mUserInfo.NewIdentityPolicyLen + Policy->Length;
251 FreePool (mUserInfo.NewIdentityPolicy);
252 }
253
254 //
255 // Save credential provider.
256 //
257 Policy = (EFI_USER_INFO_IDENTITY_POLICY *) (NewPolicyInfo + NewPolicyInfoLen);
258 Policy->Length = sizeof (EFI_USER_INFO_IDENTITY_POLICY) + sizeof (EFI_GUID);
259 Policy->Type = EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER;
260 CopyGuid ((EFI_GUID *) (Policy + 1), NewGuid);
261 NewPolicyInfoLen += Policy->Length;
262
263 //
264 // Update identity policy choice.
265 //
266 mUserInfo.NewIdentityPolicy = NewPolicyInfo;
267 mUserInfo.NewIdentityPolicyLen = NewPolicyInfoLen;
268 mUserInfo.NewIdentityPolicyModified = TRUE;
269 }
270
271
272 /**
273 This function replaces the old identity policy with a new identity policy.
274
275 This function delete the user identity policy information.
276 If enroll new credential failed, recover the old identity policy.
277
278 @retval EFI_SUCCESS Modify user identity policy successfully.
279 @retval Others Fail to modify user identity policy.
280
281 **/
282 EFI_STATUS
283 UpdateCredentialProvider (
284 )
285 {
286 EFI_STATUS Status;
287 EFI_USER_INFO_IDENTITY_POLICY *Identity;
288 UINTN Offset;
289
290 //
291 // Delete the old identification policy.
292 //
293 DeleteCredentialFromProviders (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, mModifyUser);
294
295 //
296 // Add the new identification policy.
297 //
298 Offset = 0;
299 while (Offset < mUserInfo.NewIdentityPolicyLen) {
300 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (mUserInfo.NewIdentityPolicy + Offset);
301 if (Identity->Type == EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER) {
302 //
303 // Enroll the user on this provider
304 //
305 Status = EnrollUserOnProvider (Identity, mModifyUser);
306 if (EFI_ERROR (Status)) {
307 //
308 // Failed to enroll the user by new identification policy.
309 // So removed the credential provider from the identification policy
310 //
311 DeleteProviderFromPolicy (Identity, Offset);
312 continue;
313 }
314 }
315 Offset += Identity->Length;
316 }
317
318 return EFI_SUCCESS;
319 }
320
321
322 /**
323 Check whether the identity policy is valid.
324
325 @param[in] PolicyInfo Point to the identity policy.
326 @param[in] PolicyInfoLen The policy length.
327
328 @retval TRUE The policy is a valid identity policy.
329 @retval FALSE The policy is not a valid identity policy.
330
331 **/
332 BOOLEAN
333 CheckNewIdentityPolicy (
334 IN UINT8 *PolicyInfo,
335 IN UINTN PolicyInfoLen
336 )
337 {
338 EFI_USER_INFO_IDENTITY_POLICY *Identity;
339 EFI_INPUT_KEY Key;
340 UINTN Offset;
341 UINT32 OpCode;
342
343 //
344 // Check policy expression.
345 //
346 OpCode = EFI_USER_INFO_IDENTITY_FALSE;
347 Offset = 0;
348 while (Offset < PolicyInfoLen) {
349 //
350 // Check identification policy according to type
351 //
352 Identity = (EFI_USER_INFO_IDENTITY_POLICY *) (PolicyInfo + Offset);
353 switch (Identity->Type) {
354
355 case EFI_USER_INFO_IDENTITY_TRUE:
356 break;
357
358 case EFI_USER_INFO_IDENTITY_OR:
359 if (OpCode == EFI_USER_INFO_IDENTITY_AND) {
360 CreatePopUp (
361 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
362 &Key,
363 L"Invalid Identity Policy, Mixed Connector Unsupport!",
364 L"",
365 L"Press Any Key to Continue ...",
366 NULL
367 );
368 return FALSE;
369 }
370
371 OpCode = EFI_USER_INFO_IDENTITY_OR;
372 break;
373
374 case EFI_USER_INFO_IDENTITY_AND:
375 if (OpCode == EFI_USER_INFO_IDENTITY_OR) {
376 CreatePopUp (
377 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
378 &Key,
379 L"Invalid Identity Policy, Mixed Connector Unsupport!",
380 L"",
381 L"Press Any Key to Continue ...",
382 NULL
383 );
384 return FALSE;
385 }
386
387 OpCode = EFI_USER_INFO_IDENTITY_AND;
388 break;
389
390 case EFI_USER_INFO_IDENTITY_CREDENTIAL_PROVIDER:
391 break;
392
393 default:
394 CreatePopUp (
395 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
396 &Key,
397 L"Unsupport parameter",
398 L"",
399 L"Press Any Key to Continue ...",
400 NULL
401 );
402 return FALSE;
403 }
404 Offset += Identity->Length;
405 }
406
407 return TRUE;
408 }
409
410
411 /**
412 Save the identity policy and update UI with it.
413
414 This funciton will verify the new identity policy, in current implementation,
415 the identity policy can be: T, P & P & P & ..., P | P | P | ...
416 Here, "T" means "True", "P" means "Credential Provider", "&" means "and", "|" means "or".
417 Other identity policies are not supported.
418
419 **/
420 VOID
421 SaveIdentityPolicy (
422 VOID
423 )
424 {
425 EFI_STATUS Status;
426 EFI_USER_INFO_HANDLE UserInfo;
427 EFI_USER_INFO *Info;
428
429 if (!mUserInfo.NewIdentityPolicyModified || (mUserInfo.NewIdentityPolicyLen == 0)) {
430 return;
431 }
432
433 //
434 // Check policy expression.
435 //
436 if (!CheckNewIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen)) {
437 return;
438 }
439
440 Status = FindInfoByType (mModifyUser, EFI_USER_INFO_IDENTITY_POLICY_RECORD, &UserInfo);
441 if (EFI_ERROR (Status)) {
442 return ;
443 }
444
445 //
446 // Update the informantion on credential provider.
447 //
448 Status = UpdateCredentialProvider ();
449 if (EFI_ERROR (Status)) {
450 return ;
451 }
452
453 //
454 // Save new identification policy.
455 //
456 Info = AllocateZeroPool (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen);
457 ASSERT (Info != NULL);
458
459 Info->InfoType = EFI_USER_INFO_IDENTITY_POLICY_RECORD;
460 Info->InfoAttribs = EFI_USER_INFO_STORAGE_PLATFORM_NV | EFI_USER_INFO_PUBLIC | EFI_USER_INFO_EXCLUSIVE;
461 Info->InfoSize = (UINT32) (sizeof (EFI_USER_INFO) + mUserInfo.NewIdentityPolicyLen);
462 CopyMem ((UINT8 *) (Info + 1), mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen);
463
464 Status = mUserManager->SetInfo (mUserManager, mModifyUser, &UserInfo, Info, Info->InfoSize);
465 FreePool (Info);
466
467 //
468 // Update the mUserInfo.IdentityPolicy by mUserInfo.NewIdentityPolicy
469 //
470 if (mUserInfo.IdentityPolicy != NULL) {
471 FreePool (mUserInfo.IdentityPolicy);
472 }
473 mUserInfo.IdentityPolicy = mUserInfo.NewIdentityPolicy;
474 mUserInfo.IdentityPolicyLen = mUserInfo.NewIdentityPolicyLen;
475
476 mUserInfo.NewIdentityPolicy = NULL;
477 mUserInfo.NewIdentityPolicyLen = 0;
478 mUserInfo.NewIdentityPolicyModified = FALSE;
479
480 //
481 // Update identity policy choice.
482 //
483 ResolveIdentityPolicy (mUserInfo.IdentityPolicy, mUserInfo.IdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VAL));
484 }
485
486
487 /**
488 Update the mUserInfo.NewIdentityPolicy, and UI when 'add option' is pressed.
489
490 **/
491 VOID
492 AddIdentityPolicyItem (
493 VOID
494 )
495 {
496 if (mProviderInfo->Count == 0) {
497 return ;
498 }
499
500 //
501 // Check the identity policy.
502 //
503 if (ProviderAlreadyInPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier)) {
504 return;
505 }
506
507 //
508 // Add it to identification policy
509 //
510 AddProviderToPolicy (&mProviderInfo->Provider[mProviderChoice]->Identifier);
511
512 //
513 // Update identity policy choice.
514 //
515 ResolveIdentityPolicy (mUserInfo.NewIdentityPolicy, mUserInfo.NewIdentityPolicyLen, STRING_TOKEN (STR_IDENTIFY_POLICY_VALUE));
516 }
517
518