示例#1
0
        /// <summary>
        /// Sign an existing package
        /// </summary>
        public int Sign()
        {
            try
            {
                AppletPackage pkg = null;
                using (FileStream fs = File.OpenRead(this.m_parms.Source))
                    pkg = AppletPackage.Load(fs);

                Emit.Message("INFO", "Will sign package {0}", pkg.Meta);
                pkg = this.CreateSignedPackage(pkg.Unpack());
                using (FileStream fs = File.Create(this.m_parms.Output ?? Path.ChangeExtension(this.m_parms.Source, ".signed.pak")))
                    pkg.Save(fs);
                return(0);
            }
            catch (Exception e)
            {
                Emit.Message("ERROR", "Cannot sign package: {0}", e);
                return(-0232);
            }
        }
示例#2
0
        /// <summary>
        /// Sign an existing package
        /// </summary>
        private static int Sign(ConsoleParameters parameters)
        {
            try
            {
                AppletPackage pkg = null;
                using (FileStream fs = File.OpenRead(parameters.Source))
                    pkg = AppletPackage.Load(fs);

                Console.WriteLine("Will sign package {0}", pkg.Meta);
                pkg = CreateSignedPackage(pkg.Unpack(), parameters);
                using (FileStream fs = File.Create(parameters.Output ?? Path.ChangeExtension(parameters.Source, ".signed.pak")))
                    pkg.Save(fs);
                return(0);
            }
            catch (Exception e)
            {
                Console.Error.WriteLine("Cannot sign package: {0}", e);
                return(-0232);
            }
        }
示例#3
0
        /// <summary>
        /// Compose multiple PAK files into a solution
        /// </summary>
        public int Compose()
        {
            try
            {
                AppletManifest mfst = null;
                using (FileStream fs = File.OpenRead(this.m_parms.Source))
                    mfst = AppletManifest.Load(fs);

                var slnPak = mfst.CreatePackage();

                AppletSolution sln = new AppletSolution();
                sln.Meta      = slnPak.Meta;
                sln.PublicKey = slnPak.PublicKey;
                sln.Manifest  = slnPak.Manifest;

                if (sln.Meta.Uuid == Guid.Empty)
                {
                    Emit.Message("WARN", "The package does not carry a UUID! You should add a UUID to your solution manifest");
                }
                sln.Include = new List <AppletPackage>();

                foreach (var pfile in sln.Meta.Dependencies.ToArray())
                {
                    AppletPackage pkg = null;
                    if (!String.IsNullOrEmpty(pfile.Version)) // specific version
                    {
                        pkg = PackageRepositoryUtil.GetFromAny(pfile.Id, new Version(pfile.Version));
                    }
                    else if (!String.IsNullOrEmpty(m_parms.Version))
                    {
                        pkg = PackageRepositoryUtil.GetFromAny(pfile.Id, new Version(m_parms.Version))
                              ?? PackageRepositoryUtil.GetFromAny(pfile.Id, null);
                    }
                    else
                    {
                        pkg = PackageRepositoryUtil.GetFromAny(pfile.Id, null);
                    }

                    if (pkg == null)
                    {
                        throw new KeyNotFoundException($"Package {pfile.Id} ({pfile.Version ?? m_parms.Version ?? "latest"}) not found");
                    }
                    else
                    {
                        Emit.Message("INFO", "Including {0} version {1}..", pkg.Meta.Id, pkg.Meta.Version);
                        sln.Meta.Dependencies.RemoveAll(o => o.Id == pkg.Meta.Id);

                        if (this.m_parms.Sign && pkg.Meta.Signature == null)
                        {
                            Emit.Message("WARN", "Package {0} is not signed, but you're signing your package. We'll sign it using your key", pkg.Meta.Id);
                            pkg = new Signer(this.m_parms).CreateSignedPackage(pkg.Unpack());
                        }
                        sln.Include.Add(pkg);
                    }
                }

                // Emit i18n file?
                if (!String.IsNullOrEmpty(this.m_parms.InternationalizationFile))
                {
                    Emit.Message("INFO", $"Writing string manifest to {this.m_parms.InternationalizationFile}");
                    using (var fs = File.Create(this.m_parms.InternationalizationFile))
                        using (var tw = new StreamWriter(fs, System.Text.Encoding.UTF8))
                        {
                            // tx translations
                            var mfsts         = sln.Include.Select(o => o.Unpack()).ToList();
                            var appletStrings = mfsts.SelectMany(o => o.Strings).ToArray();
                            var stringKeys    = appletStrings.SelectMany(o => o.String).Select(o => o.Key).Distinct();
                            var langs         = appletStrings.Select(o => o.Language).Distinct().ToArray();
                            tw.Write("key,");
                            tw.WriteLine(String.Join(",", langs));

                            foreach (var str in stringKeys)
                            {
                                tw.Write($"{str},");
                                foreach (var lang in langs)
                                {
                                    tw.Write($"\"{appletStrings.Where(o => o.Language == lang).SelectMany(s => s.String).FirstOrDefault(o => o.Key == str)?.Value}\",");
                                }
                                tw.WriteLine();
                            }
                        }
                }

                sln.Meta.Hash = SHA256.Create().ComputeHash(sln.Include.SelectMany(o => o.Manifest).ToArray());
                // Sign the signature package
                if (this.m_parms.Sign)
                {
                    new Signer(this.m_parms).CreateSignedSolution(sln);
                }

                // Now save
                using (FileStream fs = File.Create(this.m_parms.Output ?? Path.ChangeExtension(sln.Meta.Id, ".sln.pak")))
                    sln.Save(fs);

                return(0);
            }
            catch (System.Exception e)
            {
                Emit.Message("ERROR", e.Message);
                //Console.Error.WriteLine("Cannot compose solution {0}: {1}", this.m_parms.Source, e);
                return(-1);
            }
        }
