Skip to content

Commit

Permalink
Initial support for SslStreamCertificateContext (#38364)
Browse files Browse the repository at this point in the history
* initial support for SslStreamCertificateContext

* update openssl pal

* feedback from review

* fix unit tests

* fix platforms

* update ref
  • Loading branch information
wfurt committed Jul 2, 2020
1 parent f170db7 commit 719c58c
Show file tree
Hide file tree
Showing 17 changed files with 277 additions and 105 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -199,42 +199,11 @@ internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX50
}
}

if (hasCertificateAndKey)
if (sslAuthenticationOptions.CertificateContext != null && sslAuthenticationOptions.CertificateContext.IntermediateCertificates.Length > 0)
{
bool hasCertReference = false;
try
if (!Ssl.AddExtraChainCertificates(context, sslAuthenticationOptions.CertificateContext!.IntermediateCertificates))
{
certHandle!.DangerousAddRef(ref hasCertReference);
using (X509Certificate2 cert = new X509Certificate2(certHandle.DangerousGetHandle()))
{
X509Chain? chain = null;
try
{
chain = TLSCertificateExtensions.BuildNewChain(cert, includeClientApplicationPolicy: false);
if (chain != null && !Ssl.AddExtraChainCertificates(context, chain))
{
throw CreateSslException(SR.net_ssl_use_cert_failed);
}
}
finally
{
if (chain != null)
{
int elementsCount = chain.ChainElements.Count;
for (int i = 0; i < elementsCount; i++)
{
chain.ChainElements[i].Certificate!.Dispose();
}

chain.Dispose();
}
}
}
}
finally
{
if (hasCertReference)
certHandle!.DangerousRelease();
throw CreateSslException(SR.net_ssl_use_cert_failed);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,25 @@ internal static bool AddExtraChainCertificates(SafeSslHandle sslContext, X509Cha
return true;
}

internal static bool AddExtraChainCertificates(SafeSslHandle sslContext, X509Certificate2[] chain)
{
// send pre-computed list of intermediates.
for (int i = 0; i < chain.Length; i++)
{
SafeX509Handle dupCertHandle = Crypto.X509UpRef(chain[i].Handle);
Crypto.CheckValidOpenSslHandle(dupCertHandle);
if (!SslAddExtraChainCert(sslContext, dupCertHandle))
{
Crypto.ErrClearError();
dupCertHandle.Dispose(); // we still own the safe handle; clean it up
return false;
}
dupCertHandle.SetHandleAsInvalid(); // ownership has been transferred to sslHandle; do not free via this safe handle
}

return true;
}

internal static class SslMethods
{
internal static readonly IntPtr SSLv23_method = SslV2_3Method();
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/System.Net.Security/ref/System.Net.Security.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ public enum ProtectionLevel
public static bool operator !=(System.Net.Security.SslApplicationProtocol left, System.Net.Security.SslApplicationProtocol right) { throw null; }
public override string ToString() { throw null; }
}
public sealed partial class SslStreamCertificateContext
{
internal SslStreamCertificateContext() { throw null; }
public static SslStreamCertificateContext Create(System.Security.Cryptography.X509Certificates.X509Certificate2 target, System.Security.Cryptography.X509Certificates.X509Certificate2Collection? additionalCertificates, bool offline = false) { throw null; }
}
public partial class SslClientAuthenticationOptions
{
public SslClientAuthenticationOptions() { }
Expand All @@ -150,6 +155,7 @@ public partial class SslServerAuthenticationOptions
public System.Net.Security.EncryptionPolicy EncryptionPolicy { get { throw null; } set { } }
public System.Net.Security.RemoteCertificateValidationCallback? RemoteCertificateValidationCallback { get { throw null; } set { } }
public System.Security.Cryptography.X509Certificates.X509Certificate? ServerCertificate { get { throw null; } set { } }
public System.Net.Security.SslStreamCertificateContext? ServerCertificateContext { get { throw null; } set { } }
public System.Net.Security.ServerCertificateSelectionCallback? ServerCertificateSelectionCallback { get { throw null; } set { } }
}
public partial class SslStream : System.Net.Security.AuthenticatedStream
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<Compile Include="System\Net\Security\SslSessionsCache.cs" />
<Compile Include="System\Net\Security\SslStream.cs" />
<Compile Include="System\Net\Security\SslStream.Implementation.cs" />
<Compile Include="System\Net\Security\SslStreamCertificateContext.cs" />
<Compile Include="System\Net\Security\SslConnectionInfo.cs" />
<Compile Include="System\Net\Security\StreamSizes.cs" />
<Compile Include="System\Net\Security\TlsAlertType.cs" />
Expand Down Expand Up @@ -125,6 +126,7 @@
<Compile Include="System\Net\Security\CipherSuitesPolicyPal.Windows.cs" />
<Compile Include="System\Net\Security\NegotiateStreamPal.Windows.cs" />
<Compile Include="System\Net\Security\NetEventSource.Security.Windows.cs" />
<Compile Include="System\Net\Security\SslStreamCertificateContext.Windows.cs" />
<Compile Include="System\Net\Security\SslStreamPal.Windows.cs" />
<Compile Include="System\Net\Security\SslConnectionInfo.Windows.cs" />
<Compile Include="System\Net\Security\StreamSizes.Windows.cs" />
Expand Down Expand Up @@ -247,6 +249,7 @@
<Compile Include="System\Net\Security\CipherSuitesPolicyPal.Linux.cs" />
<Compile Include="System\Net\Security\SslStreamPal.Unix.cs" />
<Compile Include="System\Net\Security\SslConnectionInfo.Linux.cs" />
<Compile Include="System\Net\Security\SslStreamCertificateContext.Linux.cs" />
<Compile Include="System\Net\Security\StreamSizes.Unix.cs" />
<Compile Include="$(CommonPath)System\Net\Security\CertificateValidation.Unix.cs"
Link="Common\System\Net\Security\CertificateValidation.Unix.cs" />
Expand Down Expand Up @@ -328,6 +331,7 @@
<Compile Include="System\Net\Security\Pal.OSX\SafeDeleteSslContext.cs" />
<Compile Include="System\Net\Security\Pal.OSX\SafeFreeSslCredentials.cs" />
<Compile Include="System\Net\Security\SslConnectionInfo.OSX.cs" />
<Compile Include="System\Net\Security\SslStreamCertificateContext.OSX.cs" />
<Compile Include="System\Net\Security\SslStreamPal.OSX.cs" />
<Compile Include="System\Net\Security\StreamSizes.OSX.cs" />
<Compile Include="System\Net\Security\CipherSuitesPolicyPal.OSX.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,47 +105,47 @@ public void SecureChannelCtor(SecureChannel secureChannel, SslStream sslStream,
WriteEvent(SecureChannelCtorId, sslStream, hostname, secureChannelHash, clientCertificatesCount, (int)encryptionPolicy);

[NonEvent]
public void LocatingPrivateKey(X509Certificate x509Certificate, SecureChannel secureChannel)
public void LocatingPrivateKey(X509Certificate x509Certificate, object instance)
{
if (IsEnabled())
{
LocatingPrivateKey(x509Certificate.ToString(true), GetHashCode(secureChannel));
LocatingPrivateKey(x509Certificate.ToString(true), GetHashCode(instance));
}
}
[Event(LocatingPrivateKeyId, Keywords = Keywords.Default, Level = EventLevel.Informational)]
private void LocatingPrivateKey(string x509Certificate, int secureChannelHash) =>
WriteEvent(LocatingPrivateKeyId, x509Certificate, secureChannelHash);

[NonEvent]
public void CertIsType2(SecureChannel secureChannel)
public void CertIsType2(object instance)
{
if (IsEnabled())
{
CertIsType2(GetHashCode(secureChannel));
CertIsType2(GetHashCode(instance));
}
}
[Event(CertIsType2Id, Keywords = Keywords.Default, Level = EventLevel.Informational)]
private void CertIsType2(int secureChannelHash) =>
WriteEvent(CertIsType2Id, secureChannelHash);

[NonEvent]
public void FoundCertInStore(bool serverMode, SecureChannel secureChannel)
public void FoundCertInStore(bool serverMode, object instance)
{
if (IsEnabled())
{
FoundCertInStore(serverMode ? "LocalMachine" : "CurrentUser", GetHashCode(secureChannel));
FoundCertInStore(serverMode ? "LocalMachine" : "CurrentUser", GetHashCode(instance));
}
}
[Event(FoundCertInStoreId, Keywords = Keywords.Default, Level = EventLevel.Informational)]
private void FoundCertInStore(string store, int secureChannelHash) =>
WriteEvent(FoundCertInStoreId, store, secureChannelHash);

[NonEvent]
public void NotFoundCertInStore(SecureChannel secureChannel)
public void NotFoundCertInStore(object instance)
{
if (IsEnabled())
{
NotFoundCertInStore(GetHashCode(secureChannel));
NotFoundCertInStore(GetHashCode(instance));
}
}
[Event(NotFoundCertInStoreId, Keywords = Keywords.Default, Level = EventLevel.Informational)]
Expand Down
Loading

0 comments on commit 719c58c

Please sign in to comment.