Skip to content

Commit

Permalink
Disallow SslMode.VerifyCA/Full with user callback (#4293)
Browse files Browse the repository at this point in the history
Closes #4274

(cherry picked from commit 001c5ef)
  • Loading branch information
roji committed Jan 23, 2022
1 parent f867ae6 commit 22f43e7
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 7 deletions.
7 changes: 7 additions & 0 deletions src/Npgsql/Internal/NpgsqlConnector.cs
Expand Up @@ -23,6 +23,7 @@
using Npgsql.Util;
using static Npgsql.Util.Statics;
using System.Transactions;
using Npgsql.Properties;

namespace Npgsql.Internal
{
Expand Down Expand Up @@ -809,6 +810,12 @@ async Task RawOpen(SslMode sslMode, NpgsqlTimeout timeout, bool async, Cancellat
}
else if (UserCertificateValidationCallback is not null)
{
if (sslMode is SslMode.VerifyCA or SslMode.VerifyFull)
{
throw new NotSupportedException(
string.Format(NpgsqlStrings.CannotUseSslVerifyWithUserCallback, sslMode));
}

certificateValidationCallback = UserCertificateValidationCallback;
}
else if (sslMode == SslMode.VerifyCA)
Expand Down
15 changes: 15 additions & 0 deletions src/Npgsql/Npgsql.csproj
Expand Up @@ -46,4 +46,19 @@
<None Include="README.md" Pack="true" PackagePath="\"/>
</ItemGroup>

<ItemGroup>
<EmbeddedResource Update="Properties\NpgsqlStrings.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>NpgsqlStrings.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>

<ItemGroup>
<Compile Update="Properties\NpgsqlStrings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>NpgsqlStrings.resx</DependentUpon>
</Compile>
</ItemGroup>

</Project>
54 changes: 54 additions & 0 deletions src/Npgsql/Properties/NpgsqlStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions src/Npgsql/Properties/NpgsqlStrings.resx
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>

<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">

</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="CannotUseSslVerifyWithUserCallback" xml:space="preserve">
<value>SslMode.{0} cannot be used in conjunction with UserCertificateValidationCallback; when registering a validation callback, perform whatever validation you require in that callback.</value>
</data>
</root>
45 changes: 38 additions & 7 deletions test/Npgsql.Tests/SecurityTests.cs
Expand Up @@ -2,6 +2,7 @@
using System.Security.Authentication;
using System.Threading;
using System.Threading.Tasks;
using Npgsql.Properties;
using NUnit.Framework;
using static Npgsql.Tests.TestUtil;

Expand All @@ -25,7 +26,7 @@ public void Basic_ssl()
[Test, Description("Default user must run with md5 password encryption")]
public void Default_user_uses_md5_password()
{
if (!TestUtil.IsOnBuildServer)
if (!IsOnBuildServer)
Assert.Ignore("Only executed in CI");

var csb = new NpgsqlConnectionStringBuilder(ConnectionString)
Expand Down Expand Up @@ -100,7 +101,7 @@ public void IntegratedSecurity_with_Username()
}
catch (Exception e)
{
if (TestUtil.IsOnBuildServer)
if (IsOnBuildServer)
throw;
Console.WriteLine(e);
Assert.Ignore("Integrated security (GSS/SSPI) doesn't seem to be set up");
Expand All @@ -123,7 +124,7 @@ public void IntegratedSecurity_without_Username()
}
catch (Exception e)
{
if (TestUtil.IsOnBuildServer)
if (IsOnBuildServer)
throw;
Console.WriteLine(e);
Assert.Ignore("Integrated security (GSS/SSPI) doesn't seem to be set up");
Expand All @@ -147,7 +148,7 @@ public void Connection_database_is_populated_on_Open()
}
catch (Exception e)
{
if (TestUtil.IsOnBuildServer)
if (IsOnBuildServer)
throw;
Console.WriteLine(e);
Assert.Ignore("Integrated security (GSS/SSPI) doesn't seem to be set up");
Expand Down Expand Up @@ -195,7 +196,7 @@ public void ScramPlus()
Assert.That(conn.IsScramPlus, Is.True);
}
}
catch (Exception e) when (!TestUtil.IsOnBuildServer)
catch (Exception e) when (!IsOnBuildServer)
{
Console.WriteLine(e);
Assert.Ignore("scram-sha-256-plus doesn't seem to be set up");
Expand Down Expand Up @@ -224,7 +225,7 @@ public async Task Connect_with_only_ssl_allowed_user([Values] bool multiplexing,
await using var conn = await OpenConnectionAsync(csb);
Assert.IsTrue(conn.IsSecure);
}
catch (Exception e) when (!TestUtil.IsOnBuildServer)
catch (Exception e) when (!IsOnBuildServer)
{
Console.WriteLine(e);
Assert.Ignore("Only ssl user doesn't seem to be set up");
Expand Down Expand Up @@ -267,13 +268,43 @@ public async Task Connect_with_only_non_ssl_allowed_user([Values] bool multiplex
await using var conn = await OpenConnectionAsync(csb);
Assert.IsFalse(conn.IsSecure);
}
catch (Exception e) when (!TestUtil.IsOnBuildServer)
catch (Exception e) when (!IsOnBuildServer)
{
Console.WriteLine(e);
Assert.Ignore("Only nonssl user doesn't seem to be set up");
}
}

[Test]
public void Connect_with_VerifyFull_and_callback_throws()
{
var csb = new NpgsqlConnectionStringBuilder(ConnectionString)
{
SslMode = SslMode.VerifyFull
};

var connection = CreateConnection(csb.ToString());
connection.UserCertificateValidationCallback = (_, _, _, _) => true;

var ex = Assert.ThrowsAsync<NotSupportedException>(async () => await connection.OpenAsync())!;
Assert.That(ex.Message, Is.EqualTo(string.Format(NpgsqlStrings.CannotUseSslVerifyWithUserCallback, nameof(SslMode.VerifyFull))));
}

[Test]
public void Connect_with_VerifyCA_and_callback_throws()
{
var csb = new NpgsqlConnectionStringBuilder(ConnectionString)
{
SslMode = SslMode.VerifyCA
};

var connection = CreateConnection(csb.ToString());
connection.UserCertificateValidationCallback = (_, _, _, _) => true;

var ex = Assert.ThrowsAsync<NotSupportedException>(async () => await connection.OpenAsync())!;
Assert.That(ex.Message, Is.EqualTo(string.Format(NpgsqlStrings.CannotUseSslVerifyWithUserCallback, nameof(SslMode.VerifyCA))));
}

#region Setup / Teardown / Utils

[OneTimeSetUp]
Expand Down

0 comments on commit 22f43e7

Please sign in to comment.