windows-nt/Source/XPSP1/NT/base/win32/fusion/installer/clrhost/asmexec.cs

300 lines
12 KiB
C#
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*=============================================================================
**
** Class: AsmExecute
**
** Purpose: Used to setup the correct hosting environment before executing an assembly
**
** Date: 10/20/2000
** 5/10/2001 Rev for CLR Beta2
**
** Copyright (c) Microsoft, 1999-2001
**
=============================================================================*/
using System.Reflection;
using System.Configuration.Assemblies;
[assembly:AssemblyCultureAttribute("")]
[assembly:AssemblyVersionAttribute("1.0.128.0")]
[assembly:AssemblyKeyFileAttribute(/*"..\..\*/"asmexecKey.snk")]
[assembly:AssemblyTitleAttribute("Microsoft Fusion .Net Assembly Execute Host")]
[assembly:AssemblyDescriptionAttribute("Microsoft Fusion Network Services CLR Host for executing .Net assemblies")]
[assembly:AssemblyProductAttribute("Microsoft Fusion Network Services")]
[assembly:AssemblyInformationalVersionAttribute("1.0.0.0")]
[assembly:AssemblyTrademarkAttribute("Microsoft<66> is a registered trademark of Microsoft Corporation. Windows(TM) is a trademark of Microsoft Corporation")]
[assembly:AssemblyCompanyAttribute("Microsoft Corporation")]
[assembly:AssemblyCopyrightAttribute("Copyright <20> Microsoft Corp. 1999-2001. All rights reserved.")]
//BUGBUG??
[assembly:System.CLSCompliant(true)]
//namespace Microsoft {
namespace FusionCLRHost {
using System;
using System.Text;
using System.Runtime.Remoting;
using System.Globalization;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Collections;
using System.Runtime.InteropServices;
// [GuidAttribute("E612D54D-B42A-32B5-B1D7-8490CE09705C")]
public interface IAsmExecute
{
int Execute(string codebase, Int32 flags, Int32 evidenceZone, string evidenceSrcUrl, string stringArg);
}
[GuidAttribute("7EB9A84D-646E-3764-BBCA-3789CDB3447B")]
public class AsmExecute : MarshalByRefObject, IAsmExecute
{
// this must be the same as defined in the caller...
private static readonly int SECURITY_NONE = 0x00;
private static readonly int SECURITY_ZONE = 0x01;
private static readonly int SECURITY_SITE = 0x02;
// Arguments: Codebase, flags, zone, srcurl
// If the flags indicate zone then a zone must be provided.
// If the flags indicate a site then a srcurl must be provided, codebase must be a filepath
public int Execute(string codebase, Int32 flags, Int32 evidenceZone, string evidenceSrcUrl, string stringArg)
{
string file = codebase;
if((file.Length == 0) || (file[0] == '\0'))
throw new ArgumentException("Invalid codebase");
Console.WriteLine("Codebase- {0}", file);
// Find the appbase of the executable. For now we assume the
// form to be http://blah/... with forward slashes. This
// need to be update.
// Note: aso works with '\' as in file paths
string appbase = null;
string ConfigurationFile = null;
int k = file.LastIndexOf('/');
if(k <= 0)
{
k = file.LastIndexOf('\\');
if(k == 0)
{
appbase = file;
ConfigurationFile = file;
}
}
if(k != 0)
{
// if k is still < 0 at this point, appbase should be an empty string
appbase = file.Substring(0,k+1);
if(k+1 < file.Length)
ConfigurationFile = file.Substring(k+1);
}
// Check 1: disallow non-fully qualified path/codebase
if ((appbase.Length == 0) || (appbase[0] == '.'))
throw new ArgumentException("Codebase must be fully qualified");
// BUGBUG: should appbase be the source of the code, not local?
Console.WriteLine("AppBase- {0}", appbase);
// Build up the configuration File name
if(ConfigurationFile != null)
{
StringBuilder bld = new StringBuilder();
bld.Append(ConfigurationFile);
bld.Append(".config");
ConfigurationFile = bld.ToString();
}
Console.WriteLine("Config- {0}", ConfigurationFile);
// Get the flags
// 0x1 we have Zone
// 0x2 we have a unique id.
int dwFlag = flags;
Evidence documentSecurity = null;
// Check 2: disallow called with no evidence
if (dwFlag == SECURITY_NONE)
{
// BUGBUG?: disallow executing with no evidence
throw new ArgumentException("Flag set at no evidence");
}
if((dwFlag & SECURITY_SITE) != 0 ||
(dwFlag & SECURITY_ZONE) != 0)
documentSecurity = new Evidence();
// BUGBUG: check other invalid cases for dwFlag
if((dwFlag & SECURITY_ZONE) != 0)
{
int zone = evidenceZone;
documentSecurity.AddHost( new Zone((System.Security.SecurityZone)zone) );
Console.WriteLine("Evidence Zone- {0}", zone);
}
if((dwFlag & SECURITY_SITE) != 0)
{
if (file.Length<7||String.Compare(file.Substring(0,7),"file://",true)!=0)
{
documentSecurity.AddHost( System.Security.Policy.Site.CreateFromUrl(evidenceSrcUrl) );
Console.WriteLine("Evidence SiteFromUrl- {0}", evidenceSrcUrl);
// if srcUrl is given, assume file/appbase is a local file path
StringBuilder bld = new StringBuilder();
bld.Append("file://");
bld.Append(appbase);
documentSecurity.AddHost( new ApplicationDirectory(bld.ToString()) );
Console.WriteLine("Evidence AppDir- {0}", bld);
}
// URLs may be matched exactly or by a wildcard in the final position,
// for example: http://www.fourthcoffee.com/process/*
StringBuilder bld2 = new StringBuilder();
if (evidenceSrcUrl[evidenceSrcUrl.Length-1] == '/')
bld2.Append(evidenceSrcUrl);
else
{
int j = evidenceSrcUrl.LastIndexOf('/');
if(j > 0)
{
if (j > 7) // evidenceSrcUrl == "http://a/file.exe"
bld2.Append(evidenceSrcUrl.Substring(0,j+1));
else
{
// evidenceSrcUrl == "http://foo.com" -> but why?
bld2.Append(evidenceSrcUrl);
bld2.Append('/');
}
}
else
throw new ArgumentException("Invalid Url format");
}
bld2.Append('*');
documentSecurity.AddHost( new Url(bld2.ToString()) );
Console.WriteLine("Evidence Url- {0}", bld2);
}
// other evidence: Hash, Publisher, StrongName
// Set domain name to site name if possible
string friendlyName = null;
if((dwFlag & SECURITY_SITE) != 0)
friendlyName = GetSiteName(evidenceSrcUrl);
else
friendlyName = GetSiteName(file);
Console.WriteLine("AppDomain friendlyName- {0}", friendlyName);
// set up arguments
// only allow 1 for now
string[] args;
if (stringArg != null)
{
args = new string[1];
args[0] = stringArg;
}
else
args = new string[0];
AppDomainSetup properties = new AppDomainSetup();
properties.ApplicationBase = appbase;
properties.PrivateBinPath = "bin";
if(ConfigurationFile != null)
properties.ConfigurationFile = ConfigurationFile;
AppDomain proxy = AppDomain.CreateDomain(friendlyName, documentSecurity, properties);
if(proxy != null)
{
AssemblyName asmname = Assembly.GetExecutingAssembly().GetName();
Console.WriteLine("AsmExecute name- {0}", asmname);
try
{
// Use remoting. Otherwise asm will be loaded both in current and the new AppDomain
// ... as explained by URT dev
// asmexec.dll must be found on path (CorPath?) or in the GAC for this to work.
ObjectHandle handle = proxy.CreateInstance(asmname.FullName, "FusionCLRHost.AsmExecute");
if (handle != null)
{
AsmExecute execproxy = (AsmExecute)handle.Unwrap();
int retVal = -1;
Console.WriteLine("\n========");
if (execproxy != null)
retVal = execproxy.ExecuteAsAssembly(file, documentSecurity, args);
Console.WriteLine("\n========");
return retVal;
}
}
catch(Exception e)
{
Console.WriteLine("AsmExecute CreateInstance(AsmExecute) failed: {0}", e.Message);
throw e;
}
}
else
Console.WriteLine("AsmExecute CreateDomain failed");
// BUGBUG: throw Exception?
return -1;
}
// This method must be internal, since it asserts the ControlEvidence permission.
// private --> require ReflectionPermission not known how
// solution: public but LinkDemand StrongNameIdentity of ours
[ComVisible(false)]
[StrongNameIdentityPermissionAttribute(SecurityAction.LinkDemand, PublicKey = "0x002400000480000094000000060200000024000052534131000400000100010013F3CD6C291DF1566D3C6E7269800C35D9212A622FA934492AD0833DAEA2574D12A9AA2A9392FF30A892ECD3F7F9B57211A541CC4712A184450992E143C1BDBC864E31826598B0D90BB2F04C5C50F004771370F9C76444696E8DC18999A3D8448D26EBF3A9E68796CA3A7D2ACC47B491455E462F4E6DDD9DF338171D911D88B2" )]
public int ExecuteAsAssembly(string file, Evidence evidence, string[] args)
{
new PermissionSet(PermissionState.Unrestricted).Assert();
return AppDomain.CurrentDomain.ExecuteAssembly(file, evidence, args);
}
private static string GetSiteName(string pURL)
{
// BUGBUG: this does not work w/ UNC or file:// (?)
string siteName = null;
if(pURL != null) {
int j = pURL.IndexOf(':');
// If there is a protocal remove it. In a URL of the form
// yyyy://xxxx/zzzz where yyyy is the protocal, xxxx is
// the site and zzzz is extra we want to get xxxx.
if(j != -1 &&
j+3 < pURL.Length &&
pURL[j+1] == '/' &&
pURL[j+2] == '/')
{
j+=3;
// Remove characters after the
// next /.
int i = pURL.IndexOf('/',j);
if(i > -1)
siteName = pURL.Substring(j,i-j);
else
siteName = pURL.Substring(j);
}
if(siteName == null)
siteName = pURL;
}
return siteName;
}
}
}