//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ using System; using System.Collections.Generic; using System.IdentityModel.Selectors; using System.IdentityModel.Tokens; using System.Runtime; using System.Security.Cryptography; using System.Security.Authentication.ExtendedProtection; using System.ServiceModel.Diagnostics; namespace System.ServiceModel.Security.Tokens { /// /// The ProviderBackedSecurityToken was added for the ChannelBindingToken work for Win7. /// It is used to delay the resolution of a token until it is needed. /// For the CBT, this delay is necessary as the CBT is not available until SecurityAppliedMessage.OnWriteMessage is called. /// The CBT binds a token to the /// internal class ProviderBackedSecurityToken : SecurityToken { SecurityTokenProvider _tokenProvider; // Double-checked locking pattern requires volatile for read/write synchronization volatile SecurityToken _securityToken; TimeSpan _timeout; ChannelBinding _channelBinding; object _lock; /// /// Constructor to create an instance of this class. /// /// SecurityToken that represents the SecurityTokenElement element. public ProviderBackedSecurityToken( SecurityTokenProvider tokenProvider, TimeSpan timeout ) { _lock = new object(); if ( tokenProvider == null ) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("tokenProvider")); } _tokenProvider = tokenProvider; _timeout = timeout; } public SecurityTokenProvider TokenProvider { get { return _tokenProvider; } } public ChannelBinding ChannelBinding { set { _channelBinding = value; } } void ResolveSecurityToken() { if ( _securityToken == null ) { lock ( _lock ) { if ( _securityToken == null ) { ClientCredentialsSecurityTokenManager.KerberosSecurityTokenProviderWrapper kerbTokenProvider = _tokenProvider as ClientCredentialsSecurityTokenManager.KerberosSecurityTokenProviderWrapper; if (kerbTokenProvider != null) { _securityToken = kerbTokenProvider.GetToken((new TimeoutHelper(_timeout)).RemainingTime(), _channelBinding); } else { _securityToken = _tokenProvider.GetToken((new TimeoutHelper(_timeout)).RemainingTime()); } } } } if ( _securityToken == null ) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( new SecurityTokenException( SR.GetString( SR.SecurityTokenNotResolved, _tokenProvider.GetType().ToString() ) ) ); } return; } public SecurityToken Token { get { if ( _securityToken == null ) { ResolveSecurityToken(); } return _securityToken; } } public override string Id { get { if ( _securityToken == null ) { ResolveSecurityToken(); } return _securityToken.Id; } } public override System.Collections.ObjectModel.ReadOnlyCollection SecurityKeys { get { if ( _securityToken == null ) { ResolveSecurityToken(); } return _securityToken.SecurityKeys; } } public override DateTime ValidFrom { get { if ( _securityToken == null ) { ResolveSecurityToken(); } return _securityToken.ValidFrom; } } public override DateTime ValidTo { get { if ( _securityToken == null ) { ResolveSecurityToken(); } return _securityToken.ValidTo; } } } }