Skip to content

Commit 5399ee5

Browse files
authored
fix SNI handling in quic (#55468)
* fix SNI handling in quic' * cut ServerOptionsSelectionCallback * feedback from review * feedback from review
1 parent d148c34 commit 5399ee5

File tree

6 files changed

+325
-94
lines changed

6 files changed

+325
-94
lines changed

src/libraries/System.Net.Quic/src/Resources/Strings.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,14 @@
150150
<data name="net_quic_writing_notallowed" xml:space="preserve">
151151
<value>Writing is not allowed on stream.</value>
152152
</data>
153+
<data name="net_quic_ssl_option" xml:space="preserve">
154+
<value>'{0}' is not supported by System.Net.Quic.</value>
155+
</data>
156+
<data name="net_quic_cert_custom_validation" xml:space="preserve">
157+
<value>The remote certificate was rejected by the provided RemoteCertificateValidationCallback.</value>
158+
</data>
159+
<data name="net_quic_cert_chain_validation" xml:space="preserve">
160+
<value>The remote certificate is invalid because of errors in the certificate chain: {0}</value>
161+
</data>
153162
</root>
154163

src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Interop/SafeMsQuicConfigurationHandle.cs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace System.Net.Quic.Implementations.MsQuic.Internal
1717
internal sealed class SafeMsQuicConfigurationHandle : SafeHandle
1818
{
1919
private static readonly FieldInfo _contextCertificate = typeof(SslStreamCertificateContext).GetField("Certificate", BindingFlags.NonPublic | BindingFlags.Instance)!;
20-
private static readonly FieldInfo _contextChain= typeof(SslStreamCertificateContext).GetField("IntermediateCertificates", BindingFlags.NonPublic | BindingFlags.Instance)!;
20+
private static readonly FieldInfo _contextChain = typeof(SslStreamCertificateContext).GetField("IntermediateCertificates", BindingFlags.NonPublic | BindingFlags.Instance)!;
2121

2222
public override bool IsInvalid => handle == IntPtr.Zero;
2323

@@ -33,7 +33,7 @@ protected override bool ReleaseHandle()
3333
}
3434

3535
// TODO: consider moving the static code from here to keep all the handle classes small and simple.
36-
public static unsafe SafeMsQuicConfigurationHandle Create(QuicClientConnectionOptions options)
36+
public static SafeMsQuicConfigurationHandle Create(QuicClientConnectionOptions options)
3737
{
3838
X509Certificate? certificate = null;
3939
if (options.ClientAuthenticationOptions?.ClientCertificates != null)
@@ -56,15 +56,35 @@ public static unsafe SafeMsQuicConfigurationHandle Create(QuicClientConnectionOp
5656
return Create(options, QUIC_CREDENTIAL_FLAGS.CLIENT, certificate: certificate, certificateContext: null, options.ClientAuthenticationOptions?.ApplicationProtocols);
5757
}
5858

59-
public static unsafe SafeMsQuicConfigurationHandle Create(QuicListenerOptions options)
59+
public static SafeMsQuicConfigurationHandle Create(QuicOptions options, SslServerAuthenticationOptions? serverAuthenticationOptions, string? targetHost = null)
6060
{
6161
QUIC_CREDENTIAL_FLAGS flags = QUIC_CREDENTIAL_FLAGS.NONE;
62-
if (options.ServerAuthenticationOptions != null && options.ServerAuthenticationOptions.ClientCertificateRequired)
62+
X509Certificate? certificate = serverAuthenticationOptions?.ServerCertificate;
63+
64+
if (serverAuthenticationOptions != null)
6365
{
64-
flags |= QUIC_CREDENTIAL_FLAGS.REQUIRE_CLIENT_AUTHENTICATION | QUIC_CREDENTIAL_FLAGS.INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.NO_CERTIFICATE_VALIDATION;
66+
if (serverAuthenticationOptions.CipherSuitesPolicy != null)
67+
{
68+
throw new PlatformNotSupportedException(SR.Format(SR.net_quic_ssl_option, nameof(serverAuthenticationOptions.CipherSuitesPolicy)));
69+
}
70+
71+
if (serverAuthenticationOptions.EncryptionPolicy == EncryptionPolicy.NoEncryption)
72+
{
73+
throw new PlatformNotSupportedException(SR.Format(SR.net_quic_ssl_option, nameof(serverAuthenticationOptions.EncryptionPolicy)));
74+
}
75+
76+
if (serverAuthenticationOptions.ClientCertificateRequired)
77+
{
78+
flags |= QUIC_CREDENTIAL_FLAGS.REQUIRE_CLIENT_AUTHENTICATION | QUIC_CREDENTIAL_FLAGS.INDICATE_CERTIFICATE_RECEIVED | QUIC_CREDENTIAL_FLAGS.NO_CERTIFICATE_VALIDATION;
79+
}
80+
81+
if (certificate == null && serverAuthenticationOptions?.ServerCertificateSelectionCallback != null && targetHost != null)
82+
{
83+
certificate = serverAuthenticationOptions.ServerCertificateSelectionCallback(options, targetHost);
84+
}
6585
}
6686

67-
return Create(options, flags, options.ServerAuthenticationOptions?.ServerCertificate, options.ServerAuthenticationOptions?.ServerCertificateContext, options.ServerAuthenticationOptions?.ApplicationProtocols);
87+
return Create(options, flags, certificate, serverAuthenticationOptions?.ServerCertificateContext, serverAuthenticationOptions?.ApplicationProtocols);
6888
}
6989

7090
// TODO: this is called from MsQuicListener and when it fails it wreaks havoc in MsQuicListener finalizer.

0 commit comments

Comments
 (0)