/// <summary>
        /// Determines if the specified object is equal to the <paramref name="obj"/>.
        /// </summary>
        /// <param name="obj">The object to compare to this instance of object</param>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current embeded object; otherwise, false.
        /// </returns>
        public override bool Equals(object obj)
        {
            if (Object.ReferenceEquals(obj, null))
            {
                return(IsNull(this));
            }

            if (Object.ReferenceEquals(this, obj))
            {
                return(true);
            }

            ExtensionObject value = obj as ExtensionObject;

            if (value != null)
            {
                if (this.m_typeId != value.m_typeId)
                {
                    return(false);
                }

                return(Utils.IsEqual(this.m_body, value.m_body));
            }

            return(false);
        }
Beispiel #2
0
        /// <summary cref="IEncodeable.IsEqual(IEncodeable)" />
        public virtual bool IsEqual(IEncodeable encodeable)
        {
            if (Object.ReferenceEquals(this, encodeable))
            {
                return(true);
            }

            SoftwareCertificate value = encodeable as SoftwareCertificate;

            if (value == null)
            {
                return(false);
            }

            if (!Utils.IsEqual(m_productName, value.m_productName))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_productUri, value.m_productUri))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_vendorName, value.m_vendorName))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_vendorProductCertificate, value.m_vendorProductCertificate))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_softwareVersion, value.m_softwareVersion))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_buildNumber, value.m_buildNumber))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_buildDate, value.m_buildDate))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_issuedBy, value.m_issuedBy))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_issueDate, value.m_issueDate))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_supportedProfiles, value.m_supportedProfiles))
            {
                return(false);
            }

            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Returns the certificate information for a trusted peer certificate.
        /// </summary>
        private async Task <CertificateIdentifier> GetTrustedCertificate(X509Certificate2 certificate)
        {
            string certificateThumbprint = certificate.Thumbprint.ToUpper();

            // check if explicitly trusted.
            if (m_trustedCertificateList != null)
            {
                for (int ii = 0; ii < m_trustedCertificateList.Count; ii++)
                {
                    X509Certificate2 trusted = await m_trustedCertificateList[ii].Find(false);

                    if (trusted != null && trusted.Thumbprint == certificate.Thumbprint)
                    {
                        if (Utils.IsEqual(trusted.RawData, certificate.RawData))
                        {
                            return(m_trustedCertificateList[ii]);
                        }
                    }
                }
            }

            // check if in peer trust store.
            if (m_trustedCertificateStore != null)
            {
                ICertificateStore store = m_trustedCertificateStore.OpenStore();

                try
                {
                    X509Certificate2Collection trusted = await store.FindByThumbprint(certificate.Thumbprint);

                    for (int ii = 0; ii < trusted.Count; ii++)
                    {
                        if (Utils.IsEqual(trusted[ii].RawData, certificate.RawData))
                        {
                            return(new CertificateIdentifier(trusted[ii], m_trustedCertificateStore.ValidationOptions));
                        }
                    }
                }
                finally
                {
                    store.Close();
                }
            }

            // not a trusted.
            return(null);
        }
Beispiel #4
0
        /// <summary>
        /// Get the certificate by issuer and serial number.
        /// </summary>
        public static async Task <X509Certificate2> FindIssuerCABySerialNumberAsync(
            ICertificateStore store,
            string issuer,
            string serialnumber)
        {
            X509Certificate2Collection certificates = await store.Enumerate();

            foreach (var certificate in certificates)
            {
                if (X509Utils.CompareDistinguishedName(certificate.Subject, issuer) &&
                    Utils.IsEqual(certificate.SerialNumber, serialnumber))
                {
                    return(certificate);
                }
            }

            return(null);
        }
Beispiel #5
0
        /// <summary>
        /// Determines if the specified object is equal to the object.
        /// </summary>
        /// <remarks>
        /// Determines if the specified object is equal to the object.
        /// </remarks>
        /// <param name="obj">The object to compare to *this*</param>
        public override bool Equals(object obj)
        {
            if (Object.ReferenceEquals(this, obj))
            {
                return(true);
            }

            DataValue value = obj as DataValue;

            if (value != null)
            {
                if (this.m_statusCode != value.m_statusCode)
                {
                    return(false);
                }

                if (this.m_serverTimestamp != value.m_serverTimestamp)
                {
                    return(false);
                }

                if (this.m_sourceTimestamp != value.m_sourceTimestamp)
                {
                    return(false);
                }

                if (this.m_serverPicoseconds != value.m_serverPicoseconds)
                {
                    return(false);
                }

                if (this.m_serverTimestamp != value.m_serverTimestamp)
                {
                    return(false);
                }

                return(Utils.IsEqual(this.m_value.Value, value.m_value.Value));
            }

            return(false);
        }
