예제 #1
0
        /// <summary>
        /// Creates the objects used to validate the user identity tokens supported by the server.
        /// </summary>
        private void CreateUserIdentityValidators(ApplicationConfiguration configuration)
        {
            for (int ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++)
            {
                UserTokenPolicy policy = configuration.ServerConfiguration.UserTokenPolicies[ii];

                // create a validator for a certificate token policy.
                if (policy.TokenType == UserTokenType.Certificate)
                {
                    // the name of the element in the configuration file.
                    XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Opc.Ua.Namespaces.OpcUa);

                    // find the location of the trusted issuers.
                    CertificateTrustList trustedIssuers = configuration.ParseExtension <CertificateTrustList>(qname);

                    if (trustedIssuers == null)
                    {
                        Utils.Trace(
                            (int)Utils.TraceMasks.Error,
                            "Could not load CertificateTrustList for UserTokenPolicy {0}",
                            policy.PolicyId);

                        continue;
                    }

                    // trusts any certificate in the trusted people store.
                    m_certificateValidator = X509CertificateValidator.PeerTrust;
                }
            }
        }
        internal static async Task <CertificateTrustList> CreateTrustListAsync(
            string storePath,
            X509Certificate2Collection certCollection,
            IList <X509CRL> crlCollection)
        {
            var certTrustList = new CertificateTrustList();

            certTrustList.StoreType = CertificateStoreType.Directory;
            certTrustList.StorePath = storePath;
            using (var store = certTrustList.OpenStore())
            {
                foreach (var cert in certCollection)
                {
                    await store.Add(cert);
                }
                if (store.SupportsCRLs)
                {
                    foreach (var crl in crlCollection)
                    {
                        store.AddCRL(crl);
                    }
                }
            }
            return(certTrustList);
        }
예제 #3
0
        internal static async Task <CertificateTrustList> CreateTrustListAsync(
            string storePath,
            X509Certificate2Collection certCollection,
            IEnumerable <Crl> crlCollection)
        {
            var certTrustList = new CertificateTrustList {
                StoreType = CertificateStoreType.Directory,
                StorePath = storePath
            };

            using (var store = certTrustList.OpenStore()) {
                foreach (var cert in certCollection)
                {
                    await store.Add(cert);
                }
                if (store.SupportsCRLs)
                {
                    foreach (var crl in crlCollection)
                    {
                        using (var x509crl = new X509CRL(crl.RawData)) {
                            store.AddCRL(x509crl);
                        }
                    }
                }
            }
            return(certTrustList);
        }
        /// <summary>
        /// Creates the objects used to validate the user identity tokens supported by the server.
        /// </summary>
        private void CreateUserIdentityValidators(ApplicationConfiguration configuration)
        {
            for (int ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++)
            {
                UserTokenPolicy policy = configuration.ServerConfiguration.UserTokenPolicies[ii];

                // ignore policies without an explicit id.
                if (String.IsNullOrEmpty(policy.PolicyId))
                {
                    continue;
                }

                // create a validator for an issued token policy.
                if (policy.TokenType == UserTokenType.IssuedToken)
                {
                    // the name of the element in the configuration file.
                    XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa);

                    // find the id for the issuer certificate.
                    CertificateIdentifier id = configuration.ParseExtension <CertificateIdentifier>(qname);

                    if (id == null)
                    {
                        Utils.Trace(
                            (int)Utils.TraceMasks.Error,
                            "Could not load CertificateIdentifier for UserTokenPolicy {0}",
                            policy.PolicyId);

                        continue;
                    }

                    m_tokenResolver   = CreateSecurityTokenResolver(id);
                    m_tokenSerializer = WSSecurityTokenSerializer.DefaultInstance;
                }

                // create a validator for a certificate token policy.
                if (policy.TokenType == UserTokenType.Certificate)
                {
                    // the name of the element in the configuration file.
                    XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa);

                    // find the location of the trusted issuers.
                    CertificateTrustList trustedIssuers = configuration.ParseExtension <CertificateTrustList>(qname);

                    if (trustedIssuers == null)
                    {
                        Utils.Trace(
                            (int)Utils.TraceMasks.Error,
                            "Could not load CertificateTrustList for UserTokenPolicy {0}",
                            policy.PolicyId);

                        continue;
                    }

                    // trusts any certificate in the trusted people store.
                    m_certificateValidator = X509CertificateValidator.PeerTrust;
                }
            }
        }
 private string GetCtlDisplayName(CertificateTrustList ctl)
 {
     if (!string.IsNullOrEmpty(ctl.FriendlyName))
     {
         return(ctl.FriendlyName);
     }
     return("Trust List");
 }
