231 lines
7.7 KiB
C#
231 lines
7.7 KiB
C#
/*=============================================================================
|
|
**
|
|
** Class: ASMExecute
|
|
**
|
|
** Purpose: Used to setup the correct hosting environment before executing an
|
|
** assembly
|
|
**
|
|
** Date: 2:24 PM 10/20/2000
|
|
**
|
|
** Copyright (c) Microsoft, 1999-2000
|
|
**
|
|
=============================================================================*/
|
|
namespace ComHost {
|
|
using System;
|
|
using System.Text;
|
|
using System.Reflection;
|
|
using System.Globalization;
|
|
using System.Runtime.Remoting;
|
|
using System.Security;
|
|
using System.Security.Policy;
|
|
using System.Security.Permissions;
|
|
//using IIEHost;
|
|
|
|
public class AsmExecute : MarshalByRefObject
|
|
{
|
|
public static readonly int SECURITY_NONE = 0x00;
|
|
public static readonly int SECURITY_ZONE = 0x01;
|
|
public static readonly int SECURITY_SITE = 0x02;
|
|
|
|
public void Execute(string codebase, string flags)
|
|
{
|
|
string[] args = {codebase, flags};
|
|
Process(args);
|
|
}
|
|
|
|
public void Execute(string codebase, string flags, string evidence)
|
|
{
|
|
string[] args = {codebase, flags, evidence};
|
|
Process(args);
|
|
}
|
|
|
|
public void Execute(string codebase, string flags, string evidence1, string evidence2, string evidence2url)
|
|
{
|
|
string[] args = {codebase, flags, evidence1, evidence2, evidence2url};
|
|
Process(args);
|
|
}
|
|
|
|
// Arguments: Codebase, flags, zone, uniqueid, siteurl
|
|
// If the flags indicate zone then a zone must be provided.
|
|
// If the flags indicate a site then a uniqueid must be provided
|
|
//static void Main(string[] args)
|
|
private void Process(string[] args)
|
|
{
|
|
if(args == null || args.Length < 2)
|
|
throw new ArgumentException();
|
|
|
|
int index = 0;
|
|
string file = args[index++];
|
|
if(file == null)
|
|
throw new ArgumentException();
|
|
|
|
// Find the URL of the executable. For now we assume the
|
|
// form to be http://blah/... with forward slashes. This
|
|
// need to be update.
|
|
// Note: aso works w/ '\' as in file paths
|
|
string URL = null;
|
|
string Configuration = null;
|
|
int k = file.LastIndexOf('/');
|
|
if(k <= 0)
|
|
{
|
|
k = file.LastIndexOf('\\');
|
|
if(k == 0)
|
|
{
|
|
URL = file;
|
|
Configuration = file;
|
|
}
|
|
}
|
|
|
|
if(k != 0)
|
|
{
|
|
// if k is still < 0 at this point, URL should be an empty string
|
|
// BUGBUG: should URL be null instead??
|
|
URL = file.Substring(0,k+1);
|
|
if(k+1 < file.Length)
|
|
Configuration = file.Substring(k+1);
|
|
}
|
|
|
|
// BUGBUG: should URL be the source of the code, not local?
|
|
Console.WriteLine("URL- {0}", URL);
|
|
|
|
// Build up the configuration File name
|
|
if(Configuration != null)
|
|
|
|
{
|
|
k = Configuration.LastIndexOf('.');
|
|
StringBuilder bld = new StringBuilder();
|
|
if(k > 0)
|
|
{
|
|
bld.Append(Configuration.Substring(0,k));
|
|
bld.Append(".cfg");
|
|
}
|
|
else
|
|
{
|
|
bld.Append(Configuration);
|
|
bld.Append(".cfg");
|
|
}
|
|
Configuration = bld.ToString();
|
|
}
|
|
|
|
Console.WriteLine("Config- {0}", Configuration);
|
|
|
|
// Get the flags
|
|
// 0x1 we have Zone
|
|
// 0x2 we have a unique id.
|
|
int dwFlag = Int32.Parse(args[index++], NumberStyles.HexNumber);//CultureInfo.InvariantCulture);
|
|
|
|
string friendlyName = GetSiteName(file);
|
|
Console.WriteLine("SiteName- {0}", friendlyName);
|
|
Evidence documentSecurity = null;
|
|
int size = 0;
|
|
if((dwFlag & SECURITY_ZONE) != 0)
|
|
size++;
|
|
if((dwFlag & SECURITY_SITE) != 0)
|
|
size++;
|
|
|
|
if(size != 0)
|
|
documentSecurity = new Evidence();
|
|
|
|
if((dwFlag & SECURITY_ZONE) != 0)
|
|
{
|
|
if(index == args.Length)
|
|
throw new ArgumentException();
|
|
int zone = Int32.Parse(args[index++], NumberStyles.HexNumber);//, CultureInfo.InvariantCulture);
|
|
documentSecurity.AddHost( new Zone((System.Security.SecurityZone)zone) );
|
|
}
|
|
if((dwFlag & SECURITY_SITE) != 0)
|
|
{
|
|
if(index == args.Length-1)
|
|
throw new ArgumentException();
|
|
byte[] uniqueId = DecodeDomainId(args[index++]);
|
|
documentSecurity.AddHost( new Site(uniqueId, args[index]) );//file) ); uses the url instead
|
|
}
|
|
|
|
AppDomain adProxy = AppDomain.CreateDomain(friendlyName, documentSecurity, null);
|
|
|
|
// if(adProxy != null)
|
|
// {
|
|
adProxy.SetData(AppDomainFlags.ApplicationBase, URL);
|
|
adProxy.SetData(AppDomainFlags.PrivateBinPath, "bin");
|
|
if(Configuration != null)
|
|
{
|
|
adProxy.SetData(AppDomainFlags.Configuration, Configuration);
|
|
}
|
|
|
|
string asmname = Assembly.GetExecutingAssembly().Location;
|
|
Console.WriteLine("AsmName- {0}", asmname);
|
|
Console.WriteLine("\n========");
|
|
|
|
// Use remoting. Otherwise asm will be loaded both in current and the new AppDomain
|
|
// ... as explained by URT ppl
|
|
// asmexec.dll must be found on path (CorPath?) for this to work.
|
|
ObjectHandle handle = adProxy.CreateInstanceFrom(asmname, "ComHost.AsmExecute");
|
|
if (handle != null)
|
|
{
|
|
AsmExecute execproxy = (AsmExecute)handle.Unwrap();
|
|
if (execproxy != null)
|
|
execproxy.RunExecute(file, documentSecurity);
|
|
}
|
|
|
|
Console.WriteLine("\n========");
|
|
}
|
|
|
|
private void RunExecute(string file, Evidence evidence)
|
|
{
|
|
new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Assert();
|
|
AppDomain.CurrentDomain.ExecuteAssembly(file, evidence);
|
|
}
|
|
|
|
private static int ConvertHexDigit(char val)
|
|
{
|
|
if (val <= '9') return (val - '0');
|
|
return ((val - 'A') + 10);
|
|
}
|
|
|
|
public static byte[] DecodeDomainId(string hexString)
|
|
{
|
|
byte[] sArray = new byte[(hexString.Length / 2)];
|
|
int digit;
|
|
int rawdigit;
|
|
for (int i = 0, j = 0; i < hexString.Length; i += 2, j++) {
|
|
digit = ConvertHexDigit(hexString[i]);
|
|
rawdigit = ConvertHexDigit(hexString[i+1]);
|
|
sArray[j] = (byte) (digit | (rawdigit << 4));
|
|
}
|
|
return(sArray);
|
|
}
|
|
|
|
public 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;
|
|
}
|
|
}
|
|
}
|