예제 #1
0
        public void Convert()
        {
            var tempReg = System.Guid.NewGuid().ToString("N") + ".reg";
            var tempDir = "reg-out-" + System.Guid.NewGuid().ToString("N");

            Directory.CreateDirectory(tempDir);
            try
            {
                var mfn = typeof(TestConversion).Assembly.GetManifestResourceNames().First(a => a.EndsWith("team.reg"));
                using (var mf = typeof(TestConversion).Assembly.GetManifestResourceStream(mfn))
                {
                    using (var fs = File.OpenWrite(tempReg))
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        mf.CopyTo(fs);
                        fs.Flush(true);
                    }
                }

                var regConv = new MsixRegistryFileWriter(tempDir);
                var regPars = new RegFileParser();

                regPars.Parse(Path.Combine(tempReg));
                regConv.ImportRegFile(tempReg);
            }
            finally
            {
                ExceptionGuard.Guard(() =>
                {
                    Directory.Delete(tempDir, true);
                    File.Delete(tempReg);
                });
            }
        }
        public async Task <string> GetSubjectFromDeviceGuardSigning(string accessToken, string refreshToken, CancellationToken cancellationToken = default)
        {
            string tempFile = null;

            try
            {
                var cfg = new DeviceGuardConfig
                {
                    AccessToken  = accessToken,
                    RefreshToken = refreshToken
                };

                var helper = new DgssTokenCreator();
                tempFile = await helper.CreateDeviceGuardJsonTokenFile(cfg, cancellationToken).ConfigureAwait(false);

                return(await this.GetSubjectFromDeviceGuardSigning(tempFile, cancellationToken).ConfigureAwait(false));
            }
            finally
            {
                if (tempFile != null && File.Exists(tempFile))
                {
                    ExceptionGuard.Guard(() => File.Delete(tempFile));
                }
            }
        }
