Fix null sessions in HttpContextWrapper.Session
[mono.git] / mcs / class / corlib / System.Security.Permissions / StrongNameIdentityPermission.cs
1 //
2 // StrongNameIdentityPermission.cs: Strong Name Identity Permission
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
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:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
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.
28 //
29
30 using System.Collections;
31 using System.Globalization;
32 using System.Runtime.InteropServices;
33
34 namespace System.Security.Permissions {
35
36         [ComVisible (true)]
37         [Serializable]
38         public sealed class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission {
39         
40                 private const int version = 1;
41                 static private Version defaultVersion = new Version (0, 0);
42
43                 private struct SNIP {
44                         public StrongNamePublicKeyBlob PublicKey;
45                         public string Name;
46                         public Version AssemblyVersion;
47
48                         internal SNIP (StrongNamePublicKeyBlob pk, string name, Version version)
49                         {
50                                 PublicKey = pk;
51                                 Name = name;
52                                 AssemblyVersion = version;
53                         }
54
55                         internal static SNIP CreateDefault ()
56                         {
57                                 return new SNIP (null, String.Empty, (Version) defaultVersion.Clone ());
58                         }
59
60                         internal bool IsNameSubsetOf (string target) 
61                         {
62                                 if (Name == null)
63                                         return (target == null);
64                                 if (target == null)
65                                         return true;
66
67                                 int wildcard = Name.LastIndexOf ('*');
68                                 if (wildcard == 0)
69                                         return true;            // *
70                                 if (wildcard == -1)
71                                         wildcard = Name.Length; // exact match
72
73                                 return (String.Compare (Name, 0, target, 0, wildcard, true, CultureInfo.InvariantCulture) == 0);
74                         }
75
76                         internal bool IsSubsetOf (SNIP target)
77                         {
78                                 if ((PublicKey != null) && PublicKey.Equals (target.PublicKey))
79                                         return true;
80
81                                 if (!IsNameSubsetOf (target.Name))
82                                         return false;
83                                 if ((AssemblyVersion != null) && !AssemblyVersion.Equals (target.AssemblyVersion))
84                                         return false;
85                                 // in case PermissionState.None was used in the constructor
86                                 if (PublicKey == null)
87                                         return (target.PublicKey == null);
88                                 return false;
89                         }
90                 }
91
92                 private PermissionState _state;
93                 private ArrayList _list;
94
95                 public StrongNameIdentityPermission (PermissionState state) 
96                 {
97                         // Identity Permissions can be unrestricted in Fx 2.0
98                         _state = CheckPermissionState (state, true);
99                         // default values
100                         _list = new ArrayList ();
101                         _list.Add (SNIP.CreateDefault ());
102                 }
103
104                 public StrongNameIdentityPermission (StrongNamePublicKeyBlob blob, string name, Version version) 
105                 {
106                         if (blob == null)
107                                 throw new ArgumentNullException ("blob");
108                         if ((name != null) && (name.Length == 0))
109                                 throw new ArgumentException ("name");
110
111                         _state = PermissionState.None;
112                         _list = new ArrayList ();
113                         _list.Add (new SNIP (blob, name, version));
114                 }
115
116                 internal StrongNameIdentityPermission (StrongNameIdentityPermission snip) 
117                 {
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));
122                         }
123                 }
124
125                 // Properties
126
127                 public string Name { 
128                         get {
129                                 if (_list.Count > 1)
130                                         throw new NotSupportedException ();
131                                 return ((SNIP)_list [0]).Name;
132                         }
133                         set { 
134                                 if ((value != null) && (value.Length == 0))
135                                         throw new ArgumentException ("name");
136                                 if (_list.Count > 1)
137                                         ResetToDefault ();
138                                 SNIP snip = (SNIP) _list [0];
139                                 snip.Name = value;
140                                 _list [0] = snip;
141                         }
142                 }
143
144                 public StrongNamePublicKeyBlob PublicKey { 
145                         get {
146                                 if (_list.Count > 1)
147                                         throw new NotSupportedException ();
148                                 return ((SNIP)_list [0]).PublicKey;
149                         }
150                         set {
151                                 if (value == null)
152                                         throw new ArgumentNullException ("value");
153                                 if (_list.Count > 1)
154                                         ResetToDefault ();
155                                 SNIP snip = (SNIP) _list [0];
156                                 snip.PublicKey = value;
157                                 _list [0] = snip;
158                         }
159                 }
160         
161                 public Version Version { 
162                         get {
163                                 if (_list.Count > 1)
164                                         throw new NotSupportedException ();
165                                 return ((SNIP)_list [0]).AssemblyVersion;
166                         }
167                         set {
168                                 if (_list.Count > 1)
169                                         ResetToDefault ();
170                                 SNIP snip = (SNIP) _list [0];
171                                 snip.AssemblyVersion = value;
172                                 _list [0] = snip;
173                         }
174                 }
175
176                 internal void ResetToDefault ()
177                 {
178                         _list.Clear ();
179                         _list.Add (SNIP.CreateDefault ());
180                 }
181
182                 // Methods
183         
184                 public override IPermission Copy () 
185                 {
186                         if (IsEmpty ())
187                                 return new StrongNameIdentityPermission (PermissionState.None);
188                         else
189                                 return new StrongNameIdentityPermission (this);
190                 }
191         
192                 public override void FromXml (SecurityElement e) 
193                 {
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)
198                         _list.Clear ();
199                         if ((e.Children != null) && (e.Children.Count > 0)) {
200                                 foreach (SecurityElement se in e.Children) {
201                                         _list.Add (FromSecurityElement (se));
202                                 }
203                         } else {
204                                 _list.Add (FromSecurityElement (e));
205                         }
206                 }
207
208                 private SNIP FromSecurityElement (SecurityElement se)
209                 {
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);
214
215                         return new SNIP (publickey, name, assemblyVersion);
216                 }
217                 public override IPermission Intersect (IPermission target) 
218                 {
219                         if (target == null)
220                                 return null;
221                         StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
222                         if (snip == null) 
223                                 throw new ArgumentException (Locale.GetText ("Wrong permission type."));
224                         if (IsEmpty () || snip.IsEmpty ())
225                                 return null;
226                         if (!Match (snip.Name))
227                                 return null;
228
229                         string n = ((Name.Length < snip.Name.Length) ? Name : snip.Name);
230                         if (!Version.Equals (snip.Version))
231                                 return null;
232                         if (!PublicKey.Equals (snip.PublicKey))
233                                 return null;
234
235                         return new StrongNameIdentityPermission (this.PublicKey, n, this.Version);
236                 }
237
238                 public override bool IsSubsetOf (IPermission target) 
239                 {
240                         StrongNameIdentityPermission snip = Cast (target);
241                         if (snip == null)
242                                 return IsEmpty ();
243
244                         if (IsEmpty ())
245                                 return true;
246                         if (IsUnrestricted ())
247                                 return snip.IsUnrestricted ();
248                         else if (snip.IsUnrestricted ())
249                                 return true;
250
251                         foreach (SNIP e in _list) {
252                                 foreach (SNIP t in snip._list) {
253                                         if (!e.IsSubsetOf (t))
254                                                 return false;
255                                 }
256                         }
257                         return true;
258                 }
259         
260                 public override SecurityElement ToXml () 
261                 {
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);
267                                         se.AddChild (child);
268                                 }
269                         } else if (_list.Count == 1) {
270                                 SNIP snip = (SNIP)_list [0];
271                                 if (!IsEmpty (snip))
272                                         ToSecurityElement (se, snip);
273                         }
274                         return se;
275                 }
276
277                 private void ToSecurityElement (SecurityElement se, SNIP snip)
278                 {
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 ());
285                 }
286
287                 public override IPermission Union (IPermission target) 
288                 {
289                         StrongNameIdentityPermission snip = Cast (target);
290                         if ((snip == null) || snip.IsEmpty ())
291                                 return Copy ();
292
293                         if (IsEmpty ())
294                                 return snip.Copy ();
295
296                         StrongNameIdentityPermission union = (StrongNameIdentityPermission) Copy ();
297                         foreach (SNIP e in snip._list) {
298                                 if (!IsEmpty (e) && !Contains (e)) {
299                                         union._list.Add (e);
300                                 }
301                         }
302                         return union;
303                 }
304         
305                 // IBuiltInPermission
306                 int IBuiltInPermission.GetTokenIndex ()
307                 {
308                         return (int) BuiltInToken.StrongNameIdentity;
309                 }
310
311                 // helpers
312
313                 private bool IsUnrestricted ()
314                 {
315                         return (_state == PermissionState.Unrestricted);
316                 }
317
318                 private bool Contains (SNIP snip)
319                 {
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)));
326
327                                 if (pk && name && version)
328                                         return true;
329                         }
330                         return false;
331                 }
332
333                 private bool IsEmpty (SNIP snip)
334                 {
335                         if (PublicKey != null)
336                                 return false;
337                         if ((Name != null) && (Name.Length > 0))
338                                 return false;
339                         return ((Version == null) || defaultVersion.Equals (Version));
340                 }
341
342                 private bool IsEmpty ()
343                 {
344                         if (IsUnrestricted () || (_list.Count > 1))
345                                 return false;
346                         if (PublicKey != null)
347                                 return false;
348                         if ((Name != null) && (Name.Length > 0))
349                                 return false;
350                         return ((Version == null) || defaultVersion.Equals (Version));
351                 }
352
353                 private StrongNameIdentityPermission Cast (IPermission target)
354                 {
355                         if (target == null)
356                                 return null;
357
358                         StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
359                         if (snip == null) {
360                                 ThrowInvalidPermission (target, typeof (StrongNameIdentityPermission));
361                         }
362
363                         return snip;
364                 }
365
366                 private bool Match (string target) 
367                 {
368                         if ((Name == null) || (target == null))
369                                 return false;
370
371                         int wcu = Name.LastIndexOf ('*');
372                         int wct = target.LastIndexOf ('*');
373                         int length = Int32.MaxValue;
374
375                         if ((wcu == -1) && (wct == -1)) {
376                                 // no wildcard, this is an exact match
377                                 length = Math.Max (Name.Length, target.Length);
378                         }
379                         else if (wcu == -1) {
380                                 // only "target" has a wildcard, use it
381                                 length = wct;
382                         }
383                         else if (wct == -1) {
384                                 // only "this" has a wildcard, use it
385                                 length = wcu;
386                         }
387                         else {
388                                 // both have wildcards, partial match with the smallest
389                                 length = Math.Min (wcu, wct);
390                         }
391
392                         return (String.Compare (Name, 0, target, 0, length, true, CultureInfo.InvariantCulture) == 0);
393                 }
394         } 
395 }