Code:
/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Activation / HostedHttpRequestAsyncResult.cs / 3 / HostedHttpRequestAsyncResult.cs
//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------- namespace System.ServiceModel.Activation { using System.Diagnostics; using System.Globalization; using System.Net; using System.Text; using System.Threading; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Diagnostics; using System.Web; using System.Web.Hosting; using System.Web.Compilation; using System.Security.Principal; using System.IO; using System.Security; using System.Security.Permissions; class HostedHttpRequestAsyncResult : AsyncResult { ////// Critical - stores the securitycritical callback values /// we need to protect these value /// [SecurityCritical] static WindowsIdentity anonymousIdentity; [SecurityCritical] static WaitCallback waitOnBeginRequest; [SecurityCritical] static WaitCallback waitOnBeginRequestWithFlow; [SecurityCritical] static ContextCallback contextOnBeginRequest; [SecurityCritical] static AsyncCallback processRequestCompleteCallback; [ThreadStatic] static AutoResetEvent waitObject; ////// Critical - keeps track of impersonated user, caller must use with care /// [SecurityCritical] HostedImpersonationContext impersonationContext; ////// Critical - keeps track of thread static data (HttpContext, CurrentCulture, CurrentUICulture) that /// is used for AspNetCompatibility mode, caller must use with care /// [SecurityCritical] HostedThreadData hostedThreadData; ////// Critical - this field is used to manipulate request/responses using APIs protected by LinkDemand /// it is critical because we use it to determine whether we believe we're being hosted in ASP.NET or not /// the field is set in the constructor of this class and we deem it safe because: /// 1) all paths that lead to the .ctor are SecurityCritical and /// 2) those paths have called ServiceHostingEnvironment.EnsureInitialized (which is also critical) /// so if the field is not null, it's safe to say that we're hosted in ASP.NET, /// hence all the helper methods in this class that touch this field can be SecurityTreatAsSafe /// [SecurityCritical] HttpApplication context; Uri originalRequestUri; Uri requestUri; int state; ////// Critical - Determines whether to set the HttpContext on the outgoing thread. /// [SecurityCritical] bool flowContext; static class State { internal const int Running = 0; internal const int Completed = 1; internal const int Aborted = 2; } ////// Critical & TreatAsSafe - Mark this property as Securitycritical and SecuritytreatasSafe /// in order access the value of corresponding static field and prevent someone form changing its value /// public static WindowsIdentity AnonymousIdentity { [SecurityCritical, SecurityTreatAsSafe] get { if (null == anonymousIdentity) { anonymousIdentity = WindowsIdentity.GetAnonymous(); } return anonymousIdentity; } } ////// Critical & TreatAsSafe - Mark this property as Securitycritical and SecuritytreatasSafe /// in order access the value of corresponding static field and prevent someone form changing its value /// public static WaitCallback WaitOnBeginRequest { [SecurityCritical, SecurityTreatAsSafe] get { if (null == waitOnBeginRequest) { waitOnBeginRequest = new WaitCallback(OnBeginRequest); } return waitOnBeginRequest; } } ////// Critical & TreatAsSafe - Mark this property as Securitycritical and Securitytreatassafe /// in order access the value of corresponding static field and prevent someone form changing its value /// public static WaitCallback WaitOnBeginRequestWithFlow { [SecurityCritical, SecurityTreatAsSafe] get { if (null == waitOnBeginRequestWithFlow) { waitOnBeginRequestWithFlow = new WaitCallback(OnBeginRequestWithFlow); } return waitOnBeginRequestWithFlow; } } ////// Critical & TreatAsSafe - Mark this property as Securitycritical and SecuritytreatasSafe /// in order access the value of corresponding static field and prevent someone form changing its value /// public static ContextCallback ContextOnBeginRequest { [SecurityCritical, SecurityTreatAsSafe] get { if (null == contextOnBeginRequest) { contextOnBeginRequest = new ContextCallback(OnBeginRequest); } return contextOnBeginRequest; } } ////// Critical & TreatAsSafe - Mark this property as Securitycritical and SecuritytreatasSafe /// in order access the value of corresponding static field and prevent someone form changing its value /// public static AsyncCallback ProcessRequestCompleteCallback { [SecurityCritical, SecurityTreatAsSafe] get { if (null == processRequestCompleteCallback) { processRequestCompleteCallback = DiagnosticUtility.Utility.ThunkCallback(new AsyncCallback(ProcessRequestComplete)); } return processRequestCompleteCallback; } } ////// Critical - Captures HostedImpersonationContext which must be done in the right place, and calls unsafe /// ScheduleCallbackLowPriNoFlow and ScriptTimeout. Called outside of user security context. /// callers of this .ctor must call ServiceHostingEnvironment.EnsureInitialized /// [SecurityCritical] public static void ExecuteSynchronous(HttpApplication context, bool flowContext) { AutoResetEvent wait = HostedHttpRequestAsyncResult.waitObject; if (wait == null) { wait = new AutoResetEvent(false); HostedHttpRequestAsyncResult.waitObject = wait; } HostedHttpRequestAsyncResult result; try { result = new HostedHttpRequestAsyncResult(context, flowContext, ProcessRequestCompleteCallback, wait); if (!result.CompletedSynchronously) { wait.WaitOne(); } wait = null; } finally { if (wait != null) { // Not sure of the state anymore. HostedHttpRequestAsyncResult.waitObject = null; wait.Close(); } } HostedHttpRequestAsyncResult.End(result); } ////// Review - Can be called outside of a user context. /// [SecurityRequiresReview] static void ProcessRequestComplete(IAsyncResult result) { if (!result.CompletedSynchronously) { try { ((AutoResetEvent) result.AsyncState).Set(); } catch (ObjectDisposedException exception) { if (DiagnosticUtility.ShouldTraceWarning) { DiagnosticUtility.ExceptionUtility.TraceHandledException(exception, TraceEventType.Warning); } } } } ////// Critical - Captures HostedImpersonationContext which must be done in the right place, and calls unsafe /// ScheduleCallbackLowPriNoFlow and ScriptTimeout. Called outside of user security context. /// [SecurityCritical] public HostedHttpRequestAsyncResult(HttpApplication context, bool flowContext, AsyncCallback callback, object state) : base(callback, state) { if (context == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("context")); this.context = context; this.flowContext = flowContext; // If this is a DEBUG request, complete right away and let ASP.NET handle it. string method = context.Request.HttpMethod ?? ""; char firstMethodChar = method.Length == 5 ? method[0] : '\0'; if ((firstMethodChar == 'd' || firstMethodChar == 'D') && string.Compare(method, "DEBUG", StringComparison.OrdinalIgnoreCase) == 0) { if (DiagnosticUtility.ShouldTraceVerbose) { TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.WebHostDebugRequest, this); } this.state = State.Completed; Complete(true, null); return; } this.impersonationContext = new HostedImpersonationContext(); if (flowContext) { if (ServiceHostingEnvironment.AspNetCompatibilityEnabled) { // Capture HttpContext/culture context if necessary. Can be used later by HostedHttpInput to re-apply // the culture during dispatch. Also flowed here. hostedThreadData = new HostedThreadData(); } } // Set this up before calling IncrementRequestCount so if it fails, we don't leak a count. WaitCallback iotsCallback = (PartialTrustHelpers.NeedPartialTrustInvoke || flowContext) ? WaitOnBeginRequestWithFlow : WaitOnBeginRequest; // Tell ASPNET to by-pass all the other events so no other http modules will // be invoked, Indigo basically takes over the request completely. This should // only be called in non-AspNetCompatibilityEnabled mode. if (!ServiceHostingEnvironment.AspNetCompatibilityEnabled) { context.CompleteRequest(); } // Prevent ASP.NET from generating thread aborts in relation to this request. context.Server.ScriptTimeout = int.MaxValue; ServiceHostingEnvironment.IncrementRequestCount(); IOThreadScheduler.ScheduleCallbackLowPriNoFlow(iotsCallback, this); } ////// Critical - can be called outside of user context, accesses hostedThreadData. /// Safe - Uses hostedThreadData to set HttpContext.Current, cultures to the one attached to this async-result instance. /// [SecurityCritical, SecurityTreatAsSafe] static void OnBeginRequestWithFlow(object state) { HostedHttpRequestAsyncResult self = (HostedHttpRequestAsyncResult) state; IDisposable hostedThreadContext = null; try { if (self.flowContext) { // In AspCompat case, these are the three things that need to be flowed. See HostedHttpInput. if (self.hostedThreadData != null) hostedThreadContext = self.hostedThreadData.CreateContext(); } // In full-trust, this simply calls the delegate. PartialTrustHelpers.PartialTrustInvoke(ContextOnBeginRequest, self); } finally { if (hostedThreadContext != null) { hostedThreadContext.Dispose(); } } } static void OnBeginRequest(object state) { HostedHttpRequestAsyncResult self = (HostedHttpRequestAsyncResult) state; Exception completionException = null; try { self.BeginRequest(); } catch (Exception e) { if (DiagnosticUtility.IsFatal(e)) { throw; } completionException = e; } if (completionException != null) { self.CompleteOperation(completionException); } } void BeginRequest() { try { HandleRequest(); } catch (EndpointNotFoundException exception) { if (string.Compare(GetHttpMethod(), "GET", StringComparison.OrdinalIgnoreCase) == 0) { // Wrap the exception into HttpException. throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new HttpException((int)HttpStatusCode.NotFound, exception.Message, exception)); } SetStatusCode((int) HttpStatusCode.NotFound); CompleteOperation(null); } catch (ServiceActivationException exception) { if (string.Compare(GetHttpMethod(), "GET", StringComparison.OrdinalIgnoreCase) == 0) { if (exception.InnerException is HttpException) { throw exception.InnerException; } else { throw; } } SetStatusCode((int) HttpStatusCode.InternalServerError); SetStatusDescription( HttpChannelUtilities.StatusDescriptionStrings.HttpStatusServiceActivationException); CompleteOperation(null); } finally { ReleaseImpersonation(); } } public WindowsIdentity LogonUserIdentity { get { if (this.Application.User.Identity is WindowsIdentity) { return (WindowsIdentity)this.Application.User.Identity; } return AnonymousIdentity; } } public HostedImpersonationContext ImpersonationContext { ////// Critical - keeps track of impersonated user, caller must use with care /// Safe - safe for Get, individual members of HostedImpersonationContext are protected /// [SecurityCritical, SecurityTreatAsSafe] get { return impersonationContext; } } public HostedThreadData HostedThreadData { ////// Critical - keeps track of impersonated user, caller must use with care /// Safe - safe for Get, individual members of HostedThreadData are protected /// [SecurityCritical, SecurityTreatAsSafe] get { return hostedThreadData; } } public Uri OriginalRequestUri { get { return this.originalRequestUri; } } public Uri RequestUri { get { return this.requestUri; } } public HttpApplication Application { ////// Critical - touches critical field context /// Safe - does not leak control or data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] get { return this.context; } } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] public Stream GetInputStream() { try { return this.context.Request.InputStream; } catch (HttpException hostedException) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(hostedException.Message, hostedException)); } } public void OnReplySent() { CompleteOperation(null); } void CompleteOperation(Exception exception) { if (this.state == State.Running && Interlocked.CompareExchange(ref this.state, State.Completed, State.Running) == State.Running) { Complete(false, exception); ServiceHostingEnvironment.DecrementRequestCount(); } } public void Abort() { if (this.state == State.Running && Interlocked.CompareExchange(ref this.state, State.Aborted, State.Running) == State.Running) { // Closes the socket connection to the client Application.Response.Close(); Complete(false, null); ServiceHostingEnvironment.DecrementRequestCount(); } } ////// Review - can be called outside of user context. /// [SecurityRequiresReview] public static void End(IAsyncResult result) { if (result == null) throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("result")); try { AsyncResult.End(result); } catch (Exception exception) { if (!(DiagnosticUtility.IsFatal(exception))) { // Log the exception. DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error, EventLogCategory.WebHost, EventLogEventId.WebHostFailedToProcessRequest, DiagnosticTrace.CreateSourceString(result), exception == null ? string.Empty : exception.ToString()); } throw; } } void HandleRequest() { this.originalRequestUri = GetUrl(); string relativeVirtualPath = GetAppRelativeCurrentExecutionFilePath(); // Support for Cassini. if (ServiceHostingEnvironment.IsSimpleApplicationHost) { HostedTransportConfigurationManager.EnsureInitializedForSimpleApplicationHost(this); } HttpHostedTransportConfiguration transportConfiguration = HostedTransportConfigurationManager.GetConfiguration(this.originalRequestUri.Scheme) as HttpHostedTransportConfiguration; HostedHttpTransportManager transportManager = null; // There must be a transport binding that matches the request. if (transportConfiguration != null) { transportManager = transportConfiguration.GetHttpTransportManager(this.originalRequestUri); } if (transportManager == null) { InvalidOperationException invalidOpException = new InvalidOperationException(SR.GetString(SR.Hosting_TransportBindingNotFound, originalRequestUri.ToString())); ServiceActivationException activationException = new ServiceActivationException(invalidOpException.Message, invalidOpException); LogServiceActivationException(activationException); throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(activationException); } this.requestUri = new Uri(transportManager.ListenUri, this.originalRequestUri.PathAndQuery); DiagnosticUtility.DebugAssert( object.ReferenceEquals(requestUri.Scheme, Uri.UriSchemeHttp) || object.ReferenceEquals(requestUri.Scheme, Uri.UriSchemeHttps), "Scheme must be Http or Https."); ServiceHostingEnvironment.EnsureServiceAvailableFast(relativeVirtualPath); transportManager.HttpContextReceived(this); } /// /// Critical - Calls into an unsafe UnsafeLogEvent method /// TreatAsSafe - Event identities cannot be spoofed as they are constants determined inside the method /// [SecurityCritical, SecurityTreatAsSafe] private void LogServiceActivationException(ServiceActivationException activationException) { DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Error, EventLogCategory.WebHost, EventLogEventId.WebHostFailedToProcessRequest, true, DiagnosticTrace.CreateSourceString(this), activationException == null ? string.Empty : activationException.ToString()); } ////// Critical - manipulates impersonation object /// Safe - Releasing the SafeHandle early could only cause a future impersonation attempt to fail. We have to /// handle impersonation failures well already. /// [SecurityCritical, SecurityTreatAsSafe] void ReleaseImpersonation() { if (this.impersonationContext != null) { this.impersonationContext.Release(); } } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void SetContentType(string contentType) { this.context.Response.ContentType = contentType; } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void SetTransferModeToStreaming() { this.context.Response.BufferOutput = false; } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void AppendHeader(string name, string value) { this.context.Response.AppendHeader(name, value); } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void SetStatusCode(int statusCode) { this.context.Response.TrySkipIisCustomErrors = true; this.context.Response.StatusCode = statusCode; } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void SetStatusDescription(string statusDescription) { this.context.Response.StatusDescription = statusDescription; } ////// Critical - calls getters with LinkDemands in ASP .NET objects, changes properties of the HTTP response /// Safe - does not leak control or data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal void SetConnectionClose() { this.context.Response.AppendHeader("Connection", "close"); } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal byte[] GetPrereadBuffer(ref int contentLength) { byte[] preReadBuffer = new byte[1]; if (this.GetInputStream().Read(preReadBuffer, 0, 1) > 0) { contentLength = -1; return preReadBuffer; } return null; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal Stream GetOutputStream() { return this.context.Response.OutputStream; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal string GetHttpMethod() { return this.context.Request.HttpMethod; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal string GetContentType() { const string ContentTypeHeaderName = "Content-Type"; return this.context.Request.Headers[ContentTypeHeaderName]; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal string GetContentTypeFast() { return this.context.Request.ContentType; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal int GetContentLength() { return this.context.Request.ContentLength; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control or mutable/harmful data, no potential for harm /// [SecurityCritical, SecurityTreatAsSafe] internal string GetSoapAction() { const string SoapActionHeaderName = "SOAPAction"; return this.context.Request.Headers[SoapActionHeaderName]; } ////// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control of mutable/harmful data, no potential for harm [SecurityCritical, SecurityTreatAsSafe] string GetAppRelativeCurrentExecutionFilePath() { return this.context.Request.AppRelativeCurrentExecutionFilePath; } /// /// Critical - calls getters with LinkDemands in ASP .NET objects /// Safe - does not leak control of mutable/harmful data, no potential for harm [SecurityCritical, SecurityTreatAsSafe] Uri GetUrl() { return this.context.Request.Url; } } } // 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
- AllMembershipCondition.cs
- XPathExpr.cs
- NamedPipeConnectionPoolSettings.cs
- CodeGroup.cs
- UserUseLicenseDictionaryLoader.cs
- ObjectSet.cs
- Section.cs
- SingleObjectCollection.cs
- URLAttribute.cs
- CodePageUtils.cs
- DataGridViewRowsRemovedEventArgs.cs
- ScriptIgnoreAttribute.cs
- CroppedBitmap.cs
- DATA_BLOB.cs
- ListItem.cs
- Soap12ProtocolImporter.cs
- CreatingCookieEventArgs.cs
- ConvertersCollection.cs
- SaveWorkflowCommand.cs
- _Rfc2616CacheValidators.cs
- AttributeConverter.cs
- FilterableAttribute.cs
- MarkupProperty.cs
- BitmapEffect.cs
- ListViewSelectEventArgs.cs
- ListViewInsertEventArgs.cs
- XmlDataProvider.cs
- BlurEffect.cs
- WebBrowserHelper.cs
- ActiveDocumentEvent.cs
- ServerValidateEventArgs.cs
- FixedSOMElement.cs
- DelimitedListTraceListener.cs
- ParameterCollection.cs
- GotoExpression.cs
- UnknownExceptionActionHelper.cs
- precedingsibling.cs
- InternalConfigRoot.cs
- UInt32Storage.cs
- DataGridLinkButton.cs
- CodeTypeDeclaration.cs
- VirtualPathProvider.cs
- ReachUIElementCollectionSerializer.cs
- SecurityCredentialsManager.cs
- WebControlToolBoxItem.cs
- XhtmlBasicObjectListAdapter.cs
- ScopedKnownTypes.cs
- UserUseLicenseDictionaryLoader.cs
- XmlSchemaElement.cs
- DataTableMappingCollection.cs
- TextTreeRootNode.cs
- ElementAction.cs
- UpdateException.cs
- TabletDevice.cs
- WebPartDisplayModeEventArgs.cs
- ComMethodElementCollection.cs
- TextBoxView.cs
- AttachedAnnotation.cs
- ProgressBarRenderer.cs
- XmlILStorageConverter.cs
- CssStyleCollection.cs
- SqlDataSourceEnumerator.cs
- OleDbConnectionInternal.cs
- DynamicQueryStringParameter.cs
- FactoryId.cs
- ObjectContext.cs
- Menu.cs
- RoutedEventHandlerInfo.cs
- HMAC.cs
- RectIndependentAnimationStorage.cs
- XmlReflectionMember.cs
- XmlIgnoreAttribute.cs
- SerializationException.cs
- SessionParameter.cs
- RegistryKey.cs
- X509CertificateCollection.cs
- CreateUserErrorEventArgs.cs
- CompositeDataBoundControl.cs
- Directory.cs
- StreamGeometry.cs
- OrderedEnumerableRowCollection.cs
- DataControlPagerLinkButton.cs
- RelatedImageListAttribute.cs
- SqlBuffer.cs
- VirtualPathProvider.cs
- CompiledXpathExpr.cs
- Journaling.cs
- DataComponentMethodGenerator.cs
- SafeSecurityHandles.cs
- SynchronizedDispatch.cs
- FontNameConverter.cs
- RawMouseInputReport.cs
- PathFigureCollection.cs
- SqlCacheDependencySection.cs
- BreakRecordTable.cs
- ControlIdConverter.cs
- BindUriHelper.cs
- parserscommon.cs
- SystemWebExtensionsSectionGroup.cs
- SizeAnimationUsingKeyFrames.cs