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
- DispatcherFrame.cs
- ConfigurationLocation.cs
- NativeWindow.cs
- XPathNodeInfoAtom.cs
- ListBoxAutomationPeer.cs
- ActivityWithResultConverter.cs
- ItemType.cs
- Predicate.cs
- RotateTransform.cs
- NavigateUrlConverter.cs
- ChannelManagerBase.cs
- M3DUtil.cs
- CodeAttributeArgumentCollection.cs
- HttpRequestContext.cs
- invalidudtexception.cs
- DataControlFieldCollection.cs
- TextParentUndoUnit.cs
- XmlSchemaAttributeGroupRef.cs
- AsyncOperation.cs
- UnsafeNativeMethods.cs
- StrokeNodeOperations2.cs
- PersonalizationProviderHelper.cs
- WebEventCodes.cs
- DataGridCommandEventArgs.cs
- BinaryOperationBinder.cs
- IntSecurity.cs
- PropertyConverter.cs
- CategoryGridEntry.cs
- DefaultSerializationProviderAttribute.cs
- RootCodeDomSerializer.cs
- EventBuilder.cs
- unsafenativemethodstextservices.cs
- TextRunTypographyProperties.cs
- ListMarkerLine.cs
- CommandManager.cs
- BrushValueSerializer.cs
- PersonalizationProviderCollection.cs
- ContainerTracking.cs
- IDispatchConstantAttribute.cs
- DecimalAnimationBase.cs
- TeredoHelper.cs
- FormattedTextSymbols.cs
- SHA384Managed.cs
- FolderBrowserDialog.cs
- ColumnBinding.cs
- FixedSOMTableRow.cs
- CriticalFinalizerObject.cs
- XXXInfos.cs
- FeatureAttribute.cs
- AnimationTimeline.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- BaseProcessor.cs
- HwndSubclass.cs
- IdleTimeoutMonitor.cs
- XmlWhitespace.cs
- AddingNewEventArgs.cs
- XamlStyleSerializer.cs
- XmlSchemaAttributeGroupRef.cs
- _ProxyChain.cs
- WrappingXamlSchemaContext.cs
- Memoizer.cs
- MenuBase.cs
- InternalCache.cs
- SocketStream.cs
- ProgressBar.cs
- LayoutEditorPart.cs
- unsafenativemethodsother.cs
- DefaultEventAttribute.cs
- NetworkInformationException.cs
- Compensate.cs
- InputMethodStateChangeEventArgs.cs
- RootBrowserWindowProxy.cs
- HttpChannelBindingToken.cs
- DefaultValueConverter.cs
- ColumnMapProcessor.cs
- RequestUriProcessor.cs
- OneToOneMappingSerializer.cs
- _SSPISessionCache.cs
- AssemblyContextControlItem.cs
- PortCache.cs
- RelationalExpressions.cs
- CodePrimitiveExpression.cs
- MappingMetadataHelper.cs
- StyleCollectionEditor.cs
- IDQuery.cs
- GlobalizationAssembly.cs
- DictationGrammar.cs
- Literal.cs
- Activator.cs
- HttpModuleActionCollection.cs
- BindingContext.cs
- MemberExpressionHelper.cs
- arabicshape.cs
- StringAnimationUsingKeyFrames.cs
- InputScopeNameConverter.cs
- DetailsViewModeEventArgs.cs
- DbSetClause.cs
- ExpressionLink.cs
- TitleStyle.cs
- EFAssociationProvider.cs