You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			1027 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1027 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| //------------------------------------------------------------
 | |
| // Copyright (c) Microsoft Corporation.  All rights reserved.
 | |
| //------------------------------------------------------------
 | |
| namespace System.ServiceModel.Activation
 | |
| {
 | |
|     using System.Diagnostics;
 | |
|     using System.Globalization;
 | |
|     using System.IO;
 | |
|     using System.Net;
 | |
|     using System.Runtime;
 | |
|     using System.Runtime.Diagnostics;
 | |
|     using System.Runtime.CompilerServices;
 | |
|     using System.Runtime.InteropServices;
 | |
|     using System.Security;
 | |
|     using System.Security.Authentication.ExtendedProtection;
 | |
|     using System.Security.Cryptography.X509Certificates;
 | |
|     using System.Security.Permissions;
 | |
|     using System.Security.Principal;
 | |
|     using System.ServiceModel;
 | |
|     using System.ServiceModel.Channels;
 | |
|     using System.ServiceModel.Activation.Configuration;
 | |
|     using System.ServiceModel.Activation.Diagnostics;
 | |
|     using System.Threading;
 | |
|     using System.Web;
 | |
|     using System.Web.Management;
 | |
|     using System.Web.Routing;
 | |
|     using TD2 = System.ServiceModel.Diagnostics.Application.TD;
 | |
| 
 | |
|     class HostedHttpRequestAsyncResult : AsyncResult, HttpChannelListener.IHttpAuthenticationContext
 | |
|     {
 | |
|         [Fx.Tag.SecurityNote(Critical = "Stores the securitycritical callback values, we need to protect these values")]
 | |
|         [SecurityCritical]
 | |
|         static WindowsIdentity anonymousIdentity;
 | |
|         [SecurityCritical]
 | |
|         static Action<object> waitOnBeginRequest;
 | |
|         [SecurityCritical]
 | |
|         static Action<object> waitOnBeginRequestWithFlow;
 | |
|         [SecurityCritical]
 | |
|         static ContextCallback contextOnBeginRequest;
 | |
|         [SecurityCritical]
 | |
|         static AsyncCallback processRequestCompleteCallback;
 | |
| 
 | |
| 
 | |
|         [ThreadStatic]
 | |
|         static AutoResetEvent waitObject;
 | |
| 
 | |
|         static Nullable<bool> iisSupportsExtendedProtection;
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Keeps track of impersonated user, caller must use with care")]
 | |
|         [SecurityCritical]
 | |
|         HostedImpersonationContext impersonationContext;
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Keeps track of thread static data (HttpContext, CurrentCulture, CurrentUICulture) that is used for AspNetCompatibility mode, caller must use with care")]
 | |
|         [SecurityCritical]
 | |
|         HostedThreadData hostedThreadData;
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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 non-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;
 | |
| 
 | |
|         int state;
 | |
| 
 | |
|         int streamedReadState;
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Determines whether to set the HttpContext on the outgoing thread.")]
 | |
|         [SecurityCritical]
 | |
|         bool flowContext;
 | |
|         bool ensureWFService;
 | |
|         string configurationBasedServiceVirtualPath;
 | |
|         EventTraceActivity eventTraceActivity;
 | |
| 
 | |
|         readonly bool isWebSocketRequest;
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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, bool ensureWFService, AsyncCallback callback, object state) :
 | |
|             this(context, null, flowContext, ensureWFService, callback, state)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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, string aspNetRouteServiceVirtualPath, bool flowContext, bool ensureWFService, AsyncCallback callback, object state) :
 | |
|             base(callback, state)
 | |