示例#4
0
        /// <summary>
        /// Performs an installation
        /// </summary>
        public virtual bool Install(AppletPackage package, bool isUpgrade = false)
        {
            this.m_tracer.TraceWarning("Installing {0}", package.Meta);

            // TODO: Verify package hash / signature
            if (!this.VerifyPackage(package))
            {
                throw new SecurityException("Applet failed validation");
            }
            else if (!this.m_appletCollection.VerifyDependencies(package.Meta))
            {
                this.m_tracer.TraceWarning($"Applet {package.Meta} depends on : [{String.Join(", ", package.Meta.Dependencies.Select(o => o.ToString()))}] which are missing or incompatible");
            }
            var    appletSection = ApplicationContext.Current.Configuration.GetSection <AppletConfigurationSection>();
            String appletPath    = Path.Combine(appletSection.AppletDirectory, package.Meta.Id);

            try
            {
                // Desearialize an prep for install

                this.m_tracer.TraceInfo("Installing applet {0} (IsUpgrade={1})", package.Meta, isUpgrade);

                ApplicationContext.Current.SetProgress(package.Meta.GetName("en"), 0.0f);
                // TODO: Verify the package

                // Copy
                if (!Directory.Exists(appletSection.AppletDirectory))
                {
                    Directory.CreateDirectory(appletSection.AppletDirectory);
                }

                if (File.Exists(appletPath))
                {
                    if (!isUpgrade)
                    {
                        throw new InvalidOperationException(Strings.err_duplicate_package_name);
                    }

                    // Unload the loaded applet version
                    var existingApplet = this.m_appletCollection.FirstOrDefault(o => o.Info.Id == package.Meta.Id);
                    if (existingApplet != null)
                    {
                        this.UnInstallInternal(existingApplet);
                    }
                }

                var mfst = package.Unpack();
                // Migrate data.
                if (mfst.DataSetup != null)
                {
                    foreach (var itm in mfst.DataSetup.Action)
                    {
                        Type idpType = typeof(IDataPersistenceService <>);
                        idpType = idpType.MakeGenericType(new Type[] { itm.Element.GetType() });
                        var svc = ApplicationContext.Current.GetService(idpType);
                        idpType.GetMethod(itm.ActionName).Invoke(svc, new object[] { itm.Element, TransactionMode.Commit, AuthenticationContext.SystemPrincipal });
                    }
                }

                // Now export all the binary files out
                var assetDirectory = Path.Combine(appletSection.AppletDirectory, "assets", mfst.Info.Id);
                if (!Directory.Exists(assetDirectory))
                {
                    Directory.CreateDirectory(assetDirectory);
                }
                else
                {
                    Directory.Delete(assetDirectory, true);
                }

                for (int i = 0; i < mfst.Assets.Count; i++)
                {
                    var itm     = mfst.Assets[i];
                    var itmPath = Path.Combine(assetDirectory, itm.Name);
                    ApplicationContext.Current.SetProgress($"Installing {package.Meta.GetName("en")}", 0.1f + (float)(0.8 * (float)i / mfst.Assets.Count));

                    // Get dir name and create
                    if (!Directory.Exists(Path.GetDirectoryName(itmPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(itmPath));
                    }

                    // Extract content
                    if (itm.Content is byte[])
                    {
                        if (Encoding.UTF8.GetString(itm.Content as byte[], 0, 4) == "LZIP")
                        {
                            using (var fs = File.Create(itmPath))
                                using (var ms = new MemoryStream(itm.Content as byte[]))
                                    using (var lzs = new LZipStream(new NonDisposingStream(ms), SharpCompress.Compressors.CompressionMode.Decompress))
                                        lzs.CopyTo(fs);
                        }
                        else
                        {
                            File.WriteAllBytes(itmPath, itm.Content as byte[]);
                        }
                        itm.Content = null;
                    }
                    else if (itm.Content is String)
                    {
                        File.WriteAllText(itmPath, itm.Content as String);
                        itm.Content = null;
                    }
                }

                // Serialize the data to disk
                using (FileStream fs = File.Create(appletPath))
                    mfst.Save(fs);

                // For now sign with SHA256
                SHA256 sha = SHA256.Create();
                package.Meta.Hash = sha.ComputeHash(File.ReadAllBytes(appletPath));
                // HACK: Re-re-remove
                appletSection.Applets.RemoveAll(o => o.Id == package.Meta.Id);
                appletSection.Applets.Add(package.Meta.AsReference());

                ApplicationContext.Current.SetProgress(package.Meta.GetName("en"), 0.98f);

                if (ApplicationContext.Current.ConfigurationPersister.IsConfigured)
                {
                    ApplicationContext.Current.ConfigurationPersister.Save(ApplicationContext.Current.Configuration);
                }

                this.LoadApplet(mfst);
            }
            catch (Exception e)
            {
                this.m_tracer.TraceError("Error installing applet {0} : {1}", package.Meta.ToString(), e);

                // Remove
                if (File.Exists(appletPath))
                {
                    File.Delete(appletPath);
                }

                throw;
            }

            return(true);
        }
        /// <summary>
        /// Load external references
        /// </summary>
        private static void LoadReferences(MiniApplicationContext context, StringCollection references)
        {
            var appService = context.GetService <IAppletManagerService>();

            // Load references
            foreach (var appletInfo in references)// Directory.GetFiles(this.m_configuration.GetSection<AppletConfigurationSection>().AppletDirectory)) {
            {
                try
                {
                    context.m_tracer.TraceInfo("Loading applet {0}", appletInfo);

                    String appletPath = appletInfo;

                    // Is there a pak extension?
                    if (Path.GetExtension(appletPath) != ".pak")
                    {
                        appletPath += ".pak";
                    }

                    if (!Path.IsPathRooted(appletInfo))
                    {
                        appletPath = Path.Combine(Environment.CurrentDirectory, appletPath);
                    }

                    // Does the reference exist in the current directory?
                    if (!File.Exists(appletPath))
                    {
                        appletPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), Path.GetFileName(appletPath));
                    }

                    AppletPackage package = null;
                    if (!File.Exists(appletPath)) // Fetch from Repo
                    {
                        Console.WriteLine("Attempting to locate {0}", appletInfo);
                        var data = appletInfo.Split(';');
                        if (data.Length == 1)
                        {
                            package = PakMan.Repository.PackageRepositoryUtil.GetFromAny(appletInfo, null);
                        }
                        else
                        {
                            package = PakMan.Repository.PackageRepositoryUtil.GetFromAny(data[0], new Version(data[1]));
                        }
                    }
                    else
                    {
                        Console.WriteLine("Including {0}...", appletPath);
                        using (var fs = File.OpenRead(appletPath))
                        {
                            package = AppletPackage.Load(fs);
                        }
                    }

                    if (package == null)
                    {
                        throw new InvalidOperationException($"Cannot find reference {appletInfo}");
                    }

                    if (package is AppletSolution)
                    {
                        // Look for other applets with this
                        foreach (var itm in (package as AppletSolution).Include)
                        {
                            context.m_tracer.TraceInfo("Loading solution content project {0}", itm.Meta.Id);
                            appService.LoadApplet(itm.Unpack());
                        }
                    }
                    else
                    {
                        context.m_tracer.TraceInfo("Loading {0} v{1}", package.Meta.Id, package.Meta.Version);
                        // Is this applet in the allowed applets
                        appService.LoadApplet(package.Unpack());
                    }
                }
                catch (Exception e)
                {
                    context.m_tracer.TraceError("Loading applet {0} failed: {1}", appletInfo, e.ToString());
                    throw;
                }
            }
        }
