File: src\libraries\Common\src\System\Net\Security\SslClientAuthenticationOptionsExtensions.cs
Web Access
Project: src\src\libraries\System.Net.Http\src\System.Net.Http.csproj (System.Net.Http)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
#if DEBUG
using System.Collections;
using System.Diagnostics;
using System.Reflection;
#endif
 
namespace System.Net.Security
{
    internal static class SslClientAuthenticationOptionsExtensions
    {
        public static SslClientAuthenticationOptions ShallowClone(this SslClientAuthenticationOptions options)
        {
            // Use non-default values to verify the clone works fine.
            var clone = new SslClientAuthenticationOptions()
            {
                AllowRenegotiation = options.AllowRenegotiation,
                AllowTlsResume = options.AllowTlsResume,
                ApplicationProtocols = options.ApplicationProtocols != null ? new List<SslApplicationProtocol>(options.ApplicationProtocols) : null,
                CertificateRevocationCheckMode = options.CertificateRevocationCheckMode,
                CertificateChainPolicy = options.CertificateChainPolicy,
                CipherSuitesPolicy = options.CipherSuitesPolicy,
                ClientCertificates = options.ClientCertificates,
                ClientCertificateContext = options.ClientCertificateContext,
                EnabledSslProtocols = options.EnabledSslProtocols,
                EncryptionPolicy = options.EncryptionPolicy,
                LocalCertificateSelectionCallback = options.LocalCertificateSelectionCallback,
                RemoteCertificateValidationCallback = options.RemoteCertificateValidationCallback,
                TargetHost = options.TargetHost,
#pragma warning disable CA1416 // Ignore SupportedOSPlatform checks, the value will be validated at runtime inside SslStream
                AllowRsaPssPadding = options.AllowRsaPssPadding,
                AllowRsaPkcs1Padding = options.AllowRsaPkcs1Padding
#pragma warning restore CA1416
            };
 
#if DEBUG
            // Try to detect if a property gets added that we're not copying correctly.
            // The property count is guard for new properties that also needs to be added above.
            PropertyInfo[] properties = typeof(SslClientAuthenticationOptions).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)!;
            Debug.Assert(properties.Length == 15);
            foreach (PropertyInfo pi in properties)
            {
                object? origValue = pi.GetValue(options);
                object? cloneValue = pi.GetValue(clone);
 
                if (origValue is IEnumerable origEnumerable)
                {
                    IEnumerable? cloneEnumerable = cloneValue as IEnumerable;
                    Debug.Assert(cloneEnumerable != null, $"{pi.Name}. Expected enumerable cloned value.");
 
                    IEnumerator e1 = origEnumerable.GetEnumerator();
                    try
                    {
                        IEnumerator e2 = cloneEnumerable.GetEnumerator();
                        try
                        {
                            while (e1.MoveNext())
                            {
                                Debug.Assert(e2.MoveNext(), $"{pi.Name}. Cloned enumerator too short.");
                                Debug.Assert(Equals(e1.Current, e2.Current), $"{pi.Name}. Cloned enumerator's values don't match.");
                            }
                            Debug.Assert(!e2.MoveNext(), $"{pi.Name}. Cloned enumerator too long.");
                        }
                        finally
                        {
                            (e2 as IDisposable)?.Dispose();
                        }
                    }
                    finally
                    {
                        (e1 as IDisposable)?.Dispose();
                    }
                }
                else
                {
                    Debug.Assert(Equals(origValue, cloneValue), $"{pi.Name}. Expected: {origValue}, Actual: {cloneValue}");
                }
            }
#endif
 
            return clone;
        }
    }
}