| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157 |
- //-----------------------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //-----------------------------------------------------------------------------
- namespace System.ServiceModel.Security
- {
- using System.Collections.ObjectModel;
- using System.Diagnostics;
- using System.Globalization;
- using System.IdentityModel.Tokens;
- using System.Runtime;
- using System.Runtime.Diagnostics;
- using System.ServiceModel;
- using System.ServiceModel.Channels;
- using System.ServiceModel.Diagnostics;
- using System.Xml;
- using System.ServiceModel.Diagnostics.Application;
- // IssuanceTokenProviderBase is a base class for token providers that fetch tokens from
- // another party.
- // This class manages caching of tokens, async messaging, concurrency
- abstract class IssuanceTokenProviderBase<T> : CommunicationObjectSecurityTokenProvider
- where T : IssuanceTokenProviderState
- {
- internal const string defaultClientMaxTokenCachingTimeString = "10675199.02:48:05.4775807";
- internal const bool defaultClientCacheTokens = true;
- internal const int defaultServiceTokenValidityThresholdPercentage = 60;
- // if an issuer is explicitly specified it will be used otherwise target is the issuer
- EndpointAddress issuerAddress;
- // the target service's address and via
- EndpointAddress targetAddress;
- Uri via = null;
- // This controls whether the token provider caches the service tokens it obtains
- bool cacheServiceTokens = defaultClientCacheTokens;
- // This is a fudge factor that controls how long the client can use a service token
- int serviceTokenValidityThresholdPercentage = defaultServiceTokenValidityThresholdPercentage;
- // the maximum time that the client is willing to cache service tokens
- TimeSpan maxServiceTokenCachingTime;
- SecurityStandardsManager standardsManager;
- SecurityAlgorithmSuite algorithmSuite;
- ChannelProtectionRequirements applicationProtectionRequirements;
- SecurityToken cachedToken;
- Object thisLock = new Object();
- string sctUri;
- protected IssuanceTokenProviderBase()
- : base()
- {
- this.cacheServiceTokens = defaultClientCacheTokens;
- this.serviceTokenValidityThresholdPercentage = defaultServiceTokenValidityThresholdPercentage;
- this.maxServiceTokenCachingTime = DefaultClientMaxTokenCachingTime;
- this.standardsManager = null;
- }
- // settings
- public EndpointAddress IssuerAddress
- {
- get
- {
- return this.issuerAddress;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.issuerAddress = value;
- }
- }
- public EndpointAddress TargetAddress
- {
- get
- {
- return this.targetAddress;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.targetAddress = value;
- }
- }
- public bool CacheServiceTokens
- {
- get
- {
- return this.cacheServiceTokens;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.cacheServiceTokens = value;
- }
- }
- internal static TimeSpan DefaultClientMaxTokenCachingTime
- {
- get
- {
- Fx.Assert(TimeSpan.Parse(defaultClientMaxTokenCachingTimeString, CultureInfo.InvariantCulture) == TimeSpan.MaxValue, "TimeSpan value not correct");
- return TimeSpan.MaxValue;
- }
- }
- public int ServiceTokenValidityThresholdPercentage
- {
- get
- {
- return this.serviceTokenValidityThresholdPercentage;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- if (value <= 0 || value > 100)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.ValueMustBeInRange, 1, 100)));
- }
- this.serviceTokenValidityThresholdPercentage = value;
- }
- }
- public SecurityAlgorithmSuite SecurityAlgorithmSuite
- {
- get
- {
- return this.algorithmSuite;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.algorithmSuite = value;
- }
- }
- public TimeSpan MaxServiceTokenCachingTime
- {
- get
- {
- return this.maxServiceTokenCachingTime;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- if (value <= TimeSpan.Zero)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.TimeSpanMustbeGreaterThanTimeSpanZero)));
- }
- if (TimeoutHelper.IsTooLarge(value))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value,
- SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
- }
- this.maxServiceTokenCachingTime = value;
- }
- }
- public SecurityStandardsManager StandardsManager
- {
- get
- {
- if (this.standardsManager == null)
- return SecurityStandardsManager.DefaultInstance;
- return this.standardsManager;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.standardsManager = value;
- }
- }
- public ChannelProtectionRequirements ApplicationProtectionRequirements
- {
- get
- {
- return this.applicationProtectionRequirements;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.applicationProtectionRequirements = value;
- }
- }
- public Uri Via
- {
- get
- {
- return this.via;
- }
- set
- {
- this.CommunicationObject.ThrowIfDisposedOrImmutable();
- this.via = value;
- }
- }
- public override bool SupportsTokenCancellation
- {
- get
- {
- return true;
- }
- }
- protected Object ThisLock
- {
- get { return this.thisLock; }
- }
- protected virtual bool IsMultiLegNegotiation
- {
- get { return true; }
- }
- protected abstract MessageVersion MessageVersion
- {
- get;
- }
- protected abstract bool RequiresManualReplyAddressing
- {
- get;
- }
- public abstract XmlDictionaryString RequestSecurityTokenAction
- {
- get;
- }
- public abstract XmlDictionaryString RequestSecurityTokenResponseAction
- {
- get;
- }
- protected string SecurityContextTokenUri
- {
- get
- {
- ThrowIfCreated();
- return this.sctUri;
- }
- }
- protected void ThrowIfCreated()
- {
- CommunicationState state = this.CommunicationObject.State;
- if (state == CommunicationState.Created)
- {
- Exception e = new InvalidOperationException(SR.GetString(SR.CommunicationObjectCannotBeUsed, this.GetType().ToString(), state.ToString()));
- throw TraceUtility.ThrowHelperError(e, Guid.Empty, this);
- }
- }
- protected void ThrowIfClosedOrCreated()
- {
- this.CommunicationObject.ThrowIfClosed();
- ThrowIfCreated();
- }
- // ISecurityCommunicationObject methods
- public override void OnOpen(TimeSpan timeout)
- {
- if (this.targetAddress == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.TargetAddressIsNotSet, this.GetType())));
- }
- if (this.SecurityAlgorithmSuite == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SecurityAlgorithmSuiteNotSet, this.GetType())));
- }
- this.sctUri = this.StandardsManager.SecureConversationDriver.TokenTypeUri;
- }
- // helper methods
- protected void EnsureEndpointAddressDoesNotRequireEncryption(EndpointAddress target)
- {
- if (this.ApplicationProtectionRequirements == null
- || this.ApplicationProtectionRequirements.OutgoingEncryptionParts == null)
- {
- return;
- }
- MessagePartSpecification channelEncryptionParts = this.ApplicationProtectionRequirements.OutgoingEncryptionParts.ChannelParts;
- if (channelEncryptionParts == null)
- {
- return;
- }
- for (int i = 0; i < this.targetAddress.Headers.Count; ++i)
- {
- AddressHeader header = target.Headers[i];
- if (channelEncryptionParts.IsHeaderIncluded(header.Name, header.Namespace))
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.SecurityNegotiationCannotProtectConfidentialEndpointHeader, target, header.Name, header.Namespace)));
- }
- }
- }
- DateTime GetServiceTokenEffectiveExpirationTime(SecurityToken serviceToken)
- {
- // if the token never expires, return the max date time
- // else return effective expiration time
- if (serviceToken.ValidTo.ToUniversalTime() >= SecurityUtils.MaxUtcDateTime)
- {
- return serviceToken.ValidTo;
- }
- TimeSpan interval = serviceToken.ValidTo.ToUniversalTime() - serviceToken.ValidFrom.ToUniversalTime();
- long serviceTokenTicksInterval = interval.Ticks;
- long effectiveTicksInterval = Convert.ToInt64((double)this.ServiceTokenValidityThresholdPercentage / 100.0 * (double)serviceTokenTicksInterval, NumberFormatInfo.InvariantInfo);
- DateTime effectiveExpirationTime = TimeoutHelper.Add(serviceToken.ValidFrom.ToUniversalTime(), new TimeSpan(effectiveTicksInterval));
- DateTime maxCachingTime = TimeoutHelper.Add(serviceToken.ValidFrom.ToUniversalTime(), this.MaxServiceTokenCachingTime);
- if (effectiveExpirationTime <= maxCachingTime)
- {
- return effectiveExpirationTime;
- }
- else
- {
- return maxCachingTime;
- }
- }
- bool IsServiceTokenTimeValid(SecurityToken serviceToken)
- {
- DateTime effectiveExpirationTime = GetServiceTokenEffectiveExpirationTime(serviceToken);
- return (DateTime.UtcNow <= effectiveExpirationTime);
- }
- SecurityToken GetCurrentServiceToken()
- {
- if (this.CacheServiceTokens && this.cachedToken != null && IsServiceTokenTimeValid(cachedToken))
- {
- return this.cachedToken;
- }
- else
- {
- return null;
- }
- }
- static protected void ThrowIfFault(Message message, EndpointAddress target)
- {
- SecurityUtils.ThrowIfNegotiationFault(message, target);
- }
- protected override IAsyncResult BeginGetTokenCore(TimeSpan timeout, AsyncCallback callback, object state)
- {
- this.CommunicationObject.ThrowIfClosedOrNotOpen();
- IAsyncResult asyncResult;
- lock (ThisLock)
- {
- SecurityToken token = GetCurrentServiceToken();
- if (token != null)
- {
- SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, token, this.targetAddress);
- asyncResult = new CompletedAsyncResult<SecurityToken>(token, callback, state);
- }
- else
- {
- asyncResult = BeginNegotiation(timeout, callback, state);
- }
- }
- return asyncResult;
- }
- protected override SecurityToken EndGetTokenCore(IAsyncResult result)
- {
- if (result is CompletedAsyncResult<SecurityToken>)
- {
- return CompletedAsyncResult<SecurityToken>.End(result);
- }
- else
- {
- return this.EndNegotiation(result);
- }
- }
- protected override SecurityToken GetTokenCore(TimeSpan timeout)
- {
- this.CommunicationObject.ThrowIfClosedOrNotOpen();
- SecurityToken result;
- lock (ThisLock)
- {
- result = GetCurrentServiceToken();
- if (result != null)
- {
- SecurityTraceRecordHelper.TraceUsingCachedServiceToken(this, result, this.targetAddress);
- }
- }
- if (result == null)
- {
- result = DoNegotiation(timeout);
- }
- return result;
- }
- protected override void CancelTokenCore(TimeSpan timeout, SecurityToken token)
- {
- if (this.CacheServiceTokens)
- {
- lock (ThisLock)
- {
- if (Object.ReferenceEquals(token, this.cachedToken))
- {
- this.cachedToken = null;
- }
- }
- }
- }
- // Negotiation state creation methods
- protected abstract bool CreateNegotiationStateCompletesSynchronously(EndpointAddress target, Uri via);
- protected abstract IAsyncResult BeginCreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout, AsyncCallback callback, object state);
- protected abstract T CreateNegotiationState(EndpointAddress target, Uri via, TimeSpan timeout);
- protected abstract T EndCreateNegotiationState(IAsyncResult result);
- // Negotiation message processing methods
- protected abstract BodyWriter GetFirstOutgoingMessageBody(T negotiationState, out MessageProperties properties);
- protected abstract BodyWriter GetNextOutgoingMessageBody(Message incomingMessage, T negotiationState);
- protected abstract bool WillInitializeChannelFactoriesCompleteSynchronously(EndpointAddress target);
- protected abstract void InitializeChannelFactories(EndpointAddress target, TimeSpan timeout);
- protected abstract IAsyncResult BeginInitializeChannelFactories(EndpointAddress target, TimeSpan timeout, AsyncCallback callback, object state);
- protected abstract void EndInitializeChannelFactories(IAsyncResult result);
- protected abstract IRequestChannel CreateClientChannel(EndpointAddress target, Uri via);
- void PrepareRequest(Message nextMessage)
- {
- PrepareRequest(nextMessage, null);
- }
- void PrepareRequest(Message nextMessage, RequestSecurityToken rst)
- {
- if (rst != null && !rst.IsReadOnly)
- {
- rst.Message = nextMessage;
- }
- RequestReplyCorrelator.PrepareRequest(nextMessage);
- if (this.RequiresManualReplyAddressing)
- {
- // if we are on HTTP, we need to explicitly add a reply-to header for interop
- nextMessage.Headers.ReplyTo = EndpointAddress.AnonymousAddress;
- }
- }
- /*
- * Negotiation consists of the following steps (some may be async in the async case):
- * 1. Create negotiation state
- * 2. Initialize channel factories
- * 3. Create an channel
- * 4. Open the channel
- * 5. Create the next message to send to server
- * 6. Send the message and get reply
- * 8. Process incoming message and get next outgoing message.
- * 9. If no outgoing message, then negotiation is over. Go to step 11.
- * 10. Goto step 6
- * 11. Close the IRequest channel and complete
- */
- protected SecurityToken DoNegotiation(TimeSpan timeout)
- {
- ThrowIfClosedOrCreated();
- SecurityTraceRecordHelper.TraceBeginSecurityNegotiation(this, this.targetAddress);
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- IRequestChannel rstChannel = null;
- T negotiationState = null;
- TimeSpan timeLeft = timeout;
- int legs = 1;
- try
- {
- negotiationState = this.CreateNegotiationState(this.targetAddress, this.via, timeoutHelper.RemainingTime());
- InitializeNegotiationState(negotiationState);
- this.InitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime());
- rstChannel = this.CreateClientChannel(negotiationState.RemoteAddress, this.via);
- rstChannel.Open(timeoutHelper.RemainingTime());
- Message nextOutgoingMessage = null;
- Message incomingMessage = null;
- SecurityToken serviceToken = null;
- for (;;)
- {
- nextOutgoingMessage = this.GetNextOutgoingMessage(incomingMessage, negotiationState);
- if (incomingMessage != null)
- {
- incomingMessage.Close();
- }
- if (nextOutgoingMessage != null)
- {
- using (nextOutgoingMessage)
- {
- EventTraceActivity eventTraceActivity = null;
- if (TD.MessageSentToTransportIsEnabled())
- {
- eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(nextOutgoingMessage);
- }
- TraceUtility.ProcessOutgoingMessage(nextOutgoingMessage, eventTraceActivity);
- timeLeft = timeoutHelper.RemainingTime();
- incomingMessage = rstChannel.Request(nextOutgoingMessage, timeLeft);
- if (incomingMessage == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
- }
- if (eventTraceActivity == null && TD.MessageReceivedFromTransportIsEnabled())
- {
- eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(incomingMessage);
- }
- TraceUtility.ProcessIncomingMessage(incomingMessage, eventTraceActivity);
- }
- legs += 2;
- }
- else
- {
- if (!negotiationState.IsNegotiationCompleted)
- {
- throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoNegotiationMessageToSend)), incomingMessage);
- }
- try
- {
- rstChannel.Close(timeoutHelper.RemainingTime());
- }
- catch (CommunicationException e)
- {
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- rstChannel.Abort();
- }
- catch (TimeoutException e)
- {
- if (TD.CloseTimeoutIsEnabled())
- {
- TD.CloseTimeout(e.Message);
- }
- DiagnosticUtility.TraceHandledException(e, TraceEventType.Information);
- rstChannel.Abort();
- }
- rstChannel = null;
- this.ValidateAndCacheServiceToken(negotiationState);
- serviceToken = negotiationState.ServiceToken;
- SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, serviceToken, this.targetAddress);
- break;
- }
- }
- return serviceToken;
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- if (e is TimeoutException)
- {
- e = new TimeoutException(SR.GetString(SR.ClientSecurityNegotiationTimeout, timeout, legs, timeLeft), e);
- }
- EndpointAddress temp = (negotiationState == null) ? null : negotiationState.RemoteAddress;
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(WrapExceptionIfRequired(e, temp, this.issuerAddress));
- }
- finally
- {
- Cleanup(rstChannel, negotiationState);
- }
- }
- void InitializeNegotiationState(T negotiationState)
- {
- negotiationState.TargetAddress = this.targetAddress;
- if (negotiationState.Context == null && this.IsMultiLegNegotiation)
- {
- negotiationState.Context = SecurityUtils.GenerateId();
- }
- if (this.IssuerAddress != null)
- {
- negotiationState.RemoteAddress = this.IssuerAddress;
- }
- else
- {
- negotiationState.RemoteAddress = negotiationState.TargetAddress;
- }
- }
- Message GetNextOutgoingMessage(Message incomingMessage, T negotiationState)
- {
- BodyWriter nextMessageBody;
- MessageProperties nextMessageProperties = null;
- if (incomingMessage == null)
- {
- nextMessageBody = this.GetFirstOutgoingMessageBody(negotiationState, out nextMessageProperties);
- }
- else
- {
- nextMessageBody = this.GetNextOutgoingMessageBody(incomingMessage, negotiationState);
- }
- if (nextMessageBody != null)
- {
- Message nextMessage;
- if (incomingMessage == null)
- {
- nextMessage = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.RequestSecurityTokenAction, this.MessageVersion.Addressing), nextMessageBody);
- }
- else
- {
- nextMessage = Message.CreateMessage(this.MessageVersion, ActionHeader.Create(this.RequestSecurityTokenResponseAction, this.MessageVersion.Addressing), nextMessageBody);
- }
- if (nextMessageProperties != null)
- {
- nextMessage.Properties.CopyProperties(nextMessageProperties);
- }
- PrepareRequest(nextMessage, nextMessageBody as RequestSecurityToken);
- return nextMessage;
- }
- else
- {
- return null;
- }
- }
- void Cleanup(IChannel rstChannel, T negotiationState)
- {
- if (negotiationState != null)
- {
- negotiationState.Dispose();
- }
- if (rstChannel != null)
- {
- rstChannel.Abort();
- }
- }
- protected IAsyncResult BeginNegotiation(TimeSpan timeout, AsyncCallback callback, object state)
- {
- ThrowIfClosedOrCreated();
- SecurityTraceRecordHelper.TraceBeginSecurityNegotiation(this, this.targetAddress);
- return new SecurityNegotiationAsyncResult(this, timeout, callback, state);
- }
- protected SecurityToken EndNegotiation(IAsyncResult result)
- {
- SecurityToken token = SecurityNegotiationAsyncResult.End(result);
- SecurityTraceRecordHelper.TraceEndSecurityNegotiation(this, token, this.targetAddress);
- return token;
- }
- protected virtual void ValidateKeySize(GenericXmlSecurityToken issuedToken)
- {
- if (this.SecurityAlgorithmSuite == null)
- {
- return;
- }
- ReadOnlyCollection<SecurityKey> issuedKeys = issuedToken.SecurityKeys;
- if (issuedKeys != null && issuedKeys.Count == 1)
- {
- SymmetricSecurityKey symmetricKey = issuedKeys[0] as SymmetricSecurityKey;
- if (symmetricKey != null)
- {
- if (this.SecurityAlgorithmSuite.IsSymmetricKeyLengthSupported(symmetricKey.KeySize))
- {
- return;
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.InvalidIssuedTokenKeySize, symmetricKey.KeySize)));
- }
- }
- }
- else
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.CannotObtainIssuedTokenKeySize)));
- }
- }
- static bool ShouldWrapException(Exception e)
- {
- return (e is System.ComponentModel.Win32Exception
- || e is XmlException
- || e is InvalidOperationException
- || e is ArgumentException
- || e is QuotaExceededException
- || e is System.Security.SecurityException
- || e is System.Security.Cryptography.CryptographicException
- || e is SecurityTokenException);
- }
- static Exception WrapExceptionIfRequired(Exception e, EndpointAddress targetAddress, EndpointAddress issuerAddress)
- {
- if (ShouldWrapException(e))
- {
- Uri targetUri;
- if (targetAddress != null)
- {
- targetUri = targetAddress.Uri;
- }
- else
- {
- targetUri = null;
- }
- Uri issuerUri;
- if (issuerAddress != null)
- {
- issuerUri = issuerAddress.Uri;
- }
- else
- {
- issuerUri = targetUri;
- }
- // => issuerUri != null
- if (targetUri != null)
- {
- e = new SecurityNegotiationException(SR.GetString(SR.SoapSecurityNegotiationFailedForIssuerAndTarget, issuerUri, targetUri), e);
- }
- else
- {
- e = new SecurityNegotiationException(SR.GetString(SR.SoapSecurityNegotiationFailed), e);
- }
- }
- return e;
- }
- void ValidateAndCacheServiceToken(T negotiationState)
- {
- this.ValidateKeySize(negotiationState.ServiceToken);
- lock (ThisLock)
- {
- if (this.CacheServiceTokens)
- {
- this.cachedToken = negotiationState.ServiceToken;
- }
- }
- }
- class SecurityNegotiationAsyncResult : AsyncResult
- {
- static AsyncCallback createNegotiationStateCallback = Fx.ThunkCallback(new AsyncCallback(CreateNegotiationStateCallback));
- static AsyncCallback initializeChannelFactoriesCallback = Fx.ThunkCallback(new AsyncCallback(InitializeChannelFactoriesCallback));
- static AsyncCallback closeChannelCallback = Fx.ThunkCallback(new AsyncCallback(CloseChannelCallback));
- static AsyncCallback sendRequestCallback = Fx.ThunkCallback(new AsyncCallback(SendRequestCallback));
- static AsyncCallback openChannelCallback = Fx.ThunkCallback(new AsyncCallback(OpenChannelCallback));
- TimeSpan timeout;
- TimeoutHelper timeoutHelper;
- SecurityToken serviceToken;
- IssuanceTokenProviderBase<T> tokenProvider;
- IRequestChannel rstChannel;
- T negotiationState;
- Message nextOutgoingMessage;
- EndpointAddress target;
- EndpointAddress issuer;
- Uri via;
- public SecurityNegotiationAsyncResult(IssuanceTokenProviderBase<T> tokenProvider, TimeSpan timeout, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.timeout = timeout;
- timeoutHelper = new TimeoutHelper(timeout);
- this.tokenProvider = tokenProvider;
- this.target = tokenProvider.targetAddress;
- this.issuer = tokenProvider.issuerAddress;
- this.via = tokenProvider.via;
- bool completeSelf = false;
- try
- {
- completeSelf = this.StartNegotiation();
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.OnSyncNegotiationFailure(e));
- }
- if (completeSelf)
- {
- this.OnNegotiationComplete();
- Complete(true);
- }
- }
- bool StartNegotiation()
- {
- if (this.tokenProvider.CreateNegotiationStateCompletesSynchronously(this.target, this.via))
- {
- this.negotiationState = this.tokenProvider.CreateNegotiationState(target, this.via, timeoutHelper.RemainingTime());
- }
- else
- {
- IAsyncResult createStateResult = this.tokenProvider.BeginCreateNegotiationState(target, this.via, timeoutHelper.RemainingTime(), createNegotiationStateCallback, this);
- if (!createStateResult.CompletedSynchronously)
- {
- return false;
- }
- this.negotiationState = this.tokenProvider.EndCreateNegotiationState(createStateResult);
- }
- return this.OnCreateStateComplete();
- }
- static void CreateNegotiationStateCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- self.negotiationState = self.tokenProvider.EndCreateNegotiationState(result);
- completeSelf = self.OnCreateStateComplete();
- if (completeSelf)
- {
- self.OnNegotiationComplete();
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- completeSelf = true;
- completionException = self.OnAsyncNegotiationFailure(e);
- }
- if (completeSelf)
- {
- self.Complete(false, completionException);
- }
- }
- bool OnCreateStateComplete()
- {
- this.tokenProvider.InitializeNegotiationState(negotiationState);
- return InitializeChannelFactories();
- }
- bool InitializeChannelFactories()
- {
- if (this.tokenProvider.WillInitializeChannelFactoriesCompleteSynchronously(negotiationState.RemoteAddress))
- {
- this.tokenProvider.InitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime());
- }
- else
- {
- IAsyncResult result = this.tokenProvider.BeginInitializeChannelFactories(negotiationState.RemoteAddress, timeoutHelper.RemainingTime(), initializeChannelFactoriesCallback, this);
- if (!result.CompletedSynchronously)
- {
- return false;
- }
- this.tokenProvider.EndInitializeChannelFactories(result);
- }
- return this.OnChannelFactoriesInitialized();
- }
- static void InitializeChannelFactoriesCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- self.tokenProvider.EndInitializeChannelFactories(result);
- completeSelf = self.OnChannelFactoriesInitialized();
- if (completeSelf)
- {
- self.OnNegotiationComplete();
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- completeSelf = true;
- completionException = self.OnAsyncNegotiationFailure(e);
- }
- if (completeSelf)
- {
- self.Complete(false, completionException);
- }
- }
- bool OnChannelFactoriesInitialized()
- {
- this.rstChannel = this.tokenProvider.CreateClientChannel(negotiationState.RemoteAddress, this.via);
- this.nextOutgoingMessage = null;
- return this.OnRequestChannelCreated();
- }
- bool OnRequestChannelCreated()
- {
- IAsyncResult result = rstChannel.BeginOpen(timeoutHelper.RemainingTime(), openChannelCallback, this);
- if (!result.CompletedSynchronously)
- {
- return false;
- }
- rstChannel.EndOpen(result);
- return this.OnRequestChannelOpened();
- }
- static void OpenChannelCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- self.rstChannel.EndOpen(result);
- completeSelf = self.OnRequestChannelOpened();
- if (completeSelf)
- {
- self.OnNegotiationComplete();
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- completeSelf = true;
- completionException = self.OnAsyncNegotiationFailure(e);
- }
- if (completeSelf)
- {
- self.Complete(false, completionException);
- }
- }
- bool OnRequestChannelOpened()
- {
- return this.SendRequest();
- }
- bool SendRequest()
- {
- if (this.nextOutgoingMessage == null)
- {
- return this.DoNegotiation(null);
- }
- else
- {
- this.tokenProvider.PrepareRequest(this.nextOutgoingMessage);
- bool closeMessage = true;
- Message incomingMessage = null;
- IAsyncResult result = null;
- try
- {
- result = this.rstChannel.BeginRequest(this.nextOutgoingMessage, timeoutHelper.RemainingTime(), sendRequestCallback, this);
- if (!result.CompletedSynchronously)
- {
- closeMessage = false;
- return false;
- }
- incomingMessage = rstChannel.EndRequest(result);
- }
- finally
- {
- if (closeMessage && this.nextOutgoingMessage != null)
- {
- this.nextOutgoingMessage.Close();
- }
- }
- using (incomingMessage)
- {
- if (incomingMessage == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
- }
- return this.DoNegotiation(incomingMessage);
- }
- }
- }
- static void SendRequestCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- Message incomingMessage = null;
- try
- {
- incomingMessage = self.rstChannel.EndRequest(result);
- }
- finally
- {
- if (self.nextOutgoingMessage != null)
- {
- self.nextOutgoingMessage.Close();
- }
- }
- using (incomingMessage)
- {
- if (incomingMessage == null)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.FailToRecieveReplyFromNegotiation)));
- }
- completeSelf = self.DoNegotiation(incomingMessage);
- }
- if (completeSelf)
- {
- self.OnNegotiationComplete();
- }
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- completeSelf = true;
- completionException = self.OnAsyncNegotiationFailure(e);
- }
- if (completeSelf)
- {
- self.Complete(false, completionException);
- }
- }
- bool DoNegotiation(Message incomingMessage)
- {
- this.nextOutgoingMessage = this.tokenProvider.GetNextOutgoingMessage(incomingMessage, this.negotiationState);
- if (this.nextOutgoingMessage != null)
- {
- return SendRequest();
- }
- else
- {
- if (!negotiationState.IsNegotiationCompleted)
- {
- throw TraceUtility.ThrowHelperError(new SecurityNegotiationException(SR.GetString(SR.NoNegotiationMessageToSend)), incomingMessage);
- }
- return this.CloseRequestChannel();
- }
- }
- bool CloseRequestChannel()
- {
- IAsyncResult result = rstChannel.BeginClose(timeoutHelper.RemainingTime(), closeChannelCallback, this);
- if (!result.CompletedSynchronously)
- {
- return false;
- }
- rstChannel.EndClose(result);
- return true;
- }
- static void CloseChannelCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SecurityNegotiationAsyncResult self = (SecurityNegotiationAsyncResult)result.AsyncState;
- bool completeSelf = false;
- Exception completionException = null;
- try
- {
- self.rstChannel.EndClose(result);
- self.OnNegotiationComplete();
- completeSelf = true;
- }
- #pragma warning suppress 56500 // covered by FxCOP
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- throw;
- completeSelf = true;
- completionException = self.OnAsyncNegotiationFailure(e);
- }
- if (completeSelf)
- {
- self.Complete(false, completionException);
- }
- }
- void Cleanup()
- {
- this.tokenProvider.Cleanup(this.rstChannel, this.negotiationState);
- this.rstChannel = null;
- this.negotiationState = null;
- }
- Exception OnAsyncNegotiationFailure(Exception e)
- {
- EndpointAddress pinnedEpr = null;
- try
- {
- pinnedEpr = (this.negotiationState == null) ? null : this.negotiationState.RemoteAddress;
- Cleanup();
- }
- catch (CommunicationException ex)
- {
- DiagnosticUtility.TraceHandledException(ex, TraceEventType.Information);
- }
- return IssuanceTokenProviderBase<T>.WrapExceptionIfRequired(e, pinnedEpr, this.issuer);
- }
- Exception OnSyncNegotiationFailure(Exception e)
- {
- EndpointAddress pinnedTarget = (this.negotiationState == null) ? null : this.negotiationState.RemoteAddress;
- return IssuanceTokenProviderBase<T>.WrapExceptionIfRequired(e, pinnedTarget, this.issuer);
- }
- void OnNegotiationComplete()
- {
- using (negotiationState)
- {
- SecurityToken token = negotiationState.ServiceToken;
- this.tokenProvider.ValidateAndCacheServiceToken(negotiationState);
- this.serviceToken = token;
- }
- }
- public static SecurityToken End(IAsyncResult result)
- {
- SecurityNegotiationAsyncResult self = AsyncResult.End<SecurityNegotiationAsyncResult>(result);
- return self.serviceToken;
- }
- }
- }
- }
|