File: System\ServiceModel\Description\ClientCredentials.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
 
namespace System.ServiceModel.Description
{
    using System.Diagnostics.CodeAnalysis;
    using System.IdentityModel.Selectors;
    using System.Runtime;
    using System.Runtime.CompilerServices;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;
    using System.ServiceModel.Security;
    using System.IdentityModel.Tokens;
 
    public class ClientCredentials : SecurityCredentialsManager, IEndpointBehavior
    {
        internal const bool SupportInteractiveDefault = true;
 
        UserNamePasswordClientCredential userName;
        X509CertificateInitiatorClientCredential clientCertificate;
        X509CertificateRecipientClientCredential serviceCertificate;
        WindowsClientCredential windows;
        HttpDigestClientCredential httpDigest;
        IssuedTokenClientCredential issuedToken;
        PeerCredential peer;
        bool supportInteractive;
        bool isReadOnly;
        GetInfoCardTokenCallback getInfoCardTokenCallback = null;
        bool useIdentityConfiguration = false;
        SecurityTokenHandlerCollectionManager securityTokenHandlerCollectionManager = null;
        object handlerCollectionLock = new object();
 
        public ClientCredentials()
        {
            this.supportInteractive = SupportInteractiveDefault;
        }
 
        protected ClientCredentials(ClientCredentials other)
        {
            if (other == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("other");
            if (other.userName != null)
                this.userName = new UserNamePasswordClientCredential(other.userName);
            if (other.clientCertificate != null)
                this.clientCertificate = new X509CertificateInitiatorClientCredential(other.clientCertificate);
            if (other.serviceCertificate != null)
                this.serviceCertificate = new X509CertificateRecipientClientCredential(other.serviceCertificate);
            if (other.windows != null)
                this.windows = new WindowsClientCredential(other.windows);
            if (other.httpDigest != null)
                this.httpDigest = new HttpDigestClientCredential(other.httpDigest);
            if (other.issuedToken != null)
                this.issuedToken = new IssuedTokenClientCredential(other.issuedToken);
            if (other.peer != null)
                this.peer = new PeerCredential(other.peer);
 
            this.getInfoCardTokenCallback = other.getInfoCardTokenCallback;
            this.supportInteractive = other.supportInteractive;
            this.securityTokenHandlerCollectionManager = other.securityTokenHandlerCollectionManager;
            this.useIdentityConfiguration = other.useIdentityConfiguration;
            this.isReadOnly = other.isReadOnly;
        }
 
        internal GetInfoCardTokenCallback GetInfoCardTokenCallback
        {
            get
            {
                if (this.getInfoCardTokenCallback == null)
                {
                    GetInfoCardTokenCallback gtc = new GetInfoCardTokenCallback(this.GetInfoCardSecurityToken);
                    this.getInfoCardTokenCallback = gtc;
                }
                return this.getInfoCardTokenCallback;
            }
        }
 
        public IssuedTokenClientCredential IssuedToken
        {
            get
            {
                if (this.issuedToken == null)
                {
                    this.issuedToken = new IssuedTokenClientCredential();
                    if (isReadOnly)
                        this.issuedToken.MakeReadOnly();
                }
                return this.issuedToken;
            }
        }
 
        public UserNamePasswordClientCredential UserName
        {
            get
            {
                if (this.userName == null)
                {
                    this.userName = new UserNamePasswordClientCredential();
                    if (isReadOnly)
                        this.userName.MakeReadOnly();
                }
                return this.userName;
            }
        }
 
        public X509CertificateInitiatorClientCredential ClientCertificate
        {
            get
            {
                if (this.clientCertificate == null)
                {
                    this.clientCertificate = new X509CertificateInitiatorClientCredential();
                    if (isReadOnly)
                        this.clientCertificate.MakeReadOnly();
                }
                return this.clientCertificate;
            }
        }
 
        public X509CertificateRecipientClientCredential ServiceCertificate
        {
            get
            {
                if (this.serviceCertificate == null)
                {
                    this.serviceCertificate = new X509CertificateRecipientClientCredential();
                    if (isReadOnly)
                        this.serviceCertificate.MakeReadOnly();
                }
                return this.serviceCertificate;
            }
        }
 
        public WindowsClientCredential Windows
        {
            get
            {
                if (this.windows == null)
                {
                    this.windows = new WindowsClientCredential();
                    if (isReadOnly)
                        this.windows.MakeReadOnly();
                }
                return this.windows;
            }
        }
 
        public HttpDigestClientCredential HttpDigest
        {
            get
            {
                if (this.httpDigest == null)
                {
                    this.httpDigest = new HttpDigestClientCredential();
                    if (isReadOnly)
                        this.httpDigest.MakeReadOnly();
                }
                return this.httpDigest;
            }
        }
 
        public PeerCredential Peer
        {
            get
            {
                if (this.peer == null)
                {
                    this.peer = new PeerCredential();
                    if (isReadOnly)
                        this.peer.MakeReadOnly();
                }
                return this.peer;
            }
        }
 
        /// <summary>
        /// The <see cref="SecurityTokenHandlerCollectionManager" /> containing the set of <see cref="SecurityTokenHandler" />
        /// objects used for serializing and validating tokens found in WS-Trust messages.
        /// </summary>
        public SecurityTokenHandlerCollectionManager SecurityTokenHandlerCollectionManager
        {
            get
            {
                if (this.securityTokenHandlerCollectionManager == null)
                {
                    lock (this.handlerCollectionLock)
                    {
                        if (this.securityTokenHandlerCollectionManager == null)
                        {
                            this.securityTokenHandlerCollectionManager = SecurityTokenHandlerCollectionManager.CreateDefaultSecurityTokenHandlerCollectionManager();
                        }
                    }
                }
 
                return this.securityTokenHandlerCollectionManager;
            }
            set
            {
                if (this.isReadOnly)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
                }
 
                this.securityTokenHandlerCollectionManager = value;
            }
        }
 
