Ejemplo n.º 1
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public bool ShowDialog(CertificateStoreIdentifier defaultStore)
        {
            // save the default store (used when creating new bindings).
            m_defaultStore = defaultStore;

            if (m_defaultStore == null)
            {
                m_defaultStore           = new CertificateStoreIdentifier();
                m_defaultStore.StoreType = Utils.DefaultStoreType;
                m_defaultStore.StorePath = Utils.DefaultStorePath;
            }

            // populate the grid.
            foreach (SslCertificateBinding binding in HttpAccessRule.GetSslCertificateBindings())
            {
                AddRow(binding);
            }

            m_dataset.AcceptChanges();
            BindingsDV.DataSource = m_dataset.Tables[0].DefaultView;

            if (base.ShowDialog() == DialogResult.Cancel)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Displays the applications in the control.
        /// </summary>
        internal void Initialize()
        {
            ItemsLV.Items.Clear();

            try
            {
                IList <HttpAccessRule> accessRules = HttpAccessRule.GetAccessRules(null);

                if (accessRules == null || accessRules.Count == 0)
                {
                    Instructions = "No HTTP access rules defined.";
                    AdjustColumns();
                    return;
                }

                // display the list.
                foreach (HttpAccessRule accessRule in accessRules)
                {
                    AddItem(accessRule);
                }

                AdjustColumns();
            }
            catch (Exception e)
            {
                Instructions = e.Message;
                AdjustColumns();
            }
        }
Ejemplo n.º 3
0
        private void DeleteBindingMI_Click(object sender, EventArgs e)
        {
            try
            {
                if (BindingsDV.SelectedRows.Count == 0)
                {
                    return;
                }

                if (Ask("Are you sure you want to delete these bindings?"))
                {
                    foreach (DataGridViewRow row in BindingsDV.SelectedRows)
                    {
                        DataRowView           source  = row.DataBoundItem as DataRowView;
                        SslCertificateBinding binding = (SslCertificateBinding)source.Row[4];
                        HttpAccessRule.DeleteSslCertificateBinding(binding.IPAddress, binding.Port);
                    }

                    m_dataset.Tables[0].Clear();

                    // repopulate the grid.
                    foreach (SslCertificateBinding binding in HttpAccessRule.GetSslCertificateBindings())
                    {
                        AddRow(binding);
                    }

                    m_dataset.AcceptChanges();
                    BindingsDV.DataSource = m_dataset.Tables[0].DefaultView;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Extracts the access rules from the SDDL string.
        /// </summary>
        private static void ParseSddl(string url, string sddl, List <HttpAccessRule> accessRules)
        {
            IList <AccessControlEntity> entities = AccessControlEntity.Parse(sddl);

            for (int ii = 0; ii < entities.Count; ii++)
            {
                AccessControlEntity entity = entities[ii];

                if (entity.AccessType != "A")
                {
                    continue;
                }

                ApplicationAccessRight rights = ApplicationAccessRight.None;

                switch (entity.Rights)
                {
                case "GA":
                case "GXGW":
                case "GWGX":
                {
                    rights = ApplicationAccessRight.Configure;
                    break;
                }

                case "GX":
                {
                    rights = ApplicationAccessRight.Run;
                    break;
                }
                }

                if (rights == ApplicationAccessRight.None)
                {
                    continue;
                }

                string accountName = ApplicationAccessRule.SidToAccountName(entity.AccountSid);

                if (String.IsNullOrEmpty(accountName))
                {
                    continue;
                }

                HttpAccessRule rule = new HttpAccessRule();

                rule.UrlPrefix    = url;
                rule.Right        = rights;
                rule.IdentityName = accountName;

                accessRules.Add(rule);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Updates an item in the view.
        /// </summary>
        protected override void UpdateItem(ListViewItem listItem, object item)
        {
            HttpAccessRule value = item as HttpAccessRule;

            if (value == null)
            {
                base.UpdateItem(listItem, item);
                return;
            }

            listItem.SubItems[0].Text = value.UrlPrefix;
            listItem.SubItems[1].Text = value.IdentityName;
            listItem.SubItems[2].Text = value.Right.ToString();

            listItem.ImageKey = GuiUtils.Icons.Method;
            listItem.Tag      = item;
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Sets the application access rules for the specified URL (replaces the hostname with a wildcard).
        /// </summary>
        public static void SetAccessRules(Uri url, IList <ApplicationAccessRule> accessRules, bool replaceExisting)
        {
            StringBuilder wildcard = new StringBuilder();

            wildcard.Append(url.Scheme);
            wildcard.Append("://+:");
            wildcard.Append(url.Port);
            wildcard.Append(url.PathAndQuery);

            List <HttpAccessRule> httpRules = new List <HttpAccessRule>();

            foreach (ApplicationAccessRule accessRule in accessRules)
            {
                // urls do not support deny rules.
                if (accessRule.RuleType == AccessControlType.Deny)
                {
                    continue;
                }

                string identityName = accessRule.IdentityName;

                if (accessRule.IdentityName.StartsWith("S-"))
                {
                    identityName = ApplicationAccessRule.SidToAccountName(accessRule.IdentityName);

                    if (identityName == null)
                    {
                        Utils.Trace("Could not translate SID: {0}", accessRule.IdentityName);
                        continue;
                    }
                }

                HttpAccessRule httpRule = new HttpAccessRule();

                httpRule.Right        = accessRule.Right;
                httpRule.IdentityName = identityName;

                httpRules.Add(httpRule);
            }

            SetAccessRules(wildcard.ToString(), httpRules, replaceExisting);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Extracts the access rules from the SDDL string.
        /// </summary>
        private static void ParseSddl(string url, string sddl, List<HttpAccessRule> accessRules)
        {
            IList<AccessControlEntity> entities = AccessControlEntity.Parse(sddl);

            for (int ii = 0; ii < entities.Count; ii++)
            {
                AccessControlEntity entity = entities[ii];

                if (entity.AccessType != "A")
                {
                    continue;
                }

                ApplicationAccessRight rights = ApplicationAccessRight.None;

                switch (entity.Rights)
                {
                    case "GA":                 
                    case "GXGW":             
                    case "GWGX":
                    {
                        rights = ApplicationAccessRight.Configure;
                        break;
                    }
                   
                    case "GX":  
                    {
                        rights = ApplicationAccessRight.Run;
                        break;
                    }
                }
                
                if (rights == ApplicationAccessRight.None)
                {
                    continue;
                }

                string accountName = ApplicationAccessRule.SidToAccountName(entity.AccountSid);

                if (String.IsNullOrEmpty(accountName))
                {
                    continue;
                }

                HttpAccessRule rule = new HttpAccessRule();

                rule.UrlPrefix = url;
                rule.Right = rights;
                rule.IdentityName = accountName;

                accessRules.Add(rule);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Sets the application access rules for the specified URL (replaces the hostname with a wildcard). 
        /// </summary>
        public static void SetAccessRules(Uri url, IList<ApplicationAccessRule> accessRules, bool replaceExisting)
        {
            StringBuilder wildcard = new StringBuilder();

            wildcard.Append(url.Scheme);
            wildcard.Append("://+:");
            wildcard.Append(url.Port);
            wildcard.Append(url.PathAndQuery);

            List<HttpAccessRule> httpRules = new List<HttpAccessRule>();

            foreach (ApplicationAccessRule accessRule in accessRules)
            {
                // urls do not support deny rules.
                if (accessRule.RuleType == AccessControlType.Deny)
                {
                    continue;
                }
                
                string identityName = accessRule.IdentityName;

                if (accessRule.IdentityName.StartsWith("S-"))
                {
                    identityName = ApplicationAccessRule.SidToAccountName(accessRule.IdentityName); 

                    if (identityName == null)
                    {
                        Utils.Trace("Could not translate SID: {0}", accessRule.IdentityName);
                        continue;
                    }
                }

                HttpAccessRule httpRule = new HttpAccessRule();
                
                httpRule.Right = accessRule.Right;
                httpRule.IdentityName = identityName;

                httpRules.Add(httpRule);
            }

            SetAccessRules(wildcard.ToString(), httpRules, replaceExisting);
        }
Ejemplo n.º 9
0
        private void DeleteMI_Click(object sender, EventArgs e)
        {
            try
            {
                if (ItemsLV.SelectedItems.Count < 1)
                {
                    return;
                }

                DialogResult result = MessageBox.Show(
                    "Are you sure you wish to delete the rules from the list?",
                    "Delete Certificate",
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Exclamation);

                if (result != DialogResult.Yes)
                {
                    return;
                }

                // remove the items.
                Dictionary <string, List <HttpAccessRule> > rulesToDelete = new Dictionary <string, List <HttpAccessRule> >();

                while (ItemsLV.SelectedItems.Count > 0)
                {
                    HttpAccessRule rule = ItemsLV.SelectedItems[0].Tag as HttpAccessRule;

                    List <HttpAccessRule> rules = null;

                    if (!rulesToDelete.TryGetValue(rule.UrlPrefix, out rules))
                    {
                        rulesToDelete[rule.UrlPrefix] = rules = new List <HttpAccessRule>();
                    }

                    rules.Add(rule);
                    ItemsLV.SelectedItems[0].Remove();
                }

                // delete rules.
                foreach (KeyValuePair <string, List <HttpAccessRule> > pair in rulesToDelete)
                {
                    IList <HttpAccessRule> existingRules = HttpAccessRule.GetAccessRules(pair.Key);

                    List <HttpAccessRule> remainingRules = new List <HttpAccessRule>();

                    for (int ii = 0; ii < existingRules.Count; ii++)
                    {
                        HttpAccessRule existingRule = existingRules[ii];

                        bool found = false;

                        for (int jj = 0; jj < pair.Value.Count; jj++)
                        {
                            HttpAccessRule ruleToDelete = pair.Value[jj];

                            if (ruleToDelete.IdentityName == existingRule.IdentityName)
                            {
                                continue;
                            }

                            if (ruleToDelete.Right == existingRule.Right)
                            {
                                continue;
                            }

                            found = true;
                            break;
                        }

                        if (!found)
                        {
                            remainingRules.Add(existingRule);
                        }
                    }

                    HttpAccessRule.SetAccessRules(pair.Key, remainingRules, true);
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Sets the permissions to match the template on the specified directory.
        /// </summary>
        public void SetPermissions(string template, Uri url, bool exactMatch)
        {
            if (url == null)
            {
                throw new ArgumentException("Target URI is not valid.", "target");
            }

            string filePath = Utils.GetAbsoluteFilePath(m_directory.FullName + "\\" + template + m_FileExtension, false, false, false);

            // nothing more to do if no file.
            if (filePath == null)
            {
                return;
            }

            string urlMask = null;

            if (!exactMatch)
            {
                urlMask = url.Scheme;
                urlMask += "://+:";
                urlMask += url.Port;
                urlMask += url.PathAndQuery;

                if (!urlMask.EndsWith("/"))
                {
                    urlMask += "/";
                }
            }
            else
            {
                urlMask = url.ToString();
            }

            FileInfo templateFile = new FileInfo(filePath);
            FileSecurity security1 = templateFile.GetAccessControl(AccessControlSections.Access);
            List<HttpAccessRule> httpRules = new List<HttpAccessRule>();

            foreach (AuthorizationRule rule in security1.GetAccessRules(true, true, typeof(NTAccount)))
            {
                FileSystemAccessRule fsr = rule as FileSystemAccessRule;

                if (fsr != null)
                {
                    HttpAccessRule httpRule = new HttpAccessRule();
                    httpRule.UrlPrefix = urlMask;
                    httpRule.IdentityName = fsr.IdentityReference.Translate(typeof(NTAccount)).ToString();
                    httpRules.Add(httpRule);

                    if ((fsr.FileSystemRights & FileSystemRights.ChangePermissions) != 0)
                    {
                        httpRule.Right = ApplicationAccessRight.Configure;
                    }
                    else if ((fsr.FileSystemRights & FileSystemRights.WriteData) != 0)
                    {
                        httpRule.Right = ApplicationAccessRight.Update;
                    }
                    else if ((fsr.FileSystemRights & FileSystemRights.ReadData) != 0)
                    {
                        httpRule.Right = ApplicationAccessRight.Run;
                    }
                }
            }

            HttpAccessRule.SetAccessRules(urlMask, httpRules, true);
        }
Ejemplo n.º 11
0
        private void OkBTN_Click(object sender, EventArgs e)
        {
            try
            {
                IPAddress address = IPAddress.Parse(IPAddressTB.Text);
                ushort    port    = (ushort)PortUD.Value;

                if (m_certificate == null)
                {
                    throw new ArgumentException("You must specify a certificate.");
                }

                X509Certificate2 certificate = m_certificate.Find(true);

                if (certificate == null)
                {
                    throw new ArgumentException("Certificate does not exist or has no private key.");
                }

                // setup policy chain
                X509ChainPolicy policy = new X509ChainPolicy();

                policy.RevocationFlag    = X509RevocationFlag.EntireChain;
                policy.RevocationMode    = X509RevocationMode.Offline;
                policy.VerificationFlags = X509VerificationFlags.NoFlag;

                policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;

                // build chain.
                X509Chain chain = new X509Chain();
                chain.ChainPolicy = policy;
                chain.Build(certificate);

                for (int ii = 0; ii < chain.ChainElements.Count; ii++)
                {
                    X509ChainElement element = chain.ChainElements[ii];

                    // check for chain status errors.
                    foreach (X509ChainStatus status in element.ChainElementStatus)
                    {
                        if (status.Status == X509ChainStatusFlags.UntrustedRoot)
                        {
                            if (!Ask("Cannot verify certificate up to a trusted root.\r\nAdd anyways?"))
                            {
                                return;
                            }

                            continue;
                        }

                        if (status.Status == X509ChainStatusFlags.RevocationStatusUnknown)
                        {
                            if (!Ask("The revocation status of this certificate cannot be verified.\r\nAdd anyways?"))
                            {
                                return;
                            }

                            continue;
                        }

                        // ignore informational messages.
                        if (status.Status == X509ChainStatusFlags.OfflineRevocation)
                        {
                            continue;
                        }

                        if (status.Status != X509ChainStatusFlags.NoError)
                        {
                            throw new ArgumentException("[" + status.Status + "] " + status.StatusInformation);
                        }
                    }
                }

                // get the target store.
                if (m_store == null)
                {
                    m_store           = new CertificateStoreIdentifier();
                    m_store.StoreType = CertificateStoreType.Windows;
                    m_store.StorePath = CertificateStoreTB.Text;
                }

                if (m_store.StoreType != CertificateStoreType.Windows)
                {
                    throw new ArgumentException("You must choose a Windows store for SSL certificates.");
                }

                if (!m_store.StorePath.StartsWith("LocalMachine\\", StringComparison.OrdinalIgnoreCase))
                {
                    throw new ArgumentException("You must choose a machine store for SSL certificates.");
                }

                bool deleteExisting = false;

                using (ICertificateStore store = m_store.OpenStore())
                {
                    if (store.FindByThumbprint(certificate.Thumbprint) == null)
                    {
                        store.Add(certificate);
                        deleteExisting = true;
                    }
                }

                if (deleteExisting)
                {
                    if (Ask("Would you like to delete the certificate from its current location?"))
                    {
                        using (ICertificateStore store = m_certificate.OpenStore())
                        {
                            store.Delete(certificate.Thumbprint);
                        }
                    }
                }

                SslCertificateBinding binding = new SslCertificateBinding();

                binding.IPAddress     = address;
                binding.Port          = port;
                binding.Thumbprint    = certificate.Thumbprint;
                binding.ApplicationId = s_DefaultApplicationId;
                binding.StoreName     = null;

                if (!m_store.StorePath.EndsWith("\\My"))
                {
                    int index = m_store.StorePath.LastIndexOf("\\");
                    binding.StoreName = m_store.StorePath.Substring(index + 1);
                }

                HttpAccessRule.SetSslCertificateBinding(binding);

                m_binding    = binding;
                DialogResult = DialogResult.OK;
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
        /// <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);
                    }
                }
            }
        }