Пример #1
0
        protected async Task UpdateGroupStore(string storePath, X509Certificate2Collection certs, IList <Opc.Ua.X509CRL> crls)
        {
            if (!String.IsNullOrEmpty(storePath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    X509Certificate2Collection oldCertificates = await store.Enumerate();

                    foreach (var cert in oldCertificates)
                    {
                        await store.Delete(cert.Thumbprint);
                    }
                    foreach (var crl in store.EnumerateCRLs())
                    {
                        store.DeleteCRL(crl);
                    }
                    foreach (var cert in certs)
                    {
                        await store.Add(cert);
                    }
                    foreach (var crl in crls)
                    {
                        store.AddCRL(crl);
                    }
                }
            }
        }
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(CertificateStoreIdentifier store, bool allowStoreChange)
        {
            CertificateStoreCTRL.StoreType = CertificateStoreType.Directory;
            CertificateStoreCTRL.StorePath = String.Empty;
            CertificateStoreCTRL.ReadOnly = !allowStoreChange;
            CertificatesCTRL.Initialize(null);
            OkBTN.Enabled = false;

            if (store != null)
            {
                CertificateStoreCTRL.StoreType = store.StoreType;
                CertificateStoreCTRL.StorePath = store.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return null;
            }

            CertificateIdentifier id = new CertificateIdentifier();
            id.StoreType = CertificateStoreCTRL.StoreType;
            id.StorePath = CertificateStoreCTRL.StorePath;
            id.Certificate = CertificatesCTRL.SelectedCertificate;
            return id;
        }
Пример #3
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(
            CertificateStoreIdentifier targetStore,
            string issuerKeyFilePath,
            string issuerCertificatePassword)
        {
            CertificateStoreCTRL.StoreType = null;
            CertificateStoreCTRL.StorePath = null;
            IssuerKeyFilePathTB.Text       = issuerKeyFilePath;
            IssuerPasswordTB.Text          = issuerCertificatePassword;
            SubjectNameCK.Checked          = false;
            DomainNameTB.Text        = System.Net.Dns.GetHostName();
            KeySizeCB.SelectedIndex  = 0;
            LifeTimeInMonthsUD.Value = 60;

            if (targetStore != null)
            {
                CertificateStoreCTRL.StoreType = targetStore.StoreType;
                CertificateStoreCTRL.StorePath = targetStore.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return(null);
            }

            return(m_certificate);
        }
Пример #4
0
        private bool EraseStore(string storePath)
        {
            bool result = true;

            try
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    var storeCerts = store.Enumerate().Result;
                    foreach (var cert in storeCerts)
                    {
                        if (!store.Delete(cert.Thumbprint).Result)
                        {
                            result = false;
                        }
                    }
                    var storeCrls = store.EnumerateCRLs();
                    foreach (var crl in storeCrls)
                    {
                        if (!store.DeleteCRL(crl))
                        {
                            result = false;
                        }
                    }
                }
            }
            catch
            {
                result = false;
            }
            return(result);
        }
Пример #5
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(CertificateStoreIdentifier store, bool allowStoreChange)
        {
            CertificateStoreCTRL.StoreType = CertificateStoreType.Directory;
            CertificateStoreCTRL.StorePath = String.Empty;
            CertificateStoreCTRL.ReadOnly  = !allowStoreChange;
            CertificatesCTRL.Initialize(null);
            OkBTN.Enabled = false;

            if (store != null)
            {
                CertificateStoreCTRL.StoreType = store.StoreType;
                CertificateStoreCTRL.StorePath = store.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return(null);
            }

            CertificateIdentifier id = new CertificateIdentifier();

            id.StoreType   = CertificateStoreCTRL.StoreType;
            id.StorePath   = CertificateStoreCTRL.StorePath;
            id.Certificate = CertificatesCTRL.SelectedCertificate;
            return(id);
        }
Пример #6
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;
        }
