コード例 #1
0
 /// <summary>
 /// Excised section from TestPluginCompliance. Tests the specified AssemblyDefinition against all chosen security tests.
 /// </summary>
 /// <param name="testConfig">Mirror.</param>
 /// <param name="asmDef">Mirror.</param>
 /// <param name="singleResult">Mirror.</param>
 private static void RunCecilTests(SecurityLevelComplianceTestConfiguration testConfig, AssemblyDefinition asmDef, SecurityLevelComplianceSingleTestResult singleResult)
 {
     // Run the tests
     if (testConfig.RunLevel1Test)
     {
         SecurityComplianceSingleCecilTestResult level1TestResults = SecurityComplianceCecilTests.TestLevel1(asmDef);
         singleResult.TestedLevel1 = true;
         singleResult.PassLevel1   = level1TestResults.Passed;
         singleResult.MessagesLevel1.AddRange(level1TestResults.Messages);
     }
     if (testConfig.RunLevel2Test)
     {
         SecurityComplianceSingleCecilTestResult level2TestResults = SecurityComplianceCecilTests.TestLevel2(asmDef);
         singleResult.TestedLevel2 = true;
         singleResult.PassLevel2   = level2TestResults.Passed;
         singleResult.MessagesLevel2.AddRange(level2TestResults.Messages);
     }
     if (testConfig.RunLevel3Test)
     {
         SecurityComplianceSingleCecilTestResult level3TestResults = SecurityComplianceCecilTests.TestLevel3(asmDef);
         singleResult.TestedLevel3 = true;
         singleResult.PassLevel3   = level3TestResults.Passed;
         singleResult.MessagesLevel3.AddRange(level3TestResults.Messages);
     }
     if (testConfig.RunLevel4Test)
     {
         SecurityComplianceSingleCecilTestResult level4TestResults = SecurityComplianceCecilTests.TestLevel4(asmDef);
         singleResult.TestedLevel4 = true;
         singleResult.PassLevel4   = level4TestResults.Passed;
         singleResult.MessagesLevel4.AddRange(level4TestResults.Messages);
     }
 }