예제 #6
0
        /// <summary>
        /// Create trust list
        /// </summary>
        /// <param name="certificateStore"></param>
        /// <returns></returns>
        public static CertificateTrustList ToCertificateTrustList(this CertificateStore certificateStore)
        {
            var certificateTrustList = new CertificateTrustList {
                StoreType = certificateStore.StoreType,
                StorePath = certificateStore.StorePath
            };

            return(certificateTrustList);
        }
 public static X509Object Create(CertificateTrustList ctl, string storeName, StoreLocation storeLocation)
 {
     if (ctl == null)
     {
         throw new ArgumentNullException("ctl");
     }
     return(new X509Object(storeName, storeLocation)
     {
         Value = ctl,
         Data = ctl.RawData
     });
 }
        public static void VerifyApplicationCertIntegrity(
            X509Certificate2 newCert,
            byte[] privateKey,
            string privateKeyPassword,
            string privateKeyFormat,
            X509Certificate2Collection issuerCertificates)
        {
            Assert.NotNull(newCert);
            if (privateKey != null)
            {
                X509Certificate2 newPrivateKeyCert = null;
                if (privateKeyFormat == "PFX")
                {
                    newPrivateKeyCert = CertificateFactory.CreateCertificateFromPKCS12(privateKey, privateKeyPassword);
                }
                else if (privateKeyFormat == "PEM")
                {
                    newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword);
                }
                else
                {
                    Assert.True(false, "Invalid private key format");
                }
                Assert.NotNull(newPrivateKeyCert);
                // verify the public cert matches the private key
                Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true));
                Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true));
            }

            CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection();

            foreach (var issuerCert in issuerCertificates)
            {
                issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert));
            }

            // verify cert with issuer chain
            CertificateValidator certValidator = new CertificateValidator();
            CertificateTrustList issuerStore   = new CertificateTrustList();
            CertificateTrustList trustedStore  = new CertificateTrustList();

            trustedStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(trustedStore, issuerStore, null);
            Assert.Throws <Opc.Ua.ServiceResultException>(() =>
            {
                certValidator.Validate(newCert);
            });
            issuerStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(issuerStore, trustedStore, null);
            certValidator.Validate(newCert);
        }
예제 #9
0
        private CertificateValidator InitValidatorWithStores()
        {
            CertificateValidator certValidator   = new CertificateValidator();
            CertificateTrustList issuerTrustList = new CertificateTrustList();

            issuerTrustList.StoreType = "Directory";
            issuerTrustList.StorePath = _issuerStore.Directory.FullName;
            CertificateTrustList trustedTrustList = new CertificateTrustList();

            trustedTrustList.StoreType = "Directory";
            trustedTrustList.StorePath = _trustedStore.Directory.FullName;
            certValidator.Update(issuerTrustList, trustedTrustList, null);
            return(certValidator);
        }
예제 #10
0
        private CertificateValidator InitValidatorWithStores()
        {
            var certValidator   = new CertificateValidator();
            var issuerTrustList = new CertificateTrustList {
                StoreType = "Directory",
                StorePath = m_issuerStore.Directory.FullName
            };
            var trustedTrustList = new CertificateTrustList {
                StoreType = "Directory",
                StorePath = m_trustedStore.Directory.FullName
            };

            certValidator.Update(issuerTrustList, trustedTrustList, null);
            return(certValidator);
        }
예제 #11
0
        public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, byte[][] issuerCertificates)
        {
            X509Certificate2 newCert = new X509Certificate2(certificate);

            Assert.IsNotNull(newCert);
            X509Certificate2 newPrivateKeyCert = null;

            if (privateKeyFormat == "PFX")
            {
                newPrivateKeyCert = X509Utils.CreateCertificateFromPKCS12(privateKey, privateKeyPassword);
            }
            else if (privateKeyFormat == "PEM")
            {
                newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword);
            }
            else
            {
                Assert.Fail("Invalid private key format");
            }
            Assert.IsNotNull(newPrivateKeyCert);
            // verify the public cert matches the private key
            Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true));
            Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true));
            CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection();

            foreach (var issuer in issuerCertificates)
            {
                var issuerCert = new X509Certificate2(issuer);
                Assert.IsNotNull(issuerCert);
                issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert));
            }

            // verify cert with issuer chain
            CertificateValidator certValidator = new CertificateValidator();
            CertificateTrustList issuerStore   = new CertificateTrustList();
            CertificateTrustList trustedStore  = new CertificateTrustList();

            trustedStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(trustedStore, issuerStore, null);
            Assert.That(() => {
                certValidator.Validate(newCert);
            }, Throws.Exception);
            issuerStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(issuerStore, trustedStore, null);
            certValidator.Validate(newCert);
        }
