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 {
38 public sealed class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission {
40 private const int version = 1;
41 static private Version defaultVersion = new Version (0, 0);
44 public StrongNamePublicKeyBlob PublicKey;
46 public Version AssemblyVersion;
48 internal SNIP (StrongNamePublicKeyBlob pk, string name, Version version)
52 AssemblyVersion = version;
55 internal static SNIP CreateDefault ()
57 return new SNIP (null, String.Empty, (Version) defaultVersion.Clone ());
60 internal bool IsNameSubsetOf (string target)
63 return (target == null);
67 int wildcard = Name.LastIndexOf ('*');
71 wildcard = Name.Length; // exact match
73 return (String.Compare (Name, 0, target, 0, wildcard, true, CultureInfo.InvariantCulture) == 0);
76 internal bool IsSubsetOf (SNIP target)
78 if ((PublicKey != null) && PublicKey.Equals (target.PublicKey))
81 if (!IsNameSubsetOf (target.Name))
83 if ((AssemblyVersion != null) && !AssemblyVersion.Equals (target.AssemblyVersion))
85 // in case PermissionState.None was used in the constructor
86 if (PublicKey == null)
87 return (target.PublicKey == null);
92 private PermissionState _state;
93 private ArrayList _list;
95 public StrongNameIdentityPermission (PermissionState state)
97 // Identity Permissions can be unrestricted in Fx 2.0
98 _state = CheckPermissionState (state, true);
100 _list = new ArrayList ();
101 _list.Add (SNIP.CreateDefault ());
104 public StrongNameIdentityPermission (StrongNamePublicKeyBlob blob, string name, Version version)
107 throw new ArgumentNullException ("blob");
108 if ((name != null) && (name.Length == 0))
109 throw new ArgumentException ("name");
111 _state = PermissionState.None;
112 _list = new ArrayList ();
113 _list.Add (new SNIP (blob, name, version));
116 internal StrongNameIdentityPermission (StrongNameIdentityPermission snip)
118 _state = snip._state;
119 _list = new ArrayList (snip._list.Count);
120 foreach (SNIP e in snip._list) {
121 _list.Add (new SNIP (e.PublicKey, e.Name, e.AssemblyVersion));
130 throw new NotSupportedException ();
131 return ((SNIP)_list [0]).Name;
134 if ((value != null) && (value.Length == 0))
135 throw new ArgumentException ("name");
138 SNIP snip = (SNIP) _list [0];
144 public StrongNamePublicKeyBlob PublicKey {
147 throw new NotSupportedException ();
148 return ((SNIP)_list [0]).PublicKey;
152 throw new ArgumentNullException ("value");
155 SNIP snip = (SNIP) _list [0];
156 snip.PublicKey = value;
161 public Version Version {
164 throw new NotSupportedException ();
165 return ((SNIP)_list [0]).AssemblyVersion;
170 SNIP snip = (SNIP) _list [0];
171 snip.AssemblyVersion = value;
176 internal void ResetToDefault ()
179 _list.Add (SNIP.CreateDefault ());
184 public override IPermission Copy ()
187 return new StrongNameIdentityPermission (PermissionState.None);
189 return new StrongNameIdentityPermission (this);
192 public override void FromXml (SecurityElement e)
194 // General validation in CodeAccessPermission
195 CheckSecurityElement (e, "e", version, version);
196 // Note: we do not (yet) care about the return value
197 // as we only accept version 1 (min/max values)
199 if ((e.Children != null) && (e.Children.Count > 0)) {
200 foreach (SecurityElement se in e.Children) {
201 _list.Add (FromSecurityElement (se));
204 _list.Add (FromSecurityElement (e));
208 private SNIP FromSecurityElement (SecurityElement se)
210 string name = se.Attribute ("Name");
211 StrongNamePublicKeyBlob publickey = StrongNamePublicKeyBlob.FromString (se.Attribute ("PublicKeyBlob"));
212 string v = se.Attribute ("AssemblyVersion");
213 Version assemblyVersion = (v == null) ? null : new Version (v);
215 return new SNIP (publickey, name, assemblyVersion);
217 public override IPermission Intersect (IPermission target)
221 StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
223 throw new ArgumentException (Locale.GetText ("Wrong permission type."));
224 if (IsEmpty () || snip.IsEmpty ())
226 if (!Match (snip.Name))
229 string n = ((Name.Length < snip.Name.Length) ? Name : snip.Name);
230 if (!Version.Equals (snip.Version))
232 if (!PublicKey.Equals (snip.PublicKey))
235 return new StrongNameIdentityPermission (this.PublicKey, n, this.Version);
238 public override bool IsSubsetOf (IPermission target)
240 StrongNameIdentityPermission snip = Cast (target);
246 if (IsUnrestricted ())
247 return snip.IsUnrestricted ();
248 else if (snip.IsUnrestricted ())
251 foreach (SNIP e in _list) {
252 foreach (SNIP t in snip._list) {
253 if (!e.IsSubsetOf (t))
260 public override SecurityElement ToXml ()
262 SecurityElement se = Element (version);
263 if (_list.Count > 1) {
264 foreach (SNIP snip in _list) {
265 SecurityElement child = new SecurityElement ("StrongName");
266 ToSecurityElement (child, snip);
269 } else if (_list.Count == 1) {
270 SNIP snip = (SNIP)_list [0];
272 ToSecurityElement (se, snip);
277 private void ToSecurityElement (SecurityElement se, SNIP snip)
279 if (snip.PublicKey != null)
280 se.AddAttribute ("PublicKeyBlob", snip.PublicKey.ToString ());
281 if (snip.Name != null)
282 se.AddAttribute ("Name", snip.Name);
283 if (snip.AssemblyVersion != null)
284 se.AddAttribute ("AssemblyVersion", snip.AssemblyVersion.ToString ());
287 public override IPermission Union (IPermission target)
289 StrongNameIdentityPermission snip = Cast (target);
290 if ((snip == null) || snip.IsEmpty ())
296 StrongNameIdentityPermission union = (StrongNameIdentityPermission) Copy ();
297 foreach (SNIP e in snip._list) {
298 if (!IsEmpty (e) && !Contains (e)) {
305 // IBuiltInPermission
306 int IBuiltInPermission.GetTokenIndex ()
308 return (int) BuiltInToken.StrongNameIdentity;
313 private bool IsUnrestricted ()
315 return (_state == PermissionState.Unrestricted);
318 private bool Contains (SNIP snip)
320 foreach (SNIP e in _list) {
321 bool pk = (((e.PublicKey == null) && (snip.PublicKey == null)) ||
322 ((e.PublicKey != null) && e.PublicKey.Equals (snip.PublicKey)));
323 bool name = e.IsNameSubsetOf (snip.Name);
324 bool version = (((e.AssemblyVersion == null) && (snip.AssemblyVersion == null)) ||
325 ((e.AssemblyVersion != null) && e.AssemblyVersion.Equals (snip.AssemblyVersion)));
327 if (pk && name && version)
333 private bool IsEmpty (SNIP snip)
335 if (PublicKey != null)
337 if ((Name != null) && (Name.Length > 0))
339 return ((Version == null) || defaultVersion.Equals (Version));
342 private bool IsEmpty ()
344 if (IsUnrestricted () || (_list.Count > 1))
346 if (PublicKey != null)
348 if ((Name != null) && (Name.Length > 0))
350 return ((Version == null) || defaultVersion.Equals (Version));
353 private StrongNameIdentityPermission Cast (IPermission target)
358 StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
360 ThrowInvalidPermission (target, typeof (StrongNameIdentityPermission));
366 private bool Match (string target)
368 if ((Name == null) || (target == null))
371 int wcu = Name.LastIndexOf ('*');
372 int wct = target.LastIndexOf ('*');
373 int length = Int32.MaxValue;
375 if ((wcu == -1) && (wct == -1)) {
376 // no wildcard, this is an exact match
377 length = Math.Max (Name.Length, target.Length);
379 else if (wcu == -1) {
380 // only "target" has a wildcard, use it
383 else if (wct == -1) {
384 // only "this" has a wildcard, use it
388 // both have wildcards, partial match with the smallest
389 length = Math.Min (wcu, wct);
392 return (String.Compare (Name, 0, target, 0, length, true, CultureInfo.InvariantCulture) == 0);