/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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"); } }
/// <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)); }