Exemple #1
0
        // 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);
        }
        // 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 securityEvidence = 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)
            {
                securityEvidence = new Evidence();
            }

            // BUGBUG: check other invalid cases for dwFlag

            string appURLbase = null;

            if ((dwFlag & SECURITY_ZONE) != 0)
            {
                int zone = evidenceZone;
                securityEvidence.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)
                {
                    securityEvidence.AddHost(System.Security.Policy.Site.CreateFromUrl(evidenceSrcUrl));

                    Console.WriteLine("Evidence SiteFromUrl- {0}", evidenceSrcUrl);

                    // BUGBUG: possible security hole? - if this intersects with Url/Zone _may_ resolve to a less restrictive policy...
                    // if srcUrl is given, assume file/appbase is a local file path
                    StringBuilder bld = new StringBuilder();
                    bld.Append("file://");
                    bld.Append(appbase);
                    securityEvidence.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");
                    }
                }

                appURLbase = bld2.ToString();

                bld2.Append('*');

                securityEvidence.AddHost(new Url(bld2.ToString()));

                Console.WriteLine("Evidence Url- {0}", bld2);
            }

            // other evidence: Hash, Publisher, StrongName

            // NOTENOTE: not effective if not both url and zone in evidence

            // Populate the PolicyLevel with code groups that will do the following:
            // 1) For all assemblies that come from this app's cache directory,
            //    give permissions from retrieved permission set from SecurityManager.
            // 2) For all other assemblies, give FullTrust permission set.  Remember,
            //    since the permissions will be intersected with other policy levels,
            //    just because we grant full trust to all other assemblies does not mean
            //    those assemblies will end up with full trust.

            // Create a new System.Security.Policy.PolicyStatement that does not contain any permissions.
            PolicyStatement Nada = new PolicyStatement(new PermissionSet(PermissionState.None));//PermissionSet());

            // Create a System.Security.Policy.FirstMatchCodeGroup as the root that matches all
            // assemblies by supplying an AllMembershipCondition:
            FirstMatchCodeGroup RootCG = new FirstMatchCodeGroup(new AllMembershipCondition(), Nada);

            // ResolvePolicy will return a System.Security.PermissionSet
            PermissionSet AppPerms = SecurityManager.ResolvePolicy(securityEvidence);

            // Create another PolicyStatement for the permissions that we want to grant to code from the app directory:
            PolicyStatement AppStatement = new PolicyStatement(AppPerms);

            // Create a child UnionCodeGroup to handle the assemblies from the app cache.  We do this
            // by using a UrlMembershipCondition set to the app cache directory:
            UnionCodeGroup AppCG = new UnionCodeGroup(new UrlMembershipCondition("file://" + appbase + "*"), AppStatement);

            // Add AppCG to RootCG as first child.  This is important because we need it to be evaluated first
//	     if ((dwFlag & TYPE_AVALON) == 0)
            RootCG.AddChild(AppCG);

            // Create another PolicyStatement so all other code gets full trust, by passing in an _unrestricted_ PermissionSet
            PolicyStatement FullTrustStatement = new PolicyStatement(new PermissionSet(PermissionState.Unrestricted));

            // Create a second child UnionCodeGroup to handle all other code, by using the AllMembershipCondition again
            UnionCodeGroup AllCG = new UnionCodeGroup(new AllMembershipCondition(), FullTrustStatement);

            // Add AllCG to RootCG after AppCG.  If AppCG doesnt apply to the assembly, AllCG will.
            RootCG.AddChild(AllCG);

            // This will be the PolicyLevel that we will associate with the new AppDomain.
            PolicyLevel AppPolicy = PolicyLevel.CreateAppDomainLevel();

            // Set the RootCG as the root code group on the new policy level
            AppPolicy.RootCodeGroup = RootCG;

            // NOTENOTE
            // Code from the site that lives on the local machine will get the reduced permissions as expected.
            // Dependencies of this app (not under app dir or maybe dependencies that live in the GAC) would still get full trust.
            // If the full trust dependencies need to do something trusted, they carry the burden of asserting to overcome the stack walk.

            // 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.DisallowPublisherPolicy=true;  // not allowed to set safe mode
            properties.ApplicationBase = appbase;   // BUGBUG: security? see note on ApplicationDirectory above
            properties.PrivateBinPath  = "bin";
            if (ConfigurationFile != null)
            {
                properties.ConfigurationFile = ConfigurationFile;   // should not set config file if it doesnot exist?
            }
            AppDomain proxy = AppDomain.CreateDomain(friendlyName, null, properties);

            if (proxy != null)
            {
                // set the AppPolicy policy level as the policy level for the AppDomain
                proxy.SetAppDomainPolicy(AppPolicy);

                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;

                        if (execproxy != null)
                        {
                            // prepare for on-demand/asm resolution
                            execproxy.InitOnDemand(appbase, appURLbase);
                        }

                        Console.WriteLine("\n========");

                        if (execproxy != null)
                        {
                            if ((dwFlag & TYPE_AVALON) != 0)
                            {
                                retVal = execproxy.ExecuteAsAvalon(file, securityEvidence, args);
                            }
                            else
                            {
                                retVal = execproxy.ExecuteAsAssembly(file, securityEvidence, args);
                            }
                        }

                        Console.WriteLine("\n========");

                        return(retVal);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("AsmExecute CreateInstance(AsmExecute) / execute assembly failed:\n{0}: {1}", e.GetType(), e.Message);
                    throw e;
                }
            }
            else
            {
                Console.WriteLine("AsmExecute CreateDomain failed");
            }

            // BUGBUG: throw Exception?
            return(-1);
        }