예제 #3
0
        public async Task MountVhd(string vhdPath, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = null)
        {
            Logger.Info($"Mounting volume {vhdPath}...");
            var tempFile = Path.Combine(Path.GetTempPath(), "msix-hero-vhd-" + Guid.NewGuid().ToString("N").Substring(0, 10) + ".cfg");

            try
            {
                var content = @"select vdisk file = ""{0}""
attach vdisk";

                await File.WriteAllTextAsync(tempFile, string.Format(content, vhdPath), cancellationToken).ConfigureAwait(false);

                var arguments = $"/S \"{tempFile}\"";

                Logger.Debug($"DISKPART.EXE command in {tempFile}:\r\n{string.Format(content, vhdPath)}");
                await this.RunDiskPart(arguments, cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                if (File.Exists(tempFile))
                {
                    Logger.Debug($"Deleting {tempFile}...");
                    ExceptionGuard.Guard(() => File.Delete(tempFile));
                }
            }
        }
        private void OnOpenStore()
        {
            var selection = this.GetSingleOrDefaultSelection();

            if (selection == null)
            {
                return;
            }

            if (selection.SignatureKind != SignatureKind.Store)
            {
                return;
            }

            var link = $"ms-windows-store://pdp/?PFN={selection.PackageFamilyName}";
            var psi  = new ProcessStartInfo(link)
            {
                UseShellExecute = true
            };

            ExceptionGuard.Guard
            (
                () =>
            {
                Process.Start(psi);
            },
                this.interactionService
            );
        }
예제 #5
0
 // ReSharper disable once UnusedParameter.Local
 private void Dispose(bool disposing)
 {
     if (this.tempDirectory?.Exists == true)
     {
         ExceptionGuard.Guard(() => this.tempDirectory.Delete(true));
         this.tempDirectory = null;
     }
 }
예제 #6
0
 private void Hyperlink_OnClick(object sender, RoutedEventArgs e)
 {
     ExceptionGuard.Guard(() =>
     {
         var dir = (string)((Hyperlink)sender).Tag;
         Process.Start("explorer.exe", "/select," + Path.Combine(dir, FileConstants.AppxManifestFile));
     },
                          new InteractionService(new NotificationManager()));
 }
예제 #7
0
        private void OnOpenReleaseNotes()
        {
            ExceptionGuard.Guard(() =>
            {
                var psi = new ProcessStartInfo("https://msixhero.net/redirect/release-notes/" + this.CurrentVersion)
                {
                    UseShellExecute = true
                };

                Process.Start(psi);
            },
                                 this.interactionService);
        }
예제 #8
0
        private void HyperlinkOnClick(object sender, RoutedEventArgs e)
        {
            ExceptionGuard.Guard(() =>
            {
                var psi = new ProcessStartInfo((string)((Hyperlink)sender).Tag)
                {
                    UseShellExecute = true
                };

                Process.Start(psi);
            },
                                 new InteractionService(new NotificationManager()));
        }
        private async void OnView()
        {
            var selectedFile = this.SelectedNode;

            if (selectedFile == null)
            {
                return;
            }

            using var reader = FileReaderFactory.CreateFileReader(this.PackageFile);
            var path = await this.fileViewer.GetDiskPath(reader, selectedFile.Path).ConfigureAwait(false);

            ExceptionGuard.Guard(() => { this.fileInvoker.Execute(path, true); });
        }
예제 #10
0
        static App()
        {
            var logLevel = MsixHeroLogLevel.Info;

            ExceptionGuard.Guard(() =>
            {
                var service = new LocalConfigurationService();
                var config  = service.GetCurrentConfiguration();

                logLevel = config.VerboseLogging ? MsixHeroLogLevel.Trace : MsixHeroLogLevel.Info;
            });

            LogManager.Initialize(logLevel);
        }
예제 #11
0
        public async Task<string> GetSubjectFromDeviceGuardSigning(string dgssTokenPath, CancellationToken cancellationToken = default)
        {
            Logger.Info("Getting certificate subject for Device Guard signing...");

            var tempFilePath = Path.Combine(Path.GetTempPath(), "msix-hero-" + Guid.NewGuid().ToString("N") + ".cat");
            try
            {
                var name = typeof(DeviceGuardHelper).Assembly.GetManifestResourceNames().First(n => n.EndsWith("MSIXHeroTest.cat"));
                using (var manifestResourceStream = typeof(DeviceGuardHelper).Assembly.GetManifestResourceStream(name))
                {
                    if (manifestResourceStream == null)
                    {
                        throw new InvalidOperationException("Cannot extract temporary file.");
                    }

                    Logger.Debug($"Creating temporary file path {tempFilePath}");
                    using (var fileStream = File.Create(tempFilePath))
                    {
                        manifestResourceStream.Seek(0L, SeekOrigin.Begin);
                        await manifestResourceStream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
                    }
                }

                var sdk = new MsixSdkWrapper();
                Logger.Debug($"Signing temporary file path {tempFilePath}");
                await sdk.SignPackageWithDeviceGuard(new[] {tempFilePath}, "SHA256", dgssTokenPath, null, cancellationToken).ConfigureAwait(false);

                using (var fromSignedFile = X509Certificate.CreateFromSignedFile(tempFilePath))
                {
                    Logger.Info($"Certificate subject is {tempFilePath}");
                    return fromSignedFile.Subject;
                }
            }
            catch (Exception e)
            {
                Logger.Error("Could not read subject from Device Guard certificate.", e);
                throw;
            }
            finally
            {
                if (File.Exists(tempFilePath))
                {
                    Logger.Debug($"Removing {tempFilePath}");
                    ExceptionGuard.Guard(() => File.Delete(tempFilePath));
                }
            }
        }
예제 #12
0
        static Program()
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomainOnUnhandledException;
            TaskScheduler.UnobservedTaskException      += TaskSchedulerOnUnobservedTaskException;

            var logLevel = MsixHeroLogLevel.Info;

            ExceptionGuard.Guard(() =>
            {
                var service = new LocalConfigurationService();
                var config  = service.GetCurrentConfiguration();

                logLevel = config.VerboseLogging ? MsixHeroLogLevel.Trace : MsixHeroLogLevel.Info;
            });

            LogManager.Initialize(logLevel);
        }
예제 #13
0
        private async Task <int> SignDeviceGuardInteractive(string timestamp, bool updatePublisherName)
        {
            string            json = null;
            DeviceGuardConfig cfg;

            try
            {
                cfg = await this.DeviceGuardTokenCreator.SignIn().ConfigureAwait(false);

                json = await this.DeviceGuardTokenCreator.CreateDeviceGuardJsonTokenFile(cfg).ConfigureAwait(false);

                if (!this.Verb.NoPublisherUpdate)
                {
                    await this.Console.WriteInfo("Determining publisher name from Device Guard Signing certificate...").ConfigureAwait(false);

                    cfg.Subject = await this.DeviceGuardHelper.GetSubjectFromDeviceGuardSigning(json).ConfigureAwait(false);

                    await this.Console.WriteSuccess("New publisher name is " + cfg.Subject).ConfigureAwait(false);
                }
            }
            catch (SdkException e)
            {
                Logger.Error(e);
                await this.Console.WriteError($"Signing failed with error code 0x{e.ExitCode:X}: {e.Message}");

                return(e.ExitCode);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                await this.Console.WriteError($"Signing failed: {e.Message}");

                return(10);
            }
            finally
            {
                if (json != null && File.Exists(json))
                {
                    ExceptionGuard.Guard(() => File.Delete(json));
                }
            }

            return(await this.SignDeviceGuard(cfg, timestamp, updatePublisherName).ConfigureAwait(false));
        }
