GetBrowserTokenRequest.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 / infocard / Service / managed / Microsoft / InfoCards / GetBrowserTokenRequest.cs / 2 / GetBrowserTokenRequest.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
#pragma warning disable 1634, 1691      // unknown message, unknown pragma
 
namespace Microsoft.InfoCards
{ 
    using System; 
    using System.Collections.ObjectModel;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Globalization;
    using System.IdentityModel.Selectors;
    using System.IdentityModel.Tokens; 
    using System.IO;
    using System.Runtime.InteropServices; 
    using System.Runtime.Serialization; 
    using System.Security;
    using System.Security.Cryptography; 
    using System.Security.Cryptography.X509Certificates;
    using System.Security.Principal;
    using System.ServiceModel;
    using System.ServiceModel.Security; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description; 
    using System.ServiceModel.Security.Tokens; 
    using System.Text;
    using System.Threading; 
    using System.Xml;
    using System.Net.Security;
    using System.Net;
    using System.ServiceModel.Dispatcher; 

    using Microsoft.InfoCards.Diagnostics; 
    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; 

    class GetBrowserTokenRequest :GetTokenRequest 
    {
        //
        // Matches constant in icardie.idl.
        // 
        public const int POLICY_V1 = 1;
        public const int POLICY_V2 = 2; 
 
        GetBrowserTokenParameters m_params;
        ServiceEndpoint m_svcEpr; 
        byte[ ] m_rawToken;
        SelfIssuedAuthProofToken m_proofToken;
        ProtocolProfile m_protocolProfile;
 
        public GetBrowserTokenRequest(
                            Process callingProcess, 
                            WindowsIdentity callingIdentity, 
                            InfoCardUIAgent uiAgent,
                            IntPtr rpcHandle, 
                            Stream inArgs,
                            Stream outArgs )
            : base( callingProcess, callingIdentity, uiAgent, rpcHandle, inArgs, outArgs )
        { 
            m_protocolProfile = new ProtocolProfile();
        } 
 
        //
        // Summary: 
        // Given an Issuer binding determines whether that issuer is a managed card provider.
        //
        //
        static bool IsReferralToManagedIssuer( Binding issuerBinding ) 
        {
            bool bRetVal = false; 
 
            if( null != issuerBinding )
            { 
                //
                // If the UseManagedPresentationBindingElement is present then this is a ManagedCardProvider.
                //
                UseManagedPresentationBindingElement useManagedPresentationBE = 
                    issuerBinding.CreateBindingElements().Find();
 
                if( null != useManagedPresentationBE ) 
                {
                    bRetVal = true; 
                }
            }

            return bRetVal; 
        }
 
        // 
        // Summary:
        //  Marshal all incoming arguments. 
        //
        protected override void OnMarshalInArgs()
        {
            BinaryReader reader = new InfoCardBinaryReader( InArgs, Encoding.Unicode ); 

 
            try 
            {
                m_params = new GetBrowserTokenParameters(); 

                int versionFlags = reader.ReadInt32();

                // 
                // Error out immediately if version does not match
                // 
                if( POLICY_V1 != versionFlags && POLICY_V2 != versionFlags ) 
                {
                    throw IDT.ThrowHelperError( 
                                new InfoCardArgumentException( SR.GetString( SR.InvalidFlagsSpecified ) ) );
                }

                m_params.Load( reader, versionFlags ); 

                // 
                // Cases 
                //
                // Number   Issuer URL       Issuer MEX       Result 
                // 1        null             null             Invoke Infocard with null issuer
                // 2        self             null             Invoke infocard with issuer self
                // 3        anonymous        null             Invoke infocard with issuer anonymous
                // 4        X                null             Invoke infocard with issuer X 
                // 5        null             foo              Throw an exception
                // 6        self             foo              Throw an exception 
                // 7        anonymous        foo              Throw an exception 
                // 8        X                foo              Retrieve endpoints from foo. If none of the endpoints
                //                                            match X ( and require issued token ), 
                //                                            then invoke infocard with issuer X.
                //

 
                if( null == m_params.Issuer.PolicyUrl )
                { 
 
                    //
                    // Cases 1 - 4, issuer = null/self/anonymous/X, mex = null 
                    //
                    CreateInfoCardPolicyFromBrowserParams();

                } 
                else
                { 
 
                    if( Utility.CompareUri( XmlNames.WSIdentity.SelfIssuerUriValue, m_params.Issuer.Address )
                     || Utility.CompareUri( XmlNames.WSIdentity.AnonymousIssuerUriValue, m_params.Issuer.Address ) ) 
                    {
                        //
                        // Cases 6 -7, issuer = self/anonymous, mex = foo
                        // 
                        throw IDT.ThrowHelperError(
                                new InfoCardArgumentException( 
                                    SR.GetString( SR.SelfOrAnonIssuerNotAllowedWhenMexSpecified, 
                                                  m_params.Issuer.Address ) ) );
                    } 
                    else if( null == m_params.Issuer.Address )
                    {
                        //
                        // Case 5 - Issuer = null, mex = foo 
                        //
                        throw IDT.ThrowHelperError( 
                                new InfoCardArgumentException( 
                                    SR.GetString( SR.NoIssuerSpecifiedWhenMexIsSpecified ) ) );
                    } 
                    else
                    {
                        //
                        // Case 8 - issuer = X, mex = foo 
                        //
                        ServiceEndpoint svcEpr = null; 
                        ServiceEndpointCollection serviceEndpoints = null; 

                        try 
                        {
                            serviceEndpoints = GetServiceEndpointCollection( m_params.Issuer.Address, m_params.Issuer.PolicyUrl );
                        }
                        catch( Exception e ) 
                        {
                            if( IDT.IsFatal( e ) ) 
                            { 
                                throw;
                            } 
                            serviceEndpoints = null;
                        }

                        if( null != serviceEndpoints && null != serviceEndpoints.Find( m_params.Issuer.Address ) ) 
                        {
 
                            svcEpr = serviceEndpoints.Find( m_params.Issuer.Address ); 

                            if( !IsReferralToManagedIssuer( svcEpr.Binding ) && 
                                DoesEndpointSatisfySecurityRequirements( svcEpr ) &&
                                DoesEndpointSatisfyIssuedTokenRequirements( svcEpr ) )
                            {
                                if (Uri.UriSchemeHttps != m_params.Recipient.Address.Scheme) 
                                {
                                    throw IDT.ThrowHelperError(new InfoCardArgumentException(SR.GetString(SR.RPStsWithNoSSLFailure))); 
                                } 
                                //
                                // If issuer = X and mex = Y and the endpoint found at Y 
                                // that matches X has the isManaged flag then it is an ipsts
                                // i.e. the federated chain is really a managed card case
                                //
                                m_svcEpr = svcEpr; 

                                // 
                                // Examine the SecurityBindingElement of our epr to identify the version of 
                                // WS-Trust to use to communicate to this STS.
                                // The version information is stored in m_protocolProfile, which will be used in 
                                // CreateInfoCardPolicyFromBrowserParams() and further on in OnProcess().
                                //
                                BindingElementCollection bindingElements = svcEpr.Binding.CreateBindingElements();
 
                                SecurityBindingElement sbe = bindingElements.Find();
 
                                // 
                                // This should never be null as DoesEndpointSatisfyIssuedTokenRequirements would have failed
                                // 
                                IDT.Assert( null != sbe, "No SecurityBindingElement was found in the BindingElementCollection" );

                                if( TrustVersion.WSTrust13 == sbe.MessageSecurityVersion.TrustVersion )
                                { 
                                    //
                                    // Only handle the WSTrust13 case; Feb2005 is the default. 
                                    // 
                                    m_protocolProfile.WSTrust = XmlNames.WSTrustOasis2007.Instance;
                                } 
                            }
                        }

                        CreateInfoCardPolicyFromBrowserParams(); 
                    }
                } 
 
            }
            catch( InfoCardBaseException ) 
            {
                throw;
            }
            catch( Exception e ) 
            {
                if( IDT.IsFatal( e ) ) 
                { 
                    throw;
                } 
                throw IDT.ThrowHelperError(
                                new InfoCardArgumentException( SR.GetString( SR.ServiceInvalidArguments ), e ) );
            }
 
        }
 