Пример #7
0
        private void CopyMI_Click(object sender, EventArgs e)
        {
            try {
                TreeNode node = NodesTV.SelectedNode;

                // check if valid store selected.
                ContainerInfo info = node.Tag as ContainerInfo;

                if (info == null)
                {
                    return;
                }

                if (info.Type != ContainerInfoType.Store || node.Parent == null)
                {
                    return;
                }

                CertificateStoreIdentifier store = info.GetCertificateStore();

                StringBuilder builder = new StringBuilder();
                XmlWriter     writer  = XmlWriter.Create(builder);

                try {
                    DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateStoreIdentifier));
                    serializer.WriteObject(writer, store);
                } finally {
                    writer.Close();
                }

                ClipboardHack.SetData(DataFormats.Text, builder.ToString());
            } catch (Exception exception) {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(
            CertificateStoreIdentifier targetStore,
            string issuerKeyFilePath,
            string issuerCertificatePassword)
        {
            CertificateStoreCTRL.StoreType = null;
            CertificateStoreCTRL.StorePath = null;
            IssuerKeyFilePathTB.Text = issuerKeyFilePath;
            IssuerPasswordTB.Text = issuerCertificatePassword;
            SubjectNameCK.Checked = false;
            DomainNameTB.Text = System.Net.Dns.GetHostName();
            KeySizeCB.SelectedIndex = 0;
            LifeTimeInMonthsUD.Value = 60;

            if (targetStore != null)
            {
                CertificateStoreCTRL.StoreType = targetStore.StoreType;
                CertificateStoreCTRL.StorePath = targetStore.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return null;
            }

            return m_certificate;
        }
Пример #9
0
        /// <summary>
        /// Updates the certificate authority certificate and CRL in the trusted list.
        /// </summary>
        private async Task UpdateAuthorityCertInTrustedList()
        {
            string trustedListStorePath = Configuration.TrustedListPath;

            if (!String.IsNullOrEmpty(Configuration.TrustedListPath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(trustedListStorePath))
                {
                    X509Certificate2Collection certs = await store.FindByThumbprint(Certificate.Thumbprint);

                    if (certs.Count == 0)
                    {
                        await store.Add(Certificate);
                    }

                    // delete existing CRL in trusted list
                    foreach (var crl in store.EnumerateCRLs(Certificate, false))
                    {
                        if (crl.VerifySignature(Certificate, false))
                        {
                            store.DeleteCRL(crl);
                        }
                    }

                    // copy latest CRL to trusted list
                    using (ICertificateStore storeAuthority = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
                    {
                        foreach (var crl in storeAuthority.EnumerateCRLs(Certificate, true))
                        {
                            store.AddCRL(crl);
                        }
                    }
                }
            }
        }
Пример #10
0
        private void TrustListBTN_Click(object sender, EventArgs e)
        {
            try
            {
                // determine default store.
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();

                if (m_trustList != null)
                {
                    store.StoreType = m_trustList.StoreType;
                    store.StorePath = m_trustList.StorePath;
                }
                else
                {
                    store.StoreType = Utils.DefaultStoreType;
                    store.StorePath = Utils.DefaultStorePath;
                }

                // select store.
                CertificateStoreIdentifier trustList = new CertificateStoreDlg().ShowDialog(store);

                if (trustList != null)
                {
                    m_trustList      = trustList;
                    TrustListTB.Text = m_trustList.ToString();
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #11
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(CertificateStoreIdentifier store, string issuerKeyFilePath, X509Certificate2 certificate)
        {
            CertificateStoreCTRL.StoreType = null;
            CertificateStoreCTRL.StorePath = null;
            IssuerKeyFilePathTB.Text       = null;
            IssuerPasswordTB.Text          = null;
            ApplicationNameTB.Text         = null;
            ApplicationUriTB.Text          = null;
            SubjectNameTB.Text             = null;
            DomainsTB.Text           = System.Net.Dns.GetHostName();
            KeySizeCB.SelectedIndex  = 0;
            LifeTimeInMonthsUD.Value = 60;

            if (store != null)
            {
                CertificateStoreCTRL.StoreType = store.StoreType;
                CertificateStoreCTRL.StorePath = store.StorePath;
            }

            if (issuerKeyFilePath != null)
            {
                IssuerKeyFilePathTB.Text = issuerKeyFilePath;
            }

            UpdateWithCertificate(certificate);

            if (ShowDialog() != DialogResult.OK)
            {
                return(null);
            }

            return(m_certificate);
        }
Пример #12
0
        private ICertificateStore CreateStore(string storePath)
        {
            ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreIdentifier.DetermineStoreType(storePath));

            store.Open(storePath);
            return(store);
        }
Пример #13
0
        /// <summary>
        /// Displays the applications in the control.
        /// </summary>
        internal void Initialize(CertificateStoreIdentifier id, IList <string> thumbprints)
        {
            ItemsLV.Items.Clear();

            m_storeId     = id;
            m_thumbprints = thumbprints;

            if (m_storeId == null || String.IsNullOrEmpty(m_storeId.StoreType) ||
                String.IsNullOrEmpty(m_storeId.StorePath))
            {
                Instructions = "No certificates are in the store.";
                AdjustColumns();
                return;
            }

            try {
                // get the store.
                using (ICertificateStore store = m_storeId.OpenStore()) {
                    // only show certificates with the specified thumbprint.
                    if (thumbprints != null)
                    {
                        Instructions = "None of the selected certificates can be found in the store.";

                        foreach (string thumbprint in thumbprints)
                        {
                            X509Certificate2 certificate = store.FindByThumbprint(thumbprint);

                            if (certificate != null)
                            {
                                AddItem(certificate);
                            }
                        }
                    }

                    // show all certificates.
                    else
                    {
                        Instructions = "No certificates are in the store.";

                        foreach (X509Certificate2 certificate in store.Enumerate())
                        {
                            AddItem(certificate);
                        }
                    }
                }
            } catch (Exception e) {
                Instructions = "An error occurred opening the store: " + e.Message;
            }

            // save the unfiltered list.
            m_items = new List <ListViewItem>(ItemsLV.Items.Count);

            foreach (ListViewItem item in ItemsLV.Items)
            {
                m_items.Add(item);
            }

            AdjustColumns();
        }
Пример #14
0
 protected CertificateGroup(
     string authoritiesStorePath,
     CertificateGroupConfiguration certificateGroupConfiguration
     )
 {
     m_authoritiesStorePath = authoritiesStorePath;
     m_authoritiesStoreType = CertificateStoreIdentifier.DetermineStoreType(m_authoritiesStorePath);
     Configuration          = certificateGroupConfiguration;
 }
Пример #15
0
        private ServiceResult AddCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] certificate,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

            lock (m_lock)
            {

                if (m_sessionId != null)
                {
                    return StatusCodes.BadInvalidState;
                }

                if (certificate == null)
                {
                    return StatusCodes.BadInvalidArgument;
                }

                X509Certificate2 cert = null;
                X509CRL crl = null;
                try
                {
                    cert = new X509Certificate2(certificate);
                }
                catch
                {
                    try
                    {
                        crl = new X509CRL(certificate);
                    }
                    catch
                    {
                        return StatusCodes.BadCertificateInvalid;
                    }
                }

                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                {
                    if (cert != null)
                    {
                        store.Add(cert).Wait();
                    }
                    if (crl != null)
                    {
                        store.AddCRL(crl);
                    }
                }

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return ServiceResult.Good;
        }
Пример #16
0
        /// <summary>
        /// Handles a drop event.
        /// </summary>
        protected override void NodesTV_DragDrop(object sender, DragEventArgs e)
        {
            try
            {
                TreeNode node = NodesTV.GetNodeAt(PointToClient(new Point(e.X, e.Y)));

                if (node == null)
                {
                    return;
                }

                ContainerInfo info = node.Tag as ContainerInfo;

                if (info == null)
                {
                    return;
                }

                if (info.Type == ContainerInfoType.Store)
                {
                    CertificateStoreIdentifier id = info.GetCertificateStore();

                    if (id == null)
                    {
                        return;
                    }

                    object[] certificates = e.Data.GetData(typeof(object[])) as object[];

                    if (certificates == null)
                    {
                        return;
                    }

                    using (ICertificateStore store = id.OpenStore())
                    {
                        for (int ii = 0; ii < certificates.Length; ii++)
                        {
                            X509Certificate2 certificate = certificates[ii] as X509Certificate2;

                            if (certificate != null)
                            {
                                store.Add(certificate);
                            }
                        }
                    }

                    NodesTV.SelectedNode = node;
                    return;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #17
0
 // Create an empty CRL
 static void CreateCACRL(string storePath, X509Certificate2 caCert)
 {
     Console.WriteLine("Creating an empty certificate revocation list (CRL) for the CA");
     using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
     {
         List <X509CRL> caCRL      = store.EnumerateCRLs(caCert, false);
         X509CRL        updatedCRL = CertificateFactory.RevokeCertificate(caCert, caCRL, null);
         store.AddCRL(updatedCRL);
     }
 }
Пример #18
0
 protected CertificateGroup(
     string authoritiesStorePath,
     CertificateGroupConfiguration certificateGroupConfiguration
     )
 {
     m_authoritiesStorePath = authoritiesStorePath;
     m_authoritiesStoreType = CertificateStoreIdentifier.DetermineStoreType(m_authoritiesStorePath);
     Configuration          = certificateGroupConfiguration;
     m_subjectName          = Configuration.SubjectName.Replace("localhost", Utils.GetHostName());
 }
        public async Task <X509CertificateCollection> KeyVaultSigningRequestAsync()
        {
            Skip.If(!_fixture.KeyVaultInitOk);
            X509CertificateCollection certCollection = new X509CertificateCollection();

            string[] groups = await _keyVault.GetCertificateGroupIds();

            foreach (string group in groups)
            {
                var certificateGroupConfiguration = await _keyVault.GetCertificateGroupConfiguration(group);

                ApplicationTestData randomApp      = _fixture.RandomGenerator.RandomApplicationTestData();
                X509Certificate2    csrCertificate = CertificateFactory.CreateCertificate(
                    null, null, null,
                    randomApp.ApplicationRecord.ApplicationUri,
                    null,
                    randomApp.Subject,
                    randomApp.DomainNames.ToArray(),
                    certificateGroupConfiguration.DefaultCertificateKeySize,
                    DateTime.UtcNow.AddDays(-10),
                    certificateGroupConfiguration.DefaultCertificateLifetime,
                    certificateGroupConfiguration.DefaultCertificateHashSize
                    );
                byte[] certificateRequest = CertificateFactory.CreateSigningRequest(csrCertificate, randomApp.DomainNames);

                X509Certificate2 newCert = await _keyVault.SigningRequestAsync(
                    group,
                    randomApp.ApplicationRecord.ApplicationUri,
                    certificateRequest);

                // get issuer cert used for signing
                X509Certificate2Collection issuerCerts = await _keyVault.GetIssuerCACertificateChainAsync(group);

#if WRITECERT
                // save cert for debugging
                using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(CertificateStoreType.Directory))
                {
                    Assert.NotNull(store);
                    store.Open("d:\\unittest");
                    await store.Add(newCert);

                    foreach (var cert in issuerCerts)
                    {
                        await store.Add(cert);
                    }
                }
#endif
                Assert.NotNull(issuerCerts);
                Assert.True(issuerCerts.Count >= 1);
                X509TestUtils.VerifySignedApplicationCert(randomApp, newCert, issuerCerts);
                certCollection.Add(newCert);
            }
            return(certCollection);
        }
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateStoreIdentifier ShowDialog(CertificateStoreIdentifier store)
        {
            ContainersCTRL.Initialize();

            if (ShowDialog() != DialogResult.OK)
            {
                return null;
            }
  
            return ContainersCTRL.SelectedStore;
        }
Пример #21
0
        private async void DeleteExistingFromStore(string storePath)
        {
            if (String.IsNullOrEmpty(storePath))
            {
                return;
            }

            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
            {
                X509Certificate2Collection certificates = await store.Enumerate();

                foreach (var certificate in certificates)
                {
                    if (store.GetPrivateKeyFilePath(certificate.Thumbprint) != null)
                    {
                        continue;
                    }

                    List <string> fields = Utils.ParseDistinguishedName(certificate.Subject);

                    if (fields.Contains("CN=UA Local Discovery Server"))
                    {
                        continue;
                    }

                    DirectoryCertificateStore ds = store as DirectoryCertificateStore;

                    if (ds != null)
                    {
                        string path = Utils.GetAbsoluteFilePath(m_application.CertificatePublicKeyPath, true, false, false);

                        if (path != null)
                        {
                            if (String.Compare(path, ds.GetPublicKeyFilePath(certificate.Thumbprint), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                continue;
                            }
                        }

                        path = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, false, false);

                        if (path != null)
                        {
                            if (String.Compare(path, ds.GetPrivateKeyFilePath(certificate.Thumbprint), StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                continue;
                            }
                        }
                    }

                    await store.Delete(certificate.Thumbprint);
                }
            }
        }
Пример #22
0
 private void ViewBTN_Click(object sender, EventArgs e)
 {
     try {
         CertificateStoreIdentifier store = new CertificateStoreIdentifier();
         store.StoreType = CertificateStoreCTRL.StoreType;
         store.StorePath = CertificateStoreCTRL.StorePath;
         new CertificateListDlg().ShowDialog(store, false);
     } catch (Exception exception) {
         GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
     }
 }
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateStoreIdentifier ShowDialog(CertificateStoreIdentifier store)
        {
            ContainersCTRL.Initialize();

            if (ShowDialog() != DialogResult.OK)
            {
                return(null);
            }

            return(ContainersCTRL.SelectedStore);
        }
Пример #24
0
        private ServiceResult AddCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] certificate,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

            ServiceResult result = StatusCodes.Good;

            lock (m_lock)
            {
                if (m_sessionId != null)
                {
                    result = StatusCodes.BadInvalidState;
                }
                else if (certificate == null)
                {
                    result = StatusCodes.BadInvalidArgument;
                }
                else
                {
                    X509Certificate2 cert = null;
                    try
                    {
                        cert = new X509Certificate2(certificate);
                    }
                    catch
                    {
                        // note: a previous version of the sample code accepted also CRL,
                        // but the behaviour was not as specified and removed
                        // https://mantis.opcfoundation.org/view.php?id=6342
                        result = StatusCodes.BadCertificateInvalid;
                    }

                    using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                    {
                        if (cert != null)
                        {
                            store.Add(cert).GetAwaiter().GetResult();
                        }
                    }

                    m_node.LastUpdateTime.Value = DateTime.UtcNow;
                }
            }

            // report the TrustListUpdatedAuditEvent
            object[] inputParameters = new object[] { certificate, isTrustedCertificate };
            m_node.ReportTrustListUpdatedAuditEvent(context, objectId, "Method/AddCertificate", method.NodeId, inputParameters, result.StatusCode);

            return(result);
        }
        /// <summary>
        /// Default constructor
        /// </summary>
        public MqttTlsOptions()
        {
            m_certificates                 = null;
            m_SslProtocolVersion           = SslProtocols.None;
            m_allowUntrustedCertificates   = false;
            m_ignoreCertificateChainErrors = false;
            m_ignoreRevocationListErrors   = false;

            m_trustedIssuerCertificates = null;
            m_trustedPeerCertificates   = null;
            m_rejectedCertificateStore  = null;
        }
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="kvpMqttOptions">The key value pairs representing the values from which to construct MqttTlsOptions</param>
        public MqttTlsOptions(KeyValuePairCollection kvpMqttOptions)
        {
            m_certificates = new MqttTlsCertificates(kvpMqttOptions);

            QualifiedName qSslProtocolVersion = EnumMqttClientConfigurationParameters.TlsProtocolVersion.ToString();

            m_SslProtocolVersion = (SslProtocols)Convert.ToInt32(kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qSslProtocolVersion.Name))?.Value.Value);

            QualifiedName qAllowUntrustedCertificates = EnumMqttClientConfigurationParameters.TlsAllowUntrustedCertificates.ToString();

            m_allowUntrustedCertificates = Convert.ToBoolean(kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qAllowUntrustedCertificates.Name))?.Value.Value);

            QualifiedName qIgnoreCertificateChainErrors = EnumMqttClientConfigurationParameters.TlsIgnoreCertificateChainErrors.ToString();

            m_ignoreCertificateChainErrors = Convert.ToBoolean(kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qIgnoreCertificateChainErrors.Name))?.Value.Value);

            QualifiedName qIgnoreRevocationListErrors = EnumMqttClientConfigurationParameters.TlsIgnoreRevocationListErrors.ToString();

            m_ignoreRevocationListErrors = Convert.ToBoolean(kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qIgnoreRevocationListErrors.Name))?.Value.Value);

            QualifiedName qTrustedIssuerCertificatesStoreType = EnumMqttClientConfigurationParameters.TrustedIssuerCertificatesStoreType.ToString();
            string        issuerCertificatesStoreType         = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qTrustedIssuerCertificatesStoreType.Name))?.Value.Value as string;
            QualifiedName qTrustedIssuerCertificatesStorePath = EnumMqttClientConfigurationParameters.TrustedIssuerCertificatesStorePath.ToString();
            string        issuerCertificatesStorePath         = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qTrustedIssuerCertificatesStorePath.Name))?.Value.Value as string;

            m_trustedIssuerCertificates = new CertificateTrustList {
                StoreType = issuerCertificatesStoreType,
                StorePath = issuerCertificatesStorePath
            };

            QualifiedName qTrustedPeerCertificatesStoreType = EnumMqttClientConfigurationParameters.TrustedPeerCertificatesStoreType.ToString();
            string        peerCertificatesStoreType         = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qTrustedPeerCertificatesStoreType.Name))?.Value.Value as string;
            QualifiedName qTrustedPeerCertificatesStorePath = EnumMqttClientConfigurationParameters.TrustedPeerCertificatesStorePath.ToString();
            string        peerCertificatesStorePath         = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qTrustedPeerCertificatesStorePath.Name))?.Value.Value as string;

            m_trustedPeerCertificates = new CertificateTrustList {
                StoreType = peerCertificatesStoreType,
                StorePath = peerCertificatesStorePath
            };

            QualifiedName qRejectedCertificateStoreStoreType = EnumMqttClientConfigurationParameters.RejectedCertificateStoreStoreType.ToString();
            string        rejectedCertificateStoreStoreType  = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qRejectedCertificateStoreStoreType.Name))?.Value.Value as string;
            QualifiedName qRejectedCertificateStoreStorePath = EnumMqttClientConfigurationParameters.RejectedCertificateStoreStorePath.ToString();
            string        rejectedCertificateStoreStorePath  = kvpMqttOptions.Find(kvp => kvp.Key.Name.Equals(qRejectedCertificateStoreStorePath.Name))?.Value.Value as string;

            m_rejectedCertificateStore = new CertificateTrustList {
                StoreType = rejectedCertificateStoreStoreType,
                StorePath = rejectedCertificateStoreStorePath
            };

            m_keyValuePairs = kvpMqttOptions;
        }