예제 #12
0
        /// <summary>
        /// Apply the configured settings provided via a CertificateStore to a CertificateTrustList.
        /// </summary>
        public static void ApplyLocalConfig(
            this CertificateTrustList certificateTrustList,
            CertificateStore certificateStore)
        {
            if (certificateTrustList == null)
            {
                throw new ArgumentNullException(nameof(certificateTrustList));
            }

            if (certificateStore == null)
            {
                throw new ArgumentNullException(nameof(certificateStore));
            }

            if (certificateTrustList.StorePath != certificateStore.StorePath)
            {
                certificateTrustList.StoreType = certificateStore.StoreType;
                certificateTrustList.StorePath = certificateStore.StorePath;
            }
        }
예제 #13
0
        public static void VerifyApplicationCertIntegrity(
            X509Certificate2 newCert,
            Key privateKey,
            X509Certificate2Collection issuerCertificates)
        {
            Assert.NotNull(newCert);
            Assert.True(privateKey.HasPrivateKey());
            if (privateKey != null)
            {
                using (var newPrivateKeyCert = new X509Certificate2(newCert.RawData)
                {
                    PrivateKey = privateKey.ToRSA()
                }) {
                    Assert.True(newPrivateKeyCert.HasPrivateKey);
                    Assert.NotNull(newPrivateKeyCert);
                    Assert.True(newPrivateKeyCert.HasPrivateKey);
                    // verify the public cert matches the private key
                    Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true));
                    Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true));
                }
            }
            var issuerCertIdCollection = new CertificateIdentifierCollection();

            foreach (var issuerCert in issuerCertificates)
            {
                issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert));
            }

            // verify cert with issuer chain
            var certValidator = new CertificateValidator();
            var issuerStore   = new CertificateTrustList();
            var trustedStore  = new CertificateTrustList {
                TrustedCertificates = issuerCertIdCollection
            };

            certValidator.Update(trustedStore, issuerStore, null);
            Assert.Throws <ServiceResultException>(() => certValidator.Validate(newCert));
            issuerStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(issuerStore, trustedStore, null);
            certValidator.Validate(newCert);
        }
예제 #14
0
        private async Task <bool> UpdateStoreCertificates(
            CertificateTrustList trustList,
            X509Certificate2Collection updatedCerts)
        {
            bool result             = true;
            ICertificateStore store = null;

            try
            {
                store = trustList.OpenStore();
                var storeCerts = await store.Enumerate().ConfigureAwait(false);

                foreach (var cert in storeCerts)
                {
                    if (!updatedCerts.Contains(cert))
                    {
                        if (!store.Delete(cert.Thumbprint).Result)
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        updatedCerts.Remove(cert);
                    }
                }
                foreach (var cert in updatedCerts)
                {
                    await store.Add(cert).ConfigureAwait(false);
                }
            }
            catch
            {
                result = false;
            }
            finally
            {
                store?.Close();
            }
            return(result);
        }
