public TestEngineResult RunAllTests(string file, IReadOnlyList <ICmsSignature> signatures, List <ITestResultCollector> collectors, CheckConfiguration configuration) { var verbose = configuration.Verbose; var suppressedTestIDs = configuration.SuppressErrorIDs; var tests = GetTests(); var engineResult = TestEngineResult.AllPass; collectors.ForEach(c => c.BeginSet(file)); Boolean dontInsertRulesTable = false; string portal = ""; var digestStr = ""; string appID = ""; string fileName = ""; string thumbprint = ""; foreach (var test in tests) { TestResult result; var verboseWriter = verbose ? new MemorySignatureLogger() : SignatureLogger.Null; if (signatures.Count == 0) { result = TestResult.Fail; verboseWriter.LogMessage("File is not Authenticode signed."); dontInsertRulesTable = true; } else { if (suppressedTestIDs.Contains(test.Test)) { result = TestResult.Skip; } else if ((test.TestSet & configuration.TestSet) == 0) { result = TestResult.Excluded; } else { switch (test) { case IAuthenticodeFileTest fileTest: result = fileTest.Validate(file, verboseWriter, configuration); break; case IAuthenticodeSignatureTest sigTest: result = sigTest.Validate(signatures, verboseWriter, configuration); break; default: throw new NotSupportedException("Test type is not supported."); } } } if (result == TestResult.Fail) { engineResult = TestEngineResult.NotAllPass; } if (!dontInsertRulesTable) { digestStr = HashHelpers.GetHashForSignature(signatures[0]);//message digest of siganture(signature->details->advance->msg digest) appID = Program.fileName; fileName = Program.fileName; portal = Program.portalName; thumbprint = signatures[0].Certificate.Thumbprint; } collectors.ForEach(c => c.CollectResult(test, result, verboseWriter.Messages, dontInsertRulesTable, appID, fileName, digestStr, thumbprint, portal)); } if (configuration.ExtractPath != null) { Extraction.ExtractToDisk(file, configuration, signatures); } collectors.ForEach(c => c.CompleteSet()); return(engineResult); }
static async Task Main(string[] args) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { Console.Error.WriteLine("AuthenticodeLint is only supported on Windows."); //return ExitCodes.PlatformNotSupported; } var cli = Environment.CommandLine; List <CommandLineParameter> parsedCommandLine; try { var commandLine = CommandLineParser.LexCommandLine(cli).Skip(1); parsedCommandLine = CommandLineParser.CreateCommandLineParametersWithValues(commandLine).ToList(); } catch (InvalidOperationException) { parsedCommandLine = null; } if (parsedCommandLine == null || parsedCommandLine.Count == 0 || parsedCommandLine.Any(cl => cl.Name == "help")) { ShowHelp(); //Avoid returning success for printing help so that automated build systems do not interpret "show the help" //As a successful build incase the build system is incorrectly passing arguments. //return ExitCodes.InvalidInputOrConfig; } var inputs = new List <string>(); var suppress = new HashSet <int>(); bool quiet = false; bool verbose = false; string report = null; string extract = null; var revocation = RevocationChecking.None; var testSet = TestSet.All; foreach (var parameter in parsedCommandLine) { if (parameter.Name == "vt") { vt = true; } else if (parameter.Name == "in") { if (string.IsNullOrWhiteSpace(parameter.Value)) { Console.Error.WriteLine("A value is required for input."); return;// ExitCodes.InvalidInputOrConfig; } var filePattern = Path.GetFileName(parameter.Value); //The value contains a pattern. if (filePattern.Contains("*") || filePattern.Contains("?")) { var directory = Path.GetDirectoryName(parameter.Value); if (Directory.Exists(directory)) { var files = Directory.GetFiles(directory, filePattern, SearchOption.TopDirectoryOnly); inputs.AddRange(files); } } else { inputs.Add(parameter.Value); } } else if (parameter.Name == "validate") { validate = parameter.Value; } else if (parameter.Name == "portal") { portalName = parameter.Value; } else if (parameter.Name == "app") { appName = parameter.Value; } else if (parameter.Name == "type") { fileType = parameter.Value; } else if (parameter.Name == "number") { fileNumber = Int32.Parse(parameter.Value); } else if (parameter.Name == "suppress") { if (string.IsNullOrWhiteSpace(parameter.Value)) { ShowInvalidSuppression(); return;// ExitCodes.InvalidInputOrConfig; } foreach (var idString in parameter.Value.Split(',').Select(p => p.Trim())) { int id; if (int.TryParse(idString, out id)) { suppress.Add(id); } else { Console.Error.WriteLine($"{idString} is not a valid error ID."); return;// ExitCodes.InvalidInputOrConfig; } } } else if (parameter.Name == "q" || parameter.Name == "quiet") { if (!string.IsNullOrWhiteSpace(parameter.Value)) { Console.Error.WriteLine($"-{parameter.Name} does not expect a value."); return;// ExitCodes.InvalidInputOrConfig; } quiet = true; } else if (parameter.Name == "verbose") { if (!string.IsNullOrWhiteSpace(parameter.Value)) { Console.Error.WriteLine($"-{parameter.Name} does not expect a value."); return;// ExitCodes.InvalidInputOrConfig; } verbose = true; } else if (parameter.Name == "report") { report = parameter.Value; } else if (parameter.Name == "extract") { extract = parameter.Value; } else if (parameter.Name == "revocation") { if (string.IsNullOrWhiteSpace(parameter.Value)) { Console.Error.WriteLine($"-{parameter.Name} requires a value if specified."); return;// ExitCodes.InvalidInputOrConfig; } if (!Enum.TryParse(parameter.Value, true, out revocation)) { Console.Error.WriteLine($"-{parameter.Value} is an unrecognized revocation mode."); return;// ExitCodes.InvalidInputOrConfig; } } else if (parameter.Name == "testset") { if (string.IsNullOrWhiteSpace(parameter.Value)) { Console.Error.WriteLine($"-{parameter.Name} requires a value if specified."); return;// ExitCodes.InvalidInputOrConfig; } if (!Enum.TryParse(parameter.Value, true, out testSet) || parameter.Value.Equals("all", StringComparison.OrdinalIgnoreCase)) { Console.Error.WriteLine($"-{parameter.Value} is an unrecognized testset."); return;// ExitCodes.InvalidInputOrConfig; } } else { Console.Error.WriteLine($"-{parameter.Name} is an unknown parameter."); return;// ExitCodes.InvalidInputOrConfig; } } if (inputs.Count == 0) { Console.Error.WriteLine("Input is expected. See -help for usage."); return;// ExitCodes.InvalidInputOrConfig; } var configuration = new CheckConfiguration(inputs, report, quiet, suppress, verbose, revocation, extract, testSet); if (!ConfigurationValidator.ValidateAndPrint(configuration, Console.Error)) { return;// ExitCodes.InvalidInputOrConfig; } var collectors = new List <ITestResultCollector>(); if (!quiet) { collectors.Add(new StdOutTestResultCollector()); } if (!string.IsNullOrWhiteSpace(report)) { collectors.Add(new XmlTestResultCollector(report)); } var result = ExitCodes.Success; foreach (var file in inputs) { filePath = Path.GetFullPath(file); if (!vt && validate.Equals("")) { var signatures = SignatureTreeInspector.Extract(file); var verboseWriter = verbose ? new MemorySignatureLogger() : SignatureLogger.Null; fileName = Path.GetFileName(file); if (signatures.Count == 0) { DBConnect.InsertApplicationTable(appName, fileName, portalName, 0, fileType, fileNumber); verboseWriter.LogMessage("File is not Authenticode signed."); } else { DBConnect.InsertApplicationTable(appName, fileName, portalName, 1, fileType, fileNumber); signed = true; } if (CheckEngine.Instance.RunAllTests(file, signatures, collectors, configuration) != TestEngineResult.AllPass) { result = ExitCodes.ChecksFailed; } } else { fileName = Path.GetFileName(file); filePath = Path.GetFullPath(file); if (vt) { await VTChecker.GetScanReportForFile(); } /* else if (validate.Equals("signature")) * Validation.validate(fileName, signatureIndex, thumbprint);*/ } } collectors.ForEach(c => c.Flush()); return;// result; }