Пример #27
0
        public virtual async Task Init()
        {
            Utils.Trace(Utils.TraceMasks.Information, "InitializeCertificateGroup: {0}", m_subjectName);

            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
            {
                X509Certificate2Collection certificates = await store.Enumerate();

                foreach (var certificate in certificates)
                {
                    if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName))
                    {
                        using (RSA rsa = certificate.GetRSAPublicKey())
                        {
                            if (rsa.KeySize != Configuration.CACertificateKeySize)
                            {
                                continue;
                            }

                            // TODO check hash size
                        }

                        if (Certificate != null)
                        {
                            // always use latest issued cert in store
                            if (certificate.NotBefore > DateTime.UtcNow ||
                                Certificate.NotBefore > certificate.NotBefore)
                            {
                                continue;
                            }
                        }
                        Certificate = certificate;
                    }
                }
            }

            if (Certificate == null)
            {
                Utils.Trace(Utils.TraceMasks.Security,
                            "Create new CA Certificate: {0}, KeySize: {1}, HashSize: {2}, LifeTime: {3} months",
                            m_subjectName,
                            Configuration.CACertificateKeySize,
                            Configuration.CACertificateHashSize,
                            Configuration.CACertificateLifetime
                            );
                X509Certificate2 newCertificate = await CreateCACertificateAsync(m_subjectName);

                Certificate = new X509Certificate2(newCertificate.RawData);
            }
        }