예제 #15
0
        private async Task <bool> UpdateStoreCrls(
            CertificateTrustList trustList,
            X509CRLCollection updatedCrls)
        {
            bool result             = true;
            ICertificateStore store = null;

            try
            {
                store = trustList.OpenStore();
                var storeCrls = await store.EnumerateCRLs().ConfigureAwait(false);

                foreach (var crl in storeCrls)
                {
                    if (!updatedCrls.Contains(crl))
                    {
                        if (!await store.DeleteCRL(crl).ConfigureAwait(false))
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        updatedCrls.Remove(crl);
                    }
                }
                foreach (var crl in updatedCrls)
                {
                    await store.AddCRL(crl).ConfigureAwait(false);
                }
            }
            catch
            {
                result = false;
            }
            finally
            {
                store?.Close();
            }
            return(result);
        }
        /// <summary>
        /// Creates the validator using the issuer and trusted store.
        /// </summary>
        public CertificateValidator Update()
        {
            var certValidator   = new CertificateValidator();
            var issuerTrustList = new CertificateTrustList {
                StoreType = "Directory",
                StorePath = m_issuerStore.Directory.FullName
            };
            var trustedTrustList = new CertificateTrustList {
                StoreType = "Directory",
                StorePath = m_trustedStore.Directory.FullName
            };
            CertificateStoreIdentifier rejectedList = null;

            if (m_rejectedStore != null)
            {
                rejectedList = new CertificateStoreIdentifier {
                    StoreType = "Directory",
                    StorePath = m_rejectedStore.Directory.FullName
                };
            }
            certValidator.Update(issuerTrustList, trustedTrustList, rejectedList);
            m_certificateValidator = certValidator;
            return(certValidator);
        }
