/// <summary> /// Returns the certificate information for a trusted issuer certificate. /// </summary> private async Task <CertificateIdentifier> GetIssuer( X509Certificate2 certificate, CertificateIdentifierCollection explicitList, CertificateStoreIdentifier certificateStore, bool checkRecovationStatus) { // check if self-signed. if (X509Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer)) { return(null); } string subjectName = certificate.IssuerName.Name; string keyId = null; string serialNumber = null; // find the authority key identifier. X509AuthorityKeyIdentifierExtension authority = X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(certificate); if (authority != null) { keyId = authority.KeyIdentifier; serialNumber = authority.SerialNumber; } // check in explicit list. if (explicitList != null) { for (int ii = 0; ii < explicitList.Count; ii++) { X509Certificate2 issuer = await explicitList[ii].Find(false); if (issuer != null) { if (!X509Utils.IsIssuerAllowed(issuer)) { continue; } if (Match(issuer, subjectName, serialNumber, keyId)) { // can't check revocation. return(new CertificateIdentifier(issuer, CertificateValidationOptions.SuppressRevocationStatusUnknown)); } } } } // check in certificate store. if (certificateStore != null) { ICertificateStore store = certificateStore.OpenStore(); try { X509Certificate2Collection certificates = await store.Enumerate(); for (int ii = 0; ii < certificates.Count; ii++) { X509Certificate2 issuer = certificates[ii]; if (issuer != null) { if (!X509Utils.IsIssuerAllowed(issuer)) { continue; } if (Match(issuer, subjectName, serialNumber, keyId)) { CertificateValidationOptions options = certificateStore.ValidationOptions; // already checked revocation for file based stores. windows based stores always suppress. options |= CertificateValidationOptions.SuppressRevocationStatusUnknown; if (checkRecovationStatus) { StatusCode status = store.IsRevoked(issuer, certificate); if (StatusCode.IsBad(status) && status != StatusCodes.BadNotSupported) { if (status == StatusCodes.BadCertificateRevocationUnknown) { if (X509Utils.IsCertificateAuthority(certificate)) { status.Code = StatusCodes.BadCertificateIssuerRevocationUnknown; } if (m_rejectUnknownRevocationStatus) { throw new ServiceResultException(status); } } else { throw new ServiceResultException(status); } } } return(new CertificateIdentifier(certificates[ii], options)); } } } } finally { store.Close(); } } // not a trusted issuer. return(null); }
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); }
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); }
/// <summary> /// Creates a self signed application instance certificate. /// </summary> /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param> /// <param name="storePath">The store path (syntax depends on storeType).</param> /// <param name="password">The password to use to protect the certificate.</param> /// <param name="applicationUri">The application uri (created if not specified).</param> /// <param name="applicationName">Name of the application (optional if subjectName is specified).</param> /// <param name="subjectName">The subject used to create the certificate (optional if applicationName is specified).</param> /// <param name="domainNames">The domain names that can be used to access the server machine (defaults to local computer name if not specified).</param> /// <param name="keySize">Size of the key (1024, 2048 or 4096).</param> /// <param name="startTime">The start time.</param> /// <param name="lifetimeInMonths">The lifetime of the key in months.</param> /// <param name="hashSizeInBits">The hash size in bits.</param> /// <param name="isCA">if set to <c>true</c> then a CA certificate is created.</param> /// <param name="issuerCAKeyCert">The CA cert with the CA private key.</param> /// <returns>The certificate with a private key.</returns> public static X509Certificate2 CreateCertificate( string storeType, string storePath, string password, string applicationUri, string applicationName, string subjectName, IList <String> domainNames, ushort keySize, DateTime startTime, ushort lifetimeInMonths, ushort hashSizeInBits, bool isCA, X509Certificate2 issuerCAKeyCert) { if (issuerCAKeyCert != null) { if (!issuerCAKeyCert.HasPrivateKey) { throw new NotSupportedException("Cannot sign with a CA certificate without a private key."); } throw new NotSupportedException("Signing with an issuer CA certificate is currently unsupported."); } // set default values. SetSuitableDefaults( ref applicationUri, ref applicationName, ref subjectName, ref domainNames, ref keySize, ref lifetimeInMonths, isCA); // cert generators SecureRandom random = new SecureRandom(); X509V3CertificateGenerator cg = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); cg.SetSerialNumber(serialNumber); // build name attributes var nameOids = new ArrayList(); nameOids.Add(X509Name.DC); nameOids.Add(X509Name.CN); var nameValues = new ArrayList(); nameValues.Add(domainNames[0]); nameValues.Add(subjectName); // self signed X509Name subjectDN = new X509Name(nameOids, nameValues); X509Name issuerDN = subjectDN; cg.SetIssuerDN(issuerDN); cg.SetSubjectDN(subjectDN); // valid for cg.SetNotBefore(startTime); cg.SetNotAfter(startTime.AddMonths(lifetimeInMonths)); // Private/Public Key AsymmetricCipherKeyPair subjectKeyPair; var keyGenerationParameters = new KeyGenerationParameters(random, keySize); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); subjectKeyPair = keyPairGenerator.GenerateKeyPair(); cg.SetPublicKey(subjectKeyPair.Public); // add extensions // Subject key identifier cg.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectKeyPair.Public))); // Basic constraints cg.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(isCA)); // Authority Key identifier var issuerKeyPair = subjectKeyPair; var issuerSerialNumber = serialNumber; cg.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectKeyPair.Public), new GeneralNames(new GeneralName(issuerDN)), issuerSerialNumber)); if (!isCA) { // Key usage cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DataEncipherment | KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyCertSign | KeyUsage.KeyEncipherment)); // Extended Key usage cg.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(new List <DerObjectIdentifier>() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1"), // server auth new DerObjectIdentifier("1.3.6.1.5.5.7.3.2"), // client auth })); // subject alternate name cg.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName[] { new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri), new GeneralName(GeneralName.DnsName, domainNames[0]) })); } else { // Key usage CA cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign)); } // sign certificate ISignatureFactory signatureFactory = new Asn1SignatureFactory((hashSizeInBits < 256) ? "SHA1WITHRSA" : "SHA256WITHRSA", subjectKeyPair.Private, random); Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory); // create pkcs12 store for cert and private key X509Certificate2 certificate = null; using (MemoryStream pfxData = new MemoryStream()) { Pkcs12Store pkcsStore = new Pkcs12StoreBuilder().Build(); X509CertificateEntry[] chain = new X509CertificateEntry[1]; string passcode = "passcode"; chain[0] = new X509CertificateEntry(x509); pkcsStore.SetKeyEntry(applicationName, new AsymmetricKeyEntry(subjectKeyPair.Private), chain); pkcsStore.Save(pfxData, passcode.ToCharArray(), random); // merge into X509Certificate2 certificate = CreateCertificateFromPKCS12(pfxData.ToArray(), passcode); } Utils.Trace(Utils.TraceMasks.Security, "Created new certificate: {0}", certificate.Thumbprint); // add cert to the store. if (!String.IsNullOrEmpty(storePath)) { ICertificateStore store = null; if (storeType == CertificateStoreType.X509Store) { store = new X509CertificateStore(); } else if (storeType == CertificateStoreType.Directory) { store = new DirectoryCertificateStore(); } else { throw new ArgumentException("Invalid store type"); } store.Open(storePath); store.Add(certificate, password); store.Close(); store.Dispose(); } // note: this cert has a private key! return(certificate); }
public AcmeClient(IDnsProvider dnsProvider, DnsLookupService dnsLookupService, ICertificateStore certifcateStore, ILogger <AcmeClient> logger = null) { this.dnsProvider = dnsProvider; this.dnsLookupService = dnsLookupService; this.certificateStore = certifcateStore; this.logger = logger ?? NullLogger <AcmeClient> .Instance; }
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 async void CertificateRequestTimer_Tick(object sender, EventArgs e) { try { NodeId requestId = NodeId.Parse(m_application.CertificateRequestId); byte[] privateKeyPFX = null; byte[][] issuerCertificates = null; byte[] certificate = m_gds.FinishRequest( m_application.ApplicationId, requestId, out privateKeyPFX, out issuerCertificates); if (certificate == null) { // request not done yet, try again in a few seconds return; } CertificateRequestTimer.Enabled = false; RequestProgressLabel.Visible = false; if (m_application.RegistrationType != RegistrationType.ServerPush) { X509Certificate2 newCert = new X509Certificate2(certificate); if (!String.IsNullOrEmpty(m_application.CertificateStorePath) && !String.IsNullOrEmpty(m_application.CertificateSubjectName)) { CertificateIdentifier cid = new CertificateIdentifier() { StorePath = m_application.CertificateStorePath, StoreType = CertificateStoreIdentifier.DetermineStoreType(m_application.CertificateStorePath), SubjectName = m_application.CertificateSubjectName.Replace("localhost", Utils.GetHostName()) }; // update store using (var store = CertificateStoreIdentifier.OpenStore(m_application.CertificateStorePath)) { // if we used a CSR, we already have a private key and therefore didn't request one from the GDS // in this case, privateKey is null if (privateKeyPFX == null) { X509Certificate2 oldCertificate = await cid.Find(true); if (oldCertificate != null && oldCertificate.HasPrivateKey) { oldCertificate = await cid.LoadPrivateKey(string.Empty); newCert = CertificateFactory.CreateCertificateWithPrivateKey(newCert, oldCertificate); await store.Delete(oldCertificate.Thumbprint); } else { throw new ServiceResultException("Failed to merge signed certificate with the private key."); } } else { newCert = new X509Certificate2(privateKeyPFX, string.Empty, X509KeyStorageFlags.Exportable); newCert = CertificateFactory.Load(newCert, true); } await store.Add(newCert); } } else { DialogResult result = DialogResult.Yes; string absoluteCertificatePublicKeyPath = Utils.GetAbsoluteFilePath(m_application.CertificatePublicKeyPath, true, false, false) ?? m_application.CertificatePublicKeyPath; FileInfo file = new FileInfo(absoluteCertificatePublicKeyPath); if (file.Exists) { result = MessageBox.Show( Parent, "Replace certificate " + absoluteCertificatePublicKeyPath + "?", Parent.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); } if (result == DialogResult.Yes) { byte[] exportedCert; if (string.Compare(file.Extension, ".PEM", true) == 0) { exportedCert = PEMWriter.ExportCertificateAsPEM(newCert); } else { exportedCert = newCert.Export(X509ContentType.Cert); } File.WriteAllBytes(absoluteCertificatePublicKeyPath, exportedCert); } // if we provided a PFX or P12 with the private key, we need to merge the new cert with the private key if (m_application.GetPrivateKeyFormat(m_server?.GetSupportedKeyFormats()) == "PFX") { string absoluteCertificatePrivateKeyPath = Utils.GetAbsoluteFilePath(m_application.CertificatePrivateKeyPath, true, false, false) ?? m_application.CertificatePrivateKeyPath; file = new FileInfo(absoluteCertificatePrivateKeyPath); if (file.Exists) { result = MessageBox.Show( Parent, "Replace private key " + absoluteCertificatePrivateKeyPath + "?", Parent.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation); } if (result == DialogResult.Yes) { if (file.Exists) { byte[] pkcsData = File.ReadAllBytes(absoluteCertificatePrivateKeyPath); X509Certificate2 oldCertificate = X509PfxUtils.CreateCertificateFromPKCS12(pkcsData, m_certificatePassword); newCert = CertificateFactory.CreateCertificateWithPrivateKey(newCert, oldCertificate); pkcsData = newCert.Export(X509ContentType.Pfx, m_certificatePassword); File.WriteAllBytes(absoluteCertificatePrivateKeyPath, pkcsData); if (privateKeyPFX != null) { throw new ServiceResultException("Did not expect a private key for this operation."); } } else { File.WriteAllBytes(absoluteCertificatePrivateKeyPath, privateKeyPFX); } } } } // update trust list. if (!String.IsNullOrEmpty(m_application.TrustListStorePath)) { using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_application.TrustListStorePath)) { foreach (byte[] issuerCertificate in issuerCertificates) { X509Certificate2 x509 = new X509Certificate2(issuerCertificate); X509Certificate2Collection certs = await store.FindByThumbprint(x509.Thumbprint); if (certs.Count == 0) { await store.Add(new X509Certificate2(issuerCertificate)); } } } } m_certificate = newCert; } else { if (privateKeyPFX != null && privateKeyPFX.Length > 0) { var x509 = new X509Certificate2(privateKeyPFX, m_certificatePassword, X509KeyStorageFlags.Exportable); privateKeyPFX = x509.Export(X509ContentType.Pfx); } bool applyChanges = m_server.UpdateCertificate( null, m_server.ApplicationCertificateType, certificate, (privateKeyPFX != null) ? "PFX" : null, privateKeyPFX, 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; } } CertificateControl.ShowValue(null, "Application Certificate", new CertificateWrapper() { Certificate = m_certificate }, true); } catch (Exception exception) { if (exception is ServiceResultException sre && sre.StatusCode == StatusCodes.BadNothingToDo) { return; } RequestProgressLabel.Visible = false; CertificateRequestTimer.Enabled = false; Opc.Ua.Client.Controls.ExceptionDlg.Show(Text, exception); } }
public SubscriptionCloudCredentialsFactory(ICertificateStore certificateStore) { this.certificateStore = certificateStore; }
/// <summary> /// Creates a self signed application instance certificate. /// </summary> /// <param name="storeType">Type of certificate store (Directory) <see cref="CertificateStoreType"/>.</param> /// <param name="storePath">The store path (syntax depends on storeType).</param> /// <param name="password">The password to use to protect the certificate.</param> /// <param name="applicationUri">The application uri (created if not specified).</param> /// <param name="applicationName">Name of the application (optional if subjectName is specified).</param> /// <param name="subjectName">The subject used to create the certificate (optional if applicationName is specified).</param> /// <param name="domainNames">The domain names that can be used to access the server machine (defaults to local computer name if not specified).</param> /// <param name="keySize">Size of the key (1024, 2048 or 4096).</param> /// <param name="startTime">The start time.</param> /// <param name="lifetimeInMonths">The lifetime of the key in months.</param> /// <param name="hashSizeInBits">The hash size in bits.</param> /// <param name="isCA">if set to <c>true</c> then a CA certificate is created.</param> /// <param name="issuerCAKeyCert">The CA cert with the CA private key.</param> /// <returns>The certificate with a private key.</returns> public static X509Certificate2 CreateCertificate( string storeType, string storePath, string password, string applicationUri, string applicationName, string subjectName, IList <String> domainNames, ushort keySize, DateTime startTime, ushort lifetimeInMonths, ushort hashSizeInBits, bool isCA = false, X509Certificate2 issuerCAKeyCert = null, byte[] publicKey = null) { if (issuerCAKeyCert != null) { if (!issuerCAKeyCert.HasPrivateKey) { throw new NotSupportedException("Cannot sign with a CA certificate without a private key."); } } if (publicKey != null && issuerCAKeyCert == null) { throw new NotSupportedException("Cannot use a public key without a CA certificate with a private key."); } // set default values. X509Name subjectDN = SetSuitableDefaults( ref applicationUri, ref applicationName, ref subjectName, ref domainNames, ref keySize, ref lifetimeInMonths); using (var cfrg = new CertificateFactoryRandomGenerator()) { // cert generators SecureRandom random = new SecureRandom(cfrg); X509V3CertificateGenerator cg = new X509V3CertificateGenerator(); // Serial Number BigInteger serialNumber = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); cg.SetSerialNumber(serialNumber); // subject and issuer DN X509Name issuerDN = null; if (issuerCAKeyCert != null) { issuerDN = new CertificateFactoryX509Name(issuerCAKeyCert.Subject); } else { // self signed issuerDN = subjectDN; } cg.SetIssuerDN(issuerDN); cg.SetSubjectDN(subjectDN); // valid for cg.SetNotBefore(startTime); cg.SetNotAfter(startTime.AddMonths(lifetimeInMonths)); // set Private/Public Key AsymmetricKeyParameter subjectPublicKey; AsymmetricKeyParameter subjectPrivateKey; if (publicKey == null) { var keyGenerationParameters = new KeyGenerationParameters(random, keySize); var keyPairGenerator = new RsaKeyPairGenerator(); keyPairGenerator.Init(keyGenerationParameters); AsymmetricCipherKeyPair subjectKeyPair = keyPairGenerator.GenerateKeyPair(); subjectPublicKey = subjectKeyPair.Public; subjectPrivateKey = subjectKeyPair.Private; } else { // special case, if a cert is signed by CA, the private key of the cert is not needed subjectPublicKey = PublicKeyFactory.CreateKey(publicKey); subjectPrivateKey = null; } cg.SetPublicKey(subjectPublicKey); // add extensions // Subject key identifier cg.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey))); // Basic constraints cg.AddExtension(X509Extensions.BasicConstraints.Id, true, isCA ? new BasicConstraints(0) : new BasicConstraints(false)); // Authority Key identifier references the issuer cert or itself when self signed AsymmetricKeyParameter issuerPublicKey; BigInteger issuerSerialNumber; if (issuerCAKeyCert != null) { issuerPublicKey = GetPublicKeyParameter(issuerCAKeyCert); issuerSerialNumber = GetSerialNumber(issuerCAKeyCert); if (startTime.AddMonths(lifetimeInMonths) > issuerCAKeyCert.NotAfter) { cg.SetNotAfter(issuerCAKeyCert.NotAfter); } } else { issuerPublicKey = subjectPublicKey; issuerSerialNumber = serialNumber; } cg.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey), new GeneralNames(new GeneralName(issuerDN)), issuerSerialNumber)); if (!isCA) { // Key usage var keyUsage = KeyUsage.DataEncipherment | KeyUsage.DigitalSignature | KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment; if (issuerCAKeyCert == null) { // only self signed certs need KeyCertSign flag. keyUsage |= KeyUsage.KeyCertSign; } cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(keyUsage)); // Extended Key usage cg.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(new List <DerObjectIdentifier>() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1"), // server auth new DerObjectIdentifier("1.3.6.1.5.5.7.3.2"), // client auth })); // subject alternate name List <GeneralName> generalNames = new List <GeneralName>(); generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri)); generalNames.AddRange(CreateSubjectAlternateNameDomains(domainNames)); cg.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(generalNames.ToArray())); } else { // Key usage CA cg.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign)); } // sign certificate AsymmetricKeyParameter signingKey; if (issuerCAKeyCert != null) { // signed by issuer signingKey = GetPrivateKeyParameter(issuerCAKeyCert); } else { // self signed signingKey = subjectPrivateKey; } ISignatureFactory signatureFactory = new Asn1SignatureFactory(GetRSAHashAlgorithm(hashSizeInBits), signingKey, random); Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory); // convert to X509Certificate2 X509Certificate2 certificate = null; if (subjectPrivateKey == null) { // create the cert without the private key certificate = new X509Certificate2(x509.GetEncoded()); } else { // note: this cert has a private key! certificate = CreateCertificateWithPrivateKey(x509, null, subjectPrivateKey, random); } Utils.Trace(Utils.TraceMasks.Security, "Created new certificate: {0}", certificate.Thumbprint); // add cert to the store. if (!String.IsNullOrEmpty(storePath) && !String.IsNullOrEmpty(storeType)) { using (ICertificateStore store = CertificateStoreIdentifier.CreateStore(storeType)) { if (store == null) { throw new ArgumentException("Invalid store type"); } store.Open(storePath); store.Add(certificate, password).Wait(); store.Close(); } } return(certificate); } }
/// <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 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); DeleteExistingFromStore(m_issuerListStorePath); } } 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); if (store.FindByThumbprint(x509.Thumbprint) == null) { store.Add(x509); } } } 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); if (store.FindByThumbprint(x509.Thumbprint) == null) { store.Add(x509); } } } 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); } }
public CertificateRepository(ICertificateStore client) { m_client = client; }
private static X509Certificate2 GetHttpsCertificate(string certificateFilePath, ICertificateStore store) { if (store.TryGet(certificateFilePath, out var certificate)) { return(certificate); } throw new FileLoadException($"Failed to load certificate from path {certificateFilePath}"); }
/// <summary> /// Configures all OPC stack settings /// </summary> public async Task ConfigureAsync() { // Instead of using a Config.xml we configure everything programmatically. // // OPC UA Application configuration // OpcApplicationConfiguration = new ApplicationConfiguration(); // Passed in as command line argument OpcApplicationConfiguration.ApplicationName = ApplicationName; OpcApplicationConfiguration.ApplicationUri = $"urn:{Utils.GetHostName()}:{OpcApplicationConfiguration.ApplicationName}:microsoft:"; OpcApplicationConfiguration.ProductUri = "https://github.com/hansgschossmann/iot-edge-opc-agent"; OpcApplicationConfiguration.ApplicationType = ApplicationType.Client; // // Security configuration // OpcApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration(); // Application certificate OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType = OpcOwnCertStoreType; OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath = OpcOwnCertStorePath; OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = OpcApplicationConfiguration.ApplicationName; Logger.Information($"Application Certificate store type is: {OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Logger.Information($"Application Certificate store path is: {OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath}"); Logger.Information($"Application Certificate subject name is: {OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName}"); // Use existing certificate, if it is there. X509Certificate2 certificate = await OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Find(true); if (certificate == null) { Logger.Information($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Logger.Information($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType, OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath, null, OpcApplicationConfiguration.ApplicationUri, OpcApplicationConfiguration.ApplicationName, OpcApplicationConfiguration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); OpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate can not be created! Cannot continue without it!"); } else { Logger.Information("Application certificate found in Application Certificate Store"); } OpcApplicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Logger.Information($"Application certificate is for Application URI '{OpcApplicationConfiguration.ApplicationUri}', Application '{OpcApplicationConfiguration.ApplicationName} and has Subject '{OpcApplicationConfiguration.ApplicationName}'"); // TrustedIssuerCertificates OpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); OpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = OpcIssuerCertStoreType; OpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = OpcIssuerCertStorePath; Logger.Information($"Trusted Issuer store type is: {OpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Logger.Information($"Trusted Issuer Certificate store path is: {OpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // TrustedPeerCertificates OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = OpcTrustedCertStoreType; if (string.IsNullOrEmpty(OpcTrustedCertStorePath)) { // Set default. OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStoreType == X509Store ? OpcTrustedCertX509StorePathDefault : OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStorePath; } Logger.Information($"Trusted Peer Certificate store type is: {OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Logger.Information($"Trusted Peer Certificate store path is: {OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // RejectedCertificateStore OpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); OpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = OpcRejectedCertStoreType; OpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = OpcRejectedCertStorePath; Logger.Information($"Rejected certificate store type is: {OpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Logger.Information($"Rejected Certificate store path is: {OpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); // AutoAcceptUntrustedCertificates // This is a security risk and should be set to true only for debugging purposes. OpcApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false; // RejectSHA1SignedCertificates // We allow SHA1 certificates for now as many OPC Servers still use them OpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Logger.Information($"Rejection of SHA1 signed certificates is {(OpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // MinimunCertificatesKeySize // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them OpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Logger.Information($"Minimum certificate key size set to {OpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize}"); // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store. if (TrustMyself) { // Ensure it is trusted try { ICertificateStore store = OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Logger.Information($"Can not open trusted peer store. StorePath={OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Logger.Information($"Adding own certificate to trusted peer store. StorePath={OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); X509Certificate2Collection certCollection = await store.FindByThumbprint(publicKey.Thumbprint); if (certCollection.Count > 0) { Logger.Information($"A certificate with the same thumbprint is already in the trusted store."); } else { await store.Add(publicKey); } } finally { store.Close(); } } } catch (Exception e) { Logger.Error(e, $"Can not add own certificate to trusted peer store. StorePath={OpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Logger.Information($"{ProgramName} certificate is not added to trusted peer store."); } // // TransportConfigurations // OpcApplicationConfiguration.TransportQuotas = new TransportQuotas(); OpcApplicationConfiguration.TransportQuotas.MaxByteStringLength = 4 * 1024 * 1024; OpcApplicationConfiguration.TransportQuotas.MaxMessageSize = 4 * 1024 * 1024; // the maximum string length could be set to ajust for large number of nodes when reading the list of published nodes OpcApplicationConfiguration.TransportQuotas.MaxStringLength = OpcMaxStringLength; // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s OpcApplicationConfiguration.TransportQuotas.OperationTimeout = OpcOperationTimeout; Logger.Information($"OperationTimeout set to {OpcApplicationConfiguration.TransportQuotas.OperationTimeout}"); // // TraceConfiguration // // // TraceConfiguration // OpcApplicationConfiguration.TraceConfiguration = new TraceConfiguration(); OpcApplicationConfiguration.TraceConfiguration.TraceMasks = OpcStackTraceMask; OpcApplicationConfiguration.TraceConfiguration.ApplySettings(); Utils.Tracing.TraceEventHandler += new EventHandler <TraceEventArgs>(LoggerOpcUaTraceHandler); Logger.Information($"opcstacktracemask set to: 0x{OpcStackTraceMask:X}"); // add default client configuration OpcApplicationConfiguration.ClientConfiguration = new ClientConfiguration(); // validate the configuration now await OpcApplicationConfiguration.Validate(OpcApplicationConfiguration.ApplicationType); }
/// <summary> /// Installs a UA application. /// </summary> public static async Task InstallApplication( InstalledApplication application, bool autostart, bool configureFirewall) { // validate the executable file. string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); // get the default application name from the executable file. FileInfo executableFileInfo = new FileInfo(executableFile); string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length - 4); // choose a default configuration file. if (String.IsNullOrEmpty(application.ConfigurationFile)) { application.ConfigurationFile = Utils.Format( "{0}\\{1}.Config.xml", executableFileInfo.DirectoryName, applicationName); } // validate the configuration file. string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); // create a new file if one does not exist. bool useExisting = true; if (configurationFile == null) { configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, true, true); useExisting = false; } // create the default configuration file. if (useExisting) { try { Opc.Ua.Security.SecuredApplication existingSettings = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile); // copy current settings application.ApplicationType = existingSettings.ApplicationType; application.BaseAddresses = existingSettings.BaseAddresses; application.ApplicationCertificate = existingSettings.ApplicationCertificate; application.ApplicationName = existingSettings.ApplicationName; application.ProductName = existingSettings.ProductName; application.RejectedCertificatesStore = existingSettings.RejectedCertificatesStore; application.TrustedCertificateStore = existingSettings.TrustedCertificateStore; application.TrustedCertificates = existingSettings.TrustedCertificates; application.IssuerCertificateStore = existingSettings.IssuerCertificateStore; application.IssuerCertificates = application.IssuerCertificates; application.UseDefaultCertificateStores = false; } catch (Exception e) { useExisting = false; Utils.Trace("WARNING. Existing configuration file could not be loaded: {0}.\r\nReplacing with default: {1}", e.Message, configurationFile); File.Copy(configurationFile, configurationFile + ".bak", true); } } // create the configuration file from the default. if (!useExisting) { try { string installationFile = Utils.Format( "{0}\\Install\\{1}.Config.xml", executableFileInfo.Directory.Parent.FullName, applicationName); if (!File.Exists(installationFile)) { Utils.Trace("Could not find default configuation at: {0}", installationFile); } File.Copy(installationFile, configurationFile, true); Utils.Trace("File.Copy({0}, {1})", installationFile, configurationFile); } catch (Exception e) { Utils.Trace("Could not copy default configuation to: {0}. Error={1}.", configurationFile, e.Message); } } // create a default application name. if (String.IsNullOrEmpty(application.ApplicationName)) { application.ApplicationName = applicationName; } // create a default product name. if (String.IsNullOrEmpty(application.ProductName)) { application.ProductName = application.ApplicationName; } // create a default uri. if (String.IsNullOrEmpty(application.ApplicationUri)) { application.ApplicationUri = Utils.Format("http://localhost/{0}/{1}", applicationName, Guid.NewGuid()); } // make the uri specify the local machine. application.ApplicationUri = Utils.ReplaceLocalhost(application.ApplicationUri); // set a default application store. if (application.ApplicationCertificate == null) { application.ApplicationCertificate = new Opc.Ua.Security.CertificateIdentifier(); application.ApplicationCertificate.StoreType = Utils.DefaultStoreType; application.ApplicationCertificate.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.UseDefaultCertificateStores) { if (application.IssuerCertificateStore == null) { application.IssuerCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.IssuerCertificateStore.StoreType = Utils.DefaultStoreType; application.IssuerCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } if (application.TrustedCertificateStore == null) { application.TrustedCertificateStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.TrustedCertificateStore.StoreType = Utils.DefaultStoreType; application.TrustedCertificateStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\MachineDefault"; } try { Utils.GetAbsoluteDirectoryPath(application.TrustedCertificateStore.StorePath, true, true, true); } catch (Exception e) { Utils.Trace("Could not access the machine directory: {0} '{1}'", application.RejectedCertificatesStore.StorePath, e); } if (application.RejectedCertificatesStore == null) { application.RejectedCertificatesStore = new Opc.Ua.Security.CertificateStoreIdentifier(); application.RejectedCertificatesStore.StoreType = CertificateStoreType.Directory; application.RejectedCertificatesStore.StorePath = ApplicationData.Current.LocalFolder.Path + "\\OPC Foundation\\CertificateStores\\RejectedCertificates"; StringBuilder buffer = new StringBuilder(); buffer.Append(ApplicationData.Current.LocalFolder.Path); buffer.Append("\\OPC Foundation"); buffer.Append("\\RejectedCertificates"); string folderPath = buffer.ToString(); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } } } // check for valid certificate (discard invalid certificates). CertificateIdentifier applicationCertificate = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(application.ApplicationCertificate); X509Certificate2 certificate = await applicationCertificate.Find(true); if (certificate == null) { certificate = await applicationCertificate.Find(false); if (certificate != null) { Utils.Trace( "Found existing certificate but it does not have a private key: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } else { Utils.Trace( "Existing certificate could not be found: Store={0}, Certificate={1}", application.ApplicationCertificate.StorePath, application.ApplicationCertificate); } } // check if no certificate exists. if (certificate == null) { certificate = await CreateCertificateForApplication(application); } // ensure the application certificate is in the trusted peers store. try { CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.TrustedCertificateStore); using (ICertificateStore store = certificateStore.OpenStore()) { X509Certificate2Collection peerCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (peerCertificates.Count == 0) { await store.Add(new X509Certificate2(certificate.RawData)); } } } catch (Exception e) { Utils.Trace( "Could not add certificate '{0}' to trusted peer store '{1}'. Error={2}", certificate.Subject, application.TrustedCertificateStore, e.Message); } // update configuration file location. UpdateConfigurationLocation(executableFile, configurationFile); // update configuration file. new Opc.Ua.Security.SecurityConfigurationManager().WriteConfiguration(configurationFile, application); ApplicationAccessRuleCollection accessRules = application.AccessRules; bool noRulesDefined = application.AccessRules == null || application.AccessRules.Count == 0; // add the default access rules. if (noRulesDefined) { ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Administrators; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Configure; accessRules.Add(rule); rule = new ApplicationAccessRule(); rule.IdentityName = WellKnownSids.Users; rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Update; accessRules.Add(rule); } // ensure the service account has priviledges. if (application.InstallAsService) { // check if a specific account is assigned. AccountInfo accountInfo = null; if (!String.IsNullOrEmpty(application.ServiceUserName)) { accountInfo = AccountInfo.Create(application.ServiceUserName); } // choose a built-in service account. if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.NetworkService); if (accountInfo == null) { accountInfo = AccountInfo.Create(WellKnownSids.LocalSystem); } } ApplicationAccessRule rule = new ApplicationAccessRule(); rule.IdentityName = accountInfo.ToString(); rule.RuleType = AccessControlType.Allow; rule.Right = ApplicationAccessRight.Run; accessRules.Add(rule); } // set the permissions for the HTTP endpoints used by the application. if (configureFirewall && application.BaseAddresses != null && application.BaseAddresses.Count > 0) { for (int ii = 0; ii < application.BaseAddresses.Count; ii++) { Uri url = Utils.ParseUri(application.BaseAddresses[ii]); if (url != null) { try { HttpAccessRule.SetAccessRules(url, accessRules, true); Utils.Trace("Added HTTP access rules for URL: {0}", url); } catch (Exception e) { Utils.Trace("Could not set HTTP access rules for URL: {0}. Error={1}", url, e.Message); for (int jj = 0; jj < accessRules.Count; jj++) { ApplicationAccessRule rule = accessRules[jj]; Utils.Trace( (int)Utils.TraceMasks.Error, "IdentityName={0}, Right={1}, RuleType={2}", rule.IdentityName, rule.Right, rule.RuleType); } } } } } // set permissions on the local certificate store. SetCertificatePermissions( application, applicationCertificate, accessRules, false); // set permissions on the local certificate store. if (application.RejectedCertificatesStore != null) { // need to grant full control to certificates in the RejectedCertificatesStore. foreach (ApplicationAccessRule rule in accessRules) { if (rule.RuleType == AccessControlType.Allow) { rule.Right = ApplicationAccessRight.Configure; } } CertificateStoreIdentifier rejectedCertificates = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(application.RejectedCertificatesStore); using (ICertificateStore store = rejectedCertificates.OpenStore()) { if (store.SupportsAccessControl) { store.SetAccessRules(accessRules, false); } } } }
public CertificateStore(ICertificateStore personalStore, ICertificateStore rootStore) { _personalStore = personalStore; _rootStore = rootStore; }
/// <summary> /// Uninstalls a UA application. /// </summary> public static async Task UninstallApplication(InstalledApplication application) { // validate the executable file. string executableFile = Utils.GetAbsoluteFilePath(application.ExecutableFile, true, true, false); // get the default application name from the executable file. FileInfo executableFileInfo = new FileInfo(executableFile); string applicationName = executableFileInfo.Name.Substring(0, executableFileInfo.Name.Length - 4); // choose a default configuration file. if (String.IsNullOrEmpty(application.ConfigurationFile)) { application.ConfigurationFile = Utils.Format( "{0}\\{1}.Config.xml", executableFileInfo.DirectoryName, applicationName); } // validate the configuration file. string configurationFile = Utils.GetAbsoluteFilePath(application.ConfigurationFile, true, false, false); if (configurationFile != null) { // load the current configuration. Opc.Ua.Security.SecuredApplication security = new Opc.Ua.Security.SecurityConfigurationManager().ReadConfiguration(configurationFile); // delete the application certificates. if (application.DeleteCertificatesOnUninstall) { CertificateIdentifier id = Opc.Ua.Security.SecuredApplication.FromCertificateIdentifier(security.ApplicationCertificate); // delete public key from trusted peers certificate store. try { CertificateStoreIdentifier certificateStore = Opc.Ua.Security.SecuredApplication.FromCertificateStoreIdentifier(security.TrustedCertificateStore); using (ICertificateStore store = certificateStore.OpenStore()) { X509Certificate2Collection peerCertificates = await store.FindByThumbprint(id.Thumbprint); if (peerCertificates.Count > 0) { await store.Delete(peerCertificates[0].Thumbprint); } } } catch (Exception e) { Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message); } // delete private key from application certificate store. try { using (ICertificateStore store = id.OpenStore()) { await store.Delete(id.Thumbprint); } } catch (Exception e) { Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message); } // permentently delete any UA defined stores if they are now empty. try { WindowsCertificateStore store = new WindowsCertificateStore(); await store.Open("LocalMachine\\UA Applications"); X509Certificate2Collection collection = await store.Enumerate(); if (collection.Count == 0) { store.PermanentlyDeleteStore(); } } catch (Exception e) { Utils.Trace("Could not delete certificate '{0}' from store. Error={1}", id, e.Message); } } // remove the permissions for the HTTP endpoints used by the application. if (application.BaseAddresses != null && application.BaseAddresses.Count > 0) { List <ApplicationAccessRule> noRules = new List <ApplicationAccessRule>(); for (int ii = 0; ii < application.BaseAddresses.Count; ii++) { Uri url = Utils.ParseUri(application.BaseAddresses[ii]); if (url != null) { try { HttpAccessRule.SetAccessRules(url, noRules, true); Utils.Trace("Removed HTTP access rules for URL: {0}", url); } catch (Exception e) { Utils.Trace("Could not remove HTTP access rules for URL: {0}. Error={1}", url, e.Message); } } } } } }
public async void Initialize(string trustedStorePath, string issuerStorePath, string rejectedStorePath) { CertificatesTable.Rows.Clear(); m_trustedStorePath = trustedStorePath; m_issuerStorePath = issuerStorePath; m_rejectedStorePath = rejectedStorePath; if (!String.IsNullOrEmpty(trustedStorePath)) { using (ICertificateStore store = CreateStore(trustedStorePath)) { X509CertificateCollection certificates = await store.Enumerate(); foreach (X509Certificate2 certificate in certificates) { List <X509CRL> crls = new List <X509CRL>(); if (store.SupportsCRLs) { foreach (X509CRL crl in store.EnumerateCRLs(certificate)) { crls.Add(crl); } } AddCertificate(certificate, Status.Trusted, crls); } } } string path1 = Utils.GetAbsoluteDirectoryPath(trustedStorePath, true, false, false); string path2 = Utils.GetAbsoluteDirectoryPath(issuerStorePath, true, false, false); if (String.Compare(path1, path2, StringComparison.OrdinalIgnoreCase) != 0) { if (!String.IsNullOrEmpty(issuerStorePath)) { using (ICertificateStore store = CreateStore(issuerStorePath)) { X509Certificate2Collection certificates = await store.Enumerate(); foreach (X509Certificate2 certificate in certificates) { List <X509CRL> crls = new List <X509CRL>(); if (store.SupportsCRLs) { foreach (X509CRL crl in store.EnumerateCRLs(certificate)) { crls.Add(crl); } } AddCertificate(certificate, Status.Issuer, crls); } } } } if (!String.IsNullOrEmpty(rejectedStorePath)) { using (ICertificateStore store = CreateStore(rejectedStorePath)) { X509Certificate2Collection certificates = await store.Enumerate(); foreach (X509Certificate2 certificate in certificates) { AddCertificate(certificate, Status.Rejected, null); } } } m_dataset.AcceptChanges(); NoDataWarningLabel.Visible = CertificatesTable.Rows.Count == 0; }
private static void SetBinding(Binding binding, dynamic obj) { string protocol = DynamicHelper.Value(obj.protocol); string bindingInformation = DynamicHelper.Value(obj.binding_information); bool? requireSni = DynamicHelper.To <bool>(obj.require_sni); if (protocol == null) { throw new ApiArgumentException("binding.protocol"); } binding.Protocol = protocol; bool isHttp = protocol.Equals("http") || protocol.Equals("https"); if (isHttp) { // // HTTP Binding information provides port, ip address, and hostname UInt16 port; string hostname; IPAddress ipAddress = null; if (bindingInformation == null) { var ip = DynamicHelper.Value(obj.ip_address); if (ip == "*") { ipAddress = IPAddress.Any; } else if (!IPAddress.TryParse(ip, out ipAddress)) { throw new ApiArgumentException("binding.ip_address"); } UInt16?p = (UInt16?)DynamicHelper.To(obj.port, 1, UInt16.MaxValue); if (p == null) { throw new ApiArgumentException("binding.port"); } port = p.Value; hostname = DynamicHelper.Value(obj.hostname) ?? string.Empty; } else { var parts = bindingInformation.Split(':'); if (parts.Length != 3) { throw new ApiArgumentException("binding.binding_information"); } if (parts[0] == "*") { ipAddress = IPAddress.Any; } else if (!IPAddress.TryParse(parts[0], out ipAddress)) { throw new ApiArgumentException("binding.binding_information"); } if (!UInt16.TryParse(parts[1], out port)) { throw new ApiArgumentException("binding.binding_information"); } hostname = parts[2]; } binding.Protocol = protocol; // HTTPS if (protocol.Equals("https")) { if (string.IsNullOrEmpty(hostname) && requireSni.HasValue && requireSni.Value) { throw new ApiArgumentException("binding.require_sni"); } if (obj.certificate == null || !(obj.certificate is JObject)) { throw new ApiArgumentException("binding.certificate"); } dynamic certificate = obj.certificate; string uuid = DynamicHelper.Value(certificate.id); if (string.IsNullOrEmpty(uuid)) { throw new ApiArgumentException("binding.certificate.id"); } CertificateId id = new CertificateId(uuid); ICertificateStore store = CertificateStoreProviderAccessor.Instance?.Stores .FirstOrDefault(s => s.Name.Equals(id.StoreName, StringComparison.OrdinalIgnoreCase)); ICertificate cert = null; if (store != null) { cert = store.GetCertificate(id.Id).Result; } if (cert == null) { throw new NotFoundException("binding.certificate"); } if (!cert.PurposesOID.Contains(OIDServerAuth)) { throw new ApiArgumentException("binding.certificate", "Certificate does not support server authentication"); } // // Windows builtin store if (store is IWindowsCertificateStore) { // The specified certificate must be in the store with a private key or else there will be an exception when we commit if (cert == null) { throw new NotFoundException("binding.certificate"); } if (!cert.HasPrivateKey) { throw new ApiArgumentException("binding.certificate", "Certificate must have a private key"); } List <byte> bytes = new List <byte>(); // Decode the hex string of the certificate hash into bytes for (int i = 0; i < id.Id.Length; i += 2) { bytes.Add(Convert.ToByte(id.Id.Substring(i, 2), 16)); } binding.CertificateStoreName = id.StoreName; binding.CertificateHash = bytes.ToArray(); } // // IIS Central Certificate store else if (store is ICentralCertificateStore) { string name = Path.GetFileNameWithoutExtension(cert.Alias); if (string.IsNullOrEmpty(hostname) || !hostname.Replace('*', '_').Equals(name)) { throw new ApiArgumentException("binding.hostname", "Hostname must match certificate file name for central certificate store"); } binding.SslFlags |= SslFlags.CentralCertStore; } if (requireSni.HasValue) { if (!binding.Schema.HasAttribute(sslFlagsAttribute)) { // throw on IIS 7.5 which does not have SNI support throw new ApiArgumentException("binding.require_sni", "SNI not supported on this machine"); } if (requireSni.Value) { binding.SslFlags |= SslFlags.Sni; } else { binding.SslFlags &= ~SslFlags.Sni; } } } var ipModel = ipAddress.Equals(IPAddress.Any) ? "*" : ipAddress.ToString(); binding.BindingInformation = $"{ipModel}:{port}:{hostname}"; } else { // // Custom protocol if (string.IsNullOrEmpty(bindingInformation)) { throw new ApiArgumentException("binding.binding_information"); } binding.BindingInformation = bindingInformation; } }
/// <summary> /// Creates an application instance certificate if one does not already exist. /// </summary> public static void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration) { // create a default certificate id none specified. CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate; if (id == null) { id = new CertificateIdentifier { StoreType = CertificateStoreType.X509Store, StorePath = "LocalMachine\\My", SubjectName = configuration.ApplicationName }; } // check for certificate with a private key. X509Certificate2 certificate = id.Find(true).Result; if (certificate != null) { //This UA application already has an instance certificate SaveCertificate(certificate); return; } //This UA application does not have an instance certificate. Create one automatically // construct the subject name from the List <string> hostNames = new List <string> { System.Net.Dns.GetHostName() }; string commonName = Utils.Format("CN={0}", configuration.ApplicationName); string domainName = Utils.Format("DC={0}", hostNames[0]); string subjectName = Utils.Format("{0}, {1}", commonName, domainName); // check if a distinguished name was specified. if (id.SubjectName.IndexOf("=", StringComparison.Ordinal) != -1) { List <string> fields = Utils.ParseDistinguishedName(id.SubjectName); bool commonNameFound = false; bool domainNameFound = false; for (int ii = 0; ii < fields.Count; ii++) { string field = fields[ii]; if (field.StartsWith("CN=")) { fields[ii] = commonName; commonNameFound = true; continue; } if (field.StartsWith("DC=")) { fields[ii] = domainName; domainNameFound = true; continue; } } if (!commonNameFound) { fields.Insert(0, commonName); } if (!domainNameFound) { fields.Insert(0, domainName); } StringBuilder buffer = new StringBuilder(); for (int ii = 0; ii < fields.Count; ii++) { if (buffer.Length > 0) { buffer.Append(", "); } buffer.Append(fields[ii]); } subjectName = buffer.ToString(); } // create a new certificate with a new public key pair. //certificate = CertificateFactory.CreateCertificate( // id.StoreType, // id.StorePath, // configuration.ApplicationUri, // configuration.ApplicationName, // subjectName, // hostNames, // 1024, // 120); ushort minimumKeySize = CertificateFactory.defaultKeySize; ushort lifeTimeInMonths = CertificateFactory.defaultLifeTime; certificate = CertificateFactory.CreateCertificate( id.StoreType, id.StorePath, null, configuration.ApplicationUri, configuration.ApplicationName, id.SubjectName, hostNames, minimumKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), lifeTimeInMonths, CertificateFactory.defaultHashSize, false, null, null); // update and save the configuration file. id.Certificate = certificate; configuration.SaveToFile(configuration.SourceFilePath); // add certificate to the trusted peer store so other applications will trust it. ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); try { X509Certificate2 certificate2 = store.FindByThumbprint(certificate.Thumbprint).Result[0]; if (certificate2 == null) { store.Add(certificate); } } finally { store.Close(); } // tell the certificate validator about the new certificate. configuration.CertificateValidator.Update(configuration.SecurityConfiguration); SaveCertificate(certificate); }
private static object ToJsonModel(Binding binding) { dynamic obj = new ExpandoObject(); obj.protocol = binding.Protocol; obj.binding_information = binding.BindingInformation; bool isHttp = binding.Protocol.Equals("http") || binding.Protocol.Equals("https"); if (isHttp) { string ipAddress = null; int? port = null; if (binding.EndPoint != null && binding.EndPoint.Address != null) { port = binding.EndPoint.Port; if (binding.EndPoint.Address != null) { ipAddress = binding.EndPoint.Address.Equals(IPAddress.Any) ? "*" : binding.EndPoint.Address.ToString(); } } obj.ip_address = ipAddress; obj.port = port; obj.hostname = binding.Host; // // HTTPS if (binding.Protocol.Equals("https")) { ICertificateStore store = null; // Windows store if (binding.CertificateStoreName != null) { string thumbprint = binding.CertificateHash == null ? null : BitConverter.ToString(binding.CertificateHash)?.Replace("-", string.Empty); store = CertificateStoreProviderAccessor.Instance?.Stores .FirstOrDefault(s => s.Name.Equals(binding.CertificateStoreName, StringComparison.OrdinalIgnoreCase)); // Certificate if (store != null) { obj.certificate = CertificateHelper.ToJsonModelRef(GetCertificate(() => store.GetCertificate(thumbprint).Result)); } } // IIS Central Certificate Store else if (binding.Schema.HasAttribute(sslFlagsAttribute) && binding.SslFlags.HasFlag(SslFlags.CentralCertStore) && !string.IsNullOrEmpty(binding.Host)) { ICentralCertificateStore centralStore = null; if (PathUtil.IsValidFileName(binding.Host)) { centralStore = CertificateStoreProviderAccessor.Instance?.Stores.FirstOrDefault(s => s is ICentralCertificateStore) as ICentralCertificateStore; } // Certificate if (centralStore != null) { obj.certificate = CertificateHelper.ToJsonModelRef(GetCertificate(() => centralStore.GetCertificateByHostName(binding.Host.Replace('*', '_')).Result)); } } // // Ssl Flags if (binding.Schema.HasAttribute(sslFlagsAttribute)) { obj.require_sni = binding.SslFlags.HasFlag(SslFlags.Sni); } } } return(obj); }
public ServiceFabricHealthChecker(ILog log, ICertificateStore certificateStore, IVariables variables) { this.log = log; this.certificateStore = certificateStore; this.variables = variables; }
public PublicKeySymmetricEncryption(ICertificateStore store, ILogger logger, PasswordEncryption passwordEncryption) : base(store, logger) { this.passwordEncryption = passwordEncryption; }
internal void OnDeserializedMethod(StreamingContext context) { // Validate configuration and set reasonable defaults Configuration.ApplicationUri = Configuration.ApplicationUri.Replace("localhost", Utils.GetHostName()); Configuration.ApplicationType = ApplicationType.ClientAndServer; Configuration.TransportQuotas = new TransportQuotas { OperationTimeout = 15000 }; Configuration.ClientConfiguration = new ClientConfiguration(); Configuration.ServerConfiguration = new ServerConfiguration(); if (Configuration.SecurityConfiguration == null) { Configuration.SecurityConfiguration = new SecurityConfiguration(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.RejectedCertificateStore == null) { Configuration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = "CertificateStores/UA Applications"; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath == null) { Configuration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = "CertificateStores/UA Certificate Authorities"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StoreType = "Directory"; } if (Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath == null) { Configuration.SecurityConfiguration.RejectedCertificateStore.StorePath = "CertificateStores/Rejected Certificates"; } Configuration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); Configuration.SecurityConfiguration.ApplicationCertificate.StoreType = "X509Store"; Configuration.SecurityConfiguration.ApplicationCertificate.StorePath = "CurrentUser\\UA_MachineDefault"; Configuration.SecurityConfiguration.ApplicationCertificate.SubjectName = Configuration.ApplicationName; X509Certificate2 certificate = Configuration.SecurityConfiguration.ApplicationCertificate.Find(true).Result; if (certificate == null) { certificate = CertificateFactory.CreateCertificate( Configuration.SecurityConfiguration.ApplicationCertificate.StoreType, Configuration.SecurityConfiguration.ApplicationCertificate.StorePath, Configuration.ApplicationUri, Configuration.ApplicationName, Configuration.ApplicationName, new List <string>() { Configuration.ApplicationName } ); } if (certificate == null) { throw new Exception("Opc.Ua.Publisher.Module: OPC UA application certificate could not be created, cannot continue without it!"); } Configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate; Configuration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); // Ensure it is trusted try { ICertificateStore store = Configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Utils.Trace("Could not open trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } else { try { Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); store.Add(publicKey).Wait(); } finally { store.Close(); } } } catch (Exception e) { Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", Configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath); } // patch our base address if (Configuration.ServerConfiguration.BaseAddresses.Count == 0) { Configuration.ServerConfiguration.BaseAddresses.Add("opc.tcp://" + Configuration.ApplicationName.ToLowerInvariant() + ":62222/UA/Publisher"); } // tighten security policy by removing security policy "none" foreach (ServerSecurityPolicy policy in Configuration.ServerConfiguration.SecurityPolicies) { if (policy.SecurityMode == MessageSecurityMode.None) { Configuration.ServerConfiguration.SecurityPolicies.Remove(policy); break; } } // turn off LDS registration Configuration.ServerConfiguration.MaxRegistrationInterval = 0; // add sign & encrypt policy ServerSecurityPolicy newPolicy = new ServerSecurityPolicy(); newPolicy.SecurityMode = MessageSecurityMode.SignAndEncrypt; newPolicy.SecurityPolicyUri = SecurityPolicies.Basic128Rsa15; Configuration.ServerConfiguration.SecurityPolicies.Add(newPolicy); // enable logging Configuration.TraceConfiguration = new TraceConfiguration(); Configuration.TraceConfiguration.DeleteOnLoad = true; Configuration.TraceConfiguration.TraceMasks = 519; Configuration.TraceConfiguration.OutputFilePath = "./Logs/" + Configuration.ApplicationName + ".log.txt"; Configuration.TraceConfiguration.ApplySettings(); // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s Configuration.TransportQuotas.OperationTimeout = 120000; // validate the configuration now Configuration.Validate(Configuration.ApplicationType).Wait(); }
/// <summary> /// Configures all OPC stack settings /// </summary> public async Task ConfigureAsync() { // Instead of using a Config.xml we configure everything programmatically. // // OPC UA Application configuration // PublisherOpcApplicationConfiguration = new ApplicationConfiguration(); // Passed in as command line argument PublisherOpcApplicationConfiguration.ApplicationName = ApplicationName; PublisherOpcApplicationConfiguration.ApplicationUri = $"urn:{Utils.GetHostName()}:{PublisherOpcApplicationConfiguration.ApplicationName}:microsoft:"; PublisherOpcApplicationConfiguration.ProductUri = "https://github.com/Azure/iot-edge-opc-publisher"; PublisherOpcApplicationConfiguration.ApplicationType = ApplicationType.ClientAndServer; // // Security configuration // PublisherOpcApplicationConfiguration.SecurityConfiguration = new SecurityConfiguration(); // Application certificate PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate = new CertificateIdentifier(); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType = OpcOwnCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath = OpcOwnCertStorePath; PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName = PublisherOpcApplicationConfiguration.ApplicationName; Logger.Information($"Application Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType}"); Logger.Information($"Application Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath}"); Logger.Information($"Application Certificate subject name is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.SubjectName}"); // Use existing certificate, if it is there. X509Certificate2 certificate = await PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Find(true); if (certificate == null) { Logger.Information($"No existing Application certificate found. Create a self-signed Application certificate valid from yesterday for {CertificateFactory.defaultLifeTime} months,"); Logger.Information($"with a {CertificateFactory.defaultKeySize} bit key and {CertificateFactory.defaultHashSize} bit hash."); certificate = CertificateFactory.CreateCertificate( PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StoreType, PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.StorePath, null, PublisherOpcApplicationConfiguration.ApplicationUri, PublisherOpcApplicationConfiguration.ApplicationName, PublisherOpcApplicationConfiguration.ApplicationName, null, CertificateFactory.defaultKeySize, DateTime.UtcNow - TimeSpan.FromDays(1), CertificateFactory.defaultLifeTime, CertificateFactory.defaultHashSize, false, null, null ); PublisherOpcApplicationConfiguration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate ?? throw new Exception("OPC UA application certificate can not be created! Cannot continue without it!"); } else { Logger.Information("Application certificate found in Application Certificate Store"); } PublisherOpcApplicationConfiguration.ApplicationUri = Utils.GetApplicationUriFromCertificate(certificate); Logger.Information($"Application certificate is for Application URI '{PublisherOpcApplicationConfiguration.ApplicationUri}', Application '{PublisherOpcApplicationConfiguration.ApplicationName} and has Subject '{PublisherOpcApplicationConfiguration.ApplicationName}'"); // TrustedIssuerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType = OpcIssuerCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath = OpcIssuerCertStorePath; Logger.Information($"Trusted Issuer store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StoreType}"); Logger.Information($"Trusted Issuer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedIssuerCertificates.StorePath}"); // TrustedPeerCertificates PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType = OpcTrustedCertStoreType; if (string.IsNullOrEmpty(OpcTrustedCertStorePath)) { // Set default. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStoreType == X509Store ? OpcTrustedCertX509StorePathDefault : OpcTrustedCertDirectoryStorePathDefault; if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("_TPC_SP"))) { // Use environment variable. PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = Environment.GetEnvironmentVariable("_TPC_SP"); } } else { PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath = OpcTrustedCertStorePath; } Logger.Information($"Trusted Peer Certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StoreType}"); Logger.Information($"Trusted Peer Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); // RejectedCertificateStore PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore = new CertificateTrustList(); PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType = OpcRejectedCertStoreType; PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath = OpcRejectedCertStorePath; Logger.Information($"Rejected certificate store type is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StoreType}"); Logger.Information($"Rejected Certificate store path is: {PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectedCertificateStore.StorePath}"); // AutoAcceptUntrustedCertificates // This is a security risk and should be set to true only for debugging purposes. PublisherOpcApplicationConfiguration.SecurityConfiguration.AutoAcceptUntrustedCertificates = false; // RejectSHA1SignedCertificates // We allow SHA1 certificates for now as many OPC Servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates = false; Logger.Information($"Rejection of SHA1 signed certificates is {(PublisherOpcApplicationConfiguration.SecurityConfiguration.RejectSHA1SignedCertificates ? "enabled" : "disabled")}"); // MinimunCertificatesKeySize // We allow a minimum key size of 1024 bit, as many OPC UA servers still use them PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize = 1024; Logger.Information($"Minimum certificate key size set to {PublisherOpcApplicationConfiguration.SecurityConfiguration.MinimumCertificateKeySize}"); // We make the default reference stack behavior configurable to put our own certificate into the trusted peer store. if (TrustMyself) { // Ensure it is trusted try { ICertificateStore store = PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Logger.Information($"Can not open trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } else { try { Logger.Information($"Adding publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); await store.Add(publicKey); } finally { store.Close(); } } } catch (Exception e) { Logger.Error(e, $"Can not add publisher certificate to trusted peer store. StorePath={PublisherOpcApplicationConfiguration.SecurityConfiguration.TrustedPeerCertificates.StorePath}"); } } else { Logger.Information("Publisher certificate is not added to trusted peer store."); } // // TransportConfigurations // PublisherOpcApplicationConfiguration.TransportQuotas = new TransportQuotas(); PublisherOpcApplicationConfiguration.TransportQuotas.MaxByteStringLength = 4 * 1024 * 1024; PublisherOpcApplicationConfiguration.TransportQuotas.MaxMessageSize = 4 * 1024 * 1024; // the maximum string length could be set to ajust for large number of nodes when reading the list of published nodes PublisherOpcApplicationConfiguration.TransportQuotas.MaxStringLength = OpcMaxStringLength; // the OperationTimeout should be twice the minimum value for PublishingInterval * KeepAliveCount, so set to 120s PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout = OpcOperationTimeout; Logger.Information($"OperationTimeout set to {PublisherOpcApplicationConfiguration.TransportQuotas.OperationTimeout}"); // // ServerConfiguration // PublisherOpcApplicationConfiguration.ServerConfiguration = new ServerConfiguration(); // BaseAddresses if (PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Count == 0) { // We do not use the localhost replacement mechanism of the configuration loading, to immediately show the base address here PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses.Add($"opc.tcp://{Utils.GetHostName()}:{PublisherServerPort}{PublisherServerPath}"); } foreach (var endpoint in PublisherOpcApplicationConfiguration.ServerConfiguration.BaseAddresses) { Logger.Information($"Publisher server base address: {endpoint}"); } // SecurityPolicies // We do not allow security policy SecurityPolicies.None, but always high security ServerSecurityPolicy newPolicy = new ServerSecurityPolicy() { SecurityMode = MessageSecurityMode.SignAndEncrypt, SecurityPolicyUri = SecurityPolicies.Basic256Sha256 }; PublisherOpcApplicationConfiguration.ServerConfiguration.SecurityPolicies.Add(newPolicy); Logger.Information($"Security policy {newPolicy.SecurityPolicyUri} with mode {newPolicy.SecurityMode} added"); // MaxRegistrationInterval PublisherOpcApplicationConfiguration.ServerConfiguration.MaxRegistrationInterval = LdsRegistrationInterval; Logger.Information($"LDS(-ME) registration intervall set to {LdsRegistrationInterval} ms (0 means no registration)"); // // TraceConfiguration // // // TraceConfiguration // PublisherOpcApplicationConfiguration.TraceConfiguration = new TraceConfiguration(); PublisherOpcApplicationConfiguration.TraceConfiguration.TraceMasks = OpcStackTraceMask; PublisherOpcApplicationConfiguration.TraceConfiguration.ApplySettings(); Utils.Tracing.TraceEventHandler += new EventHandler <TraceEventArgs>(LoggerOpcUaTraceHandler); Logger.Information($"opcstacktracemask set to: 0x{OpcStackTraceMask:X}"); // add default client configuration PublisherOpcApplicationConfiguration.ClientConfiguration = new ClientConfiguration(); // validate the configuration now await PublisherOpcApplicationConfiguration.Validate(PublisherOpcApplicationConfiguration.ApplicationType); }
public AzurePowerShellContext() { this.fileSystem = new WindowsPhysicalFileSystem(); this.certificateStore = new CalamariCertificateStore(); this.embeddedResources = new CallingAssemblyEmbeddedResources(); }
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> /// Synchronous helper implementation of CheckApplicationInstanceCertificate for C++ Proxy /// </summary> public static void CheckApplicationInstanceCertificate(ApplicationConfiguration configuration) { // create a default certificate id none specified. CertificateIdentifier id = configuration.SecurityConfiguration.ApplicationCertificate; if (id == null) { id = new CertificateIdentifier(); id.StoreType = Utils.DefaultStoreType; id.StorePath = Utils.DefaultStorePath; id.SubjectName = configuration.ApplicationName; } // check for certificate with a private key. X509Certificate2 certificate = id.Find(true).Result; if (certificate != null) { return; } // construct the subject name from the List <string> hostNames = new List <string>(); hostNames.Add(Utils.GetHostName()); string commonName = Utils.Format("CN={0}", configuration.ApplicationName); string domainName = Utils.Format("DC={0}", hostNames[0]); string subjectName = Utils.Format("{0}, {1}", commonName, domainName); // create a new certificate with a new public key pair. //certificate = CertificateFactory.CreateCertificate( // id.StoreType, // id.StorePath, // null, // configuration.ApplicationUri, // configuration.ApplicationName, // subjectName, // hostNames, // 2048, // DateTime.UtcNow - TimeSpan.FromHours(1), // 120, // 256, // false, // null, // null); certificate = CertificateFactory.CreateCertificate(configuration.ApplicationUri, configuration.ApplicationName, subjectName, hostNames) .CreateForRSA(); // update and save the configuration file. id.Certificate = certificate; configuration.SaveToFile(configuration.SourceFilePath); // add certificate to the trusted peer store so other applications will trust it. ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); try { X509Certificate2Collection certificateCollection = store.FindByThumbprint(certificate.Thumbprint).Result; if (certificateCollection != null) { store.Add(certificateCollection[0]).Wait(); } } finally { store.Close(); } // tell the certificate validator about the new certificate. configuration.CertificateValidator.Update(configuration.SecurityConfiguration).Wait(); }
/// <summary> /// Adds the certificate to the Trusted Certificate Store /// </summary> /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param> /// <param name="certificate">The certificate to register.</param> private static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } string storePath = null; if (configuration != null && configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null) { storePath = configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath; } if (String.IsNullOrEmpty(storePath)) { Utils.Trace(Utils.TraceMasks.Information, "WARNING: Trusted peer store not specified."); return; } try { ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore(); if (store == null) { Utils.Trace("Could not open trusted peer store. StorePath={0}", storePath); return; } try { // check if it already exists. X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint); if (existingCertificates.Count > 0) { return; } Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", storePath); List <string> subjectName = Utils.ParseDistinguishedName(certificate.Subject); // check for old certificate. X509Certificate2Collection certificates = await store.Enumerate(); for (int ii = 0; ii < certificates.Count; ii++) { if (Utils.CompareDistinguishedName(certificates[ii], subjectName)) { if (certificates[ii].Thumbprint == certificate.Thumbprint) { return; } await store.Delete(certificates[ii].Thumbprint); break; } } // add new certificate. X509Certificate2 publicKey = new X509Certificate2(certificate.RawData); await store.Add(publicKey); } finally { store.Close(); } } catch (Exception e) { Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", storePath); } }
public CertificatesProvider(ICertificateStore certificatesStore, ISecretsStore secretsStore) { this.certificatesStore = certificatesStore; this.secretsStore = secretsStore; }
private async Task <IEnumerable <ICertificate> > SafeGetCertificates(ICertificateStore store) { return((await SafeAccessStore(async() => await store.GetCertificates())) ?? Enumerable.Empty <ICertificate>()); }
public AzurePowershellContext() { this.fileSystem = new WindowsPhysicalFileSystem(); this.certificateStore = new CalamariCertificateStore(); this.embeddedResources = new ExecutingAssemblyEmbeddedResources(); }
public CertificateInstallation(ICertificateStore personalStore, ICertificateStore authorityStore) { _personalStore = personalStore; _authorityStore = authorityStore; }