PeerSecurityManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / PeerSecurityManager.cs / 1 / PeerSecurityManager.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.ServiceModel.Channels
{ 
    using System.Collections.Generic;
    using System.ServiceModel; 
    using System.ServiceModel.Description; 
    using System.Collections.ObjectModel;
    using System.Diagnostics; 
    using System.Globalization;
    using System.Net;
    using System.Net.Security;
    using System.Runtime.Serialization; 
    using System.ServiceModel.Diagnostics;
    using System.Xml; 
    using System.Security; 
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy; 
    using System.IdentityModel.Selectors;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceModel.Security; 
    using System.ServiceModel.Security.Tokens;
    using System.IdentityModel.Tokens; 
    using System.Text; 
    using System.Threading;
    using System.ServiceModel.Dispatcher; 

    class PeerSecurityManager
    {
        PeerAuthenticationMode authenticationMode; 
        bool enableSigning;
        internal string password; 
 
        DuplexSecurityProtocolFactory securityProtocolFactory;
        byte[] authenticatorHash; 
        object thisLock;
        //public EventHandler OnNeighborOpened;
        public EventHandler OnNeighborAuthenticated;
        string meshId = String.Empty; 
        ChannelProtectionRequirements protection;
        PeerSecurityCredentialsManager credManager; 
        SecurityTokenManager tokenManager; 
        SelfSignedCertificate ssc;
        XmlDictionaryReaderQuotas readerQuotas; 

        // Audit
        ServiceSecurityAuditBehavior auditBehavior;
 
        PeerSecurityManager(PeerAuthenticationMode authMode, bool signing)
        { 
            this.authenticationMode = authMode; 
            this.enableSigning = signing;
            thisLock = new object(); 
        }

        public PeerAuthenticationMode AuthenticationMode
        { 
            get
            { 
                return authenticationMode; 
            }
        } 

        public string Password
        {
            get 
            {
                return password; 
            } 
        }
        public X509Certificate2 SelfCert 
        {
            get
            {
                return credManager.Certificate; 
            }
        } 
        public bool MessageAuthentication 
        {
            get 
            {
                return this.enableSigning;
            }
        } 

        internal string MeshId 
        { 
            get
            { 
                return this.meshId;
            }
            set
            { 
                this.meshId = value;
            } 
        } 

        internal SelfSignedCertificate GetCertificate() 
        {
            if (this.ssc == null)
            {
                lock (ThisLock) 
                {
                    if (ssc == null) 
                        ssc = SelfSignedCertificate.Create("CN=" + Guid.NewGuid().ToString(), this.Password); 
                }
            } 
            return ssc;
        }

        object ThisLock 
        {
            get { return thisLock; } 
        } 

        static PeerSecurityCredentialsManager GetCredentialsManager(PeerAuthenticationMode mode, bool signing, BindingContext context) 
        {
            if (mode == PeerAuthenticationMode.None && !signing)
                return null;
            ClientCredentials clientCredentials = context.BindingParameters.Find(); 
            if (clientCredentials != null)
            { 
                return new PeerSecurityCredentialsManager(clientCredentials.Peer, mode, signing); 
            }
            ServiceCredentials serviceCredentials = context.BindingParameters.Find(); 
            if (serviceCredentials != null)
            {
                return new PeerSecurityCredentialsManager(serviceCredentials.Peer, mode, signing);
            } 
            SecurityCredentialsManager credman = context.BindingParameters.Find();
            if(credman == null) 
            { 
                PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Credentials);
            } 
            return new PeerSecurityCredentialsManager(credman.CreateSecurityTokenManager(), mode, signing);
        }

        static void Convert(PeerSecuritySettings security, out PeerAuthenticationMode authMode, out bool signing) 
        {
            authMode = PeerAuthenticationMode.None; 
            signing = false; 
            if(security.Mode == SecurityMode.Transport || security.Mode == SecurityMode.TransportWithMessageCredential)
            { 
                switch(security.Transport.CredentialType)
                {
                    case PeerTransportCredentialType.Password:
                        authMode = PeerAuthenticationMode.Password; 
                        break;
                    case PeerTransportCredentialType.Certificate: 
                        authMode = PeerAuthenticationMode.MutualCertificate; 
                        break;
                } 
            }
            if( security.Mode == SecurityMode.Message || security.Mode == SecurityMode.TransportWithMessageCredential)
            {
                signing = true; 
            }
        } 
 
        static public PeerSecurityManager Create(PeerSecuritySettings security, BindingContext context, XmlDictionaryReaderQuotas readerQuotas)
        { 
            PeerAuthenticationMode authMode = PeerAuthenticationMode.None;
            bool signing = false;
            Convert(security, out authMode, out signing);
            return Create(authMode,signing,context, readerQuotas); 

        } 
 
        static public PeerSecurityManager Create(PeerAuthenticationMode authenticationMode, bool signMessages, BindingContext context, XmlDictionaryReaderQuotas readerQuotas)
        { 
            if (authenticationMode == PeerAuthenticationMode.None && !signMessages)
                return CreateDummy();

            // test FIPS mode 
            if (authenticationMode == PeerAuthenticationMode.Password)
            { 
                try 
                {
                    using(HMACSHA256 algo = new HMACSHA256()) 
                    {
                        using(SHA256Managed sha = new SHA256Managed()) {}
                    }
                } 
                catch (InvalidOperationException e)
                { 
                    DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    PeerExceptionHelper.ThrowInvalidOperation_InsufficientCryptoSupport(e);
                } 
            }

            ChannelProtectionRequirements reqs = context.BindingParameters.Find();
            PeerSecurityCredentialsManager credman = GetCredentialsManager(authenticationMode,signMessages, context); 
            if(credman.Credential != null)
            { 
                //for compatibility with existing code: 
                ValidateCredentialSettings(authenticationMode, signMessages, credman.Credential);
            } 
            PeerSecurityManager manager = Create(authenticationMode, signMessages, credman, reqs, readerQuotas);
            credman.Parent = manager;
            manager.ApplyAuditBehaviorSettings(context);
 
            return manager;
        } 
 
        static void ValidateCredentialSettings(PeerAuthenticationMode authenticationMode, bool signMessages, PeerCredential credential)
        { 
            X509CertificateValidator validator;
            if(authenticationMode == PeerAuthenticationMode.None && !signMessages)
                return;
            switch (authenticationMode) 
            {
                case PeerAuthenticationMode.Password: 
                    { 
                        if(String.IsNullOrEmpty(credential.MeshPassword))
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Password); 
                    }
                    break;
                case PeerAuthenticationMode.MutualCertificate:
                    { 
                        if (credential.Certificate == null)
                        { 
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Certificate); 
                        }
                        if(!credential.PeerAuthentication.TryGetCertificateValidator(out validator)) 
                        {
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.PeerAuthentication);
                        }
 
                    }
                    break; 
            } 
            if (signMessages)
            { 
                if (!credential.MessageSenderAuthentication.TryGetCertificateValidator(out validator))
                {
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication);
                } 
            }
        } 
 
        void ApplyAuditBehaviorSettings(BindingContext context)
        { 
            ServiceSecurityAuditBehavior auditBehavior = context.BindingParameters.Find();
            if (auditBehavior != null)
            {
                this.auditBehavior = auditBehavior.Clone(); 
            }
            else 
            { 
                this.auditBehavior = new ServiceSecurityAuditBehavior();
            } 
        }

        public void ApplyServiceSecurity(ServiceDescription description)
        { 
            if (this.AuthenticationMode == PeerAuthenticationMode.None)
                return; 
            description.Behaviors.Add(credManager.CloneForTransport()); 
        }
 
        internal static PeerSecurityManager CreateDummy()
        {
            PeerSecurityManager manager = new PeerSecurityManager(PeerAuthenticationMode.None, false);
            return manager; 
        }
 
        static public PeerSecurityManager Create(PeerAuthenticationMode authenticationMode, bool messageAuthentication, PeerSecurityCredentialsManager credman, ChannelProtectionRequirements reqs, XmlDictionaryReaderQuotas readerQuotas) 
        {
            PeerSecurityManager manager = null; 
            X509CertificateValidator connectionValidator = null;
            X509CertificateValidator messageValidator = null;
            PeerCredential credential = credman.Credential;
 
            if (null == credential && credman == null)
            { 
                if (authenticationMode != PeerAuthenticationMode.None || messageAuthentication) 
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Credentials);
                //create one that doesnt have any credentials in it. 
                return CreateDummy();
            }

            manager = new PeerSecurityManager(authenticationMode, messageAuthentication); 
            manager.credManager = credman;
            manager.password = credman.Password; 
            manager.readerQuotas = readerQuotas; 
            if (reqs != null)
            { 
                manager.protection = new ChannelProtectionRequirements(reqs);
            }
            manager.tokenManager = credman.CreateSecurityTokenManager();
            if(credential == null) 
                return manager;
 
            switch (authenticationMode) 
            {
                case PeerAuthenticationMode.None: 
                    break;
                case PeerAuthenticationMode.Password:
                    {
                        manager.password = credential.MeshPassword; 
                        if (String.IsNullOrEmpty(manager.credManager.Password))
                        { 
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Password); 
                        }
                        connectionValidator = X509CertificateValidator.None; 
                    }
                    break;
                case PeerAuthenticationMode.MutualCertificate:
                    { 
                        if (manager.credManager.Certificate == null)
                        { 
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.Certificate); 
                        }
                        if(!credential.PeerAuthentication.TryGetCertificateValidator(out connectionValidator)) 
                        {
                            PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.PeerAuthentication);
                        }
                    } 
                    break;
            } 
            if (messageAuthentication) 
            {
                if (credential.MessageSenderAuthentication != null) 
                {
                    if(!credential.MessageSenderAuthentication.TryGetCertificateValidator(out messageValidator))
                    {
                        PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication); 
                    }
                } 
                else 
                {
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication); 
                }
            }
            return manager;
        } 

        void ApplySigningRequirements(ScopedMessagePartSpecification spec) 
        { 
           //following are the headers that we add and want signed.
            MessagePartSpecification partSpec = new MessagePartSpecification( 
                                new XmlQualifiedName(PeerStrings.Via, PeerStrings.Namespace),
                                new XmlQualifiedName(PeerOperationNames.Flood, PeerStrings.Namespace),
                                new XmlQualifiedName(PeerOperationNames.PeerTo, PeerStrings.Namespace),
                                new XmlQualifiedName(PeerStrings.MessageId, PeerStrings.Namespace)); 
            foreach (string action in spec.Actions)
            { 
                spec.AddParts(partSpec, action); 
            }
            spec.AddParts(partSpec, MessageHeaders.WildcardAction); 
        }

        public void Open()
        { 
            CreateSecurityProtocolFactory();
        } 
 
        void CreateSecurityProtocolFactory()
        { 
            SecurityProtocolFactory incomingProtocolFactory;
            SecurityProtocolFactory outgoingProtocolFactory;
            ChannelProtectionRequirements protectionRequirements;
 
            lock (ThisLock)
            { 
                if (null != securityProtocolFactory) 
                    return;
 
                TimeoutHelper timeoutHelper = new TimeoutHelper(ServiceDefaults.SendTimeout);
                if (!enableSigning)
                {
                    outgoingProtocolFactory = new PeerDoNothingSecurityProtocolFactory(); 
                    incomingProtocolFactory = new PeerDoNothingSecurityProtocolFactory();
                } 
                else 
                {
                    X509Certificate2 cert = credManager.Certificate; 
                    if (cert != null)
                    {
                        SecurityBindingElement securityBindingElement = SecurityBindingElement.CreateCertificateSignatureBindingElement();
                        securityBindingElement.ReaderQuotas = this.readerQuotas; 
                        BindingParameterCollection bpc = new BindingParameterCollection();
                        if (protection == null) 
                        { 
                            protectionRequirements = new ChannelProtectionRequirements();
                        } 
                        else
                        {
                            protectionRequirements = new ChannelProtectionRequirements(protection);
                        } 
                        ApplySigningRequirements(protectionRequirements.IncomingSignatureParts);
                        ApplySigningRequirements(protectionRequirements.OutgoingSignatureParts); 
 
                        bpc.Add(protectionRequirements);
                        bpc.Add(this.auditBehavior); 
                        bpc.Add(credManager);
                        BindingContext context = new BindingContext(new CustomBinding(securityBindingElement), bpc);
                        outgoingProtocolFactory = securityBindingElement.CreateSecurityProtocolFactory(context, credManager, false, null);
                    } 
                    else
                    { 
                        outgoingProtocolFactory = new PeerDoNothingSecurityProtocolFactory(); 
                    }
                    SecurityTokenResolver resolver; 
                    X509SecurityTokenAuthenticator auth = tokenManager.CreateSecurityTokenAuthenticator(PeerSecurityCredentialsManager.PeerClientSecurityTokenManager.CreateRequirement(SecurityTokenTypes.X509Certificate, true), out resolver) as X509SecurityTokenAuthenticator ;
                    if (auth != null)
                    {
                        SecurityBindingElement securityBindingElement = SecurityBindingElement.CreateCertificateSignatureBindingElement(); 
                        securityBindingElement.ReaderQuotas = this.readerQuotas;
                        BindingParameterCollection bpc = new BindingParameterCollection(); 
                        if (protection == null) 
                        {
                            protectionRequirements = new ChannelProtectionRequirements(); 
                        }
                        else
                        {
                            protectionRequirements = new ChannelProtectionRequirements(protection); 
                        }
                        ApplySigningRequirements(protectionRequirements.IncomingSignatureParts); 
                        ApplySigningRequirements(protectionRequirements.OutgoingSignatureParts); 

                        bpc.Add(protectionRequirements); 
                        bpc.Add(this.auditBehavior);
                        bpc.Add(credManager);
                        BindingContext context = new BindingContext(new CustomBinding(securityBindingElement), bpc);
                        incomingProtocolFactory = securityBindingElement.CreateSecurityProtocolFactory(context, credManager, true, null); 
                    }
                    else 
                    { 
                        incomingProtocolFactory = new PeerDoNothingSecurityProtocolFactory();
                    } 
                }
                DuplexSecurityProtocolFactory tempFactory = new DuplexSecurityProtocolFactory(outgoingProtocolFactory, incomingProtocolFactory);
                tempFactory.Open(true, timeoutHelper.RemainingTime());
                securityProtocolFactory = tempFactory; 
            }
        } 
 
        public SecurityProtocolFactory GetProtocolFactory()
        { 
            if(securityProtocolFactory == null)
            {
                CreateSecurityProtocolFactory();
            } 
            if(typeof(TChannel) == typeof(IOutputChannel))
            { 
                if(enableSigning && securityProtocolFactory.ForwardProtocolFactory is PeerDoNothingSecurityProtocolFactory) 
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication);
                return securityProtocolFactory.ForwardProtocolFactory; 
            }
            else if(typeof(TChannel) == typeof(IInputChannel))
            {
                if(enableSigning && securityProtocolFactory.ReverseProtocolFactory is PeerDoNothingSecurityProtocolFactory) 
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication);
                return securityProtocolFactory.ReverseProtocolFactory; 
            } 
            else
            { 
                if(enableSigning && ((securityProtocolFactory.ReverseProtocolFactory is PeerDoNothingSecurityProtocolFactory)
                                        || (securityProtocolFactory.ForwardProtocolFactory is PeerDoNothingSecurityProtocolFactory)))
                    PeerExceptionHelper.ThrowArgument_InsufficientCredentials(PeerPropertyNames.MessageSenderAuthentication);
                return securityProtocolFactory; 
            }
        } 
 
        public SecurityProtocol CreateSecurityProtocol(EndpointAddress target, TimeSpan timespan)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timespan);
            SecurityProtocolFactory factory = GetProtocolFactory();
            DiagnosticUtility.DebugAssert(factory != null, "SecurityProtocolFactory is NULL!");
            SecurityProtocol instance = factory.CreateSecurityProtocol(target, null, /*listenerSecurityState*/null, /*isReturnLegSecurityRequired*/false, timeoutHelper.RemainingTime()); 
            if(instance != null)
                instance.Open(timeoutHelper.RemainingTime()); 
            return instance; 
        }
 
        public void CheckIfCompatibleNodeSettings(object other)
        {
            string mismatch = null;
            PeerSecurityManager that = other as PeerSecurityManager; 
            if (that == null)
                mismatch = PeerBindingPropertyNames.Security; 
            else if (this.authenticationMode != that.authenticationMode) 
                mismatch = PeerBindingPropertyNames.SecurityDotMode;
            else if(this.authenticationMode == PeerAuthenticationMode.None) 
                return ;
            else if(!this.tokenManager.Equals(that.tokenManager))
            {
                if(this.credManager != null) 
                    this.credManager.CheckIfCompatible(that.credManager);
                else 
                { 
                    DiagnosticUtility.DebugAssert(typeof(PeerSecurityCredentialsManager.PeerClientSecurityTokenManager).IsAssignableFrom(tokenManager.GetType()), "");
                    mismatch = PeerBindingPropertyNames.Credentials; 
                }
            }
            if(mismatch != null)
                PeerExceptionHelper.ThrowInvalidOperation_PeerConflictingPeerNodeSettings(mismatch); 
        }
 
        public bool HasCompatibleMessageSecurity(PeerSecurityManager that) 
        {
            return (this.MessageAuthentication == that.MessageAuthentication); 
        }

        public byte[] GetAuthenticator()
        { 
            if (authenticationMode != PeerAuthenticationMode.Password)
                return null; 
            if (authenticatorHash == null) 
            {
                lock (ThisLock) 
                {
                    if (authenticatorHash == null)
                    {
                        authenticatorHash = PeerSecurityHelpers.ComputeHash(credManager.Certificate, credManager.Password); 
                    }
                } 
            } 
            return authenticatorHash;
        } 


        public bool Authenticate(ServiceSecurityContext context, byte[] message)
        { 
            Claim claim = null;
            if (context == null) 
            { 
                return (authenticationMode == PeerAuthenticationMode.None);
            } 
            if (authenticationMode == PeerAuthenticationMode.Password)
            {
                if (!(context != null))
                { 
                    DiagnosticUtility.DebugAssert("No SecurityContext attached in security mode!");
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                } 
                claim = FindClaim(context);
                return PeerSecurityHelpers.Authenticate(claim, this.credManager.Password, message); 
            }
            else
            {
                if (message != null) 
                {
                    PeerExceptionHelper.ThrowInvalidOperation_UnexpectedSecurityTokensDuringHandshake(); 
                } 
                return true;
            } 
        }

        public static Claim FindClaim(ServiceSecurityContext context)
        { 
            Claim result = null;
            DiagnosticUtility.DebugAssert(context != null, "ServiceSecurityContext is null!"); 
            for (int i = 0 ; i < context.AuthorizationContext.ClaimSets.Count ; ++i) 
            {
                ClaimSet claimSet = context.AuthorizationContext.ClaimSets[i]; 
                IEnumerator claims = claimSet.FindClaims(ClaimTypes.Rsa, null).GetEnumerator();
                if(claims.MoveNext())
                {
                    result = claims.Current; 
                    break;
                } 
            } 
            return result;
        } 

        public void ApplyClientSecurity(ChannelFactory factory)
        {
            factory.Endpoint.Behaviors.Remove(); 
            if (authenticationMode != PeerAuthenticationMode.None)
            { 
                factory.Endpoint.Behaviors.Add(this.credManager.CloneForTransport()); 
            }
        } 

        public BindingElement GetSecurityBindingElement()
        {
            SslStreamSecurityBindingElement security = null; 
            if(this.AuthenticationMode != PeerAuthenticationMode.None)
            { 
                security = new SslStreamSecurityBindingElement(); 
                security.IdentityVerifier = new PeerIdentityVerifier();
                security.RequireClientCertificate = true; 
            }
            return security;
        }
 
        public PeerHashToken GetSelfToken()
        { 
            if (!(this.authenticationMode == PeerAuthenticationMode.Password)) 
            {
                DiagnosticUtility.DebugAssert("unexpected call to GetSelfToken"); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
            }
            return new PeerHashToken(this.credManager.Certificate, this.credManager.Password);
        } 

        public PeerHashToken GetExpectedTokenForClaim(Claim claim) 
        { 
            return new PeerHashToken(claim,this.password);
        } 

        public void OnNeighborOpened(object sender, EventArgs args)
        {
            IPeerNeighbor neighbor = sender as IPeerNeighbor; 
            EventHandler handler = this.OnNeighborAuthenticated;
            if (handler == null) 
            { 
                neighbor.Abort(PeerCloseReason.LeavingMesh, PeerCloseInitiator.LocalNode);
                return; 
            }
            if(this.authenticationMode == PeerAuthenticationMode.Password)
            {
                if (!(neighbor.Extensions.Find()==null)) 
                {
                    DiagnosticUtility.DebugAssert("extension already exists!"); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
                }
                PeerChannelAuthenticatorExtension extension = new PeerChannelAuthenticatorExtension(this, handler, args, this.MeshId); 
                neighbor.Extensions.Add(extension);
                if(neighbor.IsInitiator)
                    extension.InitiateHandShake();
            } 
            else
            { 
                neighbor.TrySetState(PeerNeighborState.Authenticated); 
                handler(sender, args);
            } 
        }

        public Message ProcessRequest(IPeerNeighbor neighbor, Message request)
        { 
            if(this.authenticationMode != PeerAuthenticationMode.Password || request == null)
            { 
                Abort(neighbor); 
                return null;
            } 
            PeerChannelAuthenticatorExtension extension = neighbor.Extensions.Find();
            Claim claim = FindClaim(ServiceSecurityContext.Current);
            if (!(extension != null && claim != null))
            { 
                DiagnosticUtility.DebugAssert("No suitable claim found in the context to do security negotiation!");
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false); 
            } 
            return extension.ProcessRst(request, claim);
        } 

        void Abort(IPeerNeighbor neighbor)
        {
            neighbor.Abort(PeerCloseReason.AuthenticationFailure, PeerCloseInitiator.LocalNode); 
        }
    } 
 
    class PeerSecurityCredentialsManager : SecurityCredentialsManager, IEndpointBehavior, IServiceBehavior
    { 
        SecurityTokenManager manager;
        PeerCredential credential;
        bool messageAuth;
        PeerAuthenticationMode mode = PeerAuthenticationMode.Password; 
        SelfSignedCertificate ssl;
        PeerSecurityManager parent; 
 
        public PeerSecurityCredentialsManager(SecurityTokenManager manager, PeerAuthenticationMode mode, bool messageAuth):base()
        { 
            this.manager = manager;
            this.mode = mode;
            this.messageAuth = messageAuth;
        } 

        public PeerSecurityCredentialsManager(PeerCredential credential, PeerAuthenticationMode mode, bool messageAuth):base() 
        { 
            this.credential = credential;
            this.mode = mode; 
            this.messageAuth = messageAuth;
        }

        public PeerSecurityManager Parent 
        {
            get 
            { 
                return this.parent;
            } 
            set
            {
                parent = value;
            } 
        }
 
        public override SecurityTokenManager CreateSecurityTokenManager() 
        {
            if(manager != null) 
                return new PeerClientSecurityTokenManager(this.parent, manager, mode, messageAuth);
            else
                return new PeerClientSecurityTokenManager(this.parent, credential, mode, messageAuth);
        } 

        public PeerSecurityCredentialsManager():base(){} 
 
        public PeerSecurityCredentialsManager CloneForTransport()
        { 
            PeerSecurityCredentialsManager cloner = new PeerSecurityCredentialsManager();
             if(this.credential != null)
                 cloner.credential = new PeerCredential(this.credential);
             cloner.mode = this.mode; 
             cloner.messageAuth = this.messageAuth;
             cloner.manager = this.manager; 
             cloner.parent = parent; 

             return cloner; 
        }
        internal PeerCredential Credential
        {
            get 
            {
                return this.credential; 
            } 
        }
        internal string Password 
        {
            get
            {
                if(this.credential != null) 
                    return credential.MeshPassword;
                ServiceModelSecurityTokenRequirement req = PeerClientSecurityTokenManager.CreateRequirement(SecurityTokenTypes.UserName); 
                UserNameSecurityTokenProvider tokenProvider = this.manager.CreateSecurityTokenProvider(req) as UserNameSecurityTokenProvider; 
                if(tokenProvider == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TokenProvider"); 
                UserNameSecurityToken token = tokenProvider.GetToken(ServiceDefaults.SendTimeout) as UserNameSecurityToken;
                if(token == null || String.IsNullOrEmpty(token.Password))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("password");
                return token.Password; 
            }
        } 
 
        internal X509Certificate2 Certificate
        { 
            get
            {
                X509Certificate2 result = null;
                if(mode == PeerAuthenticationMode.Password) 
                {
                    if(ssl != null) 
                        result = ssl.GetX509Certificate(); 
                }
                if(this.credential != null) 
                {
                    result = credential.Certificate;
                }
                else 
                {
                    ServiceModelSecurityTokenRequirement req = PeerClientSecurityTokenManager.CreateRequirement(SecurityTokenTypes.X509Certificate); 
                    X509SecurityTokenProvider tokenProvider = this.manager.CreateSecurityTokenProvider(req) as X509SecurityTokenProvider; 
                    if(tokenProvider == null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("TokenProvider"); 
                    X509SecurityToken token = tokenProvider.GetToken(ServiceDefaults.SendTimeout) as X509SecurityToken;
                    if(token == null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("token");
                    result = token.Certificate; 
                }
                if(result == null && mode == PeerAuthenticationMode.Password) 
                { 
                    ssl = this.parent.GetCertificate();
                    result = ssl.GetX509Certificate(); 
                }
                return result;
            }
        } 
        void IEndpointBehavior.Validate(ServiceEndpoint serviceEndpoint)
        { 
        } 

        void IEndpointBehavior.AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters) 
        {
            if (bindingParameters != null)
                bindingParameters.Add(this);
        } 

        void IEndpointBehavior.ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) 
        { 
        }
 
        void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
        {
        }
 
        void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        { 
        } 

        void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection parameters) 
        {
            if (parameters == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters"); 
            }
            parameters.Add(this); 
        } 

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase) 
        {
        }

        public override bool Equals(object other) 
        {
            PeerSecurityCredentialsManager that = other as PeerSecurityCredentialsManager ; 
            if(that == null) 
                return false;
            if(this.credential != null) 
            {
                return this.credential.Equals(that.credential, mode, messageAuth);
            }
            else 
            {
                return this.manager.Equals(that.manager); 
            } 
        }
 
        public void CheckIfCompatible(PeerSecurityCredentialsManager that)
        {
            if(that == null)
                PeerExceptionHelper.ThrowInvalidOperation_PeerConflictingPeerNodeSettings(PeerBindingPropertyNames.Credentials); 
            if(this.mode == PeerAuthenticationMode.None)
                return; 
            if(this.mode == PeerAuthenticationMode.Password) 
            {
                if(this.Password != that.Password) 
                    PeerExceptionHelper.ThrowInvalidOperation_PeerConflictingPeerNodeSettings(PeerBindingPropertyNames.Password);
            }
            if(!this.Certificate.Equals(that.Certificate))
                PeerExceptionHelper.ThrowInvalidOperation_PeerConflictingPeerNodeSettings(PeerBindingPropertyNames.Certificate); 
        }
 
        public override int GetHashCode() 
        {
            return base.GetHashCode(); 
        }

        public class PeerClientSecurityTokenManager : SecurityTokenManager
        { 
            SecurityTokenManager delegateManager;
            PeerCredential credential; 
            PeerAuthenticationMode mode; 
            bool messageAuth;
            SelfSignedCertificate ssc; 
            PeerSecurityManager parent;

            public PeerClientSecurityTokenManager(PeerSecurityManager parent, PeerCredential credential, PeerAuthenticationMode mode, bool messageAuth)
            { 
                this.credential = credential;
                this.mode = mode; 
                this.messageAuth = messageAuth; 
                this.parent = parent;
            } 

            public PeerClientSecurityTokenManager(PeerSecurityManager parent, SecurityTokenManager manager, PeerAuthenticationMode mode, bool messageAuth)
            {
                this.delegateManager = manager; 
                this.mode = mode;
                this.messageAuth = messageAuth; 
                this.parent = parent; 
            }
 
            internal static ServiceModelSecurityTokenRequirement CreateRequirement(string tokenType)
            {
                return CreateRequirement(tokenType, false);
            } 

            internal static ServiceModelSecurityTokenRequirement CreateRequirement(string tokenType, bool forMessageValidation) 
            { 
                InitiatorServiceModelSecurityTokenRequirement requirement = new InitiatorServiceModelSecurityTokenRequirement();
                requirement.TokenType = tokenType; 
                requirement.TransportScheme = PeerStrings.Scheme;
                if(forMessageValidation)
                    requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Message;
                else 
                    requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Transport;
 
                return requirement; 
            }
 
            UserNameSecurityTokenProvider GetPasswordTokenProvider()
            {
                if(delegateManager != null)
                { 
                    ServiceModelSecurityTokenRequirement requirement = CreateRequirement(SecurityTokenTypes.UserName);
                    UserNameSecurityTokenProvider tokenProvider = delegateManager.CreateSecurityTokenProvider(requirement) as UserNameSecurityTokenProvider; 
                    if(tokenProvider == null) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SecurityTokenManagerCannotCreateProviderForRequirement, requirement)));
                    return tokenProvider; 
                }
                else
                    return new UserNameSecurityTokenProvider(string.Empty, credential.MeshPassword);
            } 
            public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
            { 
                if (delegateManager != null) 
                    return delegateManager.CreateSecurityTokenSerializer(version);
                else 
                {
                    MessageSecurityTokenVersion wsVersion = version as MessageSecurityTokenVersion;
                    if (wsVersion != null)
                    { 
                        return new WSSecurityTokenSerializer(wsVersion.SecurityVersion, wsVersion.TrustVersion, wsVersion.SecureConversationVersion, wsVersion.EmitBspRequiredAttributes, null, null, null);
                    } 
                    else 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SecurityTokenManagerCannotCreateSerializerForVersion, version))); 
                    }
                }
            }
 
            public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
            { 
                ServiceModelSecurityTokenRequirement requirement = tokenRequirement as ServiceModelSecurityTokenRequirement; 
                if(requirement != null)
                { 
                    if(IsX509TokenRequirement(requirement))
                    {
                        if (IsForConnectionValidator(requirement))
                        { 
                            SecurityTokenProvider result = null;
                            if(this.ssc != null) 
                            { 
                                result = new X509SecurityTokenProvider(this.ssc.GetX509Certificate());
                            } 
                            else
                            {
                                if (this.delegateManager != null)
                                { 
                                    requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Transport;
                                    requirement.TransportScheme = PeerStrings.Scheme; 
                                    result = delegateManager.CreateSecurityTokenProvider(tokenRequirement); 
                                }
                                else 
                                {
                                    if (this.credential.Certificate != null)
                                        result = new X509SecurityTokenProvider(this.credential.Certificate);
                                } 
                            }
                            if (result == null && mode == PeerAuthenticationMode.Password) 
                            { 
                                this.ssc = parent.GetCertificate();
                                result = new X509SecurityTokenProvider(this.ssc.GetX509Certificate()); 
                            }

                            return result;
                        } 
                        else
                        { 
                            X509CertificateValidator validator; 
                            if (this.delegateManager != null)
                            { 
                                requirement.TransportScheme = PeerStrings.Scheme;
                                requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Message;
                                return delegateManager.CreateSecurityTokenProvider(tokenRequirement);
                            } 
                            if (!this.credential.MessageSenderAuthentication.TryGetCertificateValidator(out validator))
                                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("TokenType"); 
                            return new PeerX509TokenProvider(validator, this.credential.Certificate); 
                        }
                    } 
                    else if(IsPasswordTokenRequirement(requirement))
                    {
                        return GetPasswordTokenProvider();
                    } 
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("TokenType"); 
                    }
                } 
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenRequirement");
                } 

            } 
 
            bool IsPasswordTokenRequirement(ServiceModelSecurityTokenRequirement requirement)
            { 
                return ((requirement != null) && (requirement.TokenType == SecurityTokenTypes.UserName));
            }

            bool IsX509TokenRequirement(ServiceModelSecurityTokenRequirement requirement) 
            {
                return (requirement != null && requirement.TokenType == SecurityTokenTypes.X509Certificate); 
            } 

            bool IsForConnectionValidator(ServiceModelSecurityTokenRequirement requirement ) 
            {
                return (requirement.TransportScheme == "net.tcp" && requirement.SecurityBindingElement == null && requirement.MessageSecurityVersion == null);
            }
 
            public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
            { 
                ServiceModelSecurityTokenRequirement requirement = tokenRequirement as ServiceModelSecurityTokenRequirement; 
                outOfBandTokenResolver = null;
                if(requirement != null) 
                {
                    if(IsX509TokenRequirement(requirement))
                    {
                        if (mode == PeerAuthenticationMode.Password && IsForConnectionValidator(requirement)) 
                        {
                            return new X509SecurityTokenAuthenticator(X509CertificateValidator.None); 
                        } 
                        if(delegateManager != null)
                        { 
                            if (IsForConnectionValidator(requirement))
                            {
                                requirement.TransportScheme = PeerStrings.Scheme;
                                requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Transport; 
                            }
                            else 
                            { 
                                requirement.TransportScheme = PeerStrings.Scheme;
                                requirement.Properties[SecurityTokenRequirement.PeerAuthenticationMode] = SecurityMode.Message; 
                            }
                            return delegateManager.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
                        }
                        else 
                        {
                            X509CertificateValidator validator = null; 
                            if(IsForConnectionValidator(requirement)) 
                            {
                                if(this.mode == PeerAuthenticationMode.MutualCertificate) 
                                {
                                    if(!this.credential.PeerAuthentication.TryGetCertificateValidator(out validator))
                                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SecurityTokenManagerCannotCreateProviderForRequirement, requirement)));
                                } 
                                else
                                    validator = X509CertificateValidator.None; 
                            } 
                            else
                            { 
                                if(!this.credential.MessageSenderAuthentication.TryGetCertificateValidator(out validator))
                                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.SecurityTokenManagerCannotCreateProviderForRequirement, requirement)));

                            } 
                            return new X509SecurityTokenAuthenticator(validator);
                        } 
                    } 
                    else
                    { 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("tokenRequirement");
                    }
                }
                else 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenRequirement"); 
                } 
            }
 
            public override bool Equals(object other)
            {
                PeerClientSecurityTokenManager that = other as PeerClientSecurityTokenManager;
                if(that == null) 
                    return false;
                if(this.credential != null) 
                { 
                    if(that.credential == null || !this.credential.Equals(that.credential,this.mode,this.messageAuth))
                        return false; 
                    return true;
                }
                else
                { 
                    return this.delegateManager.Equals(that.delegateManager);
                } 
            } 

            internal bool HasCompatibleMessageSecuritySettings(PeerClientSecurityTokenManager that) 
            {
                if(this.credential != null)
                    return (that.credential != null && this.credential.Equals(that.credential));
                else 
                    return this.delegateManager.Equals(that.delegateManager);
            } 
 
            public override int GetHashCode()
            { 
                if(credential != null)
                    return credential.GetHashCode();
                else if(delegateManager != null)
                    return delegateManager.GetHashCode(); 
                else
                    return 0; 
            } 

        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK