Skip to content

Commit ee03bbd

Browse files
Dispose the certificate chain elements with the chain (#62531)
* Dispose the certificate chain elements with the chain * Fix the missing brace * Remove snarky comment. * Add another choice using based on review feedback * Styling fixes --------- Co-authored-by: Mackinnon Buck <[email protected]>
1 parent 223fe49 commit ee03bbd

File tree

2 files changed

+46
-18
lines changed

2 files changed

+46
-18
lines changed

src/Security/Authentication/Certificate/src/CertificateAuthenticationHandler.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,21 +135,35 @@ private async Task<AuthenticateResult> ValidateCertificateAsync(X509Certificate2
135135
}
136136

137137
var chainPolicy = BuildChainPolicy(clientCertificate, isCertificateSelfSigned);
138-
using var chain = new X509Chain
138+
var chain = new X509Chain
139139
{
140140
ChainPolicy = chainPolicy
141141
};
142142

143-
var certificateIsValid = chain.Build(clientCertificate);
144-
if (!certificateIsValid)
143+
try
144+
{
145+
var certificateIsValid = chain.Build(clientCertificate);
146+
if (!certificateIsValid)
147+
{
148+
var chainErrors = new List<string>(chain.ChainStatus.Length);
149+
foreach (var validationFailure in chain.ChainStatus)
150+
{
151+
chainErrors.Add($"{validationFailure.Status} {validationFailure.StatusInformation}");
152+
}
153+
Logger.CertificateFailedValidation(clientCertificate.Subject, chainErrors);
154+
return AuthenticateResults.InvalidClientCertificate;
155+
}
156+
}
157+
finally
145158
{
146-
var chainErrors = new List<string>(chain.ChainStatus.Length);
147-
foreach (var validationFailure in chain.ChainStatus)
159+
// Disposing the chain does not dispose the elements we potentially built.
160+
// Do the full walk manually to dispose.
161+
for (var i = 0; i < chain.ChainElements.Count; i++)
148162
{
149-
chainErrors.Add($"{validationFailure.Status} {validationFailure.StatusInformation}");
163+
chain.ChainElements[i].Certificate.Dispose();
150164
}
151-
Logger.CertificateFailedValidation(clientCertificate.Subject, chainErrors);
152-
return AuthenticateResults.InvalidClientCertificate;
165+
166+
chain.Dispose();
153167
}
154168

155169
var certificateValidatedContext = new CertificateValidatedContext(Context, Scheme, Options)

src/Shared/CertificateGeneration/UnixCertificateManager.cs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,32 @@ public override TrustLevel GetTrustLevel(X509Certificate2 certificate)
6262
// Building the chain will check whether dotnet trusts the cert. We could, instead,
6363
// enumerate the Root store and/or look for the file in the OpenSSL directory, but
6464
// this tests the real-world behavior.
65-
using var chain = new X509Chain();
66-
// This is just a heuristic for whether or not we should prompt the user to re-run with `--trust`
67-
// so we don't need to check revocation (which doesn't really make sense for dev certs anyway)
68-
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
69-
if (chain.Build(certificate))
65+
var chain = new X509Chain();
66+
try
7067
{
71-
sawTrustSuccess = true;
68+
// This is just a heuristic for whether or not we should prompt the user to re-run with `--trust`
69+
// so we don't need to check revocation (which doesn't really make sense for dev certs anyway)
70+
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
71+
if (chain.Build(certificate))
72+
{
73+
sawTrustSuccess = true;
74+
}
75+
else
76+
{
77+
sawTrustFailure = true;
78+
Log.UnixNotTrustedByDotnet();
79+
}
7280
}
73-
else
81+
finally
7482
{
75-
sawTrustFailure = true;
76-
Log.UnixNotTrustedByDotnet();
83+
// Disposing the chain does not dispose the elements we potentially built.
84+
// Do the full walk manually to dispose.
85+
for (var i = 0; i < chain.ChainElements.Count; i++)
86+
{
87+
chain.ChainElements[i].Certificate.Dispose();
88+
}
89+
90+
chain.Dispose();
7791
}
7892

7993
// Will become the name of the file on disk and the nickname in the NSS DBs
@@ -94,7 +108,7 @@ public override TrustLevel GetTrustLevel(X509Certificate2 certificate)
94108
var certPath = Path.Combine(sslCertDir, certificateNickname + ".pem");
95109
if (File.Exists(certPath))
96110
{
97-
var candidate = X509CertificateLoader.LoadCertificateFromFile(certPath);
111+
using var candidate = X509CertificateLoader.LoadCertificateFromFile(certPath);
98112
if (AreCertificatesEqual(certificate, candidate))
99113
{
100114
foundCert = true;

0 commit comments

Comments
 (0)