        // 
        //
        // Summary 
        //   Create an 'InfoCardPolicy' from the browser parameters to prime the request for infocard invocation
        //
        void CreateInfoCardPolicyFromBrowserParams()
        { 
            CardSpacePolicyElement policyElement = m_params.CreatePolicyElement( m_protocolProfile );
 
            // 
            // Set the policy usage context to browser in this case since we are dealing with incoming
            // parameters from the browser. 
            //
            InfoCardPolicy policy = PolicyFactory.CreatePolicyForGetBrowserTokenRequest(
                policyElement,
                policyElement.PolicyNoticeLink, 
                (uint)policyElement.PolicyNoticeVersion,
                RecipientIdentity.CreateIdentity( m_params.Recipient.CreateEndpointAddress(), true ), 
                PolicyUsageContext.Browser ); //recipient of the token is m_params.Recipient 

            policy.Validate(); 
            base.Policy = policy;
        }

        // 
        // Summary:
        // Given a service endpoint, verify if it fulfills the issued token requirements 
        // 
        // Parameters:
        //   serviceEndpoint - The endpoints to be filtered 
        //
        // Returns:
        //  True if it satisfies the requirements
        // 
        private bool DoesEndpointSatisfyIssuedTokenRequirements( ServiceEndpoint serviceEndpoint )
        { 
            if( null != serviceEndpoint ) 
            {
                bool ignoreDisallowedStpDetected = false; 
                IssuedSecurityTokenParameters param = TryGetNextStsIssuedTokenParameters(
                    serviceEndpoint.Binding.CreateBindingElements(),
                    ref ignoreDisallowedStpDetected );
 
                if( null != param )
                { 
                    return true; 
                }
            } 
            return false;
        }

        // 
        // Summary:
        // Given a service endpoint, verify if it fulfills the security requirements 
        // 
        // Parameters:
        //   serviceEndpoint - The endpoints to be filtered 
        //
        // Returns:
        //  True if it satisfies the requirements
        // 
        private bool DoesEndpointSatisfySecurityRequirements( ServiceEndpoint serviceEndpoint )
        { 
 
            if( null != serviceEndpoint )
            { 
                //
                // check if endpoint has required security
                //
                ISecurityCapabilities capabilities = serviceEndpoint.Binding.GetProperty( new BindingParameterCollection() ); 
                if( ( null != capabilities
                    && capabilities.SupportedRequestProtectionLevel == System.Net.Security.ProtectionLevel.EncryptAndSign 
                    && capabilities.SupportedResponseProtectionLevel == System.Net.Security.ProtectionLevel.EncryptAndSign 
                    && capabilities.SupportsClientAuthentication
                    && capabilities.SupportsServerAuthentication ) ) 
                {
                    return true;
                }
 
            }
            return false; 
        } 

        // 
        // Summary:
        //  Marshal outgoing token.
        //
        protected override void OnMarshalOutArgs() 
        {
            BinaryWriter writer = new BinaryWriter( OutArgs, Encoding.Unicode ); 
            try 
            {
                try 
                {
                    writer.Write( m_rawToken.Length );
                    writer.Write( m_rawToken, 0, m_rawToken.Length );
 
                }
                finally 
                { 
                    Array.Clear( m_rawToken, 0, m_rawToken.Length );
                } 
            }
            catch( Exception e )
            {
                if( IDT.IsFatal( e ) ) 
                {
                    throw; 
                } 
                throw IDT.ThrowHelperError(
                                new TrustExchangeException( SR.GetString( SR.ServiceFailedToWriteToken ), e ) ); 
            }

        }
 