예제 #14
0
        private void OpenLogsClicked(object sender, RoutedEventArgs e)
        {
            var logFile = LogManager.LogFile;

            if (logFile != null)
            {
                ExceptionGuard.Guard(() =>
                {
                    var psi = new ProcessStartInfo
                    {
                        UseShellExecute = true,
                        FileName        = "explorer.exe",
                        Arguments       = "/e," + Path.GetDirectoryName(logFile)
                    };

                    Process.Start(psi);
                });
            }
        }
예제 #15
0
        public override async Task <int> Execute()
        {
            var msixSdkWrapper = new MakeAppxWrapper();

            Logger.Info($"Packing [{this.Verb.Directory}] to [{this.Verb.Package}]...");

            try
            {
                await this.Console.WriteInfo($"Packing [{this.Verb.Directory}] to [{this.Verb.Package}]...").ConfigureAwait(false);

                await msixSdkWrapper.PackPackageDirectory(this.Verb.Directory, this.Verb.Package, !this.Verb.NoCompression, !this.Verb.NoValidation).ConfigureAwait(false);

                await this.Console.WriteSuccess($"Package [{this.Verb.Package}] has been created.");

                if (this.Verb.RemoveDirectoryAfterPacking)
                {
                    await this.Console.WriteInfo($"Removing source directory {this.Verb.Directory}...");

                    ExceptionGuard.Guard(() => Directory.Delete(this.Verb.Directory, true));
                }

                return(StandardExitCodes.ErrorSuccess);
            }
            catch (SdkException e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message);

                return(e.ExitCode);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message);

                return(StandardExitCodes.ErrorGeneric);
            }
        }
예제 #16
0
        public override async Task <int> Execute()
        {
            var msixSdkWrapper = new MakeAppxWrapper();

            Logger.Info($"Unpacking [{this.Verb.Package}] to [{this.Verb.Directory}]...");

            try
            {
                await this.Console.WriteInfo($"Unpacking [{this.Verb.Package}] to [{this.Verb.Directory}]...").ConfigureAwait(false);

                await msixSdkWrapper.UnpackPackage(this.Verb.Package, this.Verb.Directory, !this.Verb.NoValidation).ConfigureAwait(false);

                await this.Console.WriteSuccess($"The package has been unpacked to [{this.Verb.Directory}].");

                if (this.Verb.RemovePackageAfterExtraction)
                {
                    await this.Console.WriteInfo($"Removing source package {this.Verb.Package}...");

                    ExceptionGuard.Guard(() => File.Delete(this.Verb.Package));
                }

                return(StandardExitCodes.ErrorSuccess);
            }
            catch (SdkException e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message);

                return(e.ExitCode);
            }
            catch (Exception e)
            {
                Logger.Error(e);
                await this.Console.WriteError(e.Message);

                return(StandardExitCodes.ErrorGeneric);
            }
        }
예제 #17
0
        static async Task <int> Main(string[] args)
        {
            var logLevel = MsixHeroLogLevel.Trace;

            ExceptionGuard.Guard(() =>
            {
                var service = new LocalConfigurationService();
                var config  = service.GetCurrentConfiguration();

                logLevel = config.VerboseLogging ? MsixHeroLogLevel.Trace : MsixHeroLogLevel.Info;
            });

            LogManager.Initialize(logLevel);

            var console = new ConsoleImpl(Console.Out, Console.Error);

            try
            {
                // First argument is the "edit" verb.
                // Second argument is the path of the package.
                if (args.Length > 1 &&
                    string.Equals(args[0], "edit", StringComparison.OrdinalIgnoreCase) &&
                    !args[1].StartsWith("-", StringComparison.OrdinalIgnoreCase))
                {
                    return(await DoEditVerb(args[1], args.Skip(2), console));
                }

                return(await DoCommonVerbs(args, console));
            }
            catch (Exception e)
            {
                await console.WriteError(e.Message).ConfigureAwait(false);

                Environment.ExitCode = 1;
                return(1);
            }
        }