Beispiel #6
0
        /// <summary cref="IEncodeable.IsEqual(IEncodeable)" />
        public virtual bool IsEqual(IEncodeable encodeable)
        {
            if (Object.ReferenceEquals(this, encodeable))
            {
                return(true);
            }

            SupportedProfile value = encodeable as SupportedProfile;

            if (value == null)
            {
                return(false);
            }

            if (!Utils.IsEqual(m_organizationUri, value.m_organizationUri))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_profileId, value.m_profileId))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_complianceTool, value.m_complianceTool))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_complianceDate, value.m_complianceDate))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_complianceLevel, value.m_complianceLevel))
            {
                return(false);
            }
            if (!Utils.IsEqual(m_unsupportedUnitIds, value.m_unsupportedUnitIds))
            {
                return(false);
            }

            return(true);
        }
Beispiel #7
0
        /// <summary>
        /// Determines if the specified object is equal to the object.
        /// </summary>
        /// <remarks>
        /// Determines if the specified object is equal to the object.
        /// </remarks>
        /// <param name="other">The DataValue to compare to *this*</param>
        public bool Equals(DataValue other)
        {
            if (Object.ReferenceEquals(this, other))
            {
                return(true);
            }

            if (other != null)
            {
                if (this.m_statusCode != other.m_statusCode)
                {
                    return(false);
                }

                if (this.m_serverTimestamp != other.m_serverTimestamp)
                {
                    return(false);
                }

                if (this.m_sourceTimestamp != other.m_sourceTimestamp)
                {
                    return(false);
                }

                if (this.m_serverPicoseconds != other.m_serverPicoseconds)
                {
                    return(false);
                }

                if (this.m_sourcePicoseconds != other.m_sourcePicoseconds)
                {
                    return(false);
                }

                return(Utils.IsEqual(this.m_value.Value, other.m_value.Value));
            }

            return(false);
        }
Beispiel #8
0
        /// <summary>
        /// Validate domains in a server certificate against endpoint used to connect a session.
        /// </summary>
        /// <param name="serverCertificate">The server certificate returned by a session connect.</param>
        /// <param name="endpoint">The endpoint used to connect to a server.</param>
        public void ValidateDomains(X509Certificate2 serverCertificate, ConfiguredEndpoint endpoint)
        {
            X509Certificate2 certificate2;

            if (m_validatedCertificates.TryGetValue(serverCertificate.Thumbprint, out certificate2))
            {
                if (Utils.IsEqual(certificate2.RawData, serverCertificate.RawData))
                {
                    return;
                }
            }

            bool domainFound = FindDomain(serverCertificate, endpoint);

            if (!domainFound)
            {
                bool   accept  = false;
                string message = Utils.Format(
                    "The domain '{0}' is not listed in the server certificate.",
                    endpoint.EndpointUrl.DnsSafeHost);
                var serviceResult = new ServiceResultException(StatusCodes.BadCertificateHostNameInvalid, message);
                if (m_CertificateValidation != null)
                {
                    var args = new CertificateValidationEventArgs(new ServiceResult(serviceResult), serverCertificate);
                    m_CertificateValidation(this, args);
                    accept = args.Accept || args.AcceptAll;
                }
                // throw if rejected.
                if (!accept)
                {
                    // write the invalid certificate to rejected store if specified.
                    Utils.Trace(Utils.TraceMasks.Error, "Certificate '{0}' rejected. Reason={1}",
                                serverCertificate.Subject, serviceResult.ToString());
                    SaveCertificate(serverCertificate);

                    throw serviceResult;
                }
            }
        }
        /// <summary cref="IEncodeable.IsEqual(IEncodeable)" />
        public virtual bool IsEqual(IEncodeable encodeable)
        {
            if (Object.ReferenceEquals(this, encodeable))
            {
                return(true);
            }
            var value = encodeable as KeyDataValuePair;

            if (value == null)
            {
                return(false);
            }
            if (!Utils.IsEqual(Key, value.Key))
            {
                return(false);
            }
            if (!Utils.IsEqual(Value, value.Value))
            {
                return(false);
            }
            return(true);
        }
