SspiNegotiationTokenProvider.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 / Security / SspiNegotiationTokenProvider.cs / 1 / SspiNegotiationTokenProvider.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Security
{ 
    using System.IdentityModel.Claims;
    using System.ServiceModel; 
    using System.IdentityModel.Policy; 
    using System.IdentityModel.Selectors;
    using System.IdentityModel.Tokens; 
    using System.Security.Principal;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceModel.Security.Tokens; 
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.ServiceModel.Channels; 
    using System.Xml;
    using System.Net; 
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.Runtime.Serialization; 
    using System.ServiceModel.Diagnostics;
 
    using CanonicalizationDriver = System.IdentityModel.CanonicalizationDriver; 
    using Psha1DerivedKeyGenerator = System.IdentityModel.Psha1DerivedKeyGenerator;
    using SafeFreeCredentials = System.IdentityModel.SafeFreeCredentials; 

    abstract class SspiNegotiationTokenProvider : NegotiationTokenProvider
    {
        bool negotiateTokenOnOpen; 

        protected SspiNegotiationTokenProvider() 
            : base() 
        {
        } 

        public bool NegotiateTokenOnOpen
        {
            get 
            {
                return this.negotiateTokenOnOpen; 
            } 
            set
            { 
                this.CommunicationObject.ThrowIfDisposedOrImmutable();
                this.negotiateTokenOnOpen = value;
            }
        } 

        // SspiNegotiationTokenProvider abstract methods 
        protected abstract ReadOnlyCollection ValidateSspiNegotiation(ISspiNegotiation sspiNegotiation); 
        public abstract XmlDictionaryString NegotiationValueType { get; }
 
        public override void OnOpen(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            this.EnsureEndpointAddressDoesNotRequireEncryption(this.TargetAddress); 
            base.OnOpen(timeoutHelper.RemainingTime());
            if (this.negotiateTokenOnOpen) 
            { 
                this.DoNegotiation(timeoutHelper.RemainingTime());
            } 
        }

        protected override IChannelFactory GetNegotiationChannelFactory(IChannelFactory transportChannelFactory, ChannelBuilder channelBuilder)
        { 
            return transportChannelFactory;
        } 
 
        // helper methods
        void ValidateIncomingBinaryNegotiation(BinaryNegotiation incomingNego) 
        {
            incomingNego.Validate(NegotiationValueType);
        }
 
        static void AddToDigest(HashAlgorithm negotiationDigest, Stream stream)
        { 
            stream.Flush(); 
            stream.Seek(0, SeekOrigin.Begin);
            CanonicalizationDriver canonicalizer = new CanonicalizationDriver(); 
            canonicalizer.SetInput(stream);
            byte[] canonicalizedData = canonicalizer.GetBytes();
            lock (negotiationDigest)
            { 
                negotiationDigest.TransformBlock(canonicalizedData, 0, canonicalizedData.Length, canonicalizedData, 0);
            } 
        } 

        static void AddToDigest(SspiNegotiationTokenProviderState sspiState, RequestSecurityToken rst) 
        {
            MemoryStream stream = new MemoryStream();
            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
            rst.WriteTo(writer); 
            writer.Flush();
            AddToDigest(sspiState.NegotiationDigest, stream); 
        } 

        void AddToDigest(SspiNegotiationTokenProviderState sspiState, RequestSecurityTokenResponse rstr, bool wasReceived, bool isFinalRstr) 
        {
            MemoryStream stream = new MemoryStream();
            XmlDictionaryWriter writer = XmlDictionaryWriter.CreateTextWriter(stream);
            if (!wasReceived) 
            {
                rstr.WriteTo(writer); 
            } 
            else
            { 
                if (!isFinalRstr)
                {
                    rstr.RequestSecurityTokenResponseXml.WriteTo(writer);
                } 
                else
                { 
                    XmlElement rstrClone = (XmlElement) rstr.RequestSecurityTokenResponseXml.CloneNode(true); 
                    List nodesToRemove = new List(2);
                    for (int i = 0; i < rstrClone.ChildNodes.Count; ++i) 
                    {
                        XmlNode child = (rstrClone.ChildNodes[i]);
                        if (this.StandardsManager.TrustDriver.IsRequestedSecurityTokenElement(child.LocalName, child.NamespaceURI))
                        { 
                            nodesToRemove.Add(child);
                        } 
                        else if (this.StandardsManager.TrustDriver.IsRequestedProofTokenElement(child.LocalName, child.NamespaceURI)) 
                        {
                            nodesToRemove.Add(child); 
                        }
                    }
                    for (int i = 0; i < nodesToRemove.Count; ++i)
                    { 
                        rstrClone.RemoveChild(nodesToRemove[i]);
                    } 
                    rstrClone.WriteTo(writer); 
                }
            } 
            writer.Flush();
            AddToDigest(sspiState.NegotiationDigest, stream);
        }
 
        static bool IsCorrectAuthenticator(SspiNegotiationTokenProviderState sspiState, byte[] proofKey, byte[] serverAuthenticator)
        { 
            byte[] negotiationHash; 
            lock (sspiState.NegotiationDigest)
            { 
                sspiState.NegotiationDigest.TransformFinalBlock(CryptoHelper.EmptyBuffer, 0, 0);
                negotiationHash = sspiState.NegotiationDigest.Hash;
            }
            Psha1DerivedKeyGenerator generator = new Psha1DerivedKeyGenerator(proofKey); 
            byte[] clientAuthenticator = generator.GenerateDerivedKey(SecurityUtils.CombinedHashLabel, negotiationHash, SecurityNegotiationConstants.NegotiationAuthenticatorSize, 0);
            if (clientAuthenticator.Length != serverAuthenticator.Length) 
            { 
                return false;
            } 
            for (int i = 0; i < clientAuthenticator.Length; ++i)
            {
                if (clientAuthenticator[i] != serverAuthenticator[i])
                { 
                    return false;
                } 
            } 
            return true;
        } 

        BodyWriter PrepareRst(SspiNegotiationTokenProviderState sspiState, byte[] outgoingBlob)
        {
            RequestSecurityToken rst = new RequestSecurityToken(this.StandardsManager); 
            rst.Context = sspiState.Context;
            rst.TokenType = this.StandardsManager.SecureConversationDriver.TokenTypeUri; 
            rst.SetBinaryNegotiation(new BinaryNegotiation(NegotiationValueType, outgoingBlob)); 
            rst.KeySize = this.SecurityAlgorithmSuite.DefaultSymmetricKeyLength;
            rst.MakeReadOnly(); 
            AddToDigest(sspiState, rst);
            return rst;
        }
 
        BodyWriter PrepareRstr(SspiNegotiationTokenProviderState sspiState, byte[] outgoingBlob)
        { 
            RequestSecurityTokenResponse rstr = new RequestSecurityTokenResponse(this.StandardsManager); 
            rstr.Context = sspiState.Context;
            rstr.SetBinaryNegotiation(new BinaryNegotiation(NegotiationValueType, outgoingBlob)); 
            rstr.MakeReadOnly();
            AddToDigest(sspiState, rstr, false, false);
            return rstr;
        } 

        protected override BodyWriter GetFirstOutgoingMessageBody(SspiNegotiationTokenProviderState sspiState, out MessageProperties messageProperties) 
        { 
            messageProperties = null;
            ISspiNegotiation sspiNegotiation = sspiState.SspiNegotiation; 
            byte[] outgoingBlob = sspiNegotiation.GetOutgoingBlob(null);
            if (outgoingBlob == null && sspiNegotiation.IsCompleted == false)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoBinaryNegoToSend))); 
            }
            return PrepareRst(sspiState, outgoingBlob); 
        } 

        protected override BodyWriter GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState) 
        {
            try
            {
                ThrowIfFault(incomingMessage, this.TargetAddress); 
            }
            catch (FaultException fault) 
            { 
                if (fault.Code.IsSenderFault)
                { 
                    if (fault.Code.SubCode.Name == TrustApr2004Strings.FailedAuthenticationFaultCode || fault.Code.SubCode.Name == TrustFeb2005Strings.FailedAuthenticationFaultCode)
                        throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.AuthenticationOfClientFailed), fault), incomingMessage);

                    throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.FailedSspiNegotiation), fault), incomingMessage); 
                }
                else 
                { 
                    throw;
                } 
            }
            RequestSecurityTokenResponse negotiationRstr = null;
            RequestSecurityTokenResponse authenticatorRstr = null;
            XmlDictionaryReader bodyReader = incomingMessage.GetReaderAtBodyContents(); 
            using (bodyReader)
            { 
                if (this.StandardsManager.TrustDriver.IsAtRequestSecurityTokenResponseCollection(bodyReader)) 
                {
                    RequestSecurityTokenResponseCollection rstrCollection = this.StandardsManager.TrustDriver.CreateRequestSecurityTokenResponseCollection(bodyReader); 
                    using (IEnumerator enumerator = rstrCollection.RstrCollection.GetEnumerator())
                    {
                        enumerator.MoveNext();
                        negotiationRstr = enumerator.Current; 
                        if (enumerator.MoveNext())
                        { 
                            authenticatorRstr = enumerator.Current; 
                        }
                    } 
                    if (authenticatorRstr == null)
                    {
                        throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.AuthenticatorNotPresentInRSTRCollection)), incomingMessage);
                    } 
                    else if (authenticatorRstr.Context != negotiationRstr.Context)
                    { 
                        throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.RSTRAuthenticatorHasBadContext)), incomingMessage); 
                    }
                    AddToDigest(sspiState, negotiationRstr, true, true); 
                }
                else if (this.StandardsManager.TrustDriver.IsAtRequestSecurityTokenResponse(bodyReader))
                {
                    negotiationRstr = RequestSecurityTokenResponse.CreateFrom(this.StandardsManager, bodyReader); 
                    AddToDigest(sspiState, negotiationRstr, true, false);
                } 
                else 
                {
                    this.StandardsManager.TrustDriver.OnRSTRorRSTRCMissingException(); 
                }
                incomingMessage.ReadFromBodyContentsToEnd(bodyReader);
            }
            if (negotiationRstr.Context != sspiState.Context) 
            {
                throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.BadSecurityNegotiationContext)), incomingMessage); 
            } 
            BinaryNegotiation incomingBinaryNego = negotiationRstr.GetBinaryNegotiation();
            byte[] incomingBlob; 
            if (incomingBinaryNego != null)
            {
                ValidateIncomingBinaryNegotiation(incomingBinaryNego);
                incomingBlob = incomingBinaryNego.GetNegotiationData(); 
            }
            else 
            { 
                incomingBlob = null;
            } 
            BodyWriter nextMessageBody;
            if (incomingBlob == null && sspiState.SspiNegotiation.IsCompleted == false)
            {
                throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoBinaryNegoToReceive)), incomingMessage); 
            }
            else if (incomingBlob == null && sspiState.SspiNegotiation.IsCompleted == true) 
            { 
                // the incoming RSTR must have the negotiated token
                OnNegotiationComplete(sspiState, negotiationRstr, authenticatorRstr); 
                nextMessageBody = null;
            }
            else
            { 
                // we got an incoming blob. Process it and see if there is an outgoing blob
                byte[] outgoingBlob = sspiState.SspiNegotiation.GetOutgoingBlob(incomingBlob); 
                if (outgoingBlob == null && sspiState.SspiNegotiation.IsCompleted == false) 
                {
                    throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoBinaryNegoToSend)), incomingMessage); 
                }
                else if (outgoingBlob == null && sspiState.SspiNegotiation.IsCompleted == true)
                {
                    // the incoming RSTR had the last blob. It must have the token too 
                    this.OnNegotiationComplete(sspiState, negotiationRstr, authenticatorRstr);
                    nextMessageBody = null; 
                } 
                else
                { 
                    nextMessageBody = PrepareRstr(sspiState, outgoingBlob);
                }
            }
            return nextMessageBody; 
        }
 
        void OnNegotiationComplete(SspiNegotiationTokenProviderState sspiState, RequestSecurityTokenResponse negotiationRstr, RequestSecurityTokenResponse authenticatorRstr) 
        {
            ISspiNegotiation sspiNegotiation = sspiState.SspiNegotiation; 
            ReadOnlyCollection authorizationPolicies = ValidateSspiNegotiation(sspiNegotiation);
            // the negotiation has completed successfully - the service token needs to be extracted from the
            // negotiationRstr
            SecurityTokenResolver tokenResolver = new SspiSecurityTokenResolver(sspiNegotiation); 
            GenericXmlSecurityToken serviceToken = negotiationRstr.GetIssuedToken(tokenResolver, EmptyReadOnlyCollection.Instance,
                SecurityKeyEntropyMode.ServerEntropy, null, this.SecurityContextTokenUri, authorizationPolicies, 0, false); 
            if (serviceToken == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoServiceTokenReceived))); 
            }
            WrappedKeySecurityToken wrappedToken = (serviceToken.ProofToken as WrappedKeySecurityToken);
            if (wrappedToken == null || wrappedToken.WrappingAlgorithm != sspiNegotiation.KeyEncryptionAlgorithm)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.ProofTokenWasNotWrappedCorrectly)));
            } 
            byte[] proofKey = wrappedToken.GetWrappedKey(); 
            if (authenticatorRstr == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.RSTRAuthenticatorNotPresent)));
            }
            byte[] serverAuthenticator = authenticatorRstr.GetAuthenticator();
            if (serverAuthenticator == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.RSTRAuthenticatorNotPresent))); 
            } 
            if (!IsCorrectAuthenticator(sspiState, proofKey, serverAuthenticator))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.RSTRAuthenticatorIncorrect)));
            }
            sspiState.SetServiceToken(serviceToken);
        } 

        class SspiSecurityTokenResolver : SecurityTokenResolver, ISspiNegotiationInfo 
        { 
            ISspiNegotiation sspiNegotiation;
 
            public SspiSecurityTokenResolver(ISspiNegotiation sspiNegotiation)
            {
                this.sspiNegotiation = sspiNegotiation;
            } 

            public ISspiNegotiation SspiNegotiation 
            { 
                get { return this.sspiNegotiation; }
            } 

            protected override bool TryResolveTokenCore(SecurityKeyIdentifier keyIdentifier, out SecurityToken token)
            {
                token = null; 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
            } 
 
            protected override bool TryResolveTokenCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityToken token)
            { 
                token = null;
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
            }
 
            protected override bool TryResolveSecurityKeyCore(SecurityKeyIdentifierClause keyIdentifierClause, out SecurityKey key)
            { 
                key = null; 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotImplementedException());
            } 
        }
    }

    class SspiIssuanceChannelParameter 
    {
        bool getTokenOnOpen; 
        SafeFreeCredentials credentialsHandle; 

        public SspiIssuanceChannelParameter(bool getTokenOnOpen, SafeFreeCredentials credentialsHandle) 
        {
            this.getTokenOnOpen = getTokenOnOpen;
            this.credentialsHandle = credentialsHandle;
        } 

        public bool GetTokenOnOpen 
        { 
            get { return this.getTokenOnOpen; }
        } 

        public SafeFreeCredentials CredentialsHandle
        {
            get { return this.credentialsHandle; } 
        }
    } 
 

    interface ISspiNegotiationInfo 
    {
        ISspiNegotiation SspiNegotiation { get; }
    }
} 

// 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