예제 #18
0
        public void Convert()
        {
            var tempReg = System.Guid.NewGuid().ToString("N") + ".reg";
            var tempDir = "reg-out-" + System.Guid.NewGuid().ToString("N");

            Directory.CreateDirectory(tempDir);
            try
            {
                var mfn = typeof(TestConversion).Assembly.GetManifestResourceNames().First(a => a.EndsWith("team.reg"));
                using (var mf = typeof(TestConversion).Assembly.GetManifestResourceStream(mfn))
                {
                    using (var fs = System.IO.File.OpenWrite(tempReg))
                    {
                        // ReSharper disable once PossibleNullReferenceException
                        mf.CopyTo(fs);
                        fs.Flush(true);
                    }
                }

                var regConv = new RegConverter();
                var regPars = new RegFileParser();

                regPars.Parse(Path.Combine(tempReg));
                regConv.ConvertFromRegToDat(tempReg, Path.Combine(tempDir, "Registry.dat"), RegistryRoot.HKEY_LOCAL_MACHINE).GetAwaiter().GetResult();
                regConv.ConvertFromRegToDat(tempReg, Path.Combine(tempDir, "UserClasses.dat"), RegistryRoot.HKEY_CLASSES_ROOT).GetAwaiter().GetResult();
                regConv.ConvertFromRegToDat(tempReg, Path.Combine(tempDir, "User.dat"), RegistryRoot.HKEY_CURRENT_USER).GetAwaiter().GetResult();
            }
            finally
            {
                ExceptionGuard.Guard(() =>
                {
                    System.IO.Directory.Delete(tempDir, true);
                    System.IO.File.Delete(tempReg);
                });
            }
        }
예제 #19
0
 private Configuration GetConfigurationSafe()
 {
     return(ExceptionGuard.Guard(() => this.Container.Resolve <IConfigurationService>().GetCurrentConfiguration()));
 }
예제 #20
0
        protected override async Task <bool> Save(CancellationToken cancellationToken, IProgress <ProgressData> progress)
        {
            var temporaryFiles = new List <string>();

            try
            {
                var fileListBuilder = new PackageFileListBuilder();
                fileListBuilder.AddDirectory(this.InputPath.CurrentValue, true, null);

                if (this.PrePackOptions != null && !this.PrePackOptions.ManifestPresent)
                {
                    if (!this.PrePackOptions.CanConvert)
                    {
                        throw new InvalidOperationException("The selected folder does not contain a manifest file and any executable files. It cannot be packed to MSIX format.");
                    }

                    if (!string.IsNullOrEmpty(this.InputPath.CurrentValue))
                    {
                        progress.Report(new ProgressData(0, "Creating manifest file..."));
                        var options = new AppxManifestCreatorOptions
                        {
                            CreateLogo         = this.PrePackOptions.CreateLogo,
                            EntryPoints        = this.PrePackOptions.EntryPoints.Where(e => e.IsChecked).Select(e => e.Value).ToArray(),
                            PackageDisplayName = Path.GetFileName(this.InputPath.CurrentValue),
                            RegistryFile       = this.PrePackOptions.SelectedRegistry?.FilePath == null ? null : new FileInfo(this.PrePackOptions.SelectedRegistry.FilePath)
                        };

                        // ReSharper disable once AssignNullToNotNullAttribute
                        await foreach (var result in this.manifestCreator.CreateManifestForDirectory(new DirectoryInfo(this.InputPath.CurrentValue), options, cancellationToken).ConfigureAwait(false))
                        {
                            temporaryFiles.Add(result.SourcePath);

                            if (result.PackageRelativePath == null)
                            {
                                continue;
                            }

                            fileListBuilder.AddFile(result.SourcePath, result.PackageRelativePath);
                        }
                    }
                }

                using var progressWrapper = new WrappedProgress(progress);
                var progress1 = progressWrapper.GetChildProgress(50);
                var progress2 = this.Sign.CurrentValue ? progressWrapper.GetChildProgress(30) : null;

                var tempFileList = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".list");
                temporaryFiles.Add(tempFileList);

                var tempManifestPath = Path.Combine(Path.GetTempPath(), "AppxManifest-" + Guid.NewGuid().ToString("N") + ".xml");
                temporaryFiles.Add(tempManifestPath);

                var srcManifest = fileListBuilder.GetManifestSourcePath();
                if (srcManifest == null || !File.Exists(srcManifest))
                {
                    throw new InvalidOperationException("The selected folder cannot be packed because it has no manifest, and MSIX Hero was unable to create one. A manifest can be only created if the selected folder contains any executable file.");
                }

                // Copy manifest to a temporary file
                var injector = new MsixHeroBrandingInjector();
                await using (var manifestStream = File.OpenRead(fileListBuilder.GetManifestSourcePath()))
                {
                    var xml = await XDocument.LoadAsync(manifestStream, LoadOptions.None, cancellationToken).ConfigureAwait(false);

                    await injector.Inject(xml).ConfigureAwait(false);

                    await File.WriteAllTextAsync(tempManifestPath, xml.ToString(SaveOptions.None), cancellationToken);

                    fileListBuilder.AddManifest(tempManifestPath);
                }

                await File.WriteAllTextAsync(tempFileList, fileListBuilder.ToString(), cancellationToken).ConfigureAwait(false);

                var sdk = new MakeAppxWrapper();
                await sdk.PackPackageFiles(tempFileList, this.OutputPath.CurrentValue, this.Compress.CurrentValue, this.Validate.CurrentValue, cancellationToken, progress1).ConfigureAwait(false);

                if (this.Sign.CurrentValue)
                {
                    var manager = await this.signingManagerFactory.GetProxyFor(SelfElevationLevel.HighestAvailable, cancellationToken).ConfigureAwait(false);

                    string timeStampUrl;
                    switch (this.SelectedCertificate.TimeStampSelectionMode.CurrentValue)
                    {
                    case TimeStampSelectionMode.None:
                        timeStampUrl = null;
                        break;

                    case TimeStampSelectionMode.Auto:
                        timeStampUrl = "auto";
                        break;

                    case TimeStampSelectionMode.Url:
                        timeStampUrl = this.SelectedCertificate.TimeStamp.CurrentValue;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    switch (this.SelectedCertificate.Store.CurrentValue)
                    {
                    case CertificateSource.Personal:
                        await manager.SignPackageWithInstalled(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.SelectedPersonalCertificate.CurrentValue?.Model, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false);

                        break;

                    case CertificateSource.Pfx:
                        await manager.SignPackageWithPfx(this.OutputPath.CurrentValue, this.OverrideSubject.CurrentValue, this.SelectedCertificate.PfxPath.CurrentValue, this.SelectedCertificate.Password.CurrentValue, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false);

                        break;

                    case CertificateSource.DeviceGuard:
                        await manager.SignPackageWithDeviceGuardFromUi(this.OutputPath.CurrentValue, this.SelectedCertificate.DeviceGuard.CurrentValue, timeStampUrl, IncreaseVersionMethod.None, cancellationToken, progress2).ConfigureAwait(false);

                        break;
                    }
                }

                if (this.RemoveDirectory.CurrentValue)
                {
                    ExceptionGuard.Guard(() => Directory.Delete(this.InputPath.CurrentValue, true));
                }

                return(true);
            }
            finally
            {
                foreach (var tempFile in temporaryFiles)
                {
                    ExceptionGuard.Guard(() => File.Delete(tempFile));
                }
            }
        }
예제 #21
0
        private async Task RunMsixMgr(string arguments, CancellationToken cancellationToken = default, Action <string> callBack = null)
        {
            string msixMgrPath;
            string msixMgrDirectory;
            bool   cleanupMsixMgrDirectory;

            if (!this.forceRunFromSource && new DesktopBridge.Helpers().IsRunningAsUwp())
            {
                Logger.Info("Detected MSIX Hero running with package identity. MSIXMGR must be started from a temporary location...");
                msixMgrDirectory = Path.Combine(Path.GetTempPath(), "msixmgr-" + Guid.NewGuid().ToString("N").Substring(0, 10));

                var originalMsixMgrPath      = GetMsixMgrPath("msixmgr.exe", BundleHelper.MsixMgrPath);
                var originalMsixMgrDirectory = Path.GetDirectoryName(originalMsixMgrPath);
                if (originalMsixMgrDirectory == null)
                {
                    throw new InvalidOperationException("Original directory not available.");
                }

                foreach (var item in Directory.EnumerateFiles(originalMsixMgrDirectory, "*.*", SearchOption.AllDirectories))
                {
                    var relativePath = Path.GetRelativePath(originalMsixMgrDirectory, item);
                    var sourceFile   = new FileInfo(Path.Combine(originalMsixMgrDirectory, relativePath));
                    var targetFile   = new FileInfo(Path.Combine(msixMgrDirectory, relativePath));

                    if (targetFile.Directory?.Exists == false)
                    {
                        targetFile.Directory.Create();
                    }

                    Logger.Debug("Copying {0} to {1}...", sourceFile.FullName, targetFile.FullName);
                    sourceFile.CopyTo(targetFile.FullName);
                }

                msixMgrPath             = Path.Combine(msixMgrDirectory, "msixmgr.exe");
                cleanupMsixMgrDirectory = true;
            }
            else
            {
                msixMgrPath             = GetMsixMgrPath("msixmgr.exe", BundleHelper.MsixMgrPath);
                msixMgrDirectory        = Path.GetDirectoryName(msixMgrPath);
                cleanupMsixMgrDirectory = false;
            }

            Logger.Info("Executing {0} {1}", msixMgrPath, arguments);

            try
            {
                var tempDir = Path.GetTempPath();
                await RunAsync(msixMgrPath, arguments, tempDir, cancellationToken, callBack, 0).ConfigureAwait(false);
            }
            catch (ProcessWrapperException e)
            {
                Logger.Warn("Process returned exit code " + e.ExitCode);
                if (e.ExitCode == -1951596541)
                {
                    throw new InvalidOperationException("Could not expand MSIX Package to the VHD file. The maximum size of the virtual disk is smaller than the file size of expanded MSIX package. Try using a bigger disk size.", e);
                }

#pragma warning disable 652
                if (e.ExitCode == 0x80070522)
#pragma warning restore 652
                {
                    throw new UnauthorizedAccessException("This operation requires admin permissions.", e);
                }

                throw new InvalidOperationException(
                          e.StandardError.LastOrDefault(stdError =>
                                                        !string.IsNullOrWhiteSpace(stdError) &&
                                                        !stdError.Contains("Successfully started the Shell Hardware Detection Service",
                                                                           StringComparison.OrdinalIgnoreCase)), e);
            }
            finally
            {
                if (cleanupMsixMgrDirectory)
                {
                    Logger.Debug("Removing temporary files from {0}...", msixMgrDirectory);
                    ExceptionGuard.Guard(() => Directory.Delete(msixMgrDirectory, true));
                }
            }
        }
