예제 #1
0
        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);
        }
예제 #2
0
        public RuleEngineResult RunAllRules(string file, IReadOnlyList <ISignature> signatures, List <IRuleResultCollector> collectors, CheckConfiguration configuration)
        {
            var verbose           = configuration.Verbose;
            var suppressedRuleIDs = configuration.SuppressErrorIDs;
            var rules             = GetRules();
            var engineResult      = RuleEngineResult.AllPass;

            collectors.ForEach(c => c.BeginSet(file));
            foreach (var rule in rules)
            {
                RuleResult result;
                var        verboseWriter = verbose ? new MemorySignatureLogger() : SignatureLogger.Null;
                if (signatures.Count == 0)
                {
                    result = RuleResult.Fail;
                    verboseWriter.LogMessage("File is not Authenticode signed.");
                }
                else
                {
                    if (suppressedRuleIDs.Contains(rule.RuleId))
                    {
                        result = RuleResult.Skip;
                    }
                    else if (rule is IAuthenticodeFileRule)
                    {
                        result = ((IAuthenticodeFileRule)rule).Validate(file, verboseWriter, configuration);
                    }
                    else if (rule is IAuthenticodeSignatureRule)
                    {
                        result = ((IAuthenticodeSignatureRule)rule).Validate(signatures, verboseWriter, configuration);
                    }
                    else
                    {
                        throw new NotSupportedException("Rule type is not supported.");
                    }
                }
                if (result == RuleResult.Fail)
                {
                    engineResult = RuleEngineResult.NotAllPass;
                }
                collectors.ForEach(c => c.CollectResult(rule, result, verboseWriter.Messages));
            }
            if (configuration.ExtractPath != null)
            {
                Extraction.ExtractToDisk(file, configuration, signatures);
            }
            collectors.ForEach(c => c.CompleteSet());
            return(engineResult);
        }