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
- CodeTypeReferenceExpression.cs
- XPathDescendantIterator.cs
- Vector3D.cs
- MetadataItemCollectionFactory.cs
- OpacityConverter.cs
- BitmapEffectDrawingContextState.cs
- DecimalAnimation.cs
- DesignSurfaceCollection.cs
- AssociationTypeEmitter.cs
- CompilerGeneratedAttribute.cs
- QuaternionValueSerializer.cs
- LabelDesigner.cs
- SafeNativeMethods.cs
- EntityCommandDefinition.cs
- Buffer.cs
- SpecialNameAttribute.cs
- MaterialGroup.cs
- SecurityProtocolCorrelationState.cs
- PipelineDeploymentState.cs
- BindingCompleteEventArgs.cs
- ImageMapEventArgs.cs
- TextStore.cs
- DataSysAttribute.cs
- SoapProtocolReflector.cs
- Model3DGroup.cs
- FocusManager.cs
- InstanceCollisionException.cs
- DataSourceConverter.cs
- TimeZone.cs
- Pair.cs
- SR.cs
- BindingBase.cs
- COM2PropertyPageUITypeConverter.cs
- CompositeControl.cs
- XmlNamespaceManager.cs
- SizeF.cs
- EpmCustomContentDeSerializer.cs
- ImmutableClientRuntime.cs
- CounterCreationDataCollection.cs
- SqlMultiplexer.cs
- BadImageFormatException.cs
- SerializerWriterEventHandlers.cs
- Expander.cs
- OperationAbortedException.cs
- PropertyGridCommands.cs
- CloudCollection.cs
- ServiceHttpHandlerFactory.cs
- DefaultTextStoreTextComposition.cs
- Debug.cs
- RealizedColumnsBlock.cs
- ProxyAttribute.cs
- WindowsIPAddress.cs
- FormsAuthenticationCredentials.cs
- Pen.cs
- WebBrowserDocumentCompletedEventHandler.cs
- HttpPostProtocolImporter.cs
- CompositeFontFamily.cs
- ComplexLine.cs
- GridViewColumnCollectionChangedEventArgs.cs
- EncoderParameter.cs
- AccessDataSourceView.cs
- KoreanCalendar.cs
- GridViewEditEventArgs.cs
- ConstructorNeedsTagAttribute.cs
- BuildManager.cs
- WmlLiteralTextAdapter.cs
- ToolStripScrollButton.cs
- ScriptReference.cs
- OdbcConnectionFactory.cs
- OperatingSystem.cs
- DetailsView.cs
- TargetConverter.cs
- MD5CryptoServiceProvider.cs
- SmtpAuthenticationManager.cs
- FileLogRecordHeader.cs
- TraceListener.cs
- MarkupExtensionReturnTypeAttribute.cs
- WebPartConnectionsCancelEventArgs.cs
- DecimalAnimationBase.cs
- InvalidOleVariantTypeException.cs
- ClientProxyGenerator.cs
- GridViewDeletedEventArgs.cs
- TryExpression.cs
- MetafileHeader.cs
- Attributes.cs
- EventTrigger.cs
- GcSettings.cs
- CodeTypeMember.cs
- CharacterBufferReference.cs
- PackagingUtilities.cs
- EventsTab.cs
- XsltLibrary.cs
- WizardPanel.cs
- MessagePropertyDescriptionCollection.cs
- InvalidCastException.cs
- ADMembershipUser.cs
- KeyboardDevice.cs
- AssertHelper.cs
- ProjectionRewriter.cs
- DeliveryRequirementsAttribute.cs