Merge pull request #2377 from joelmartinez/docs-multiassembly-extension-fix
[mono.git] / mcs / class / referencesource / mscorlib / system / security / permissions / strongnameidentitypermission.cs
1 // ==++==
2
3 // 
4 //   Copyright (c) Microsoft Corporation.  All rights reserved.
5 // 
6 // ==--==
7 // StrongNameIdentityPermission.cs
8 // 
9 // <OWNER>[....]</OWNER>
10 // 
11
12 namespace System.Security.Permissions
13 {
14     using System;
15 #if FEATURE_CAS_POLICY
16     using SecurityElement = System.Security.SecurityElement;
17 #endif // FEATURE_CAS_POLICY
18     using System.Security.Util;
19     using System.IO;
20     using String = System.String;
21     using Version = System.Version;
22     using System.Security.Policy;
23     using System.Collections;
24     using System.Collections.Generic;
25     using System.Globalization;
26     using System.Diagnostics.Contracts;
27
28     // The only difference between this class and System.Security.Policy.StrongName is that this one
29     // allows m_name to be null.  We should merge this class with System.Security.Policy.StrongName
30     [Serializable]
31     sealed internal class StrongName2
32     {
33         public StrongNamePublicKeyBlob m_publicKeyBlob;
34         public String m_name;
35         public Version m_version;
36
37         public StrongName2(StrongNamePublicKeyBlob publicKeyBlob, String name, Version version)
38         {
39             m_publicKeyBlob = publicKeyBlob;
40             m_name = name;
41             m_version = version;
42         }
43
44         public StrongName2 Copy()
45         {
46             return new StrongName2(m_publicKeyBlob, m_name, m_version);
47         }
48
49         public bool IsSubsetOf(StrongName2 target)
50         {
51             // This StrongName2 is a subset of the target if it's public key blob is null no matter what
52             if (this.m_publicKeyBlob == null)
53                 return true;
54
55             // Subsets are always false if the public key blobs do not match
56             if (!this.m_publicKeyBlob.Equals( target.m_publicKeyBlob ))
57                 return false;
58
59             // We use null in strings to represent the "Anything" state.
60             // Therefore, the logic to detect an individual subset is:
61             //
62             // 1. If the this string is null ("Anything" is a subset of any other).
63             // 2. If the this string and target string are the same (equality is sufficient for a subset).
64             //
65             // The logic is reversed here to discover things that are not subsets.
66             if (this.m_name != null)
67             {
68                 if (target.m_name == null || !System.Security.Policy.StrongName.CompareNames( target.m_name, this.m_name ))
69                     return false;
70             }
71
72             if ((Object) this.m_version != null)
73             {
74                 if ((Object) target.m_version == null ||
75                     target.m_version.CompareTo( this.m_version ) != 0)
76                 {
77                     return false;
78                 }
79             }
80
81             return true;
82         }
83         
84         public StrongName2 Intersect(StrongName2 target)
85         {
86             if (target.IsSubsetOf( this ))
87                 return target.Copy();
88             else if (this.IsSubsetOf( target ))
89                 return this.Copy();
90             else
91                 return null;
92         }
93
94         public bool Equals(StrongName2 target)
95         {
96             if (!target.IsSubsetOf(this))
97                 return false;
98             if (!this.IsSubsetOf(target))
99                 return false;
100             return true;
101         }
102     }
103
104
105
106 [System.Runtime.InteropServices.ComVisible(true)]
107     [Serializable]
108     sealed public class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission
109     {
110         //------------------------------------------------------
111         //
112         // PRIVATE STATE DATA
113         //
114         //------------------------------------------------------
115
116         private bool m_unrestricted;
117         private StrongName2[] m_strongNames;
118
119         //------------------------------------------------------
120         //
121         // PUBLIC CONSTRUCTORS
122         //
123         //------------------------------------------------------
124
125
126         public StrongNameIdentityPermission(PermissionState state)
127         {
128             if (state == PermissionState.Unrestricted)
129             {
130                 m_unrestricted = true;
131             }
132             else if (state == PermissionState.None)
133             {
134                 m_unrestricted = false;
135             }
136             else
137             {
138                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
139             }
140         }
141
142         public StrongNameIdentityPermission( StrongNamePublicKeyBlob blob, String name, Version version )
143         {
144             if (blob == null)
145                 throw new ArgumentNullException( "blob" );
146             if (name != null && name.Equals( "" ))
147                 throw new ArgumentException( Environment.GetResourceString( "Argument_EmptyStrongName" ) );      
148             Contract.EndContractBlock();
149             m_unrestricted = false;
150             m_strongNames = new StrongName2[1];
151             m_strongNames[0] = new StrongName2(blob, name, version);
152         }
153
154
155         //------------------------------------------------------
156         //
157         // PUBLIC ACCESSOR METHODS
158         //
159         //------------------------------------------------------
160
161         public StrongNamePublicKeyBlob PublicKey
162         {
163             set
164             {
165                 if (value == null)
166                     throw new ArgumentNullException( "PublicKey" );
167                 Contract.EndContractBlock();
168                 m_unrestricted = false;
169                 if(m_strongNames != null && m_strongNames.Length == 1)
170                     m_strongNames[0].m_publicKeyBlob = value;
171                 else
172                 {
173                     m_strongNames = new StrongName2[1];
174                     m_strongNames[0] = new StrongName2(value, "", new Version());                   
175                 }
176             }
177
178             get
179             {
180                 if(m_strongNames == null || m_strongNames.Length == 0)
181                     return null;
182                 if(m_strongNames.Length > 1)
183                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
184                 return m_strongNames[0].m_publicKeyBlob;
185             }
186         }
187
188         public String Name
189         {
190             set
191             {
192                 if (value != null && value.Length == 0)
193                     throw new ArgumentException( Environment.GetResourceString("Argument_EmptyName" ));    
194                 Contract.EndContractBlock();
195                 m_unrestricted = false;
196                 if(m_strongNames != null && m_strongNames.Length == 1)
197                     m_strongNames[0].m_name = value;
198                 else
199                 {
200                     m_strongNames = new StrongName2[1];
201                     m_strongNames[0] = new StrongName2(null, value, new Version());                 
202                 }
203             }                    
204
205             get
206             {
207                 if(m_strongNames == null || m_strongNames.Length == 0)
208                     return "";
209                 if(m_strongNames.Length > 1)
210                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
211                 return m_strongNames[0].m_name;
212             }
213         }
214
215         public Version Version
216         {
217             set
218             {
219                 m_unrestricted = false;
220                 if(m_strongNames != null && m_strongNames.Length == 1)
221                     m_strongNames[0].m_version = value;
222                 else
223                 {
224                     m_strongNames = new StrongName2[1];
225                     m_strongNames[0] = new StrongName2(null, "", value);
226                 }
227             }
228             
229             get
230             {
231                 if(m_strongNames == null || m_strongNames.Length == 0)
232                     return new Version();
233                 if(m_strongNames.Length > 1)
234                     throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
235                 return m_strongNames[0].m_version;
236             }
237         }
238
239         //------------------------------------------------------
240         //
241         // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
242         //
243         //------------------------------------------------------
244     
245         //------------------------------------------------------
246         //
247         // CODEACCESSPERMISSION IMPLEMENTATION
248         //
249         //------------------------------------------------------
250         
251         //------------------------------------------------------
252         //
253         // IPERMISSION IMPLEMENTATION
254         //
255         //------------------------------------------------------
256
257
258         public override IPermission Copy()
259         {
260             StrongNameIdentityPermission perm = new StrongNameIdentityPermission(PermissionState.None);
261             perm.m_unrestricted = this.m_unrestricted;
262             if(this.m_strongNames != null)
263             {
264                 perm.m_strongNames = new StrongName2[this.m_strongNames.Length];
265                 int n;
266                 for(n = 0; n < this.m_strongNames.Length; n++)
267                     perm.m_strongNames[n] = this.m_strongNames[n].Copy();
268             }
269             return perm;
270         }
271
272         public override bool IsSubsetOf(IPermission target)
273         {
274             if (target == null)
275             {
276                 if(m_unrestricted)
277                     return false;
278                 if(m_strongNames == null)
279                     return true;
280                 if(m_strongNames.Length == 0)
281                     return true;
282                 return false;
283             }
284             StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
285             if(that == null)
286                 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
287             if(that.m_unrestricted)
288                 return true;
289             if(m_unrestricted)
290                 return false;
291             if(this.m_strongNames != null)
292             {
293                 foreach(StrongName2 snThis in m_strongNames)
294                 {
295                     bool bOK = false;
296                     if(that.m_strongNames != null)
297                     {
298                         foreach(StrongName2 snThat in that.m_strongNames)
299                         {
300                             if(snThis.IsSubsetOf(snThat))
301                             {
302                                 bOK = true;
303                                 break;
304                             }
305                         }
306                     }
307                     if(!bOK)
308                         return false;           
309                 }
310             }
311             return true;
312         }
313
314
315
316         public override IPermission Intersect(IPermission target)
317         {
318             if (target == null)
319                 return null;
320             StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
321             if(that == null)
322                 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
323             if(this.m_unrestricted && that.m_unrestricted)
324             {
325                 StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
326                 res.m_unrestricted = true;
327                 return res;
328             }
329             if(this.m_unrestricted)
330                 return that.Copy();
331             if(that.m_unrestricted)
332                 return this.Copy();
333             if(this.m_strongNames == null || that.m_strongNames == null || this.m_strongNames.Length == 0 || that.m_strongNames.Length == 0)
334                 return null;
335             List<StrongName2> alStrongNames = new List<StrongName2>();
336             foreach(StrongName2 snThis in this.m_strongNames)
337             {
338                 foreach(StrongName2 snThat in that.m_strongNames)
339                 {
340                     StrongName2 snInt = (StrongName2)snThis.Intersect(snThat);
341                     if(snInt != null)
342                         alStrongNames.Add(snInt);
343                 }
344             }
345             if(alStrongNames.Count == 0)
346                 return null;
347             StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
348             result.m_strongNames = alStrongNames.ToArray();
349             return result;
350         }
351
352         public override IPermission Union(IPermission target)
353         {
354             if (target == null)
355             {
356                 if((this.m_strongNames == null || this.m_strongNames.Length == 0) && !this.m_unrestricted)
357                     return null;
358                 return this.Copy();
359             }
360             StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
361             if(that == null)
362                 throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
363             if(this.m_unrestricted || that.m_unrestricted)
364             {
365                 StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
366                 res.m_unrestricted = true;
367                 return res;
368             }
369             if (this.m_strongNames == null || this.m_strongNames.Length == 0)
370             {
371                 if(that.m_strongNames == null || that.m_strongNames.Length == 0)
372                     return null;
373                 return that.Copy();
374             }
375             if(that.m_strongNames == null || that.m_strongNames.Length == 0)
376                 return this.Copy();
377             List<StrongName2> alStrongNames = new List<StrongName2>();
378             foreach(StrongName2 snThis in this.m_strongNames)
379                 alStrongNames.Add(snThis);
380             foreach(StrongName2 snThat in that.m_strongNames)
381             {
382                 bool bDupe = false;
383                 foreach(StrongName2 sn in alStrongNames)
384                 {
385                     if(snThat.Equals(sn))
386                     {
387                         bDupe = true;
388                         break;
389                     }
390                 }
391                 if(!bDupe)
392                     alStrongNames.Add(snThat);
393             }
394             StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
395             result.m_strongNames = alStrongNames.ToArray();
396             return result;
397         }
398
399 #if FEATURE_CAS_POLICY
400         public override void FromXml(SecurityElement e)
401         {
402             m_unrestricted = false;
403             m_strongNames = null;
404             CodeAccessPermission.ValidateElement( e, this );
405             String unr = e.Attribute( "Unrestricted" );
406             if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0)
407             {
408                 m_unrestricted = true;
409                 return;
410             }
411             String elBlob = e.Attribute("PublicKeyBlob");
412             String elName = e.Attribute("Name");
413             String elVersion = e.Attribute("AssemblyVersion");
414             StrongName2 sn;
415             List<StrongName2> al = new List<StrongName2>();
416             if(elBlob != null || elName != null || elVersion != null)
417             {
418                 sn = new StrongName2(
419                                     (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), 
420                                     elName, 
421                                     (elVersion == null ? null : new Version(elVersion)));
422                 al.Add(sn);
423             }
424             ArrayList alChildren = e.Children;
425             if(alChildren != null)
426             {
427                 foreach(SecurityElement child in alChildren)
428                 {
429                     elBlob = child.Attribute("PublicKeyBlob");
430                     elName = child.Attribute("Name");
431                     elVersion = child.Attribute("AssemblyVersion");
432                     if(elBlob != null || elName != null || elVersion != null)
433                     {
434                         sn = new StrongName2(
435                                             (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)), 
436                                             elName, 
437                                             (elVersion == null ? null : new Version(elVersion)));
438                         al.Add(sn);
439                     }
440                 }
441             }
442             if(al.Count != 0)
443                 m_strongNames = al.ToArray();
444         }
445
446         public override SecurityElement ToXml()
447         {
448             SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.StrongNameIdentityPermission" );
449             if (m_unrestricted)
450                 esd.AddAttribute( "Unrestricted", "true" );
451             else if (m_strongNames != null)
452             {
453                 if (m_strongNames.Length == 1)
454                 {
455                     if (m_strongNames[0].m_publicKeyBlob != null)
456                         esd.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[0].m_publicKeyBlob.PublicKey));
457                     if (m_strongNames[0].m_name != null)
458                         esd.AddAttribute("Name", m_strongNames[0].m_name);
459                     if ((Object)m_strongNames[0].m_version != null)
460                         esd.AddAttribute("AssemblyVersion", m_strongNames[0].m_version.ToString());
461                 }
462                 else
463                 {
464                     int n;
465                     for(n = 0; n < m_strongNames.Length; n++)
466                     {
467                         SecurityElement child = new SecurityElement("StrongName");
468                         if (m_strongNames[n].m_publicKeyBlob != null)
469                             child.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[n].m_publicKeyBlob.PublicKey));
470                         if (m_strongNames[n].m_name != null)
471                             child.AddAttribute("Name", m_strongNames[n].m_name);
472                         if ((Object)m_strongNames[n].m_version != null)
473                             child.AddAttribute("AssemblyVersion", m_strongNames[n].m_version.ToString());
474                         esd.AddChild(child);
475                     }
476                 }
477             }
478             return esd;
479         }
480 #endif // FEATURE_CAS_POLICY
481
482         /// <internalonly/>
483         int IBuiltInPermission.GetTokenIndex()
484         {
485             return StrongNameIdentityPermission.GetTokenIndex();
486         }
487
488         internal static int GetTokenIndex()
489         {
490             return BuiltInPermissionIndex.StrongNameIdentityPermissionIndex;
491         }
492             
493     }
494 }