예제 #17
0
        /// <summary>
        /// hardcoded application configuration of the collector server/client
        /// </summary>
        /// <returns>application configuration of the collector server/client</returns>
        public static ApplicationConfiguration getConfiguration()
        {
            //not fully implemented

            ApplicationConfiguration config = new ApplicationConfiguration();

            config.ApplicationName = "Collector Server";
            //config.ApplicationType = null;
            config.ApplicationUri = @"urn:localhost:UA:InformationModelServer";
            //config.CertificateValidator = null;
            //config.ClientConfiguration = null;
            //config.DisableHiResClock = null;
            //config.DiscoveryServerConfiguration = null;
            #region Extensions
            List <XmlElement> config_extensions = new List <XmlElement>();

            #endregion
            config.Extensions = new XmlElementCollection();
            //config.MessageContext = null;
            config.ProductUri = @"http://opcfoundation.org/UA/InformationModelServer";
            //config.Properties = null;
            //config.PropertiesLock = null;
            #region Security Configuration
            SecurityConfiguration config_security             = new SecurityConfiguration();
            CertificateIdentifier config_security_certificate = new CertificateIdentifier();
            config_security_certificate.StoreType   = "Directory";
            config_security_certificate.StorePath   = @"%CommonApplicationData%\OPC Foundation\pki\own";
            config_security_certificate.SubjectName = @"CN = Demo Server, C = US, S = Arizona, O = OPC Foundation, DC = localhost";
            config_security.ApplicationCertificate  = config_security_certificate;
            CertificateTrustList config_trustedIssuer = new CertificateTrustList();
            config_trustedIssuer.StoreType            = "Directory";
            config_trustedIssuer.StorePath            = @"%CommonApplicationData%\OPC Foundation\pki\issuer";
            config_security.TrustedIssuerCertificates = config_trustedIssuer;
            CertificateTrustList config_security_trustedPeer = new CertificateTrustList();
            config_security_trustedPeer.StoreType   = "Directory";
            config_security_trustedPeer.StorePath   = @"%CommonApplicationData%\OPC Foundation\pki\trusted";
            config_security.TrustedPeerCertificates = config_security_trustedPeer;
            CertificateStoreIdentifier config_security_rejected = new CertificateStoreIdentifier();
            config_security_rejected.StoreType       = "Directory";
            config_security_rejected.StorePath       = @"%CommonApplicationData%\OPC Foundation\pki\rejected";
            config_security.RejectedCertificateStore = config_security_rejected;
            #endregion
            config.SecurityConfiguration = config_security;
            //config_security.ApplicationCertificate = null;
            #region ServerConfiguration
            ServerConfiguration config_server            = new ServerConfiguration();
            List <string>       config_server_baseAdress = new List <string>();
            config_server_baseAdress.Add(@"https://*****:*****@"opc.tcp://localhost:51210/CollectorServer");
            config_server.BaseAddresses = new StringCollection(config_server_baseAdress);
            List <ServerSecurityPolicy> config_server_policies = new List <ServerSecurityPolicy>();
            ServerSecurityPolicy        tmp_pol1 = new ServerSecurityPolicy();
            tmp_pol1.SecurityMode      = MessageSecurityMode.SignAndEncrypt;
            tmp_pol1.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256";
            config_server_policies.Add(tmp_pol1);
            ServerSecurityPolicy tmp_pol2 = new ServerSecurityPolicy();
            tmp_pol2.SecurityMode      = MessageSecurityMode.None;
            tmp_pol2.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#None";
            config_server_policies.Add(tmp_pol2);
            ServerSecurityPolicy tmp_pol3 = new ServerSecurityPolicy();
            tmp_pol3.SecurityMode      = MessageSecurityMode.Sign;
            tmp_pol3.SecurityPolicyUri = @"";
            config_server_policies.Add(tmp_pol3);
            ServerSecurityPolicy tmp_pol4 = new ServerSecurityPolicy();
            tmp_pol4.SecurityMode      = MessageSecurityMode.SignAndEncrypt;
            tmp_pol4.SecurityPolicyUri = @"";
            ServerSecurityPolicyCollection config_server_policy = new ServerSecurityPolicyCollection(config_server_policies);
            config_server.SecurityPolicies = config_server_policy;
            List <UserTokenPolicy> config_server_userTokenPolicies = new List <UserTokenPolicy>();
            config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous));
            config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName));
            config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Certificate));
            config_server.UserTokenPolicies            = new UserTokenPolicyCollection(config_server_userTokenPolicies);
            config_server.DiagnosticsEnabled           = false;
            config_server.MaxSessionCount              = 100;
            config_server.MinSessionTimeout            = 10000;
            config_server.MaxSessionTimeout            = 3600000;
            config_server.MaxBrowseContinuationPoints  = 10;
            config_server.MaxQueryContinuationPoints   = 10;
            config_server.MaxHistoryContinuationPoints = 100;
            config_server.MaxRequestAge               = 600000;
            config_server.MinPublishingInterval       = 100;
            config_server.MaxPublishingInterval       = 3600000;
            config_server.PublishingResolution        = 50;
            config_server.MaxSubscriptionLifetime     = 3600000;
            config_server.MaxMessageQueueSize         = 10;
            config_server.MaxNotificationQueueSize    = 100;
            config_server.MaxNotificationsPerPublish  = 1000;
            config_server.MinMetadataSamplingInterval = 1000;
            List <SamplingRateGroup> config_server_samplingRateGroups = new List <SamplingRateGroup>();
            config_server_samplingRateGroups.Add(new SamplingRateGroup(5, 5, 20));
            config_server_samplingRateGroups.Add(new SamplingRateGroup(100, 100, 4));
            config_server_samplingRateGroups.Add(new SamplingRateGroup(500, 250, 2));
            config_server_samplingRateGroups.Add(new SamplingRateGroup(1000, 500, 20));
            config_server.AvailableSamplingRates  = new SamplingRateGroupCollection(config_server_samplingRateGroups);
            config_server.MaxRegistrationInterval = 30000;
            #endregion
            config.ServerConfiguration = config_server;
            //config.SourceFilePath = null;
            #region TraceConfiguration
            TraceConfiguration config_traceConfiguration = new TraceConfiguration();
            config_traceConfiguration.OutputFilePath = @"Logs\Quickstarts.BoilerServer.log.txt";
            config_traceConfiguration.DeleteOnLoad   = true;
            config_traceConfiguration.TraceMasks     = 515;
            #endregion
            config.TraceConfiguration      = config_traceConfiguration;
            config.TransportConfigurations = new TransportConfigurationCollection();
            #region TransportQuotas
            TransportQuotas config_transportQuotas = new TransportQuotas();
            config_transportQuotas.OperationTimeout      = 600000;
            config_transportQuotas.MaxStringLength       = 1048576;
            config_transportQuotas.MaxByteStringLength   = 1048576;
            config_transportQuotas.MaxArrayLength        = 65535;
            config_transportQuotas.ChannelLifetime       = 300000;
            config_transportQuotas.SecurityTokenLifetime = 3600000;
            #endregion
            config.TransportQuotas = config_transportQuotas;
            return(config);
        }