예제 #22
0
        public async Task SignPackageWithDeviceGuard(string package,
                                                     bool updatePublisher,
                                                     DeviceGuardConfig config,
                                                     string timestampUrl = null,
                                                     IncreaseVersionMethod increaseVersion = IncreaseVersionMethod.None,
                                                     CancellationToken cancellationToken   = default,
                                                     IProgress <ProgressData> progress     = null)
        {
            Logger.Info("Signing package {0} using Device Guard for {1}.", package, config.Subject);

            var dgssTokenPath = await new DgssTokenCreator().CreateDeviceGuardJsonTokenFile(config, cancellationToken);

            try
            {
                var publisherName = config.Subject;
                if (publisherName == null)
                {
                    var dgh = new DeviceGuardHelper();
                    publisherName = await dgh.GetSubjectFromDeviceGuardSigning(dgssTokenPath, cancellationToken).ConfigureAwait(false);
                }

                var localCopy = await this.PreparePackageForSigning(package, updatePublisher, increaseVersion, publisherName, cancellationToken).ConfigureAwait(false);

                try
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var sdk = new SignToolWrapper();
                    progress?.Report(new ProgressData(25, "Signing with Device Guard..."));

                    timestampUrl = await this.GetTimeStampUrl(timestampUrl).ConfigureAwait(false);

                    await sdk.SignPackageWithDeviceGuard(new[] { localCopy }, "SHA256", dgssTokenPath, timestampUrl, cancellationToken).ConfigureAwait(false);

                    progress?.Report(new ProgressData(75, "Signing with Device Guard..."));
                    await Task.Delay(500, cancellationToken).ConfigureAwait(false);

                    Logger.Debug("Moving {0} to {1}.", localCopy, package);
                    File.Copy(localCopy, package, true);
                    progress?.Report(new ProgressData(95, "Signing with Device Guard..."));
                }
                finally
                {
                    try
                    {
                        if (File.Exists(localCopy))
                        {
                            File.Delete(localCopy);
                        }
                    }
                    catch (Exception e)
                    {
                        Logger.Warn(e, "Clean-up of a temporary file {0} failed.", localCopy);
                    }
                }
            }
            finally
            {
                if (File.Exists(dgssTokenPath))
                {
                    ExceptionGuard.Guard(() => File.Delete(dgssTokenPath));
                }
            }
        }
