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
- WebColorConverter.cs
- LocatorManager.cs
- ResponseBodyWriter.cs
- NoResizeSelectionBorderGlyph.cs
- OSFeature.cs
- ListControlBuilder.cs
- CompilationUtil.cs
- BackStopAuthenticationModule.cs
- Properties.cs
- PowerStatus.cs
- InkCanvasAutomationPeer.cs
- BypassElement.cs
- StringComparer.cs
- PointKeyFrameCollection.cs
- CodeSnippetCompileUnit.cs
- MaskDesignerDialog.cs
- ObservableCollection.cs
- Debug.cs
- EdmSchemaError.cs
- ProfilePropertySettingsCollection.cs
- BasicAsyncResult.cs
- StorageComplexTypeMapping.cs
- WpfKnownTypeInvoker.cs
- Point4D.cs
- SyndicationCategory.cs
- MessageBox.cs
- _SSPISessionCache.cs
- TaskFileService.cs
- NegatedCellConstant.cs
- EventProviderClassic.cs
- EntityDataReader.cs
- SqlServer2KCompatibilityAnnotation.cs
- SystemNetworkInterface.cs
- CodeValidator.cs
- TextRange.cs
- ViewSimplifier.cs
- DataSvcMapFileSerializer.cs
- AuthenticateEventArgs.cs
- iisPickupDirectory.cs
- MarginCollapsingState.cs
- XPathNavigator.cs
- Freezable.cs
- Label.cs
- RegexStringValidator.cs
- DetailsViewCommandEventArgs.cs
- AssemblyBuilder.cs
- AttachedPropertyBrowsableAttribute.cs
- __ComObject.cs
- TrackBarRenderer.cs
- CodeCommentStatement.cs
- PaintValueEventArgs.cs
- JumpList.cs
- OperationCanceledException.cs
- ObjectCloneHelper.cs
- Point.cs
- PathParser.cs
- _ProxyRegBlob.cs
- ACL.cs
- SqlDataSourceSummaryPanel.cs
- CustomMenuItemCollection.cs
- MultipleViewPattern.cs
- ResumeStoryboard.cs
- ArraySortHelper.cs
- XmlText.cs
- GraphicsContext.cs
- KeySpline.cs
- VisualProxy.cs
- ConstructorNeedsTagAttribute.cs
- ToolStripManager.cs
- CodeDomConfigurationHandler.cs
- GeneralTransform3DTo2DTo3D.cs
- ConsoleCancelEventArgs.cs
- StylusShape.cs
- ExpressionBuilderContext.cs
- EventMetadata.cs
- Panel.cs
- SortedList.cs
- SoapHeader.cs
- DriveNotFoundException.cs
- X509UI.cs
- EventProxy.cs
- TextRunProperties.cs
- TextEffect.cs
- CodeSubDirectoriesCollection.cs
- GeneralTransform2DTo3D.cs
- TemplateKeyConverter.cs
- DisableDpiAwarenessAttribute.cs
- IInstanceTable.cs
- MediaPlayer.cs
- SerializationEventsCache.cs
- XmlDesigner.cs
- ResolvedKeyFrameEntry.cs
- TypeBrowserDialog.cs
- InfoCardRSAPKCS1KeyExchangeFormatter.cs
- ListBox.cs
- Dictionary.cs
- DesignTableCollection.cs
- PriorityChain.cs
- BuildDependencySet.cs
- PackageRelationshipSelector.cs