示例#6
0
        /// <summary>
        /// Verify package signature
        /// </summary>
        private bool VerifyPackage(AppletPackage package)
        {
            byte[] verifyBytes = package.Manifest;
            // First check: Hash - Make sure the HASH is ok
            if (package is AppletSolution)
            {
                verifyBytes = (package as AppletSolution).Include.SelectMany(o => o.Manifest).ToArray();
                if (BitConverter.ToString(SHA256.Create().ComputeHash(verifyBytes)) != BitConverter.ToString(package.Meta.Hash))
                {
                    throw new InvalidOperationException($"Package contents of {package.Meta.Id} appear to be corrupt!");
                }
            }
            else if (BitConverter.ToString(SHA256.Create().ComputeHash(package.Manifest)) != BitConverter.ToString(package.Meta.Hash))
            {
                throw new InvalidOperationException($"Package contents of {package.Meta.Id} appear to be corrupt!");
            }

            if (package.Meta.Signature != null)
            {
                this.m_tracer.TraceInfo("Will verify package {0}", package.Meta.Id.ToString());

                // Get the public key
                var x509Store = new X509Store(StoreName.TrustedPublisher, StoreLocation.LocalMachine);
                try
                {
                    x509Store.Open(OpenFlags.ReadOnly);
                    var cert = x509Store.Certificates.Find(X509FindType.FindByThumbprint, package.Meta.PublicKeyToken, false);

                    if (cert.Count == 0)
                    {
                        if (package.PublicKey != null)
                        {
                            // Embedded cert and trusted CA
                            X509Certificate2 embCert = new X509Certificate2(package.PublicKey);

                            // Not explicitly trusted to we need to build a chain
                            if (!this.m_caIssuerCert.Subject.Equals(embCert.Issuer) && !this.m_configuration.TrustedPublishers.Contains(embCert.Thumbprint))
                            {
                                // Build the certificate chain
                                var embChain = new X509Chain();
                                embChain.Build(embCert);

                                // Validate the chain elements if possible
                                bool isTrusted = false;
                                foreach (var itm in embChain.ChainElements)
                                {
                                    isTrusted |= this.m_configuration.TrustedPublishers.Contains(itm.Certificate.Thumbprint);
                                }

                                if (!isTrusted || embChain.ChainStatus.Any(o => o.Status != X509ChainStatusFlags.RevocationStatusUnknown) && !this.m_configuration.TrustedPublishers.Contains(embCert.Issuer))
                                {
                                    throw new SecurityException($"Cannot verify identity of publisher {embCert.Subject}");
                                }
                                else
                                {
                                    cert = new X509Certificate2Collection(embCert);
                                }
                            }
                            else
                            {
                                cert = new X509Certificate2Collection(embCert);
                            }
                        }
                        else
                        {
                            throw new SecurityException($"Cannot find public key of publisher information for {package.Meta.PublicKeyToken} or the local certificate is invalid");
                        }
                    }

                    // Verify signature
                    RSACryptoServiceProvider rsa = cert[0].PublicKey.Key as RSACryptoServiceProvider;

                    var retVal = rsa.VerifyData(verifyBytes, CryptoConfig.MapNameToOID("SHA1"), package.Meta.Signature);

                    // Verify timestamp
                    var timestamp = package.Unpack().Info.TimeStamp;
                    if (timestamp > DateTime.Now)
                    {
                        throw new SecurityException($"Package {package.Meta.Id} was published in the future! Something's fishy, refusing to load");
                    }
                    else if (cert[0].NotAfter <timestamp || cert[0].NotBefore> timestamp)
                    {
                        throw new SecurityException($"Cannot find public key of publisher information for {package.Meta.PublicKeyToken} or the local certificate is invalid");
                    }

                    if (retVal == true)
                    {
                        this.m_tracer.TraceEvent(EventLevel.Informational, "SUCCESSFULLY VALIDATED: {0} v.{1}\r\n" +
                                                 "\tKEY TOKEN: {2}\r\n" +
                                                 "\tSIGNED BY: {3}\r\n" +
                                                 "\tVALIDITY: {4:yyyy-MMM-dd} - {5:yyyy-MMM-dd}\r\n" +
                                                 "\tISSUER: {6}",
                                                 package.Meta.Id, package.Meta.Version, cert[0].Thumbprint, cert[0].Subject, cert[0].NotBefore, cert[0].NotAfter, cert[0].Issuer);
                    }
                    else
                    {
                        this.m_tracer.TraceEvent(EventLevel.Critical, ">> SECURITY ALERT : {0} v.{1} <<\r\n" +
                                                 "\tPACKAGE HAS BEEN TAMPERED WITH\r\n" +
                                                 "\tKEY TOKEN (CLAIMED): {2}\r\n" +
                                                 "\tSIGNED BY  (CLAIMED): {3}\r\n" +
                                                 "\tVALIDITY: {4:yyyy-MMM-dd} - {5:yyyy-MMM-dd}\r\n" +
                                                 "\tISSUER: {6}\r\n\tSERVICE WILL HALT",
                                                 package.Meta.Id, package.Meta.Version, cert[0].Thumbprint, cert[0].Subject, cert[0].NotBefore, cert[0].NotAfter, cert[0].Issuer);
                    }
                    return(retVal);
                }
                finally
                {
                    x509Store.Close();
                }
            }
            else if (this.m_configuration.AllowUnsignedApplets)
            {
                this.m_tracer.TraceEvent(EventLevel.Warning, "Package {0} v.{1} (publisher: {2}) is not signed. To prevent unsigned applets from being installed disable the configuration option", package.Meta.Id, package.Meta.Version, package.Meta.Author);
                return(true);
            }
            else
            {
                this.m_tracer.TraceEvent(EventLevel.Critical, "Package {0} v.{1} (publisher: {2}) is not signed and cannot be installed", package.Meta.Id, package.Meta.Version, package.Meta.Author);
                return(false);
            }
        }