Beispiel #10
0
        /// <summary>
        /// Throws an exception if validation fails.
        /// </summary>
        /// <param name="certificates">The certificates to be checked.</param>
        /// <exception cref="ServiceResultException">If certificate[0] cannot be accepted</exception>
        protected virtual async Task InternalValidate(X509Certificate2Collection certificates)
        {
            X509Certificate2 certificate = certificates[0];

            // check for previously validated certificate.
            X509Certificate2 certificate2 = null;

            if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2))
            {
                if (Utils.IsEqual(certificate2.RawData, certificate.RawData))
                {
                    return;
                }
            }

            CertificateIdentifier trustedCertificate = await GetTrustedCertificate(certificate);

            // get the issuers (checks the revocation lists if using directory stores).
            List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
            bool isIssuerTrusted = await GetIssuers(certificates, issuers);

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

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

            foreach (CertificateIdentifier issuer in issuers)
            {
                if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                {
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;
                }

                // we did the revocation check in the GetIssuers call. No need here.
                policy.RevocationMode = X509RevocationMode.NoCheck;
                policy.ExtraStore.Add(issuer.Certificate);
            }

            // build chain.
            X509Chain chain = new X509Chain();

            chain.ChainPolicy = policy;
            chain.Build(certificate);

            // check the chain results.
            CertificateIdentifier target = trustedCertificate;

            if (target == null)
            {
                target = new CertificateIdentifier(certificate);
            }

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

                CertificateIdentifier issuer = null;

                if (ii < issuers.Count)
                {
                    issuer = issuers[ii];
                }

                // check for chain status errors.
                foreach (X509ChainStatus status in element.ChainElementStatus)
                {
                    ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0));

                    if (ServiceResult.IsBad(result))
                    {
                        // check untrusted certificates.
                        if (trustedCertificate == null)
                        {
                            throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed);
                        }

                        throw new ServiceResultException(result);
                    }
                }

                if (issuer != null)
                {
                    target = issuer;
                }
            }

            bool issuedByCA = !Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer);

            // check if certificate issuer is trusted.
            if (issuedByCA && !isIssuerTrusted)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate issuer is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }

            // check if certificate is trusted.
            if (trustedCertificate == null && !isIssuerTrusted)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }
        }
        /// <summary>
        /// Throws an exception if validation fails.
        /// </summary>
        /// <param name="certificates">The certificates to be checked.</param>
        /// <exception cref="ServiceResultException">If certificate[0] cannot be accepted</exception>
        protected virtual async Task InternalValidate(X509Certificate2Collection certificates)
        {
            X509Certificate2 certificate = certificates[0];

            // check for previously validated certificate.
            X509Certificate2 certificate2 = null;

            if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2))
            {
                if (Utils.IsEqual(certificate2.RawData, certificate.RawData))
                {
                    return;
                }
            }

            CertificateIdentifier trustedCertificate = await GetTrustedCertificate(certificate);

            // get the issuers (checks the revocation lists if using directory stores).
            List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
            bool isIssuerTrusted = await GetIssuers(certificates, issuers);

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

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

            foreach (CertificateIdentifier issuer in issuers)
            {
                if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) != 0)
                {
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                    policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;
                }

                // we did the revocation check in the GetIssuers call. No need here.
                policy.RevocationMode = X509RevocationMode.NoCheck;
                policy.ExtraStore.Add(issuer.Certificate);
            }

            // build chain.
            bool      chainStatusChecked = false;
            X509Chain chain = new X509Chain();

            chain.ChainPolicy = policy;
            chain.Build(certificate);

            // check the chain results.
            CertificateIdentifier target = trustedCertificate;

            if (target == null)
            {
                target = new CertificateIdentifier(certificate);
            }

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

                CertificateIdentifier issuer = null;

                if (ii < issuers.Count)
                {
                    issuer = issuers[ii];
                }

                // check for chain status errors.
                foreach (X509ChainStatus status in element.ChainElementStatus)
                {
                    ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0));

                    if (ServiceResult.IsBad(result))
                    {
                        // check untrusted certificates.
                        if (trustedCertificate == null)
                        {
                            throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed);
                        }

                        throw new ServiceResultException(result);
                    }
                    chainStatusChecked = true;
                }

                if (issuer != null)
                {
                    target = issuer;
                }
            }

            // check whether the chain is complete (if there is a chain)
            bool issuedByCA      = !Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer);
            bool chainIncomplete = false;

            if (issuers.Count > 0)
            {
                var rootCertificate = issuers[issuers.Count - 1].Certificate;
                if (!Utils.CompareDistinguishedName(rootCertificate.Subject, rootCertificate.Issuer))
                {
                    chainIncomplete = true;
                }
            }
            else
            {
                if (issuedByCA)
                {
                    // no issuer found at all
                    chainIncomplete = true;
                }
            }

            if (issuedByCA && (!chainStatusChecked || chainIncomplete))
            {
                throw ServiceResultException.Create(
                          StatusCodes.BadCertificateChainIncomplete,
                          "Certificate chain validation incomplete.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                          certificate.SubjectName.Name,
                          certificate.IssuerName.Name);
            }

            // check if certificate issuer is trusted.
            if (issuedByCA && !isIssuerTrusted && trustedCertificate == null)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate issuer is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }

            // check if certificate is trusted.
            if (trustedCertificate == null && !isIssuerTrusted)
            {
                if (m_applicationCertificate == null || !Utils.IsEqual(m_applicationCertificate.RawData, certificate.RawData))
                {
                    throw ServiceResultException.Create(
                              StatusCodes.BadCertificateUntrusted,
                              "Certificate is not trusted.\r\nSubjectName: {0}\r\nIssuerName: {1}",
                              certificate.SubjectName.Name,
                              certificate.IssuerName.Name);
                }
            }

            // check if certificate is valid for use as app/sw or user cert
            X509KeyUsageFlags certificateKeyUsage = CertificateFactory.GetKeyUsage(certificate);

            if ((certificateKeyUsage & X509KeyUsageFlags.DataEncipherment) == 0)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed, "Usage of certificate is not allowed.");
            }

            // check if minimum requirements are met
            if (m_rejectSHA1SignedCertificates && IsSHA1SignatureAlgorithm(certificate.SignatureAlgorithm))
            {
                throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "SHA1 signed certificates are not trusted");
            }

            if (certificate.GetRSAPublicKey().KeySize < m_minimumCertificateKeySize)
            {
                throw new ServiceResultException(StatusCodes.BadCertificatePolicyCheckFailed, "Certificate doesn't meet minimum key length requirement");
            }
        }