|         {
 | |
|             if (context == null)
 | |
|             {
 | |
|                 throw FxTrace.Exception.ArgumentNull("context");
 | |
|             }
 | |
| 
 | |
|             AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
 | |
| 
 | |
|             HostedAspNetEnvironment.TrySetWebSocketVersion(context);
 | |
|             this.context = context;
 | |
|             // WebSockets require the integrated pipeline mode and the WebSocket IIS module to be loaded. If these conditions 
 | |
|             // are not met, the HttpContext.IsWebSocketRequest property throws. Also, if these conditions are not met,
 | |
|             // we do not let WebSocket listeners to be started (we fail the service activation), so setting the 'isWebSocketRequest' flag 
 | |
|             // to false in this case will not create confusion (or make troubleshooting difficult).
 | |
|             this.isWebSocketRequest = HttpRuntime.UsingIntegratedPipeline && AspNetEnvironment.Current.IsWebSocketModuleLoaded && this.context.Context.IsWebSocketRequest;
 | |
|             this.flowContext = flowContext;
 | |
|             if (ensureWFService)
 | |
|             {
 | |
|                 // check for CBA scenario. if true, service should be handled by WCF instead of WF, 
 | |
|                 // set this.ensureWFservice to false
 | |
|                 if (ServiceHostingEnvironment.IsConfigurationBasedService(context, out this.configurationBasedServiceVirtualPath))
 | |
|                 {
 | |
|                     this.ensureWFService = false;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     this.ensureWFService = true;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (!string.IsNullOrEmpty(aspNetRouteServiceVirtualPath))
 | |
|             {
 | |
|                 // aspnet routing can hijack CBA request as we append {*pathInfo} to urlpattern and there is no real file for CBA 
 | |
|                 // check for CBA scenario. if the request is hijacked. i.e., 
 | |
|                 // 1) route maps to a virtual directory:
 | |
|                 // aspNetRouteServiceVirtualPath <> context.Request.AppRelativeCurrentExecutionFilePath == configurationBasedServiceVirtualPath 
 | |
|                 // if RouteExistingFiles <> true, set aspnetRouteServiceVirtualPath to null so that the request will be treated as CBA
 | |
|                 // if RouteExistingFiles == true, this hijack is by-design, do nothing
 | |
|                 // 2) route maps to a CBA entry:
 | |
|                 // aspNetRouteServiceVirtualPath == context.Request.AppRelativeCurrentExecutionFilePath == configurationBasedServiceVirtualPath
 | |
|                 // we will use RouteExistingFiles to decide which service should be activated. We do it in ServiceHostingEnviroment.HostingManager, 
 | |
|                 // as we cannot pass this info to the latter. 
 | |
|                 if (!RouteTable.Routes.RouteExistingFiles &&
 | |
|                     ServiceHostingEnvironment.IsConfigurationBasedService(context, out this.configurationBasedServiceVirtualPath))
 | |
|                 {
 | |
|                     this.AspNetRouteServiceVirtualPath = null;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     this.AspNetRouteServiceVirtualPath = aspNetRouteServiceVirtualPath;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // 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, SR.TraceCodeWebHostDebugRequest, 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.
 | |
|             Action<object> iotsCallback = (AspNetPartialTrustHelpers.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 && !this.ensureWFService)
 | |
|             {
 | |
|                 context.CompleteRequest();
 | |
|             }
 | |
| 
 | |
|             // Prevent ASP.NET from generating thread aborts in relation to this request.
 | |
|             context.Server.ScriptTimeout = int.MaxValue;
 | |
| 
 | |
|             ServiceHostingEnvironment.IncrementRequestCount(ref this.eventTraceActivity, context.Request.AppRelativeCurrentExecutionFilePath);
 | |
| 
 | |
|             IOThreadScheduler.ScheduleCallbackLowPriNoFlow(iotsCallback, this);
 | |
|         }
 | |
| 
 | |
|         public static WindowsIdentity AnonymousIdentity
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Access the value of corresponding static field and prevent someone from changing its value")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 if (anonymousIdentity == null)
 | |
|                 {
 | |
|                     anonymousIdentity = WindowsIdentity.GetAnonymous();
 | |
|                 }
 | |
|                 return anonymousIdentity;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static Action<object> WaitOnBeginRequest
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Access the value of corresponding static field and prevent someone from changing its value")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 if (waitOnBeginRequest == null)
 | |
|                 {
 | |
|                     waitOnBeginRequest = new Action<object>(OnBeginRequest);
 | |
|                 }
 | |
|                 return waitOnBeginRequest;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static Action<object> WaitOnBeginRequestWithFlow
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Access the value of corresponding static field and prevent someone from changing its value")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 if (waitOnBeginRequestWithFlow == null)
 | |
|                 {
 | |
|                     waitOnBeginRequestWithFlow = new Action<object>(OnBeginRequestWithFlow);
 | |
|                 }
 | |
|                 return waitOnBeginRequestWithFlow;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static ContextCallback ContextOnBeginRequest
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Access the value of corresponding static field and prevent someone from changing its value")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 if (contextOnBeginRequest == null)
 | |
|                 {
 | |
|                     contextOnBeginRequest = new ContextCallback(OnBeginRequest);
 | |
|                 }
 | |
|                 return contextOnBeginRequest;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public static AsyncCallback ProcessRequestCompleteCallback
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Access the value of corresponding static field and prevent someone from changing its value")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 if (processRequestCompleteCallback == null)
 | |
|                 {
 | |
|                     processRequestCompleteCallback = Fx.ThunkCallback(new AsyncCallback(ProcessRequestComplete));
 | |
|                 }
 | |
|                 return processRequestCompleteCallback;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public bool IISSupportsExtendedProtection
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 if (HostedHttpRequestAsyncResult.iisSupportsExtendedProtection == null)
 | |
|                 {
 | |
|                     HostedHttpRequestAsyncResult.iisSupportsExtendedProtection = this.IISSupportsExtendedProtectionInternal();
 | |
|                 }
 | |
|                 return HostedHttpRequestAsyncResult.iisSupportsExtendedProtection.Value;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public bool IsWebSocketRequest
 | |
|         {
 | |
|             get { return this.isWebSocketRequest; }
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Touches critical field context.", Safe = "Does not leak control or data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         [MethodImpl(MethodImplOptions.NoInlining)]
 | |
|         [PermissionSetAttribute(SecurityAction.Assert, Unrestricted = true)]
 | |
|         private bool IISSupportsExtendedProtectionInternal()
 | |
|         {
 | |
|             DiagnosticUtility.DebugAssert(ExtendedProtectionPolicy.OSSupportsExtendedProtection, "OS must support ExtendedProtection");
 | |
| 
 | |
|             try
 | |
|             {
 | |
|                 ChannelBinding cbt = this.context.Request.HttpChannelBinding;
 | |
|                 return true;
 | |
|             }
 | |
|             catch (PlatformNotSupportedException)
 | |
|             {
 | |
|                 // contract with Asp.Net is that they will always throw a PlatformNotSupportedException if IIS is not patched for CBT yet
 | |
|                 return false;
 | |
|             }
 | |
|             catch (COMException)
 | |
|             {
 | |
|                 // If IIS is patched for CBT and an error occurs when trying to retrieve the token a COMException is thrown. Even in this
 | |
|                 // case we know that IIS is patched for CBT.
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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 function must call ServiceHostingEnvironment.EnsureInitialized")]
 | |
|         [SecurityCritical]
 | |
|         public static void ExecuteSynchronous(HttpApplication context, bool flowContext, bool ensureWFService)
 | |
|         {
 | |
|             ExecuteSynchronous(context, null, flowContext, ensureWFService);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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 function must call ServiceHostingEnvironment.EnsureInitialized")]
 | |
|         [SecurityCritical]
 | |
|         public static void ExecuteSynchronous(HttpApplication context, string routeServiceVirtualPath, bool flowContext, bool ensureWFService)
 | |
|         {
 | |
|             AutoResetEvent wait = HostedHttpRequestAsyncResult.waitObject;
 | |
|             if (wait == null)
 | |
|             {
 | |
|                 wait = new AutoResetEvent(false);
 | |
|                 HostedHttpRequestAsyncResult.waitObject = wait;
 | |
|             }
 | |
| 
 | |
|             HostedHttpRequestAsyncResult result;
 | |
|             try
 | |
|             {
 | |
|                 result = new HostedHttpRequestAsyncResult(context, routeServiceVirtualPath, flowContext, ensureWFService, 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);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Can be called outside of a user context.")]
 | |
|         static void ProcessRequestComplete(IAsyncResult result)
 | |
|         {
 | |
|             if (!result.CompletedSynchronously)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     ((AutoResetEvent)result.AsyncState).Set();
 | |
|                 }
 | |
|                 catch (ObjectDisposedException exception)
 | |
|                 {
 | |
|                     DiagnosticUtility.TraceHandledException(exception, TraceEventType.Warning);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         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.
 | |
|                 AspNetPartialTrustHelpers.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 (Fx.IsFatal(e))
 | |
|                 {
 | |
|                     throw;
 | |
|                 }
 | |
| 
 | |
|                 completionException = e;
 | |
|             }
 | |
| 
 | |
|             if (completionException != null)
 | |
|             {
 | |
|                 self.CompleteOperation(completionException);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void BeginRequest()
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 HandleRequest();
 | |
|             }
 | |
|             catch (EndpointNotFoundException exception)
 | |
|             {
 | |
|                 // HTTP-GET is special cased to avoid that the ServiceActivation-HTTP-response is treated as service response.
 | |
|                 // For WebSocket requests we treat the ServiceActivation in the same way like for SOAP (HTTP-POST) requests.
 | |
|                 if (string.Compare(GetHttpMethod(), "GET", StringComparison.OrdinalIgnoreCase) == 0 &&
 | |
|                     !this.isWebSocketRequest)
 | |
|                 {
 | |
|                     // Wrap the exception into HttpException
 | |
|                     throw FxTrace.Exception.AsError(new HttpException((int)HttpStatusCode.NotFound, exception.Message, exception));
 | |
|                 }
 | |
| 
 | |
|                 SetStatusCode((int)HttpStatusCode.NotFound);
 | |
|                 CompleteOperation(null);
 | |
|             }
 | |
|             catch (ServiceActivationException exception)
 | |
|             {
 | |
|                 // HTTP-GET is special cased to avoid that the ServiceActivation-HTTP-response is treated as service response.
 | |
|                 // For WebSocket requests we treat the ServiceActivation in the same way like for SOAP (HTTP-POST) requests.
 | |
|                 if (string.Compare(GetHttpMethod(), "GET", StringComparison.OrdinalIgnoreCase) == 0 &&
 | |
|                     !this.isWebSocketRequest)
 | |
|                 {
 | |
|                     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
 | |
|             {
 | |
|                 IPrincipal user = this.Application.User;
 | |
|                 if (user == null)
 | |
|                 {
 | |
|                     return AnonymousIdentity;
 | |
|                 }
 | |
| 
 | |
|                 WindowsIdentity identity = user.Identity as WindowsIdentity;
 | |
|                 if (identity == null)
 | |
|                 {
 | |
|                     return AnonymousIdentity;
 | |
|                 }
 | |
| 
 | |
|                 return identity;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         WindowsIdentity HttpChannelListener.IHttpAuthenticationContext.LogonUserIdentity
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this.LogonUserIdentity;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public HostedImpersonationContext ImpersonationContext
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Keeps track of impersonated user, caller must use with care.",
 | |
|                 Safe = "Safe for Get, individual members of HostedImpersonationContext are protected.")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 return this.impersonationContext;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public HostedThreadData HostedThreadData
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Keeps track of impersonated user, caller must use with care.",
 | |
|                 Safe = "Safe for Get, individual members of HostedThreadData are protected.")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 return this.hostedThreadData;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public EventTraceActivity EventTraceActivity
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return this.eventTraceActivity;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public Uri OriginalRequestUri
 | |
|         {
 | |
|             get;
 | |
|             private set;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         public Uri RequestUri
 | |
|         {
 | |
|             get;
 | |
|             private set;
 | |
|         }
 | |
| 
 | |
|         public HttpApplication Application
 | |
|         {
 | |
|             [Fx.Tag.SecurityNote(Critical = "Touches critical field context.", Safe = "Does not leak control or data, no potential for harm.")]
 | |
|             [SecuritySafeCritical]
 | |
|             get
 | |
|             {
 | |
|                 return this.context;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public string AspNetRouteServiceVirtualPath
 | |
|         {
 | |
|             get;
 | |
|             private set;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.", Safe = "Does not leak control or data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         public Stream GetInputStream()
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 // CSDMain #133228: "Consume GetBufferlessInputStream"
 | |
|                 // The ReadEntityBodyMode property on the HttpRequest keeps track of whether the request stream has already been accessed, and if so, what API was used to access the request.
 | |
|                 //     - "None" means that the request stream hasn't been accessed.
 | |
|                 //     - "Bufferless" means that GetBufferlessInputStream() was used to access it.
 | |
|                 //     - "Buffered" means GetBufferedInputStream() was used to access it.
 | |
|                 //     - "Classic" means that either the InputStream, Form, Files, or BinaryRead APIs were invoked already.
 | |
|                 // In general, these values are incompatible with one another, meaning that once the request was accessed in a "Classic" way, only "Classic" APIs can be invoked on the HttpRequest.
 | |
|                 // If incompatible APIs are invoked, an HttpException is thrown.
 | |
|                 // In order to prevent HttpExceptions from being thrown for this reason, we will check the ReadEntityBodyMode, and access the request stream with the corresponding API
 | |
|                 // If the request stream hasn't been accessed yet (eg, by an HttpModule which executed earlier), then we will use GetBufferlessInputStream by default.
 | |
|                 ReadEntityBodyMode mode = this.context.Request.ReadEntityBodyMode;
 | |
|                 Fx.Assert(mode == ReadEntityBodyMode.None || mode == ReadEntityBodyMode.Bufferless || mode == ReadEntityBodyMode.Buffered || mode == ReadEntityBodyMode.Classic,
 | |
|                     "Unknown value for System.Web.ReadEntityBodyMode enum");
 | |
| 
 | |
|                 if (mode == ReadEntityBodyMode.None && ServiceHostingEnvironment.AspNetCompatibilityEnabled && AppSettings.UseClassicReadEntityMode)
 | |
|                 {
 | |
|                     mode = ReadEntityBodyMode.Classic;
 | |
|                 }
 | |
| 
 | |
|                 switch (mode)
 | |
|                 {
 | |
|                     case ReadEntityBodyMode.None:
 | |
|                     case ReadEntityBodyMode.Bufferless:
 | |
|                         return this.context.Request.GetBufferlessInputStream(true);  // ignores system.web/httpRuntime/maxRequestLength
 | |
|                     case ReadEntityBodyMode.Buffered:
 | |
|                         return this.context.Request.GetBufferedInputStream();
 | |
|                     default: 
 | |
|                         // ReadEntityBodyMode.Classic:
 | |
|                         return this.context.Request.InputStream;
 | |
|                 }
 | |
|             }
 | |
|             catch (HttpException hostedException)
 | |
|             {
 | |
|                 if (hostedException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge)
 | |
|                 {
 | |
|                     throw FxTrace.Exception.AsError(HttpInput.CreateHttpProtocolException(SR.Hosting_MaxRequestLengthExceeded, HttpStatusCode.RequestEntityTooLarge, null, hostedException));
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     throw FxTrace.Exception.AsError(new CommunicationException(hostedException.Message, hostedException));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void OnReplySent()
 | |
|         {
 | |
|             CompleteOperation(null);
 | |
|         }
 | |
| 
 | |
|         internal void CompleteOperation(Exception exception)
 | |
|         {
 | |
|             if (this.state == State.Running &&
 | |
|                 Interlocked.CompareExchange(ref this.state, State.Completed, State.Running) == State.Running)
 | |
|             {
 | |
|                 this.CompleteAsynchronously(exception);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         public void Abort()
 | |
|         {
 | |
|             if (this.state == State.Running &&
 | |
|                 Interlocked.CompareExchange(ref this.state, State.Aborted, State.Running) == State.Running)
 | |
|             {
 | |
|                 int currentStreamedReadState = Interlocked.Exchange(ref this.streamedReadState, StreamedReadState.AbortStarted);
 | |
|                 // Closes the socket connection to the client
 | |
|                 if (HttpRuntime.UsingIntegratedPipeline)
 | |
|                 {
 | |
|                     Application.Request.Abort();
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Application.Response.Close();
 | |
|                 }
 | |
| 
 | |
|                 if (currentStreamedReadState == StreamedReadState.None)
 | |
|                 {
 | |
|                     this.CompleteAsynchronously(null);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     Fx.Assert(currentStreamedReadState == StreamedReadState.ReceiveStarted, string.Format(CultureInfo.InvariantCulture, "currentStramedReadState is not ReceivedStarted: {0}", currentStreamedReadState));
 | |
|                     if (Interlocked.CompareExchange(ref this.streamedReadState, StreamedReadState.Aborted, StreamedReadState.AbortStarted) == StreamedReadState.AbortStarted)
 | |
|                     {
 | |
|                         return;
 | |
|                     }
 | |
| 
 | |
|                     Fx.Assert(this.streamedReadState == StreamedReadState.ReceiveFinishedAfterAbortStarted, string.Format(CultureInfo.InvariantCulture, "currentStramedReadState is not ReceiveFinished: {0}", this.streamedReadState));
 | |
|                     this.CompleteAsynchronously(null);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void CompleteAsynchronously(Exception ex)
 | |
|         {
 | |
|             Complete(false, ex);
 | |
|             ServiceHostingEnvironment.DecrementRequestCount(this.eventTraceActivity);
 | |
|         }
 | |
| 
 | |
|         internal bool TryStartStreamedRead()
 | |
|         {
 | |
|             return Interlocked.CompareExchange(ref this.streamedReadState, StreamedReadState.ReceiveStarted, StreamedReadState.None) == StreamedReadState.None;
 | |
|         }
 | |
| 
 | |
|         internal void SetStreamedReadFinished()
 | |
|         {
 | |
|             if (Interlocked.CompareExchange(ref this.streamedReadState, StreamedReadState.None, StreamedReadState.ReceiveStarted) == StreamedReadState.ReceiveStarted)
 | |
|             {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if (Interlocked.CompareExchange(ref this.streamedReadState, StreamedReadState.ReceiveFinishedAfterAbortStarted, StreamedReadState.AbortStarted) == StreamedReadState.AbortStarted)
 | |
|             {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             Fx.Assert(this.streamedReadState == StreamedReadState.Aborted, string.Format(CultureInfo.InvariantCulture, "currentStramedReadState is not Aborted: {0}", this.streamedReadState));
 | |
| 
 | |
|             this.CompleteAsynchronously(null);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Can be called outside of a user context.")]
 | |
|         public static void End(IAsyncResult result)
 | |
|         {
 | |
|             try
 | |
|             {
 | |
|                 AsyncResult.End<HostedHttpRequestAsyncResult>(result);
 | |
|             }
 | |
|             catch (Exception exception)
 | |
|             {
 | |
|                 if (!Fx.IsFatal(exception))
 | |
|                 {
 | |
|                     // Log the exception.
 | |
|                     DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error, (ushort)System.Runtime.Diagnostics.EventLogCategory.WebHost, 
 | |
|                         (uint)System.Runtime.Diagnostics.EventLogEventId.WebHostFailedToProcessRequest,
 | |
|                       TraceUtility.CreateSourceString(result),
 | |
|                       exception == null ? string.Empty : exception.ToString());
 | |
|                 }
 | |
|                 throw;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         X509Certificate2 HttpChannelListener.IHttpAuthenticationContext.GetClientCertificate(out bool isValidCertificate)
 | |
|         {
 | |
|             HttpClientCertificate certificateInfo = this.Application.Request.ClientCertificate;
 | |
|             isValidCertificate = certificateInfo.IsValid;
 | |
|             if (certificateInfo.IsPresent)
 | |
|             {
 | |
|                 return new X509Certificate2(certificateInfo.Certificate);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         TraceRecord HttpChannelListener.IHttpAuthenticationContext.CreateTraceRecord()
 | |
|         {
 | |
|             return new System.ServiceModel.Diagnostics.HttpRequestTraceRecord(this.Application.Request);
 | |
|         }
 | |
| 
 | |
|         void HandleRequest()
 | |
|         {
 | |
|             this.OriginalRequestUri = GetUrl();
 | |
|             string relativeVirtualPath;
 | |
|             if (!string.IsNullOrEmpty(this.AspNetRouteServiceVirtualPath))
 | |
|             {
 | |
|                 relativeVirtualPath = this.AspNetRouteServiceVirtualPath;
 | |
|             }
 | |
|             else if (!string.IsNullOrEmpty(this.configurationBasedServiceVirtualPath))
 | |
|             {
 | |
|                 relativeVirtualPath = this.configurationBasedServiceVirtualPath;
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 relativeVirtualPath = GetAppRelativeCurrentExecutionFilePath();
 | |
|             }
 | |
| 
 | |
|             if (ensureWFService)
 | |
|             {
 | |
|                 bool bypass = false;
 | |
|                 try
 | |
|                 {
 | |
|                     if (!ServiceHostingEnvironment.EnsureWorkflowService(relativeVirtualPath))
 | |
|                     {
 | |
|                         CompleteOperation(null);
 | |
|                         bypass = true;
 | |
|                         return;
 | |
|                     }
 | |
|                 }
 | |
|                 finally
 | |
|                 {
 | |
|                     if (!bypass)
 | |
|                     {
 | |
|                         CompleteRequest();
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // 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.Hosting_TransportBindingNotFound(OriginalRequestUri.ToString()));
 | |
| 
 | |
|                 ServiceActivationException activationException = new ServiceActivationException(invalidOpException.Message, invalidOpException);
 | |
| 
 | |
|                 LogServiceActivationException(activationException);
 | |
| 
 | |
|                 throw FxTrace.Exception.AsError(activationException);
 | |
|             }
 | |
| 
 | |
|             this.RequestUri = new Uri(transportManager.ListenUri, this.OriginalRequestUri.PathAndQuery);
 | |
|             Fx.Assert(
 | |
|                 object.ReferenceEquals(this.RequestUri.Scheme, Uri.UriSchemeHttp) || object.ReferenceEquals(this.RequestUri.Scheme, Uri.UriSchemeHttps),
 | |
|                 "Scheme must be Http or Https.");
 | |
| 
 | |
|             ServiceHostingEnvironment.EnsureServiceAvailableFast(relativeVirtualPath, this.eventTraceActivity);
 | |
| 
 | |
|             transportManager.HttpContextReceived(this);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls into an unsafe UnsafeLogEvent method",
 | |
|             Safe = "Event identities cannot be spoofed as they are constants determined inside the method")]
 | |
|         [SecuritySafeCritical]
 | |
|         void LogServiceActivationException(ServiceActivationException activationException)
 | |
|         {
 | |
|             if (TD2.ServiceExceptionIsEnabled())
 | |
|             {
 | |
|                 TD2.ServiceException(this.eventTraceActivity, activationException.ToString(), typeof(ServiceActivationException).FullName);
 | |
|             }
 | |
| 
 | |
|             if (TD.ServiceActivationExceptionIsEnabled())
 | |
|             {
 | |
|                 TD.ServiceActivationException(activationException != null ? activationException.ToString() : string.Empty, activationException);
 | |
|             }
 | |
|             DiagnosticUtility.UnsafeEventLog.UnsafeLogEvent(TraceEventType.Error, (ushort)System.Runtime.Diagnostics.EventLogCategory.WebHost, 
 | |
|                 (uint)System.Runtime.Diagnostics.EventLogEventId.WebHostFailedToProcessRequest, true,
 | |
|                     TraceUtility.CreateSourceString(this), activationException.ToString());
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "manipulates impersonation object",
 | |
|            Safe = "Does not leak control or mutable/harmful data, no potential for harm except memory leak.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void AddRefForImpersonation()
 | |
|         {
 | |
|             if (this.impersonationContext != null)
 | |
|             {
 | |
|                 this.impersonationContext.AddRef();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void ReleaseImpersonation()
 | |
|         {
 | |
|             if (this.impersonationContext != null)
 | |
|             {
 | |
|                 this.impersonationContext.Release();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetContentType(string contentType)
 | |
|         {
 | |
|             this.context.Response.ContentType = contentType;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetContentEncoding(string contentEncoding)
 | |
|         {
 | |
|             this.context.Response.AddHeader(HttpChannelUtilities.ContentEncodingHeader, contentEncoding);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects, completes the request.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void CompleteRequest()
 | |
|         {
 | |
|             this.context.CompleteRequest();
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetTransferModeToStreaming()
 | |
|         {
 | |
|             this.context.Response.BufferOutput = false;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void AppendHeader(string name, string value)
 | |
|         {
 | |
|             this.context.Response.AppendHeader(name, value);
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetStatusCode(int statusCode)
 | |
|         {
 | |
|             this.context.Response.TrySkipIisCustomErrors = true;
 | |
|             this.context.Response.StatusCode = statusCode;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetStatusDescription(string statusDescription)
 | |
|         {
 | |
|             this.context.Response.StatusDescription = statusDescription;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(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.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal void SetConnectionClose()
 | |
|         {
 | |
|             this.context.Response.AppendHeader("Connection", "close");
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         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;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal Stream GetOutputStream()
 | |
|         {
 | |
|             return this.context.Response.OutputStream;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal string GetHttpMethod()
 | |
|         {
 | |
|             return this.context.Request.HttpMethod;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal string GetContentType()
 | |
|         {
 | |
|             const string ContentTypeHeaderName = "Content-Type";
 | |
|             return this.context.Request.Headers[ContentTypeHeaderName];
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal string GetAcceptEncoding()
 | |
|         {
 | |
|             return this.context.Request.Headers[HttpChannelUtilities.AcceptEncodingHeader];
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal string GetContentTypeFast()
 | |
|         {
 | |
|             return this.context.Request.ContentType;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal int GetContentLength()
 | |
|         {
 | |
|             return this.context.Request.ContentLength;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal string GetSoapAction()
 | |
|         {
 | |
|             const string SoapActionHeaderName = "SOAPAction";
 | |
|             return this.context.Request.Headers[SoapActionHeaderName];
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         internal ChannelBinding GetChannelBinding()
 | |
|         {
 | |
|             if (!this.IISSupportsExtendedProtection)
 | |
|             {
 | |
|                 return null;
 | |
|             }
 | |
| 
 | |
|             return this.context.Request.HttpChannelBinding;
 | |
|         }
 | |
| 
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         string GetAppRelativeCurrentExecutionFilePath()
 | |
|         {
 | |
|             return this.context.Request.AppRelativeCurrentExecutionFilePath;
 | |
|         }
 | |
| 
 | |
|         [Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.",
 | |
|             Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
 | |
|         [SecuritySafeCritical]
 | |
|         Uri GetUrl()
 | |
|         {
 | |
|             return this.context.Request.Url;
 | |
|         }
 | |
| 
 | |
|         static class State
 | |
|         {
 | |
|             internal const int Running = 0;
 | |
|             internal const int Completed = 1;
 | |
|             internal const int Aborted = 2;
 | |
|         }
 | |
| 
 | |
|         static class StreamedReadState
 | |
|         {
 | |
|             internal const int None = 0;
 | |
|             internal const int ReceiveStarted = 1;
 | |
|             internal const int ReceiveFinishedAfterAbortStarted = 2;
 | |
|             internal const int AbortStarted = 3;
 | |
|             internal const int Aborted = 4;
 | |
|         }
 | |
|     }
 | |
| }
 |