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