2 // System.Security.Policy.Evidence
5 // Sean MacIsaac (macisaac@ximian.com)
6 // Nick Drochak (ndrochak@gol.com)
7 // Jackson Harper (Jackson@LatitudeGeo.com)
8 // Sebastien Pouliot <sebastien@ximian.com>
10 // (C) 2001 Ximian, Inc.
11 // Portions (C) 2003, 2004 Motus Technologies Inc. (http://www.motus.com)
12 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System
.Collections
;
35 using System
.Globalization
;
36 using System
.Reflection
;
37 using System
.Runtime
.CompilerServices
;
38 using System
.Runtime
.InteropServices
;
39 using System
.Security
.Permissions
;
40 using System
.Security
.Cryptography
.X509Certificates
;
43 using Mono
.Security
.Authenticode
;
46 namespace System
.Security
.Policy
{
49 [MonoTODO ("Serialization format not compatible with .NET")]
51 public sealed class Evidence
: ICollection
, IEnumerable
{
54 private ArrayList hostEvidenceList
;
55 private ArrayList assemblyEvidenceList
;
56 private int _hashCode
;
62 public Evidence (Evidence evidence
)
71 public Evidence (object[] hostEvidence
, object[] assemblyEvidence
)
73 if (null != hostEvidence
)
74 HostEvidenceList
.AddRange (hostEvidence
);
75 if (null != assemblyEvidence
)
76 AssemblyEvidenceList
.AddRange (assemblyEvidence
);
89 if (hostEvidenceList
!= null)
90 count
+= hostEvidenceList
.Count
;
91 if (assemblyEvidenceList
!= null)
92 count
+= assemblyEvidenceList
.Count
;
97 public bool IsReadOnly
{
101 public bool IsSynchronized
{
102 get { return false; }
106 get { return _locked; }
107 [SecurityPermission (SecurityAction
.Demand
, ControlEvidence
= true)]
113 public object SyncRoot
{
117 internal ArrayList HostEvidenceList
{
119 if (hostEvidenceList
== null)
120 hostEvidenceList
= ArrayList
.Synchronized (new ArrayList ());
121 return hostEvidenceList
;
125 internal ArrayList AssemblyEvidenceList
{
127 if (assemblyEvidenceList
== null)
128 assemblyEvidenceList
= ArrayList
.Synchronized (new ArrayList ());
129 return assemblyEvidenceList
;
140 public void AddAssembly (object id
)
142 AssemblyEvidenceList
.Add (id
);
149 public void AddHost (object id
)
151 if (_locked
&& SecurityManager
.SecurityEnabled
) {
152 new SecurityPermission (SecurityPermissionFlag
.ControlEvidence
).Demand ();
154 HostEvidenceList
.Add (id
);
161 if (hostEvidenceList
!= null)
162 hostEvidenceList
.Clear ();
163 if (assemblyEvidenceList
!= null)
164 assemblyEvidenceList
.Clear ();
171 public void CopyTo (Array array
, int index
)
174 if (hostEvidenceList
!= null) {
175 hc
= hostEvidenceList
.Count
;
177 hostEvidenceList
.CopyTo (array
, index
);
179 if ((assemblyEvidenceList
!= null) && (assemblyEvidenceList
.Count
> 0))
180 assemblyEvidenceList
.CopyTo (array
, index
+ hc
);
184 public override bool Equals (object obj
)
188 Evidence e
= (obj
as Evidence
);
192 if (HostEvidenceList
.Count
!= e
.HostEvidenceList
.Count
)
194 if (AssemblyEvidenceList
.Count
!= e
.AssemblyEvidenceList
.Count
)
197 for (int i
= 0; i
< hostEvidenceList
.Count
; i
++) {
199 for (int j
= 0; j
< e
.hostEvidenceList
.Count
; i
++) {
200 if (hostEvidenceList
[i
].Equals (e
.hostEvidenceList
[j
])) {
208 for (int i
= 0; i
< assemblyEvidenceList
.Count
; i
++) {
210 for (int j
= 0; j
< e
.assemblyEvidenceList
.Count
; i
++) {
211 if (assemblyEvidenceList
[i
].Equals (e
.assemblyEvidenceList
[j
])) {
226 public IEnumerator
GetEnumerator ()
228 IEnumerator he
= null;
229 if (hostEvidenceList
!= null)
230 he
= hostEvidenceList
.GetEnumerator ();
231 IEnumerator ae
= null;
232 if (assemblyEvidenceList
!= null)
233 ae
= assemblyEvidenceList
.GetEnumerator ();
234 return new EvidenceEnumerator (he
, ae
);
237 public IEnumerator
GetAssemblyEnumerator ()
239 return AssemblyEvidenceList
.GetEnumerator ();
243 public override int GetHashCode ()
245 // kind of long so we cache it
246 if (_hashCode
== 0) {
247 if (hostEvidenceList
!= null) {
248 for (int i
= 0; i
< hostEvidenceList
.Count
; i
++)
249 _hashCode ^
= hostEvidenceList
[i
].GetHashCode ();
251 if (assemblyEvidenceList
!= null) {
252 for (int i
= 0; i
< assemblyEvidenceList
.Count
; i
++)
253 _hashCode ^
= assemblyEvidenceList
[i
].GetHashCode ();
259 public IEnumerator
GetHostEnumerator ()
261 return HostEvidenceList
.GetEnumerator ();
264 public void Merge (Evidence evidence
)
266 if ((evidence
!= null) && (evidence
.Count
> 0)) {
267 if (evidence
.hostEvidenceList
!= null) {
268 foreach (object o
in evidence
.hostEvidenceList
)
271 if (evidence
.assemblyEvidenceList
!= null) {
272 foreach (object o
in evidence
.assemblyEvidenceList
)
280 public void RemoveType (Type t
)
282 for (int i
= hostEvidenceList
.Count
; i
>= 0; i
--) {
283 if (hostEvidenceList
.GetType () == t
) {
284 hostEvidenceList
.RemoveAt (i
);
288 for (int i
= assemblyEvidenceList
.Count
; i
>= 0; i
--) {
289 if (assemblyEvidenceList
.GetType () == t
) {
290 assemblyEvidenceList
.RemoveAt (i
);
296 // Use an icall to avoid multiple file i/o to detect the
297 // "possible" presence of an Authenticode signature
298 [MethodImplAttribute (MethodImplOptions
.InternalCall
)]
299 static extern bool IsAuthenticodePresent (Assembly a
);
301 static internal Evidence
GetDefaultHostEvidence (Assembly a
)
303 return new Evidence ();
306 // this avoid us to build all evidences from the runtime
307 // (i.e. multiple unmanaged->managed calls) and also allows
308 // to delay their creation until (if) needed
309 [FileIOPermission (SecurityAction
.Assert
, Unrestricted
= true)]
310 static internal Evidence
GetDefaultHostEvidence (Assembly a
)
312 Evidence e
= new Evidence ();
313 string aname
= a
.EscapedCodeBase
;
315 // by default all assembly have the Zone, Url and Hash evidences
316 e
.AddHost (Zone
.CreateFromUrl (aname
));
317 e
.AddHost (new Url (aname
));
318 e
.AddHost (new Hash (a
));
320 // non local files (e.g. http://) also get a Site evidence
321 if (String
.Compare ("FILE://", 0, aname
, 0, 7, true, CultureInfo
.InvariantCulture
) != 0) {
322 e
.AddHost (Site
.CreateFromUrl (aname
));
325 // strongnamed assemblies gets a StrongName evidence
326 AssemblyName an
= a
.UnprotectedGetName ();
327 byte[] pk
= an
.GetPublicKey ();
328 if ((pk
!= null) && (pk
.Length
> 0)) {
329 StrongNamePublicKeyBlob blob
= new StrongNamePublicKeyBlob (pk
);
330 e
.AddHost (new StrongName (blob
, an
.Name
, an
.Version
));
333 // Authenticode(r) signed assemblies get a Publisher evidence
334 if (IsAuthenticodePresent (a
)) {
335 // Note: The certificate is part of the evidences even if it is not trusted!
336 // so we can't call X509Certificate.CreateFromSignedFile
337 AuthenticodeDeformatter ad
= new AuthenticodeDeformatter (a
.Location
);
338 if (ad
.SigningCertificate
!= null) {
339 X509Certificate x509
= new X509Certificate (ad
.SigningCertificate
.RawData
);
340 if (x509
.GetHashCode () != 0) {
341 e
.AddHost (new Publisher (x509
));
345 // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
346 if (a
.GlobalAssemblyCache
) {
347 e
.AddHost (new GacInstalled ());
350 // the current HostSecurityManager may add/remove some evidence
351 AppDomainManager dommgr
= AppDomain
.CurrentDomain
.DomainManager
;
352 if (dommgr
!= null) {
353 if ((dommgr
.HostSecurityManager
.Flags
& HostSecurityManagerOptions
.HostAssemblyEvidence
) ==
354 HostSecurityManagerOptions
.HostAssemblyEvidence
) {
355 e
= dommgr
.HostSecurityManager
.ProvideAssemblyEvidence (a
, e
);
364 private class EvidenceEnumerator
: IEnumerator
{
366 private IEnumerator currentEnum
, hostEnum
, assemblyEnum
;
368 public EvidenceEnumerator (IEnumerator hostenum
, IEnumerator assemblyenum
)
370 this.hostEnum
= hostenum
;
371 this.assemblyEnum
= assemblyenum
;
372 currentEnum
= hostEnum
;
375 public bool MoveNext ()
377 if (currentEnum
== null)
380 bool ret
= currentEnum
.MoveNext ();
382 if (!ret
&& (hostEnum
== currentEnum
) && (assemblyEnum
!= null)) {
383 currentEnum
= assemblyEnum
;
384 ret
= assemblyEnum
.MoveNext ();
392 if (hostEnum
!= null) {
394 currentEnum
= hostEnum
;
396 currentEnum
= assemblyEnum
;
398 if (assemblyEnum
!= null)
399 assemblyEnum
.Reset ();
402 public object Current
{
404 return currentEnum
.Current
;