< Summary

Line coverage
10%
Covered lines: 23
Uncovered lines: 198
Coverable lines: 221
Total lines: 337
Line coverage: 10.4%
Branch coverage
2%
Covered branches: 2
Total branches: 82
Branch coverage: 2.4%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor()100%11100%
UpdateOptions(...)0%26260%
UpdateOptions(...)100%11100%
UpdateOptions(...)0%50500%
FilterOutIncompatibleSslProtocols(...)0%220%
SetCertificateContextFromCert(...)100%110%
Clone()100%110%
CopyFrom(...)100%110%
Dispose()50%4450%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Net.Security/src/System/Net/Security/SslAuthenticationOptions.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Collections.Generic;
 6using System.Diagnostics;
 7using System.Security.Authentication;
 8using System.Security.Cryptography.X509Certificates;
 9
 10namespace System.Net.Security
 11{
 12    internal sealed partial class SslAuthenticationOptions : IDisposable
 13    {
 14        // Hook invoked by OpenSSL's CertVerifyCallback to drive remote
 15        // certificate validation. Set by SslStream and by standalone TlsSession
 16        // so both flows share the same callback plumbing. Declared on the
 17        // cross-platform partial so the delegate type is resolvable in test
 18        // projects (unit-test fakes) that compile SslStream.cs on non-Linux
 19        // targets where the OpenSSL partial file isn't included.
 20        internal delegate bool VerifyRemoteCertificateCallback(
 21            X509Certificate2? certificate,
 22            X509Chain? chain,
 23            SslCertificateTrust? trust,
 24            ref ProtocolToken alertToken,
 25            ref SslPolicyErrors sslPolicyErrors,
 26            out X509ChainStatusFlags chainStatus);
 27
 28        internal VerifyRemoteCertificateCallback? RemoteCertificateValidator { get; set; }
 29
 30        internal const X509RevocationMode DefaultRevocationMode = X509RevocationMode.NoCheck;
 31
 3132        internal SslAuthenticationOptions()
 3133        {
 3134            TargetHost = string.Empty;
 3135        }
 36
 37        internal void UpdateOptions(SslClientAuthenticationOptions sslClientAuthenticationOptions)
 038        {
 039            if (CertValidationDelegate == null)
 040            {
 041                CertValidationDelegate = sslClientAuthenticationOptions.RemoteCertificateValidationCallback;
 042            }
 043            else if (sslClientAuthenticationOptions.RemoteCertificateValidationCallback != null &&
 044                     CertValidationDelegate != sslClientAuthenticationOptions.RemoteCertificateValidationCallback)
 045            {
 46                // Callback was set in constructor to different value.
 047                throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(RemoteCertificateValida
 48            }
 49
 050            if (CertSelectionDelegate == null)
 051            {
 052                CertSelectionDelegate = sslClientAuthenticationOptions.LocalCertificateSelectionCallback;
 053            }
 054            else if (sslClientAuthenticationOptions.LocalCertificateSelectionCallback != null &&
 055                     CertSelectionDelegate != sslClientAuthenticationOptions.LocalCertificateSelectionCallback)
 056            {
 057                throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(LocalCertificateSelecti
 58            }
 59
 60            // Common options.
 061            AllowRenegotiation = sslClientAuthenticationOptions.AllowRenegotiation;
 062            AllowTlsResume = sslClientAuthenticationOptions.AllowTlsResume;
 063            ApplicationProtocols = sslClientAuthenticationOptions.ApplicationProtocols;
 064            CheckCertName = !(sslClientAuthenticationOptions.CertificateChainPolicy?.VerificationFlags.HasFlag(X509Verif
 065            EnabledSslProtocols = FilterOutIncompatibleSslProtocols(sslClientAuthenticationOptions.EnabledSslProtocols);
 066            EncryptionPolicy = sslClientAuthenticationOptions.EncryptionPolicy;
 067            IsServer = false;
 068            RemoteCertRequired = true;
 069            CertificateContext = sslClientAuthenticationOptions.ClientCertificateContext;
 070            TargetHost = sslClientAuthenticationOptions.TargetHost ?? string.Empty;
 71
 072            AllowRsaPssPadding = sslClientAuthenticationOptions.AllowRsaPssPadding;
 073            AllowRsaPkcs1Padding = sslClientAuthenticationOptions.AllowRsaPkcs1Padding;
 74
 075            if (!OperatingSystem.IsWindows() && !OperatingSystem.IsLinux())
 076            {
 077                if (!sslClientAuthenticationOptions.AllowRsaPssPadding || !sslClientAuthenticationOptions.AllowRsaPkcs1P
 078                {
 079                    throw new PlatformNotSupportedException(SR.net_ssl_allow_rsa_padding_not_supported);
 80                }
 081            }
 82
 83            // Client specific options.
 084            CertificateRevocationCheckMode = sslClientAuthenticationOptions.CertificateRevocationCheckMode;
 085            ClientCertificates = sslClientAuthenticationOptions.ClientCertificates;
 086            CipherSuitesPolicy = sslClientAuthenticationOptions.CipherSuitesPolicy;
 87
 088            if (sslClientAuthenticationOptions.CertificateChainPolicy != null)
 089            {
 090                CertificateChainPolicy = sslClientAuthenticationOptions.CertificateChainPolicy.Clone();
 091            }
 092        }
 93
 94        internal void UpdateOptions(ServerOptionsSelectionCallback optionCallback, object? state)
 3195        {
 3196            CheckCertName = false;
 3197            TargetHost = string.Empty;
 3198            IsServer = true;
 3199            UserState = state;
 31100            ServerOptionDelegate = optionCallback;
 31101        }
 102
 103        internal void UpdateOptions(SslServerAuthenticationOptions sslServerAuthenticationOptions)
 0104        {
 0105            if (sslServerAuthenticationOptions.ServerCertificate == null &&
 0106                sslServerAuthenticationOptions.ServerCertificateContext == null &&
 0107                sslServerAuthenticationOptions.ServerCertificateSelectionCallback == null &&
 0108                CertSelectionDelegate == null)
 0109            {
 0110                throw new NotSupportedException(SR.net_ssl_io_no_server_cert);
 111            }
 112
 0113            if ((sslServerAuthenticationOptions.ServerCertificate != null ||
 0114                 sslServerAuthenticationOptions.ServerCertificateContext != null ||
 0115                 CertSelectionDelegate != null) &&
 0116                sslServerAuthenticationOptions.ServerCertificateSelectionCallback != null)
 0117            {
 0118                throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(ServerCertificateSelect
 119            }
 120
 0121            if (CertValidationDelegate == null)
 0122            {
 0123                CertValidationDelegate = sslServerAuthenticationOptions.RemoteCertificateValidationCallback;
 0124            }
 0125            else if (sslServerAuthenticationOptions.RemoteCertificateValidationCallback != null &&
 0126                     CertValidationDelegate != sslServerAuthenticationOptions.RemoteCertificateValidationCallback)
 0127            {
 128                // Callback was set in constructor to differet value.
 0129                throw new InvalidOperationException(SR.Format(SR.net_conflicting_options, nameof(RemoteCertificateValida
 130            }
 131
 0132            IsServer = true;
 0133            AllowRenegotiation = sslServerAuthenticationOptions.AllowRenegotiation;
 0134            AllowTlsResume = sslServerAuthenticationOptions.AllowTlsResume;
 0135            ApplicationProtocols = sslServerAuthenticationOptions.ApplicationProtocols;
 0136            EnabledSslProtocols = FilterOutIncompatibleSslProtocols(sslServerAuthenticationOptions.EnabledSslProtocols);
 0137            EncryptionPolicy = sslServerAuthenticationOptions.EncryptionPolicy;
 0138            RemoteCertRequired = sslServerAuthenticationOptions.ClientCertificateRequired;
 0139            CipherSuitesPolicy = sslServerAuthenticationOptions.CipherSuitesPolicy;
 0140            CertificateRevocationCheckMode = sslServerAuthenticationOptions.CertificateRevocationCheckMode;
 141
 0142            AllowRsaPssPadding = sslServerAuthenticationOptions.AllowRsaPssPadding;
 0143            AllowRsaPkcs1Padding = sslServerAuthenticationOptions.AllowRsaPkcs1Padding;
 144
 0145            if (!OperatingSystem.IsWindows() && !OperatingSystem.IsLinux())
 0146            {
 0147                if (!sslServerAuthenticationOptions.AllowRsaPssPadding || !sslServerAuthenticationOptions.AllowRsaPkcs1P
 0148                {
 0149                    throw new PlatformNotSupportedException(SR.net_ssl_allow_rsa_padding_not_supported);
 150                }
 0151            }
 152
 0153            if (sslServerAuthenticationOptions.ServerCertificateContext != null)
 0154            {
 155                // Release any previously owned context before replacing it with the caller's context.
 0156                if (OwnsCertificateContext && CertificateContext is not null &&
 0157                    !ReferenceEquals(CertificateContext, sslServerAuthenticationOptions.ServerCertificateContext))
 0158                {
 0159                    CertificateContext.ReleaseResources();
 0160                }
 0161                CertificateContext = sslServerAuthenticationOptions.ServerCertificateContext;
 0162                OwnsCertificateContext = false;
 0163            }
 0164            else if (sslServerAuthenticationOptions.ServerCertificate != null)
 0165            {
 0166                X509Certificate2? certificateWithKey = sslServerAuthenticationOptions.ServerCertificate as X509Certifica
 167
 0168                if (certificateWithKey != null && certificateWithKey.HasPrivateKey)
 0169                {
 0170                    bool ocspFetch = LocalAppContextSwitches.EnableOcspStapling;
 171                    // given cert is X509Certificate2 with key. We can use it directly.
 0172                    SetCertificateContextFromCert(certificateWithKey, !ocspFetch);
 0173                }
 174                else
 0175                {
 176                    // This is legacy fix-up. If the Certificate did not have key, we will search stores and we
 177                    // will try to find one with matching hash.
 0178                    certificateWithKey = SslStream.FindCertificateWithPrivateKey(this, true, sslServerAuthenticationOpti
 0179                    if (certificateWithKey == null)
 0180                    {
 0181                        throw new AuthenticationException(SR.net_ssl_io_no_server_cert);
 182                    }
 183
 0184                    SetCertificateContextFromCert(certificateWithKey);
 0185                }
 0186            }
 187
 0188            if (sslServerAuthenticationOptions.ServerCertificateSelectionCallback != null)
 0189            {
 0190                ServerCertSelectionDelegate = sslServerAuthenticationOptions.ServerCertificateSelectionCallback;
 0191            }
 192
 0193            if (sslServerAuthenticationOptions.CertificateChainPolicy != null)
 0194            {
 0195                CertificateChainPolicy = sslServerAuthenticationOptions.CertificateChainPolicy.Clone();
 0196            }
 0197        }
 198
 199        private static SslProtocols FilterOutIncompatibleSslProtocols(SslProtocols protocols)
 0200        {
 0201            if ((protocols & (SslProtocols.Tls12 | SslProtocols.Tls13)) != SslProtocols.None)
 0202            {
 203#pragma warning disable 0618
 204                // SSL2 is mutually exclusive with >= TLS1.2
 0205                protocols &= ~SslProtocols.Ssl2;
 206#pragma warning restore 0618
 0207            }
 208
 0209            return protocols;
 0210        }
 211
 212        internal void SetCertificateContextFromCert(X509Certificate2 certificate, bool? noOcspFetch = null)
 0213        {
 0214            CertificateContext = SslStreamCertificateContext.Create(certificate, null, offline: false, null, noOcspFetch
 0215            OwnsCertificateContext = true;
 0216        }
 217
 218        // Shallow copy of the configuration carried by this bag. Per-handle/per-stream
 219        // state (SafeSslHandle, SslStream, RemoteCertificateValidator) is intentionally
 220        // not propagated, and the clone does not take ownership of CertificateContext
 221        // even if the source did.
 222        internal SslAuthenticationOptions Clone()
 0223        {
 0224            SslAuthenticationOptions copy = new SslAuthenticationOptions
 0225            {
 0226                AllowRenegotiation = AllowRenegotiation,
 0227                TargetHost = TargetHost,
 0228                ClientCertificates = ClientCertificates,
 0229                ApplicationProtocols = ApplicationProtocols,
 0230                IsServer = IsServer,
 0231                CertificateContext = CertificateContext,
 0232                OwnsCertificateContext = false,
 0233                EnabledSslProtocols = EnabledSslProtocols,
 0234                CertificateRevocationCheckMode = CertificateRevocationCheckMode,
 0235                EncryptionPolicy = EncryptionPolicy,
 0236                RemoteCertRequired = RemoteCertRequired,
 0237                CheckCertName = CheckCertName,
 0238                CertValidationDelegate = CertValidationDelegate,
 0239                CertSelectionDelegate = CertSelectionDelegate,
 0240                ServerCertSelectionDelegate = ServerCertSelectionDelegate,
 0241                CipherSuitesPolicy = CipherSuitesPolicy,
 0242                UserState = UserState,
 0243                ServerOptionDelegate = ServerOptionDelegate,
 0244                CertificateChainPolicy = CertificateChainPolicy,
 0245                AllowTlsResume = AllowTlsResume,
 0246                AllowRsaPssPadding = AllowRsaPssPadding,
 0247                AllowRsaPkcs1Padding = AllowRsaPkcs1Padding,
 0248                ForceSyncPal = ForceSyncPal,
 0249            };
 0250            return copy;
 0251        }
 252
 253        // Bulk-copy field values from another options bag into this one. Used by
 254        // TlsSession.SetContext to inherit a fully-configured server context's
 255        // options into an existing session (whose bag was originally created empty
 256        // from a deferred TlsContext.Create((SslServerAuthenticationOptions?)null)).
 257        // Mirrors the field set copied by Clone(). Session-scoped state (SafeSslHandle,
 258        // RemoteCertificateValidator, SocketHandle, ReplayPrefix, PreallocatedSslContext)
 259        // is intentionally NOT copied — those belong to the receiving session.
 260        internal void CopyFrom(SslAuthenticationOptions other)
 0261        {
 0262            AllowRenegotiation = other.AllowRenegotiation;
 0263            TargetHost = other.TargetHost;
 0264            ClientCertificates = other.ClientCertificates;
 0265            ApplicationProtocols = other.ApplicationProtocols;
 0266            IsServer = other.IsServer;
 0267            CertificateContext = other.CertificateContext;
 0268            OwnsCertificateContext = false;
 0269            EnabledSslProtocols = other.EnabledSslProtocols;
 0270            CertificateRevocationCheckMode = other.CertificateRevocationCheckMode;
 0271            EncryptionPolicy = other.EncryptionPolicy;
 0272            RemoteCertRequired = other.RemoteCertRequired;
 0273            CheckCertName = other.CheckCertName;
 0274            CertValidationDelegate = other.CertValidationDelegate;
 0275            CertSelectionDelegate = other.CertSelectionDelegate;
 0276            ServerCertSelectionDelegate = other.ServerCertSelectionDelegate;
 0277            CipherSuitesPolicy = other.CipherSuitesPolicy;
 0278            UserState = other.UserState;
 0279            ServerOptionDelegate = other.ServerOptionDelegate;
 0280            CertificateChainPolicy = other.CertificateChainPolicy;
 0281            AllowTlsResume = other.AllowTlsResume;
 0282            AllowRsaPssPadding = other.AllowRsaPssPadding;
 0283            AllowRsaPkcs1Padding = other.AllowRsaPkcs1Padding;
 0284            ForceSyncPal = other.ForceSyncPal;
 0285        }
 286
 0287        internal bool AllowRenegotiation { get; set; }
 62288        internal string TargetHost { get; set; }
 0289        internal X509CertificateCollection? ClientCertificates { get; set; }
 0290        internal List<SslApplicationProtocol>? ApplicationProtocols { get; set; }
 71291        internal bool IsServer { get; set; }
 292        internal bool IsClient => !IsServer;
 0293        internal SslStreamCertificateContext? CertificateContext { get; set; }
 294        // If true, the certificate context was created by the SslStream and
 295        // certificates inside should be disposed when no longer needed.
 31296        internal bool OwnsCertificateContext { get; set; }
 0297        internal SslProtocols EnabledSslProtocols { get; set; }
 0298        internal X509RevocationMode CertificateRevocationCheckMode { get; set; }
 31299        internal EncryptionPolicy EncryptionPolicy { get; set; }
 0300        internal bool RemoteCertRequired { get; set; }
 31301        internal bool CheckCertName { get; set; }
 31302        internal RemoteCertificateValidationCallback? CertValidationDelegate { get; set; }
 31303        internal LocalCertificateSelectionCallback? CertSelectionDelegate { get; set; }
 0304        internal ServerCertificateSelectionCallback? ServerCertSelectionDelegate { get; set; }
 0305        internal CipherSuitesPolicy? CipherSuitesPolicy { get; set; }
 31306        internal object? UserState { get; set; }
 31307        internal ServerOptionsSelectionCallback? ServerOptionDelegate { get; set; }
 0308        internal X509ChainPolicy? CertificateChainPolicy { get; set; }
 0309        internal bool AllowTlsResume { get; set; }
 0310        internal bool AllowRsaPssPadding { get; set; }
 0311        internal bool AllowRsaPkcs1Padding { get; set; }
 312        // Set by callers (e.g. TlsSession) whose state machine is intrinsically synchronous
 313        // and cannot use the async Network Framework PAL path on macOS.
 0314        internal bool ForceSyncPal { get; set; }
 315
 316#if TARGET_ANDROID
 317        internal SslStream.JavaProxy? SslStreamProxy { get; set; }
 318#endif
 319
 320#if !TARGET_WINDOWS && !SYSNETSECURITY_NO_OPENSSL
 321        internal SslStream? SslStream { get; set; }
 322#endif
 323
 324        public void Dispose()
 31325        {
 31326            if (OwnsCertificateContext && CertificateContext != null)
 0327            {
 0328                CertificateContext.ReleaseResources();
 0329            }
 330
 331#if TARGET_ANDROID
 332            SslStreamProxy?.Dispose();
 333#endif
 31334        }
 335    }
 336}
 337