Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / security / permissions / principalpermission.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 //  PrincipalPermission.cs
7 // 
8 // <OWNER>Microsoft</OWNER>
9 //
10
11 namespace System.Security.Permissions
12 {
13     using System;
14     using SecurityElement = System.Security.SecurityElement;
15     using System.Security.Util;
16     using System.IO;
17     using System.Collections;
18     using System.Collections.Generic;
19     using System.Security.Principal;
20     using System.Text;
21     using System.Threading;    
22     using System.Globalization;
23     using System.Reflection;
24     using System.Diagnostics.Contracts;
25     
26     [Serializable]
27     internal class IDRole
28     {
29         internal bool m_authenticated;
30         internal String m_id;
31         internal String m_role;
32
33 #if !FEATURE_PAL
34         // cache the translation from name to Sid for the case of WindowsPrincipal.
35         [NonSerialized]
36         private SecurityIdentifier m_sid = null;
37         internal SecurityIdentifier Sid {
38             [System.Security.SecurityCritical]  // auto-generated
39             get {
40                 if (String.IsNullOrEmpty(m_role))
41                     return null;
42
43                 if (m_sid == null) {
44                     NTAccount ntAccount = new NTAccount(m_role);
45                     IdentityReferenceCollection source = new IdentityReferenceCollection(1);
46                     source.Add(ntAccount);
47                     IdentityReferenceCollection target = NTAccount.Translate(source, typeof(SecurityIdentifier), false);
48                     m_sid = target[0] as SecurityIdentifier;
49                 }
50
51                 return m_sid;
52             }
53         }
54 #endif // !FEATURE_PAL
55
56 #if FEATURE_CAS_POLICY
57         internal SecurityElement ToXml()
58         {
59             SecurityElement root = new SecurityElement( "Identity" );
60             
61             if (m_authenticated)
62                 root.AddAttribute( "Authenticated", "true" );
63                 
64             if (m_id != null)
65             {
66                 root.AddAttribute( "ID", SecurityElement.Escape( m_id ) );
67             }
68                
69             if (m_role != null)
70             {
71                 root.AddAttribute( "Role", SecurityElement.Escape( m_role ) );
72             }
73                             
74             return root;
75         }
76         
77         internal void FromXml( SecurityElement e )
78         {
79             String elAuth = e.Attribute( "Authenticated" );
80             if (elAuth != null)
81             {
82                 m_authenticated = String.Compare( elAuth, "true", StringComparison.OrdinalIgnoreCase) == 0;
83             }
84             else
85             {
86                 m_authenticated = false;
87             }
88            
89             String elID = e.Attribute( "ID" );
90             if (elID != null)
91             {
92                 m_id = elID;
93             }
94             else
95             {
96                 m_id = null;
97             }
98             
99             String elRole = e.Attribute( "Role" );
100             if (elRole != null)
101             {
102                 m_role = elRole;
103             }
104             else
105             {
106                 m_role = null;
107             }
108         }
109 #endif // FEATURE_CAS_POLICY
110
111         public override int GetHashCode()
112         {
113             return ((m_authenticated ? 0 : 101) +
114                         (m_id == null ? 0 : m_id.GetHashCode()) +
115                         (m_role == null? 0 : m_role.GetHashCode()));
116         }    
117
118     }
119     
120 [System.Runtime.InteropServices.ComVisible(true)]
121     [Serializable]
122     sealed public class PrincipalPermission : IPermission, IUnrestrictedPermission, ISecurityEncodable, IBuiltInPermission
123     {
124         private IDRole[] m_array;
125         
126         public PrincipalPermission( PermissionState state )
127         {
128             if (state == PermissionState.Unrestricted)
129             {
130                 m_array = new IDRole[1];
131                 m_array[0] = new IDRole();
132                 m_array[0].m_authenticated = true;
133                 m_array[0].m_id = null;
134                 m_array[0].m_role = null;
135             }
136             else if (state == PermissionState.None)
137             {
138                 m_array = new IDRole[1];
139                 m_array[0] = new IDRole();
140                 m_array[0].m_authenticated = false;
141                 m_array[0].m_id = "";
142                 m_array[0].m_role = "";
143             }
144             else
145                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
146         }
147         
148         public PrincipalPermission( String name, String role )
149         {
150             m_array = new IDRole[1];
151             m_array[0] = new IDRole();
152             m_array[0].m_authenticated = true;
153             m_array[0].m_id = name;
154             m_array[0].m_role = role;
155         }
156     
157         public PrincipalPermission( String name, String role, bool isAuthenticated )
158         {
159             m_array = new IDRole[1];
160             m_array[0] = new IDRole();
161             m_array[0].m_authenticated = isAuthenticated;
162             m_array[0].m_id = name;
163             m_array[0].m_role = role;
164         }        
165     
166         private PrincipalPermission( IDRole[] array )
167         {
168             m_array = array;
169         }
170     
171         private bool IsEmpty()
172         {
173             for (int i = 0; i < m_array.Length; ++i)
174             {
175                 if ((m_array[i].m_id == null || !m_array[i].m_id.Equals( "" )) ||
176                     (m_array[i].m_role == null || !m_array[i].m_role.Equals( "" )) ||
177                     m_array[i].m_authenticated)
178                 {
179                     return false;
180                 }
181             }
182             return true;
183         }
184         
185         private bool VerifyType(IPermission perm)
186         {
187             // if perm is null, then obviously not of the same type
188             if ((perm == null) || (perm.GetType() != this.GetType())) {
189                 return(false);
190             } else {
191                 return(true);
192             }
193         }
194          
195         
196         public bool IsUnrestricted()
197         {
198             for (int i = 0; i < m_array.Length; ++i)
199             {
200                 if (m_array[i].m_id != null || m_array[i].m_role != null || !m_array[i].m_authenticated)
201                 {
202                     return false;
203                 }
204             }
205             return true;
206         }
207
208         
209         //------------------------------------------------------
210         //
211         // IPERMISSION IMPLEMENTATION
212         //
213         //------------------------------------------------------
214         
215         public bool IsSubsetOf(IPermission target)
216         {
217             if (target == null)
218             {
219                 return this.IsEmpty();
220             }
221         
222             try
223             {
224                 PrincipalPermission operand = (PrincipalPermission)target;
225             
226                 if (operand.IsUnrestricted())
227                     return true;
228                 else if (this.IsUnrestricted())
229                     return false;
230                 else
231                 {
232                     for (int i = 0; i < this.m_array.Length; ++i)
233                     {
234                         bool foundMatch = false;
235                 
236                         for (int j = 0; j < operand.m_array.Length; ++j)
237                         {
238                             if (operand.m_array[j].m_authenticated == this.m_array[i].m_authenticated &&
239                                 (operand.m_array[j].m_id == null ||
240                                  (this.m_array[i].m_id != null && this.m_array[i].m_id.Equals( operand.m_array[j].m_id ))) &&
241                                 (operand.m_array[j].m_role == null ||
242                                  (this.m_array[i].m_role != null && this.m_array[i].m_role.Equals( operand.m_array[j].m_role ))))
243                             {
244                                 foundMatch = true;
245                                 break;
246                             }
247                         }
248                     
249                         if (!foundMatch)
250                             return false;
251                     }
252                                             
253                     return true;
254                 }
255             }
256             catch (InvalidCastException)
257             {
258                 throw new 
259                     ArgumentException(
260                                     Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
261                                      );
262             }                
263
264             
265         }
266         
267         public IPermission Intersect(IPermission target)
268         {
269             if (target == null)
270             {
271                 return null;
272             }
273             else if (!VerifyType(target))
274             {
275                 throw new 
276                     ArgumentException(
277                                     Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
278                                      );
279             }
280             else if (this.IsUnrestricted())
281             {
282                 return target.Copy();
283             }
284     
285             PrincipalPermission operand = (PrincipalPermission)target;
286     
287             if (operand.IsUnrestricted())
288             {
289                 return this.Copy();
290             }
291             
292             List<IDRole> idroles = null;
293             
294             for (int i = 0; i < this.m_array.Length; ++i)
295             {
296                 for (int j = 0; j < operand.m_array.Length; ++j)
297                 {
298                     if (operand.m_array[j].m_authenticated == this.m_array[i].m_authenticated)
299                     {
300                         if (operand.m_array[j].m_id == null ||
301                             this.m_array[i].m_id == null ||
302                             this.m_array[i].m_id.Equals( operand.m_array[j].m_id ))
303                         {
304                             if (idroles == null)
305                             {
306                                 idroles = new List<IDRole>();
307                             }
308                     
309                             IDRole idrole = new IDRole();
310                             
311                             idrole.m_id = operand.m_array[j].m_id == null ? this.m_array[i].m_id : operand.m_array[j].m_id;
312                             
313                             if (operand.m_array[j].m_role == null ||
314                                 this.m_array[i].m_role == null ||
315                                 this.m_array[i].m_role.Equals( operand.m_array[j].m_role))
316                             {
317                                 idrole.m_role = operand.m_array[j].m_role == null ? this.m_array[i].m_role : operand.m_array[j].m_role;
318                             }
319                             else
320                             {
321                                 idrole.m_role = "";
322                             }
323                             
324                             idrole.m_authenticated = operand.m_array[j].m_authenticated;
325                             
326                             idroles.Add( idrole );
327                         }
328                         else if (operand.m_array[j].m_role == null ||
329                                  this.m_array[i].m_role == null ||
330                                  this.m_array[i].m_role.Equals( operand.m_array[j].m_role))
331                         {
332                             if (idroles == null)
333                             {
334                                 idroles = new List<IDRole>();
335                             }
336
337                             IDRole idrole = new IDRole();
338                             
339                             idrole.m_id = "";
340                             idrole.m_role = operand.m_array[j].m_role == null ? this.m_array[i].m_role : operand.m_array[j].m_role;
341                             idrole.m_authenticated = operand.m_array[j].m_authenticated;
342                             
343                             idroles.Add( idrole );
344                         }
345                     }
346                 }
347             }
348             
349             if (idroles == null)
350             {
351                 return null;
352             }
353             else
354             {
355                 IDRole[] idrolesArray = new IDRole[idroles.Count];
356                 
357                 IEnumerator idrolesEnumerator = idroles.GetEnumerator();
358                 int index = 0;
359                 
360                 while (idrolesEnumerator.MoveNext())
361                 {
362                     idrolesArray[index++] = (IDRole)idrolesEnumerator.Current;
363                 }
364                                                                 
365                 return new PrincipalPermission( idrolesArray );
366             }
367         }                                                    
368         
369         public IPermission Union(IPermission other)
370         {
371             if (other == null)
372             {
373                 return this.Copy();
374             }
375             else if (!VerifyType(other))
376             {
377                 throw new 
378                     ArgumentException(
379                                     Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
380                                      );
381             }
382     
383             PrincipalPermission operand = (PrincipalPermission)other;
384            
385             if (this.IsUnrestricted() || operand.IsUnrestricted())
386             {
387                 return new PrincipalPermission( PermissionState.Unrestricted );
388             }
389     
390             // Now we have to do a real union
391             
392             int combinedLength = this.m_array.Length + operand.m_array.Length;
393             IDRole[] idrolesArray = new IDRole[combinedLength];
394             
395             int i, j;
396             for (i = 0; i < this.m_array.Length; ++i)
397             {
398                 idrolesArray[i] = this.m_array[i];
399             }
400             
401             for (j = 0; j < operand.m_array.Length; ++j)
402             {
403                 idrolesArray[i+j] = operand.m_array[j];
404             }
405             
406             return new PrincipalPermission( idrolesArray );
407
408         }    
409
410         [System.Runtime.InteropServices.ComVisible(false)]
411         public override bool Equals(Object obj)
412         {
413             IPermission perm = obj as IPermission;
414             if(obj != null && perm == null)
415                 return false;
416             if(!this.IsSubsetOf(perm))
417                 return false;
418             if(perm != null && !perm.IsSubsetOf(this))
419                 return false;
420             return true;
421         }
422
423         [System.Runtime.InteropServices.ComVisible(false)]
424         public override int GetHashCode()
425         {
426             int hash = 0;
427             int i;
428             for(i = 0; i < m_array.Length; i++)
429                 hash += m_array[i].GetHashCode();
430             return hash;
431         }    
432
433         public IPermission Copy()
434         {
435             return new PrincipalPermission( m_array );  
436         }
437
438         [System.Security.SecurityCritical]  // auto-generated
439         private void ThrowSecurityException()
440         {
441             System.Reflection.AssemblyName name = null;
442             System.Security.Policy.Evidence evid = null;
443             PermissionSet.s_fullTrust.Assert();                    
444             try
445             {
446                 System.Reflection.Assembly asm = Reflection.Assembly.GetCallingAssembly();
447                 name = asm.GetName();
448 #if FEATURE_CAS_POLICY
449                 if(asm != Assembly.GetExecutingAssembly()) // this condition is to avoid having to marshal mscorlib's evidence (which is always in teh default domain) to the current domain
450                     evid = asm.Evidence;
451 #endif // FEATURE_CAS_POLICY
452             }
453             catch
454             {
455             }
456             PermissionSet.RevertAssert();
457             throw new SecurityException(Environment.GetResourceString("Security_PrincipalPermission"), name, null, null, null, SecurityAction.Demand, this, this, evid);
458         }
459
460         [System.Security.SecuritySafeCritical]  // auto-generated
461         public void Demand()
462         {
463             IPrincipal principal = null;
464 #if FEATURE_IMPERSONATION
465             new SecurityPermission(SecurityPermissionFlag.ControlPrincipal).Assert();
466             principal = Thread.CurrentPrincipal;
467 #endif // FEATURE_IMPERSONATION
468
469             if (principal == null)
470                 ThrowSecurityException();
471
472             if (m_array == null)
473                 return;
474
475             // A demand passes when the grant satisfies all entries.
476
477             int count = this.m_array.Length;
478             bool foundMatch = false;
479             for (int i = 0; i < count; ++i)
480             {
481                 // If the demand is authenticated, we need to check the identity and role
482
483                 if (m_array[i].m_authenticated)
484                 {
485                     IIdentity identity = principal.Identity;
486
487                     if ((identity.IsAuthenticated &&
488                          (m_array[i].m_id == null || String.Compare( identity.Name, m_array[i].m_id, StringComparison.OrdinalIgnoreCase) == 0)))
489                     {
490                         if (m_array[i].m_role == null) {
491                             foundMatch = true;
492                         }
493                         else {
494 #if !FEATURE_PAL && FEATURE_IMPERSONATION 
495                             WindowsPrincipal wp = principal as WindowsPrincipal;
496                             if (wp != null && m_array[i].Sid != null)
497                                 foundMatch = wp.IsInRole(m_array[i].Sid);
498                             else
499 #endif // !FEATURE_PAL && FEATURE_IMPERSONATION 
500                                 foundMatch = principal.IsInRole(m_array[i].m_role);
501                         }
502
503                         if (foundMatch)
504                             break;
505                     }
506                 }
507                 else
508                 {
509                     foundMatch = true;
510                     break;
511                 }
512             }
513
514             if (!foundMatch)
515                 ThrowSecurityException();
516         }
517         
518 #if FEATURE_CAS_POLICY
519         public SecurityElement ToXml()
520         {
521             SecurityElement root = new SecurityElement( "IPermission" );
522             
523             XMLUtil.AddClassAttribute( root, this.GetType(), "System.Security.Permissions.PrincipalPermission" );
524             // If you hit this assert then most likely you are trying to change the name of this class. 
525             // This is ok as long as you change the hard coded string above and change the assert below.
526             Contract.Assert( this.GetType().FullName.Equals( "System.Security.Permissions.PrincipalPermission" ), "Class name changed!" );
527
528             root.AddAttribute( "version", "1" );
529             
530             int count = m_array.Length;
531             for (int i = 0; i < count; ++i)
532             {
533                 root.AddChild( m_array[i].ToXml() );
534             }
535             
536             return root;
537         }
538
539         public void FromXml(SecurityElement elem)
540         {
541             CodeAccessPermission.ValidateElement( elem, this );
542
543             if (elem.InternalChildren != null && elem.InternalChildren.Count != 0)
544             { 
545                 int numChildren = elem.InternalChildren.Count;
546                 int count = 0;
547                 
548                 m_array = new IDRole[numChildren];
549             
550                 IEnumerator enumerator = elem.Children.GetEnumerator();
551             
552                 while (enumerator.MoveNext())  
553                 {
554                     IDRole idrole = new IDRole();
555                     
556                     idrole.FromXml( (SecurityElement)enumerator.Current );
557                     
558                     m_array[count++] = idrole;
559                 }
560             }
561             else
562                 m_array = new IDRole[0];
563         }
564                  
565         public override String ToString()
566         {
567             return ToXml().ToString();
568         }    
569 #endif // FEATURE_CAS_POLICY
570
571         /// <internalonly/>
572         int IBuiltInPermission.GetTokenIndex()
573         {
574             return PrincipalPermission.GetTokenIndex();
575         }
576
577         internal static int GetTokenIndex()
578         {
579             return BuiltInPermissionIndex.PrincipalPermissionIndex;
580         }
581
582     }
583
584 }