예제 #18
0
        private ServiceResult UpdateCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            byte[] certificate,
            byte[][] issuerCertificates,
            string privateKeyFormat,
            byte[] privateKey,
            ref bool applyChangesRequired)
        {
            HasApplicationSecureAdminAccess(context);

            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            privateKeyFormat = privateKeyFormat?.ToUpper();
            if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX"))
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported.");
            }

            ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId);

            certificateGroup.UpdateCertificate = null;

            X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection();
            X509Certificate2           newCert;

            try
            {
                // build issuer chain
                if (issuerCertificates != null)
                {
                    foreach (byte[] issuerRawCert in issuerCertificates)
                    {
                        var newIssuerCert = new X509Certificate2(issuerRawCert);
                        newIssuerCollection.Add(newIssuerCert);
                    }
                }

                newCert = new X509Certificate2(certificate);
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid.");
            }

            // load existing application cert and private key
            if (!Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name))
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application.");
            }

            // self signed
            bool selfSigned = Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer);

            if (selfSigned && newIssuerCollection.Count != 0)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate.");
            }

            if (!selfSigned)
            {
                try
                {
                    // verify cert with issuer chain
                    CertificateValidator            certValidator    = new CertificateValidator();
                    CertificateTrustList            issuerStore      = new CertificateTrustList();
                    CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection();
                    foreach (var issuerCert in newIssuerCollection)
                    {
                        issuerCollection.Add(new CertificateIdentifier(issuerCert));
                    }
                    issuerStore.TrustedCertificates = issuerCollection;
                    certValidator.Update(issuerStore, issuerStore, null);
                    certValidator.Validate(newCert);
                }
                catch
                {
                    throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list.");
                }
            }

            var updateCertificate = new UpdateCertificateData();

            try
            {
                string password = String.Empty;
                switch (privateKeyFormat)
                {
                case null:
                case "":
                {
                    X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKey(password).Result;
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PFX":
                {
                    X509Certificate2 certWithPrivateKey = CertificateFactory.CreateCertificateFromPKCS12(privateKey, password);
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PEM":
                {
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, password);
                    break;
                }
                }
                updateCertificate.IssuerCollection = newIssuerCollection;
                updateCertificate.SessionId        = context.SessionId;
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key.");
            }

            certificateGroup.UpdateCertificate = updateCertificate;
            applyChangesRequired = true;

            return(ServiceResult.Good);
        }
예제 #19
0
        public static void VerifySignedApplicationCert(ApplicationTestData testApp,
                                                       X509Certificate2 signedCert, X509Certificate2Collection issuerCerts)
        {
            var issuerCert = issuerCerts[0];

            var signedCertO = signedCert.ToCertificate();

            Assert.NotNull(signedCertO);
            Assert.False(signedCert.HasPrivateKey);
            Assert.True(Utils.CompareDistinguishedName(testApp.Subject, signedCert.Subject));
            Assert.False(Utils.CompareDistinguishedName(signedCert.Issuer, signedCert.Subject));
            Assert.True(Utils.CompareDistinguishedName(signedCert.Issuer, issuerCert.Subject));

            // test basic constraints
            var constraints = signedCertO.GetBasicConstraintsExtension();

            Assert.NotNull(constraints);
            Assert.True(constraints.Critical);
            Assert.False(constraints.CertificateAuthority);
            Assert.False(constraints.HasPathLengthConstraint);

            // key usage
            var keyUsage = signedCertO.GetKeyUsageExtension();

            Assert.NotNull(keyUsage);
            Assert.True(keyUsage.Critical);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.CrlSign) == 0);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DataEncipherment) == X509KeyUsageFlags.DataEncipherment);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DecipherOnly) == 0);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.DigitalSignature);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.EncipherOnly) == 0);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyAgreement) == 0);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyCertSign) == 0);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyEncipherment) == X509KeyUsageFlags.KeyEncipherment);
            Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.NonRepudiation);

            // enhanced key usage
            var enhancedKeyUsage = signedCertO.GetEnhancedKeyUsageExtension();

            Assert.NotNull(enhancedKeyUsage);
            Assert.True(enhancedKeyUsage.Critical);

            // test for authority key
            var authority = signedCertO.GetAuthorityKeyIdentifierExtension();

            Assert.NotNull(authority);
            Assert.NotNull(authority.SerialNumber);
            Assert.NotNull(authority.KeyId);
            Assert.NotNull(authority.AuthorityNames);

            // verify authority key in signed cert
            var subjectKeyId = signedCertO.GetSubjectKeyIdentifierExtension();

            Assert.Equal(subjectKeyId.SubjectKeyIdentifier, authority.KeyId);
            Assert.Equal(issuerCert.SerialNumber, authority.SerialNumber.ToString());

            var subjectAlternateName = signedCertO.GetSubjectAltNameExtension();

            Assert.NotNull(subjectAlternateName);
            Assert.False(subjectAlternateName.Critical);
            var domainNames = Utils.GetDomainsFromCertficate(signedCert);

            foreach (var domainName in testApp.DomainNames)
            {
                Assert.Contains(domainName, domainNames, StringComparer.OrdinalIgnoreCase);
            }
            Assert.True(subjectAlternateName.Uris.Count == 1);
            var applicationUri = Utils.GetApplicationUriFromCertificate(signedCert);

            Assert.True(testApp.ApplicationRecord.ApplicationUri == applicationUri);

            var issuerCertIdCollection = new CertificateIdentifierCollection();

            foreach (var cert in issuerCerts)
            {
                issuerCertIdCollection.Add(new CertificateIdentifier(cert));
            }

            // verify cert with issuer chain
            var certValidator = new CertificateValidator();
            var issuerStore   = new CertificateTrustList();
            var trustedStore  = new CertificateTrustList {
                TrustedCertificates = issuerCertIdCollection
            };

            certValidator.Update(trustedStore, issuerStore, null);
            Assert.Throws <ServiceResultException>(() => certValidator.Validate(signedCert));
            issuerStore.TrustedCertificates = issuerCertIdCollection;
            certValidator.Update(issuerStore, trustedStore, null);
            certValidator.Validate(signedCert);
        }
