Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / InfoCard.cs / 2 / InfoCard.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- // // Presharp uses the c# pragma mechanism to supress its warnings. // These are not recognised by the base compiler so we need to explictly // disable the following warnings. See http://winweb/cse/Tools/PREsharp/userguide/default.asp // for details. // #pragma warning disable 1634, 1691 // unknown message, unknown pragma internal enum RequireAppliesToStatus : byte { NotPresent = 0, Optional = 1, Required = 2 }; namespace Microsoft.InfoCards { using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Globalization; using System.IO; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; using System.ServiceModel; using Microsoft.InfoCards.Diagnostics; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; // // Summary // This is the primary "ticket" information the user receives from the issuer. It service // the service to retrieve security tokens from the associated token factory on behalf of // the user. It includes display data (name, logo, category), issuer information // authentication information allowing the system to present the user's credentials to the // associated token factory. The class also includes accessor's for retrieving associated // collections including supported claims and ledger entries. // // Remarks // internal class InfoCard : IXmlSerializable { // // Row numbers start at 1. 0 will never be valid // const Int32 InvalidRow = 0; // // Random value used to mark the start/end of serialized object. // const byte Marker = 29; // // Used to verify the serialized version of the InfoCard // const byte Version = 1; // // Size of RSA subject keys in bits // public const int KeySize = 2048; // // Size of InfoCard MasterKey in bytes // public const int MasterKeySize = 32; // // Size of InfoCard Salt in bytes // public const int SaltSize = 16; enum PinAction : byte { NoPin = 0, PinSame = 1, PinAdded = 2, PinRemoved = 3, PinChanged = 4 }; InfoCardClaimCollection m_claims; DateTime m_expiresOn = DateTime.MaxValue; UInt32 m_epoch = 0; Uri m_id; DateTime m_issuedOn = DateTime.MinValue; bool m_isImported = false; DateTime m_installedOn = DateTime.Now; string m_issuerName = String.Empty; string m_language = String.Empty; LedgerEntryCollection m_ledger; byte[ ] m_logo; string m_mimeType = String.Empty; string m_name = String.Empty; DateTime m_lastUpdate = DateTime.MinValue; Int32 m_rowId = InvalidRow; StoreConnection m_storeConnection; Int32 m_backgroundColor; string[ ] m_tokenTypes; RequireAppliesToStatus m_requireAppliesTo = RequireAppliesToStatus.NotPresent; byte[ ] m_pinHash; bool m_isSelfIssued = false; byte[ ] m_salt = null; InfoCardMasterKey m_masterKey; string m_privacyPolicyLink = String.Empty; byte[ ] m_issuerIdentifierAsBytes; Uri m_issuer; uint m_privacyPolicyVersion; string m_pin = String.Empty; string m_oldPin = String.Empty; PinAction m_pinAction = PinAction.NoPin; InfocardExtendedInformationCollection m_extendedInformation; bool m_readIssuerInformation = false; RPIdentityRequirement m_rpStrongIdentityRequired; Listm_creationParameters; // // Summary // Create an instance of the InfoCard class in the initial state. // // Remarks // We will support this since it may be needed to build an instance piece meal. // Other methods that require the object to be complete (e.g. Serialize) will need to call // ThrowIfNotComplete() to verify that all required fields have been populated. // // // Consider for future -- see postponed bug 40840 // Avoid piecemeal construction of InfoCard -- which would prevent construction of // incomplete InfoCards // public InfoCard() { m_lastUpdate = DateTime.UtcNow; } // // Summary // Create an instance of the InfoCard to be used to retrieve the card from the store. // public InfoCard( Uri id ) { m_id = id; } // // Summary // Create an instance of the InfoCard class from a previously serialized stream. // // Remarks // This method will primarily be called when an updated intance of an infocard is returned from the // agent process via RPC. // // Parameters // stream - binary stream conforming to the serialization format supported by this class. See Serialize/Deserialize method // for more details. // public InfoCard( Stream stream ) { Deserialize( stream ); } public string[ ] TokenTypes { set { m_tokenTypes = value; } } public List CreationParameters { get { if( null == m_creationParameters ) { m_creationParameters = new List (); } return m_creationParameters; } } public InfoCardClaimCollection GetClaims() { if( null == m_claims ) { if( null == m_id ) { IDT.Assert( null != m_id, "m_id" ); } m_claims = new InfoCardClaimCollection( m_id ); if( null != m_storeConnection ) { m_claims.Get( m_storeConnection ); } } return m_claims; } public static IssuerInformation GetIssuerInformation( string xml ) { IssuerInformation info = new IssuerInformation(); if( !string.IsNullOrEmpty( xml ) ) { try { info.ReadIssuerInformation( InfoCardSchemas.CreateReader( xml ) ); } catch( Exception e ) { if( IDT.IsFatal( e ) ) { throw; } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ServiceUnableToDeserializeInfoCardStream ), e ) ); } } } return info; } public InfocardExtendedInformationCollection GetExtendedInformation() { if( null == m_extendedInformation ) { IDT.Assert( null != m_id, "m_id" ); m_extendedInformation = new InfocardExtendedInformationCollection( m_id ); if( null != m_storeConnection ) { m_extendedInformation.Get( m_storeConnection ); } } return m_extendedInformation; } public RPIdentityRequirement GetRPIdentityRequirement() { if( null == m_rpStrongIdentityRequired ) { m_rpStrongIdentityRequired = new RPIdentityRequirement( m_id, false ); if( null != m_storeConnection ) { m_rpStrongIdentityRequired.Get( m_storeConnection ); } } return m_rpStrongIdentityRequired; } public void AddClaim( InfoCardClaim claim ) { IDT.Assert( null != claim, "null claim" ); GetClaims().Add( claim ); } public void AddLedgerEntry( LedgerEntry entry ) { IDT.Assert( null != entry, "null ledger entry" ); GetLedger().Add( entry ); } public DateTime ExpiresOn { get { return m_expiresOn; } set { m_expiresOn = value; } } public UInt32 Epoch { get { return m_epoch; } set { m_epoch = value; } } public Uri Id { get { return m_id; } set { m_id = value; } } public DateTime IssuedOn { get { return m_issuedOn; } set { m_issuedOn = value; } } public string IssuerName { get { return m_issuerName; } set { m_issuerName = value; } } public byte[ ] IssuerIdentifierAsBytes { get { return m_issuerIdentifierAsBytes; } set { m_issuerIdentifierAsBytes = value; } } public Uri Issuer { set { m_issuer = value; } } public string Language { get { return m_language; } set { m_language = value; } } public RequireAppliesToStatus RequireAppliesto { get { return m_requireAppliesTo; } set { m_requireAppliesTo = value; } } public bool IsSelfIssued { get { return m_isSelfIssued; } set { m_isSelfIssued = value; } } public string PrivacyPolicyLink { get { return m_privacyPolicyLink; } set { m_privacyPolicyLink = value; } } public uint PrivacyPolicyVersion { get { return m_privacyPolicyVersion; } } public LedgerEntryCollection GetLedger() { if( null == m_ledger ) { IDT.Assert( null != m_id, "m_id is null" ); m_ledger = new LedgerEntryCollection( m_id ); if( null != m_storeConnection ) { m_ledger.Get( m_storeConnection ); } } return m_ledger; } public StoreConnection Connection { set { m_storeConnection = value; } } // // Summary // Trys to retrieve the ledger entry for the specified recipient. // // Parameters // connection - Specifies store connection. // recipientIdentifier - Specifies recipient identifier. // // Returns // Returns ledger entry if one found otherwise null. // public LedgerEntry TryGetLedgerEntry( StoreConnection connection, string recipientIdentifier ) { LedgerEntry entry = null; IDT.Assert( null != connection, "The store connection cannot be null." ); IDT.Assert( false == string.IsNullOrEmpty( recipientIdentifier ), "A recipient identifier must be specified." ); // // Query ledger member first. // if( null != m_ledger ) { if( m_ledger.ContainsKey( recipientIdentifier ) ) { entry = m_ledger[ recipientIdentifier ]; } } // // If not found in ledger member then query store. // if( null == entry ) { DataRow row = connection.GetSingleRow( new QueryParameter( SecondaryIndexDefinition.ObjectTypeIndex, (Int32)StorableObjectType.LedgerEntry ), new QueryParameter( SecondaryIndexDefinition.ParentIdIndex, GlobalId.DeriveFrom( m_id.ToString() ) ), new QueryParameter( SecondaryIndexDefinition.RecipientIdIndex, recipientIdentifier ) ); if( null != row ) { entry = new LedgerEntry( new MemoryStream( row.GetDataField() ), connection ); } } return entry; } // // Summary // Creates ledger entry for specified recipient. // // Parameters // recipient - Specifies the recipient. // // Returns // Returns the new ledger entry. // public LedgerEntry CreateLedgerEntry( Recipient recipient, string immediateTokenRecipientOrganizationIdentifier ) { IDT.Assert( null != recipient, "A recipient must be specified." ); if( null == m_ledger ) { IDT.Assert( null != m_id, "The card identifier must be defined." ); m_ledger = new LedgerEntryCollection( Id ); } LedgerEntry entry = LedgerEntry.NewLedgerEntry( Id, recipient, Key, immediateTokenRecipientOrganizationIdentifier ); m_ledger.Add( entry ); return entry; } // // Summary // Checks and updates the ledger entry. // // Parameters // entry - Ledger entry to be updated // immediateTokenRecipientOrgId - Specifies the immediate token recipient Id. // // public void CheckAndUpdateLedgerEntry( LedgerEntry entry, string immediateTokenRecipientOrgId ) { if( entry.CheckAndUpdateSubjectKey( immediateTokenRecipientOrgId, this.Key ) ) { if( null == m_ledger ) { IDT.Assert( null != this.Id, "The card identifier must be defined." ); m_ledger = new LedgerEntryCollection( this.Id ); } // // Update the ledger entry in the collection // if( m_ledger.ContainsKey( entry.Recipient.RecipientId ) ) { m_ledger[ entry.Recipient.RecipientId ] = entry; } else { m_ledger.Add( entry ); } } } public byte[ ] Logo { get { return m_logo; } set { m_logo = value; } } public string LogoMimeType { get { return m_mimeType; } set { m_mimeType = value; } } public string Name { get { return m_name; } set { m_name = value; } } public DateTime LastUpdate { get { return m_lastUpdate; } set { m_lastUpdate = value; } } public Int32 BackgroundColor { get { return m_backgroundColor; } set { m_backgroundColor = value; } } public byte[ ] HashSalt { set { m_salt = value; } get { return m_salt; } } public string[ ] SupportedClaimTypes { get { List supportedClaimTypes = new List (); foreach( string key in GetClaims().Keys ) { if( !IsSelfIssued || !String.IsNullOrEmpty( GetClaims()[ key ].Value ) ) { supportedClaimTypes.Add( key ); } } return supportedClaimTypes.ToArray(); } } public bool IsImported { set { m_isImported = value; } } public DateTime InstalledOn { set { m_installedOn = value; } } public bool IsPinProtected { get { return ( null == m_pinHash ) ? false : ( m_pinHash.Length > 0 ); } } public string Pin { get { return m_pin; } } // // Summary // Read this infocard's masterkey from the store // // Returns // connection - the store connection object // public InfoCardMasterKey GetMasterKey( StoreConnection connection ) { IDT.Assert( null != connection, "Store connection should not be null" ); m_masterKey = new InfoCardMasterKey( m_id ); m_masterKey.Get( connection ); return m_masterKey; } public void Decrypt() { IDT.Assert( null != m_masterKey, "The GetMasterKey must be called before using this method." ); // // Decrypt the masterkey and claims // PinProtectionHelper pinHelper = m_masterKey.GetPinHelper( m_pin ); m_masterKey.Decrypt( pinHelper ); GetClaims().Decrypt( pinHelper ); } // // Summary: // Retrieve the infocard masterkey. // public byte[ ] Key { get { return ( null == m_masterKey ) ? null : m_masterKey.Key; } } // // Summary: // Use this function to clear the bytes of the masterkey buffer // public void ClearSensitiveData() { // // Expect masterkey to be null for read only requests // if( null != m_masterKey ) { Array.Clear( m_masterKey.Key, 0, m_masterKey.Key.Length ); } } // // Summary // Generate salt for the Infocard. To be used for // setting infocard properties piece meal // // Returns // The generated salt // public static byte[ ] GenerateSalt() { byte[ ] salt = new byte[ SaltSize ]; RNGCryptoServiceProvider prov = new RNGCryptoServiceProvider(); prov.GetBytes( salt ); return salt; } public void ThrowIfNotComplete() { if( !IsComplete() ) { throw IDT.ThrowHelperError( new SerializationIncompleteException( this.GetType() ) ); } } // // Summary // Provides an indication of whether the required members of the InfoCard class // all properly specified. // // Remarks // This function is useful to determine if the object is ready to be persisted. // If an object is not complete or contains nulls for certain values the serialization // code will not work. // // Returns // true - object is complete // false - object is incomplete // public bool IsComplete() { // // Verify that the infocard has been populated. // bool complete = ( !string.IsNullOrEmpty( m_language ) && null != m_id && null != m_issuer && !Utility.ArrayIsNullOrEmpty( m_tokenTypes ) && // Card is expected to have at least one token type null != m_privacyPolicyLink && !Utility.ArrayIsNullOrEmpty( m_salt ) && m_epoch > 0 && DateTime.MinValue != m_issuedOn && DateTime.MinValue != m_expiresOn && DateTime.MinValue != m_lastUpdate ); if( !IsSelfIssued ) { complete = complete && CreationParameters.Count > 0 && null != m_issuerIdentifierAsBytes; } return complete; } // // Summary: // Private function, only to be used by GetPrivate/PublicCryptography // // private RSACryptoServiceProvider GetPrivateKeyPairRsaProvider( string recipientIdentifier ) { // // Perform a lookup to get the LedgerEntry associated with this recipient // LedgerEntry entry = TryGetLedgerEntry( m_storeConnection, recipientIdentifier ); IDT.Assert( null != entry, "null ledger" ); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider( InfoCard.KeySize ); rsa.ImportCspBlob( entry.SubjectKey ); return rsa; } // // Summary // Generates and returns an instance of an RSACryptoProvider for signing // using the pair-wise key associated with the recipient whose recipientIdentifier is // specified. // // Remarks // The RSA key pair is retrieved from the LedgerEntry associated with the specified // recipient. // // Parameters // recipientIdentifier - a unique identifier to identify the recipient // // Returns // An RSACryptoServiceProvider containing the pair-wise key pair from the ledger entry. // Includes private key info. // public RSACryptoServiceProvider GetPrivateCryptography( string recipientIdentifier ) { RSACryptoServiceProvider rsa = GetPrivateKeyPairRsaProvider( recipientIdentifier ); return rsa; } // // Summary // Generates and returns an instance of an RSACryptoProvider for signing // using the pair-wise key associated with the recipient whose recipientIdentifier is // specified. // // Remarks // The RSA key pair is retrieved from the LedgerEntry associated with the specified // recipient. // // Parameters // recipientIdentifier - a unique identifier to identify the recipient // // Returns // An RSACryptoServiceProvider containing the pair-wise key pair from the ledger entry. // Only has public key info. // public RSACryptoServiceProvider GetPublicCryptography( string recipientIdentifier ) { RSACryptoServiceProvider rsa = GetPrivateKeyPairRsaProvider( recipientIdentifier ); // // Recreate it with just the public part // rsa.ImportCspBlob( rsa.ExportCspBlob( false ) ); IDT.Assert( rsa.PublicOnly, "GetPublicCryptography returns a public only rsa" ); return rsa; } // // Summary // Write binary sequence of instance members to the provided stream. // // Remarks // This method will verify that the instance has been fully populated by calling // ThrowIfNotComplete() to confirm that all required fields have been populated. // All members are serialized using fixed length (or counted) types in little-endian format (e.g. Int64). // Strings are serialized using a counted array of unicode characters. // // Parameters // stream - binary stream conforming to the serialization format supported by this class. // private void Serialize( System.IO.Stream stream ) { // // Make sure that we don't serialize an incomplete object. Serializing null values will result in a // serialization exception or a corrupt signature. // ThrowIfNotComplete(); // // Setup a BinaryWriter to serialize the bytes of each member to the provided stream // System.IO.BinaryWriter writer = new BinaryWriter( stream, Encoding.Unicode ); // // Write each member to binary stream // writer.Write( Version ); writer.Write( (Int64)m_expiresOn.ToFileTimeUtc() ); writer.Write( m_epoch ); Utility.SerializeUri( writer, m_id ); writer.Write( (Int64)m_issuedOn.ToFileTimeUtc() ); writer.Write( m_isImported ); writer.Write( (Int64)m_installedOn.ToFileTimeUtc() ); writer.Write( m_isSelfIssued ); Utility.SerializeUri( writer, m_issuer ); Utility.SerializeString( writer, m_issuerName ); Utility.SerializeBytes( writer, m_issuerIdentifierAsBytes ); Utility.SerializeString( writer, m_language ); Utility.SerializeBytes( writer, m_logo ); Utility.SerializeString( writer, m_mimeType ); Utility.SerializeString( writer, m_name ); writer.Write( (Int64)m_lastUpdate.ToFileTimeUtc() ); writer.Write( m_backgroundColor ); writer.Write( (byte)m_requireAppliesTo ); Utility.SerializeString( writer, m_privacyPolicyLink ); writer.Write( m_privacyPolicyVersion ); Utility.SerializeBytes( writer, m_pinHash ); Utility.SerializeBytes( writer, m_salt ); writer.Write( (Int32)m_tokenTypes.Length ); for( int i = 0; i < m_tokenTypes.Length; i++ ) { Utility.SerializeString( writer, m_tokenTypes[ i ] ); } // // Serialize the list of identity provider end point information. // Note: This list will be empty on self issued cards // writer.Write( ( null == m_creationParameters ? (Int32)0 : m_creationParameters.Count ) ); if( null != m_creationParameters ) { for( int i = 0; i < m_creationParameters.Count; i++ ) { m_creationParameters[ i ].Serialize( writer ); } } // // We will never serialize the pins out of the service. These must be supplied by the // service in order to unlock pin protected cards. // Utility.SerializeString( writer, String.Empty ); Utility.SerializeString( writer, String.Empty ); writer.Write( (byte)m_pinAction ); writer.Write( Marker ); } public void AgentSerialize( System.IO.Stream stream, bool initCalcAttributesForGetToken, InfoCardPolicy policy, StoreConnection storeConnection, CultureInfo userCulture ) { // // Serialize the infocard // this.Serialize( stream ); // // Consider for future -- see bug 38733 -- If we have the context object in place // we do not need to do this // // // The store connection has to always be set before // any information is retrieved from the store. Don't call GetClaims() // or GetExtendedInformation() before doing the step below. // m_storeConnection = storeConnection; GetRPIdentityRequirement().Serialize( stream ); GetExtendedInformation().Serialize( stream ); string issuerInformation = GetExtendedInformation().GetIssuerInformationElement(); InfoCard.GetIssuerInformation( issuerInformation ).Serialize( stream ); // // Serialize the claims. Claims must already have been populated // InfoCardClaimCollection claimCollection = GetClaims(); // // Add the ppid claim here // if( null != policy && IsSelfIssued ) { CultureInfo backup = System.Threading.Thread.CurrentThread.CurrentUICulture; // // Change the culture before reading the claim strings // try { System.Threading.Thread.CurrentThread.CurrentUICulture = userCulture; string ppidStr = Utility.CreatePpid( Convert.FromBase64String( policy.ImmediateTokenRecipient.GetOrganizationPPIDIdentifier() ), m_id ); claimCollection.Add( new InfoCardClaim( InfoCardConstants.PPIDClaimsUri, ppidStr, InfoCardConstants.ClaimsDescription( InfoCardConstants.PPID ), InfoCardConstants.ClaimDisplayTag( InfoCardConstants.PPID ) ) ); } finally { System.Threading.Thread.CurrentThread.CurrentUICulture = backup; } } // // Now serialize all the claims // claimCollection.AgentSerialize( stream ); BinaryWriter writer = new BinaryWriter( stream, System.Text.Encoding.Unicode ); // // Serialize the calculated attributes // if( initCalcAttributesForGetToken ) { writer.Write( DoesCardMatchPolicySet( policy ) ); writer.Write( CardMatchesPolicyRequiredIssuer( policy ) ); writer.Write( HasCardBeenUsedBefore( policy.Recipient.GetIdentifier(), storeConnection ) ); writer.Write( HaveRequestedClaimsChanged( policy, storeConnection ) ); writer.Write( WillSendAppliesToInRst( policy ) ); writer.Write( DoesCardSupportAnyOptionalClaims( policy ) ); writer.Write( DoesCardMatchNonClaimPolicyRequirements( policy ) ); } else { writer.Write( false ); writer.Write( false ); writer.Write( false ); writer.Write( false ); writer.Write( false ); writer.Write( false ); writer.Write( false ); } writer.Flush(); } // // Summary: // Copy the metadata of a card to another card // // Parameters: // card - card from from which data should be copied // public void CopyMetaData( InfoCard card ) { this.m_salt = new byte[ card.HashSalt.Length ]; Array.Copy( card.HashSalt, 0, this.m_salt, 0, card.HashSalt.Length ); this.m_pinHash = new byte[ card.m_pinHash.Length ]; Array.Copy( card.m_pinHash, 0, this.m_pinHash, 0, card.m_pinHash.Length ); } // // Summary: // Return true if this card can support any of the optional claims in the policy // // Parameters: // policy - Pointer to the incoming policy. // bool DoesCardSupportAnyOptionalClaims( InfoCardPolicy policy ) { List optionalClaims = new List ( policy.OptionalClaims ); foreach( string s in this.GetClaims().Keys ) { if( optionalClaims.Contains( s ) ) { return true; } } return false; } // // Summary: // Return true if appliesTo is to be sent in the RST // // Parameters: // policy - Pointer to the incoming policy. // bool WillSendAppliesToInRst( InfoCardPolicy policy ) { AppliesToBehaviorDecision decision = AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForPolicyMatch( policy, this.RequireAppliesto ); if( AppliesToBehaviorDecision.SendCustomAppliesTo == decision || AppliesToBehaviorDecision.SendRPAppliesTo == decision ) { return true; } else { return false; } } // // Summary // Populates the instance members from a binary stream of serialized data. // // Remarks // This method will be used to support the construction of an instance of // an InfoCard class after marshalling from the database or from the UI Agent. // All members are serialized using fixed length (or counted) types in little-endian format (e.g. Int64). // Strings are serialized using a counted array of unicode characters. // // Parameters // stream - binary stream conforming to the serialization format supported by this class. // // // Notes // Making this private. Use constructor instead of calling this directly. // private void Deserialize( System.IO.Stream stream ) { // // Populate each member from the stream // BinaryReader reader = new InfoCardBinaryReader( stream, Encoding.Unicode ); // // Check the version // if( InfoCard.Version != reader.ReadByte() ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.ServiceCardWrongVersion ) ); } m_expiresOn = DateTime.FromFileTimeUtc( (long)reader.ReadInt64() ); m_epoch = reader.ReadUInt32(); m_id = new System.Uri( Utility.DeserializeString( reader ) ); m_issuedOn = DateTime.FromFileTimeUtc( (long)reader.ReadInt64() ); m_isImported = reader.ReadBoolean(); m_installedOn = DateTime.FromFileTimeUtc( (long)reader.ReadInt64() ); m_isSelfIssued = reader.ReadBoolean(); m_issuer = Utility.DeserializeUri( reader ); m_issuerName = Utility.DeserializeString( reader ); int keyLen = reader.ReadInt32(); m_issuerIdentifierAsBytes = reader.ReadBytes( keyLen ); m_language = Utility.DeserializeString( reader ); int logoLen = reader.ReadInt32(); IDT.Assert( 0 <= logoLen && logoLen < Constants.Maxima.LogoLength, "logo length out of range {0}", logoLen ); m_logo = reader.ReadBytes( logoLen ); m_mimeType = Utility.DeserializeString( reader ); m_name = Utility.DeserializeString( reader ); m_lastUpdate = DateTime.FromFileTimeUtc( (long)reader.ReadInt64() ); m_backgroundColor = reader.ReadInt32(); m_requireAppliesTo = (RequireAppliesToStatus)reader.ReadByte(); m_privacyPolicyLink = Utility.DeserializeString( reader ); m_privacyPolicyVersion = reader.ReadUInt32(); int hashLen = reader.ReadInt32(); IDT.Assert( 0 <= hashLen && hashLen < Constants.Maxima.PinHashLength, "pin hash out fo range {0}", hashLen ); m_pinHash = reader.ReadBytes( hashLen ); int saltLen = reader.ReadInt32(); IDT.Assert( 0 <= saltLen && saltLen < Constants.Maxima.SaltLength, "salt length out of range {0}", saltLen ); m_salt = reader.ReadBytes( saltLen ); Int32 tokenTypeCount = reader.ReadInt32(); IDT.Assert( Constants.Maxima.TokenTypes > tokenTypeCount, "too many token types" ); m_tokenTypes = new String[ tokenTypeCount ]; for( int i = 0; i < tokenTypeCount; i++ ) { m_tokenTypes[ i ] = Utility.DeserializeString( reader ); } Int32 creationParamCount = reader.ReadInt32(); IDT.Assert( 0 <= creationParamCount && creationParamCount < Constants.Maxima.CreationParameters, "creation parametes out of range {0}", creationParamCount ); for( int i = 0; i < creationParamCount; i++ ) { TokenCreationParameter parameter = new TokenCreationParameter(); parameter.Deserialize( reader ); CreationParameters.Add( parameter ); } m_pin = Utility.DeserializeString( reader ); m_oldPin = Utility.DeserializeString( reader ); m_pinAction = (PinAction)reader.ReadByte(); // // Validate the end of the buffer // if( Marker != reader.ReadByte() ) { IDT.Assert( false, "malformed stream detected" ); } // // Just a correctness check // ThrowIfNotComplete(); } // // Summary // This function is invoked by the RemoteTokenFactory (before RST to IP/STS) // to figure out which claims we'll request from the IP/STS // // Arguments // policy - the incoming recipient policy // discloseOptional - Specifies whether optional claims are to be disclosed. // public Dictionary GetClaimsToBeDisclosed( InfoCardPolicy policy, bool discloseOptional ) { Dictionary claimsToBeDisclosed = new Dictionary ( policy.RequiredClaims.Length ); for( int i = 0; i < policy.RequiredClaims.Length; i++ ) { claimsToBeDisclosed.Add( policy.RequiredClaims[ i ], false ); } // // Only disclose optional claims if user has chosen to disclose optional claims. // if( discloseOptional ) { for( int i = 0; i < policy.OptionalClaims.Length; i++ ) { // // If optional claim in policy present in card, that means we'll send to the IP/STS // Therefore, such a claim is also a disclosed claim // string optUri = policy.OptionalClaims[ i ]; if( this.GetClaims().ContainsKey( optUri ) ) { // // Track optional claim by passing in true as 2nd arg // claimsToBeDisclosed.Add( policy.OptionalClaims[ i ], true ); } } } return claimsToBeDisclosed; } // // Summary // Find if the card matches a given policy // // Parameters // policy - Policy of the RP // // Return // True if card matches the policy requirements, false otherwise. // public bool DoesCardMatchPolicySet( InfoCardPolicy policy ) { IDT.TraceDebug( " Matching card {0} for token policy requirements", m_name ); IDT.Assert( null != policy, "null policy" ); bool hasRequiredClaims = true; List supportedClaims = new List ( this.SupportedClaimTypes ); if ( null != policy.RequiredClaims ) { foreach ( string policyClaim in policy.RequiredClaims ) { // // If a required claim is not found in the claims supported by the card // set the card as not matching requirements // if ( !supportedClaims.Contains( policyClaim ) ) { // // For self issued cards, do not include PPID claim as a search criteria // This is because the PPID claim is not stored as a part of the infocard claims // list, but it is generated on demand by the local STS. // if ( !(IsSelfIssued && InfoCardConstants.PPIDClaimsUri == policyClaim) ) { hasRequiredClaims = false; break; } } } } return ( hasRequiredClaims && DoesCardMatchNonClaimPolicyRequirements( policy ) ); } // // Summary // Find if the given card matches a given policy, except for the claims requirement // // Parameters // policy - Policy of the RP // // Return // True if card matches the policy requirements other than claim requirements, false otherwise // public bool DoesCardMatchNonClaimPolicyRequirements( InfoCardPolicy policy ) { IDT.Assert( null != policy, "null policy" ); // // For a managed card if RP specifies AppliesTo and the card // does not specify RequireAppliesTo then the card does not match // bool appliesTocheck = true; if( !this.IsSelfIssued && AppliesToBehaviorDecision.FailMatch == AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForPolicyMatch( policy, this.RequireAppliesto ) ) { appliesTocheck = false; } bool meetsIdentityRequirement = true; if( GetRPIdentityRequirement().StrongIdentityRequired && !(policy.ImmediateTokenRecipient is X509RecipientIdentity) ) { meetsIdentityRequirement = false; } // // Self issued cards should not match policy if a managed card is required // return ( !( IsSelfIssued && policy.RequiresManagedCard ) && CardMatchesPolicyTokenType( policy ) && CardMatchesPolicyRequiredIssuer( policy ) && appliesTocheck && meetsIdentityRequirement ); } // // Summary // Find if the requires claims are a subset of the claims last // disclosed by the user. // // Parameters // policy - Policy of the RP // connection - the store connection // // Return // True if the set of requested claims has changed and false otherwise // public bool HaveRequestedClaimsChanged( InfoCardPolicy policy, StoreConnection connection ) { IDT.TraceDebug( "NeedApprovalForRequiredClaims: CardName={0}", m_name ); IDT.Assert( null != m_id, "Null id" ); IDT.Assert( null != policy, "null policy" ); IDT.Assert( null != connection, "null connection" ); LedgerEntry le = TryGetLedgerEntry( connection, policy.Recipient.GetIdentifier() ); if( null == le ) { IDT.TraceDebug( "Claims have changed: no ledger entry. CardName={0}", m_name ); return true; } IList disclosedClaims = le.DisclosedClaims ?? new string[ 0 ]; int count = 0; if( null != policy.RequiredClaims ) { count = policy.RequiredClaims.Length; } // // If |requiredClaims| > |disclosedClaims|, it's clearly not a subset. // if( count > disclosedClaims.Count ) { IDT.TraceDebug( "Claims have changed: more required claims. CardName={0}", m_name ); return true; } // // Otherwise, each required claim must appear in disclosedClaims. // bool found = true; foreach( string claim in policy.RequiredClaims ) { if( !disclosedClaims.Contains( claim ) ) { IDT.TraceDebug( "Claims have changed: new required claim. CardName={0} ClaimName={1}", m_name, claim ); found = false; break; } } if( found ) { IDT.TraceDebug( "Claims have not changed. CardName={0}", m_name ); } return !found; } // // Summary // Find if the card matches a the token type requirements of the IP // // Parameters // policy - Policy of the RP // connection - the store connection // // Return // True if card matches the policy requirements, false otherwise // private bool CardMatchesPolicyTokenType( InfoCardPolicy policy ) { // // Check if card matches the token type requirement // IDT.TraceDebug( "Check if card matches token type requirement of policy" ); if( String.IsNullOrEmpty( policy.OptionalRstParams.TokenType ) ) { IDT.TraceDebug( "No token type specified in policy" ); return true; } else { foreach( String type in m_tokenTypes ) { if( type == policy.OptionalRstParams.TokenType ) { IDT.TraceDebug( " Type in card {0} matches type {1} in policy ", type, policy.OptionalRstParams.TokenType ); return true; } IDT.TraceDebug( " Type in card {0} does not match type {1} in policy ", type, policy.OptionalRstParams.TokenType ); } } return false; } // // Summary // Find if the card is issued by the issuer required by the RP // // Parameters // policy - Policy of the RP // // Return // True if card matches the policy requirements, false otherwise // private bool CardMatchesPolicyRequiredIssuer( InfoCardPolicy policy ) { // // Check if the card is issued by the issuer requested by the RP // if( null == policy.Issuer || null == policy.Issuer.Uri || Utility.CompareUri( policy.Issuer.Uri, XmlNames.WSIdentity.AnonymousIssuerUriValue ) ) { IDT.TraceDebug( " Card matches null or anonymous issuer policy. Name={0} ", m_name ); return true; } if( m_isSelfIssued && Utility.CompareUri( policy.Issuer.Uri, XmlNames.WSIdentity.SelfIssuerUriValue ) ) { IDT.TraceDebug( " Card matches self-issuer policy. Name={0} ", m_name ); return true; } if( !m_isSelfIssued && Utility.CompareUri( policy.Issuer.Uri, m_issuer ) ) { IDT.TraceDebug( " Card matches explicit issuer policy. Name={0}; Issuer={1} ", m_name, m_issuer ); return true; } return false; } // // Summary // Find if the card has been used before with this recipient // // Parameters // recipientId - RecipientId of the RP's cert. // connection - the store connection // // Return // True if card has been used before, false otherwise // public bool HasCardBeenUsedBefore( string recipientId, StoreConnection connection ) { return null != connection.GetSingleRow( QueryDetails.Identifiers, new QueryParameter( SecondaryIndexDefinition.ObjectTypeIndex, (Int32)StorableObjectType.LedgerEntry ), new QueryParameter( SecondaryIndexDefinition.RecipientIdIndex, recipientId ), new QueryParameter( SecondaryIndexDefinition.ParentIdIndex, GlobalId.DeriveFrom( m_id.ToString() ) ) ); } // // Summary // Retrieves an InfoCard from the store using the specified connection. // // Remarks // The m_id must be populated for this call to work. // The m_rowId is cached as part of this call allowing // subsequent database calls to be more efficient. // The InfoCard will be retrieved from the roaming portion of the store. // // Parameters // con - The connection to the InfoCard store to be used for the query. // public void Get( StoreConnection con ) { IDT.Assert( null != m_id, "null id" ); IDT.Assert( null != con, "null connection" ); // // Cache the connection to enable lazy retrieval of the ledger and claims // m_storeConnection = con; // // Retrieve the row for the object from the database // DataRow row = GetRow( con, QueryDetails.FullRow ); // // Populate the infocard using the byte array // Deserialize( new MemoryStream( row.GetDataField() ) ); // // Update the row id from the database // m_rowId = row.LocalId; } // // Summary // Updates or inserts the InfoCard instance into the roaming portion of the store using // the specified connection. // // Remarks // The object must be complete for this operation to succeed. // The store global Id will be a hash of the URI of the card. // // Parameters // con - The connection to the InfoCard store to be used for the query. // public void Save( StoreConnection con ) { ThrowIfNotComplete(); IDT.Assert( null != con, "null connection" ); IDT.TraceDebug( "CARD: Saving..." ); IDT.TraceDebug( "CARD: {0}", this.ToString() ); // // Try and get the database header information to // see if this is an insert or update. // // Note: The datafield is not part of the projection // in order to avoid unecessary decryption. // DataRow row = TryGetRow( con, QueryDetails.FullHeader ); bool masterKeyChanged = false; if( null == row ) { // // If this is a new card create a new master key // For an imported card from a store, the master key will already be present // if( null == m_masterKey ) { m_masterKey = InfoCardMasterKey.NewMasterKey( m_id ); } masterKeyChanged = true; row = new DataRow(); row.ObjectType = (Int32)StorableObjectType.InfoCard; row.GlobalId = GlobalId.DeriveFrom( m_id.ToString() ); } InfoCardClaimCollection plainTextClaims = null; switch( m_pinAction ) { case PinAction.NoPin: { // // No pin protection necessary: no action // break; } case PinAction.PinSame: { // // A pin protected card has been saved, but the // pin has not been changed. So simply encrypt the // claims with the key generated using the specified pin // and the key info from the master key in the store. // // // Save the unencrypted claims so we can return // the object unencrypted // plainTextClaims = m_claims.Clone(); GetMasterKey( con ); m_claims.Encrypt( m_masterKey.GetPinHelper( m_pin ) ); break; } case PinAction.PinAdded: { // // New pin needs to be applied: // Generate a new key using the specified PIN // Encrypt the master key // Encrypt the claims // Store the keyinfo and encrypted master key in the store. // Store the encrypted claims in the store. // // // Save the unencrypted claims so we can return // the object unencrypted // plainTextClaims = m_claims.Clone(); GetMasterKey( con ); PinProtectionHelper pinHelper = new PinProtectionHelper( m_pin ); m_masterKey.Encrypt( pinHelper ); m_claims.Encrypt( pinHelper ); masterKeyChanged = true; break; } case PinAction.PinRemoved: { // // Pin needs to be removed: // Decrypt the master key with the pin and // params from the stored master key // Store the master key in the store // Store the claims in plain text // GetMasterKey( con ); m_masterKey.Decrypt( m_masterKey.GetPinHelper( m_oldPin ) ); masterKeyChanged = true; break; } case PinAction.PinChanged: { // // A pin protected card had it's pin changed // So decrypt the master key and then encrypt it and // the claims with the new pin // Store the key info with the encrypted master key // Store the encrypted claims // // // Save the unencrypted claims so we can return // them unencrypted // plainTextClaims = m_claims.Clone(); GetMasterKey( con ); m_masterKey.Decrypt( m_masterKey.GetPinHelper( m_oldPin ) ); PinProtectionHelper pinHelper = new PinProtectionHelper( m_pin ); m_masterKey.Encrypt( pinHelper ); m_claims.Encrypt( pinHelper ); masterKeyChanged = true; break; } default: break; } if( masterKeyChanged ) { // // The master key was modified so save the changes // to the store. // m_masterKey.Save( con ); } // // Update the pin action to the appropriate value so that // the agent has the proper default. // m_pinAction = IsPinProtected ? PinAction.PinSame : PinAction.NoPin; // // Populate the index fields // string[ ] issuer; if( IsSelfIssued ) { issuer = new String[ ] { XmlNames.WSIdentity.SelfIssuerUri }; } else { // // Calculate the array of tuples // issuer = new string[ CreationParameters.Count ]; int i = 0; foreach( TokenCreationParameter param in CreationParameters ) { issuer[ i++ ] = param.Epr.Uri.ToString(); } } row.SetIndexValue( SecondaryIndexDefinition.ProductionServiceIndex, issuer ); IDT.Assert( null != m_claims, "Must already be initialized at this point" ); row.SetIndexValue( SecondaryIndexDefinition.SupportedClaimIndex, SupportedClaimTypes ); if( CreationParameters.Count > 0 ) { object[ ] auth = new object[ CreationParameters.Count ]; int i = 0; foreach( TokenCreationParameter param in CreationParameters ) { auth[ i++ ] = (Int32)param.CredentialType; } row.SetIndexValue( SecondaryIndexDefinition.SupportedAuthIndex, auth ); } // // Populate the data object // MemoryStream ms = new MemoryStream(); Serialize( ms ); row.SetDataField( ms.ToArray() ); // // Save the InfoCard row to the database // con.Save( row ); // // Update the row id in the object in case // this was an insert. // m_rowId = row.LocalId; // // Save the extended card information in case it exists // if( null != m_extendedInformation ) { m_extendedInformation.Save( con ); } // // Write the claims collection row to the store // m_claims.Save( con, m_isSelfIssued ); // // Restore the claims back to the plain text version // if necessary // if( null != plainTextClaims ) { m_claims = plainTextClaims; } GetRPIdentityRequirement().Save( con ); } // // Summary // Creates a string containing the state of the InfoCard. // // Remarks // Members with a byte[] type are omitted. // // Returns // string - Multiline string with InfoCard state information. // public override string ToString() { #if DEBUG StringBuilder sb = new StringBuilder(); sb.AppendFormat( "Dumping InfoCard({0})\n", m_name ); sb.AppendFormat( "Expires On:\t{0}\n", m_expiresOn.ToString() ); sb.AppendFormat( "Epoch:\t\t{0}\n", m_epoch ); sb.AppendFormat( "Id:\t\t{0}\n", m_id.ToString() ); sb.AppendFormat( "Issued On:\t{0}\n", m_issuedOn.ToString() ); sb.AppendFormat( "Issuer Key:\t{0}\n", "Omitted not implemented" ); sb.AppendFormat( "Issuer Name:\t{0}\n", m_issuerName ); sb.AppendFormat( "Key:\t\t{0}\n", "Omitted not implemented" ); sb.AppendFormat( "Language:\t{0}\n", m_language ); sb.AppendFormat( "Logo:\t\t{0}\n", "Omitted not implemented" ); sb.AppendFormat( "Logo MimeType:\t{0}\n", m_mimeType ); sb.AppendFormat( "Name:\t\t{0}\n", m_name ); sb.AppendFormat( "Last Update:\t{0}\n", m_lastUpdate.ToString() ); sb.AppendFormat( "BackGround Color:\t{0}\n", m_backgroundColor.ToString( CultureInfo.InvariantCulture ) ); sb.AppendFormat( "RequireAppliesTo:\t{0}\n", m_requireAppliesTo.ToString() ); sb.AppendFormat( "PrivacyNotice:\t{0}\n", m_privacyPolicyLink ); sb.AppendFormat( "PrivacyNoticeVersion:\t{0}\n", m_privacyPolicyVersion ); return sb.ToString(); #else return base.ToString(); #endif } // // Summary // Create a new card. // // Remarks // This method will be called by the UI to create a new card. The information // that is not filled in, is supposed to be completed within the UI. // public static InfoCard NewCard( CultureInfo userCulture ) { InfoCard card = new InfoCard(); card.m_expiresOn = DateTime.MaxValue; card.m_epoch = 1; card.m_id = new Uri( "urn:uuid:" + Guid.NewGuid().ToString() ); card.m_issuedOn = DateTime.UtcNow; card.m_isImported = false; card.m_installedOn = DateTime.UtcNow; card.m_isSelfIssued = true; card.m_issuerName = SR.GetString( SR.SelfIssuedIssuerName ); card.m_issuer = XmlNames.WSIdentity.SelfIssuerUriValue; card.m_language = userCulture.TwoLetterISOLanguageName; card.m_logo = new byte[ 0 ]; card.m_name = null; card.m_lastUpdate = DateTime.UtcNow; card.m_backgroundColor = 0x00FFFFFF; card.m_requireAppliesTo = RequireAppliesToStatus.NotPresent; card.m_salt = InfoCard.GenerateSalt(); card.m_tokenTypes = new String[ ]{ XmlNames.Saml11.Namespace, XmlNames.Saml11.AltNamespace }; CultureInfo backup = System.Threading.Thread.CurrentThread.CurrentUICulture; // // Change the culture before reading the claim strings // try { System.Threading.Thread.CurrentThread.CurrentUICulture = userCulture; for( int i = 0; i < InfoCardConstants.SelfIssuedClaimsUris.Length; i++ ) { InfoCardClaim claim = new InfoCardClaim( InfoCardConstants.SelfIssuedClaimsUris[ i ], null, InfoCardConstants.ClaimsDescription( InfoCardConstants.SelfIssuedClaimsUris[ i ] ), InfoCardConstants.ClaimDisplayTag( InfoCardConstants.SelfIssuedClaimsUris[ i ] ) ); card.AddClaim( claim ); } } finally { System.Threading.Thread.CurrentThread.CurrentUICulture = backup; } IDT.TraceDebug( "CARD: InfoCard created. Follows:\n{0}", card ); IDT.Assert( null == card.m_masterKey, "Card key is only populated during save" ); return card; } // // Summary // Attempts to retrieve the specified row information from the store // using the specified connection. // // Remarks // The m_id field must be populated for this method to succeed. // // Parameters // con - The connection to the InfoCard store to be used for the query. // details - Identifies the projection (think columns) of data to be returned. // Since the data field must be decrypted before returning avoid projecting it if possible. // // Returns // Will always return a row. If a row is not found an exception will be thrown. // protected DataRow GetRow( StoreConnection con, QueryDetails details ) { IDT.Assert( null != con, " null connection" ); DataRow row = TryGetRow( con, details ); // // Verify that an infocard row was returned // IDT.Assert( null != row, "null row" ); IDT.Assert( (Int32)StorableObjectType.InfoCard == row.ObjectType, "Attempt to deserialize an incorrect object type {0}", row.ObjectType ); return row; } // // Summary // Attempts to retrieve the specified row information from the store // using the specified connection. // // Remarks // The m_id field must be populated for this method to succeed. // Called by GetRow() // // Parameters // con - The connection to the InfoCard store to be used for the query. // details - Identifies the projection (think columns) of data to be returned. // Since the data field must be decrypted before returning avoid projecting it if possible. // // Returns // Will return null if the row associated with the m_id is not found. // protected DataRow TryGetRow( StoreConnection con, QueryDetails details ) { IDT.Assert( null != m_id, "null id" ); IDT.Assert( null != con, "null connection" ); // // Retrieve a single object from the database. // DataRow row = con.GetSingleRow( details, new QueryParameter( SecondaryIndexDefinition.GlobalIdIndex, GlobalId.DeriveFrom( m_id.ToString() ) ) ); return row; } // // Summary // Read the infocard from the xml. The reader should be either at the // InfoCard element or the RoamingInfoCard element. // // Parameters // reader - The XmlReader to read data from // public void ReadXml( XmlReader reader ) { if( XmlNames.WSIdentity.RoamingInfoCardElement == reader.LocalName ) { ReadRoamingInfoCard( reader ); } else if( XmlNames.WSIdentity.InfoCardElement == reader.LocalName ) { ReadImportedInfoCard( reader ); } else { IDT.Assert( false, "Invalid element found. Did schema validation fail? Found {0}", reader.LocalName ); } } public XmlSchema GetSchema() { return null; } // // Summary // Write the infocard to xml. // // Parameters // writer - The XmlWriter to write the data to // public void WriteXml( XmlWriter writer ) { ThrowIfNotComplete(); writer.WriteStartElement( XmlNames.WSIdentity.RoamingInfoCardElement, XmlNames.WSIdentity.Namespace ); writer.WriteStartElement( XmlNames.WSIdentity.InfoCardMetaDataElement, XmlNames.WSIdentity.Namespace ); writer.WriteAttributeString( XmlNames.Xml.Language, XmlNames.Xml.Namespace, m_language ); // // infocard reference - card id and version // writer.WriteStartElement( XmlNames.WSIdentity.InfoCardRefElement, XmlNames.WSIdentity.Namespace ); writer.WriteStartElement( XmlNames.WSIdentity.CardIdElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( m_id.AbsoluteUri ); writer.WriteEndElement(); writer.WriteStartElement( XmlNames.WSIdentity.CardVersionElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( m_epoch.ToString( CultureInfo.InvariantCulture ) ); writer.WriteEndElement(); writer.WriteEndElement(); // // card name // if( !String.IsNullOrEmpty( m_name ) ) { writer.WriteStartElement( XmlNames.WSIdentity.CardNameElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( m_name ); writer.WriteEndElement(); } // // card image // if( null != m_logo && 0 != m_logo.Length ) { writer.WriteStartElement( XmlNames.WSIdentity.CardImageElement, XmlNames.WSIdentity.Namespace ); if( !String.IsNullOrEmpty( m_mimeType ) ) { writer.WriteAttributeString( XmlNames.WSIdentity.MimeTypeAttribute, m_mimeType ); } string val = Convert.ToBase64String( m_logo ); writer.WriteString( val ); writer.WriteEndElement(); } // // card issuer id // writer.WriteStartElement( XmlNames.WSIdentity.IssuerElement, XmlNames.WSIdentity.Namespace ); if( null != m_issuer ) { writer.WriteString( m_issuer.AbsoluteUri ); } writer.WriteEndElement(); // // issue time // writer.WriteStartElement( XmlNames.WSIdentity.TimeIssuedElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( XmlConvert.ToString( m_issuedOn, XmlDateTimeSerializationMode.Utc ) ); writer.WriteEndElement(); // // expiry time // writer.WriteStartElement( XmlNames.WSIdentity.TimeExpiresElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( XmlConvert.ToString( m_expiresOn, XmlDateTimeSerializationMode.Utc ) ); writer.WriteEndElement(); // // authentication info // if( null != m_creationParameters ) { writer.WriteStartElement( XmlNames.WSIdentity.TokenServiceListElement, XmlNames.WSIdentity.Namespace ); foreach( TokenCreationParameter param in m_creationParameters ) { param.WriteXml( writer ); } writer.WriteEndElement(); } // // tokentypes // writer.WriteStartElement( XmlNames.WSIdentity.SupportedTokenTypeListElement, XmlNames.WSIdentity.Namespace ); foreach( string type in m_tokenTypes ) { writer.WriteElementString( XmlNames.WSTrustXmlSoap2005.c_TokenType, XmlNames.WSTrustXmlSoap2005.c_Namespace, type ); } writer.WriteEndElement(); // // claims // writer.WriteStartElement( XmlNames.WSIdentity.SupportedClaimTypeListElement, XmlNames.WSIdentity.Namespace ); foreach( string clmId in GetClaims().Keys ) { InfoCardClaim claim = GetClaims()[ clmId ]; // // For self-issued cards the private personal identifier // claim must not be written to the roaming store file. // if( m_isSelfIssued && Utility.CompareUri( claim.Id, InfoCardConstants.PPIDClaimsUri ) ) { continue; } writer.WriteStartElement( XmlNames.WSIdentity.SupportedClaimTypeElement, XmlNames.WSIdentity.Namespace ); writer.WriteAttributeString( XmlNames.WSIdentity.UriAttribute, claim.Id ); if( !String.IsNullOrEmpty( claim.DisplayTag ) ) { writer.WriteElementString( XmlNames.WSIdentity.DisplayTagElement, XmlNames.WSIdentity.Namespace, claim.DisplayTag ); } if( !String.IsNullOrEmpty( claim.Description ) ) { writer.WriteElementString( XmlNames.WSIdentity.DescriptionElement, XmlNames.WSIdentity.Namespace, claim.Description ); } writer.WriteEndElement(); } writer.WriteEndElement(); // // RequireAppliesTo // if( RequireAppliesToStatus.NotPresent != m_requireAppliesTo ) { writer.WriteStartElement( XmlNames.WSIdentity.RequireAppliesToElement, XmlNames.WSIdentity.Namespace ); if( RequireAppliesToStatus.Optional == m_requireAppliesTo ) { writer.WriteAttributeString( XmlNames.WSIdentity.OptionalAttribute, "true" ); } writer.WriteEndElement(); } // // privacy notice // if( !String.IsNullOrEmpty( m_privacyPolicyLink ) ) { writer.WriteStartElement( XmlNames.WSIdentity.PrivacyNoticeAtElement, XmlNames.WSIdentity.Namespace ); if( 0 < m_privacyPolicyVersion ) { writer.WriteAttributeString( XmlNames.WSIdentity.PrivacyNoticeVersionAttribute, m_privacyPolicyVersion.ToString( CultureInfo.InvariantCulture ) ); } writer.WriteString( m_privacyPolicyLink ); writer.WriteEndElement(); } if( GetRPIdentityRequirement().StrongIdentityRequired ) { writer.WriteStartElement( XmlNames.WSIdentity07.RequireStrongRPIdentity, XmlNames.WSIdentity07.Namespace ); writer.WriteEndElement(); } // // Issuer information // if( null != GetExtendedInformation() ) { foreach( InfocardExtendedInformationEntry entry in m_extendedInformation ) { entry.WriteXml( writer ); } } // // card type // writer.WriteStartElement( XmlNames.WSIdentity.IsSelfIssuedElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( XmlConvert.ToString( m_isSelfIssued ) ); writer.WriteEndElement(); // // card pin // if( !Utility.ArrayIsNullOrEmpty( m_pinHash ) ) { writer.WriteStartElement( XmlNames.WSIdentity.PinDigestElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( Convert.ToBase64String( m_pinHash ) ); writer.WriteEndElement(); } // // card salt // writer.WriteStartElement( XmlNames.WSIdentity.HashSaltElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( Convert.ToBase64String( m_salt ) ); writer.WriteEndElement(); // // update time // writer.WriteStartElement( XmlNames.WSIdentity.TimeLastUpdatedElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( XmlConvert.ToString( m_lastUpdate, XmlDateTimeSerializationMode.Utc ) ); writer.WriteEndElement(); // // issuer key // writer.WriteStartElement( XmlNames.WSIdentity.IssuerIdElement, XmlNames.WSIdentity.Namespace ); if( null != m_issuerIdentifierAsBytes ) { writer.WriteString( Convert.ToBase64String( m_issuerIdentifierAsBytes, Base64FormattingOptions.None ) ); } writer.WriteEndElement(); // // card issuer name // writer.WriteStartElement( XmlNames.WSIdentity.IssuerNameElement, XmlNames.WSIdentity.Namespace ); if( !String.IsNullOrEmpty( m_issuerName ) ) { writer.WriteString( m_issuerName ); } writer.WriteEndElement(); // // backgroundcolour // writer.WriteStartElement( XmlNames.WSIdentity.BackgroundColorElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( XmlConvert.ToString( m_backgroundColor ) ); writer.WriteEndElement(); // // end of InfoCardMetaData element // writer.WriteEndElement(); // // Start writing the private data // writer.WriteStartElement( XmlNames.WSIdentity.InfoCardPrivateDataElement, XmlNames.WSIdentity.Namespace ); // // card key // IDT.Assert( null != m_masterKey, "Masterkey Cannot be null when trying to export a card" ); writer.WriteStartElement( XmlNames.WSIdentity.MasterKeyElement, XmlNames.WSIdentity.Namespace ); writer.WriteString( Convert.ToBase64String( m_masterKey.Key ) ); writer.WriteEndElement(); if( IsSelfIssued ) { writer.WriteStartElement( XmlNames.WSIdentity.ClaimValueListElement, XmlNames.WSIdentity.Namespace ); foreach( string clmId in GetClaims().Keys ) { InfoCardClaim claim = GetClaims()[ clmId ]; // // For self-issued cards the private personal identifier // claim must not be written to the roaming store file. // if( Utility.CompareUri( claim.Id, InfoCardConstants.PPIDClaimsUri ) ) { continue; } writer.WriteStartElement( XmlNames.WSIdentity.ClaimValueElement, XmlNames.WSIdentity.Namespace ); writer.WriteAttributeString( XmlNames.WSIdentity.UriAttribute, claim.Id ); if( !String.IsNullOrEmpty( claim.Value ) ) { writer.WriteElementString( XmlNames.WSIdentity.ValueElement, XmlNames.WSIdentity.Namespace, claim.Value ); } else { writer.WriteElementString( XmlNames.WSIdentity.ValueElement, XmlNames.WSIdentity.Namespace, String.Empty ); } writer.WriteEndElement(); } writer.WriteEndElement(); } // // end of InfoCardPrivateData element // writer.WriteEndElement(); // // end of Roaming Infocard element // writer.WriteEndElement(); } private void ReadImportedInfoCard( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.InfoCardElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } this.Language = reader.GetAttribute( XmlNames.Xml.Language, XmlNames.Xml.Namespace ); if( String.IsNullOrEmpty( this.Language ) ) { this.Language = reader.GetAttribute( XmlNames.Xml.Language ); } reader.ReadStartElement(); ReadBaseInfoCard( reader ); // // Do not allow self issued uri as a managed IP address // if( !IsSelfIssued ) { if( Utility.CompareUri( m_issuer, XmlNames.WSIdentity.SelfIssuerUriValue ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.SelfIssuedUriUsed ) ) ); } } if( null == m_extendedInformation ) { m_extendedInformation = new InfocardExtendedInformationCollection( m_id ); } } private void ReadRoamingInfoCard( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.RoamingInfoCardElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } // // Read the metadata // reader.ReadStartElement(); this.Language = reader.GetAttribute( XmlNames.Xml.Language, XmlNames.Xml.Namespace ); if( String.IsNullOrEmpty( this.Language ) ) { this.Language = reader.GetAttribute( XmlNames.Xml.Language ); } ReadBaseInfoCard( reader ); // // It is invalid for a roaming store file to contain the private // personal identifier claim for self-issued cards. // if( m_isSelfIssued ) { InfoCardClaimCollection claims = GetClaims(); if( claims.ContainsKey( InfoCardConstants.PPIDClaimsUri ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } } ReadInfoCardPrivateData( reader ); } // // Summary // Populate the private infocard data by parsing a managed card file // // Parameter // reader - The XmlReader to read from // // private void ReadInfoCardPrivateData( XmlReader reader ) { // // Read the private data // while( reader.Read() ) { switch( reader.LocalName ) { case XmlNames.WSIdentity.RoamingInfoCardElement: if( XmlNodeType.EndElement == reader.NodeType ) { return; } break; case XmlNames.WSIdentity.MasterKeyElement: byte[ ] rawKey = Utility.ReadByteStreamFromBase64( reader ).ToArray(); if( this.IsPinProtected ) { if( null != rawKey && PinProtectionHelper.EncryptedMasterKeySize == rawKey.Length ) { m_masterKey = new InfoCardMasterKey( m_id, rawKey ); } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } } else { if( null != rawKey && MasterKeySize == rawKey.Length ) { m_masterKey = new InfoCardMasterKey( m_id, rawKey ); } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } } break; case XmlNames.WSIdentity.ClaimValueListElement: ReadClaimValues( reader ); break; } } } // // Summary // Populate the infocard by parsing a managed card file // // Parameter // reader - The XmlReader to read from // // private void ReadBaseInfoCard( XmlReader reader ) { string value; try { while( reader.Read() ) { if( XmlNames.WSIdentity.Namespace == reader.NamespaceURI && XmlNodeType.EndElement == reader.NodeType && ( XmlNames.WSIdentity.InfoCardElement == reader.LocalName || XmlNames.WSIdentity.InfoCardMetaDataElement == reader.LocalName ) ) { reader.ReadEndElement(); return; } if( XmlNames.WSIdentity.Namespace != reader.NamespaceURI && XmlNodeType.Element == reader.NodeType ) { if( XmlNames.WSIdentity07.Namespace == reader.NamespaceURI && XmlNames.WSIdentity07.IssuerInformation == reader.LocalName ) { if( m_readIssuerInformation ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.MultipleIssuerInformation ) ) ); } InfocardExtendedInformationEntry entry = new InfocardExtendedInformationEntry(); entry.ReadXml( reader ); if( null == m_extendedInformation ) { m_extendedInformation = new InfocardExtendedInformationCollection( m_id ); } m_extendedInformation.Add( entry ); m_readIssuerInformation = true; continue; } else { // // We do not store these for now. In V2 we will be storing these entries too. // InfocardExtendedInformationEntry entry = new InfocardExtendedInformationEntry(); entry.ReadXml( reader ); // just used to skip this element } } if( XmlNames.WSIdentity.Namespace == reader.NamespaceURI && XmlNodeType.EndElement != reader.NodeType ) { switch( reader.LocalName ) { case XmlNames.WSIdentity.CardIdElement: this.Id = new Uri( reader.ReadString().Trim() ); break; case XmlNames.WSIdentity.CardVersionElement: this.Epoch = Convert.ToUInt32( reader.ReadString().Trim(), CultureInfo.InvariantCulture ); break; case XmlNames.WSIdentity.CardImageElement: this.LogoMimeType = reader.GetAttribute( XmlNames.WSIdentity.MimeTypeAttribute, XmlNames.WSIdentity.Namespace ); if( String.IsNullOrEmpty( this.LogoMimeType ) ) { this.LogoMimeType = reader.GetAttribute( XmlNames.WSIdentity.MimeTypeAttribute ); } this.Logo = Utility.ReadByteStreamFromBase64( reader ).ToArray(); break; case XmlNames.WSIdentity.CardNameElement: this.Name = reader.ReadString().Trim(); break; case XmlNames.WSIdentity.IssuerNameElement: this.IssuerName = reader.ReadString().Trim(); break; case XmlNames.WSIdentity.IssuerElement: this.Issuer = new Uri( reader.ReadString().Trim() ); break; case XmlNames.WSIdentity.TimeExpiresElement: this.ExpiresOn = XmlConvert.ToDateTime( reader.ReadString().Trim(), XmlDateTimeSerializationMode.Utc ); break; case XmlNames.WSIdentity.TimeIssuedElement: this.IssuedOn = XmlConvert.ToDateTime( reader.ReadString().Trim(), XmlDateTimeSerializationMode.Utc ); break; case XmlNames.WSIdentity.SupportedClaimTypeListElement: ReadClaims( reader ); break; case XmlNames.WSIdentity.SupportedTokenTypeListElement: List tokenTypes = ReadTokenType( reader ); this.TokenTypes = tokenTypes.ToArray(); break; case XmlNames.WSIdentity.RequireAppliesToElement: string optionalValue = reader.GetAttribute( XmlNames.WSIdentity.OptionalAttribute, XmlNames.WSIdentity.Namespace ); if( String.IsNullOrEmpty( optionalValue ) ) { optionalValue = reader.GetAttribute( XmlNames.WSIdentity.OptionalAttribute ); } if( !String.IsNullOrEmpty( optionalValue ) && ( "true" == optionalValue || "1" == optionalValue ) ) { this.RequireAppliesto = RequireAppliesToStatus.Optional; } else { this.RequireAppliesto = RequireAppliesToStatus.Required; } break; case XmlNames.WSIdentity.TokenServiceListElement: ReadAuthServices( reader ); break; case XmlNames.WSIdentity.PrivacyNoticeAtElement: ReadPrivacyPolicy( reader ); break; case XmlNames.WSIdentity.IsSelfIssuedElement: this.IsSelfIssued = Convert.ToBoolean( reader.ReadString().Trim(), CultureInfo.InvariantCulture ); if( this.IsSelfIssued && m_readIssuerInformation ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ExtendedInfoInSelfIssued ) ) ); } break; case XmlNames.WSIdentity.PinDigestElement: byte[ ] pinHash = Utility.ReadByteStreamFromBase64( reader ).ToArray(); if( null != pinHash && 0 != pinHash.Length ) { m_pinHash = pinHash; } break; case XmlNames.WSIdentity.HashSaltElement: byte[ ] hashSalt = Utility.ReadByteStreamFromBase64( reader ).ToArray(); if( null != hashSalt && 0 != hashSalt.Length ) { this.HashSalt = hashSalt; } break; case XmlNames.WSIdentity.TimeLastUpdatedElement: value = reader.ReadString().Trim(); if( !String.IsNullOrEmpty( value ) ) { this.LastUpdate = XmlConvert.ToDateTime( value, XmlDateTimeSerializationMode.Utc ); } break; case XmlNames.WSIdentity.IssuerIdElement: byte[ ] issuerIdentifierAsBytes = Utility.ReadByteStreamFromBase64( reader ).ToArray(); if( null != issuerIdentifierAsBytes && 0 != issuerIdentifierAsBytes.Length ) { this.IssuerIdentifierAsBytes = issuerIdentifierAsBytes; } break; case XmlNames.WSIdentity.BackgroundColorElement: this.BackgroundColor = Convert.ToInt32( reader.ReadString().Trim(), CultureInfo.InvariantCulture ); break; default: break; } } else if( XmlNames.WSIdentity07.Namespace == reader.NamespaceURI && XmlNodeType.EndElement != reader.NodeType ) { if( XmlNames.WSIdentity07.RequireStrongRPIdentity == reader.LocalName && XmlNames.WSIdentity07.Namespace == reader.NamespaceURI ) { GetRPIdentityRequirement().StrongIdentityRequired = true; } } } } catch( UriFormatException e ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidUriFormat ), e ) ); } } // // Summary // Read the privacy policy of the issuer // // Parameter // reader - The XmlReader to read from // private void ReadPrivacyPolicy( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.PrivacyNoticeAtElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } string privacyPolicyVersion = reader.GetAttribute( XmlNames.WSIdentity.PrivacyNoticeVersionAttribute, XmlNames.Xml.Namespace ); if( String.IsNullOrEmpty( privacyPolicyVersion ) ) { privacyPolicyVersion = reader.GetAttribute( XmlNames.WSIdentity.PrivacyNoticeVersionAttribute ); } if( !String.IsNullOrEmpty( privacyPolicyVersion ) ) { m_privacyPolicyVersion = Convert.ToUInt32( privacyPolicyVersion, CultureInfo.InvariantCulture ); } IDT.TraceDebug( "Start reading the privacy policy element" ); m_privacyPolicyLink = reader.ReadString().Trim(); } // // Summary // Read the claims values for self issued cards and populate the claim collection // // Parameter // reader - The XmlReader to read from // private void ReadClaimValues( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.ClaimValueListElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } IDT.TraceDebug( "Start reading the claim values elements" ); while( reader.Read() ) { if( XmlNodeType.EndElement == reader.NodeType && XmlNames.WSIdentity.ClaimValueListElement == reader.LocalName ) { return; } if( XmlNames.WSIdentity.Namespace == reader.NamespaceURI && XmlNames.WSIdentity.ClaimValueElement == reader.LocalName && XmlNodeType.Element == reader.NodeType ) { string claimUri = reader.GetAttribute( XmlNames.WSIdentity.UriAttribute, XmlNames.Xml.Namespace ); if( String.IsNullOrEmpty( claimUri ) ) { claimUri = reader.GetAttribute( XmlNames.WSIdentity.UriAttribute ); } reader.Read(); string value = reader.ReadString().Trim(); // // For non-encrypted values a maximum length of 255 is enforced // if( !this.IsPinProtected && value.Length > 255 ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.TooLongClaimValue ) ) ); } if( !String.IsNullOrEmpty( claimUri ) ) { // // Need to check if the claimUri is a valid key in the // Infocard claim collection // if( !this.m_claims.ContainsKey( claimUri ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } // // Need to perform validation of Gender and DateOfBirth fields // if( !String.IsNullOrEmpty( value ) && !this.IsPinProtected ) { if( InfoCardConstants.Gender == claimUri ) { bool valid = ( "0" == value || "1" == value || "2" == value ); if( !valid ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } } if( ( InfoCardConstants.DateOfBirth == claimUri ) ) { try { DateTime dob = XmlConvert.ToDateTime( value, XmlDateTimeSerializationMode.Utc ); } #pragma warning disable 56500 // do not catch non-recoverable exceptions catch( Exception e ) { if( IDT.IsFatal( e ) ) { InfoCardService.Crash( e ); } throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.InvalidImportFile ) ) ); } #pragma warning restore 56500 } } m_claims[ claimUri ].Value = value; } } } } // // Summary // Read the claims list in the infocard and populate the claim collection // // Parameter // reader - The XmlReader to read from // private void ReadClaims( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.SupportedClaimTypeListElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } IDT.TraceDebug( "Start reading the claims elements" ); while( reader.Read() ) { if( XmlNodeType.EndElement == reader.NodeType && XmlNames.WSIdentity.SupportedClaimTypeListElement == reader.LocalName ) { return; } if( XmlNames.WSIdentity.Namespace == reader.NamespaceURI && XmlNames.WSIdentity.SupportedClaimTypeElement == reader.LocalName ) { InfoCardClaim clm = ReadSingleClaim( reader ); if( null != clm ) { this.AddClaim( clm ); } } } } // // Summary // Read a single claim to be added to the claim collection // // Parameter // reader - The XmlReader to read from // private InfoCardClaim ReadSingleClaim( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.SupportedClaimTypeElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } IDT.TraceDebug( "Start reading the claim element" ); string claimUri = null; string displayTag = null; string description = null; string claimValue = null; claimUri = reader.GetAttribute( XmlNames.WSIdentity.UriAttribute, XmlNames.WSIdentity.Namespace ); if( String.IsNullOrEmpty( claimUri ) ) { claimUri = reader.GetAttribute( XmlNames.WSIdentity.UriAttribute ); } // // return if the element is empty // if( reader.IsEmptyElement ) { if( !String.IsNullOrEmpty( claimUri ) ) { InfoCardClaim claim = new InfoCardClaim( claimUri, claimValue, description, displayTag ); return claim; } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ClaimIdNull ) ) ); } } while( reader.Read() ) { // // Read the claim details // switch( reader.LocalName ) { case XmlNames.WSIdentity.SupportedClaimTypeElement: if( XmlNodeType.EndElement == reader.NodeType ) { if( !String.IsNullOrEmpty( claimUri ) ) { InfoCardClaim claim = new InfoCardClaim( claimUri, claimValue, description, displayTag ); return claim; } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ClaimIdNull ) ) ); } } break; case XmlNames.WSIdentity.DescriptionElement: description = reader.ReadString().Trim(); break; case XmlNames.WSIdentity.DisplayTagElement: displayTag = reader.ReadString().Trim(); break; case XmlNames.WSIdentity.ClaimValueElement: // // read values only for self issued cards // if( IsSelfIssued ) { claimValue = reader.ReadString().Trim(); } break; default: break; } } return null; } // // Summary // Read the authentication service in the card // // Parameter // reader - The XmlReader to read from // // Return // The list of the authentication services // private void ReadAuthServices( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.TokenServiceListElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } IDT.TraceDebug( "Start reading the authentication service elements" ); if( reader.IsEmptyElement ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.NoAuthenticationServicesInCard ) ) ); } while( reader.Read() ) { switch( reader.LocalName ) { case XmlNames.WSIdentity.TokenServiceElement: if( reader.NodeType != XmlNodeType.EndElement ) { TokenCreationParameter service = new TokenCreationParameter(); service.ReadXml( reader ); if( service.IsComplete() ) { this.CreationParameters.Add( service ); } else { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.ServiceInvalidTokenService ) ) ); } } break; case XmlNames.WSIdentity.TokenServiceListElement: return; } } } // // Summary // Read list of token types supported by the issuer of the managed card // // Parameter // reader - The XmlReader to read from // // Return // The list of token types // private List ReadTokenType( XmlReader reader ) { IDT.Assert( null != reader, "null reader" ); if( !reader.IsStartElement( XmlNames.WSIdentity.SupportedTokenTypeListElement, XmlNames.WSIdentity.Namespace ) ) { throw IDT.ThrowHelperError( new InvalidCardException( SR.GetString( SR.UnexpectedElement ) ) ); } IDT.TraceDebug( "Reading the token types information" ); List tokenTypes = new List (); while( reader.Read() ) { if( XmlNodeType.EndElement == reader.NodeType && XmlNames.WSIdentity.SupportedTokenTypeListElement == reader.LocalName ) { return tokenTypes; } if( XmlNames.WSTrustXmlSoap2005.c_TokenType == reader.LocalName && XmlNames.WSTrustXmlSoap2005.c_Namespace == reader.NamespaceURI && XmlNodeType.EndElement != reader.NodeType && !reader.IsEmptyElement ) { String tokenType = reader.ReadString().Trim(); if( !String.IsNullOrEmpty( tokenType ) ) { tokenTypes.Add( tokenType ); } } } return tokenTypes; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbProviderManifest.cs
- HwndStylusInputProvider.cs
- Clipboard.cs
- ViewManager.cs
- IChannel.cs
- ResourceReader.cs
- DocumentViewerConstants.cs
- SerializableAttribute.cs
- ArrayTypeMismatchException.cs
- RowToFieldTransformer.cs
- PageAsyncTask.cs
- DisplayNameAttribute.cs
- ConstraintEnumerator.cs
- XmlReaderSettings.cs
- ManifestSignatureInformation.cs
- NewArrayExpression.cs
- DataColumnPropertyDescriptor.cs
- CurrentTimeZone.cs
- RadioButton.cs
- ISAPIRuntime.cs
- CommentEmitter.cs
- StorageAssociationTypeMapping.cs
- DbBuffer.cs
- TextViewSelectionProcessor.cs
- ConnectorEditor.cs
- DataColumnMappingCollection.cs
- ProxyGenerationError.cs
- SmiMetaData.cs
- ReflectionTypeLoadException.cs
- SQLBinary.cs
- OdbcEnvironment.cs
- backend.cs
- shaperfactoryquerycacheentry.cs
- SolidBrush.cs
- ConfigurationException.cs
- LinqDataSourceView.cs
- XmlILConstructAnalyzer.cs
- DocumentSequence.cs
- PathStreamGeometryContext.cs
- GroupBoxAutomationPeer.cs
- NullRuntimeConfig.cs
- OdbcConnectionOpen.cs
- XmlnsDefinitionAttribute.cs
- DesignerCommandAdapter.cs
- SmtpException.cs
- DrawingAttributes.cs
- FixedBufferAttribute.cs
- ExpressionsCollectionEditor.cs
- TranslateTransform.cs
- UnsafeNativeMethodsCLR.cs
- EntitySqlQueryState.cs
- AuthenticationConfig.cs
- SqlError.cs
- StrokeCollectionConverter.cs
- TargetPerspective.cs
- AmbientProperties.cs
- AssertFilter.cs
- SQLRoleProvider.cs
- EmptyStringExpandableObjectConverter.cs
- SmtpDigestAuthenticationModule.cs
- DirectoryRedirect.cs
- BindingObserver.cs
- XmlChildNodes.cs
- MatrixKeyFrameCollection.cs
- XmlIncludeAttribute.cs
- _ConnectStream.cs
- InheritanceAttribute.cs
- bindurihelper.cs
- HashSetDebugView.cs
- DefaultMemberAttribute.cs
- ObjectQueryExecutionPlan.cs
- ValueType.cs
- TypedElement.cs
- ClientProxyGenerator.cs
- AutomationIdentifier.cs
- DataBindingExpressionBuilder.cs
- ObjectToIdCache.cs
- DependencyObjectPropertyDescriptor.cs
- PathTooLongException.cs
- PrimitiveXmlSerializers.cs
- DetailsViewRow.cs
- DirectoryRedirect.cs
- DesignerWebPartChrome.cs
- XmlStreamNodeWriter.cs
- XPathScanner.cs
- XsdDuration.cs
- NativeRightsManagementAPIsStructures.cs
- XmlDeclaration.cs
- ScriptManager.cs
- ObjectKeyFrameCollection.cs
- XmlChildEnumerator.cs
- XpsFilter.cs
- InputProviderSite.cs
- DataPagerFieldCollection.cs
- xdrvalidator.cs
- StateDesignerConnector.cs
- DependencyPropertyHelper.cs
- ParseChildrenAsPropertiesAttribute.cs
- TTSEngineTypes.cs
- ToolStripScrollButton.cs