internal void UpdateOptions(SslServerAuthenticationOptions sslServerAuthenticationOptions) { AllowRenegotiation = sslServerAuthenticationOptions.AllowRenegotiation; ApplicationProtocols = sslServerAuthenticationOptions.ApplicationProtocols; EnabledSslProtocols = FilterOutIncompatibleSslProtocols(sslServerAuthenticationOptions.EnabledSslProtocols); EncryptionPolicy = sslServerAuthenticationOptions.EncryptionPolicy; RemoteCertRequired = sslServerAuthenticationOptions.ClientCertificateRequired; CipherSuitesPolicy = sslServerAuthenticationOptions.CipherSuitesPolicy; CertificateRevocationCheckMode = sslServerAuthenticationOptions.CertificateRevocationCheckMode; if (sslServerAuthenticationOptions.ServerCertificateContext != null) { CertificateContext = sslServerAuthenticationOptions.ServerCertificateContext; } else if (sslServerAuthenticationOptions.ServerCertificate is X509Certificate2 certificateWithKey && certificateWithKey.HasPrivateKey) { // given cert is X509Certificate2 with key. We can use it directly. CertificateContext = SslStreamCertificateContext.Create(certificateWithKey); } if (sslServerAuthenticationOptions.RemoteCertificateValidationCallback != null) { CertValidationDelegate = sslServerAuthenticationOptions.RemoteCertificateValidationCallback; } }
internal SslAuthenticationOptions(SslServerAuthenticationOptions sslServerAuthenticationOptions) { // Common options. AllowRenegotiation = sslServerAuthenticationOptions.AllowRenegotiation; ApplicationProtocols = sslServerAuthenticationOptions.ApplicationProtocols; CheckCertName = false; EnabledSslProtocols = FilterOutIncompatibleSslProtocols(sslServerAuthenticationOptions.EnabledSslProtocols); EncryptionPolicy = sslServerAuthenticationOptions.EncryptionPolicy; IsServer = true; RemoteCertRequired = sslServerAuthenticationOptions.ClientCertificateRequired; if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(this, $"Server RemoteCertRequired: {RemoteCertRequired}."); } TargetHost = string.Empty; // Server specific options. CipherSuitesPolicy = sslServerAuthenticationOptions.CipherSuitesPolicy; CertificateRevocationCheckMode = sslServerAuthenticationOptions.CertificateRevocationCheckMode; if (sslServerAuthenticationOptions.ServerCertificateContext != null) { CertificateContext = sslServerAuthenticationOptions.ServerCertificateContext; } else if (sslServerAuthenticationOptions.ServerCertificate != null) { X509Certificate2?certificateWithKey = sslServerAuthenticationOptions.ServerCertificate as X509Certificate2; if (certificateWithKey != null && certificateWithKey.HasPrivateKey) { // given cert is X509Certificate2 with key. We can use it directly. CertificateContext = SslStreamCertificateContext.Create(certificateWithKey, null); } else { // This is legacy fix-up. If the Certificate did not have key, we will search stores and we // will try to find one with matching hash. certificateWithKey = SecureChannel.FindCertificateWithPrivateKey(this, true, sslServerAuthenticationOptions.ServerCertificate); if (certificateWithKey == null) { throw new AuthenticationException(SR.net_ssl_io_no_server_cert); } CertificateContext = SslStreamCertificateContext.Create(certificateWithKey); } } if (sslServerAuthenticationOptions.RemoteCertificateValidationCallback != null) { CertValidationDelegate = sslServerAuthenticationOptions.RemoteCertificateValidationCallback; } }
private static SecurityStatusPal HandshakeInternal( SafeFreeCredentials credential, ref SafeDeleteSslContext?context, ReadOnlySpan <byte> inputBuffer, ref byte[]?outputBuffer, SslAuthenticationOptions sslAuthenticationOptions, SelectClientCertificate?clientCertificateSelectionCallback) { Debug.Assert(!credential.IsInvalid); try { SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context); if ((null == context) || context.IsInvalid) { sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials) !, sslAuthenticationOptions); context = sslContext; } if (inputBuffer.Length > 0) { sslContext !.Write(inputBuffer); } SafeSslHandle sslHandle = sslContext !.SslContext; SecurityStatusPal status = PerformHandshake(sslHandle); if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded && clientCertificateSelectionCallback != null) { X509Certificate2?clientCertificate = clientCertificateSelectionCallback(out bool _); if (clientCertificate != null) { sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); SafeDeleteSslContext.SetCertificate(sslContext.SslContext, sslAuthenticationOptions.CertificateContext); } // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK. status = PerformHandshake(sslHandle); } outputBuffer = sslContext.ReadPendingWrites(); return(status); } catch (Exception exc) { return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc)); } }
internal void UpdateOptions(SslServerAuthenticationOptions sslServerAuthenticationOptions) { if (sslServerAuthenticationOptions.ServerCertificate == null && sslServerAuthenticationOptions.ServerCertificateContext == null && sslServerAuthenticationOptions.ServerCertificateSelectionCallback == null && CertSelectionDelegate == null) { throw new NotSupportedException(SR.net_ssl_io_no_server_cert); } if ((sslServerAuthenticationOptions.ServerCertificate != null || sslServerAuthenticationOptions.ServerCertificateContext != null || CertSelectionDelegate != null) && sslServerAuthenticationOptions.ServerCertificateSelectionCallback != null) { throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(ServerCertificateSelectionCallback))); } if (CertValidationDelegate == null) { CertValidationDelegate = sslServerAuthenticationOptions.RemoteCertificateValidationCallback; } else if (sslServerAuthenticationOptions.RemoteCertificateValidationCallback != null && CertValidationDelegate != sslServerAuthenticationOptions.RemoteCertificateValidationCallback) { // Callback was set in constructor to differet value. throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(RemoteCertificateValidationCallback))); } IsServer = true; AllowRenegotiation = sslServerAuthenticationOptions.AllowRenegotiation; ApplicationProtocols = sslServerAuthenticationOptions.ApplicationProtocols; EnabledSslProtocols = FilterOutIncompatibleSslProtocols(sslServerAuthenticationOptions.EnabledSslProtocols); EncryptionPolicy = sslServerAuthenticationOptions.EncryptionPolicy; RemoteCertRequired = sslServerAuthenticationOptions.ClientCertificateRequired; CipherSuitesPolicy = sslServerAuthenticationOptions.CipherSuitesPolicy; CertificateRevocationCheckMode = sslServerAuthenticationOptions.CertificateRevocationCheckMode; if (sslServerAuthenticationOptions.ServerCertificateContext != null) { CertificateContext = sslServerAuthenticationOptions.ServerCertificateContext; } else if (sslServerAuthenticationOptions.ServerCertificate != null) { X509Certificate2?certificateWithKey = sslServerAuthenticationOptions.ServerCertificate as X509Certificate2; if (certificateWithKey != null && certificateWithKey.HasPrivateKey) { // given cert is X509Certificate2 with key. We can use it directly. CertificateContext = SslStreamCertificateContext.Create(certificateWithKey, null); } else { // This is legacy fix-up. If the Certificate did not have key, we will search stores and we // will try to find one with matching hash. certificateWithKey = SslStream.FindCertificateWithPrivateKey(this, true, sslServerAuthenticationOptions.ServerCertificate); if (certificateWithKey == null) { throw new AuthenticationException(SR.net_ssl_io_no_server_cert); } CertificateContext = SslStreamCertificateContext.Create(certificateWithKey); } } if (sslServerAuthenticationOptions.ServerCertificateSelectionCallback != null) { ServerCertSelectionDelegate = sslServerAuthenticationOptions.ServerCertificateSelectionCallback; } }
private static SecurityStatusPal HandshakeInternal( SecureChannel secureChannel, SafeFreeCredentials credential, ref SafeDeleteSslContext?context, ReadOnlySpan <byte> inputBuffer, ref byte[]?outputBuffer, SslAuthenticationOptions sslAuthenticationOptions) { Debug.Assert(!credential.IsInvalid); try { SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context); if ((null == context) || context.IsInvalid) { sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials) !, sslAuthenticationOptions); context = sslContext; if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer) { Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost); } if (sslAuthenticationOptions.CertificateContext == null && sslAuthenticationOptions.CertSelectionDelegate != null) { // certificate was not provided but there is user callback. We can break handshake if server asks for certificate // and we can try to get it based on remote certificate and trusted issuers. Interop.AppleCrypto.SslBreakOnCertRequested(sslContext.SslContext, true); } if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired) { Interop.AppleCrypto.SslSetAcceptClientCert(sslContext.SslContext); } } if (inputBuffer.Length > 0) { sslContext !.Write(inputBuffer); } SafeSslHandle sslHandle = sslContext !.SslContext; SecurityStatusPal status = PerformHandshake(sslHandle); if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded) { X509Certificate2?clientCertificate = secureChannel.SelectClientCertificate(out _); if (clientCertificate != null) { sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate); SafeDeleteSslContext.SetCertificate(sslContext.SslContext, sslAuthenticationOptions.CertificateContext); } // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK. status = PerformHandshake(sslHandle); } outputBuffer = sslContext.ReadPendingWrites(); return(status); } catch (Exception exc) { return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc)); } }