Specifies how to configure an application during installation.
        /// <summary>
        /// Creates a new certificate for application.
        /// </summary>
        /// <param name="application">The application.</param>
        private static async Task <X509Certificate2> CreateCertificateForApplication(InstalledApplication application)
        {
            // build list of domains.
            List <string> domains = new List <string>();

            if (application.BaseAddresses != null)
            {
                foreach (string baseAddress in application.BaseAddresses)
                {
                    Uri uri = Utils.ParseUri(baseAddress);

                    if (uri != null)
                    {
                        string domain = uri.DnsSafeHost;

                        if (String.Compare(domain, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            domain = Utils.GetHostName();
                        }

                        if (!Utils.FindStringIgnoreCase(domains, domain))
                        {
                            domains.Add(domain);
                        }
                    }
                }
            }

            // must at least of the localhost.
            if (domains.Count == 0)
            {
                domains.Add(Utils.GetHostName());
            }

            // create the certificate.
            X509Certificate2 certificate = await Opc.Ua.CertificateFactory.CreateCertificate(
                application.ApplicationCertificate.StoreType,
                application.ApplicationCertificate.StorePath,
                application.ApplicationUri,
                application.ApplicationName,
                Utils.Format("CN={0}/DC={1}", application.ApplicationName, domains[0]),
                domains,
                1024,
                300);

            CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate);

            return(await applicationCertificate.LoadPrivateKey(null));
        }
        /// <summary>
        /// Uninstalls a UA application.
        /// </summary>
        public static async Task UninstallApplication(InstalledApplication application)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false);

            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);
            string   applicationName    = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length - 4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml",
                    executableFileInfo.DirectoryName,
                    applicationName);
            }

            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false);

            if (configurationFile != null)
            {
                // load the current configuration.
                Opc.Ua.Security.SecuredApplication security = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);

                // delete the application certificates.
                if (application.DeleteCertificatesOnUninstall)
                {
                    CertificateIdentifier id = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(security.ApplicationCertificate);

                    // delete public key from trusted peers certificate store.
                    try
                    {
                        CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(security.TrustedCertificateStore);

                        using (ICertificateStore store = certificateStore.OpenStore())
                        {
                            X509Certificate2Collection peerCertificates = await store.FindByThumbprint(id.Thumbprint);

                            if (peerCertificates.Count > 0)
                            {
                                await store.Delete(peerCertificates[0].Thumbprint);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }

                    // delete private key from application certificate store.
                    try
                    {
                        using (ICertificateStore store = id.OpenStore())
                        {
                            await store.Delete(id.Thumbprint);
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }

                    // permentently delete any UA defined stores if they are now empty.
                    try
                    {
                        WindowsCertificateStore store = new WindowsCertificateStore();
                        await store.Open("LocalMachine\\UA Applications");

                        X509Certificate2Collection collection = await store.Enumerate();

                        if (collection.Count == 0)
                        {
                            store.PermanentlyDeleteStore();
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }
                }

                // remove the permissions for the HTTP endpoints used by the application.
                if (application.BaseAddresses != null && application.BaseAddresses.Count > 0)
                {
                    List <ApplicationAccessRule> noRules = new List <ApplicationAccessRule>();

                    for (int ii = 0; ii < application.BaseAddresses.Count; ii++)
                    {
                        Uri url = Utils.ParseUri(application.BaseAddresses[ii]);

                        if (url != null)
                        {
                            try
                            {
                                HttpAccessRule.SetAccessRules(url, noRules, true);
                                Utils.Trace("Removed HTTP access rules for URL: {0}", url);
                            }
                            catch (Exception e)
                            {
                                Utils.Trace("Could not remove HTTP access rules for URL: {0}. Error={1}", url, e.Message);
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Installs a UA application.
        /// </summary>
        public static async Task InstallApplication(
            InstalledApplication application,
            bool autostart,
            bool configureFirewall)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false);

            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);

            string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length - 4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml",
                    executableFileInfo.DirectoryName,
                    applicationName);
            }

            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false);

            // create a new file if one does not exist.
            bool useExisting = true;

            if (configurationFile == null)
            {
                configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true);
                useExisting       = false;
            }

            // create the default configuration file.

            if (useExisting)
            {
                try
                {
                    Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);

                    // copy current settings
                    application.ApplicationType             = existingSettings.ApplicationType;
                    application.BaseAddresses               = existingSettings.BaseAddresses;
                    application.ApplicationCertificate      = existingSettings.ApplicationCertificate;
                    application.ApplicationName             = existingSettings.ApplicationName;
                    application.ProductName                 = existingSettings.ProductName;
                    application.RejectedCertificatesStore   = existingSettings.RejectedCertificatesStore;
                    application.TrustedCertificateStore     = existingSettings.TrustedCertificateStore;
                    application.TrustedCertificates         = existingSettings.TrustedCertificates;
                    application.IssuerCertificateStore      = existingSettings.IssuerCertificateStore;
                    application.IssuerCertificates          = application.IssuerCertificates;
                    application.UseDefaultCertificateStores = false;
                }
                catch (Exception e)
                {
                    useExisting = false;
                    Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile);
                    File.Copy(configurationFile, configurationFile + ".bak", true);
                }
            }

            // create the configuration file from the default.
            if (!useExisting)
            {
                try
                {
                    string installationFile = Utils.Format(
                        "{0}\\Install\\{1}.Config.xml",
                        executableFileInfo.Directory.Parent.FullName,
                        applicationName);

                    if (!File.Exists(installationFile))
                    {
                        Utils.Trace("Could not find default configuation at: {0}", installationFile);
                    }

                    File.Copy(installationFile, configurationFile, true);
                    Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message);
                }
            }

            // create a default application name.
            if (String.IsNullOrEmpty(application.ApplicationName))
            {
                application.ApplicationName = applicationName;
            }

            // create a default product name.
            if (String.IsNullOrEmpty(application.ProductName))
            {
                application.ProductName = application.ApplicationName;
            }

            // create a default uri.
            if (String.IsNullOrEmpty(application.ApplicationUri))
            {
                application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid());
            }

            // make the uri specify the local machine.
            application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri);

            // set a default application store.
            if (application.ApplicationCertificate == null)
            {
                application.ApplicationCertificate           = new Opc.Ua.Security.CertificateIdentifier();
                application.ApplicationCertificate.StoreType = Utils.DefaultStoreType;
                application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }

            if (application.UseDefaultCertificateStores)
            {
                if (application.IssuerCertificateStore == null)
                {
                    application.IssuerCertificateStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                }

                if (application.TrustedCertificateStore == null)
                {
                    application.TrustedCertificateStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                }

                try
                {
                    Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e);
                }

                if (application.RejectedCertificatesStore == null)
                {
                    application.RejectedCertificatesStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory;
                    application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates";

                    StringBuilder buffer = new StringBuilder();

                    buffer.Append(ApplicationData.Current.LocalFolder.Path);
                    buffer.Append("\\OPC Foundation");
                    buffer.Append("\\RejectedCertificates");

                    string folderPath = buffer.ToString();

                    if (!Directory.Exists(folderPath))
                    {
                        Directory.CreateDirectory(folderPath);
                    }
                }
            }

            // check for valid certificate (discard invalid certificates).
            CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate);
            X509Certificate2      certificate            = await applicationCertificate.Find(true);

            if (certificate == null)
            {
                certificate = await applicationCertificate.Find(false);

                if (certificate != null)
                {
                    Utils.Trace(
                        "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}",
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
                else
                {
                    Utils.Trace(
                        "Existing certificate could not be found: Store={0}, Certificate={1}",
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
            }

            // check if no certificate exists.
            if (certificate == null)
            {
                certificate = await CreateCertificateForApplication(application);
            }

            // ensure the application certificate is in the trusted peers store.
            try
            {
                CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore);

                using (ICertificateStore store = certificateStore.OpenStore())
                {
                    X509Certificate2Collection peerCertificates = await store.FindByThumbprint(certificate.Thumbprint);

                    if (peerCertificates.Count == 0)
                    {
                        await store.Add(new X509Certificate2(certificate.RawData));
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(
                    "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}",
                    certificate.Subject,
                    application.TrustedCertificateStore,
                    e.Message);
            }

            // update configuration file location.
            UpdateConfigurationLocation(executableFile, configurationFile);

            // update configuration file.
            new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application);

            ApplicationAccessRuleCollection accessRules = application.AccessRules;
            bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0;

            // add the default access rules.
            if (noRulesDefined)
            {
                ApplicationAccessRule rule = new ApplicationAccessRule();

                rule.IdentityName = WellKnownSids.Administrators;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Configure;

                accessRules.Add(rule);

                rule = new ApplicationAccessRule();

                rule.IdentityName = WellKnownSids.Users;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Update;

                accessRules.Add(rule);
            }

            // ensure the service account has priviledges.
            if (application.InstallAsService)
            {
                // check if a specific account is assigned.
                AccountInfo accountInfo = null;

                if (!String.IsNullOrEmpty(application.ServiceUserName))
                {
                    accountInfo = AccountInfo.Create(application.ServiceUserName);
                }

                // choose a built-in service account.
                if (accountInfo == null)
                {
                    accountInfo = AccountInfo.Create(WellKnownSids.NetworkService);

                    if (accountInfo == null)
                    {
                        accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem);
                    }
                }

                ApplicationAccessRule rule = new ApplicationAccessRule();

                rule.IdentityName = accountInfo.ToString();
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Run;

                accessRules.Add(rule);
            }

            // set the permissions for the HTTP endpoints used by the application.
            if (configureFirewall && application.BaseAddresses != null && application.BaseAddresses.Count > 0)
            {
                for (int ii = 0; ii < application.BaseAddresses.Count; ii++)
                {
                    Uri url = Utils.ParseUri(application.BaseAddresses[ii]);

                    if (url != null)
                    {
                        try
                        {
                            HttpAccessRule.SetAccessRules(url, accessRules, true);
                            Utils.Trace("Added HTTP access rules for URL: {0}", url);
                        }
                        catch (Exception e)
                        {
                            Utils.Trace("Could not set HTTP access rules for URL: {0}. Error={1}", url, e.Message);

                            for (int jj = 0; jj < accessRules.Count; jj++)
                            {
                                ApplicationAccessRule rule = accessRules[jj];

                                Utils.Trace(
                                    (int)Utils.TraceMasks.Error,
                                    "IdentityName={0}, Right={1}, RuleType={2}",
                                    rule.IdentityName,
                                    rule.Right,
                                    rule.RuleType);
                            }
                        }
                    }
                }
            }

            // set permissions on the local certificate store.
            SetCertificatePermissions(
                application,
                applicationCertificate,
                accessRules,
                false);

            // set permissions on the local certificate store.
            if (application.RejectedCertificatesStore != null)
            {
                // need to grant full control to certificates in the RejectedCertificatesStore.
                foreach (ApplicationAccessRule rule in accessRules)
                {
                    if (rule.RuleType == AccessControlType.Allow)
                    {
                        rule.Right = ApplicationAccessRight.Configure;
                    }
                }

                CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore);

                using (ICertificateStore store = rejectedCertificates.OpenStore())
                {
                    if (store.SupportsAccessControl)
                    {
                        store.SetAccessRules(accessRules, false);
                    }
                }
            }
        }
        /// <summary>
        /// Uninstalls a UA application.
        /// </summary>
        public static async Task UninstallApplication(InstalledApplication application)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false);

            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);
            string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml", 
                    executableFileInfo.DirectoryName, 
                    applicationName);                
            }
            
            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); 
            
            if (configurationFile != null)
            {
                // load the current configuration.
                Opc.Ua.Security.SecuredApplication security = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);

                // delete the application certificates.
                if (application.DeleteCertificatesOnUninstall)
                {
                    CertificateIdentifier id = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(security.ApplicationCertificate);
                                        
                    // delete public key from trusted peers certificate store.
                    try
                    {
                        CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(security.TrustedCertificateStore);

                        using (ICertificateStore store = certificateStore.OpenStore())
                        {
                            X509Certificate2Collection peerCertificates = await store.FindByThumbprint(id.Thumbprint);

                            if (peerCertificates.Count > 0)
                            {
                                await store.Delete(peerCertificates[0].Thumbprint);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }    

                    // delete private key from application certificate store.
                    try
                    {
                        using (ICertificateStore store = id.OpenStore())
                        {
                            await store.Delete(id.Thumbprint);
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }
                    
                    // permentently delete any UA defined stores if they are now empty.
                    try
                    {
                        WindowsCertificateStore store = new WindowsCertificateStore();
                        await store.Open("LocalMachine\\UA Applications");

                        X509Certificate2Collection collection = await store.Enumerate();
                        if (collection.Count == 0)
                        {
                            store.PermanentlyDeleteStore();
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }
                }
            }
        }
        /// <summary>
        /// Sets the defaults for all fields.
        /// </summary>
        /// <param name="application">The application.</param>
        private static void SetDefaults(InstalledApplication application)
        {
            // create a default product name.
            if (String.IsNullOrEmpty(application.ProductName))
            {
                application.ProductName = application.ApplicationName;
            }

            // create a default uri.
            if (String.IsNullOrEmpty(application.ApplicationUri))
            {
                application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", application.ApplicationName, Guid.NewGuid());
            }

            // make the uri specify the local machine.
            application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri);

            // set a default application store.
            if (application.ApplicationCertificate == null)
            {
                application.ApplicationCertificate             = new Opc.Ua.Security.CertificateIdentifier();
                application.ApplicationCertificate.StoreType   = Utils.DefaultStoreType;
                application.ApplicationCertificate.StorePath   = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                application.ApplicationCertificate.SubjectName = application.ApplicationName;
            }

            if (application.IssuerCertificateStore == null)
            {
                application.IssuerCertificateStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType;
                application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }

            if (application.TrustedCertificateStore == null)
            {
                application.TrustedCertificateStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType;
                application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }

            try
            {
                Utils.GetAbsoluteDirectoryPath(application.ApplicationCertificate.StorePath, true, true, true);
            }
            catch (Exception e)
            {
                Utils.Trace("Could not access the machine directory: {0} '{1}'", application.ApplicationCertificate.StorePath, e);
            }

            if (application.RejectedCertificatesStore == null)
            {
                application.RejectedCertificatesStore           = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory;
                application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates";
            }

            if (application.RejectedCertificatesStore.StoreType == CertificateStoreType.Directory)
            {
                try
                {
                    Utils.GetAbsoluteDirectoryPath(application.RejectedCertificatesStore.StorePath, true, true, true);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not access rejected certificates directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e);
                }
            }
        }
        /// <summary>
        /// Creates a new certificate for application.
        /// </summary>
        /// <param name="application">The application.</param>
        private static async Task<X509Certificate2> CreateCertificateForApplication(InstalledApplication application)
        {
            // build list of domains.
            List<string> domains = new List<string>();

            if (application.BaseAddresses != null)
            {
                foreach (string baseAddress in application.BaseAddresses)
                {
                    Uri uri = Utils.ParseUri(baseAddress);

                    if (uri != null)
                    {
                        string domain = uri.DnsSafeHost;

                        if (String.Compare(domain, "localhost", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            domain = Utils.GetHostName();
                        }

                        if (!Utils.FindStringIgnoreCase(domains, domain))
                        {
                            domains.Add(domain);
                        }
                    }
                }
            }

            // must at least of the localhost.
            if (domains.Count == 0)
            {
                domains.Add(Utils.GetHostName());
            }

            // create the certificate.
            X509Certificate2 certificate = await Opc.Ua.CertificateFactory.CreateCertificate(
                application.ApplicationCertificate.StoreType,
                application.ApplicationCertificate.StorePath,
                application.ApplicationUri,
                application.ApplicationName,
                Utils.Format("CN={0}/DC={1}", application.ApplicationName, domains[0]),
                domains,
                1024,
                300);

            CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate);
            return await applicationCertificate.LoadPrivateKey(null);
        }
        /// <summary>
        /// Installs a UA application.
        /// </summary>
        public static async Task InstallApplication(
            InstalledApplication application,
            bool autostart,
            bool configureFirewall)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false);
            
            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);

            string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml", 
                    executableFileInfo.DirectoryName, 
                    applicationName);                
            }

            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false);
            
            // create a new file if one does not exist.
            bool useExisting = true;

            if (configurationFile == null)
            {
                configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true);
                useExisting = false;
            }

            // create the default configuration file.

            if (useExisting)
            {
                try
                {
                    Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);
                    
                    // copy current settings
                    application.ApplicationType = existingSettings.ApplicationType;
                    application.BaseAddresses = existingSettings.BaseAddresses;
                    application.ApplicationCertificate = existingSettings.ApplicationCertificate;
                    application.ApplicationName = existingSettings.ApplicationName;
                    application.ProductName = existingSettings.ProductName;
                    application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore;
                    application.TrustedCertificateStore = existingSettings.TrustedCertificateStore;
                    application.TrustedCertificates = existingSettings.TrustedCertificates;
                    application.IssuerCertificateStore = existingSettings.IssuerCertificateStore;
                    application.IssuerCertificates = application.IssuerCertificates;
                    application.UseDefaultCertificateStores = false;
                }
                catch (Exception e)
                {
                    useExisting = false;
                    Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile);
                    File.Copy(configurationFile, configurationFile + ".bak", true);
                }
            }
            
            // create the configuration file from the default.
            if (!useExisting)
            {
                try
                {
                    string installationFile = Utils.Format(
                        "{0}\\Install\\{1}.Config.xml", 
                        executableFileInfo.Directory.Parent.FullName, 
                        applicationName);
                    
                    if (!File.Exists(installationFile))
                    {
                        Utils.Trace("Could not find default configuation at: {0}", installationFile);
                    }
                        
                    File.Copy(installationFile, configurationFile, true);
                    Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message);
                }
            }

            // create a default application name.
            if (String.IsNullOrEmpty(application.ApplicationName))
            {
                application.ApplicationName = applicationName;
            }
                        
            // create a default product name.
            if (String.IsNullOrEmpty(application.ProductName))
            {
                application.ProductName = application.ApplicationName;
            }

            // create a default uri.
            if (String.IsNullOrEmpty(application.ApplicationUri))
            {
                application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid());
            }
            
            // make the uri specify the local machine.
            application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri);

            // set a default application store.
            if (application.ApplicationCertificate == null)
            {
                application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier();
                application.ApplicationCertificate.StoreType = Utils.DefaultStoreType;
                application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }
            
            if (application.UseDefaultCertificateStores)
            {
                if (application.IssuerCertificateStore == null)
                {
                    application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                }

                if (application.TrustedCertificateStore == null)
                {
                    application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                }
                
                try
                {
                    Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e);
                }

                if (application.RejectedCertificatesStore == null)
                {
                    application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory;
                    application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates";

                    StringBuilder buffer = new StringBuilder();

                    buffer.Append(ApplicationData.Current.LocalFolder.Path);
                    buffer.Append("\\OPC Foundation");
                    buffer.Append("\\RejectedCertificates");

                    string folderPath = buffer.ToString();

                    if (!Directory.Exists(folderPath))
                    {
                        Directory.CreateDirectory(folderPath);
                    }
                }
            }
            
            // check for valid certificate (discard invalid certificates).
            CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); 
            X509Certificate2 certificate = await applicationCertificate.Find(true);

            if (certificate == null)
            {
                certificate = await applicationCertificate.Find(false);

                if (certificate != null)
                {
                    Utils.Trace(
                        "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", 
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
                else
                {            
                    Utils.Trace(
                        "Existing certificate could not be found: Store={0}, Certificate={1}", 
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
            }

            // check if no certificate exists.
            if (certificate == null)
            {
                certificate = await CreateCertificateForApplication(application);
            }

            // ensure the application certificate is in the trusted peers store.
            try
            {
                CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore);

                using (ICertificateStore store = certificateStore.OpenStore())
                {
                    X509Certificate2Collection peerCertificates = await store.FindByThumbprint(certificate.Thumbprint);

                    if (peerCertificates.Count == 0)
                    {
                        await store.Add(new X509Certificate2(certificate.RawData));
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(
                    "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", 
                    certificate.Subject,
                    application.TrustedCertificateStore, 
                    e.Message);
            }

            // update configuration file location.
            UpdateConfigurationLocation(executableFile, configurationFile);

            // update configuration file.
            new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application);
            
            ApplicationAccessRuleCollection accessRules = application.AccessRules;
            bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0;
            
            // add the default access rules.
            if (noRulesDefined)
            {
                ApplicationAccessRule rule = new ApplicationAccessRule();
                
                rule.IdentityName = WellKnownSids.Administrators;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Configure;

                accessRules.Add(rule);

                rule = new ApplicationAccessRule();
                
                rule.IdentityName = WellKnownSids.Users;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Update;

                accessRules.Add(rule);
            }
             
            // ensure the service account has priviledges.
            if (application.InstallAsService)
            {
                // check if a specific account is assigned.
                AccountInfo accountInfo = null;

                if (!String.IsNullOrEmpty(application.ServiceUserName))
                {
                    accountInfo = AccountInfo.Create(application.ServiceUserName);
                }

                // choose a built-in service account.
                if (accountInfo == null)
                {
                    accountInfo = AccountInfo.Create(WellKnownSids.NetworkService);
                    
                    if (accountInfo == null)
                    {
                        accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem);
                    }
                }

                ApplicationAccessRule rule = new ApplicationAccessRule();
                
                rule.IdentityName = accountInfo.ToString();
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Run;

                accessRules.Add(rule);
            }

            // set permissions on the local certificate store.
            SetCertificatePermissions(
                application,
                applicationCertificate, 
                accessRules, 
                false);

           // set permissions on the local certificate store.
            if (application.RejectedCertificatesStore != null)
            {
                // need to grant full control to certificates in the RejectedCertificatesStore.
                foreach (ApplicationAccessRule rule in accessRules)
                {
                    if (rule.RuleType == AccessControlType.Allow)
                    {
                        rule.Right = ApplicationAccessRight.Configure;
                    }
                }

                CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore);

                using (ICertificateStore store = rejectedCertificates.OpenStore())
                {
                    if (store.SupportsAccessControl)
                    {
                        store.SetAccessRules(accessRules, false);
                    }
                }
            }

            
        }
        /// <summary>
        /// Sets the defaults for all fields.
        /// </summary>
        /// <param name="application">The application.</param>
        private static void SetDefaults(InstalledApplication application)
        { 
            // create a default product name.
            if (String.IsNullOrEmpty(application.ProductName))
            {
                application.ProductName = application.ApplicationName;
            }

            // create a default uri.
            if (String.IsNullOrEmpty(application.ApplicationUri))
            {
                application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", application.ApplicationName, Guid.NewGuid());
            }

            // make the uri specify the local machine.
            application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri);

            // set a default application store.
            if (application.ApplicationCertificate == null)
            {
                application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier();
                application.ApplicationCertificate.StoreType = Utils.DefaultStoreType;
                application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
                application.ApplicationCertificate.SubjectName = application.ApplicationName;
            }

            if (application.IssuerCertificateStore == null)
            {
                application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType;
                application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }

            if (application.TrustedCertificateStore == null)
            {
                application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType;
                application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault";
            }

            try
            {
                Utils.GetAbsoluteDirectoryPath(application.ApplicationCertificate.StorePath, true, true, true);
            }
            catch (Exception e)
            {
                Utils.Trace("Could not access the machine directory: {0} '{1}'", application.ApplicationCertificate.StorePath, e);
            }

            if (application.RejectedCertificatesStore == null)
            {
                application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory;
                application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates";
            }

            if (application.RejectedCertificatesStore.StoreType == CertificateStoreType.Directory)
            {
                try
                {
                    Utils.GetAbsoluteDirectoryPath(application.RejectedCertificatesStore.StorePath, true, true, true);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not access rejected certificates directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e);
                }
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Installs a UA application.
        /// </summary>
        public static void InstallApplication(
            InstalledApplication application, 
            bool autostart, 
            bool configureFirewall)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false);
            
            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);

            string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml", 
                    executableFileInfo.DirectoryName, 
                    applicationName);                
            }

            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false);
            
            // create a new file if one does not exist.
            bool useExisting = true;

            if (configurationFile == null)
            {
                configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true);
                useExisting = false;
            }

            // create the default configuration file.

            if (useExisting)
            {
                try
                {
                    Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);
                    
                    // copy current settings
                    application.ApplicationType = existingSettings.ApplicationType;
                    application.BaseAddresses = existingSettings.BaseAddresses;
                    application.ApplicationCertificate = existingSettings.ApplicationCertificate;
                    application.ApplicationName = existingSettings.ApplicationName;
                    application.ProductName = existingSettings.ProductName;
                    application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore;
                    application.TrustedCertificateStore = existingSettings.TrustedCertificateStore;
                    application.TrustedCertificates = existingSettings.TrustedCertificates;
                    application.IssuerCertificateStore = existingSettings.IssuerCertificateStore;
                    application.IssuerCertificates = application.IssuerCertificates;
                    application.UseDefaultCertificateStores = false;
                }
                catch (Exception e)
                {
                    useExisting = false;
                    Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile);
                    File.Copy(configurationFile, configurationFile + ".bak", true);
                }
            }
            
            // create the configuration file from the default.
            if (!useExisting)
            {
                try
                {
                    string installationFile = Utils.Format(
                        "{0}\\Install\\{1}.Config.xml", 
                        executableFileInfo.Directory.Parent.FullName, 
                        applicationName);
                    
                    if (!File.Exists(installationFile))
                    {
                        Utils.Trace("Could not find default configuation at: {0}", installationFile);
                    }
                        
                    File.Copy(installationFile, configurationFile, true);
                    Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message);
                }
            }

            // create a default application name.
            if (String.IsNullOrEmpty(application.ApplicationName))
            {
                application.ApplicationName = applicationName;
            }
                        
            // create a default product name.
            if (String.IsNullOrEmpty(application.ProductName))
            {
                application.ProductName = application.ApplicationName;
            }

            // create a default uri.
            if (String.IsNullOrEmpty(application.ApplicationUri))
            {
                application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid());
            }
            
            // make the uri specify the local machine.
            application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri);

            // set a default application store.
            if (application.ApplicationCertificate == null)
            {
                application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier();
                application.ApplicationCertificate.StoreType = Utils.DefaultStoreType;
                application.ApplicationCertificate.StorePath = Utils.DefaultStorePath;
            }
            
            if (application.UseDefaultCertificateStores)
            {
                if (application.IssuerCertificateStore == null)
                {
                    application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.IssuerCertificateStore.StorePath = Utils.DefaultStorePath;
                }

                if (application.TrustedCertificateStore == null)
                {
                    application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType;
                    application.TrustedCertificateStore.StorePath = Utils.DefaultStorePath;
                }
                
                try
                {
                    Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true);
                }
                catch (Exception e)
                {
                    Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e);
                }

                if (application.RejectedCertificatesStore == null)
                {
                    application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                    application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory;
                    application.RejectedCertificatesStore.StorePath = "%CommonApplicationData%\\OPC Foundation\\CertificateStores\\RejectedCertificates";

                    StringBuilder buffer = new StringBuilder();

                    buffer.Append(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
                    buffer.Append("\\OPC Foundation");
                    buffer.Append("\\RejectedCertificates");

                    string folderPath = buffer.ToString();

                    if (!Directory.Exists(folderPath))
                    {
                        Directory.CreateDirectory(folderPath);
                    }
                }
            }


            // check for valid certificate (discard invalid certificates).
            CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); 
            X509Certificate2 certificate = applicationCertificate.Find(true);

            if (certificate == null)
            {
                certificate = applicationCertificate.Find(false);

                if (certificate != null)
                {
                    Utils.Trace(
                        "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", 
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
                else
                {            
                    Utils.Trace(
                        "Existing certificate could not be found: Store={0}, Certificate={1}", 
                        application.ApplicationCertificate.StorePath,
                        application.ApplicationCertificate);
                }
            }
            
            // check if no certificate exists.
            if (certificate == null)
            {
                certificate = CreateCertificateForApplication(application);
            }
            
            // ensure the application certificate is in the trusted peers store.
            try
            {
                CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore);

                using (ICertificateStore store = certificateStore.OpenStore())
                {
                    X509Certificate2 peerCertificate = store.FindByThumbprint(certificate.Thumbprint);
 
                    if (peerCertificate == null)
                    {
                        store.Add(new X509Certificate2(certificate.GetRawCertData()));
                    }
                }
            }
            catch (Exception e)
            {
                Utils.Trace(
                    "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", 
                    certificate.Subject,
                    application.TrustedCertificateStore, 
                    e.Message);
            }

            // locally register the certficate OIDs.
            if (application.LocallyRegisterOIDs)
            {
                try
                {
                    LocallyRegisterCertificateOIDs(certificate);
                }
                catch (Exception e)
                {
                    Utils.Trace(
                        "Could not register OIDs used for certificate '{0}'. Error={1}", 
                        certificate.Subject, 
                        e.Message);
                }
            }

            // update configuration file location.
            UpdateConfigurationLocation(executableFile, configurationFile);

            // update configuration file.
            new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application);
            
            // configure firewall.
            if (configureFirewall && application.ConfigureFirewall)
            {
                if (application.BaseAddresses != null && application.BaseAddresses.Count > 0)
                {
                    try
                    {
                        SetFirewallAccess(application, executableFile);
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not set firewall access for executable: {0}. Error={1}", executableFile, e.Message);
                    }
                }
            }

            ApplicationAccessRuleCollection accessRules = application.AccessRules;
            bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0;
            
            // add the default access rules.
            if (noRulesDefined)
            {
                ApplicationAccessRule rule = new ApplicationAccessRule();
                
                rule.IdentityName = WellKnownSids.Administrators;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Configure;

                accessRules.Add(rule);

                rule = new ApplicationAccessRule();
                
                rule.IdentityName = WellKnownSids.Users;
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Update;

                accessRules.Add(rule);
            }
             
            // ensure the service account has priviledges.
            if (application.InstallAsService)
            {
                // check if a specific account is assigned.
                AccountInfo accountInfo = null;

                if (!String.IsNullOrEmpty(application.ServiceUserName))
                {
                    accountInfo = AccountInfo.Create(application.ServiceUserName);
                }

                // choose a built-in service account.
                if (accountInfo == null)
                {
                    accountInfo = AccountInfo.Create(WellKnownSids.NetworkService);
                    
                    if (accountInfo == null)
                    {
                        accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem);
                    }
                }

                ApplicationAccessRule rule = new ApplicationAccessRule();
                
                rule.IdentityName = accountInfo.ToString();
                rule.RuleType     = AccessControlType.Allow;
                rule.Right        = ApplicationAccessRight.Run;

                accessRules.Add(rule);
            }

            // set the permissions for the HTTP endpoints used by the application.
            if (configureFirewall && application.BaseAddresses != null && application.BaseAddresses.Count > 0)
            {
                for (int ii = 0; ii < application.BaseAddresses.Count; ii++)
                {
                    Uri url = Utils.ParseUri(application.BaseAddresses[ii]);

                    if (url != null)
                    {
                        if (url.Scheme == Uri.UriSchemeHttp || url.Scheme == Uri.UriSchemeHttps)
                        {
                            try
                            {
                                HttpAccessRule.SetAccessRules(url, accessRules, true);                    
                                Utils.Trace("Added HTTP access rules for URL: {0}", url);    
                            }
                            catch (Exception e)
                            {
                                Utils.Trace("Could not set HTTP access rules for URL: {0}. Error={1}", url, e.Message);

                                for (int jj = 0; jj < accessRules.Count; jj++)
                                {
                                    ApplicationAccessRule rule = accessRules[jj];

                                    Utils.Trace(
                                        (int)Utils.TraceMasks.Error,
                                        "IdentityName={0}, Right={1}, RuleType={2}",
                                        rule.IdentityName,
                                        rule.Right,
                                        rule.RuleType);
                                }
                            }
                        }
                    }
                }
            }
            
            // set permissions on the local certificate store.
            SetCertificatePermissions(
                application,
                applicationCertificate, 
                accessRules, 
                false);

           // set permissions on the local certificate store.
            if (application.RejectedCertificatesStore != null)
            {
                // need to grant full control to certificates in the RejectedCertificatesStore.
                foreach (ApplicationAccessRule rule in accessRules)
                {
                    if (rule.RuleType == AccessControlType.Allow)
                    {
                        rule.Right = ApplicationAccessRight.Configure;
                    }
                }

                CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore);

                using (ICertificateStore store = rejectedCertificates.OpenStore())
                {
                    if (store.SupportsAccessControl)
                    {
                        store.SetAccessRules(accessRules, false);
                    }
                }
            }

            // install as a service.
            if (application.InstallAsService)
            {
                ServiceInstaller.UnInstallService(application.ApplicationName);

                StartMode startMode = application.ServiceStartMode;

                if (!autostart)
                {
                    startMode = StartMode.Manual;
                }

                bool start = true;

                bool result = ServiceInstaller.InstallService(
                    executableFileInfo.FullName,
                    application.ApplicationName,
                    application.ApplicationName,
                    application.ServiceDescription,
                    startMode,
                    application.ServiceUserName,
                    application.ServicePassword,
                    ref start);

                if (!result)
                {
                    throw new ApplicationException("Could not install service.");
                }
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Uninstalls a UA application.
        /// </summary>
        public static void UninstallApplication(InstalledApplication application)
        {
            // validate the executable file.
            string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); 
            
            // get the default application name from the executable file.
            FileInfo executableFileInfo = new FileInfo(executableFile);
            string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length-4);

            // choose a default configuration file.
            if (String.IsNullOrEmpty(application.ConfigurationFile))
            {
                application.ConfigurationFile = Utils.Format(
                    "{0}\\{1}.Config.xml", 
                    executableFileInfo.DirectoryName, 
                    applicationName);                
            }
            
            // install as a service.
            if (application.InstallAsService)
            {
                ServiceInstaller.UnInstallService(application.ApplicationName);
            }

            // validate the configuration file.
            string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); 
            
            if (configurationFile != null)
            {
                // load the current configuration.
                Opc.Ua.Security.SecuredApplication security = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile);

                // delete the application certificates.
                if (application.DeleteCertificatesOnUninstall)
                {
                    CertificateIdentifier id = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(security.ApplicationCertificate);
                                        
                    // delete public key from trusted peers certificate store.
                    try
                    {
                        CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(security.TrustedCertificateStore);

                        using (ICertificateStore store = certificateStore.OpenStore())
                        {
                            X509Certificate2 peerCertificate = store.FindByThumbprint(id.Thumbprint);

                            if (peerCertificate != null)
                            {
                                store.Delete(peerCertificate.Thumbprint);
                            }
                        }                      
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }    

                    // delete private key from application certificate store.
                    try
                    {
                        using (ICertificateStore store = id.OpenStore())
                        {
                            store.Delete(id.Thumbprint);
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }        
                    
                    // permentently delete any UA defined stores if they are now empty.
                    try
                    {
                        WindowsCertificateStore store = new WindowsCertificateStore();
                        store.Open("LocalMachine\\UA Applications");

                        if (store.Enumerate().Count == 0)
                        {
                            store.PermanentlyDeleteStore();
                        }
                    }
                    catch (Exception e)
                    {
                        Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message);
                    }
                }

                // configure firewall.
                if (application.ConfigureFirewall)
                {
                    if (security.BaseAddresses != null && security.BaseAddresses.Count > 0)
                    {
                        try
                        {
                            RemoveFirewallAccess(security, executableFile);
                        }
                        catch (Exception e)
                        {
                            Utils.Trace("Could not remove firewall access for executable: {0}. Error={1}", executableFile, e.Message);
                        }
                    }
                }

                // remove the permissions for the HTTP endpoints used by the application.
                if (application.BaseAddresses != null && application.BaseAddresses.Count > 0)
                {
                    List<ApplicationAccessRule> noRules = new List<ApplicationAccessRule>();

                    for (int ii = 0; ii < application.BaseAddresses.Count; ii++)
                    {
                        Uri url = Utils.ParseUri(application.BaseAddresses[ii]);

                        if (url != null)
                        {
                            if (url.Scheme == Uri.UriSchemeHttp || url.Scheme == Uri.UriSchemeHttps)
                            {
                                try
                                {
                                    HttpAccessRule.SetAccessRules(url, noRules, true);                                    
                                    Utils.Trace("Removed HTTP access rules for URL: {0}", url);    
                                }
                                catch (Exception e)
                                {
                                    Utils.Trace("Could not remove HTTP access rules for URL: {0}. Error={1}", url, e.Message);
                                }
                            }
                        }
                    }
                }
            }
        }