@@ -286,29 +286,36 @@ public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate(
286286 {
287287 var result = EnsureCertificateResult . Succeeded ;
288288
289- var currentUserCertificates = ListCertificates ( StoreName . My , StoreLocation . CurrentUser , isValid : true , requireExportable : true ) ;
290- var localMachineCertificates = ListCertificates ( StoreName . My , StoreLocation . LocalMachine , isValid : true , requireExportable : true ) ;
291- var certificates = currentUserCertificates . Concat ( localMachineCertificates ) ;
289+ var allCurrentUserCertificates = ListCertificates ( StoreName . My , StoreLocation . CurrentUser , isValid : true , requireExportable : true ) ;
290+ var allLocalMachineCertificates = ListCertificates ( StoreName . My , StoreLocation . LocalMachine , isValid : true , requireExportable : true ) ;
292291
293- var filteredCertificates = certificates . Where ( c => c . Subject == Subject ) ;
292+ var currentUserCertificates = allCurrentUserCertificates . Where ( c => c . Subject == Subject ) . ToList ( ) ;
293+ var localMachineCertificates = allLocalMachineCertificates . Where ( c => c . Subject == Subject ) . ToList ( ) ;
294+ var filteredCertificates = currentUserCertificates . Concat ( localMachineCertificates ) . ToList ( ) ;
295+
294296 if ( isInteractive )
295297 {
296298 // For purposes of updating the dev cert, only consider certificates with the current version or higher as valid
297299 // Only applies to interactive scenarios where we want to ensure we're generating the latest certificate
298300 // For non-interactive scenarios (e.g. first run experience), we want to accept older versions of the certificate as long as they meet the minimum version requirement
299301 // This will allow us to respond to scenarios where we need to invalidate older certificates due to security issues, etc. but not leave users
300302 // with a partially valid certificate after their first run experience.
301- filteredCertificates = filteredCertificates . Where ( c => GetCertificateVersion ( c ) >= AspNetHttpsCertificateVersion ) ;
303+ filteredCertificates = filteredCertificates . Where ( c => GetCertificateVersion ( c ) >=
304+ AspNetHttpsCertificateVersion ) . ToList ( ) ;
302305 }
303306
304307 if ( Log . IsEnabled ( ) )
305308 {
306- var excludedCertificates = certificates . Except ( filteredCertificates ) ;
309+ var excludedCertificates = allCurrentUserCertificates . Concat ( allLocalMachineCertificates ) . Except ( filteredCertificates ) ;
307310 Log . FilteredCertificates ( ToCertificateDescription ( filteredCertificates ) ) ;
308311 Log . ExcludedCertificates ( ToCertificateDescription ( excludedCertificates ) ) ;
309312 }
310313
311- certificates = filteredCertificates ;
314+ // Dispose certificates we're not going to use
315+ DisposeCertificates ( allCurrentUserCertificates . Except ( currentUserCertificates ) ) ;
316+ DisposeCertificates ( allLocalMachineCertificates . Except ( localMachineCertificates ) ) ;
317+
318+ var certificates = filteredCertificates ;
312319
313320 X509Certificate2 ? certificate = null ;
314321 var isNewCertificate = false ;
@@ -380,6 +387,7 @@ public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate(
380387 Log . CreateDevelopmentCertificateError ( e . ToString ( ) ) ;
381388 }
382389 result = EnsureCertificateResult . ErrorCreatingTheCertificate ;
390+ DisposeCertificates ( certificates ) ;
383391 return result ;
384392 }
385393 Log . CreateDevelopmentCertificateEnd ( ) ;
@@ -391,6 +399,11 @@ public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate(
391399 catch ( Exception e )
392400 {
393401 Log . SaveCertificateInStoreError ( e . ToString ( ) ) ;
402+ if ( isNewCertificate )
403+ {
404+ certificate ? . Dispose ( ) ;
405+ }
406+ DisposeCertificates ( certificates ) ;
394407 result = EnsureCertificateResult . ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore ;
395408 return result ;
396409 }
@@ -448,6 +461,11 @@ public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate(
448461 result :
449462 EnsureCertificateResult . ErrorExportingTheCertificate ;
450463
464+ if ( isNewCertificate )
465+ {
466+ certificate ? . Dispose ( ) ;
467+ }
468+ DisposeCertificates ( certificates ) ;
451469 return result ;
452470 }
453471 }
@@ -464,21 +482,41 @@ public EnsureCertificateResult EnsureAspNetCoreHttpsDevelopmentCertificate(
464482 break ;
465483 case TrustLevel . Partial :
466484 result = EnsureCertificateResult . PartiallyFailedToTrustTheCertificate ;
485+ if ( isNewCertificate )
486+ {
487+ certificate ? . Dispose ( ) ;
488+ }
489+ DisposeCertificates ( certificates ) ;
467490 return result ;
468491 case TrustLevel . None :
469492 default : // Treat unknown status (should be impossible) as failure
470493 result = EnsureCertificateResult . FailedToTrustTheCertificate ;
494+ if ( isNewCertificate )
495+ {
496+ certificate ? . Dispose ( ) ;
497+ }
498+ DisposeCertificates ( certificates ) ;
471499 return result ;
472500 }
473501 }
474502 catch ( UserCancelledTrustException )
475503 {
476504 result = EnsureCertificateResult . UserCancelledTrustStep ;
505+ if ( isNewCertificate )
506+ {
507+ certificate ? . Dispose ( ) ;
508+ }
509+ DisposeCertificates ( certificates ) ;
477510 return result ;
478511 }
479512 catch
480513 {
481514 result = EnsureCertificateResult . FailedToTrustTheCertificate ;
515+ if ( isNewCertificate )
516+ {
517+ certificate ? . Dispose ( ) ;
518+ }
519+ DisposeCertificates ( certificates ) ;
482520 return result ;
483521 }
484522
@@ -515,51 +553,58 @@ internal ImportCertificateResult ImportCertificate(string certificatePath, strin
515553 return ImportCertificateResult . ExistingCertificatesPresent ;
516554 }
517555
518- X509Certificate2 certificate ;
556+ X509Certificate2 ? certificate = null ;
519557 try
520558 {
521- Log . LoadCertificateStart ( certificatePath ) ;
522- certificate = new X509Certificate2 ( certificatePath , password , X509KeyStorageFlags . Exportable | X509KeyStorageFlags . EphemeralKeySet ) ;
523- if ( Log . IsEnabled ( ) )
559+ try
524560 {
525- Log . LoadCertificateEnd ( GetDescription ( certificate ) ) ;
561+ Log . LoadCertificateStart ( certificatePath ) ;
562+ certificate = new X509Certificate2 ( certificatePath , password , X509KeyStorageFlags . Exportable | X509KeyStorageFlags . EphemeralKeySet ) ;
563+ if ( Log . IsEnabled ( ) )
564+ {
565+ Log . LoadCertificateEnd ( GetDescription ( certificate ) ) ;
566+ }
526567 }
527- }
528- catch ( Exception e )
529- {
530- if ( Log . IsEnabled ( ) )
568+ catch ( Exception e )
569+ {
570+ if ( Log . IsEnabled ( ) )
571+ {
572+ Log . LoadCertificateError ( e . ToString ( ) ) ;
573+ }
574+ return ImportCertificateResult . InvalidCertificate ;
575+ }
576+
577+ // Note that we're checking Subject, rather than LocalhostHttpsDistinguishedName,
578+ // because the tests use a different subject.
579+ if ( ! string . Equals ( certificate . Subject , Subject , StringComparison . Ordinal ) || // Kestrel requires this
580+ ! IsHttpsDevelopmentCertificate ( certificate ) )
531581 {
532- Log . LoadCertificateError ( e . ToString ( ) ) ;
582+ if ( Log . IsEnabled ( ) )
583+ {
584+ Log . NoHttpsDevelopmentCertificate ( GetDescription ( certificate ) ) ;
585+ }
586+ return ImportCertificateResult . NoDevelopmentHttpsCertificate ;
533587 }
534- return ImportCertificateResult . InvalidCertificate ;
535- }
536588
537- // Note that we're checking Subject, rather than LocalhostHttpsDistinguishedName,
538- // because the tests use a different subject.
539- if ( ! string . Equals ( certificate . Subject , Subject , StringComparison . Ordinal ) || // Kestrel requires this
540- ! IsHttpsDevelopmentCertificate ( certificate ) )
541- {
542- if ( Log . IsEnabled ( ) )
589+ try
543590 {
544- Log . NoHttpsDevelopmentCertificate ( GetDescription ( certificate ) ) ;
591+ certificate = SaveCertificate ( certificate ) ;
592+ }
593+ catch ( Exception e )
594+ {
595+ if ( Log . IsEnabled ( ) )
596+ {
597+ Log . SaveCertificateInStoreError ( e . ToString ( ) ) ;
598+ }
599+ return ImportCertificateResult . ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore ;
545600 }
546- return ImportCertificateResult . NoDevelopmentHttpsCertificate ;
547- }
548601
549- try
550- {
551- SaveCertificate ( certificate ) ;
602+ return ImportCertificateResult . Succeeded ;
552603 }
553- catch ( Exception e )
604+ finally
554605 {
555- if ( Log . IsEnabled ( ) )
556- {
557- Log . SaveCertificateInStoreError ( e . ToString ( ) ) ;
558- }
559- return ImportCertificateResult . ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore ;
606+ certificate ? . Dispose ( ) ;
560607 }
561-
562- return ImportCertificateResult . Succeeded ;
563608 }
564609
565610 public void CleanupHttpsCertificates ( )
0 commit comments