        // 
        // Summary: 
        //  Handle the Onprocess event.
        // 
        protected override void OnProcess()
        {
            try
            { 
                if( null == m_svcEpr )
                { 
                    // 
                    // Didn't do mex, so assume IP/STS or self-issued STS.
                    // 

                    //
                    // if null == m_svcEpr, then it is a self issued case.
                    // In that case, we have already initialized all the policy. 
                    //
 
                    // 
                    // Don't populate the PolicyAppliesTo - so
                    // whether we send AppliesTo or not will depend 
                    // on card.RequireAppliesTo
                    //

 
                    base.OnProcess();
 
                    if( null != base.ProcessingException ) 
                    {
                        throw IDT.ThrowHelperError( base.ProcessingException ); 
                    }
                    using( MemoryStream stream = new MemoryStream() )
                    {
                        XmlWriterSettings settings = new XmlWriterSettings(); 
                        settings.CloseOutput = false;
                        settings.Encoding = Encoding.UTF8; 
                        settings.OmitXmlDeclaration = true; 

                        using( XmlWriter writer = XmlWriter.Create( stream, settings ) ) 
                        {
                            base.Token.ProtectedToken.WriteTo( writer );
                        }
 
                        //
                        // Strip the UTF-8 BOM 
                        // 
                        m_rawToken = new byte[ stream.Length - 3 ];
                        Array.Copy( 
                                stream.GetBuffer(),
                                3,
                                m_rawToken,
                                0, 
                                Convert.ToInt32( stream.Length - 3 ) );
                    } 
                } 
                else
                { 
                    //
                    // Did the mex this is the Resource STS case.
                    // Imagine we are writing an Indigo client application.
                    // The function we are trying to invoke remotely is ProcessRequestSecurityToken 
                    // Indigo steps in to build the chain, which will eventually show UI
                    // so that the user can select a self-issued or managed card. 
                    // 

                    CreateIssuedTokenClientCredentials creds = CreateClientCredentials( m_svcEpr ); 
                    //
                    // Disallow NTLM. This is necessary for http with message security case.
                    //
                    // As for transport security, we're manually turning off client auth for all legs 
                    // except the IP/STS leg
                    // 
                    creds.Windows.AllowNtlm = false; 

                    Binding enforcedBinding = FedChainUpdateProxyAndRestrictTransportBindingWrapper( m_svcEpr.Binding, this.UserProxy ); 

                    using( ChannelFactory channelFactory = new ChannelFactory(
                            enforcedBinding,
                            m_svcEpr.Address ) ) 
                    {
 
                        channelFactory.Endpoint.Binding.OpenTimeout = new TimeSpan( 5, 0, 0 ); // 5 hours 
                        channelFactory.Endpoint.Binding.SendTimeout = new TimeSpan( 5, 0, 0 ); // 5 hours
                        channelFactory.Endpoint.Binding.ReceiveTimeout = new TimeSpan( 5, 0, 0 ); // 5 hours 
                        channelFactory.Endpoint.Binding.CloseTimeout = new TimeSpan( 5, 0, 0 ); // 5 hours
                        channelFactory.Endpoint.Behaviors.Remove();
                        channelFactory.Endpoint.Behaviors.Add( creds );
 
                        IDT.Assert( false == channelFactory.Credentials.Windows.AllowNtlm, "Should be false" );
 
                        // 
                        // Create a channel and process do the RST/RSTR - do the chaining.
                        // Note no tokens will be released to any STS in the federation chain 
                        // as a result of calling CreateChannel.
                        //

                        // 
                        // Note: CreateChannel eventually calls our CreateIssuedTokenClientCredentials.ApplyClientBehavior
                        // override, which will throw if the scenario is NOT CardSpace relevant. 
                        // 

                        ISts sts = channelFactory.CreateChannel(); 


                        if( null == Policy )
                        { 
                            //
                            // We need a valid InfoCardPolicy to retrieve the raw XML string for the SecondaryParameters element 
                            // 
                            CreateInfoCardPolicyFromBrowserParams();
                        } 

                        RequestSecurityTokenParameters rstParams = new RequestSecurityTokenParameters( m_svcEpr.Binding.MessageVersion.Addressing,
                                                                                            m_params,
                                                                                            m_protocolProfile, 
                                                                                            Policy,
                                                                                            true ); 
 
                        RequestSecurityToken rst = new RequestSecurityTokenForGetBrowserToken( rstParams );
 
                        Message rstMsg = Message.CreateMessage(
                                            m_svcEpr.Binding.MessageVersion,
                                            m_protocolProfile.WSTrust.RequestSecurityTokenAction,
                                            rst ); 

                        // 
                        // This will invoke the base.Process method via the custom callback provided 
                        //  to the InfoCardClientCredentials.
                        // 
                        Message rstrMsg = null;

                        if( XmlNames.WSSpecificationVersion.WSTrustXmlSoap2005 == m_protocolProfile.WSTrust.Version )
                        { 
                            ExecuteCancelable(
                                    delegate { rstrMsg = sts.ProcessRequestSecurityTokenFeb2005( rstMsg ); }, 
                                    delegate { channelFactory.Abort(); } ); 
                        }
                        else if( XmlNames.WSSpecificationVersion.WSTrustOasis2007 == m_protocolProfile.WSTrust.Version ) 
                        {
                            ExecuteCancelable(
                                    delegate { rstrMsg = sts.ProcessRequestSecurityTokenWSTrust13( rstMsg ); },
                                    delegate { channelFactory.Abort(); } ); 
                        }
                        else 
                        { 
                            IDT.Assert( false, "Unsupported version of WS-Trust detected" );
                        } 

                        IDT.Assert( null != rstrMsg, "Should have thrown before this if message is null" );

                        WSIdentityFaultException.ThrowIfFaultMessage( rstrMsg, CultureInfo.GetCultureInfo( this.UserLanguage ) ); 

                        using( XmlReader reader = rstrMsg.GetReaderAtBodyContents() ) 
                        { 
                            using( MemoryStream stream = new MemoryStream() )
                            { 
                                XmlWriterSettings settings = new XmlWriterSettings();
                                settings.CloseOutput = false;
                                settings.Encoding = Encoding.UTF8;
                                settings.OmitXmlDeclaration = true; 

                                using( XmlWriter writer = XmlWriter.Create( stream, settings ) ) 
                                { 
                                    WriteRequestedTokenFrom( reader, writer );
                                } 

                                //
                                // Strip the UTF-8 BOM
                                // 
                                m_rawToken = new byte[ stream.Length - 3 ];
                                Array.Copy( 
                                        stream.GetBuffer(), 
                                        3,
                                        m_rawToken, 
                                        0,
                                        Convert.ToInt32( stream.Length - 3 ) );
                            }
                        } 

                        // 
                        // Teardown the factory. 
                        //
                        channelFactory.Close(); 
                    }
                }
            }
            catch( InfoCardBaseException ) 
            {
                throw; 
            } 
            catch( Exception e )
            { 
                if( IDT.IsFatal( e ) )
                {
                    throw;
                } 
                throw IDT.ThrowHelperError(
                                new TrustExchangeException( 
                                        SR.GetString( SR.ServiceSTSCommunicationFailed ), 
                                        e ) );
            } 
        }

        public static void WriteSourceUrlAppliesTo( XmlWriter writer, GetBrowserTokenParameters browserParams, ProtocolProfile profile )
        { 
            EndpointAddress appliesTo = browserParams.Recipient.CreateEndpointAddress();
            writer.WriteStartElement( profile.WSPolicy.DefaultPrefix, profile.WSPolicy.AppliesTo, profile.WSPolicy.Namespace ); 
            appliesTo.WriteTo( AddressingVersion.WSAddressing10, writer ); 
            writer.WriteEndElement();
        } 