Пример #28
0
        private void StorePathCB_SelectedIndexChanged(object sender, EventArgs e)
        {
            try {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = StoreTypeCB.SelectedItem as string;
                store.StorePath = StorePathCB.Text;

                if (StorePathCB.SelectedIndex != -1)
                {
                    store.StorePath = StorePathCB.SelectedItem as string;
                }
            } catch (Exception exception) {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #29
0
        private void CertificateStoreCTRL_StoreChanged(object sender, EventArgs e)
        {
            try
            {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = CertificateStoreCTRL.StoreType;
                store.StorePath = CertificateStoreCTRL.StorePath;
                CertificatesCTRL.Initialize(store, null);

                FilterBTN_Click(sender, e);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #30
0
        private ServiceResult AddCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] certificate,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

            lock (m_lock)
            {
                if (m_sessionId != null)
                {
                    return(StatusCodes.BadInvalidState);
                }

                if (certificate == null)
                {
                    return(StatusCodes.BadInvalidArgument);
                }

                X509Certificate2 cert = null;
                try
                {
                    cert = new X509Certificate2(certificate);
                }
                catch
                {
                    // note: a previous version of the sample code accepted also CRL,
                    // but the behaviour was not as specified and removed
                    // https://mantis.opcfoundation.org/view.php?id=6342
                    return(StatusCodes.BadCertificateInvalid);
                }

                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                {
                    if (cert != null)
                    {
                        store.Add(cert).Wait();
                    }
                }

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return(ServiceResult.Good);
        }
Пример #31
0
        public async Task CertifcateStoreTypeConfigTest()
        {
            var fileInfo  = new FileInfo(Path.Combine(TestContext.CurrentContext.TestDirectory, "Security", "Certificates", "CertificateStoreTypeTestConfig.xml"));
            var appConfig = await ApplicationConfiguration.Load(fileInfo, ApplicationType.Client, null).ConfigureAwait(false);

            int instancesCreatedWhileLoadingConfig = TestCertStore.InstancesCreated;

            Assert.IsTrue(instancesCreatedWhileLoadingConfig > 0);
            var trustedIssuers = appConfig.SecurityConfiguration.TrustedIssuerCertificates;
            ICertificateStore trustedIssuersStore = trustedIssuers.OpenStore();

            trustedIssuersStore.Close();
            int instancesCreatedWhileOpeningAuthRootStore = TestCertStore.InstancesCreated;

            Assert.IsTrue(instancesCreatedWhileLoadingConfig < instancesCreatedWhileOpeningAuthRootStore);
            CertificateStoreIdentifier.OpenStore(TestCertStore.StoreTypePrefix + @"CurrentUser\Disallowed");
            Assert.IsTrue(instancesCreatedWhileOpeningAuthRootStore < TestCertStore.InstancesCreated);
        }
Пример #32
0
        private void PasteMI_Click(object sender, EventArgs e)
        {
            try
            {
                string xml = (string)ClipboardHack.GetData(DataFormats.Text);

                if (String.IsNullOrEmpty(xml))
                {
                    return;
                }

                // check if in the favorites list.
                ContainerInfo info = NodesTV.SelectedNode.Tag as ContainerInfo;

                // check if pasting into a store.
                if (info.Type == ContainerInfoType.Store)
                {
                    CertificateIdentifier id = null;

                    using (XmlTextReader reader = new XmlTextReader(new StringReader(xml)))
                    {
                        DataContractSerializer serializer = new DataContractSerializer(typeof(CertificateIdentifier));
                        id = (CertificateIdentifier)serializer.ReadObject(reader, false);
                    }

                    if (id.Certificate != null)
                    {
                        CertificateStoreIdentifier storeId = info.GetCertificateStore();

                        using (ICertificateStore store = storeId.OpenStore())
                        {
                            store.Add(id.Certificate);
                        }
                    }

                    SelectNode();
                    return;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #33
0
            /// <summary>
            /// Returns a store for the container.
            /// </summary>
            public CertificateStoreIdentifier GetCertificateStore()
            {
                if (this.Store != null)
                {
                    return(this.Store);
                }

                if (this.CertificateStore != null)
                {
                    CertificateStoreIdentifier store = new CertificateStoreIdentifier();

                    store.StoreType = CertificateStoreType.Windows;
                    store.StorePath = this.CertificateStore.Format();

                    return(store);
                }

                return(null);
            }
Пример #34
0
        /// <summary>
        /// Adds an application certificate to a store.
        /// </summary>
        private static void AddApplicationCertificateToStore(
            CertificateStoreIdentifier csid,
            X509Certificate2 certificate,
            string oldThumbprint)
        {
            ICertificateStore store = csid.OpenStore();

            try
            {
                // delete the old certificate.
                if (oldThumbprint != null)
                {
                    store.Delete(oldThumbprint);
                }

                // delete certificates with the same application uri.
                if (store.FindByThumbprint(certificate.Thumbprint) != null)
                {
                    return;
                }
                string applicationUri = Utils.GetApplicationUriFromCertficate(certificate);

                // delete any existing certificates.
                foreach (X509Certificate2 target in store.Enumerate())
                {
                    if (!Utils.CompareDistinguishedName(target.Subject, certificate.Subject))
                    {
                        continue;
                    }
                    if (Utils.GetApplicationUriFromCertficate(target) == applicationUri)
                    {
                        store.Delete(target.Thumbprint);
                    }
                }

                // add new certificate.
                store.Add(new X509Certificate2(certificate.RawData));
            }
            finally
            {
                store.Close();
            }
        }
Пример #35
0
        private void BrowseBTN_Click(object sender, EventArgs e)
        {
            CertificateStoreIdentifier store = new CertificateStoreIdentifier();
            store.StoreType = CertificateStoreIdentifier.DetermineStoreType(CertificateStoreControl.Text);
            store.StorePath = CertificateStoreControl.Text;

            store = new CertificateStoreDlg().ShowDialog(store);

            if (store == null)
            {
                return;
            }

            CertificateStoreControl.Text = store.StorePath;

            if (m_CertificateStoreSelected != null)
            {
                m_CertificateStoreSelected(this, new EventArgs());
            }
        }
Пример #36
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateStoreIdentifier ShowDialog(CertificateStoreIdentifier store)
        {
            CertificateStoreCTRL.StoreType = CertificateStoreType.Directory;
            CertificateStoreCTRL.StorePath = null;

            if (store != null)
            {
                CertificateStoreCTRL.StoreType = store.StoreType;
                CertificateStoreCTRL.StorePath = store.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return null;
            }

            store = new CertificateStoreIdentifier();
            store.StoreType = CertificateStoreCTRL.StoreType;
            store.StorePath = CertificateStoreCTRL.StorePath;
            return store;
        }
Пример #37
0
        /// <summary>
        /// Displays the dialog.
        /// </summary>
        public CertificateIdentifier ShowDialog(CertificateStoreIdentifier store)
        {
            CertificateStoreCTRL.StoreType = null;
            CertificateStoreCTRL.StorePath = null;
            ApplicationNameTB.Text = null;
            SubjectNameTB.Text = null;
            KeySizeCB.SelectedIndex = 0;
            LifeTimeInMonthsUD.Value = 60;

            if (store != null)
            {
                CertificateStoreCTRL.StoreType = store.StoreType;
                CertificateStoreCTRL.StorePath = store.StorePath;
            }

            if (ShowDialog() != DialogResult.OK)
            {
                return null;
            }

            return m_certificate;
        }
Пример #38
0
        private void ExportPrivateKeyBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Select Certificate to Export";

                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = ManagedStoreCTRL.StoreType;
                store.StorePath = ManagedStoreCTRL.StorePath;

                CertificateIdentifier id = new CertificateListDlg().ShowDialog(store, true);

                if (id == null)
                {
                    return;
                }

                X509Certificate2 certificate = id.Find(false);

                if (certificate == null)
                {
                    MessageBox.Show(
                        this,
                        "Certificate does not exist or its private key cannot be accessed.",
                        caption,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);

                    return;
                }

                string displayName = null;

                foreach (string element in Utils.ParseDistinguishedName(certificate.Subject))
                {
                    if (element.StartsWith("CN="))
                    {
                        displayName = element.Substring(3);
                        break;
                    }
                }

                StringBuilder filePath = new StringBuilder();

                if (!String.IsNullOrEmpty(displayName))
                {
                    filePath.Append(displayName);
                    filePath.Append(" ");
                }

                filePath.Append("[");
                filePath.Append(certificate.Thumbprint);
                filePath.Append("].pfx");

                SaveFileDialog dialog = new SaveFileDialog();

                dialog.CheckFileExists = false;
                dialog.CheckPathExists = true;
                dialog.DefaultExt = ".pfx";
                dialog.Filter = "PKCS#12 Files (*.pfx)|*.pfx|All Files (*.*)|*.*";
                dialog.ValidateNames = true;
                dialog.Title = "Save Private File";
                dialog.FileName = filePath.ToString();
                dialog.InitialDirectory = m_currentDirectory;

                if (dialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                string password = new PasswordDlg().ShowDialog(null, "Password recommended");

                FileInfo fileInfo = new FileInfo(dialog.FileName);
                m_currentDirectory = fileInfo.DirectoryName;

                // save the file.
                using (Stream ostrm = fileInfo.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    byte[] data = certificate.Export(X509ContentType.Pkcs12, password);
                    ostrm.Write(data, 0, data.Length);
                }

                // save the public key.
                string fileRoot = fileInfo.FullName.Substring(0, fileInfo.FullName.Length - fileInfo.Extension.Length);
                fileRoot += ".der";

                using (Stream ostrm = File.Open(fileRoot, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    byte[] data = certificate.RawData;
                    ostrm.Write(data, 0, data.Length);
                }

                // check if original certificate should be deleted.
                if (new YesNoDlg().ShowDialog("Delete original certificate?", caption) == DialogResult.Yes)
                {                    
                    ICertificateStore physicalStore = id.OpenStore();

                    try
                    {
                        physicalStore.Delete(certificate.Thumbprint);
                    }
                    finally
                    {
                        physicalStore.Close();
                    }
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #39
0
        /// <summary>
        /// Gets the default store.
        /// </summary>
        private CertificateStoreIdentifier GetDefaultStore(ManagedApplication application, bool useApplicationCertificate)
        {
            CertificateStoreIdentifier store = m_currentStore;

            if (m_currentStore != null)
            {
                return m_currentStore;
            }
                
            store = new CertificateStoreIdentifier();

            if (application != null)
            {
                if (useApplicationCertificate && application.Certificate != null && !String.IsNullOrEmpty(application.Certificate.StorePath))
                {
                    store.StoreType = application.Certificate.StoreType;
                    store.StorePath = application.Certificate.StorePath;
                    return store;
                }

                if (application.TrustList != null && !String.IsNullOrEmpty(application.TrustList.StorePath))
                {
                    store.StoreType = application.TrustList.StoreType;
                    store.StorePath = application.TrustList.StorePath;
                    return store;
                }
            }

            store.StoreType = Utils.DefaultStoreType;
            store.StorePath = Utils.DefaultStorePath;
            return store;
        }
Пример #40
0
 public ContainerInfo(ContainerInfoType type, CertificateStoreIdentifier store)
 {
     Type = type;
     DisplayName = store.ToString();
     Store = store;
 }
Пример #41
0
        private void ImportCertificateListToStoreBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Import Certificate List";
                
                CertificateStoreIdentifier list1 = new CertificateStoreIdentifier();
                list1.StoreType = ManagedStoreCTRL.StoreType;
                list1.StorePath = ManagedStoreCTRL.StorePath;

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

                CertificateStoreIdentifier list2 = new CertificateStoreDlg().ShowDialog(m_currentStore);

                if (list2 == null)
                {
                    return;
                }

                m_currentStore = list2;

                int count = 0;
                ICertificateStore store1 = list1.OpenStore();
                ICertificateStore store2 = list2.OpenStore();

                try
                {
                    foreach (X509Certificate2 certificate in store2.Enumerate())
                    {
                        if (store1.FindByThumbprint(certificate.Thumbprint) == null)
                        {
                            store1.Add(certificate);
                            count++;
                        }
                    }
                }
                finally
                {
                    store1.Close();
                    store2.Close();
                }

                MessageBox.Show(
                    this,
                    count.ToString() + " certificates added.",
                    caption,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #42
0
        private void CertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = m_certificate.StoreType;
                store.StorePath = m_certificate.StorePath;
               
                CertificateIdentifier certificate = new CertificateListDlg().ShowDialog(store, true);

                if (certificate != null)
                {
                    m_certificate = certificate;
                    CertificateTB.Text = m_certificate.Thumbprint;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #43
0
            /// <summary>
            /// Returns a store for the container.
            /// </summary>
            public CertificateStoreIdentifier GetCertificateStore()
            {
                if (this.Store != null)
                {
                    return this.Store;
                }

                if (this.CertificateStore != null)
                {
                    CertificateStoreIdentifier store = new CertificateStoreIdentifier();

                    store.StoreType = CertificateStoreType.Windows;
                    store.StorePath = this.CertificateStore.Format();
                    
                    return store;
                }

                return null;
            }
Пример #44
0
        private void ImportAndIssueCertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Select Certificate to Import";

                // set current directory.
                if (m_currentDirectory == null)
                {
                    m_currentDirectory = Utils.GetAbsoluteDirectoryPath("%LocalApplicationData%", false, false, false);
                }

                // open file dialog.
                OpenFileDialog dialog = new OpenFileDialog();

                dialog.CheckFileExists = true;
                dialog.CheckPathExists = true;
                dialog.DefaultExt = ".pfx";
                dialog.Filter = "Certificate Files (*.der)|*.der|All Files (*.*)|*.*";
                dialog.Multiselect = false;
                dialog.ValidateNames = true;
                dialog.Title = "Open Certificate File";
                dialog.FileName = null;
                dialog.InitialDirectory = m_currentDirectory;
                dialog.RestoreDirectory = true;

                if (dialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                FileInfo fileInfo = new FileInfo(dialog.FileName);
                m_currentDirectory = fileInfo.Directory.FullName;
                
                X509Certificate2 certificate = new X509Certificate2(fileInfo.FullName);

                if (certificate == null)
                {
                    return;
                }

                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = ManagedStoreCTRL.StoreType;
                store.StorePath = ManagedStoreCTRL.StorePath;

                CertificateIdentifier id = new CreateCertificateDlg().ShowDialog(store, IssuerKeyFilePathTB.Text, certificate);

                if (id == null)
                {
                    return;
                }

                certificate = id.Find(true);

                MessageBox.Show(
                    this,
                    certificate.Subject + " issued.",
                    caption,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #45
0
        private void UpdateApplicationCertificate(Opc.Ua.Security.SecuredApplication application, CertificateStoreIdentifier store, X509Certificate2 certificate)
        {
            if (!certificate.HasPrivateKey)
            {
                MessageBox.Show("Cannot use a certificate without an accessible private key.", "Import Certificate", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // check if the old certificate should be deleted.
            Opc.Ua.Security.CertificateIdentifier oldId = application.ApplicationCertificate;

            if (oldId != null)
            {
                X509Certificate2 oldCertificate = oldId.Find();

                if (oldCertificate != null && oldCertificate.Thumbprint != certificate.Thumbprint)
                {
                    if (new YesNoDlg().ShowDialog("Would you like to delete the old certificate?", "Delete Certificate") == DialogResult.Yes)
                    {
                        DeleteApplicationCertificate(application, oldCertificate);
                    }
                }
            }

            // set the application name.
            List<string> subjectName = Utils.ParseDistinguishedName(certificate.Subject);

            foreach (string subjectField in subjectName)
            {
                if (subjectField.StartsWith("CN="))
                {
                    application.ApplicationName = subjectField.Substring(3);
                    break;
                }
            }

            // set the application uri.
            string applicationUri = Utils.GetApplicationUriFromCertficate(certificate);

            if (applicationUri != null)
            {
                application.ApplicationUri = applicationUri;
            }

            // update the certificate.
            application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier();
            application.ApplicationCertificate.StorePath = store.StorePath;
            application.ApplicationCertificate.StoreType = store.StoreType;
            application.ApplicationCertificate.SubjectName = certificate.Subject;
            application.ApplicationCertificate.Thumbprint = certificate.Thumbprint;

            // save the configuration.
            new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(application.ConfigurationFile, application);
        }
Пример #46
0
 private void ViewBTN_Click(object sender, EventArgs e)
 {
     try
     {
         CertificateStoreIdentifier store = new CertificateStoreIdentifier();
         store.StoreType = CertificateStoreCTRL.StoreType;
         store.StorePath = CertificateStoreCTRL.StorePath;
         new CertificateListDlg().ShowDialog(store, false);
     }
     catch (Exception exception)
     {
         GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
     }
 }
Пример #47
0
        private void IssueSslCertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = ManagedStoreCTRL.StoreType;
                store.StorePath = ManagedStoreCTRL.StorePath;

                CertificateIdentifier id = new CreateSslCertificateDlg().ShowDialog(store, IssuerKeyFilePathTB.Text, null);

                if (id == null)
                {
                    return;
                }
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #48
0
        private void BindSslCertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = ManagedStoreCTRL.StoreType;
                store.StorePath = ManagedStoreCTRL.StorePath;

                new ManageSslBindingsDlg().ShowDialog(store);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
        private void OkBTN_Click(object sender, EventArgs e)
        {
            try
            {
                string storeType = null;
                string storePath = null;
                string domainName = null;
                string organization = null;
                string subjectName = SubjectNameTB.Text.Trim();
                string issuerKeyFilePath = IssuerKeyFilePathTB.Text.Trim();
                string issuerKeyFilePassword = IssuerPasswordTB.Text.Trim();

                if (String.IsNullOrEmpty(issuerKeyFilePath))
                {
                    throw new ApplicationException("Must provide an issuer certificate.");
                }

                // verify certificate.
                X509Certificate2 issuer = new X509Certificate2(
                    issuerKeyFilePath,
                    issuerKeyFilePassword,
                    X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
                
                if (!issuer.HasPrivateKey)
                {
                    throw new ApplicationException("Issuer certificate does not have a private key.");
                }

                // determine certificate type.
                foreach (X509Extension extension in issuer.Extensions)
                {
                    X509BasicConstraintsExtension basicContraints = extension as X509BasicConstraintsExtension;

                    if (basicContraints != null)
                    {
                        if (!basicContraints.CertificateAuthority)
                        {
                            throw new ApplicationException("Certificate cannot be used to issue new certificates.");
                        }
                    }
                }

                // check traget store.
                if (!String.IsNullOrEmpty(CertificateStoreCTRL.StorePath))
                {
                    storeType = CertificateStoreCTRL.StoreType;
                    storePath = CertificateStoreCTRL.StorePath;
                }

                if (String.IsNullOrEmpty(storePath))
                {
                    throw new ApplicationException("Please specify a store path.");
                }

                domainName = DomainNameTB.Text;
                organization = OrganizationTB.Text;

                // extract key fields from the subject name.
                if (SubjectNameCK.Checked)
                {
                    List<string> parts = Utils.ParseDistinguishedName(SubjectNameTB.Text);

                    for (int ii = 0; ii < parts.Count; ii++)
                    {
                        if (parts[ii].StartsWith("CN="))
                        {
                            domainName = parts[ii].Substring(3).Trim();
                        }

                        if (parts[ii].StartsWith("O="))
                        {
                            organization = parts[ii].Substring(2).Trim();
                        }
                    }
                }

                if (String.IsNullOrEmpty(domainName))
                {
                    throw new ApplicationException("Please specify a domain name.");
                }

                if (!String.IsNullOrEmpty(DomainNameTB.Text) && domainName != DomainNameTB.Text)
                {
                    throw new ApplicationException("The domain name must be the common name for the certificate.");
                }

                if (!String.IsNullOrEmpty(OrganizationTB.Text) && organization != OrganizationTB.Text)
                {
                    throw new ApplicationException("The organization must be the organization for the certificate.");
                }
                
                X509Certificate2 certificate = Opc.Ua.CertificateFactory.CreateCertificate(
                    storeType,
                    storePath,
                    null,
                    null,
                    domainName,
                    subjectName,
                    null,
                    Convert.ToUInt16(KeySizeCB.SelectedItem.ToString()),
                    DateTime.MinValue,
                    (ushort)LifeTimeInMonthsUD.Value,
                    0,
                    false,
                    false,
                    issuerKeyFilePath,
                    issuerKeyFilePassword);

                m_certificate = new CertificateIdentifier();
                m_certificate.StoreType = storeType;
                m_certificate.StorePath = storePath;
                m_certificate.Certificate = certificate;

                try
                {
                    CertificateStoreIdentifier rootStore = new CertificateStoreIdentifier();
                    rootStore.StoreType = CertificateStoreType.Windows;
                    rootStore.StorePath = "LocalMachine\\Root";

                    using (ICertificateStore store = rootStore.OpenStore())
                    {
                        X509Certificate2 rootCertificate = new X509Certificate2(issuerKeyFilePath, issuerKeyFilePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                        if (store.FindByThumbprint(rootCertificate.Thumbprint) == null)
                        {
                            if (Ask("Would you like to install the signing certificate as a trusted root authority on this machine?"))
                            {
                                store.Add(new X509Certificate2(rootCertificate.RawData));
                            }
                        }
                    }
                }
                catch (Exception exception)
                {
                    GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception);
                }
                
                // close the dialog.
                DialogResult = DialogResult.OK;
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, System.Reflection.MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #50
0
        /// <summary>
        /// Creates a new self signed for a certificate.
        /// </summary>
        private void CreateApplicationCertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                // get application.
                ManagedApplication application = ApplicationToManageCTRL.GetSelectedApplication();;

                if (application == null)
                {
                    return;
                }

                // load the configuration.
                application.Reload();

                // can't set application certificate for non-sdk apps.
                if (!application.IsSdkCompatible)
                {
                    return;
                }

                // create the certificate.
                CertificateIdentifier certificate = new CreateCertificateDlg().ShowDialog(application.Application);

                if (certificate == null)
                {
                    return;
                }

                // save the configuration.
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StorePath = certificate.StorePath;
                store.StoreType = certificate.StoreType;
                m_currentStore = store;

                UpdateApplicationCertificate(application.Application, store, certificate.Certificate);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #51
0
        private void ImportCertificateToStoreBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Import Certificate";

                CertificateStoreIdentifier list1 = new CertificateStoreIdentifier();
                list1.StoreType = ManagedStoreCTRL.StoreType;
                list1.StorePath = ManagedStoreCTRL.StorePath;

                // set current directory.
                if (m_currentDirectory == null)
                {
                    m_currentDirectory = Utils.GetAbsoluteDirectoryPath("%CommonApplicationData%\\OPC Foundation\\CertificateStores\\UA Applications", false, false);
                }

                if (m_currentDirectory == null)
                {
                    m_currentDirectory = new FileInfo(Application.ExecutablePath).DirectoryName;
                }

                // open file dialog.
                OpenFileDialog dialog = new OpenFileDialog();

                dialog.CheckFileExists = true;
                dialog.CheckPathExists = true;
                dialog.DefaultExt = ".der";
                dialog.Filter = "DER Files (*.der)|*.der|PKCS #12 Files (*.pfx)|*.pfx|All Files (*.*)|*.*";
                dialog.Multiselect = false;
                dialog.ValidateNames = true;
                dialog.Title = caption;
                dialog.FileName = null;
                dialog.InitialDirectory = m_currentDirectory;
                dialog.RestoreDirectory = true;

                if (dialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                FileInfo fileInfo = new FileInfo(dialog.FileName);
                m_currentDirectory = fileInfo.Directory.FullName;

                if (!fileInfo.Exists)
                {
                    return;
                }

                X509Certificate2 certificate = new X509Certificate2(fileInfo.FullName, (string)null, X509KeyStorageFlags.Exportable);
                ValidateAndImport(list1, certificate);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #52
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);
            }
        }
Пример #53
0
        /// <summary>
        /// Displays the applications in the control.
        /// </summary>
        internal void Initialize(CertificateStoreIdentifier id, IList<string> thumbprints)
        {
            ItemsLV.Items.Clear();

            m_storeId = id;
            m_thumbprints = thumbprints;

            if (m_storeId == null || String.IsNullOrEmpty(m_storeId.StoreType) || String.IsNullOrEmpty(m_storeId.StorePath))
            {
                Instructions = "No certificates are in the store.";
                AdjustColumns();
                return;
            }

            try
            {
                // get the store.
                using (ICertificateStore store = m_storeId.OpenStore())
                {
                    // only show certificates with the specified thumbprint.
                    if (thumbprints != null)
                    {
                        Instructions = "None of the selected certificates can be found in the store.";

                        foreach (string thumbprint in thumbprints)
                        {
                            X509Certificate2 certificate = store.FindByThumbprint(thumbprint);

                            if (certificate != null)
                            {
                                AddItem(certificate);
                            }
                        }
                    }

                    // show all certificates.
                    else
                    {
                        Instructions = "No certificates are in the store.";

                        foreach (X509Certificate2 certificate in store.Enumerate())
                        {
                            AddItem(certificate);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Instructions = "An error occurred opening the store: " + e.Message;
            }
            
            // save the unfiltered list.
            m_items = new List<ListViewItem>(ItemsLV.Items.Count);

            foreach (ListViewItem item in ItemsLV.Items)
            {
                m_items.Add(item);
            }

            AdjustColumns();

        }
Пример #54
0
        /// <summary>
        /// Assigns a certificate to the application.
        /// </summary>
        private void AssignTrustListBTN_Click(object sender, EventArgs e)
        {
            try
            {
                // get application.
                ManagedApplication application = ApplicationToManageCTRL.GetSelectedApplication();;

                if (application == null)
                {
                    return;
                }
                
                // load the configuration.
                application.Reload();

                // can't set application certificate for non-sdk apps.
                if (!application.IsSdkCompatible)
                {
                    return;
                }

                CertificateStoreIdentifier store = application.TrustList;

                if (store == null)
                {
                    store = GetDefaultStore(application, false);
                }

                // prompt for the store to open.
                store = new CertificateStoreDlg().ShowDialog(store);

                if (store == null)
                {
                    return;
                }

                // update the trust list.
                application.Application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier();
                application.Application.TrustedCertificateStore.StorePath = store.StorePath;
                application.Application.TrustedCertificateStore.StoreType = store.StoreType;
                application.Application.TrustedCertificates = new Opc.Ua.Security.CertificateList();

                m_currentStore = store;

                // save the configuration.
                new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(application.Application.ConfigurationFile, application.Application);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #55
0
        private void AddCertificateToTrustListBTN_Click(object sender, EventArgs e)
        {
            try
            {
                // get application.
                ManagedApplication application = ApplicationToManageCTRL.GetSelectedApplication();;

                if (application == null)
                {
                    return;
                }
                
                // load the configuration.
                application.Reload();

                CertificateStoreIdentifier store = GetDefaultStore(application, false);

                // show the list of rejected certificates.
                CertificateIdentifier id = new CertificateListDlg().ShowDialog(store, true);

                if (id == null)
                {
                    return;
                }

                store = new CertificateStoreIdentifier();
                store.StoreType = id.StoreType;
                store.StorePath = id.StorePath;
                m_currentStore = store;

                X509Certificate2 certificate = id.Find();
                ValidateAndImport(application.TrustList, certificate);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
        private void CertificateStoreCTRL_StoreChanged(object sender, EventArgs e)
        {
            try
            {
                CertificateStoreIdentifier store = new CertificateStoreIdentifier();
                store.StoreType = CertificateStoreCTRL.StoreType;
                store.StorePath = CertificateStoreCTRL.StorePath;
                Task.Run( async () => await CertificatesCTRL.Initialize(store, null)).Wait();

                FilterBTN_Click(sender, e);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #57
0
        private void ImportCertificateListToTrustBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Import Certificate List";

                ManagedApplication application = ManageApplicationSecurityCTRL.GetSelectedApplication();

                if (application == null)
                {
                    return;
                }

                if (application.TrustList == null)
                {
                    MessageBox.Show(application.ToString() + " does not have a trust list defined.", caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

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

                CertificateStoreIdentifier store = new CertificateStoreDlg().ShowDialog(m_currentStore);

                if (store == null)
                {
                    return;
                }

                m_currentStore = store;

                int count = 0;
                ICertificateStore store1 = application.TrustList.OpenStore();
                ICertificateStore store2 = store.OpenStore();

                try
                {
                    foreach (X509Certificate2 certificate in store2.Enumerate())
                    {
                        if (store1.FindByThumbprint(certificate.Thumbprint) == null)
                        {
                            store1.Add(certificate);
                            count++;
                        }
                    }
                }
                finally
                {
                    store1.Close();
                    store2.Close();
                }

                MessageBox.Show(
                    this,
                    count.ToString() + " certificates added.",
                    caption,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #58
0
        /// <summary>
        /// Validates a certificate and adds it to the trust list.
        /// </summary>
        private void ValidateAndImport(CertificateStoreIdentifier store, X509Certificate2 certificate)
        {
            if (store == null || certificate == null)
            {
                return;
            }

            // validate the certificate using the trust lists for the certificate tool.                                
            try
            {
                CertificateValidator validator = new CertificateValidator();
                validator.Update(m_configuration);
                validator.Validate(certificate);
            }
            catch (ServiceResultException exception)
            {
                if (!HandleValidationError(certificate, exception))
                {
                    return;
                }
            }

            // confirm import.
            StringBuilder buffer = new StringBuilder();

            buffer.Append("You are adding this certificate to a trust list that may be shared with other applications.");
            buffer.Append("\r\n");
            buffer.Append("\r\n");
            buffer.Append("Would you still like to accept the certificate?\r\n");
            buffer.Append("\r\n");
            buffer.Append("Target Trust List = ");
            buffer.Append(store.ToString());
            buffer.Append("\r\n");
            buffer.Append("Certificate to Add = ");
            buffer.Append(certificate.Subject);

            DialogResult result = new YesNoDlg().ShowDialog(buffer.ToString(), "Import Certificate to Trust List");

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

            // update store.
            ICertificateStore physicalStore = store.OpenStore();

            if (physicalStore.FindByThumbprint(certificate.Thumbprint) == null)
            {
                physicalStore.Add(new X509Certificate2(certificate.RawData));
            }
        }
Пример #59
0
        /// <summary>
        /// Browses for a certificate to import.
        /// </summary>
        private void ImportApplicationCertificateBTN_Click(object sender, EventArgs e)
        {
            try
            {
                // get application.
                ManagedApplication application = ApplicationToManageCTRL.GetSelectedApplication();;

                if (application == null)
                {
                    return;
                }

                // load the configuration.
                application.Reload();

                // can't set application certificate for non-sdk apps.
                if (!application.IsSdkCompatible)
                {
                    return;
                }

                // set current directory.
                if (m_currentDirectory == null)
                {
                    m_currentDirectory = Utils.GetAbsoluteDirectoryPath("%CommonApplicationData%\\OPC Foundation\\CertificateStores\\MachineDefault", false, false);
                }

                if (m_currentDirectory == null)
                {
                    m_currentDirectory = new FileInfo(Application.ExecutablePath).DirectoryName;
                }

                // open file dialog.
                OpenFileDialog dialog = new OpenFileDialog();

                dialog.CheckFileExists = true;
                dialog.CheckPathExists = true;
                dialog.DefaultExt = ".pfx";
                dialog.Filter = "PKCS#12 Files (*.pfx)|*.pfx|All Files (*.*)|*.*";
                dialog.Multiselect = false;
                dialog.ValidateNames = true;
                dialog.Title = "Open Application Certificate File";
                dialog.FileName = null;
                dialog.InitialDirectory = m_currentDirectory;
                dialog.RestoreDirectory = true;

                if (dialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                FileInfo fileInfo = new FileInfo(dialog.FileName);
                m_currentDirectory = fileInfo.Directory.FullName;

                CertificateStoreIdentifier store = GetDefaultStore(application, true);

                // prompt for the store to import into.
                store = new CertificateStoreDlg().ShowDialog(store);

                if (store == null)
                {
                    return;
                }

                m_currentStore = store;
                string password = String.Empty;
                X509Certificate2 certificate = null;

                do
                {
                    try
                    {
                        // load the certificate.
                        certificate = new X509Certificate2(
                            fileInfo.FullName,
                            password,
                            X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);

                        if (!certificate.HasPrivateKey)
                        {
                            MessageBox.Show("Certificate does not have a private key.", "Import Certificate", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }

                        // import certificate.
                        ICertificateStore physicalStore = store.OpenStore();
                        physicalStore.Add(certificate);
                        physicalStore.Close();
                        break;
                    }
                    catch (System.Security.Cryptography.CryptographicException exception)
                    {
                        // prompt for password.
                        password = new PasswordDlg().ShowDialog(password, exception.Message);

                        if (password == null)
                        {
                            return;
                        }
                    }
                }
                while (true);

                UpdateApplicationCertificate(application.Application, store, certificate);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }
Пример #60
0
        private void SelectCertificateToTrustBTN_Click(object sender, EventArgs e)
        {
            try
            {
                const string caption = "Select Certificate to Trust";

                ManagedApplication application = ManageApplicationSecurityCTRL.GetSelectedApplication();

                if (application == null)
                {
                    return;
                }

                if (application.TrustList == null)
                {
                    MessageBox.Show(application.ToString() + " does not have a trust list defined.", caption, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

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

                CertificateIdentifier id = new CertificateListDlg().ShowDialog(m_currentStore, true);

                if (id == null)
                {
                    return;
                }

                m_currentStore.StoreType = id.StoreType;
                m_currentStore.StorePath = id.StorePath;

                X509Certificate2 certificate = id.Find();

                if (certificate == null)
                {
                    return;
                }

                ICertificateStore store = application.TrustList.OpenStore();

                try
                {
                    if (store.FindByThumbprint(certificate.Thumbprint) == null)
                    {
                        store.Add(new X509Certificate2(certificate.RawData));
                    }
                }
                finally
                {
                    store.Close();
                }

                MessageBox.Show(
                    this,
                    certificate.Subject + " now trusted.",
                    caption,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
            catch (Exception exception)
            {
                GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception);
            }
        }