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

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace Microsoft.InfoCards
{ 
    using System;
    using System.Collections; 
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Threading; //ManualResetEvent 
    using System.ComponentModel; //Win32Exception
    using System.IO; //Stream
    using System.Security.Cryptography;
    using System.Text; 
    using System.ServiceModel;
    using System.ServiceModel.Description; 
    using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; 
    using System.Security.Principal;
    using System.IdentityModel.Selectors; 
    using System.Net;

    class GetTokenRequest : ClientUIRequest
    { 
        public enum TrustDecision :byte
        { 
            NoTrustDecision,  // Indicating a recipient for whom a trust decision has never been made before 
            IsTrusted,        // Indicating a recipient who has been trusted before
            IsNotTrusted      // Indicating a recipient who has been set to "untrusted" before 
        };

        //
        // inargs 
        //
        InfoCardPolicy[ ] m_policyChain; 
        InfoCardPolicy m_policy; 

        // 
        // outargs
        //
        TokenDescriptor m_token;
 
        ITokenFactory m_tokenFactory;
        LedgerEntry m_ledgerEntry; 
        InfoCard m_selectedCard; 
        Recipient m_recipient;
 
        //
        // Required for synchronization for member variables between SelectCard
        // and CreateToken
        // 
        object m_createSecurityTokenDoneMonitor = new object();
 
        // 
        // Set to true if CreateToken has finished processing
        // 
        bool m_isProcessingComplete = true;

        //
        // Set to true if user proceeded to CreateToken after SelectCard 
        //
        bool m_userProceededToCreateToken = false; 
 
        public GetTokenRequest( Process callingProcess, WindowsIdentity callingIdentity, InfoCardUIAgent uiAgent, IntPtr rpcHandle, Stream inArgs, Stream outArgs )
            : base( callingProcess, callingIdentity, uiAgent, rpcHandle, inArgs, outArgs, InfoCardUIAgent.CallMode.GetToken, ExceptionList.AllNonFatal ) 
        {
        }

        public TokenDescriptor Token 
        {
            get { return m_token; } 
        } 

        public InfoCardPolicy Policy 
        {
            get { return m_policy; }
            protected set { m_policy = value; }
        } 

        protected Recipient GetRecipient() 
        { 
            if ( null == m_recipient )
            { 
                IDT.DebugAssert( null != m_policy, "null policy" );

                m_recipient = new Recipient(
                                      m_policy.Recipient, 
                                      false, // cert is not cached
                                      m_policy.PrivacyPolicyVersion ); 
            } 

            return m_recipient; 
        }


        protected override void OnMarshalInArgs() 
        {
            BinaryReader breader = new InfoCardBinaryReader( InArgs, Encoding.Unicode ); 
 
            int policyLength = breader.ReadInt32();
 
            //
            // policyLength is specified by the rpc client, so we should perform a
            // sanity check here
            // 
            if( policyLength <= 0 || policyLength > CardSpaceSelector.MaxPolicyChainLength )
            { 
                throw IDT.ThrowHelperError( new InfoCardArgumentException( SR.GetString( SR.InvalidPolicyLength ) ) ); 
            }
 
            m_policyChain = new InfoCardPolicy[ policyLength ];

            for ( int i = 0; i < policyLength; i++ )
            { 
                string recipientXml = Utility.DeserializeString( breader );
                string issuerXml = Utility.DeserializeString( breader ); 
                string policyXml = Utility.DeserializeString( breader ); 
                string privacyPolicy = Utility.DeserializeString( breader );
                uint privacyVersion = breader.ReadUInt32(); 
                bool isManaged = breader.ReadBoolean();

                m_policyChain[ i ] = PolicyFactory.CreatePolicyForGetTokenRequest(
                        breader, 
                        recipientXml,
                        issuerXml, 
                        policyXml, 
                        isManaged );
 
                //
                // The "recipient" of any element in the chain refers to m_policyChain[ 0 ].
                // So the certificate, the privacy policy URL, and version should
                // be set to those belonging to m_policyChain[ 0 ] 
                //
                if( 0 == i ) 
                { 
                    m_policyChain[ i ].SetRecipientInfo(
                        m_policyChain[ 0 ].ImmediateTokenRecipient, 
                        privacyPolicy,
                        privacyVersion );
                }
                else 
                {
                    m_policyChain[ i ].SetRecipientInfo( 
                        m_policyChain[ 0 ].ImmediateTokenRecipient, 
                        m_policyChain[ 0 ].PrivacyPolicyLink,
                        m_policyChain[ 0 ].PrivacyPolicyVersion ); 
                }
            }

            // 
            // See if the last policy in the chain is really the policy of a
            // managed token provider that requires an imported managed card. 
            // If it is back up one sts. 
            //
            int last = policyLength - 1; 
            if ( m_policyChain[ last ].IsManaged )
            {
                if( 0 == last )
                { 
                    //
                    // The number of policy elements is wrong.  If 0 == last and last is managed, 
                    //  we are missing a policy element. 
                    //
                    throw IDT.ThrowHelperError( new InfoCardArgumentException( SR.GetString( SR.InvalidPolicyLength ) ) ); 
                }
                last -= 1;
            }
 
            m_policy = m_policyChain[ last ];
            m_policy.Validate(); 
        } 

        protected override void OnProcess() 
        {
            StartAndWaitForUIAgent();
        }
 
        protected override void OnMarshalOutArgs()
        { 
            BinaryWriter bwriter = new BinaryWriter( OutArgs, Encoding.Unicode ); 

            m_token.Write( bwriter ); 

            //
            // Don't dispose this crypto session.  It get's disposed either when the client process has gone away,
            // or the client explicitly closes it. 
            //
            SymmetricAlgorithm symmetricProof = m_token.SymmetricProof; 
            CryptoSession cryptoSession = null; 
            if ( null == symmetricProof )
            { 
                //
                // GetPrivateCryptography - PRIVATE becuase this is to sign tokens in the self-issued case.
                //
                RSACryptoServiceProvider rsaIdentityWithPrivateKey = 
                    GetPrivateCryptography();
                // 
                // Transfer ownership of the rsa key pair to cryptoSession 
                //
                cryptoSession = CryptoSession.Create( 
                    CallerProcess,
                    m_token.ExpirationTime,
                    RequestorIdentity,
                    rsaIdentityWithPrivateKey ); 

            } 
            else 
            {
                cryptoSession = CryptoSession.Create( 
                    CallerProcess,
                    m_token.ExpirationTime,
                    RequestorIdentity,
                    symmetricProof.Key ); 
            }
 
            cryptoSession.Write( bwriter ); 
        }
 
        protected RSACryptoServiceProvider GetPrivateCryptography()
        {
            return m_selectedCard.GetPrivateCryptography( GetRecipient().RecipientId );
        } 

        // 
        // Summary: 
        //  Dispose all user bound resources.
        // 
        protected override void OnDisposeAsUser()
        {
            //
            // Dispose the token info, as the keys with in 
            //  must be released by the same identity that
            //  created them (the user). 
            // 
            base.OnDisposeAsUser();
 
            if ( null != m_token )
            {
                m_token.Dispose();
                m_token = null; 
            }
 
        } 

        // 
        // Summary:
        //  Sets the state booleans
        //
        public void CancelSelectCard() 
        {
 
            m_userProceededToCreateToken = false; 
            m_isProcessingComplete = true;
 
            //
            // A subsequent SelectCard thread should NOT have come in,
            // no need to Pulse to wake it up.
            // 

        } 
 

        // 
        // Optionally implement OnDisposeAsSystem
        //

        // 
        // Optionally implement OnHandleExceptions
        // 
 
        //
        // Remarks: 
        // Running on threadpool thread from BeginSelectCardRequest.
        //
        public Int32 SelectCard( InfoCard card, bool isSelfIssued )
        { 
            //
            // NB: Lock is equivalent to Monitor.Enter( m_createSecurityTokenDoneMonitor ). 
            // Note we're using Monitor.Wait on the same object below. 
            //
            lock( m_createSecurityTokenDoneMonitor ) 
            {
                //
                // m_userProceededToCreateToken m_isProcessingComplete
                // True,          True    ---------------> Go ahead, createToken completed successfully 
                // True,          False   ---------------> Wait, User cancelled in createToken, wait till createToken also executes
                // False,         True    ---------------> Go ahead, user cancelled in select card 
                // False,         False   ---------------> Go ahead, SelectCard completed but user cancelled before CreateToken 
                //
                while( m_userProceededToCreateToken && !m_isProcessingComplete ) 
                {
                    Monitor.Wait( m_createSecurityTokenDoneMonitor );
                }
 
                //
                // Reset these 
                // 
                m_userProceededToCreateToken = false;
                m_isProcessingComplete = false; 


                Int32 tokenCreationParamIndex = 0;
                TokenCreationParameter createParam = null; 
                ServiceEndpoint ep = null;
                IWebProxy proxy = null; 
 
                StoreConnection connection = StoreConnection.GetConnection();
                try 
                {
                    card.Connection = connection;
                    if( isSelfIssued )
                    { 
                        ;
                    } 
                    else 
                    {
                        // 
                        // As this is the most common case we will optimize the behaviour
                        // for a single auth type. In this case we will
                        // do the Mex operation just before creating the token. This will reduce
                        // the wait time between clicking submit and the appearing of the credential 
                        // collection window.
                        // 
                        if( 1 == card.CreationParameters.Count ) 
                        {
                            tokenCreationParamIndex = 0; 
                            createParam = card.CreationParameters[ tokenCreationParamIndex ];
                        }
                        else
                        { 
                            for( Int32 i = 0; i < card.CreationParameters.Count; i++ )
                            { 
                                try 
                                {
                                    ep = RemoteTokenFactory.DoMexExchange( card.CreationParameters[ i ], this.UserProxy ); 
                                    tokenCreationParamIndex = i;
                                    createParam = card.CreationParameters[ tokenCreationParamIndex ];
                                    break;
                                } 
                                catch( TrustExchangeException )
                                { 
                                    // 
                                    // If this is the last auth type in the list we were not able to
                                    // do a successful mex at any of the Epr's in the list. Throw an 
                                    // exception indicating failure to the UI.
                                    //
                                    if( i == card.CreationParameters.Count - 1 )
                                    { 
                                        throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.InvalidServiceUri ) ) );
                                    } 
                                } 
                            }
                        } 
                        proxy = this.UserProxy;
                    }
                }
                finally 
                {
                    connection.Close(); 
                } 

                m_tokenFactory = TokenFactoryFactory.Create( card, createParam, ep, proxy ); 
                m_selectedCard = card;

                return tokenCreationParamIndex;
            } 
        }
 
 
        //
        // Summary: 
        //  Cancels the outstanding token factory object if present.
        //
        public void CancelCreateSecurityToken()
        { 
            //
            // We are running on the main UI thread here, hence cannot take lock [Doing so will 
            // block the UI.] 
            //
 

            if( null != m_tokenFactory )
            {
                m_tokenFactory.Abort(); 
            }
 
            m_userProceededToCreateToken = true; 

            // 
            // A subsequent SelectCard thread has should NOT have come in,
            // no need to Pulse to wake that up.
            //
 
        }
 
 
        //
        // Remarks: 
        // Running on threadpool thread from BeginGetSecurityTokenRequest.
        //
        public DisplayToken CreateSecurityToken( TokenFactoryCredential credential, bool discloseOptional )
        { 
            lock( m_createSecurityTokenDoneMonitor )
            { 
                try 
                {
 
                    IDT.DebugAssert( null != m_tokenFactory, "No TokenFactory selected" );
                    IDT.DebugAssert( null != m_selectedCard, "No Card Selected" );

                    // 
                    // Ledger must exist on the object before
                    //  we attempt to create the token. 
                    // 
                    m_ledgerEntry = GetLedgerEntry();
 
                    if( null != m_token )
                    {
                        m_token.Dispose();
                        m_token = null; 
                    }
 
                    using( credential ) 
                    {
                        m_token = m_tokenFactory.CreateToken( m_selectedCard, credential, m_policy, discloseOptional ); 
                    }

                    m_ledgerEntry.DisclosureDate = DateTime.UtcNow;
                    m_ledgerEntry.DisclosedClaims = new string[ m_token.DisclosedClaims.Count ]; 
                    for( int index = 0; index < m_token.DisclosedClaims.Count; index++ )
                    { 
                        m_ledgerEntry.DisclosedClaims[ index ] = m_token.DisclosedClaims[ index ]; 
                    }
 
                    Array.Clear( m_selectedCard.Key, 0, m_selectedCard.Key.Length );

                    return m_token.DisplayToken;
                } 
                finally
                { 
                    // 
                    // Allow new SelectCard calls to get through.
                    // 
                    m_isProcessingComplete = true;
                    m_userProceededToCreateToken = true;

                    // 
                    // Wake up the subsequent SelectCard thread if it has already come in
                    // 
                    Monitor.Pulse( m_createSecurityTokenDoneMonitor ); 
                }
 

            }

        } 

        // 
        // Summary 
        // Retrieves or creates ledger entry.
        // 
        // Returns
        // Returns ledger entry.
        //
        // Note : the logic followed by this function is a little twisted. 
        // As we do not want a perf hit, we do not retrieve the complete ledger
        // instead create a new ledger for the card with only the new or updated entry so 
        // that subsequent calls to TryGetLedgerEntry will return the correct 
        // ledger entry from the card ledger cache. This code is extremly fragile and should
        // be changed so that ledger entry that is returned by this function is used in all 
        // subsequent token related calls.
        //
        private LedgerEntry GetLedgerEntry()
        { 
            LedgerEntry entry = null;
 
            StoreConnection connection = StoreConnection.GetConnection(); 

            try 
            {
                //
                // Attempt to get an existing ledger entry.
                // 
                entry = m_selectedCard.TryGetLedgerEntry( connection, m_policy.Recipient.GetIdentifier() );
 
                // 
                // If an existing ledger entry doesn't exist then create a new ledger entry.
                // 
                if( null == entry )
                {
                    entry = m_selectedCard.CreateLedgerEntry( GetRecipient(), m_policy.ImmediateTokenRecipient.GetOrganizationIdentifier() );
                } 
                else
                { 
                    m_selectedCard.CheckAndUpdateLedgerEntry( entry, m_policy.ImmediateTokenRecipient.GetOrganizationIdentifier() ); 
                }
            } 
            finally
            {
                connection.Close();
            } 

            return entry; 
        } 

        // 
        // Summary
        // Saves ledger entry to store.
        //
        public void SaveLedgerEntry() 
        {
            StoreConnection con = StoreConnection.GetConnection(); 
            try 
            {
                con.BeginTransaction(); 
                try
                {
                    m_ledgerEntry.Save( con );
                    con.CommitTransaction(); 
                }
                catch 
                { 
                    con.RollbackTransaction();
                    throw; 
                }
            }
            finally
            { 
                con.Close();
            } 
        } 
    }
} 

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