        //
        // Summary:
        //  Check for unapproved SecurityTokenParameters hidden in the Optional*TokenParameters. 
        //  We do NOT pass in a ThrowOnMultipleAssignment because
        //  we do NOT wish to change behavior from RTM of honoring IssuedSecurityTokens in 
        //  Optional*TokenParameters. 
        //
        // Params: 
        //  oestp - OptionalEndpointSupportingTokenParameters from the security binding element
        //  oostp - OptionalOperationSupportingTokenParameters from the security binding element
        //  disallowedStpDetected - will set to true if disallowed Security Token Parameters are detected
        // 
        private static void CheckOptionalTokenParameters(
                SupportingTokenParameters oestp, 
                IDictionary oostp, 
                ref bool disallowedStpDetected )
        { 

            //
            // Use a new object, we do not wish to change behavior of NOT honoring IssuedSecurityTokens in
            // Optional*TokenParameters. There is however a change in behavior that we will now throw 
            // when multiple issued token params are found in the optional*parameters
            // 
            ThrowOnMultipleAssignment ignoreItp = 
              new ThrowOnMultipleAssignment( SR.GetString( SR.TooManyIssuedSecurityTokenParameters ) );
 
            //
            // Check OptionalEndpointSupportingTokenParameters
            //
            GetIssuedSecurityTokenParametersFromSupportingTokenParameters( 
                oestp, ignoreItp, ref disallowedStpDetected );
 
            // 
            // Check OptionalOperationSupportingTokenParameters
            // 
            foreach( SupportingTokenParameters param in oostp.Values )
            {
                GetIssuedSecurityTokenParametersFromSupportingTokenParameters(
                    param, ignoreItp, ref disallowedStpDetected ); 
            }
 
        } 

 
        // Summary:
        //  Searches a binding for a single IssuedSecurityTokenParameters.  This method will throw an
        //  argument exception if more than one is found.
        // 
        // Parameters:
        //  currentStsBinding   -  The Binding to search. 
        //  disallowedStpDetected - This function will set this to true if there is a 
        //      disallowed SecurityTokenParameters found on this leg of the federation chain.
        // 
        // Return Value:
        //  Returns an IssuedSecurityTokenParameters if one is found, otherwise null.
        //
        // Remarks: 
        //  Calling function should throw if disallowedStpDetected is set to true and
        //  the federation leg is an intermediate leg 
        // 
        public static IssuedSecurityTokenParameters TryGetNextStsIssuedTokenParameters(
            BindingElementCollection bindingElements, 
            ref bool disallowedStpDetected )
        {
            if( null == bindingElements )
            { 
                return null;
            } 
 
            //
            // This object can have a value assigned to it exactly once.  After one assignment of a non-null value 
            // any other non-null assignment will cause the object to throw an argument excaption.
            //
            ThrowOnMultipleAssignment issuedTokenParameters =
                new ThrowOnMultipleAssignment( SR.GetString( SR.TooManyIssuedSecurityTokenParameters ) ); 

            SecurityBindingElement sbe = bindingElements.Find(); 
 
            if( null == sbe )
            { 
                return null;
            }

            // 
            // Go down the list of possible places for an IssuedSecurityTokenParameters, and hope we don't
            // miss anything. 
            // 

            // 
            // Start with EndpointSupportingTokenParameters.
            //
            SupportingTokenParameters supportingTokenParameters = sbe.EndpointSupportingTokenParameters;
 
            GetIssuedSecurityTokenParametersFromSupportingTokenParameters( supportingTokenParameters,
                                                                             issuedTokenParameters, 
                                                                             ref disallowedStpDetected ); 

            // 
            // Check OperationSupportingTokenParameters.
            //
            IDictionary opSupporting = sbe.OperationSupportingTokenParameters;
            foreach( SupportingTokenParameters parameters in opSupporting.Values ) 
            {
                GetIssuedSecurityTokenParametersFromSupportingTokenParameters( parameters, 
                                                                                 issuedTokenParameters, 
                                                                                 ref disallowedStpDetected );
            } 


            //
            // Depending on the derived type of the SecurityBindingElement there may be other places to check. 
            //
            if( sbe is AsymmetricSecurityBindingElement ) 
            { 
                AsymmetricSecurityBindingElement asbe = (AsymmetricSecurityBindingElement)sbe;
 
                CheckAndAssignIssuedTokenParameters( asbe.InitiatorTokenParameters, issuedTokenParameters, ref disallowedStpDetected );
                CheckAndAssignIssuedTokenParameters( asbe.RecipientTokenParameters, issuedTokenParameters, ref disallowedStpDetected );
            }
            else if( sbe is SymmetricSecurityBindingElement ) 
            {
                SymmetricSecurityBindingElement ssbe = (SymmetricSecurityBindingElement)sbe; 
                SecurityTokenParameters param = ssbe.ProtectionTokenParameters; 

                // 
                // If this is SecureConversationSecurityTokenParameters then we might need
                // to search further.
                //
                if( param is SecureConversationSecurityTokenParameters ) 
                {
                    SecureConversationSecurityTokenParameters secConvParam = 
                        (SecureConversationSecurityTokenParameters)param; 
                    BindingElementCollection elements = new BindingElementCollection();
                    if( secConvParam.BootstrapSecurityBindingElement != null ) 
                    {
                        elements.Add( secConvParam.BootstrapSecurityBindingElement );
                    }
                    CheckAndAssignIssuedTokenParameters( 
                        TryGetNextStsIssuedTokenParameters( elements, ref disallowedStpDetected ),
                        issuedTokenParameters, 
                        ref disallowedStpDetected ); 
                }
                else 
                {
                    CheckAndAssignIssuedTokenParameters( param, issuedTokenParameters, ref disallowedStpDetected );
                }
            } 
            else
            { 
                // 
                // We only know one other type of SecurityBindingElement.
                // 
                Microsoft.InfoCards.Diagnostics.DiagnosticUtility.DebugAssert(sbe is TransportSecurityBindingElement, "Unknown type of SecurityBindingElement");

            }
 
            //
            // Check OptionalEndpointSupportingTokenParameters 
            // and OptionalOperationSupportingTokenParameters. 
            //
            SupportingTokenParameters oestp = sbe.OptionalEndpointSupportingTokenParameters; 
            IDictionary oostp = sbe.OptionalOperationSupportingTokenParameters;
            CheckOptionalTokenParameters( oestp, oostp, ref disallowedStpDetected );

            return issuedTokenParameters.Value; 
        }
 
        // 
        // Summary
        // Sets disallowedStpDetected to ture if a SecurityTokenParam from the un-approved list 
        // is detected.
        //
        // Remarks:
        //  SecureConversationSecurityTokenParameters case for stp should be handled before 
        //  calling this function.
        // 
        public static void CheckAndAssignIssuedTokenParameters( 
            SecurityTokenParameters stp,
            ThrowOnMultipleAssignment issuedTokenParameters, 
            ref bool disallowedStpDetected )
        {

            if( null == stp ) 
            {
                return; 
            } 

            IDT.Assert( null == stp as SecureConversationSecurityTokenParameters, 
               "Should have already filtered this" );

            if(   ( stp is IssuedSecurityTokenParameters ) ||
                  ( stp is RsaSecurityTokenParameters ) || 
                  ( stp is SslSecurityTokenParameters ) ||
                  ( stp is X509SecurityTokenParameters ) ) 
            { 
                //
                // Allowed 
                //
                issuedTokenParameters.Value = stp as IssuedSecurityTokenParameters;
            }
            else 
            {
                // 
                // SspiSecurityTokenParameters - we want to disallow except on IP/STS leg 
                // KerberosSecurityTokenParameters - we want to disallow except on IP/STS leg
                // SecureConversationSecurityTokenParameters - Not expected in this function 
                // UserNameSecurityTokenParameters
                // - we want to disallow except on last leg. CardSpace does NOT set any username password
                // credentials anyway.
                // 
                disallowedStpDetected = true;
            } 
 
        }
 



        // 
        // Summary:
        //  Searches a SupportingTokenParameters for a single IssuedSecurityTokenParameters.  This method will 
        //  throw an argument exception if more than one is found. 
        //
        // Parameters: 
        //  Parameters          - The SupportingTokenParameters to search.
        //  issuedTokenParameters - This is where any found parameters will be placed.
        //
        static void GetIssuedSecurityTokenParametersFromSupportingTokenParameters( 
            SupportingTokenParameters parameters,
            ThrowOnMultipleAssignment issuedTokenParameters, 
            ref bool disallowedStpDetected ) 
        {
            GetIssuedSecurityTokenParametersFromCollection( parameters.Endorsing, issuedTokenParameters, ref disallowedStpDetected ); 
            GetIssuedSecurityTokenParametersFromCollection( parameters.SignedEndorsing, issuedTokenParameters, ref disallowedStpDetected );
            GetIssuedSecurityTokenParametersFromCollection( parameters.Signed, issuedTokenParameters, ref disallowedStpDetected );
            GetIssuedSecurityTokenParametersFromCollection( parameters.SignedEncrypted, issuedTokenParameters, ref disallowedStpDetected );
        } 

        // Summary: 
        //  Goes through a collection of SecurityTokenParameters looking for a single IssuedSecurityTokenParameters. 
        //  This method will throw an argument exception if more than one is found.
        // 
        // Parameters:
        //  collection            - The collection to search.
        //  issuedTokenParameters - This is where any found parameters will be placed.
        // 
        static void GetIssuedSecurityTokenParametersFromCollection(
            Collection collection, 
            ThrowOnMultipleAssignment issuedTokenParameters, 
            ref bool disallowedStpDetected)
        { 
            foreach( SecurityTokenParameters param in collection )
            {
                if( param is SecureConversationSecurityTokenParameters )
                { 
                    //
                    // We may have a whole new binding to check now. 
                    // 
                    SecureConversationSecurityTokenParameters secConvParam =
                        (SecureConversationSecurityTokenParameters)param; 
                    BindingElementCollection bindingElements = new BindingElementCollection();
                    if( secConvParam.BootstrapSecurityBindingElement != null )
                    {
                        bindingElements.Add( secConvParam.BootstrapSecurityBindingElement ); 
                    }
                    CheckAndAssignIssuedTokenParameters( 
                        TryGetNextStsIssuedTokenParameters( bindingElements, ref disallowedStpDetected ), 
                        issuedTokenParameters,
                        ref disallowedStpDetected ); 
                }
                else
                {
                    CheckAndAssignIssuedTokenParameters( param, issuedTokenParameters, ref disallowedStpDetected ); 
                }
            } 
        } 

