/// <summary> /// List all reasons for failing cert validation. /// </summary> private static void TraceInnerServiceResults(ServiceResult result) { while (result != null) { Utils.Trace(Utils.TraceMasks.Security, " -- {0}", result.ToString()); result = result.InnerResult; } }
/// <summary> /// Extracts an exception message from a Result object. /// </summary> private static string GetMessage(ServiceResult status) { if (status == null) { return(Strings.DefaultMessage); } if (!LocalizedText.IsNullOrEmpty(status.LocalizedText)) { return(status.LocalizedText.Text); } return(status.ToString()); }
/// <summary> /// Extracts an exception message from a Result object. /// </summary> private static string GetMessage(ServiceResult status) { if (status == null) { return Strings.DefaultMessage; } if (!LocalizedText.IsNullOrEmpty(status.LocalizedText)) { return status.LocalizedText.Text; } return status.ToString(); }
/// <summary> /// Validates a certificate. /// </summary> /// <remarks> /// Each UA application may have a list of trusted certificates that is different from /// all other UA applications that may be running on the same machine. As a result, the /// certificate validator cannot rely completely on the Windows certificate store and /// user or machine specific CTLs (certificate trust lists). /// /// The validator constructs the trust chain for the certificate and follows the chain /// until it finds a certification that is in the application trust list. Non-fatal trust /// chain errors (i.e. certificate expired) are ignored if the certificate is in the /// application trust list. /// /// If no certificate in the chain is trusted then the validator will still accept the /// certification if there are no trust chain errors. /// /// The validator may be configured to ignore the application trust list and/or trust chain. /// </remarks> public virtual void Validate(X509Certificate2Collection chain) { X509Certificate2 certificate = chain[0]; try { lock (m_lock) { InternalValidate(chain).GetAwaiter().GetResult(); // add to list of validated certificates. m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); } } catch (ServiceResultException se) { // check for errors that may be suppressed. if (ContainsUnsuppressibleSC(se.Result)) { SaveCertificate(certificate); Utils.Trace(Utils.TraceMasks.Error, "Certificate '{0}' rejected. Reason={1}.", certificate.Subject, se.Result.ToString()); TraceInnerServiceResults(se.Result); throw new ServiceResultException(se, StatusCodes.BadCertificateInvalid); } else { Utils.Trace("Certificate Vaildation failed for '{0}'. Reason={1}", certificate.Subject, se.ToLongString()); TraceInnerServiceResults(se.Result); } // invoke callback. bool accept = false; ServiceResult serviceResult = se.Result; lock (m_callbackLock) { if (m_CertificateValidation != null) { do { CertificateValidationEventArgs args = new CertificateValidationEventArgs(new ServiceResult(serviceResult), certificate); m_CertificateValidation(this, args); accept = args.Accept; if (accept) { serviceResult = serviceResult.InnerResult; } else { // report the rejected service result se = new ServiceResultException(serviceResult); } } while (accept && serviceResult != null); } } // throw if rejected. if (!accept) { // write the invalid certificate to rejected store if specified. Utils.Trace(Utils.TraceMasks.Error, "Certificate '{0}' rejected. Reason={1}", certificate.Subject, serviceResult.ToString()); SaveCertificate(certificate); throw new ServiceResultException(se, StatusCodes.BadCertificateInvalid); } // add to list of peers. lock (m_lock) { Utils.Trace("Validation error suppressed for '{0}'.", certificate.Subject); m_validatedCertificates[certificate.Thumbprint] = new X509Certificate2(certificate.RawData); } } }