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
ProviderAlreadyInPolicy(IN EFI_GUID * NewGuid)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
EnrollUserOnProvider(IN EFI_USER_INFO_IDENTITY_POLICY * Identity,IN EFI_USER_PROFILE_HANDLE User)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
DeleteUserOnProvider(IN EFI_USER_INFO_IDENTITY_POLICY * Identity,IN EFI_USER_PROFILE_HANDLE User)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
DeleteCredentialFromProviders(IN UINT8 * IdentityPolicy,IN UINTN IdentityPolicyLen,IN EFI_USER_PROFILE_HANDLE User)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
DeleteProviderFromPolicy(IN EFI_USER_INFO_IDENTITY_POLICY * IdentityPolicy,IN UINTN Offset)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
AddProviderToPolicy(IN EFI_GUID * NewGuid)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
UpdateCredentialProvider()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
CheckNewIdentityPolicy(IN UINT8 * PolicyInfo,IN UINTN PolicyInfoLen)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 funciton 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
SaveIdentityPolicy(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
AddIdentityPolicyItem(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