public static void ShouldExtractSignatureDetails() { var extract = SignatureTreeInspector.Extract(_path); var root = Assert.Single(extract); Assert.NotNull(root); Assert.Equal(SignatureKind.Signature, root.Kind); Assert.Equal(HashAlgorithmName.SHA256, root.DigestAlgorithmName); Assert.Equal("CN=Kevin Jones, O=Kevin Jones, L=Alexandria, S=VA, C=US", root.Certificate.Subject); Assert.Equal("1.2.840.113549.1.1.1", root.HashEncryptionAlgorithm.Value); //pkcs-1 rsaEncryption var timestamp = Assert.Single(root.VisitAll(SignatureKind.Rfc3161Timestamp, false)); Assert.NotNull(timestamp); Assert.Equal(SignatureKind.Rfc3161Timestamp, timestamp.Kind); Assert.Equal(HashAlgorithmName.SHA256, timestamp.DigestAlgorithmName); Assert.Equal("CN=DigiCert SHA2 Timestamp Responder, O=DigiCert, C=US", timestamp.Certificate.Subject); Assert.Equal("1.2.840.113549.1.1.1", timestamp.HashEncryptionAlgorithm.Value); //pkcs-1 rsaEncryption }
static int 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 ruleSet = RuleSet.Modern; foreach (var parameter in parsedCommandLine) { 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 == "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 == "ruleset") { 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 ruleSet) || parameter.Value.Equals("all", StringComparison.OrdinalIgnoreCase)) { Console.Error.WriteLine($"-{parameter.Value} is an unrecognized ruleset."); 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, ruleSet); if (!ConfigurationValidator.ValidateAndPrint(configuration, Console.Error)) { return(ExitCodes.InvalidInputOrConfig); } var collectors = new List <IRuleResultCollector>(); if (!quiet) { collectors.Add(new StdOutRuleResultCollector()); } if (!string.IsNullOrWhiteSpace(report)) { collectors.Add(new XmlRuleResultCollector(report)); } var result = ExitCodes.Success; foreach (var file in inputs) { var signatures = SignatureTreeInspector.Extract(file); if (CheckEngine.Instance.RunAllRules(file, signatures, collectors, configuration) != RuleEngineResult.AllPass) { result = ExitCodes.ChecksFailed; } } collectors.ForEach(c => c.Flush()); return(result); }
private static IReadOnlyList <ICmsSignature> GetGraphForFile(string file) { return(SignatureTreeInspector.Extract(file)); }
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; }