2 // StrongNameIdentityPermission.cs: Strong Name Identity Permission
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System.Collections;
31 using System.Globalization;
32 using System.Runtime.InteropServices;
34 namespace System.Security.Permissions {
40 public sealed class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission {
42 private const int version = 1;
43 static private Version defaultVersion = new Version (0, 0);
46 public StrongNamePublicKeyBlob PublicKey;
48 public Version AssemblyVersion;
50 internal SNIP (StrongNamePublicKeyBlob pk, string name, Version version)
54 AssemblyVersion = version;
57 internal static SNIP CreateDefault ()
59 return new SNIP (null, String.Empty, (Version) defaultVersion.Clone ());
62 internal bool IsNameSubsetOf (string target)
65 return (target == null);
69 int wildcard = Name.LastIndexOf ('*');
73 wildcard = Name.Length; // exact match
75 return (String.Compare (Name, 0, target, 0, wildcard, true, CultureInfo.InvariantCulture) == 0);
78 internal bool IsSubsetOf (SNIP target)
80 if ((PublicKey != null) && PublicKey.Equals (target.PublicKey))
83 if (!IsNameSubsetOf (target.Name))
85 if ((AssemblyVersion != null) && !AssemblyVersion.Equals (target.AssemblyVersion))
87 // in case PermissionState.None was used in the constructor
88 if (PublicKey == null)
89 return (target.PublicKey == null);
95 private PermissionState _state;
96 private ArrayList _list;
98 public StrongNameIdentityPermission (PermissionState state)
100 // Identity Permissions can be unrestricted in Fx 2.0
101 _state = CheckPermissionState (state, true);
103 _list = new ArrayList ();
104 _list.Add (SNIP.CreateDefault ());
107 public StrongNameIdentityPermission (StrongNamePublicKeyBlob blob, string name, Version version)
110 throw new ArgumentNullException ("blob");
111 if ((name != null) && (name.Length == 0))
112 throw new ArgumentException ("name");
114 _state = PermissionState.None;
115 _list = new ArrayList ();
116 _list.Add (new SNIP (blob, name, version));
119 internal StrongNameIdentityPermission (StrongNameIdentityPermission snip)
121 _state = snip._state;
122 _list = new ArrayList (snip._list.Count);
123 foreach (SNIP e in snip._list) {
124 _list.Add (new SNIP (e.PublicKey, e.Name, e.AssemblyVersion));
128 private SNIP _single;
130 public StrongNameIdentityPermission (PermissionState state)
132 // false == do not allow Unrestricted for Identity Permissions
133 CheckPermissionState (state, false);
135 _single = SNIP.CreateDefault ();
138 public StrongNameIdentityPermission (StrongNamePublicKeyBlob blob, string name, Version version)
141 throw new ArgumentNullException ("blob");
143 _single = new SNIP (blob, name, version);
146 internal StrongNameIdentityPermission (StrongNameIdentityPermission snip)
147 : this (snip.PublicKey, snip.Name, snip.Version)
158 throw new NotSupportedException ();
159 return ((SNIP)_list [0]).Name;
162 if ((value != null) && (value.Length == 0))
163 throw new ArgumentException ("name");
166 SNIP snip = (SNIP) _list [0];
172 public StrongNamePublicKeyBlob PublicKey {
175 throw new NotSupportedException ();
176 return ((SNIP)_list [0]).PublicKey;
180 throw new ArgumentNullException ("value");
183 SNIP snip = (SNIP) _list [0];
184 snip.PublicKey = value;
189 public Version Version {
192 throw new NotSupportedException ();
193 return ((SNIP)_list [0]).AssemblyVersion;
198 SNIP snip = (SNIP) _list [0];
199 snip.AssemblyVersion = value;
204 internal void ResetToDefault ()
207 _list.Add (SNIP.CreateDefault ());
211 get { return _single.Name; }
212 set { _single.Name = value; }
215 public StrongNamePublicKeyBlob PublicKey {
216 get { return _single.PublicKey; }
219 throw new ArgumentNullException ("value");
220 _single.PublicKey = value;
224 public Version Version {
225 get { return _single.AssemblyVersion; }
226 set { _single.AssemblyVersion = value; }
232 public override IPermission Copy ()
235 return new StrongNameIdentityPermission (PermissionState.None);
237 return new StrongNameIdentityPermission (this);
240 public override void FromXml (SecurityElement e)
242 // General validation in CodeAccessPermission
243 CheckSecurityElement (e, "e", version, version);
244 // Note: we do not (yet) care about the return value
245 // as we only accept version 1 (min/max values)
248 if ((e.Children != null) && (e.Children.Count > 0)) {
249 foreach (SecurityElement se in e.Children) {
250 _list.Add (FromSecurityElement (se));
253 _list.Add (FromSecurityElement (e));
256 _single = FromSecurityElement (e);
260 private SNIP FromSecurityElement (SecurityElement se)
262 string name = se.Attribute ("Name");
263 StrongNamePublicKeyBlob publickey = StrongNamePublicKeyBlob.FromString (se.Attribute ("PublicKeyBlob"));
264 string v = se.Attribute ("AssemblyVersion");
265 Version assemblyVersion = (v == null) ? null : new Version (v);
267 return new SNIP (publickey, name, assemblyVersion);
270 public override IPermission Intersect (IPermission target)
274 StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
276 throw new ArgumentException (Locale.GetText ("Wrong permission type."));
277 if (IsEmpty () || snip.IsEmpty ())
279 if (!Match (snip.Name))
282 string n = ((Name.Length < snip.Name.Length) ? Name : snip.Name);
283 if (!Version.Equals (snip.Version))
285 if (!PublicKey.Equals (snip.PublicKey))
288 return new StrongNameIdentityPermission (this.PublicKey, n, this.Version);
291 public override bool IsSubsetOf (IPermission target)
293 StrongNameIdentityPermission snip = Cast (target);
299 if (IsUnrestricted ())
300 return snip.IsUnrestricted ();
301 else if (snip.IsUnrestricted ())
304 foreach (SNIP e in _list) {
305 foreach (SNIP t in snip._list) {
306 if (!e.IsSubsetOf (t))
313 public override IPermission Intersect (IPermission target)
315 StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
316 if ((snip == null) || IsEmpty ())
319 return new StrongNameIdentityPermission (PermissionState.None);
320 if (!Match (snip.Name))
323 string n = ((Name.Length < snip.Name.Length) ? Name : snip.Name);
324 if (!Version.Equals (snip.Version))
326 if (!PublicKey.Equals (snip.PublicKey))
329 return new StrongNameIdentityPermission (this.PublicKey, n, this.Version);
332 public override bool IsSubsetOf (IPermission target)
334 StrongNameIdentityPermission snip = Cast (target);
340 return _single.IsSubsetOf (snip._single);
344 public override SecurityElement ToXml ()
346 SecurityElement se = Element (version);
348 if (_list.Count > 1) {
349 foreach (SNIP snip in _list) {
350 SecurityElement child = new SecurityElement ("StrongName");
351 ToSecurityElement (child, snip);
354 } else if (_list.Count == 1) {
355 SNIP snip = (SNIP)_list [0];
357 ToSecurityElement (se, snip);
360 ToSecurityElement (se, _single);
365 private void ToSecurityElement (SecurityElement se, SNIP snip)
367 if (snip.PublicKey != null)
368 se.AddAttribute ("PublicKeyBlob", snip.PublicKey.ToString ());
369 if (snip.Name != null)
370 se.AddAttribute ("Name", snip.Name);
371 if (snip.AssemblyVersion != null)
372 se.AddAttribute ("AssemblyVersion", snip.AssemblyVersion.ToString ());
376 public override IPermission Union (IPermission target)
378 StrongNameIdentityPermission snip = Cast (target);
379 if ((snip == null) || snip.IsEmpty ())
385 StrongNameIdentityPermission union = (StrongNameIdentityPermission) Copy ();
386 foreach (SNIP e in snip._list) {
387 if (!IsEmpty (e) && !Contains (e)) {
394 public override IPermission Union (IPermission target)
396 StrongNameIdentityPermission snip = Cast (target);
397 if ((snip == null) || snip.IsEmpty ())
403 if (!PublicKey.Equals (snip.PublicKey)) {
408 if ((n == null) || (n.Length == 0)) {
411 else if (Match (snip.Name)) {
412 n = ((Name.Length > snip.Name.Length) ? Name : snip.Name);
414 else if ((snip.Name != null) && (snip.Name.Length > 0) && (n != snip.Name)) {
422 else if ((snip.Version != null) && (v != snip.Version)) {
426 return new StrongNameIdentityPermission (PublicKey, n, v);
430 // IBuiltInPermission
431 int IBuiltInPermission.GetTokenIndex ()
433 return (int) BuiltInToken.StrongNameIdentity;
439 private bool IsUnrestricted ()
441 return (_state == PermissionState.Unrestricted);
444 private bool Contains (SNIP snip)
446 foreach (SNIP e in _list) {
447 bool pk = (((e.PublicKey == null) && (snip.PublicKey == null)) ||
448 ((e.PublicKey != null) && e.PublicKey.Equals (snip.PublicKey)));
449 bool name = e.IsNameSubsetOf (snip.Name);
450 bool version = (((e.AssemblyVersion == null) && (snip.AssemblyVersion == null)) ||
451 ((e.AssemblyVersion != null) && e.AssemblyVersion.Equals (snip.AssemblyVersion)));
453 if (pk && name && version)
459 private bool IsEmpty (SNIP snip)
461 if (PublicKey != null)
463 if ((Name != null) && (Name.Length > 0))
465 return ((Version == null) || defaultVersion.Equals (Version));
469 private bool IsEmpty ()
472 if (IsUnrestricted () || (_list.Count > 1))
475 if (PublicKey != null)
477 if ((Name != null) && (Name.Length > 0))
479 return ((Version == null) || defaultVersion.Equals (Version));
482 private StrongNameIdentityPermission Cast (IPermission target)
487 StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
489 ThrowInvalidPermission (target, typeof (StrongNameIdentityPermission));
495 private bool Match (string target)
497 if ((Name == null) || (target == null))
500 int wcu = Name.LastIndexOf ('*');
501 int wct = target.LastIndexOf ('*');
502 int length = Int32.MaxValue;
504 if ((wcu == -1) && (wct == -1)) {
505 // no wildcard, this is an exact match
506 length = Math.Max (Name.Length, target.Length);
508 else if (wcu == -1) {
509 // only "target" has a wildcard, use it
512 else if (wct == -1) {
513 // only "this" has a wildcard, use it
517 // both have wildcards, partial match with the smallest
518 length = Math.Min (wcu, wct);
521 return (String.Compare (Name, 0, target, 0, length, true, CultureInfo.InvariantCulture) == 0);