        public bool UseIdentityConfiguration
        {
            get
            {
                return this.useIdentityConfiguration;
            }
            set
            {
                if (this.isReadOnly)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
                }
                this.useIdentityConfiguration = value;
            }
        }
 
        public bool SupportInteractive
        {
            get
            {
                return this.supportInteractive;
            }
            set
            {
                if (this.isReadOnly)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.ObjectIsReadOnly)));
                }
                this.supportInteractive = value;
            }
        }
 
        internal static ClientCredentials CreateDefaultCredentials()
        {
            return new ClientCredentials();
        }
 
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new ClientCredentialsSecurityTokenManager(this.Clone());
        }
 
        protected virtual ClientCredentials CloneCore()
        {
            return new ClientCredentials(this);
        }
 
        public ClientCredentials Clone()
        {
            ClientCredentials result = CloneCore();
            if (result == null || result.GetType() != this.GetType())
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException(SR.GetString(SR.CloneNotImplementedCorrectly, this.GetType(), (result != null) ? result.ToString() : "null")));
            }
            return result;
        }
 
        void IEndpointBehavior.Validate(ServiceEndpoint serviceEndpoint)
        {
        }
 
        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters)
        {
            if (bindingParameters == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("bindingParameters");
            }
            // throw if bindingParameters already has a SecurityCredentialsManager
            SecurityCredentialsManager otherCredentialsManager = bindingParameters.Find<SecurityCredentialsManager>();
            if (otherCredentialsManager != null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MultipleSecurityCredentialsManagersInChannelBindingParameters, otherCredentialsManager)));
            }
            bindingParameters.Add(this);
        }
 
        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                SR.GetString(SR.SFXEndpointBehaviorUsedOnWrongSide, typeof(ClientCredentials).Name)));
        }
 
        [MethodImpl(MethodImplOptions.NoInlining)]
        void AddInteractiveInitializers(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
        {
            CardSpacePolicyElement[] dummyPolicyElements;
            Uri dummyRelyingPartyIssuer;
            // we add the initializer only if infocard is required. At this point, serviceEndpoint.Address is not populated correctly but that's not needed to
            // determine whether infocard is required or not.
            if (InfoCardHelper.IsInfocardRequired(serviceEndpoint.Binding, this, this.CreateSecurityTokenManager(), EndpointAddress.AnonymousAddress, out dummyPolicyElements, out dummyRelyingPartyIssuer))
            {
                behavior.InteractiveChannelInitializers.Add(new InfocardInteractiveChannelInitializer(this, serviceEndpoint.Binding));
            }
        }
 
        public virtual void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
        {
 
            if (serviceEndpoint == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint");
            }
 
            if (serviceEndpoint.Binding == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceEndpoint.Binding");
            }
 
 
            if (serviceEndpoint.Binding.CreateBindingElements().Find<SecurityBindingElement>() == null)
            {
                return;
            }
 
            try
            {
                AddInteractiveInitializers(serviceEndpoint, behavior);
            }
            catch (System.IO.FileNotFoundException)
            {
 
            }
 
        }
 
        // RC0 workaround to freeze credentials when the channel factory is opened
        internal void MakeReadOnly()
        {
            this.isReadOnly = true;
            if (this.clientCertificate != null)
                this.clientCertificate.MakeReadOnly();
            if (this.serviceCertificate != null)
                this.serviceCertificate.MakeReadOnly();
            if (this.userName != null)
                this.userName.MakeReadOnly();
            if (this.windows != null)
                this.windows.MakeReadOnly();
            if (this.httpDigest != null)
                this.httpDigest.MakeReadOnly();
            if (this.issuedToken != null)
                this.issuedToken.MakeReadOnly();
            if (this.peer != null)
                this.peer.MakeReadOnly();
        }
 
        // This APTCA method calls CardSpaceSelector.GetToken(..), which is defined in a non-APTCA assembly. It would be a breaking change to add a Demand, 
        // while we don't have an identified security vulnerability here.
        [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods)]
        internal protected virtual SecurityToken GetInfoCardSecurityToken(bool requiresInfoCard, CardSpacePolicyElement[] chain, SecurityTokenSerializer tokenSerializer)
        {
            if (!requiresInfoCard)
            {
                return null;
            }
            return CardSpaceSelector.GetToken(chain, tokenSerializer);
        }
 
    }
}