        class CreateIssuedTokenClientCredentials : ClientCredentials 
        {
            GetBrowserTokenRequest request;

            public CreateIssuedTokenClientCredentials( GetBrowserTokenRequest request ) 
            {
                IDT.ThrowInvalidArgumentConditional( request == null, "request" ); 
                this.request = request; 
            }
 
            protected internal CreateIssuedTokenClientCredentials( CreateIssuedTokenClientCredentials other )
                : base( other )
            {
                this.request = other.request; 
            }
 
            protected override ClientCredentials CloneCore() 
            {
                return new CreateIssuedTokenClientCredentials( this ); 
            }

            protected internal override SecurityToken GetInfoCardSecurityToken( bool requiresInfoCard, CardSpacePolicyElement[ ] chain, SecurityTokenSerializer tokenSerializer )
            { 
                return request.CreateIssuedToken( chain, tokenSerializer );
            } 
 
            public override void ApplyClientBehavior( ServiceEndpoint serviceEndpoint, ClientRuntime behavior )
            { 
                base.ApplyClientBehavior( serviceEndpoint, behavior );

                //
                // The above calls ((ClientCrendentials)creds).AddInteractiveInitializers which in turn calls 
                // InfoCardHelper.IsInfocardRequired. If InfoCardHelper.IsInfocardRequired returns true,
                // then an InfocardInteractiveChannelInitializer should have been added 
                // to behaviors.InteractiveChannelInitializers. 
                //
                bool isCardSpaceRelevant = false; 
                foreach( IInteractiveChannelInitializer iici in behavior.InteractiveChannelInitializers )
                {
                    if( null != ( iici as System.ServiceModel.Security.InfocardInteractiveChannelInitializer ) )
                    { 
                        isCardSpaceRelevant = true;
                        break; 
                    } 
                }
 
                if( !isCardSpaceRelevant )
                {
                    //
                    // Bail out if this request is NOT relevant to CardSpace, i.e. if the 
                    // InfocardInteractiveChannelInitializer was not added to behaviors.InteractiveChannelInitializers.
                    // 
 
                    //
                    // 



                    throw IDT.ThrowHelperError( 
                        new TrustExchangeException(
                              SR.GetString( SR.IdentityProviderRequestedUnsupportedAuthType ) ) ); 
                } 

            } 

        }

        // 
        // Summary:
        //  Creates the Client Credentials for the current endpoint and binding. 
        // 
        // Arguments:
        //  svcEpr:  The service EPR to create the credentials for. 
        //
        // Returns:
        //  return new InfoCardClientCredentials instnace popultated with all
        //  federated credentials. 
        //
        CreateIssuedTokenClientCredentials CreateClientCredentials( ServiceEndpoint svcEpr ) 
        { 
            CreateIssuedTokenClientCredentials creds = new CreateIssuedTokenClientCredentials( this );
 
            EndpointAddress currentAddress = svcEpr.Address;
            IssuedSecurityTokenParameters currentParam = null;
            Binding currentBinding = svcEpr.Binding;
 
            X509Certificate2Collection supportingCertificates =  new X509Certificate2Collection();
 
            bool disallowedStpDetected = false; 

            try 
            {

                while( null != currentBinding )
                { 
                    currentParam = TryGetNextStsIssuedTokenParameters(
                        currentBinding.CreateBindingElements(), 
                        ref disallowedStpDetected ); 

                    if( null == currentParam ) 
                    {
                        //
                        // We've reached the end of the issued token chain.
                        // Note: This leg is NOT asking for an issued token. 
                        // Therefore, it is exempt from disallowedStpDetectedCheck
                        // because Kerberos for example is allowed on the IP/STS leg. 
                        // 
                        break;
                    } 

                    //
                    // We're now either in:
                    // 1) intermediate leg OR 
                    // 2) last leg that has issued token
                    //      (a) self-issued leg 
                    //      (b) managed card leg. (In the next iteration, we'll bail out from the loop) 
                    //
                    // For all of the above, it is not acceptable to have the unapproved SecurityTokenParameters. 
                    //
                    if( disallowedStpDetected )
                    {
                        // 
                        //
 
 
                        throw IDT.ThrowHelperError( new UnsupportedPolicyOptionsException() );
                    } 

                    if( null == currentParam.IssuerAddress ||
                         null == currentParam.IssuerAddress.Uri )
                    { 
                        break;
                    } 
 
                    X509CertificateEndpointIdentity certId = currentAddress.Identity as X509CertificateEndpointIdentity;
                    if( null != certId ) 
                    {
                        supportingCertificates.AddRange( certId.Certificates );
                        supportingCertificates.Remove( certId.Certificates[ 0 ] );
 
                        //
                        // Validate the intermediate STS cert before adding to scoped certificates 
                        // 
                        bool chainValidatedTemp = false;
                        InfoCardX509Validator.ValidateChainOrPeer( 
                            certId.Certificates[ 0 ],
                            supportingCertificates,
                            out chainValidatedTemp );
 
                        creds.ServiceCertificate.ScopedCertificates.Add( currentAddress.Uri, certId.Certificates[ 0 ] );
 
                    } 

                    currentBinding = currentParam.IssuerBinding; 
                    currentAddress = currentParam.IssuerAddress;
                }
                if( null != m_params.Issuer.LeafCertificate )
                { 
                    //
                    // When server binding is configured as IssuedTokenForCertificate, MutualCertificate, 
                    // UserNameForCertificate for authentication mode: 
                    // Indigo considers the server identity to be retrieved out-of-band,
                    // their custom certificate validation extensibility points are not invoked 
                    //
                    bool chainValidatedTemp2 = false;
                    InfoCardX509Validator.ValidateChainOrPeer(
                        m_params.Issuer.LeafCertificate, 
                        m_params.Issuer.SupportingCertificates,
                        out chainValidatedTemp2 ); 
                    creds.ServiceCertificate.DefaultCertificate = m_params.Issuer.LeafCertificate; 
                    supportingCertificates.AddRange( m_params.Issuer.SupportingCertificates );
                } 
                else
                {
                    X509CertificateEndpointIdentity certId = null;
 
                    certId = svcEpr.Address.Identity as X509CertificateEndpointIdentity;
                    if( null != certId ) 
                    { 
                        //
                        // certId.Certificates[ 0 ] was already validated above, 
                        // hence don't need to validate again
                        //

                        creds.ServiceCertificate.DefaultCertificate = certId.Certificates[ 0 ]; 
                        supportingCertificates.AddRange( certId.Certificates );
                        supportingCertificates.Remove( certId.Certificates[ 0 ] ); 
                    } 
                    else
                    { 
                        throw IDT.ThrowHelperError(
                            new TrustExchangeException(
                                    SR.GetString( SR.InvalidIPSTSPolicy ) ) );
                    } 
                }
 
                IDT.Assert( null != creds.ServiceCertificate.DefaultCertificate, 
                    "This is configured in both cases above - either via the incoming params or via the endpoint retrieved from mex" );
 
                //
                // When server binding is configured as IssuedTokenForSslNegotiated, UserNameForSslNegotiated,
                // MutualSslNegotiated for authentication mode:
                // We want to override the validator used by Indigo (because we have some 
                // special behavior, e.g. {chaining up to LM or CU Trusted CA} OR {Peer Trust}, Offline validation,
                // IgnoreRevocationUnknown etc). 
                // 
                // NB: The same validator will be used by the Indigo federation
                // code (since there is only one channel factory being used). Therefore we need 
                // to configure this validator will all the intermediate certs of each STS in the
                // federation chain
                //
                creds.ServiceCertificate.Authentication.CertificateValidationMode = 
                    X509CertificateValidationMode.Custom;
                creds.ServiceCertificate.Authentication.CustomCertificateValidator = 
                    InfoCardX509Validator.Create( supportingCertificates ); 
            }
            catch( SecurityTokenValidationException validationE ) 
            {
                throw IDT.ThrowHelperError(
                    new IdentityValidationException(
                    SR.GetString( SR.RecipientCertificateNotValid ), validationE ) ); 

            } 
 
            return creds;
        } 