コード例 #2
0
        /// <summary>
        /// Tests PluginFile(s) against all security levels so as to determine the maximum security level that will allow a plugin to function.
        /// </summary>
        /// <param name="testConfig">The parameters to be used in this security level compliance test.</param>
        /// <returns>A SecurityLevelComplianceTestResult object containing the test results.</returns>
        public static SecurityLevelComplianceTestsResults TestPluginCompliance(SecurityLevelComplianceTestConfiguration testConfig)
        {
            SecurityLevelComplianceTestsResults allResults = new SecurityLevelComplianceTestsResults();

            bool firstCompile = true;

            foreach (PluginFile pluginFile in testConfig.PluginFilesToTest)
            {
                SecurityLevelComplianceSingleTestResult singleResult = new SecurityLevelComplianceSingleTestResult(pluginFile);
                allResults.IndividualResults[pluginFile] = singleResult;

                try
                {
                    byte[] asmBytesToTest = null;

                    // If source file, compile it
                    HPluginCompilationResult compileResult = null;
                    if (pluginFile.FileType == PluginFileType.CSSourceFile)
                    {
                        HPluginCompilationConfiguration compileConfig = new HPluginCompilationConfiguration();
                        compileConfig.SingleAssemblyOutput = true;
                        compileConfig.SourceFiles.Add(pluginFile.PathToFile);
                        compileConfig.UserFilesRootDirectory            = testConfig.UserFilesRootDirectory;
                        compileConfig.SingleAssemblyOutput              = true;
                        compileConfig.DeleteOutputFilesFromDiskWhenDone = false; // Keep the output files so we can load the PDBs for the cecil-based security tests
                        compileConfig.ReferencesOnDisk.Add(testConfig.TerrariaPath);
                        compileConfig.ReferencesInMemory.AddRange(testConfig.TerrariaDependencyAssemblies);
                        if (firstCompile && testConfig.PluginFilesToTest.Count > 1) // Write the Terraria dependencies to disk on the first compile...
                        {
                            compileConfig.ClearTemporaryFilesWhenDone = false;
                            compileConfig.ReuseTemporaryFiles         = false;
                        }
                        else // ...and reuse them on subsequent compiles. They will be finally deleted with HPluginAssemblyCompiler.ClearTemporaryCompileFiles() at the end of these tests.
                        {
                            compileConfig.ClearTemporaryFilesWhenDone = false;
                            compileConfig.ReuseTemporaryFiles         = true;
                        }
                        compileResult = HPluginAssemblyCompiler.Compile(compileConfig);
                        if (compileResult.CompiledAssemblies.Count == 0)
                        {
                            // Clean up
                            HPluginAssemblyCompiler.ClearTemporaryCompileFiles();
                            HPluginAssemblyCompiler.TryRemoveDirectory(compileResult.OutputDirectory);

                            // Note down the compile failure
                            singleResult.CompileFailure = true;
                            if (compileResult.CompileErrors.Count > 0)
                            {
                                singleResult.GenericMessages.Add("Failed to compile source CS files. Error details are as follows.");
                                foreach (CompilerError error in compileResult.CompileErrors)
                                {
                                    singleResult.GenericMessages.Add(error.ToString());
                                }
                            }
                            else
                            {
                                singleResult.GenericMessages.Add("Generic failure while compiling source CS files. No error details are available.");
                            }
                            allResults.AnyCompileFailure = true;
                        }
                        else
                        {
                            // Turn the Assembly into a byte array
                            Assembly asmToTest = compileResult.CompiledAssemblies[0];
                            asmBytesToTest = asmToTest.ToByteArray();
                        }
                    }
                    // If already a compiled assembly, load its bytes
                    else if (pluginFile.FileType == PluginFileType.CompiledAssemblyFile)
                    {
                        if (File.Exists(pluginFile.PathToFile))
                        {
                            try { asmBytesToTest = File.ReadAllBytes(pluginFile.PathToFile); }
                            catch (Exception e)
                            {
                                singleResult.GenericTestFailure = true;
                                singleResult.GenericMessages.Add("Could not load assembly \"" + pluginFile.PathToFile + "\" from disk. Details: " + e);
                            }
                        }
                    }

                    if (asmBytesToTest == null) // Can't test assemblies that failed to load
                    {
                        continue;
                    }

                    ///// Check security compliance with Cecil
                    using (MemoryStream memStream = new MemoryStream(asmBytesToTest))
                    {
                        // Try to load the compiled assembly's associated pdb file (if one exists)
                        string pdbPath = null;
                        if (pluginFile.FileType == PluginFileType.CSSourceFile)
                        {
                            // Since we used SingleAssemblyOutput and we're only testing one plugin at a time, there should be only one pdb file in the compiler's output.
                            pdbPath = compileResult.OutputFilesOnDisk.Where(x => Path.GetExtension(x) == ".pdb").FirstOrDefault();
                        }
                        else if (pluginFile.FileType == PluginFileType.CompiledAssemblyFile)
                        {
                            string dllPath      = pluginFile.PathToFile;
                            string checkPdbPath = "";
                            int    spot         = dllPath.LastIndexOf(".dll");
                            if (spot > -1)
                            {
                                checkPdbPath = dllPath.Substring(0, spot) + ".pdb";
                            }
                            if (File.Exists(checkPdbPath))
                            {
                                pdbPath = checkPdbPath;
                            }
                        }

                        AssemblyDefinition asmDef = null;
                        if (pdbPath != null)
                        {
                            // Run tests with the pdb to get helpful info like line numbers
                            using (FileStream pdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
                            {
                                ReaderParameters readerParameters = new ReaderParameters();
                                readerParameters.ReadSymbols  = true;
                                readerParameters.SymbolStream = pdbStream;
                                asmDef = AssemblyDefinition.ReadAssembly(memStream, readerParameters);

                                RunCecilTests(testConfig, asmDef, singleResult);
                            }
                        }
                        else
                        {
                            // Run tests without a pdb and just have generic error messages
                            asmDef = AssemblyDefinition.ReadAssembly(memStream);

                            RunCecilTests(testConfig, asmDef, singleResult);
                        }

                        // Make an aggregated generic messag for the user
                        string overallResult = "Final security level test results >> ";
                        overallResult += "Level 1: " + (singleResult.TestedLevel1 ? (singleResult.PassLevel1 ? "Compliant" : "Violated") : "Untested");
                        overallResult += "; Level 2: " + (singleResult.TestedLevel2 ? (singleResult.PassLevel2 ? "Compliant" : "Violated") : "Untested");
                        overallResult += "; Level 3: " + (singleResult.TestedLevel3 ? (singleResult.PassLevel3 ? "Compliant" : "Violated") : "Untested");
                        overallResult += "; Level 4: " + (singleResult.TestedLevel4 ? (singleResult.PassLevel4 ? "Compliant" : "Violated") : "Untested");
                        overallResult += ".";
                        singleResult.GenericMessages.Add(overallResult);

                        // All done
                    }

                    // Clear the on-disk output files that were generated during the assembly compile
                    if (compileResult != null && Directory.Exists(compileResult.OutputDirectory))
                    {
                        DirectoryInfo topDirInfo = new DirectoryInfo(compileResult.OutputDirectory);
                        topDirInfo.Delete(true);
                    }
                }
                catch (Exception e)
                {
                    singleResult.GenericTestFailure = true;
                    singleResult.GenericMessages.Add("Unexpected error during security level testing: " + e.ToString());
                }

                firstCompile = false;
            }

            // Delete the temporary disk copies of the Terraria dependencies
            HPluginAssemblyCompiler.ClearTemporaryCompileFiles();

            return(allResults);
        }