Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / RemoteTokenFactory.cs / 3 / RemoteTokenFactory.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 namespace Microsoft.InfoCards { using System; using System.Security; using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certificates; using System.IdentityModel.Tokens; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.ServiceModel.Security; using System.ServiceModel.Security.Tokens; using System.Runtime.Serialization; using System.Xml; using System.Globalization; using System.IO; using System.Collections.ObjectModel; using System.Collections.Generic; using Microsoft.InfoCards.Diagnostics; using IDT = Microsoft.InfoCards.Diagnostics.InfoCardTrace; using System.Net.Security; using System.Net; using System.IdentityModel.Claims; // // Summary // This class is used to make request to an Indigo STS for security tokens. // internal class RemoteTokenFactory : TokenFactoryBase { internal const string MetadataExchangeClientKey = "MetadataExchangeClientKey"; ServiceEndpoint m_endPoint; ChannelFactorym_channelFactory; object m_channelChangeSync; IWebProxy m_proxy; ProtocolProfile m_protocolProfile; // // Capture the list of claims that we will request for from the IP/STS. // I.e. the claims that will be disclosed to the recipient. // // The bool specifies if Recipient policy specified that claim as optional or not. // We need to track this because we need to add an "optional" attribute in the RST // we send to the IP/STS // Dictionary m_disclosedClaims; public RemoteTokenFactory( ServiceEndpoint endPoint, IWebProxy proxy ) { m_endPoint = endPoint; m_channelChangeSync = new object(); m_proxy = proxy; } protected override TokenDescriptor ProduceToken( InfoCard card, TokenCreationParameter parameter, TokenFactoryCredential credential, InfoCardPolicy policy, bool discloseOptional ) { IDT.ThrowInvalidArgumentConditional( null == card, "card" ); IDT.ThrowInvalidArgumentConditional( null == parameter, "parameter" ); IDT.ThrowInvalidArgumentConditional( null == credential, "credential" ); IDT.ThrowInvalidArgumentConditional( null == policy, "policy" ); DisplayToken displayToken; RequestSecurityToken rst; RSACryptoServiceProvider identityKey = null; byte[] clientEntropyForSymmetric = null; SymmetricAlgorithm sessionKey = null; RSAKeyValue rsaKeyValue = null; string internalTokenReference = string.Empty; string externalTokenReference = string.Empty; GenericXmlSecurityToken tok = null; ISts sts; // // Retrieve the protocol profile from the incoming policy. // m_protocolProfile = policy.ProtocolVersionProfile; TokenDescriptor token; bool needUseKey = false; RSATokenProvider endorsingSigTokenProvider = null; try { // // Create the appropriate keys. // Note : We will always create the asymmetric key pair. // The IP can decide to not use it and send us a new key in the proof token // if ( SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType ) { // // Use asymmetric keys - this requires the ledger // to be in memory [which is the case -- in GetTokenRequest.cs // we fetch the ledgerentry before calling CreateToken]. // However, a pointer to the ledger entry would be required // if future optimization work removes the global ledger entry // identityKey = card.GetPublicCryptography( policy.Recipient.GetIdentifier() ); needUseKey = true; IDT.Assert( null == clientEntropyForSymmetric, "Null in in asymmetric case" ); } else if ( SecurityKeyTypeInternal.SymmetricKey == policy.KeyType ) { // // We will always send entropy to the IP/STS in the symmetric case. // Generate it here. If the IP/STS used combined entropy, // then we need this information while we are processing the RSTR. // clientEntropyForSymmetric = new byte[ policy.GetIntelligentKeySize( false ) / 8 ]; RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); rng.GetNonZeroBytes( clientEntropyForSymmetric ); IDT.Assert( null == identityKey, "Null in symmetric case" ); } else { IDT.Assert( null == identityKey, "Null in no proof key case" ); IDT.Assert( null == clientEntropyForSymmetric, "Null in no proof key case" ); IDT.Assert( SecurityKeyTypeInternal.NoKey == policy.KeyType, "Null in no proof key case" ); } if ( null == m_endPoint ) { m_endPoint = DoMexExchange( parameter, m_proxy ); } BindingElementCollection bindingElements = m_endPoint.Binding.CreateBindingElements(); SecurityBindingElement sbe = bindingElements.Find (); if( null == sbe ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, m_endPoint.Address.Uri ) ) ); } if( sbe.MessageSecurityVersion.TrustVersion == TrustVersion.WSTrust13 ) { m_protocolProfile.WSTrust = XmlNames.WSTrustOasis2007.Instance; } else { m_protocolProfile.WSTrust = XmlNames.WSTrustXmlSoap2005.Instance; } Binding stsBinding = m_endPoint.Binding; EndpointAddress stsAddress = m_endPoint.Address; if ( needUseKey ) { // // We will be sending a UseKey element with the public part of a pair wise key pair to be used // as a proof token. We must prove posession of the private key as well. To do that we add // an endorsing signature to the message. The code below is how we inform the security stack // that such a signature is necessary. This will cause the security stack to ask our // private ClientCredentials for an RSASecurityToken later to be used to make the signature. // SupportingTokenParameters requirements; if( sbe.OptionalOperationSupportingTokenParameters.ContainsKey( m_protocolProfile.WSTrust.RequestSecurityTokenAction ) ) { requirements = sbe.OptionalOperationSupportingTokenParameters[ m_protocolProfile.WSTrust.RequestSecurityTokenAction ]; } else { requirements = new SupportingTokenParameters(); sbe.OptionalOperationSupportingTokenParameters[ m_protocolProfile.WSTrust.RequestSecurityTokenAction ] = requirements; } bool addRsaRequirements = true; foreach ( SecurityTokenParameters stp in requirements.Endorsing ) { if ( stp is RsaSecurityTokenParameters ) { addRsaRequirements = false; break; } } if ( addRsaRequirements ) { RsaSecurityTokenParameters rsaParams = new RsaSecurityTokenParameters(); rsaParams.InclusionMode = SecurityTokenInclusionMode.Never; rsaParams.RequireDerivedKeys = false; requirements.Endorsing.Add( rsaParams ); } stsBinding = new CustomBinding( bindingElements ); } stsBinding = new CustomBinding( Utility.UpdateProxyForHttpAndRestrictTransportBinding( stsBinding.CreateBindingElements(), m_proxy, false ) ); // Client auth on transport is allowed for IP/STS leg List disclosedClaimUris; InfoCardServiceClientCredentials creds = new InfoCardServiceClientCredentials( credential, m_protocolProfile ); if ( needUseKey ) { // // The client credentials will need an rsa token in order to add the endorsing signature. // We need to keep a reference to this here so that we can make certain that it gets disposed. // endorsingSigTokenProvider = new RSATokenProvider( policy, card ); creds.EndorsingSignatureTokenProvider = endorsingSigTokenProvider; } ChannelFactory channelFactory = null; bool channelFactorySucceeded = false; // // Huge try catch around use of the channel factory // try { IDT.Assert( false == channelFactorySucceeded, "Will set to true upon sucess" ); // // We must syncronize the creation and cleanup of the channel factory to prevent races // on the cancel thread. // lock ( m_channelChangeSync ) { if ( base.IsAborted ) { throw IDT.ThrowHelperError( new UserCancelledException() ); } channelFactory = new ChannelFactory ( stsBinding, stsAddress ); // // Disallow NTLM. This is necessary http with message security case. // // Waiting on CSDMain bug 28343 for transport level auth to not release NTLM creds // // Specifically here in IP/STS scenario, setting AllowNtlm to false // is useful mainly for managed card backed by Kerberos case. // However there is no harm to set for ALL credential types // creds.Windows.AllowNtlm = false; ClientCredentials existingCreds = channelFactory.Endpoint.Behaviors.Find (); if ( null != existingCreds ) { channelFactory.Endpoint.Behaviors.Remove( existingCreds ); } channelFactory.Endpoint.Behaviors.Remove (); channelFactory.Endpoint.Behaviors.Add( creds ); X509Certificate2Collection certificateCollection = null; bool chainValidated = false; // // Set authorization credentials // // // We implement our own validation to implement some special behaviour: // e.g. {chaining up to LM or CU Trusted CA} OR {Peer Trust}, Offline validation, // IgnoreRevocationUnknown etc). // // // [In IssuedTokenForCertificate, MutualCertificate, UserNameForCertificate cases]: // Note that since Indigo considers this identity to be retrieved out-of-band // we cannot use their custom certificate validation extensibility points. // switch ( parameter.CredentialType ) { case TokenFactoryCredentialType.UserNamePasswordCredential: creds.UserName.UserName = ((UserNameTokenFactoryCredential)credential).UserName; creds.UserName.Password = ((UserNameTokenFactoryCredential)credential).Password; certificateCollection = GetCertificateChainFromAddress( stsAddress ); InfoCardX509Validator.ValidateChainOrPeer( certificateCollection[ 0 ], certificateCollection, out chainValidated ); creds.ServiceCertificate.DefaultCertificate = certificateCollection[ 0 ]; break; case TokenFactoryCredentialType.KerberosCredential: break; case TokenFactoryCredentialType.X509CertificateCredential: creds.ClientCertificate.Certificate = ((X509CertificateTokenFactoryCredential)credential).Certificate; certificateCollection = GetCertificateChainFromAddress( stsAddress ); InfoCardX509Validator.ValidateChainOrPeer( certificateCollection[ 0 ], certificateCollection, out chainValidated ); creds.ServiceCertificate.DefaultCertificate = certificateCollection[ 0 ]; break; case TokenFactoryCredentialType.SelfIssuedCredential: creds.IsSelfIssuedCred = true; SelfIssuedTokenFactoryCredential sic = ((SelfIssuedTokenFactoryCredential)credential); creds.SelectedCard = sic.LocalCard; certificateCollection = GetCertificateChainFromAddress( stsAddress ); X509Certificate2 certificate = certificateCollection[ 0 ]; InfoCardX509Validator.ValidateChainOrPeer( certificate, certificateCollection, out chainValidated ); Recipient.RecipientCertParameters recipientParams; string recipientId = Recipient.CertGetRecipientIdHash( certificate, certificateCollection, chainValidated, out recipientParams ); string recipientOrganizationId = Recipient.CertGetRecipientOrganizationIdHash( certificate, certificateCollection, chainValidated ); // // Pass the issuer cert and recipientId into this function. // (So do not use policy.RecipientIdentifier as that belongs to the recipient) // In this case the immediate token recipient is same as the RP EnsureSelfIssuedCardHasLedgerEntryForIssuer( sic.LocalCard, certificate, recipientId, recipientOrganizationId, recipientParams, recipientOrganizationId ); creds.ServiceCertificate.DefaultCertificate = certificate; break; default: IDT.ThrowInvalidArgumentConditional( true, "CredentialType" ); break; } // // In IssuedTokenForSslNegotiated, UserNameForSslNegotiated, MutualSslNegotiated, // the client initiates a new SSL handshake to exchange certs. (This could be over http still). // In these cases, the Indigo validator will get invoked. // So we are overriding the Indigo validator given that we have some // special behavior, e.g. {chaining up to LM or CU Trusted CA} OR {Peer Trust}, Offline validation, // IgnoreRevocationUnknown etc. // creds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom; creds.ServiceCertificate.Authentication.CustomCertificateValidator = InfoCardX509Validator.Create( certificateCollection ); // // Now that the channelfactory is setup // we will capture the object value in a member before we, // begin communicating on the channel. // m_channelFactory = channelFactory; }//lock( m_channelChangeSync ) try { sts = channelFactory.CreateChannel(); if ( null != identityKey ) { rsaKeyValue = new RSAKeyValue( identityKey ); } // // Disclosed claims is all required claims in the card/policy + // optional claims // m_disclosedClaims = card.GetClaimsToBeDisclosed( policy, discloseOptional ); disclosedClaimUris = new List ( m_disclosedClaims.Count ); disclosedClaimUris.AddRange( m_disclosedClaims.Keys ); rst = CreateRst( stsBinding.MessageVersion.Addressing, policy, card, discloseOptional, rsaKeyValue, clientEntropyForSymmetric, new CultureInfo( credential.LCID ) ); Message rstMessage = Message.CreateMessage( stsBinding.MessageVersion, m_protocolProfile.WSTrust.RequestSecurityTokenAction, rst ); // // Process the Request for security token // Message rstrMessage = null; if( XmlNames.WSSpecificationVersion.WSTrustXmlSoap2005 == m_protocolProfile.WSTrust.Version ) { rstrMessage = sts.ProcessRequestSecurityTokenFeb2005( rstMessage ); } else if( XmlNames.WSSpecificationVersion.WSTrustOasis2007 == m_protocolProfile.WSTrust.Version ) { rstrMessage = sts.ProcessRequestSecurityTokenWSTrust13( rstMessage ); } else { IDT.Assert( false, "Unsupported version of WS-Trust detected" ); } WSIdentityFaultException.ThrowIfFaultMessage( rstrMessage, CultureInfo.GetCultureInfo( credential.LCID ) ); // // Retrive the keys from the proof token // if ( SecurityKeyTypeInternal.SymmetricKey == policy.KeyType ) { // // Find the symmetric key in the proof key. // tok = RequestSecurityTokenResponseHelper.ProcessSymmetricTokenData( rstrMessage.GetReaderAtBodyContents(), m_protocolProfile.TokenSerializer, null, clientEntropyForSymmetric, m_protocolProfile, out displayToken ); if ( tok.ProofToken.SecurityKeys.Count < 1 ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.NoSymmetricKeyFound ) ) ); } foreach ( SecurityKey key in tok.ProofToken.SecurityKeys ) { InMemorySymmetricSecurityKey symKey = key as InMemorySymmetricSecurityKey; if ( null != symKey ) { IDT.TraceDebug( "IPSTSCLIENT: Found a symmetric key in the proof token" ); sessionKey = new RijndaelManaged(); sessionKey.Key = ((InMemorySymmetricSecurityKey)key).GetSymmetricKey(); break; } } if ( null == sessionKey ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.NoSymmetricKeyFound ) ) ); } } else if ( SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType ) { tok = RequestSecurityTokenResponseHelper.ProcessAsymmetricTokenData( rstrMessage.GetReaderAtBodyContents(), identityKey, m_protocolProfile.TokenSerializer, null, m_protocolProfile, out displayToken ); } else { IDT.Assert( SecurityKeyTypeInternal.NoKey == policy.KeyType, "Bad enum member for SecurityKeyTypeInternal" ); tok = RequestSecurityTokenResponseHelper.ProcessBearerTokenData( rstrMessage.GetReaderAtBodyContents(), m_protocolProfile.TokenSerializer, null, m_protocolProfile, out displayToken ); } // // Close can throw CommunicationException (or exceptions derived from that) and TimeoutException // channelFactory.Close(); channelFactorySucceeded = true; } finally { lock ( m_channelChangeSync ) { if ( !channelFactorySucceeded ) { // // Abort on failure // channelFactory.Abort(); } // // We have finished our communications, either via cancel, error, or success // we should unset the member var so cancels can not cancel the operation. // m_channelFactory = null; } } } catch ( EndpointNotFoundException e ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.EndpointNotFound ), e ) ); } catch ( InfoCardBaseException ) { // // Don't want to wrap it again in a TrustExchangeException! // Could be for example if failed in selfIssued token factory // when doing self-issued for managed. // throw; } catch ( Exception e ) { if ( IDT.IsFatal( e ) ) { throw; } throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.ProblemRetrievingTokenFromIdentityProvider ), e ) ); } XmlElement protectedToken = tok.TokenXml; // // If the token is not encrypted, then we need to do it ourselves. // If no certificate was specified for the immediate token recipient // then the token cannot be encrypted. // X509RecipientIdentity x509Id = policy.ImmediateTokenRecipient as X509RecipientIdentity; if ( null != x509Id && !IsEncryptedXml( protectedToken ) && AppliesToBehaviorDecision.DoNotSend == AppliesToBehaviorDecisionTable.GetAppliesToBehaviorDecisionForRst( policy, card.RequireAppliesto ) ) { try { string keyWrapAlgorithm; // // Choosing the keyWrapAlgorithm is split into 3 cases for clarity. // (I.e. the below code is not condensed further for clarity purposes.) // if ( SecurityKeyTypeInternal.SymmetricKey == policy.KeyType ) { // // Choose default for the key wrap algorithm // keyWrapAlgorithm = SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm; } else if ( SecurityKeyTypeInternal.AsymmetricKey == policy.KeyType ) { keyWrapAlgorithm = !String.IsNullOrEmpty( policy.OptionalRstParams.EncryptWith ) ? policy.OptionalRstParams.EncryptWith : SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm; } else { // // Ignore encryptWith as there is no proof key! // keyWrapAlgorithm = SecurityAlgorithmSuite.Default.DefaultAsymmetricKeyWrapAlgorithm; } protectedToken = EncryptionUtility.EncryptSecurityToken( protectedToken, x509Id.LeafCertificate, !String.IsNullOrEmpty( policy.OptionalRstParams.EncryptionAlgorithm ) ? policy.OptionalRstParams.EncryptionAlgorithm : SecurityAlgorithmSuite.Default.DefaultEncryptionAlgorithm, keyWrapAlgorithm, policy.ProtocolVersionProfile ); } catch ( Exception e ) { if ( IDT.IsFatal( e ) ) { throw; } throw IDT.ThrowHelperError( new TrustExchangeException( SR.ServiceTokenEncryptionFailed, e ) ); } } GetKeyIdentifierClauses( tok, policy.ProtocolVersionProfile, out internalTokenReference, out externalTokenReference ); FillOutDisplayToken( card, displayToken ); token = new TokenDescriptor( tok.Id, tok.ValidFrom, tok.ValidTo, protectedToken, displayToken, sessionKey, internalTokenReference, externalTokenReference, disclosedClaimUris ); // // Clear out references whose ownership has been transferred to the TokenDescriptor. // sessionKey = null; tok = null; } finally { // // Have to make certain that we dispose of the identity key. // If we don't dispose of this then the finalizer will run and // throw since it will attempt to dispose as the wrong identity. // if ( null != identityKey ) { ((IDisposable)identityKey).Dispose(); identityKey = null; } if ( null != rsaKeyValue ) { ((IDisposable)(rsaKeyValue.Key)).Dispose(); rsaKeyValue.Key = null; } if ( null != sessionKey ) { ((IDisposable)sessionKey).Dispose(); sessionKey = null; } if ( null != endorsingSigTokenProvider ) { ((IDisposable)endorsingSigTokenProvider).Dispose(); endorsingSigTokenProvider = null; } } return token; } protected override void OnAbort() { lock ( m_channelChangeSync ) { if ( !base.IsAborted && null != m_channelFactory ) { m_channelFactory.Abort(); } } } // // Summary // Retrieve certificate from the EndPointAddress of the service // // Parameters // address - address from which to extract the certificate // // Returns // The selected certificate chain in a X509Certificate2Collection // X509Certificate2Collection GetCertificateChainFromAddress( EndpointAddress address ) { if ( null == address || null == address.Identity ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.NoCertificateInEndPoint ) ) ); } X509CertificateEndpointIdentity identity = address.Identity as X509CertificateEndpointIdentity; if ( null == identity || null == identity.Certificates || identity.Certificates.Count < 1 ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.NoCertificateInEndPoint ) ) ); } return identity.Certificates; } // // Summary // Do a mex exchange to retrieve the WSDL // // Parameters // param - parameters from which to extract the mex uri // proxy - proxy value for the user // // Returns // The selected service end point // public static ServiceEndpoint DoMexExchange( TokenCreationParameter param, IWebProxy proxy ) { ServiceEndpoint endPoint = null; bool foundMexEndpoint = false; if ( null == param || null == param.Epr ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.InvalidServiceUri ) ) ); } EndpointAddress address = Utility.DeriveMexAddress( param.Epr ); if ( null == address ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.InvalidServiceUri ) ) ); } // // Do a WS-MetaDataExchange over SOAP to retrieve the endpoint binding // InfoCardMetadataExchangeClient mex = new InfoCardMetadataExchangeClient(); mex.Proxy = proxy; MetadataSet metadataSet = null; mex.ResolveMetadataReferences = true; mex.MaximumResolvedReferences = InfoCardConstants.MaximumMexChainLength; IDT.TraceDebug( "IPSTSCLIENT: Retrieving metadata over SOAP from {0}", address.Uri ); Exception ex = null; try { metadataSet = mex.GetMetadata( address ); foundMexEndpoint = true; } catch ( Exception e ) { if ( IDT.IsFatal( e ) ) { throw; } } // // Do a WS-MetaDataExchange over HTTP to retrieve the endpoint binding // if ( !foundMexEndpoint ) { IDT.TraceDebug( "IPSTSCLIENT: Retrieving metadata over HTTP from {0}", address.Uri ); try { metadataSet = mex.GetMetadata( address.Uri, MetadataExchangeClientMode.HttpGet ); foundMexEndpoint = true; } catch ( Exception e ) { if ( IDT.IsFatal( e ) ) { throw; } ex = e; } } // // Throw an exception if none of the above methods succeeded. // The inner exception is the last exception thrown when trying to retrieve Mex // if ( !foundMexEndpoint ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.EndpointNotFound ), ex ) ); } WsdlImporter imp = new WsdlImporter( metadataSet ); // // Remember the original MEC so that later on the SecurityBindingElementConverter can use it // imp.State.Add( MetadataExchangeClientKey, mex ); ServiceEndpointCollection serviceEndpoints = imp.ImportAllEndpoints(); // // Find the correct endpoint from the collection // if ( null != serviceEndpoints ) { foreach ( ServiceEndpoint ep in serviceEndpoints ) { if ( Utility.CompareUri( ep.Address.Uri, param.Epr.Uri ) ) { ISecurityCapabilities capabilities = ep.Binding.GetProperty ( new BindingParameterCollection() ); if ( null != capabilities ) { if ( capabilities.SupportedRequestProtectionLevel == System.Net.Security.ProtectionLevel.EncryptAndSign && capabilities.SupportedResponseProtectionLevel == System.Net.Security.ProtectionLevel.EncryptAndSign && capabilities.SupportsServerAuthentication ) { endPoint = ep; break; } } } } } else { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, param.Epr.Uri.AbsoluteUri ) ) ); } if ( null == endPoint ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, param.Epr.Uri.AbsoluteUri ) ) ); } ValidateEndpointAddressIdentityFromMex( endPoint ); return endPoint; } // // Summary: // Validate the identity specified in the EndpointAddress after mex // // Params: // endPoint - the endPoint retrieved from Mex // static void ValidateEndpointAddressIdentityFromMex( ServiceEndpoint endPoint ) { EndpointIdentity ei = endPoint.Address.Identity; Uri stsAddress = endPoint.Address.Uri; // // Only null, Dns, X509, Spn identities are allowed // if( null != ei && null != ei.IdentityClaim && null != ei.IdentityClaim.ClaimType && ClaimTypes.Dns != ei.IdentityClaim.ClaimType && ClaimTypes.Spn != ei.IdentityClaim.ClaimType && ClaimTypes.Thumbprint != ei.IdentityClaim.ClaimType ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, endPoint.Address.Uri ) ) ); } if( null == ei || null == ei.IdentityClaim || null == ei.IdentityClaim.ClaimType ) { // // Default to WCF behavior // } else if( ClaimTypes.Dns == ei.IdentityClaim.ClaimType ) { if( !NativeMcppMethods.DnsNameCompareWrapper( ei.IdentityClaim.Resource.ToString(), stsAddress.DnsSafeHost ) ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, endPoint.Address.Uri ) ) ); } } else if( ClaimTypes.Spn == ei.IdentityClaim.ClaimType ) { string spnFromMex = ei.IdentityClaim.Resource.ToString(); string expectedSpn = String.Format( CultureInfo.InvariantCulture, "host/{0}", stsAddress.DnsSafeHost ); if( !expectedSpn.Equals( spnFromMex, StringComparison.OrdinalIgnoreCase ) ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IndigoNoSuitableEndpointsForAddress, endPoint.Address.Uri ) ) ); } } else { IDT.Assert( ClaimTypes.Thumbprint == ei.IdentityClaim.ClaimType, "Should be Thumbprint" ); } } // // Summary // Create the RST for the request // // Parameters // policy - The policy of the RP. // card - The card to be used for creating the token. // val - The public key to be used by the IP in case of asymmetric keys // clientEntropyForSymmetric - entropy we pass to IP/STS in symmetric case // RequestSecurityToken CreateRst( AddressingVersion version, InfoCardPolicy policy, InfoCard card, bool discloseOptional, RSAKeyValue val, byte[] clientEntropyForSymmetric, CultureInfo displayCulture ) { IDT.ThrowInvalidArgumentConditional( null == policy, "policy" ); IDT.ThrowInvalidArgumentConditional( null == card, "card" ); RequestSecurityTokenParameters rstParams = new RequestSecurityTokenParameters( version, card, policy, discloseOptional, val, m_disclosedClaims, "ProcessRequestSecurityToken", clientEntropyForSymmetric, displayCulture ); return new RequestSecurityTokenForRemoteTokenFactory( rstParams ); } // // Summary // Retrive the KeyIdentifierClauses from the RSTR // // Parameters // tok - The token returned by the IP // internalTokenReference - Return the xml for the InternalTokenReference // externalTokenReference - Return the xml for the ExternalTokenReference // void GetKeyIdentifierClauses( GenericXmlSecurityToken tok, ProtocolProfile profile, out string internalTokenReference, out string externalTokenReference ) { if ( null == tok.InternalTokenReference || null == tok.ExternalTokenReference ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IPSTSClientInvalidTokenReference ) ) ); } try { using ( StringWriter writer = new StringWriter( CultureInfo.InvariantCulture ) ) { profile.TokenSerializer.WriteKeyIdentifierClause( XmlDictionaryWriter.CreateDictionaryWriter( new XmlTextWriter( writer ) ), tok.InternalTokenReference ); writer.Flush(); internalTokenReference = writer.GetStringBuilder().ToString(); } using ( StringWriter writer = new StringWriter( CultureInfo.InvariantCulture ) ) { profile.TokenSerializer.WriteKeyIdentifierClause( XmlDictionaryWriter.CreateDictionaryWriter( new XmlTextWriter( writer ) ), tok.ExternalTokenReference ); writer.Flush(); externalTokenReference = writer.GetStringBuilder().ToString(); } } catch ( XmlException e ) { throw IDT.ThrowHelperError( new TrustExchangeException( SR.GetString( SR.IPSTSClientInvalidTokenReference ), e ) ); } } void EnsureSelfIssuedCardHasLedgerEntryForIssuer( InfoCard card, X509Certificate2 issuerCert, string recipientId, string recipientOrgId, Recipient.RecipientCertParameters recipientParams, string immediateTokenRecipientOrganizationIdentifier ) { IDT.DebugAssert( null != card, "null card" ); IDT.DebugAssert( null != issuerCert, "null issuer cert" ); LedgerEntryCollection ledger = card.GetLedger(); StoreConnection connection = StoreConnection.GetConnection(); try { ledger.Get( connection ); if ( !ledger.ContainsKey( recipientId ) ) { connection.BeginTransaction(); try { // // We are going to generate a token with this card // so we will need to decrypt the master key (if it is decrypted) // The claims are already decrypted (since the card was received from the agent) // so we can skip that step in this case. // InfoCardMasterKey masterKey = card.GetMasterKey( connection ); if ( card.IsPinProtected ) { // // If card is pin protected, the Pin value must be populated. // IDT.Assert( !String.IsNullOrEmpty( card.Pin ), "Should not be null here" ); masterKey.Decrypt( masterKey.GetPinHelper( card.Pin ) ); } else { // // We have a self-issued card without a pin // ; } // // Must save recipient before Ledger entry - see 40019 for details // Recipient recipient = new Recipient( issuerCert, recipientId, recipientOrgId, false, // cert is not cached 0, recipientParams ); recipient.Save( connection ); // // Now save the ledger entry // LedgerEntry entry = LedgerEntry.NewLedgerEntry( card.Id, recipient, card.Key, immediateTokenRecipientOrganizationIdentifier ); ledger.Add( entry ); entry.Save( connection ); connection.CommitTransaction(); } catch { connection.RollbackTransaction(); throw; } } else { IDT.Assert( immediateTokenRecipientOrganizationIdentifier == recipientOrgId, "For the self issued case the RP should be same as token recipient" ); } } finally { connection.Close(); } } // // Summary // STS's don't have to pass back claim names in the DisplayToken. This method looks up the names of the // claims in the managed card based on the claim id. // // Parameters // card - The card in which to look up the claim names. // displayToken - The token for which claim names should be looked up. // private void FillOutDisplayToken( InfoCard card, DisplayToken displayToken ) { if ( null != displayToken.ClaimList ) { InfoCardClaimCollection claims = card.GetClaims(); foreach ( DisplayClaim claim in displayToken.ClaimList ) { // // If no claim name was given see if we can lookup one up in the original card // from which we obtained the token. // if ( String.IsNullOrEmpty( claim.Name ) ) { string name = null; string id = claim.Id; if ( !String.IsNullOrEmpty( claim.Id ) ) { // // Since there is an id, attempt to look up the name in the infocard. // if ( claims.ContainsKey( id ) ) { // // This may end up being null so there is a check below for that. // name = claims[ id ].DisplayTag; } if ( String.IsNullOrEmpty( name ) ) { // // There isn't a name so just use the id. // name = id; } } else { // // There wasn't an id so we can't look up a name at all. // name = SR.GetString( SR.ServiceDisplayTokenNoClaimName ); } claim.Name = name; } } } } // // Summary // Determines whether the given xml content is encrypted via XmlEnc or not. // // Parameters // content - the content to check for encryption. // // Returns // true if the content is encrypted via XmlEnc otherwise false. private bool IsEncryptedXml( XmlElement content ) { return (XmlNames.XmlEnc.EncryptedData == content.LocalName) && (XmlNames.XmlEnc.Namespace == content.NamespaceURI); } [ServiceContract( Namespace = XmlNames.WSIdentity.Namespace, Name = XmlNames.WSIdentity.RequestBrowserToken )] internal interface ISts { [OperationContract( Name = "ProcessRequestSecurityTokenFeb2005", Action = XmlNames.WSTrustXmlSoap2005.c_RequestSecurityTokenAction, ReplyAction = XmlNames.WSTrustXmlSoap2005.c_RequestSecurityTokenResponseAction, ProtectionLevel = ProtectionLevel.EncryptAndSign )] Message ProcessRequestSecurityTokenFeb2005( Message rstMessage ); [OperationContract( Name = "ProcessRequestSecurityTokenWSTrust13", Action = XmlNames.WSTrustOasis2007.c_RequestSecurityTokenAction, ReplyAction = XmlNames.WSTrustOasis2007.c_RequestSecurityTokenResponseAction, ProtectionLevel = ProtectionLevel.EncryptAndSign )] Message ProcessRequestSecurityTokenWSTrust13( Message rstMessage ); } } } // 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
- DrawingImage.cs
- SafeNativeMethods.cs
- COM2Properties.cs
- PassportAuthentication.cs
- SQLBytesStorage.cs
- AccessDataSourceDesigner.cs
- XmlDocumentType.cs
- SqlHelper.cs
- GetPageNumberCompletedEventArgs.cs
- MediaCommands.cs
- ExtractedStateEntry.cs
- SizeFConverter.cs
- CannotUnloadAppDomainException.cs
- WebEventTraceProvider.cs
- ColorConverter.cs
- GenericUI.cs
- SqlClientPermission.cs
- TextSchema.cs
- EntityDataSourceContainerNameItem.cs
- Size.cs
- CompModHelpers.cs
- DataGridTableCollection.cs
- SqlBulkCopyColumnMappingCollection.cs
- SourceFileInfo.cs
- ListViewDataItem.cs
- HtmlImageAdapter.cs
- XmlHierarchyData.cs
- Utils.cs
- ConfigurationErrorsException.cs
- StylusEventArgs.cs
- DiscoveryClientReferences.cs
- IisTraceWebEventProvider.cs
- SchemaImporterExtensionsSection.cs
- BitVec.cs
- TimeSpanSecondsOrInfiniteConverter.cs
- KnownBoxes.cs
- DoWorkEventArgs.cs
- DeflateEmulationStream.cs
- FileIOPermission.cs
- ServiceNameElement.cs
- ThousandthOfEmRealPoints.cs
- BamlLocalizabilityResolver.cs
- Decorator.cs
- PropertyGrid.cs
- DbConnectionPoolIdentity.cs
- DbConnectionHelper.cs
- RelationshipEndMember.cs
- SecurityDescriptor.cs
- PerformanceCounterCategory.cs
- MetadataArtifactLoaderComposite.cs
- PnrpPermission.cs
- PropertyValueChangedEvent.cs
- ListViewItemEventArgs.cs
- GridViewRowEventArgs.cs
- PerspectiveCamera.cs
- BamlRecordWriter.cs
- ErrorProvider.cs
- KeySpline.cs
- ObjectAnimationUsingKeyFrames.cs
- WebServiceBindingAttribute.cs
- ProtocolsSection.cs
- SqlSelectStatement.cs
- Form.cs
- IdentityHolder.cs
- TypeSchema.cs
- GradientBrush.cs
- DbSetClause.cs
- ActiveXMessageFormatter.cs
- RecognizerInfo.cs
- ValuePattern.cs
- ExeContext.cs
- MembershipPasswordException.cs
- XmlCharCheckingReader.cs
- HttpContext.cs
- SchemaHelper.cs
- NamedPermissionSet.cs
- RemotingException.cs
- OleDbSchemaGuid.cs
- TaskResultSetter.cs
- HttpServerProtocol.cs
- AddressAlreadyInUseException.cs
- SqlServer2KCompatibilityCheck.cs
- InstanceHandleConflictException.cs
- CodeTypeDeclarationCollection.cs
- SqlDataSourceEnumerator.cs
- SessionStateContainer.cs
- InfoCardMetadataExchangeClient.cs
- Pair.cs
- Validator.cs
- HtmlTableCell.cs
- FixedSOMPageElement.cs
- TableItemPattern.cs
- webeventbuffer.cs
- SizeValueSerializer.cs
- BehaviorDragDropEventArgs.cs
- Bitmap.cs
- Metafile.cs
- DataGridViewSelectedCellsAccessibleObject.cs
- StorageRoot.cs
- WebServiceReceiveDesigner.cs