예제 #23
0
        public async Task <DeviceGuardConfig> SignIn(CancellationToken cancellationToken = default, IProgress <ProgressData> progress = null)
        {
            Logger.Info("Signing in to AzureAD...");
            progress?.Report(new ProgressData(50, "Waiting for authentication..."));
            var tokens   = new DeviceGuardConfig();
            var pipeName = "msixhero-" + Guid.NewGuid().ToString("N");

            await using (var namedPipeServer = new NamedPipeServerStream(pipeName, PipeDirection.In))
            {
                var entry = (Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()).Location;

                // ReSharper disable once AssignNullToNotNullAttribute
                var startPath = Path.Combine(Path.GetDirectoryName(entry), "DGSS", "msixhero-dgss.exe");
                Logger.Debug($"Starting {startPath}...");
                var process = new ProcessStartInfo(
                    startPath,
                    pipeName);

                var tcs = new TaskCompletionSource <int>();

                var start = Process.Start(process);
                if (start == null)
                {
                    throw new InvalidOperationException();
                }

                start.EnableRaisingEvents = true;
                start.Exited += (sender, args) =>
                {
                    tcs.SetResult(start.ExitCode);
                };

                await namedPipeServer.WaitForConnectionAsync(cancellationToken).ConfigureAwait(false);

                var bufferInt = new byte[4];
                await namedPipeServer.ReadAsync(bufferInt, 0, bufferInt.Length, cancellationToken).ConfigureAwait(false);

                var bufferObj = new byte[BitConverter.ToInt32(bufferInt, 0)];
                await namedPipeServer.ReadAsync(bufferObj, 0, bufferObj.Length, cancellationToken).ConfigureAwait(false);

                var text = System.Text.Encoding.UTF8.GetString(bufferObj);
                var obj  = JObject.Parse(text);

                if (obj["exception"] != null)
                {
                    var type      = obj["exception"]["type"]?.Value <string>();
                    var message   = obj["exception"]["message"]?.Value <string>();
                    var errorCode = obj["exception"]["errorCode"]?.Value <string>();

                    Logger.Error($"Got exception (type: {type}, error code: {errorCode}, message: {message}");

                    switch (type)
                    {
                    case nameof(AuthenticationException):
                        throw new AuthenticationException(message);

                    case nameof(MsalException):
                        throw new MsalException(errorCode ?? "1", message);

                    case nameof(MsalClientException):
                        throw new MsalClientException(errorCode ?? "1", message);

                    default:
                        throw new Exception(message);
                    }
                }

                tokens.AccessToken  = obj["access_token"]?.Value <string>();
                tokens.RefreshToken = obj["refresh_token"]?.Value <string>();

                Logger.Info("Got access and refresh token!");
                await tcs.Task.ConfigureAwait(false);
            }

            string tempJsonFile = null;

            try
            {
                var dgh = new DeviceGuardHelper();
                progress?.Report(new ProgressData(75, "Verifying signing capabilities..."));
                tempJsonFile = await this.CreateDeviceGuardJsonTokenFile(tokens, cancellationToken).ConfigureAwait(false);

                progress?.Report(new ProgressData(98, "Verifying signing capabilities..."));
                var subject = await dgh.GetSubjectFromDeviceGuardSigning(tempJsonFile, cancellationToken).ConfigureAwait(false);

                tokens.Subject = subject;
            }
            finally
            {
                if (tempJsonFile != null)
                {
                    Logger.Debug($"Removing {tempJsonFile}...");
                    ExceptionGuard.Guard(() => File.Delete(tempJsonFile));
                }
            }

            return(tokens);
        }
        public override async Task <int> Execute()
        {
            try
            {
                await this.OnBegin().ConfigureAwait(false);

                if (!File.Exists(this.package) && !Directory.Exists(this.package))
                {
                    await this.Console.WriteError($"The path {this.package} does not exist.");

                    return(10);
                }

                var validation = await this.Validate().ConfigureAwait(false);

                if (validation != 0)
                {
                    return(validation);
                }

                if (File.Exists(this.package))
                {
                    // This is a file...
                    if (string.Equals(Path.GetFileName(this.package), FileConstants.AppxManifestFile, StringComparison.OrdinalIgnoreCase))
                    {
                        // .. a manifest file
                        var result = await this.ExecuteOnExtractedPackage(Path.GetDirectoryName(this.package)).ConfigureAwait(false);

                        await this.OnFinished().ConfigureAwait(false);

                        return(result);
                    }

                    if (string.Equals(".msix", Path.GetExtension(this.package)))
                    {
                        // .. an MSIX package
                        var msixMgr    = new MakeAppxWrapper();
                        var tempFolder = Path.Combine(Path.GetTempPath(), "msixhero-" + Guid.NewGuid().ToString("N").Substring(0, 8));

                        try
                        {
                            await this.Console.WriteInfo($"Opening {Path.GetFileName(this.package)}...").ConfigureAwait(false);

                            // 1) Unpack first
                            await msixMgr.UnpackPackage(this.package, tempFolder, false).ConfigureAwait(false);

                            // 2) Make edit
                            var result = await this.ExecuteOnExtractedPackage(tempFolder).ConfigureAwait(false);

                            if (result != StandardExitCodes.ErrorSuccess)
                            {
                                await this.Console.WriteWarning($"The package has not been updated due to previous errors.").ConfigureAwait(false);

                                return(result);
                            }

                            // 3) Add branding
                            XDocument document;
                            await using (var fs = File.OpenRead(Path.Combine(tempFolder, "AppxManifest.xml")))
                            {
                                document = await XDocument.LoadAsync(fs, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);
                            }

                            var inject = new MsixHeroBrandingInjector();
                            await inject.Inject(document).ConfigureAwait(false);

                            var writer = new AppxDocumentWriter(document);
                            await writer.WriteAsync(Path.Combine(tempFolder, "AppxManifest.xml")).ConfigureAwait(false);

                            if (result == StandardExitCodes.ErrorSuccess)
                            {
                                await this.Console.WriteInfo($"Saving {Path.GetFileName(this.package)}...").ConfigureAwait(false);

                                // 3) Pack again
                                await msixMgr.PackPackageDirectory(tempFolder, this.package, false, false);

                                await this.OnFinished().ConfigureAwait(false);
                            }

                            return(result);
                        }
                        finally
                        {
                            if (Directory.Exists(tempFolder))
                            {
                                ExceptionGuard.Guard(() => Directory.Delete(tempFolder, true));
                            }
                        }
                    }
                }
                else if (Directory.Exists(this.package))
                {
                    // this is extracted directory
                    var manifestPath = Path.Combine(this.package, FileConstants.AppxManifestFile);
                    if (File.Exists(manifestPath))
                    {
                        var result = await this.ExecuteOnExtractedPackage(this.package).ConfigureAwait(false);

                        XDocument document;
                        await using (var fs = File.OpenRead(manifestPath))
                        {
                            document = await XDocument.LoadAsync(fs, LoadOptions.None, CancellationToken.None).ConfigureAwait(false);
                        }

                        var inject = new MsixHeroBrandingInjector();
                        await inject.Inject(document).ConfigureAwait(false);

                        var writer = new AppxDocumentWriter(document);
                        await writer.WriteAsync(manifestPath).ConfigureAwait(false);

                        await this.OnFinished().ConfigureAwait(false);

                        return(result);
                    }
                }

                await this.Console.WriteError($"The path {this.package} is neither a directory with extracted MSIX, an .MSIX package or a manifest file.").ConfigureAwait(false);

                return(StandardExitCodes.ErrorParameter);
            }
            catch (Exception e)
            {
                await this.Console.WriteError(e.Message).ConfigureAwait(false);

                return(StandardExitCodes.ErrorGeneric);
            }
        }