예제 #20
0
        private ServiceResult UpdateCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            byte[] certificate,
            byte[][] issuerCertificates,
            string privateKeyFormat,
            byte[] privateKey,
            ref bool applyChangesRequired)
        {
            HasApplicationSecureAdminAccess(context);

            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            privateKeyFormat = privateKeyFormat?.ToUpper();
            if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX"))
            {
                throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported.");
            }

            ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId);

            certificateGroup.UpdateCertificate = null;

            X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection();
            X509Certificate2           newCert;

            try
            {
                // build issuer chain
                if (issuerCertificates != null)
                {
                    foreach (byte[] issuerRawCert in issuerCertificates)
                    {
                        var newIssuerCert = new X509Certificate2(issuerRawCert);
                        newIssuerCollection.Add(newIssuerCert);
                    }
                }

                newCert = new X509Certificate2(certificate);
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid.");
            }

            // validate new subject matches the previous subject
            if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name))
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application.");
            }

            // self signed
            bool selfSigned = X509Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer);

            if (selfSigned && newIssuerCollection.Count != 0)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate.");
            }

            if (!selfSigned)
            {
                try
                {
                    // verify cert with issuer chain
                    CertificateValidator            certValidator    = new CertificateValidator();
                    CertificateTrustList            issuerStore      = new CertificateTrustList();
                    CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection();
                    foreach (var issuerCert in newIssuerCollection)
                    {
                        issuerCollection.Add(new CertificateIdentifier(issuerCert));
                    }
                    issuerStore.TrustedCertificates = issuerCollection;
                    certValidator.Update(issuerStore, issuerStore, null);
                    certValidator.Validate(newCert);
                }
                catch
                {
                    throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list.");
                }
            }

            var updateCertificate = new UpdateCertificateData();

            try
            {
                var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider;
                switch (privateKeyFormat)
                {
                case null:
                case "":
                {
                    X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result;
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PFX":
                {
                    X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate));
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey);
                    break;
                }

                case "PEM":
                {
                    updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate));
                    break;
                }
                }
                updateCertificate.IssuerCollection = newIssuerCollection;
                updateCertificate.SessionId        = context.SessionId;
            }
            catch
            {
                throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key.");
            }

            certificateGroup.UpdateCertificate = updateCertificate;
            applyChangesRequired = true;

            if (updateCertificate != null)
            {
                try
                {
                    using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore())
                    {
                        Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate);
                        appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait();
                        Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey);
                        var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider;
                        appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait();
                        // keep only track of cert without private key
                        var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData);
                        updateCertificate.CertificateWithPrivateKey.Dispose();
                        updateCertificate.CertificateWithPrivateKey = certOnly;
                    }
                    using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath))
                    {
                        foreach (var issuer in updateCertificate.IssuerCollection)
                        {
                            try
                            {
                                Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer);
                                issuerStore.Add(issuer).Wait();
                            }
                            catch (ArgumentException)
                            {
                                // ignore error if issuer cert already exists
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex));
                    throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex);
                }
            }

            return(ServiceResult.Good);
        }
예제 #21
0
 public CapiCtlWrapper(CertificateTrustList certificateTrustList)
 {
     ctl = certificateTrustList;
 }