File: System\ServiceModel\UnixDomainSocketTransportSecurity.cs
Web Access
Project: src\src\System.ServiceModel.UnixDomainSocket\src\System.ServiceModel.UnixDomainSocket.csproj (System.ServiceModel.UnixDomainSocket)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.ComponentModel;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
 
namespace System.ServiceModel
{
    public sealed class UnixDomainSocketTransportSecurity
    {
        internal const UnixDomainSocketClientCredentialType DefaultClientCredentialType = UnixDomainSocketClientCredentialType.Default;
        internal const ProtectionLevel DefaultProtectionLevel = ProtectionLevel.EncryptAndSign;
 
        private UnixDomainSocketClientCredentialType _clientCredentialType;
        private ProtectionLevel _protectionLevel;
        private ExtendedProtectionPolicy _extendedProtectionPolicy;
        private SslProtocols _sslProtocols;
 
        public UnixDomainSocketTransportSecurity()
        {
            _clientCredentialType = DefaultClientCredentialType;
            _protectionLevel = DefaultProtectionLevel;
            _extendedProtectionPolicy = Channels.ChannelBindingUtility.DefaultPolicy;
            _sslProtocols = UnixDomainSocketTransportDefaults.SslProtocols;
        }
 
        [DefaultValue(DefaultClientCredentialType)]
        public UnixDomainSocketClientCredentialType ClientCredentialType
        {
            get { return _clientCredentialType; }
            set
            {
                if (!UnixDomainSocketClientCredentialTypeHelper.IsDefined(value))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value)));
                }
                _clientCredentialType = value;
            }
        }
 
        [DefaultValue(DefaultProtectionLevel)]
        public ProtectionLevel ProtectionLevel
        {
            get { return _protectionLevel; }
            set
            {
                if (!Security.ProtectionLevelHelper.IsDefined(value))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value)));
                }
 
                _protectionLevel = value;
            }
        }
 
        public ExtendedProtectionPolicy ExtendedProtectionPolicy
        {
            get
            {
                return _extendedProtectionPolicy;
            }
            set
            {
                if (value == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value));
                }
 
                if (value.PolicyEnforcement == PolicyEnforcement.Always &&
                    !ExtendedProtectionPolicy.OSSupportsExtendedProtection)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new PlatformNotSupportedException(SR.ExtendedProtectionNotSupported));
                }
                _extendedProtectionPolicy = value;
            }
        }
 
        [DefaultValue(UnixDomainSocketTransportDefaults.SslProtocols)]
        public SslProtocols SslProtocols
        {
            get { return _sslProtocols; }
            set
            {
                SslProtocolsHelper.Validate(value);
                _sslProtocols = value;
            }
        }
 
        private SslStreamSecurityBindingElement CreateSslBindingElement(bool requireClientCertificate)
        {
            if (_protectionLevel != ProtectionLevel.EncryptAndSign)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(
                    SR.UnsupportedSslProtectionLevel, _protectionLevel)));
            }
 
            SslStreamSecurityBindingElement result = new SslStreamSecurityBindingElement();
            result.RequireClientCertificate = requireClientCertificate;
            result.SslProtocols = _sslProtocols;
            return result;
        }
 
        internal BindingElement CreatePosixIdentityOnlyBinding()
        {
            return new UnixPosixIdentityBindingElement();
        }
 
        private static bool IsSslBindingElement(BindingElement element, UnixDomainSocketTransportSecurity transportSecurity)
        {
            SslStreamSecurityBindingElement ssl = element as SslStreamSecurityBindingElement;
            if (ssl == null)
            {
                return false;
            }
 
            transportSecurity.ProtectionLevel = ProtectionLevel.EncryptAndSign;
            return true;
        }
 
        internal BindingElement CreateTransportProtectionOnly()
        {
            return CreateSslBindingElement(false);
        }
 
        internal static bool SetTransportProtectionOnly(BindingElement transport, UnixDomainSocketTransportSecurity transportSecurity)
        {
            return IsSslBindingElement(transport, transportSecurity);
        }
 
        internal BindingElement CreateTransportProtectionAndAuthentication()
        {
            if (_clientCredentialType == UnixDomainSocketClientCredentialType.Default)
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    return new WindowsStreamSecurityBindingElement
                    {
                        ProtectionLevel = _protectionLevel
                    };
                }
                else
                {
                    return CreatePosixIdentityOnlyBinding();
                }
            }
            else if (_clientCredentialType == UnixDomainSocketClientCredentialType.Certificate)
            {
                return CreateSslBindingElement(true);
            }
            else if(_clientCredentialType == UnixDomainSocketClientCredentialType.Windows)
            {
                return new WindowsStreamSecurityBindingElement
                {
                    ProtectionLevel = _protectionLevel
                };
            }
            else if (_clientCredentialType == UnixDomainSocketClientCredentialType.PosixIdentity)
            {
                if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                {
                    throw new NotSupportedException();
                }
                return CreatePosixIdentityOnlyBinding();
            }
            else if(_clientCredentialType == UnixDomainSocketClientCredentialType.None)
            {
                return CreateTransportProtectionOnly();
            }
            else
            {
                return null;
            }
        }
        
    }
}