Beispiel #12
0
        /// <summary>
        /// Throws an exception if validation fails.
        /// </summary>
        /// <param name="certificates">The certificates to be checked.</param>
        /// <exception cref="ServiceResultException">If certificate[0] cannot be accepted</exception>
        protected virtual void InternalValidateWithChainSupportEnabled(X509Certificate2Collection certificates)
        {
            lock (m_lock) {
                X509Certificate2 certificate = certificates[0];

                // check for previously validated certificate.
                X509Certificate2 certificate2 = null;

                if (m_validatedCertificates.TryGetValue(certificate.Thumbprint, out certificate2))
                {
                    if (Utils.IsEqual(certificate2.RawData, certificate.RawData))
                    {
                        return;
                    }
                }

                CertificateIdentifier trustedCertificate = GetTrustedCertificate(certificate);

                // get the issuers (checks the revocation lists if using directory stores).
                List <CertificateIdentifier> issuers = new List <CertificateIdentifier>();
                bool isIssuerTrusted = GetIssuersWithChainSupportEnabled(certificates, issuers);
                // setup policy chain
                X509ChainPolicy policy = new X509ChainPolicy();

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

                foreach (CertificateIdentifier issuer in issuers)
                {
                    if ((issuer.ValidationOptions & CertificateValidationOptions.SuppressRevocationStatusUnknown) !=
                        0)
                    {
                        policy.VerificationFlags |= X509VerificationFlags.IgnoreCertificateAuthorityRevocationUnknown;
                        policy.VerificationFlags |= X509VerificationFlags.IgnoreCtlSignerRevocationUnknown;
                        policy.VerificationFlags |= X509VerificationFlags.IgnoreEndRevocationUnknown;
                        policy.VerificationFlags |= X509VerificationFlags.IgnoreRootRevocationUnknown;
                    }

                    // we did the revocation check in the GetIssuers call. No need here.
                    policy.RevocationMode = X509RevocationMode.NoCheck;
                    policy.ExtraStore.Add(issuer.Certificate);
                }

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

                // check the chain results.
                CertificateIdentifier target = trustedCertificate;

                if (target == null)
                {
                    target = new CertificateIdentifier(certificate);
                }

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

                    CertificateIdentifier issuer = null;

                    if (ii < issuers.Count)
                    {
                        issuer = issuers[ii];
                    }

                    // check for chain status errors.
                    foreach (X509ChainStatus status in element.ChainElementStatus)
                    {
                        ServiceResult result = CheckChainStatus(status, target, issuer, (ii != 0));

                        if (ServiceResult.IsBad(result))
                        {
                            throw new ServiceResultException(result);
                        }
                    }

                    if (issuer != null)
                    {
                        target = issuer;
                    }
                }
            }
        }
 /// <summary>
 /// Compares two distinguished names.
 /// </summary>
 public static bool CompareDistinguishedName(X500DistinguishedName name1, X500DistinguishedName name2)
 {
     // check for simple binary equality.
     return(Utils.IsEqual(name1.RawData, name2.RawData));
 }