@@ -538,17 +538,67 @@ private async ValueTask<UpdateCertificateMethodStateResult> UpdateCertificateAsy
538538 {
539539 try
540540 {
541- // verify cert with issuer chain
542- var certValidator = new CertificateValidator ( Server . Telemetry ) ;
543- var issuerStore = new CertificateTrustList ( ) ;
544- var issuerCollection = new CertificateIdentifierCollection ( ) ;
541+ // Verify chain integrity: build a chain rooted at any of the provided
542+ // issuer certificates and ensure all signatures are valid. We do not
543+ // consult the application's trust list here — the caller is supplying
544+ // the issuer chain as part of the UpdateCertificate input. Policy checks
545+ // (minimum key size, SHA-1, revocation) are intentionally not applied here;
546+ // the server's configured SecurityConfiguration governs certificate
547+ // acceptance on its communication channels.
548+ var chainPolicy = new X509ChainPolicy
549+ {
550+ RevocationFlag = X509RevocationFlag . EntireChain ,
551+ RevocationMode = X509RevocationMode . NoCheck ,
552+ VerificationFlags =
553+ X509VerificationFlags . AllowUnknownCertificateAuthority |
554+ X509VerificationFlags . IgnoreCertificateAuthorityRevocationUnknown |
555+ X509VerificationFlags . IgnoreEndRevocationUnknown |
556+ X509VerificationFlags . IgnoreRootRevocationUnknown ,
557+ #if NET5_0_OR_GREATER
558+ DisableCertificateDownloads = true ,
559+ #endif
560+ UrlRetrievalTimeout = TimeSpan. FromMilliseconds ( 1 )
561+ } ;
562+
545563 foreach ( X509Certificate2 issuerCert in newIssuerCollection )
546564 {
547- issuerCollection . Add ( new CertificateIdentifier ( issuerCert ) ) ;
565+ chainPolicy . ExtraStore . Add ( issuerCert ) ;
566+ }
567+
568+ using var chain = new X509Chain { ChainPolicy = chainPolicy } ;
569+ chain . Build ( newCert ) ;
570+
571+ foreach ( X509ChainStatus chainStatus in chain . ChainStatus ?? [ ] )
572+ {
573+ if ( chainStatus . Status is X509ChainStatusFlags . NoError or
574+ X509ChainStatusFlags . UntrustedRoot )
575+ {
576+ continue ;
577+ }
578+ if ( chainStatus . Status is X509ChainStatusFlags . NotSignatureValid or
579+ X509ChainStatusFlags . PartialChain or
580+ X509ChainStatusFlags . NotValidForUsage or
581+ X509ChainStatusFlags . InvalidBasicConstraints )
582+ {
583+ throw new ServiceResultException (
584+ StatusCodes . BadSecurityChecksFailed ,
585+ Utils . Format (
586+ "Certificate chain validation failed. {0}: {1}" ,
587+ chainStatus . Status ,
588+ chainStatus . StatusInformation ) ) ;
589+ }
590+ }
591+
592+ if ( newIssuerCollection . Count + 1 != chain . ChainElements . Count )
593+ {
594+ throw new ServiceResultException (
595+ StatusCodes . BadSecurityChecksFailed ,
596+ "The supplied issuer chain is incomplete." ) ;
548597 }
549- issuerStore . TrustedCertificates = issuerCollection ;
550- certValidator . Update ( issuerStore , issuerStore , null ) ;
551- await certValidator . ValidateAsync ( newCert , ct ) . ConfigureAwait ( false ) ;
598+ }
599+ catch ( ServiceResultException )
600+ {
601+ throw ;
552602 }
553603 catch ( Exception ex )
554604 {
0 commit comments