예제 #25
0
        public async Task CreateVhdAndAssignDriveLetter(string vhdPath, long requiredSize, CancellationToken cancellationToken = default, IProgress <ProgressData> progress = null)
        {
            Logger.Info($"Creating volume {vhdPath} with required size {requiredSize}");

            switch (Path.GetExtension(vhdPath).ToLowerInvariant())
            {
            case ".vhd":
            case ".vhdx":

                var tempCreateFile = Path.Combine(Path.GetTempPath(), "msix-hero-vhd-" + Guid.NewGuid().ToString("N").Substring(0, 10) + ".cfg");

                try
                {
                    var content = @"create vdisk file=""{0}"" maximum={1} type=expandable";

                    var requiredSizeMb = (int)(10 * Math.Ceiling(0.1 * requiredSize / 1024 / 1024));
                    await File.WriteAllTextAsync(tempCreateFile, string.Format(content, vhdPath, requiredSizeMb), cancellationToken).ConfigureAwait(false);

                    var arguments = $"/S \"{tempCreateFile}\"";

                    Logger.Debug($"DISKPART.EXE command in {tempCreateFile}:\r\n{string.Format(content, vhdPath, requiredSizeMb)}");
                    await this.RunDiskPart(arguments, cancellationToken).ConfigureAwait(false);
                }
                finally
                {
                    if (File.Exists(tempCreateFile))
                    {
                        Logger.Debug($"Deleting {tempCreateFile}...");
                        ExceptionGuard.Guard(() => File.Delete(tempCreateFile));
                    }
                }

                break;

            default:
                throw new NotSupportedException($"Extension {Path.GetExtension(vhdPath)} is not supported.");
            }

            Logger.Info("Formatting drive and assigning drive letter...");
            string tempFileMount = null;

            try
            {
                var content = @"select vdisk file = ""{0}""
attach vdisk
create partition primary
format fs=ntfs
assign";
                tempFileMount = Path.Combine(Path.GetTempPath(), "msix-hero-vhd-" + Guid.NewGuid().ToString("N").Substring(0, 10) + ".cfg");
                await File.WriteAllTextAsync(tempFileMount, string.Format(content, vhdPath), cancellationToken).ConfigureAwait(false);

                var arguments = $"/S \"{tempFileMount}\"";

                Logger.Debug($"DISKPART.EXE command in {tempFileMount}:\r\n{string.Format(content, vhdPath)}");
                await this.RunDiskPart(arguments, cancellationToken).ConfigureAwait(false);
            }
            finally
            {
                if (File.Exists(tempFileMount))
                {
                    Logger.Debug($"Deleting {tempFileMount}...");
                    ExceptionGuard.Guard(() => File.Delete(tempFileMount));
                }
            }
        }