Exemple #1
0
        static int VerifySignatures(
            Dictionary <string, FileMapTarget> fileMap,
            ExclusionSet exclusions,
            string exclusionsBootstrapReason)
        {
            int totalUnsigned = 0;
            int i             = 0;

            foreach (var entry in fileMap)
            {
                var extension = Path.GetExtension(entry.Value.SourcePath).ToLowerInvariant();

                VerifyResult result;
                if (exclusions.Contains(entry.Value.InstallPath))
                {
                    result = VerifyResult.Excluded;
                }
                else if (extensionsToCheck.Contains(extension))
                {
                    result = WinTrust.VerifyAuthenticodeTrust(
                        entry.Value.SourcePath) == SignatureVerificationResult.Valid
                        ? VerifyResult.Signed
                        : VerifyResult.Unsigned;
                }
                else
                {
                    result = VerifyResult.Skipped;
                }

                var level = LogEventLevel.Verbose;

                switch (result)
                {
                case VerifyResult.Unsigned:
                    if (exclusionsBootstrapReason != null)
                    {
                        exclusions.Bootstrap(entry.Value.InstallPath, exclusionsBootstrapReason);
                    }
                    level = LogEventLevel.Error;
                    totalUnsigned++;
                    break;
                }

                Log.Write(
                    level,
                    "[{Is}/{Of}] {Result}: {Id} → {InstallPath}",
                    ++i,
                    fileMap.Count,
                    result,
                    entry.Key,
                    NormalizePath(entry.Value.InstallPath));
            }

            return(totalUnsigned);
        }
        public bool Match(IEntity entity)
        {
            Func <Type, bool> hasComponent = (t => entity.HasComponent(t));

            if (ExclusionSet.Any(hasComponent))
            {
                return(false);
            }

            if (!AllSet.All(hasComponent))
            {
                return(false);
            }

            if (OneSet.Any() && !OneSet.Any(hasComponent))
            {
                return(false);
            }

            // Nobody complained so we're good here!
            return(true);
        }
Exemple #3
0
        static int Main(string [] args)
        {
            var loggingLevelSwitch = new LoggingLevelSwitch {
                MinimumLevel = LogEventLevel.Information
            };

            Log.Logger = new LoggerConfiguration()
                         .WriteTo.Console()
                         .MinimumLevel.ControlledBy(loggingLevelSwitch)
                         .CreateLogger();

            Console.OutputEncoding = Encoding.UTF8;

            string    workingPath               = null;
            bool      cleanWorkingPath          = false;
            string    exclusionsFile            = null;
            bool      updateExclusionsFile      = false;
            string    exclusionsBootstrapReason = null;
            bool      showHelp     = false;
            string    msiFile      = null;
            Exception optionsError = null;

            var optionSet = new OptionSet
            {
                { "o|output=", "Output path for intermediate work",
                  v => workingPath = v },
                { "x|exclude=", "Path to an exclusions JSON file (see below for format)",
                  v => exclusionsFile = v },
                { "exclude-update", "Update the exclusions file in place by removing " +
                  "entries in the exclusion file no longer present in the installer.",
                  v => updateExclusionsFile = true },
                { "exclude-bootstrap=", "Generate an initial exclusions file based on all unsigned files.",
                  v => exclusionsBootstrapReason = v },
                { "v|verbose", "Verbose", v => {
                      switch (loggingLevelSwitch.MinimumLevel)
                      {
                      case LogEventLevel.Debug:
                          loggingLevelSwitch.MinimumLevel = LogEventLevel.Verbose;
                          break;

                      case LogEventLevel.Verbose:
                          break;

                      default:
                          loggingLevelSwitch.MinimumLevel = LogEventLevel.Debug;
                          break;
                      }
                  } },
                { "h|?|help", "Show this help",
                  v => showHelp = true }
            };

            try {
                var remaining = optionSet.Parse(args);
                switch (remaining.Count)
                {
                case 0:
                    throw new Exception("must specify an MSI file to process");

                case 1:
                    msiFile = remaining [0];
                    break;

                default:
                    throw new Exception("only one MSI file may be specified");
                }
            } catch (Exception e) {
                showHelp     = true;
                optionsError = e;
            }

            if (showHelp)
            {
                if (optionsError != null)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Error.WriteLine("Error: {0}", optionsError.Message);
                    Console.Error.WriteLine();
                    Console.ResetColor();
                }

                Console.Error.WriteLine(
                    "Usage: {0} [OPTIONS] MSI_FILE",
                    Path.GetFileName(typeof(Program).Assembly.Location));
                Console.Error.WriteLine();
                Console.Error.WriteLine("Options:");
                optionSet.WriteOptionDescriptions(Console.Error);
                return(1);
            }

            if (workingPath == null)
            {
                workingPath      = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
                cleanWorkingPath = true;
            }

            ExclusionSet exclusions;

            try {
                exclusions = new ExclusionSet(exclusionsFile);
            } catch (Exception e) {
                Log.Fatal(e, "Error loading exclusions file {ExclusionsFile}", exclusionsFile);
                return(1);
            }

            int totalUnsigned = 0;

            try {
                var wxsOutputPath = Path.Combine(
                    workingPath,
                    Path.GetFileNameWithoutExtension(msiFile) + ".wxs");

                var extractPath = Path.Combine(workingPath, "contents");

                if (!Directory.Exists(extractPath))
                {
                    Exec(
                        "wix/dark",
                        Path.Combine(FindWixTools(), "dark.exe"),
                        "-v",
                        "-sui",
                        "-o", wxsOutputPath,
                        "-x", extractPath,
                        msiFile);
                }

                var fileMap = GenerateFileMap(wxsOutputPath);
                foreach (var entry in fileMap)
                {
                    exclusions.MarkHandled(entry.Value.InstallPath);
                }

                var stopwatch = new Stopwatch();
                stopwatch.Start();

                totalUnsigned = VerifySignatures(
                    fileMap,
                    exclusions,
                    exclusionsBootstrapReason);

                stopwatch.Stop();

                Log.Debug("Signature verification completed: {Duration}", stopwatch.Elapsed);

                if (exclusionsBootstrapReason != null || updateExclusionsFile)
                {
                    exclusions.Save();
                }
            } finally {
                if (cleanWorkingPath)
                {
                    Log.Debug("Removing working directory {WorkingPath}…", workingPath);
                    Directory.Delete(workingPath, recursive: true);
                }
            }

            if (totalUnsigned > 0)
            {
                Log.Error("{TotalUnsigned} unsigned files", totalUnsigned);
                return(2);
            }

            return(0);
        }