示例#7
0
        /// <summary>
        /// Performs an installation
        /// </summary>
        public bool Install(AppletPackage package, bool isUpgrade, AppletSolution owner)
        {
            this.m_tracer.TraceInfo("Installing {0}", package.Meta);


            var appletScope = owner?.Meta.Id ?? String.Empty;

            // TODO: Verify package hash / signature
            if (!this.VerifyPackage(package))
            {
                throw new SecurityException("Applet failed validation");
            }
            else if (!this.m_appletCollection[appletScope].VerifyDependencies(package.Meta))
            {
                this.m_tracer.TraceWarning($"Applet {package.Meta} depends on : [{String.Join(", ", package.Meta.Dependencies.Select(o => o.ToString()))}] which are missing or incompatible");
            }

            // Save the applet
            var appletDir = this.m_configuration.AppletDirectory;

            if (!Path.IsPathRooted(appletDir))
            {
                appletDir = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), this.m_configuration.AppletDirectory);
            }
            if (owner != null)
            {
                appletDir = Path.Combine(appletDir, owner.Meta.Id);
            }
            if (!Directory.Exists(appletDir))
            {
                Directory.CreateDirectory(appletDir);
            }

            // Install
            var pakFile = Path.Combine(appletDir, package.Meta.Id + ".pak");

            if (this.m_appletCollection[appletScope].Any(o => o.Info.Id == package.Meta.Id) && File.Exists(pakFile) && !isUpgrade)
            {
                throw new InvalidOperationException($"Cannot replace {package.Meta} unless upgrade is specifically specified");
            }

            using (var fs = File.Create(pakFile))
            {
                package.Save(fs);
            }

            lock (this.m_fileDictionary)
                if (!this.m_fileDictionary.ContainsKey($"{appletScope}{package.Meta.Id}"))
                {
                    this.m_fileDictionary.Add($"{appletScope}{package.Meta.Id}", pakFile);
                }

            var pkg = package.Unpack();

            // remove the package from the collection if this is an upgrade
            if (isUpgrade)
            {
                this.m_appletCollection[appletScope].Remove(pkg);
            }

            this.m_appletCollection[appletScope].Add(pkg);

            // We want to install the templates & protocols into the DB
            this.m_tracer.TraceInfo("Installing templates...");

            // Install templates
            var idp = ApplicationServiceContext.Current.GetService <ITemplateDefinitionRepositoryService>();

            if (idp != null)
            {
                foreach (var itm in pkg.Templates)
                {
                    if (idp.GetTemplateDefinition(itm.Mnemonic) == null)
                    {
                        this.m_tracer.TraceInfo("Installing {0}...", itm.Mnemonic);
                        idp.Insert(new TemplateDefinition()
                        {
                            Oid         = itm.Oid,
                            Mnemonic    = itm.Mnemonic,
                            Description = itm.Description,
                            Name        = itm.Mnemonic
                        });
                    }
                }
            }

            AppletCollection.ClearCaches();

            return(true);
        }