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;
41 using Mono.Security.Authenticode;
43 namespace System.Security.Policy {
46 [MonoTODO ("Serialization format not compatible with .NET")]
48 public sealed class Evidence : ICollection, IEnumerable {
51 private ArrayList hostEvidenceList;
52 private ArrayList assemblyEvidenceList;
58 public Evidence (Evidence evidence)
65 public Evidence (object[] hostEvidence, object[] assemblyEvidence)
67 if (null != hostEvidence)
68 HostEvidenceList.AddRange (hostEvidence);
69 if (null != assemblyEvidence)
70 AssemblyEvidenceList.AddRange (assemblyEvidence);
81 if (hostEvidenceList != null)
82 count += hostEvidenceList.Count;
83 if (assemblyEvidenceList!= null)
84 count += assemblyEvidenceList.Count;
89 public bool IsReadOnly {
93 public bool IsSynchronized {
98 get { return _locked; }
99 [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
105 public object SyncRoot {
109 internal ArrayList HostEvidenceList {
111 if (hostEvidenceList == null)
112 hostEvidenceList = ArrayList.Synchronized (new ArrayList ());
113 return hostEvidenceList;
117 internal ArrayList AssemblyEvidenceList {
119 if (assemblyEvidenceList == null)
120 assemblyEvidenceList = ArrayList.Synchronized (new ArrayList ());
121 return assemblyEvidenceList;
130 public void AddAssembly (object id)
132 AssemblyEvidenceList.Add (id);
136 public void AddHost (object id)
138 if (_locked && SecurityManager.SecurityEnabled) {
139 new SecurityPermission (SecurityPermissionFlag.ControlEvidence).Demand ();
141 HostEvidenceList.Add (id);
147 if (hostEvidenceList != null)
148 hostEvidenceList.Clear ();
149 if (assemblyEvidenceList != null)
150 assemblyEvidenceList.Clear ();
154 public void CopyTo (Array array, int index)
157 if (hostEvidenceList != null) {
158 hc = hostEvidenceList.Count;
160 hostEvidenceList.CopyTo (array, index);
162 if ((assemblyEvidenceList != null) && (assemblyEvidenceList.Count > 0))
163 assemblyEvidenceList.CopyTo (array, index + hc);
168 public IEnumerator GetEnumerator ()
170 IEnumerator he = null;
171 if (hostEvidenceList != null)
172 he = hostEvidenceList.GetEnumerator ();
173 IEnumerator ae = null;
174 if (assemblyEvidenceList != null)
175 ae = assemblyEvidenceList.GetEnumerator ();
176 return new EvidenceEnumerator (he, ae);
179 public IEnumerator GetAssemblyEnumerator ()
181 return AssemblyEvidenceList.GetEnumerator ();
184 public IEnumerator GetHostEnumerator ()
186 return HostEvidenceList.GetEnumerator ();
189 public void Merge (Evidence evidence)
191 if ((evidence != null) && (evidence.Count > 0)) {
192 if (evidence.hostEvidenceList != null) {
193 foreach (object o in evidence.hostEvidenceList)
196 if (evidence.assemblyEvidenceList != null) {
197 foreach (object o in evidence.assemblyEvidenceList)
204 public void RemoveType (Type t)
206 for (int i = hostEvidenceList.Count; i >= 0; i--) {
207 if (hostEvidenceList.GetType () == t) {
208 hostEvidenceList.RemoveAt (i);
211 for (int i = assemblyEvidenceList.Count; i >= 0; i--) {
212 if (assemblyEvidenceList.GetType () == t) {
213 assemblyEvidenceList.RemoveAt (i);
218 // Use an icall to avoid multiple file i/o to detect the
219 // "possible" presence of an Authenticode signature
220 [MethodImplAttribute (MethodImplOptions.InternalCall)]
221 static extern bool IsAuthenticodePresent (Assembly a);
223 static internal Evidence GetDefaultHostEvidence (Assembly a)
225 return new Evidence ();
228 // this avoid us to build all evidences from the runtime
229 // (i.e. multiple unmanaged->managed calls) and also allows
230 // to delay their creation until (if) needed
231 [FileIOPermission (SecurityAction.Assert, Unrestricted = true)]
232 static internal Evidence GetDefaultHostEvidence (Assembly a)
234 Evidence e = new Evidence ();
235 string aname = a.EscapedCodeBase;
237 // by default all assembly have the Zone, Url and Hash evidences
238 e.AddHost (Zone.CreateFromUrl (aname));
239 e.AddHost (new Url (aname));
240 e.AddHost (new Hash (a));
242 // non local files (e.g. http://) also get a Site evidence
243 if (String.Compare ("FILE://", 0, aname, 0, 7, true, CultureInfo.InvariantCulture) != 0) {
244 e.AddHost (Site.CreateFromUrl (aname));
247 // strongnamed assemblies gets a StrongName evidence
248 AssemblyName an = a.UnprotectedGetName ();
249 byte[] pk = an.GetPublicKey ();
250 if ((pk != null) && (pk.Length > 0)) {
251 StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob (pk);
252 e.AddHost (new StrongName (blob, an.Name, an.Version));
255 // Authenticode(r) signed assemblies get a Publisher evidence
256 if (IsAuthenticodePresent (a)) {
257 // Note: The certificate is part of the evidences even if it is not trusted!
258 // so we can't call X509Certificate.CreateFromSignedFile
259 AuthenticodeDeformatter ad = new AuthenticodeDeformatter (a.Location);
260 if (ad.SigningCertificate != null) {
261 X509Certificate x509 = new X509Certificate (ad.SigningCertificate.RawData);
262 if (x509.GetHashCode () != 0) {
263 e.AddHost (new Publisher (x509));
267 // assemblies loaded from the GAC also get a Gac evidence (new in Fx 2.0)
268 if (a.GlobalAssemblyCache) {
269 e.AddHost (new GacInstalled ());
272 // the current HostSecurityManager may add/remove some evidence
273 AppDomainManager dommgr = AppDomain.CurrentDomain.DomainManager;
274 if (dommgr != null) {
275 if ((dommgr.HostSecurityManager.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) ==
276 HostSecurityManagerOptions.HostAssemblyEvidence) {
277 e = dommgr.HostSecurityManager.ProvideAssemblyEvidence (a, e);
286 private class EvidenceEnumerator : IEnumerator {
288 private IEnumerator currentEnum, hostEnum, assemblyEnum;
290 public EvidenceEnumerator (IEnumerator hostenum, IEnumerator assemblyenum)
292 this.hostEnum = hostenum;
293 this.assemblyEnum = assemblyenum;
294 currentEnum = hostEnum;
297 public bool MoveNext ()
299 if (currentEnum == null)
302 bool ret = currentEnum.MoveNext ();
304 if (!ret && (hostEnum == currentEnum) && (assemblyEnum != null)) {
305 currentEnum = assemblyEnum;
306 ret = assemblyEnum.MoveNext ();
314 if (hostEnum != null) {
316 currentEnum = hostEnum;
318 currentEnum = assemblyEnum;
320 if (assemblyEnum != null)
321 assemblyEnum.Reset ();
324 public object Current {
326 return currentEnum.Current;