Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
12 KiB

  1. /*=============================================================================
  2. **
  3. ** Class: AsmExecute
  4. **
  5. ** Purpose: Used to setup the correct hosting environment before executing an assembly
  6. **
  7. ** Date: 10/20/2000
  8. ** 5/10/2001 Rev for CLR Beta2
  9. **
  10. ** Copyright (c) Microsoft, 1999-2001
  11. **
  12. =============================================================================*/
  13. using System.Reflection;
  14. using System.Configuration.Assemblies;
  15. [assembly:AssemblyCultureAttribute("")]
  16. [assembly:AssemblyVersionAttribute("1.0.128.0")]
  17. [assembly:AssemblyKeyFileAttribute(/*"..\..\*/"asmexecKey.snk")]
  18. [assembly:AssemblyTitleAttribute("Microsoft Fusion .Net Assembly Execute Host")]
  19. [assembly:AssemblyDescriptionAttribute("Microsoft Fusion Network Services CLR Host for executing .Net assemblies")]
  20. [assembly:AssemblyProductAttribute("Microsoft Fusion Network Services")]
  21. [assembly:AssemblyInformationalVersionAttribute("1.0.0.0")]
  22. [assembly:AssemblyTrademarkAttribute("Microsoft� is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation")]
  23. [assembly:AssemblyCompanyAttribute("Microsoft Corporation")]
  24. [assembly:AssemblyCopyrightAttribute("Copyright � Microsoft Corp. 1999-2001. All rights reserved.")]
  25. //BUGBUG??
  26. [assembly:System.CLSCompliant(true)]
  27. //namespace Microsoft {
  28. namespace FusionCLRHost {
  29. using System;
  30. using System.Text;
  31. using System.Runtime.Remoting;
  32. using System.Globalization;
  33. using System.Security;
  34. using System.Security.Policy;
  35. using System.Security.Permissions;
  36. using System.Collections;
  37. using System.Runtime.InteropServices;
  38. // [GuidAttribute("E612D54D-B42A-32B5-B1D7-8490CE09705C")]
  39. public interface IAsmExecute
  40. {
  41. int Execute(string codebase, Int32 flags, Int32 evidenceZone, string evidenceSrcUrl, string stringArg);
  42. }
  43. [GuidAttribute("7EB9A84D-646E-3764-BBCA-3789CDB3447B")]
  44. public class AsmExecute : MarshalByRefObject, IAsmExecute
  45. {
  46. // this must be the same as defined in the caller...
  47. private static readonly int SECURITY_NONE = 0x00;
  48. private static readonly int SECURITY_ZONE = 0x01;
  49. private static readonly int SECURITY_SITE = 0x02;
  50. // Arguments: Codebase, flags, zone, srcurl
  51. // If the flags indicate zone then a zone must be provided.
  52. // If the flags indicate a site then a srcurl must be provided, codebase must be a filepath
  53. public int Execute(string codebase, Int32 flags, Int32 evidenceZone, string evidenceSrcUrl, string stringArg)
  54. {
  55. string file = codebase;
  56. if((file.Length == 0) || (file[0] == '\0'))
  57. throw new ArgumentException("Invalid codebase");
  58. Console.WriteLine("Codebase- {0}", file);
  59. // Find the appbase of the executable. For now we assume the
  60. // form to be http://blah/... with forward slashes. This
  61. // need to be update.
  62. // Note: aso works with '\' as in file paths
  63. string appbase = null;
  64. string ConfigurationFile = null;
  65. int k = file.LastIndexOf('/');
  66. if(k <= 0)
  67. {
  68. k = file.LastIndexOf('\\');
  69. if(k == 0)
  70. {
  71. appbase = file;
  72. ConfigurationFile = file;
  73. }
  74. }
  75. if(k != 0)
  76. {
  77. // if k is still < 0 at this point, appbase should be an empty string
  78. appbase = file.Substring(0,k+1);
  79. if(k+1 < file.Length)
  80. ConfigurationFile = file.Substring(k+1);
  81. }
  82. // Check 1: disallow non-fully qualified path/codebase
  83. if ((appbase.Length == 0) || (appbase[0] == '.'))
  84. throw new ArgumentException("Codebase must be fully qualified");
  85. // BUGBUG: should appbase be the source of the code, not local?
  86. Console.WriteLine("AppBase- {0}", appbase);
  87. // Build up the configuration File name
  88. if(ConfigurationFile != null)
  89. {
  90. StringBuilder bld = new StringBuilder();
  91. bld.Append(ConfigurationFile);
  92. bld.Append(".config");
  93. ConfigurationFile = bld.ToString();
  94. }
  95. Console.WriteLine("Config- {0}", ConfigurationFile);
  96. // Get the flags
  97. // 0x1 we have Zone
  98. // 0x2 we have a unique id.
  99. int dwFlag = flags;
  100. Evidence documentSecurity = null;
  101. // Check 2: disallow called with no evidence
  102. if (dwFlag == SECURITY_NONE)
  103. {
  104. // BUGBUG?: disallow executing with no evidence
  105. throw new ArgumentException("Flag set at no evidence");
  106. }
  107. if((dwFlag & SECURITY_SITE) != 0 ||
  108. (dwFlag & SECURITY_ZONE) != 0)
  109. documentSecurity = new Evidence();
  110. // BUGBUG: check other invalid cases for dwFlag
  111. if((dwFlag & SECURITY_ZONE) != 0)
  112. {
  113. int zone = evidenceZone;
  114. documentSecurity.AddHost( new Zone((System.Security.SecurityZone)zone) );
  115. Console.WriteLine("Evidence Zone- {0}", zone);
  116. }
  117. if((dwFlag & SECURITY_SITE) != 0)
  118. {
  119. if (file.Length<7||String.Compare(file.Substring(0,7),"file://",true)!=0)
  120. {
  121. documentSecurity.AddHost( System.Security.Policy.Site.CreateFromUrl(evidenceSrcUrl) );
  122. Console.WriteLine("Evidence SiteFromUrl- {0}", evidenceSrcUrl);
  123. // if srcUrl is given, assume file/appbase is a local file path
  124. StringBuilder bld = new StringBuilder();
  125. bld.Append("file://");
  126. bld.Append(appbase);
  127. documentSecurity.AddHost( new ApplicationDirectory(bld.ToString()) );
  128. Console.WriteLine("Evidence AppDir- {0}", bld);
  129. }
  130. // URLs may be matched exactly or by a wildcard in the final position,
  131. // for example: http://www.fourthcoffee.com/process/*
  132. StringBuilder bld2 = new StringBuilder();
  133. if (evidenceSrcUrl[evidenceSrcUrl.Length-1] == '/')
  134. bld2.Append(evidenceSrcUrl);
  135. else
  136. {
  137. int j = evidenceSrcUrl.LastIndexOf('/');
  138. if(j > 0)
  139. {
  140. if (j > 7) // evidenceSrcUrl == "http://a/file.exe"
  141. bld2.Append(evidenceSrcUrl.Substring(0,j+1));
  142. else
  143. {
  144. // evidenceSrcUrl == "http://foo.com" -> but why?
  145. bld2.Append(evidenceSrcUrl);
  146. bld2.Append('/');
  147. }
  148. }
  149. else
  150. throw new ArgumentException("Invalid Url format");
  151. }
  152. bld2.Append('*');
  153. documentSecurity.AddHost( new Url(bld2.ToString()) );
  154. Console.WriteLine("Evidence Url- {0}", bld2);
  155. }
  156. // other evidence: Hash, Publisher, StrongName
  157. // Set domain name to site name if possible
  158. string friendlyName = null;
  159. if((dwFlag & SECURITY_SITE) != 0)
  160. friendlyName = GetSiteName(evidenceSrcUrl);
  161. else
  162. friendlyName = GetSiteName(file);
  163. Console.WriteLine("AppDomain friendlyName- {0}", friendlyName);
  164. // set up arguments
  165. // only allow 1 for now
  166. string[] args;
  167. if (stringArg != null)
  168. {
  169. args = new string[1];
  170. args[0] = stringArg;
  171. }
  172. else
  173. args = new string[0];
  174. AppDomainSetup properties = new AppDomainSetup();
  175. properties.ApplicationBase = appbase;
  176. properties.PrivateBinPath = "bin";
  177. if(ConfigurationFile != null)
  178. properties.ConfigurationFile = ConfigurationFile;
  179. AppDomain proxy = AppDomain.CreateDomain(friendlyName, documentSecurity, properties);
  180. if(proxy != null)
  181. {
  182. AssemblyName asmname = Assembly.GetExecutingAssembly().GetName();
  183. Console.WriteLine("AsmExecute name- {0}", asmname);
  184. try
  185. {
  186. // Use remoting. Otherwise asm will be loaded both in current and the new AppDomain
  187. // ... as explained by URT dev
  188. // asmexec.dll must be found on path (CorPath?) or in the GAC for this to work.
  189. ObjectHandle handle = proxy.CreateInstance(asmname.FullName, "FusionCLRHost.AsmExecute");
  190. if (handle != null)
  191. {
  192. AsmExecute execproxy = (AsmExecute)handle.Unwrap();
  193. int retVal = -1;
  194. Console.WriteLine("\n========");
  195. if (execproxy != null)
  196. retVal = execproxy.ExecuteAsAssembly(file, documentSecurity, args);
  197. Console.WriteLine("\n========");
  198. return retVal;
  199. }
  200. }
  201. catch(Exception e)
  202. {
  203. Console.WriteLine("AsmExecute CreateInstance(AsmExecute) failed: {0}", e.Message);
  204. throw e;
  205. }
  206. }
  207. else
  208. Console.WriteLine("AsmExecute CreateDomain failed");
  209. // BUGBUG: throw Exception?
  210. return -1;
  211. }
  212. // This method must be internal, since it asserts the ControlEvidence permission.
  213. // private --> require ReflectionPermission not known how
  214. // solution: public but LinkDemand StrongNameIdentity of ours
  215. [ComVisible(false)]
  216. [StrongNameIdentityPermissionAttribute(SecurityAction.LinkDemand, PublicKey = "0x002400000480000094000000060200000024000052534131000400000100010013F3CD6C291DF1566D3C6E7269800C35D9212A622FA934492AD0833DAEA2574D12A9AA2A9392FF30A892ECD3F7F9B57211A541CC4712A184450992E143C1BDBC864E31826598B0D90BB2F04C5C50F004771370F9C76444696E8DC18999A3D8448D26EBF3A9E68796CA3A7D2ACC47B491455E462F4E6DDD9DF338171D911D88B2" )]
  217. public int ExecuteAsAssembly(string file, Evidence evidence, string[] args)
  218. {
  219. new PermissionSet(PermissionState.Unrestricted).Assert();
  220. return AppDomain.CurrentDomain.ExecuteAssembly(file, evidence, args);
  221. }
  222. private static string GetSiteName(string pURL)
  223. {
  224. // BUGBUG: this does not work w/ UNC or file:// (?)
  225. string siteName = null;
  226. if(pURL != null) {
  227. int j = pURL.IndexOf(':');
  228. // If there is a protocal remove it. In a URL of the form
  229. // yyyy://xxxx/zzzz where yyyy is the protocal, xxxx is
  230. // the site and zzzz is extra we want to get xxxx.
  231. if(j != -1 &&
  232. j+3 < pURL.Length &&
  233. pURL[j+1] == '/' &&
  234. pURL[j+2] == '/')
  235. {
  236. j+=3;
  237. // Remove characters after the
  238. // next /.
  239. int i = pURL.IndexOf('/',j);
  240. if(i > -1)
  241. siteName = pURL.Substring(j,i-j);
  242. else
  243. siteName = pURL.Substring(j);
  244. }
  245. if(siteName == null)
  246. siteName = pURL;
  247. }
  248. return siteName;
  249. }
  250. }
  251. }