3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 // <OWNER>Microsoft</OWNER>
10 using System.Collections.Generic;
11 using System.Diagnostics.Contracts;
12 using System.Reflection;
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Security;
16 using System.Security.Permissions;
17 using Microsoft.Win32.SafeHandles;
19 namespace System.Security.Policy
23 /// Factory class which can create evidence on demand for an assembly
25 internal sealed class AssemblyEvidenceFactory : IRuntimeEvidenceFactory
27 private PEFileEvidenceFactory m_peFileFactory;
28 private RuntimeAssembly m_targetAssembly;
31 /// Create a factory which can generate evidence for the specified assembly
33 private AssemblyEvidenceFactory(RuntimeAssembly targetAssembly, PEFileEvidenceFactory peFileFactory)
35 Contract.Assert(targetAssembly != null);
36 Contract.Assert(peFileFactory != null);
38 m_targetAssembly = targetAssembly;
39 m_peFileFactory = peFileFactory;
43 /// PEFile that the assembly is loaded from
45 internal SafePEFileHandle PEFile
48 get { return m_peFileFactory.PEFile; }
52 /// Assembly that the evidence generated is for
54 public IEvidenceFactory Target
56 get { return m_targetAssembly; }
60 /// Generate a specific type of evidence for this assembly
62 public EvidenceBase GenerateEvidence(Type evidenceType)
64 // Assembly evidence is a superset of the evidence that a PEFile can supply, so first see if the
65 // requested evidence type can be generated by the assembly's PEFile
66 EvidenceBase evidence = m_peFileFactory.GenerateEvidence(evidenceType);
72 // If the PEFile didn't know about this type of evidence, see if it is an evidence type that the
73 // Assembly knows how to generate
74 if (evidenceType == typeof(GacInstalled))
76 return GenerateGacEvidence();
78 else if (evidenceType == typeof(Hash))
80 return GenerateHashEvidence();
82 #pragma warning disable 618 // We need to generate PermissionRequestEvidence in compatibility mode
83 else if (evidenceType == typeof(PermissionRequestEvidence))
85 return GeneratePermissionRequestEvidence();
87 #pragma warning restore 618
88 else if (evidenceType == typeof(StrongName))
90 return GenerateStrongNameEvidence();
97 /// Generate evidence if the assembly is installed in the GAC
99 private GacInstalled GenerateGacEvidence()
101 if (!m_targetAssembly.GlobalAssemblyCache)
106 m_peFileFactory.FireEvidenceGeneratedEvent(EvidenceTypeGenerated.Gac);
107 return new GacInstalled();
111 /// Generate evidence for the assembly's hash value
113 private Hash GenerateHashEvidence()
115 if (m_targetAssembly.IsDynamic)
120 m_peFileFactory.FireEvidenceGeneratedEvent(EvidenceTypeGenerated.Hash);
121 return new Hash(m_targetAssembly);
124 #pragma warning disable 618 // We need to generate PermissionRequestEvidence in compatibility mode
126 /// Generate evidence for the assembly's declarative security
128 [SecuritySafeCritical]
129 private PermissionRequestEvidence GeneratePermissionRequestEvidence()
131 Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled);
133 PermissionSet minimumPermissions = null;
134 PermissionSet optionalPermissions = null;
135 PermissionSet refusedPermissions = null;
137 GetAssemblyPermissionRequests(m_targetAssembly.GetNativeHandle(),
138 JitHelpers.GetObjectHandleOnStack(ref minimumPermissions),
139 JitHelpers.GetObjectHandleOnStack(ref optionalPermissions),
140 JitHelpers.GetObjectHandleOnStack(ref refusedPermissions));
142 if (minimumPermissions != null || optionalPermissions != null || refusedPermissions != null)
144 return new PermissionRequestEvidence(minimumPermissions,
151 #pragma warning restore 618
154 /// Generate evidence for this file's strong name
156 [SecuritySafeCritical]
157 private StrongName GenerateStrongNameEvidence()
159 byte[] publicKeyBlob = null;
160 string simpleName = null;
161 ushort majorVersion = 0;
162 ushort minorVersion = 0;
166 GetStrongNameInformation(m_targetAssembly.GetNativeHandle(),
167 JitHelpers.GetObjectHandleOnStack(ref publicKeyBlob),
168 JitHelpers.GetStringHandleOnStack(ref simpleName),
174 if (publicKeyBlob == null || publicKeyBlob.Length == 0)
179 return new StrongName(new StrongNamePublicKeyBlob(publicKeyBlob),
181 new Version(majorVersion, minorVersion, build, revision),
185 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
187 [SuppressUnmanagedCodeSecurity]
188 private static extern void GetAssemblyPermissionRequests(RuntimeAssembly assembly,
189 ObjectHandleOnStack retMinimumPermissions,
190 ObjectHandleOnStack retOptionalPermissions,
191 ObjectHandleOnStack retRefusedPermissions);
194 /// Get any evidence that was serialized into the assembly
196 public IEnumerable<EvidenceBase> GetFactorySuppliedEvidence()
198 // The PEFile knows how to read the serialized evidence, so we can just delegate to it
199 return m_peFileFactory.GetFactorySuppliedEvidence();
202 [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
204 [SuppressUnmanagedCodeSecurity]
205 private static extern void GetStrongNameInformation(RuntimeAssembly assembly,
206 ObjectHandleOnStack retPublicKeyBlob,
207 StringHandleOnStack retSimpleName,
208 [Out] out ushort majorVersion,
209 [Out] out ushort minorVersion,
210 [Out] out ushort build,
211 [Out] out ushort revision);
214 /// Retarget an evidence object from generating evidence for a PEFile to generating evidence for
215 /// the file's assembly.
218 private static Evidence UpgradeSecurityIdentity(Evidence peFileEvidence, RuntimeAssembly targetAssembly)
220 Contract.Assert(peFileEvidence != null);
221 Contract.Assert(targetAssembly != null);
222 Contract.Assert(peFileEvidence.Target is PEFileEvidenceFactory, "Expected upgrade path is from PEFile to Assembly");
224 peFileEvidence.Target = new AssemblyEvidenceFactory(targetAssembly,
225 peFileEvidence.Target as PEFileEvidenceFactory);
227 // Whidbey hosts would provide evidence for assemblies up front rather than on demand. If there
228 // is a HostSecurityManager which does want to provide evidence, then we should provide it the
229 // opprotunity to do the same for compatibility.
230 HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager;
231 if ((securityManager.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) == HostSecurityManagerOptions.HostAssemblyEvidence)
233 peFileEvidence = securityManager.ProvideAssemblyEvidence(targetAssembly, peFileEvidence);
234 if (peFileEvidence == null)
236 throw new InvalidOperationException(Environment.GetResourceString("Policy_NullHostEvidence", securityManager.GetType().FullName, targetAssembly.FullName));
240 return peFileEvidence;