        //
        // Summary:
        //  Reads an input stream until it finds the requested token, 
        //  then writes the token to the output writer.
        // 
        // Arguments: 
        //  reader:  reader to read from
        //  writer:  writer to write element to. 
        //
        void WriteRequestedTokenFrom( XmlReader reader, XmlWriter writer )
        {
            while( reader.Read() ) 
            {
                if( reader.IsStartElement( m_protocolProfile.WSTrust.RequestedSecurityToken, m_protocolProfile.WSTrust.Namespace ) ) 
                { 
                    reader.Read();
                    writer.WriteNode( reader, false ); 
                    return;
                }
            }
 
            throw IDT.ThrowHelperError(
                            new TrustExchangeException( SR.GetString( SR.NoTokenReturned ) ) ); 
        } 

 
        //
        // Summary:
        //  Fetches the ServiceEndpoint via the Mex Uri.
        // 
        // Arguments:
        //  serviceUri: The address of the service that will issue the token. 
        //  mexUri:     Optional uri that specifies the mex address for the service. 
        //
        ServiceEndpointCollection GetServiceEndpointCollection( Uri serviceUri, Uri mexUri ) 
        {
            bool foundMexEndpoint = false;
            //
            // Do a WS-MetaDataExchange over SOAP to retrieve the endpoint binding 
            //
            InfoCardMetadataExchangeClient mex = new InfoCardMetadataExchangeClient(); 
            mex.Proxy = this.UserProxy; 

            MetadataSet metadataSet = null; 
            mex.ResolveMetadataReferences = true;
            mex.MaximumResolvedReferences = InfoCardConstants.MaximumMexChainLength;
            EndpointAddress metadataAddress = new EndpointAddress( mexUri );
            IDT.TraceDebug( "BROWSERREQUEST: Retrieving metadata over SOAP from {0}", mexUri ); 
            try
            { 
                ExecuteCancelable( delegate { metadataSet = mex.GetMetadata( metadataAddress ); }, delegate { mex.Abort(); } ); 

                foundMexEndpoint = true; 
            }
            catch( Exception e )
            {
                if( IDT.IsFatal( e ) ) 
                {
                    throw; 
                } 
            }
 

            //
            // Do a WS-MetaDataExchange over HTTP to retrieve the endpoint binding
            // 
            if( !foundMexEndpoint )
            { 
                IDT.TraceDebug( "BROWSERREQUEST: Retrieving metadata over HTTP from {0}", mexUri ); 
                try
                { 
                    ExecuteCancelable( delegate { metadataSet = mex.GetMetadata( mexUri, MetadataExchangeClientMode.HttpGet ); }, delegate { mex.Abort(); } );

                    foundMexEndpoint = true;
                } 
                catch( Exception e )
                { 
                    if( IDT.IsFatal( e ) ) 
                    {
                        throw; 
                    }
                }
            }
 
            //
            // Throw an exception if none of the above methods succeeded. 
            // 
            if( !foundMexEndpoint )
            { 
                throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.EndpointNotFound ) ) );
            }

            WsdlImporter imp = new WsdlImporter( metadataSet ); 
            //
            // Remember the original MEC so that later on the SecurityBindingElementConverter can use it 
            // 
            imp.State.Add( RemoteTokenFactory.MetadataExchangeClientKey, mex );
 
            ServiceEndpointCollection serviceEndpoints = null;

            ExecuteCancelable( delegate { serviceEndpoints = imp.ImportAllEndpoints(); }, null );
 
            return serviceEndpoints;
        } 
 
        //
        // Summary: 
        //  Recursively updates the binding elements with the proxy element in every issuer binding
        //
        // Arguments:
        //  bindingElements:  The bindingElements to update 
        //  proxy: The proxy to be used for HttpTransport
        // 
        // Returns: 
        //  Returns the updated bindingElements.
        // 
        static BindingElementCollection FedChainUpdateProxyForHttpAndRestrictTransportBinding( BindingElementCollection bindingElements, IWebProxy proxy )
        {
            bindingElements = Utility.UpdateProxyForHttpAndRestrictTransportBinding(
                bindingElements, 
                proxy,
                true ); // Client auth on transport is to be turned off for intermediate legs. 
 
            //
            // Note that actual binding used with IP/STS leg is determined in RemoteTokenFactory, 
            // even though the binding may appear here.
            //

            bool ignoreBool = false; 
            IssuedSecurityTokenParameters currentParam =
                TryGetNextStsIssuedTokenParameters( bindingElements, ref ignoreBool ); 
 
            if( null != currentParam &&
                null != currentParam.IssuerAddress && 
                null != currentParam.IssuerAddress.Uri &&
                null != currentParam.IssuerBinding )
            {
                currentParam.IssuerBinding = new CustomBinding( FedChainUpdateProxyForHttpAndRestrictTransportBinding( currentParam.IssuerBinding.CreateBindingElements(), proxy ) ); 
            }
            return bindingElements; 
        } 

        // 
        // Summary:
        //  Updates the complete federated chain found in the binding with the proxy binding element
        //
        // Arguments: 
        //  binding:  The binding to update
        //  proxy: The proxy to be used for HttpTransport 
        // 
        // Returns:
        //  Returns the updated binding. 
        //
        static Binding FedChainUpdateProxyAndRestrictTransportBindingWrapper( Binding binding, IWebProxy proxy )
        {
            BindingElementCollection bindingElements = binding.CreateBindingElements(); 
            return new CustomBinding( FedChainUpdateProxyForHttpAndRestrictTransportBinding( bindingElements, proxy ) );
        } 
 

 
        //
        // Summary:
        //  Custom callback for the InfoCardClientCredentials to prevent re-entrant calls into the system.
        // 
        // Arguments:
        //  policyElements:  The policy for the current exchange. 
        // 
        // Returns:
        //  Returns the created security token. 
        //
        SecurityToken CreateIssuedToken( CardSpacePolicyElement[ ] policyElements, SecurityTokenSerializer tokenSerializer )
        {
 
            WindowsImpersonationContext impersonation = base.RequestorIdentity.Impersonate();
            try 
            { 
                try
                { 
                    int lastElementIndex = policyElements.Length - 1;
                    IDT.Assert( 0 <= lastElementIndex, "lastElementIndex should be non-negative" );

                    if( policyElements[ lastElementIndex ].IsManagedIssuer ) 
                    {
                        IDT.DebugAssert( 0 < lastElementIndex, "Managed issuer must be last in chain, with one or more previous sts eprs" ); 
                        lastElementIndex -= 1; 
                    }
 
                    //
                    // Use lastElementIndex and NOT policyElements.Length - 1 because
                    // we might have subtraced 1 for IsManagedIssuer
                    // 
                    int numOfElementsExcludingLast = lastElementIndex;
 
                    // 
                    // Only the elements until numOfElementsExcludingLast one needs validation,
                    // whereas the others don't. 
                    //
                    if( 0 < numOfElementsExcludingLast )
                    {
                        InfoCardPolicy[] policyArray = new InfoCardPolicy[ numOfElementsExcludingLast ]; 

                        for( int i = 0; i < numOfElementsExcludingLast; i++ ) 
                        { 
                            policyArray[ i ] = PolicyFactory.CreatePolicyForIntermediateGetBrowserTokenRequest(
                                policyElements[ i ], 
                                null,
                                0,
                                null );
 
                            //
                            // Validate the policy here to check for bogus AppliesTo urls. 
                            // 
                            policyArray[ i ].Validate();
                        } 
                    }

                    //
                    // Pass in the recipient's PolicyNoticeLink 
                    // (and policyNoticeVersion) instead of the policyElements[ lastElementIndex ].PolicyNoticeLink
                    // (and PolicyNoticeVersion). 
                    // 
                    // Set the policy usage context to Gettoken because this is the final hop between the resource sts and
                    // the ipsts. 
                    //
                    InfoCardPolicy policy = PolicyFactory.CreatePolicyForGetBrowserTokenRequest(
                        policyElements[ lastElementIndex ],
                        m_params.PrivacyUrl, 
                        m_params.PrivacyVersion,
                        RecipientIdentity.CreateIdentity( m_params.Recipient.CreateEndpointAddress(), true ), 
                        PolicyUsageContext.GetToken ); 

 
                    policy.Validate();
                    base.Policy = policy;

                    base.OnProcess(); 

                    if( null != base.ProcessingException ) 
                    { 
                        throw IDT.ThrowHelperError( base.ProcessingException );
                    } 


                    SecurityKeyIdentifierClause internalTokenReference = tokenSerializer.ReadKeyIdentifierClause(
                           Utility.CreateReaderWithQuotas( base.Token.InternalTokenReference ) ); 

                    SecurityKeyIdentifierClause externalTokenReference = tokenSerializer.ReadKeyIdentifierClause( 
                            Utility.CreateReaderWithQuotas( base.Token.ExternalTokenReference ) ); 

                    if( null == Token.SymmetricProof ) 
                    {
                        //
                        // Private because we need the private key for proof of possesion.
                        // The regular self-issued case does not need the private key 
                        // in the proof crypto because we hand out the CryptoSession handle
                        // to do the proof of possession for us. 
                        // 
                        m_proofToken = new SelfIssuedAuthProofToken(
                                base.GetPrivateCryptography(), 
                                Token.ExpirationTime );
                    }
                    else
                    { 
                        m_proofToken = new SelfIssuedAuthProofToken(
                                 new InMemorySymmetricSecurityKey( Token.SymmetricProof.Key ), 
                                 Token.ExpirationTime ); 
                    }
 
                    SecurityToken token = new GenericXmlSecurityToken(
                                             base.Token.ProtectedToken,
                                             m_proofToken,
                                             base.Token.EffectiveTime, 
                                             base.Token.ExpirationTime,
                                             internalTokenReference, 
                                             externalTokenReference, 
                                             null );
 
                    return token;
                }
                finally
                { 
                    impersonation.Undo();
                } 
            } 
            catch
            { 
                throw;
            }
        }
 
        //
        // Summary: 
        //  Dispose all user bound resources. 
        //
        protected override void OnDisposeAsUser() 
        {

            base.OnDisposeAsUser();
 
            //
            // Dispose the proof token, as the keys with in 
            //  must be released by the same identity that 
            //  created them (the user).
            // 
            if( null != m_proofToken )
            {
                ( (IDisposable)m_proofToken ).Dispose();
                m_proofToken = null; 
            }
 
        } 

        [ServiceContract] 
        internal interface ISts
        {
            [OperationContract( Name = "ProcessRequestSecurityTokenFeb2005",
                                    Action = XmlNames.WSTrustXmlSoap2005.c_RequestSecurityTokenAction, 
                                    ReplyAction = XmlNames.WSTrustXmlSoap2005.c_RequestSecurityTokenResponseAction,
                                    ProtectionLevel = ProtectionLevel.EncryptAndSign )] 
            Message ProcessRequestSecurityTokenFeb2005( Message rstMessage ); 

            [OperationContract( Name = "ProcessRequestSecurityTokenWSTrust13", 
                                    Action = XmlNames.WSTrustOasis2007.c_RequestSecurityTokenAction,
                                    ReplyAction = XmlNames.WSTrustOasis2007.c_RequestSecurityTokenResponseAction,
                                    ProtectionLevel = ProtectionLevel.EncryptAndSign )]
            Message ProcessRequestSecurityTokenWSTrust13( Message rstMessage ); 
        }
    } 
 
    //
    // Summary: 
    //  Class to manage the input parameters for the GetBrowserTokenRequest
    //
    internal class GetBrowserTokenEndpoint
    { 
        Uri m_address;
        Uri m_policyAddress; 
        X509Certificate2Collection m_supportingCertsCollection = new X509Certificate2Collection(); 
        X509Certificate2 m_leafCert = null;
 
        public Uri Address
        {
            get { return m_address; }
        } 

        public Uri PolicyUrl 
        { 
            get { return m_policyAddress; }
        } 

        public X509Certificate2Collection SupportingCertificates
        {
            get { return m_supportingCertsCollection; } 
        }
 
        public X509Certificate2 LeafCertificate 
        {
            get 
            {
                return m_leafCert;
            }
        } 

        public EndpointAddress CreateEndpointAddress() 
        { 
            if( null != m_address )
            { 
                if( null != LeafCertificate )
                {
                    return new EndpointAddress(
                                m_address, 
                                EndpointIdentity.CreateX509CertificateIdentity(
                                    LeafCertificate, SupportingCertificates ) ); 
                } 
                else
                { 
                    return new EndpointAddress( m_address );
                }
            }
            return null; 
        }
 
        public XmlElement CreateEndpointAddressXml() 
        {
            if( null != m_address ) 
            {
                EndpointAddress epr = null;
                if( null != LeafCertificate )
                { 
                    //
                    // Leave out the leaf certificate in SupportingCertificates, 
                    // otherwise the endpoint address xml includes a duplicate copy of the leaf cert. 
                    //
                    epr = new EndpointAddress( 
                                m_address,
                                EndpointIdentity.CreateX509CertificateIdentity( LeafCertificate, SupportingCertificates ) );

                } 
                else
                { 
                    epr = new EndpointAddress( m_address ); 
                }
                if( null != epr ) 
                {
                    using( MemoryStream buffer = new MemoryStream() )
                    {
                        using( XmlWriter writer = new XmlTextWriter( buffer, Encoding.UTF8 ) ) 
                        {
                            epr.WriteTo( AddressingVersion.WSAddressing10, writer ); 
                            // 
                            // Skip the BOM and trailing padding.
                            // 
                            writer.Flush();
                            buffer.Flush();
                            buffer.Seek( 0, 0 );
                            using( XmlReader reader = Utility.CreateReaderWithQuotas( buffer ) ) 
                            {
                                XmlDocument doc = new XmlDocument(); 
                                return (XmlElement)doc.ReadNode( reader ); 
                            }
 
                        }

                    }
                } 
            }
            return null; 
        } 

        public void Load( BinaryReader reader, int paramVersion ) 
        {
            string addr = Utility.DeserializeString( reader );

            if( !String.IsNullOrEmpty( addr ) ) 
            {
                m_address = new Uri( addr ); 
            } 

            addr = Utility.DeserializeString( reader ); 

            if( !String.IsNullOrEmpty( addr ) )
            {
                m_policyAddress = new Uri( addr ); 
            }
 
            int certCount = 0; 

            if( GetBrowserTokenRequest.POLICY_V2 == paramVersion ) 
            {
                certCount = reader.ReadInt32();
            }
            else if( GetBrowserTokenRequest.POLICY_V1 == paramVersion ) 
            {
                certCount = 1; 
            } 

            for( int i = 0; i < certCount; i++ ) 
            {
                byte[ ] rawCert = reader.ReadBytes( reader.ReadInt32() );
                if( !Utility.ArrayIsNullOrEmpty( rawCert ) )
                { 
                    X509Certificate2 cert = new X509Certificate2( rawCert );
 
                    if( 0 == i ) 
                    {
                        m_leafCert = cert; 
                    }
                    else
                    {
                        m_supportingCertsCollection.Add( cert ); 
                    }
                } 
            } 
        }
    } 

    //
    // Summary:
    //  Class to manage the input parameters for the GetBrowserTokenRequest 
    //
    internal class GetBrowserTokenParameters 
    { 
        GetBrowserTokenEndpoint m_recipient;
        GetBrowserTokenEndpoint m_issuer; 
        Uri m_tokenType;
        List m_requiredClaims;
        List m_optionalClaims;
        int m_flags; 
        uint m_privacyVersion;
        Uri m_privacyUrl; 
 
        public GetBrowserTokenParameters()
        { 
            m_recipient = new GetBrowserTokenEndpoint();
            m_issuer = new GetBrowserTokenEndpoint();
            m_requiredClaims = new List();
            m_optionalClaims = new List(); 
        }
 
        public GetBrowserTokenEndpoint Recipient 
        {
            get { return m_recipient; } 
        }

        public GetBrowserTokenEndpoint Issuer
        { 
            get { return m_issuer; }
        } 
 
        public IList RequiredClaims
        { 
            get { return m_requiredClaims.AsReadOnly(); }
        }

        public IList OptionalClaims 
        {
            get { return m_optionalClaims.AsReadOnly(); } 
        } 

        public Uri PrivacyUrl 
        {
            get { return m_privacyUrl; }
        }
 
        public uint PrivacyVersion
        { 
            get { return m_privacyVersion; } 
        }
 
        public void Load( BinaryReader reader, int paramVersion )
        {
            m_flags = paramVersion;
 
            m_recipient.Load( reader, paramVersion );
            m_issuer.Load( reader, paramVersion ); 
 
            string tokenType = Utility.DeserializeString( reader );
            if( !String.IsNullOrEmpty( tokenType ) ) 
            {
                m_tokenType = new Uri( tokenType );
            }
 
            int count = reader.ReadInt32();
            for( int i = 0; i < count; i++ ) 
            { 
                m_requiredClaims.Add( Utility.DeserializeString( reader ) );
            } 
            count = reader.ReadInt32();
            for( int i = 0; i < count; i++ )
            {
                m_optionalClaims.Add( Utility.DeserializeString( reader ) ); 
            }
 
            m_privacyVersion = reader.ReadUInt32(); 

            string urlString = Utility.DeserializeString( reader ); 
            if( !String.IsNullOrEmpty( urlString ) )
            {
                m_privacyUrl = new Uri( urlString );
            } 
            else
            { 
                m_privacyUrl = null; 
            }
        } 

        public CardSpacePolicyElement CreatePolicyElement( ProtocolProfile protocolProfile )
        {
            XmlDocument doc = new XmlDocument(); 
            XmlElement elt = doc.CreateElement( protocolProfile.WSTrust.DefaultPrefix,
                                                protocolProfile.WSTrust.ClaimsElement, 
                                                protocolProfile.WSTrust.Namespace ); 
            foreach( string uri in RequiredClaims )
            { 
                elt.AppendChild( CreateClaimElement( doc, uri, false ) );
            }
            foreach( string uri in OptionalClaims )
            { 
                elt.AppendChild( CreateClaimElement( doc, uri, true ) );
            } 
 

            IssuedSecurityTokenParameters istp = new IssuedSecurityTokenParameters(); 
            if( null != m_tokenType )
            {
                istp.TokenType = m_tokenType.ToString();
            } 

            istp.AdditionalRequestParameters.Add( elt ); 
 
            //
            // IssuedSecurityTokenParameters only knows about Symmetric 
            // and Asymmetric keys, so we have to go fix the emitted
            // KeyType element to reflect NoProofKey for browsers.
            //
            Collection requestParameters = 
                istp.CreateRequestParameters( protocolProfile.MsgSecurityVersion,
                                              new WSSecurityTokenSerializer( protocolProfile.MsgSecurityVersion.SecurityVersion, true, null, null, null ) ); 
 
            foreach( XmlElement e in requestParameters )
            { 
                if( StringComparer.Ordinal.Equals( e.LocalName, protocolProfile.WSTrust.KeyType ) &&
                    StringComparer.Ordinal.Equals( e.NamespaceURI, protocolProfile.WSTrust.Namespace ) )
                {
                    e.RemoveAll(); 
                    e.AppendChild( e.OwnerDocument.CreateTextNode(
                        protocolProfile.WSTrust.KeyTypeBearer.OriginalString ) ); 
 
                    break;
                } 
            }

            return new CardSpacePolicyElement( null != m_recipient ? m_recipient.CreateEndpointAddressXml() : null,
                                      null != m_issuer ? m_issuer.CreateEndpointAddressXml() : null, 
                                      requestParameters,
                                      m_privacyUrl, 
                                      Convert.ToInt32( m_privacyVersion ), 
                                      false );
        } 

        //
        // Summary:
        // Creates a claim element representing the incoming claim string. 
        // Parameters:
        // document - the document to add the claim to. 
        // claimUri -  the string representation of the claim uri 
        // optional - whether this is an optional claim
        // Returns 
        // The xml element representing the claim.
        //
        static XmlElement CreateClaimElement( XmlDocument document, string claimUri, bool optional )
        { 
            XmlElement elt = document.CreateElement( XmlNames.WSIdentity.DefaultPrefix,
                                                        XmlNames.WSIdentity.ClaimElement, 
                                                        XmlNames.WSIdentity.Namespace ); 

            elt.SetAttribute( XmlNames.WSIdentity.UriAttribute, claimUri ); 
            if( optional )
            {
                elt.SetAttribute( XmlNames.WSIdentity.OptionalAttribute, "true" );
            } 
            return elt;
        } 
    } 
}

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