Skip to content

Commit caa6b2a

Browse files
authored
Dispose X509Certificate2 when the connector is cleaned up (npgsql#4975)
Fixes npgsql#4969
1 parent d389387 commit caa6b2a

File tree

1 file changed

+17
-9
lines changed

1 file changed

+17
-9
lines changed

src/Npgsql/Internal/NpgsqlConnector.cs

+17-9
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,8 @@ internal bool PostgresCancellationPerformed
283283
internal bool AttemptPostgresCancellation { get; private set; }
284284
static readonly TimeSpan _cancelImmediatelyTimeout = TimeSpan.FromMilliseconds(-1);
285285

286+
X509Certificate2? _certificate;
287+
286288
internal NpgsqlLoggingConfiguration LoggingConfiguration { get; }
287289

288290
internal ILogger ConnectionLogger { get; }
@@ -756,7 +758,6 @@ async ValueTask<string> GetUsernameAsyncInternal()
756758

757759
async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, CancellationToken cancellationToken, bool isFirstAttempt = true)
758760
{
759-
var cert = default(X509Certificate2?);
760761
try
761762
{
762763
if (async)
@@ -815,15 +816,15 @@ async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, Cancellat
815816
#if NET5_0_OR_GREATER
816817
// It's PEM time
817818
var keyPath = Settings.SslKey ?? PostgresEnvironment.SslKey ?? PostgresEnvironment.SslKeyDefault;
818-
cert = string.IsNullOrEmpty(password)
819+
_certificate = string.IsNullOrEmpty(password)
819820
? X509Certificate2.CreateFromPemFile(certPath, keyPath)
820821
: X509Certificate2.CreateFromEncryptedPemFile(certPath, password, keyPath);
821822
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
822823
{
823824
// Windows crypto API has a bug with pem certs
824825
// See #3650
825-
using var previousCert = cert;
826-
cert = new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
826+
using var previousCert = _certificate;
827+
_certificate = new X509Certificate2(_certificate.Export(X509ContentType.Pkcs12));
827828
}
828829
#else
829830
// Technically PEM certificates are supported as of .NET 5 but we don't build for the net5.0
@@ -833,8 +834,8 @@ async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, Cancellat
833834
#endif
834835
}
835836

836-
cert ??= new X509Certificate2(certPath, password);
837-
clientCertificates.Add(cert);
837+
_certificate ??= new X509Certificate2(certPath, password);
838+
clientCertificates.Add(_certificate);
838839
}
839840

840841
ClientCertificatesCallback?.Invoke(clientCertificates);
@@ -851,10 +852,10 @@ async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, Cancellat
851852
throw new ArgumentException(string.Format(NpgsqlStrings.CannotUseSslVerifyWithUserCallback, sslMode));
852853

853854
if (Settings.RootCertificate is not null)
854-
throw new ArgumentException(string.Format(NpgsqlStrings.CannotUseSslRootCertificateWithUserCallback));
855+
throw new ArgumentException(NpgsqlStrings.CannotUseSslRootCertificateWithUserCallback);
855856

856857
if (DataSource.RootCertificateCallback is not null)
857-
throw new ArgumentException(string.Format(NpgsqlStrings.CannotUseValidationRootCertificateCallbackWithUserCallback));
858+
throw new ArgumentException(NpgsqlStrings.CannotUseValidationRootCertificateCallbackWithUserCallback);
858859

859860
certificateValidationCallback = UserCertificateValidationCallback;
860861
}
@@ -921,7 +922,8 @@ async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, Cancellat
921922
}
922923
catch
923924
{
924-
cert?.Dispose();
925+
_certificate?.Dispose();
926+
_certificate = null;
925927

926928
_stream?.Dispose();
927929
_stream = null!;
@@ -2179,6 +2181,12 @@ void Cleanup()
21792181
Connection = null;
21802182
PostgresParameters.Clear();
21812183
_currentCommand = null;
2184+
2185+
if (_certificate is not null)
2186+
{
2187+
_certificate.Dispose();
2188+
_certificate = null;
2189+
}
21822190
}
21832191

21842192
void GenerateResetMessage()

0 commit comments

Comments
 (0)