/// <summary> /// Displays the applications in the control. /// </summary> internal async 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. 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) { X509Certificate2Collection certificates = await store.FindByThumbprint(thumbprint); if (certificates.Count > 0) { AddItem(certificates[0]); } } } // show all certificates. else { Instructions = "No certificates are in the store."; X509Certificate2Collection certificates = await store.Enumerate(); foreach (X509Certificate2 certificate in certificates) { 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(); }
/// <summary> /// Adds a certificate binding to to list. /// </summary> private void AddRow(SslCertificateBinding binding) { DataRow row = m_dataset.Tables[0].NewRow(); row[0] = binding.IPAddress; row[1] = binding.Port; row[3] = binding.Thumbprint; row[4] = binding; CertificateStoreIdentifier id = new CertificateStoreIdentifier(); id.StoreType = CertificateStoreType.Windows; id.StorePath = "LocalMachine\\" + ((String.IsNullOrEmpty(binding.StoreName)) ? "My" : binding.StoreName); using (ICertificateStore store = id.OpenStore()) { X509Certificate2 certificate = store.FindByThumbprint(binding.Thumbprint); if (certificate != null) { row[2] = certificate.Subject; } else { row[2] = "<not found>"; } } m_dataset.Tables[0].Rows.Add(row); }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // validate new subject matches the previous subject if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.Certificate.SubjectName, newCert.SubjectName)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = X509Utils.IsSelfSigned(newCert); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; if (updateCertificate != null) { try { using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore()) { Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate); appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey); var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait(); // keep only track of cert without private key var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData); updateCertificate.CertificateWithPrivateKey.Dispose(); updateCertificate.CertificateWithPrivateKey = certOnly; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer); issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } } catch (Exception ex) { Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex)); throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex); } } return(ServiceResult.Good); }
/// <summary> /// Updates an item in the view. /// </summary> protected override void UpdateItem(ListViewItem listItem, object item) { X509Certificate2 certificate = item as X509Certificate2; if (certificate == null) { base.UpdateItem(listItem, item); return; } listItem.SubItems[0].Text = null; listItem.SubItems[1].Text = null; listItem.SubItems[2].Text = null; listItem.SubItems[3].Text = null; listItem.SubItems[4].Text = null; listItem.SubItems[5].Text = null; if (certificate != null) { List <string> fields = Utils.ParseDistinguishedName(certificate.Subject); for (int ii = 0; ii < fields.Count; ii++) { if (fields[ii].StartsWith("CN=")) { listItem.SubItems[0].Text = fields[ii].Substring(3); } if (fields[ii].StartsWith("DC=")) { listItem.SubItems[1].Text = fields[ii].Substring(3); } } if (String.IsNullOrEmpty(listItem.SubItems[0].Text)) { listItem.SubItems[0].Text = String.Format("{0}", certificate.Subject); } // determine certificate type. foreach (X509Extension extension in certificate.Extensions) { X509BasicConstraintsExtension basicContraints = extension as X509BasicConstraintsExtension; if (basicContraints != null) { if (basicContraints.CertificateAuthority) { listItem.SubItems[1].Text = "CA"; } else { listItem.SubItems[1].Text = "End-Entity"; } break; } } // check if a private key is available. if (certificate.HasPrivateKey) { listItem.SubItems[2].Text = "Yes"; } else { listItem.SubItems[2].Text = "No"; if (m_storeId != null) { ICertificateStore store = m_storeId.OpenStore(); try { if (store.GetPrivateKeyFilePath(certificate.Thumbprint) != null) { listItem.SubItems[2].Text = "Yes (No Access)"; } } catch (Exception e) { listItem.SubItems[2].Text = e.Message; } finally { store.Close(); } } } // look up domains. IList <string> domains = Utils.GetDomainsFromCertficate(certificate); StringBuilder buffer = new StringBuilder(); for (int ii = 0; ii < domains.Count; ii++) { if (buffer.Length > 0) { buffer.Append(";"); } buffer.Append(domains[ii]); } listItem.SubItems[3].Text = buffer.ToString(); listItem.SubItems[4].Text = Utils.GetApplicationUriFromCertficate(certificate); listItem.SubItems[5].Text = String.Format("{0:yyyy-MM-dd}", certificate.NotAfter); } listItem.ImageKey = GuiUtils.Icons.Certificate; listItem.Tag = item; }
/// <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(); }
/// <summary> /// Revoke the CA signed certificate. /// The issuer CA public key, the private key and the crl reside in the storepath. /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store. /// </summary> public static async Task <X509CRL> RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { X509CRL updatedCRL = null; try { string subjectName = certificate.IssuerName.Name; string keyId = null; string serialNumber = null; // caller may want to create empty CRL using the CA cert itself bool isCACert = IsCertificateAuthority(certificate); // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = FindAuthorityKeyIdentifier(certificate); if (authority != null) { keyId = authority.KeyId; serialNumber = authority.SerialNumber; } else { throw new ArgumentException("Certificate does not contain an Authority Key"); } if (!isCACert) { if (serialNumber == certificate.SerialNumber || Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates"); } } X509Certificate2 certCA = null; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { if (store == null) { throw new ArgumentException("Invalid store path/type"); } certCA = await FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber); if (certCA == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store."); } if (!certCA.HasPrivateKey) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate."); } CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA); certCAIdentifier.StorePath = storePath; certCAIdentifier.StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath); X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword); if (certCAWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?"); } List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false); using (var cfrg = new CertificateFactoryRandomGenerator()) { // cert generators SecureRandom random = new SecureRandom(cfrg); BigInteger crlSerialNumber = BigInteger.Zero; Org.BouncyCastle.X509.X509Certificate bcCertCA = new X509CertificateParser().ReadCertificate(certCA.RawData); AsymmetricKeyParameter signingKey = GetPrivateKeyParameter(certCAWithPrivateKey); ISignatureFactory signatureFactory = new Asn1SignatureFactory(GetRSAHashAlgorithm(defaultHashSize), signingKey, random); X509V2CrlGenerator crlGen = new X509V2CrlGenerator(); crlGen.SetIssuerDN(bcCertCA.IssuerDN); crlGen.SetThisUpdate(DateTime.UtcNow); crlGen.SetNextUpdate(DateTime.UtcNow.AddMonths(12)); // merge all existing revocation list X509CrlParser parser = new X509CrlParser(); foreach (X509CRL caCrl in certCACrl) { X509Crl crl = parser.ReadCrl(caCrl.RawData); crlGen.AddCrl(crl); var crlVersion = GetCrlNumber(crl); if (crlVersion.IntValue > crlSerialNumber.IntValue) { crlSerialNumber = crlVersion; } } if (isCACert) { // add a dummy revoked cert crlGen.AddCrlEntry(BigInteger.One, DateTime.UtcNow, CrlReason.Superseded); } else { // add the revoked cert crlGen.AddCrlEntry(GetSerialNumber(certificate), DateTime.UtcNow, CrlReason.PrivilegeWithdrawn); } crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(bcCertCA)); // set new serial number crlSerialNumber = crlSerialNumber.Add(BigInteger.One); crlGen.AddExtension(X509Extensions.CrlNumber, false, new CrlNumber(crlSerialNumber)); // generate updated CRL X509Crl updatedCrl = crlGen.Generate(signatureFactory); // add updated CRL to store updatedCRL = new X509CRL(updatedCrl.GetEncoded()); store.AddCRL(updatedCRL); // delete outdated CRLs from store foreach (X509CRL caCrl in certCACrl) { store.DeleteCRL(caCrl); } } store.Close(); } } catch (Exception e) { throw e; } return(updatedCRL); }
private ServiceResult ApplyChanges( ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { HasApplicationSecureAdminAccess(context); bool disconnectSessions = false; foreach (var certificateGroup in m_certificateGroups) { try { var updateCertificate = certificateGroup.UpdateCertificate; if (updateCertificate != null) { if (certificateGroup.UpdateCertificate.SessionId == context.SessionId) { using (ICertificateStore appStore = CertificateStoreIdentifier.OpenStore(certificateGroup.ApplicationCertificate.StorePath)) { appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); appStore.Add(updateCertificate.CertificateWithPrivateKey).Wait(); updateCertificate.CertificateWithPrivateKey = null; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } disconnectSessions = true; } } } finally { certificateGroup.UpdateCertificate = null; } } if (disconnectSessions) { Task.Run(async() => { // give the client some time to receive the response // before the certificate update may disconnect all sessions await Task.Delay(1000); await m_configuration.CertificateValidator.UpdateCertificate(m_configuration.SecurityConfiguration); } ); } return(StatusCodes.Good); }
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); } }
private ServiceResult RemoveCertificate( ISystemContext context, MethodState method, NodeId objectId, string thumbprint, bool isTrustedCertificate) { HasSecureWriteAccess(context); ServiceResult result = StatusCodes.Good; lock (m_lock) { if (m_sessionId != null) { result = StatusCodes.BadInvalidState; } else if (String.IsNullOrEmpty(thumbprint)) { result = StatusCodes.BadInvalidArgument; } else { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { var certCollection = store.FindByThumbprint(thumbprint).GetAwaiter().GetResult(); if (certCollection.Count == 0) { result = StatusCodes.BadInvalidArgument; } else { // delete all CRLs signed by cert var crlsToDelete = new X509CRLCollection(); foreach (var crl in store.EnumerateCRLs().GetAwaiter().GetResult()) { foreach (var cert in certCollection) { if (X509Utils.CompareDistinguishedName(cert.SubjectName, crl.IssuerName) && crl.VerifySignature(cert, false)) { crlsToDelete.Add(crl); break; } } } if (!store.Delete(thumbprint).GetAwaiter().GetResult()) { result = StatusCodes.BadInvalidArgument; } else { foreach (var crl in crlsToDelete) { if (!store.DeleteCRL(crl).GetAwaiter().GetResult()) { // intentionally ignore errors, try best effort Utils.LogError("RemoveCertificate: Failed to delete CRL {0}.", crl.ToString()); } } } } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } } // report the TrustListUpdatedAuditEvent object[] inputParameters = new object[] { thumbprint }; m_node.ReportTrustListUpdatedAuditEvent(context, objectId, "Method/RemoveCertificate", method.NodeId, inputParameters, result.StatusCode); return(result); }
private async void CertificateRequestTimer_Tick(object sender, EventArgs e) { try { NodeId requestId = NodeId.Parse(m_application.CertificateRequestId); byte[] privateKey = null; byte[][] issuerCertificates = null; byte[] certificate = m_gds.FinishRequest( m_application.ApplicationId, requestId, out privateKey, out issuerCertificates); if (certificate == null) { return; } CertificateRequestTimer.Enabled = false; RequestProgressLabel.Visible = false; if (m_application.RegistrationType != RegistrationType.ServerPush) { // save public key. if (!String.IsNullOrEmpty(m_application.CertificatePublicKeyPath)) { string file = Utils.GetAbsoluteFilePath(m_application.CertificatePublicKeyPath, true, false, true); File.WriteAllBytes(file, certificate); } // check if the private was re-used. if (privateKey == null || privateKey.Length == 0) { if (!String.IsNullOrEmpty(m_application.CertificatePrivateKeyPath)) { string path = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, true, true); if (path != null) { if (!m_application.CertificatePrivateKeyPath.EndsWith("PEM", StringComparison.OrdinalIgnoreCase)) { var x509 = new X509Certificate2(certificate); var oldPfx = new X509Certificate2(path, (string)null, X509KeyStorageFlags.Exportable); var newPfx = CertificateAuthority.Replace(x509, oldPfx); var bytes = newPfx.Export(X509ContentType.Pfx); File.WriteAllBytes(path, bytes); } } } else { if (!String.IsNullOrEmpty(m_application.CertificateStorePath) && !String.IsNullOrEmpty(m_application.CertificateSubjectName)) { var x509 = new X509Certificate2(certificate); var cid = new CertificateIdentifier() { StorePath = m_application.CertificateStorePath, SubjectName = m_application.CertificateSubjectName.Replace("localhost", System.Net.Dns.GetHostName()) }; var oldPfx = await cid.Find(true); if (oldPfx != null) { var newPfx = CertificateAuthority.Replace(x509, oldPfx); using (var store = CertificateStoreIdentifier.OpenStore(m_application.CertificateStorePath)) { await store.Delete(oldPfx.Thumbprint); await store.Add(newPfx); } } } } } // save private key. else { if (!String.IsNullOrEmpty(m_application.CertificatePrivateKeyPath)) { string path = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, true, true); if (path != null) { File.WriteAllBytes(path, privateKey); } } else { if (!String.IsNullOrEmpty(m_application.CertificateStorePath) && !String.IsNullOrEmpty(m_application.CertificateSubjectName)) { var cid = new CertificateIdentifier() { StorePath = m_application.CertificateStorePath, SubjectName = m_application.CertificateSubjectName }; var oldCertificate = await cid.Find(); using (var store = CertificateStoreIdentifier.OpenStore(m_application.CertificateStorePath)) { if (oldCertificate != null) { await store.Delete(oldCertificate.Thumbprint); } var x509 = new X509Certificate2(privateKey, new System.Security.SecureString(), X509KeyStorageFlags.Exportable); x509 = CertificateFactory.Load(x509, true); await store.Add(x509); } } } } // update trust list. if (!String.IsNullOrEmpty(m_application.TrustListStorePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_application.TrustListStorePath)) { foreach (var issuerCertificate in issuerCertificates) { var x509 = new X509Certificate2(issuerCertificate); if (store.FindByThumbprint(x509.Thumbprint) == null) { await store.Add(new X509Certificate2(issuerCertificate)); } } } } } else { if (privateKey != null && privateKey.Length > 0) { var x509 = new X509Certificate2(privateKey, m_certificatePassword, X509KeyStorageFlags.Exportable); privateKey = x509.Export(X509ContentType.Pfx); } bool applyChanges = m_server.UpdateCertificate(null, null, certificate, GetPrivateKeyFormat(), privateKey, issuerCertificates); if (applyChanges) { MessageBox.Show( Parent, "The certificate was updated, however, the apply changes command must be sent before the server will use the new certificate.", Parent.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); ApplyChangesButton.Enabled = true; } } m_certificate = new X509Certificate2(certificate); CertificateControl.ShowValue(null, "Application Certificate", new CertificateWrapper() { Certificate = m_certificate }, true); } catch (Exception exception) { var sre = exception as ServiceResultException; if (sre != null && sre.StatusCode == StatusCodes.BadNothingToDo) { return; } MessageBox.Show(Parent.Text + ": " + exception.Message); CertificateRequestTimer.Enabled = false; } }
public override async Task Init() { Utils.Trace(Utils.TraceMasks.Information, "InitializeCertificateGroup: {0}", m_subjectName); X509Certificate2Collection rootCACertificateChain; IList <Opc.Ua.X509CRL> rootCACrlChain; try { // read root CA chain for certificate group rootCACertificateChain = await _opcVaultHandler.GetCACertificateChainAsync(Configuration.Id).ConfigureAwait(false); rootCACrlChain = await _opcVaultHandler.GetCACrlChainAsync(Configuration.Id).ConfigureAwait(false); var rootCaCert = rootCACertificateChain[0]; var rootCaCrl = rootCACrlChain[0]; if (Utils.CompareDistinguishedName(rootCaCert.Subject, m_subjectName)) { Certificate = rootCaCert; rootCaCrl.VerifySignature(rootCaCert, true); } else { throw new ServiceResultException("Key Vault certificate subject(" + rootCaCert.Subject + ") does not match cert group subject " + m_subjectName); } } catch (Exception ex) { Utils.Trace("Failed to load CA certificate " + Configuration.Id + " from key Vault "); Utils.Trace(ex.Message); throw ex; } // add all existing cert versions to trust list // erase old certs using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath)) { try { X509Certificate2Collection certificates = await store.Enumerate(); foreach (var certificate in certificates) { // TODO: Subject may have changed over time if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName)) { var certs = rootCACertificateChain.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false); if (certs == null || certs.Count == 0) { Utils.Trace("Delete CA certificate from authority store: " + certificate.Thumbprint); // delete existing CRL in trusted list foreach (var crl in store.EnumerateCRLs(certificate, false)) { if (crl.VerifySignature(certificate, false)) { store.DeleteCRL(crl); } } await store.Delete(certificate.Thumbprint); } } } } catch (Exception ex) { Utils.Trace("Failed to Delete existing certificates from authority store: " + ex.Message); } foreach (var rootCACertificate in rootCACertificateChain) { X509Certificate2Collection certs = await store.FindByThumbprint(rootCACertificate.Thumbprint); if (certs.Count == 0) { await store.Add(rootCACertificate); Utils.Trace("Added CA certificate to authority store: " + rootCACertificate.Thumbprint); } else { Utils.Trace("CA certificate already exists in authority store: " + rootCACertificate.Thumbprint); } foreach (var rootCACrl in rootCACrlChain) { if (rootCACrl.VerifySignature(rootCACertificate, false)) { // delete existing CRL in trusted list foreach (var crl in store.EnumerateCRLs(rootCACertificate, false)) { if (crl.VerifySignature(rootCACertificate, false)) { store.DeleteCRL(crl); } } store.AddCRL(rootCACrl); } } } // load trust list from server var trustList = await _opcVaultHandler.GetTrustListAsync(Configuration.Id).ConfigureAwait(false); await UpdateTrustList(trustList); } }
private void PullFromGds(bool deleteBeforeAdd) { try { NodeId trustListId = m_gds.GetTrustList(m_application.ApplicationId, null); if (trustListId == null) { CertificateStoreControl.Initialize(null, null, null); return; } var trustList = m_gds.ReadTrustList(trustListId); if (m_application.RegistrationType == RegistrationType.ServerPush) { CertificateStoreControl.Initialize(trustList); MessageBox.Show( Parent, "The trust list (include CRLs) was downloaded from the GDS. It now has to be pushed to the Server.", Parent.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); return; } if (!String.IsNullOrEmpty(m_trustListStorePath)) { if (deleteBeforeAdd) { DeleteExistingFromStore(m_trustListStorePath).Wait(); DeleteExistingFromStore(m_issuerListStorePath).Wait();; } } if (!String.IsNullOrEmpty(m_trustListStorePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_trustListStorePath)) { if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.TrustedCertificates) != 0) { foreach (var certificate in trustList.TrustedCertificates) { var x509 = new X509Certificate2(certificate); X509Certificate2Collection certs = store.FindByThumbprint(x509.Thumbprint).Result; if (certs.Count == 0) { store.Add(x509).Wait(); } } } if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.TrustedCrls) != 0) { foreach (var crl in trustList.TrustedCrls) { store.AddCRL(new X509CRL(crl)); } } } } if (!String.IsNullOrEmpty(m_application.IssuerListStorePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_application.IssuerListStorePath)) { if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.IssuerCertificates) != 0) { foreach (var certificate in trustList.IssuerCertificates) { var x509 = new X509Certificate2(certificate); X509Certificate2Collection certs = store.FindByThumbprint(x509.Thumbprint).Result; if (certs.Count == 0) { store.Add(x509).Wait(); } } } if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.IssuerCrls) != 0) { foreach (var crl in trustList.IssuerCrls) { store.AddCRL(new X509CRL(crl)); } } } } CertificateStoreControl.Initialize(m_trustListStorePath, m_issuerListStorePath, null); MessageBox.Show( Parent, "The trust list (include CRLs) was downloaded from the GDS and saved locally.", Parent.Text, MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (Exception exception) { MessageBox.Show(Parent.Text + ": " + exception.Message); } }
private async void DeleteMI_Click(object sender, EventArgs e) { try { if (ItemsLV.SelectedItems.Count < 1) { return; } DialogResult result = MessageBox.Show( "Are you sure you wish to delete the certificates from the store?", "Delete Certificate", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); if (result != DialogResult.Yes) { return; } // remove the certificates. List <ListViewItem> itemsToDelete = new List <ListViewItem>(); bool yesToAll = false; using (ICertificateStore store = m_storeId.OpenStore()) { for (int ii = 0; ii < ItemsLV.SelectedItems.Count; ii++) { X509Certificate2 certificate = ItemsLV.SelectedItems[ii].Tag as X509Certificate2; // check for private key. X509Certificate2Collection certificate2 = await store.FindByThumbprint(certificate.Thumbprint); if (!yesToAll && (certificate2.Count > 0) && certificate2[0].HasPrivateKey) { StringBuilder buffer = new StringBuilder(); buffer.Append("Certificate '"); buffer.Append(certificate2[0].Subject); buffer.Append("'"); buffer.Append("Deleting it may cause applications to stop working."); buffer.Append("\r\n"); buffer.Append("\r\n"); buffer.Append("Are you sure you wish to continue?."); DialogResult yesno = new YesNoDlg().ShowDialog(buffer.ToString(), "Delete Private Key", true); if (yesno == DialogResult.No) { continue; } yesToAll = yesno == DialogResult.Retry; } if (certificate != null) { await store.Delete(certificate.Thumbprint); itemsToDelete.Add(ItemsLV.SelectedItems[ii]); } } } // remove the items. foreach (ListViewItem itemToDelete in itemsToDelete) { itemToDelete.Remove(); } } catch (Exception exception) { GuiUtils.HandleException(this.Text, MethodBase.GetCurrentMethod(), exception); await Initialize(m_storeId, m_thumbprints); } }
/// <summary> /// Adds an application certificate to a store. /// </summary> private static async Task AddApplicationCertificateToStore( CertificateStoreIdentifier csid, X509Certificate2 certificate, string oldThumbprint) { ICertificateStore store = csid.OpenStore(); try { // delete the old certificate. if (oldThumbprint != null) { await store.Delete(oldThumbprint); } // delete certificates with the same application uri. if (store.FindByThumbprint(certificate.Thumbprint) == null) { string applicationUri = Utils.GetApplicationUriFromCertificate(certificate); // delete any existing certificates. X509Certificate2Collection collection = await store.Enumerate(); foreach (X509Certificate2 target in collection) { if (Utils.CompareDistinguishedName(target.Subject, certificate.Subject)) { if (Utils.GetApplicationUriFromCertificate(target) == applicationUri) { await store.Delete(target.Thumbprint); } } } // add new certificate. await store.Add(new X509Certificate2(certificate.RawData)); } } finally { store.Close(); } }
private ServiceResult RemoveCertificate( ISystemContext context, MethodState method, NodeId objectId, string thumbprint, bool isTrustedCertificate) { HasSecureWriteAccess(context); lock (m_lock) { if (m_sessionId != null) { return(StatusCodes.BadInvalidState); } if (String.IsNullOrEmpty(thumbprint)) { return(StatusCodes.BadInvalidArgument); } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath)) { var certCollection = store.FindByThumbprint(thumbprint).Result; if (certCollection.Count == 0) { return(StatusCodes.BadInvalidArgument); } // delete all CRLs signed by cert var crlsToDelete = new List <X509CRL>(); foreach (var crl in store.EnumerateCRLs()) { foreach (var cert in certCollection) { if (Utils.CompareDistinguishedName(cert.Subject, crl.Issuer) && crl.VerifySignature(cert, false)) { crlsToDelete.Add(crl); break; } } } if (!store.Delete(thumbprint).Result) { return(StatusCodes.BadInvalidArgument); } foreach (var crl in crlsToDelete) { if (!store.DeleteCRL(crl)) { // intentionally ignore errors, try best effort Utils.Trace("RemoveCertificate: Failed to delete CRL {0}.", crl.ToString()); } } } m_node.LastUpdateTime.Value = DateTime.UtcNow; } return(ServiceResult.Good); }
/// <summary> /// Adds an application certificate to a store. /// </summary> private static void AddIssuerCertificatesToStore(CertificateStoreIdentifier csid, IList<X509Certificate2> issuers) { ICertificateStore store = csid.OpenStore(); try { foreach (X509Certificate2 issuer in issuers) { if (store.FindByThumbprint(issuer.Thumbprint) == null) { store.Add(issuer); } } } finally { store.Close(); } }
private ServiceResult Open( ISystemContext context, MethodState method, NodeId objectId, OpenFileMode mode, TrustListMasks masks, ref uint fileHandle) { HasSecureReadAccess(context); if (mode == OpenFileMode.Read) { HasSecureReadAccess(context); } else if (mode == (OpenFileMode.Write | OpenFileMode.EraseExisting)) { HasSecureWriteAccess(context); } else { return(StatusCodes.BadNotWritable); } lock (m_lock) { if (m_sessionId != null) { // to avoid deadlocks, last open always wins m_sessionId = null; m_strm = null; m_node.OpenCount.Value = 0; } m_readMode = mode == OpenFileMode.Read; m_sessionId = context.SessionId; fileHandle = ++m_fileHandle; TrustListDataType trustList = new TrustListDataType() { SpecifiedLists = (uint)masks }; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_trustedStorePath)) { if ((masks & TrustListMasks.TrustedCertificates) != 0) { X509Certificate2Collection certificates = store.Enumerate().Result; foreach (var certificate in certificates) { trustList.TrustedCertificates.Add(certificate.RawData); } } if ((masks & TrustListMasks.TrustedCrls) != 0) { foreach (var crl in store.EnumerateCRLs()) { trustList.TrustedCrls.Add(crl.RawData); } } } using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_issuerStorePath)) { if ((masks & TrustListMasks.IssuerCertificates) != 0) { X509Certificate2Collection certificates = store.Enumerate().Result; foreach (var certificate in certificates) { trustList.IssuerCertificates.Add(certificate.RawData); } } if ((masks & TrustListMasks.IssuerCrls) != 0) { foreach (var crl in store.EnumerateCRLs()) { trustList.IssuerCrls.Add(crl.RawData); } } } if (m_readMode) { m_strm = EncodeTrustListData(context, trustList); } else { m_strm = new MemoryStream(DefaultTrustListCapacity); } m_node.OpenCount.Value = 1; } return(ServiceResult.Good); }
/// <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)); } }
/// <summary> /// Revoke the CA signed certificate. /// The issuer CA public key, the private key and the crl reside in the storepath. /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store. /// </summary> public static async Task <X509CRL> RevokeCertificateAsync( string storePath, X509Certificate2 certificate, string issuerKeyFilePassword = null ) { X509CRL updatedCRL = null; try { string subjectName = certificate.IssuerName.Name; string keyId = null; string serialNumber = null; // caller may want to create empty CRL using the CA cert itself bool isCACert = IsCertificateAuthority(certificate); // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = FindAuthorityKeyIdentifier(certificate); if (authority != null) { keyId = authority.KeyId; serialNumber = authority.SerialNumber; } else { throw new ArgumentException("Certificate does not contain an Authority Key"); } if (!isCACert) { if (serialNumber == certificate.SerialNumber || Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer)) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates"); } } X509Certificate2 certCA = null; using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath)) { if (store == null) { throw new ArgumentException("Invalid store path/type"); } certCA = await FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber); if (certCA == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store."); } if (!certCA.HasPrivateKey) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate."); } CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA); certCAIdentifier.StorePath = storePath; certCAIdentifier.StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath); X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword); if (certCAWithPrivateKey == null) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?"); } List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false); var certificateCollection = new X509Certificate2Collection() { certificate }; updatedCRL = RevokeCertificate(certCAWithPrivateKey, certCACrl, certificateCollection); store.AddCRL(updatedCRL); // delete outdated CRLs from store foreach (X509CRL caCrl in certCACrl) { store.DeleteCRL(caCrl); } store.Close(); } } catch (Exception e) { throw e; } return(updatedCRL); }
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); } }
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); } }