Skip to content
Merged
Prev Previous commit
Next Next commit
feedback from review
  • Loading branch information
wfurt committed Aug 26, 2021
commit df51d00e59c24f224369477cee9b07468a42cd9d
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia
SafeSslContextHandle? newCtxHandle = null;
SslProtocols protocols = sslAuthenticationOptions.EnabledSslProtocols;
bool cacheSslContext = !DisableTlsResume && sslAuthenticationOptions.EncryptionPolicy == EncryptionPolicy.RequireEncryption &&
sslAuthenticationOptions.CertificateContext != null &&
sslAuthenticationOptions.CertificateContext.SslContexts != null &&
sslAuthenticationOptions.CipherSuitesPolicy == null &&
(!sslAuthenticationOptions.IsServer ||
(sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0));
Expand Down Expand Up @@ -258,88 +260,79 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia
protocols = SslProtocols.Tls13;
}

if (sslAuthenticationOptions.CertificateContext != null && cacheSslContext)
if (cacheSslContext)
{
sslAuthenticationOptions.CertificateContext.SslContexts.TryGetValue(sslAuthenticationOptions.EnabledSslProtocols, out sslCtxHandle);
sslAuthenticationOptions.CertificateContext!.SslContexts!.TryGetValue(sslAuthenticationOptions.EnabledSslProtocols, out sslCtxHandle);
}

if (sslCtxHandle == null)
{
// We did not get SslContext from cache
sslCtxHandle = newCtxHandle = AllocateSslContext(credential, sslAuthenticationOptions);

if (cacheSslContext && sslAuthenticationOptions.CertificateContext!.SslContexts!.TryAdd(sslAuthenticationOptions.EnabledSslProtocols, newCtxHandle))
{
newCtxHandle = null;
}
}

GCHandle alpnHandle = default;
try
{
GCHandle alpnHandle = default;
try
sslHandle = SafeSslHandle.Create(sslCtxHandle, sslAuthenticationOptions.IsServer);
Debug.Assert(sslHandle != null, "Expected non-null return value from SafeSslHandle.Create");
if (sslHandle.IsInvalid)
{
sslHandle = SafeSslHandle.Create(sslCtxHandle, sslAuthenticationOptions.IsServer);
Debug.Assert(sslHandle != null, "Expected non-null return value from SafeSslHandle.Create");
if (sslHandle.IsInvalid)
{
sslHandle.Dispose();
throw CreateSslException(SR.net_allocate_ssl_context_failed);
}

if (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)
{
if (sslAuthenticationOptions.IsServer)
{
alpnHandle = GCHandle.Alloc(sslAuthenticationOptions.ApplicationProtocols);
Interop.Ssl.SslSetData(sslHandle, GCHandle.ToIntPtr(alpnHandle));
sslHandle.AlpnHandle = alpnHandle;
}
else
{
if (Interop.Ssl.SslSetAlpnProtos(sslHandle, sslAuthenticationOptions.ApplicationProtocols) != 0)
{
throw CreateSslException(SR.net_alpn_config_failed);
}
}
}
sslHandle.Dispose();
throw CreateSslException(SR.net_allocate_ssl_context_failed);
}

if (!sslAuthenticationOptions.IsServer)
if (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)
{
if (sslAuthenticationOptions.IsServer)
{
// The IdnMapping converts unicode input into the IDNA punycode sequence.
string punyCode = string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) ? string.Empty : s_idnMapping.GetAscii(sslAuthenticationOptions.TargetHost!);

// Similar to windows behavior, set SNI on openssl by default for client context, ignore errors.
if (!Ssl.SslSetTlsExtHostName(sslHandle, punyCode))
{
Crypto.ErrClearError();
}
alpnHandle = GCHandle.Alloc(sslAuthenticationOptions.ApplicationProtocols);
Interop.Ssl.SslSetData(sslHandle, GCHandle.ToIntPtr(alpnHandle));
sslHandle.AlpnHandle = alpnHandle;
}

if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired)
else
{
unsafe
if (Interop.Ssl.SslSetAlpnProtos(sslHandle, sslAuthenticationOptions.ApplicationProtocols) != 0)
{
Ssl.SslSetVerifyPeer(sslHandle);
throw CreateSslException(SR.net_alpn_config_failed);
}
}
}
catch

if (!sslAuthenticationOptions.IsServer)
{
if (alpnHandle.IsAllocated)
// The IdnMapping converts unicode input into the IDNA punycode sequence.
string punyCode = string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) ? string.Empty : s_idnMapping.GetAscii(sslAuthenticationOptions.TargetHost!);

// Similar to windows behavior, set SNI on openssl by default for client context, ignore errors.
if (!Ssl.SslSetTlsExtHostName(sslHandle, punyCode))
{
alpnHandle.Free();
Crypto.ErrClearError();
}
}

throw;
if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired)
{
Ssl.SslSetVerifyPeer(sslHandle);
}
}
finally
catch
{
if (newCtxHandle != null)
if (alpnHandle.IsAllocated)
{
// We allocated new context and we want to cache
if (!cacheSslContext || sslAuthenticationOptions.CertificateContext?.SslContexts == null ||
!sslAuthenticationOptions.CertificateContext.SslContexts.TryAdd(sslAuthenticationOptions.EnabledSslProtocols, newCtxHandle))
{
newCtxHandle.Dispose();
}
alpnHandle.Free();
}

throw;
}
finally
{
newCtxHandle?.Dispose();
}

return sslHandle;
Expand Down