Imported Upstream version 4.0.0~alpha1

Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
This commit is contained in:
Jo Shields
2015-04-07 09:35:12 +01:00
parent 283343f570
commit 3c1f479b9d
22469 changed files with 2931443 additions and 869343 deletions

View File

@ -0,0 +1,127 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
//This is the behavior is intended to auto apply IIS/AspNet configuration to WCF post design time
class ApplyHostConfigurationBehavior : IServiceBehavior
{
internal ApplyHostConfigurationBehavior()
{
}
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase service)
{
if (service.Description.Endpoints != null && ServiceHostingEnvironment.MultipleSiteBindingsEnabled)
{
FailActivationIfEndpointsHaveAbsoluteAddress(service);
}
}
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase service, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase service)
{
if (ServiceHostingEnvironment.MultipleSiteBindingsEnabled)
{
SetEndpointAddressFilterToIgnorePort(service);
}
}
void SetEndpointAddressFilterToIgnorePort(ServiceHostBase service)
{
for (int i = 0; i < service.ChannelDispatchers.Count; i++)
{
ChannelDispatcher channelDispatcher = service.ChannelDispatchers[i] as ChannelDispatcher;
if (channelDispatcher != null)
{
if (IsSchemeHttpOrHttps(channelDispatcher.Listener.Uri.Scheme))
{
for (int j = 0; j < channelDispatcher.Endpoints.Count; j++)
{
EndpointDispatcher endpointDispatcher = channelDispatcher.Endpoints[j];
EndpointAddressMessageFilter endpointAddressMessageFilter = endpointDispatcher.AddressFilter as EndpointAddressMessageFilter;
if (endpointAddressMessageFilter != null)
{
endpointAddressMessageFilter.ComparePort = false;
}
}
}
}
}
}
void FailActivationIfEndpointsHaveAbsoluteAddress(ServiceHostBase service)
{
foreach (ServiceEndpoint endpoint in service.Description.Endpoints)
{
if (IsSchemeHttpOrHttps(endpoint.Binding.Scheme))
{
if (endpoint.UnresolvedListenUri != null)
{
ThrowIfAbsolute(endpoint.UnresolvedListenUri);
}
else
{
//If the listen URI is not null, we shouldn't care about address. Because there are
//customers who have following config (for load balancer scenarios) - Note ExtraFolder and https
//listen URI - http://localhost/App1/x.svc
//Address - https://externalhost/ExtranFolder/App1/x.svc
ThrowIfAbsolute(endpoint.UnresolvedAddress);
}
}
}
ServiceDebugBehavior debugBehavior = service.Description.Behaviors.Find<ServiceDebugBehavior>();
if (debugBehavior != null)
{
if (debugBehavior.HttpHelpPageEnabled)
{
ThrowIfAbsolute(debugBehavior.HttpHelpPageUrl);
}
if (debugBehavior.HttpsHelpPageEnabled)
{
ThrowIfAbsolute(debugBehavior.HttpsHelpPageUrl);
}
}
ServiceMetadataBehavior metadataBehavior = service.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (metadataBehavior != null)
{
if (metadataBehavior.HttpGetEnabled)
{
ThrowIfAbsolute(metadataBehavior.HttpGetUrl);
}
if (metadataBehavior.HttpsGetEnabled)
{
ThrowIfAbsolute(metadataBehavior.HttpsGetUrl);
}
}
}
static void ThrowIfAbsolute(Uri uri)
{
if (uri != null && uri.IsAbsoluteUri)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_SharedEndpointRequiresRelativeEndpoint(uri.ToString())));
}
}
static bool IsSchemeHttpOrHttps(string scheme)
{
return string.Compare(scheme, Uri.UriSchemeHttp, StringComparison.OrdinalIgnoreCase) == 0 ||
string.Compare(scheme, Uri.UriSchemeHttps, StringComparison.OrdinalIgnoreCase) == 0;
}
}
}

View File

@ -0,0 +1,116 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel
{
using System.Diagnostics.CodeAnalysis;
using System.Runtime;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Web;
using System.Web.Hosting;
static class AspNetPartialTrustHelpers
{
[Fx.Tag.SecurityNote(Critical = "Caches the PermissionSet associated with the asp.net trust level."
+ "This will not change over the life of the AppDomain.")]
[SecurityCritical]
static SecurityContext aspNetSecurityContext;
[Fx.Tag.SecurityNote(Critical = "If erroneously set to true, could bypass the PermitOnly.")]
[SecurityCritical]
static bool isInitialized;
[Fx.Tag.SecurityNote(Critical = "Critical field used to prevent usage of System.Web types in partial trust outside the ASP.NET context.")]
[SecurityCritical]
private static bool isInPartialTrustOutsideAspNet; // indicates if we are running in partial trust outside the ASP.NET context
[Fx.Tag.SecurityNote(Critical = "Critical field used to prevent usage of System.Web types in partial trust outside the ASP.NET context.")]
[SecurityCritical]
private static bool isInPartialTrustOutsideAspNetInitialized = false;
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - determines if the given PermissionSet is full trust."
+ "We will base subsequent security decisions on this.")]
static bool IsFullTrust(PermissionSet perms)
{
return perms == null || perms.IsUnrestricted();
}
internal static bool NeedPartialTrustInvoke
{
[SuppressMessage(FxCop.Category.Security, "CA2107:ReviewDenyAndPermitOnlyUsage")]
[Fx.Tag.SecurityNote(Critical = "Makes a security sensitive decision, updates aspNetSecurityContext and isInitialized.",
Safe = "Ok to know whether the ASP app is partial trust.")]
[SecuritySafeCritical]
get
{
if (!isInitialized)
{
FailIfInPartialTrustOutsideAspNet();
NamedPermissionSet aspNetPermissionSet = GetHttpRuntimeNamedPermissionSet();
if (!IsFullTrust(aspNetPermissionSet))
{
try
{
aspNetPermissionSet.PermitOnly();
aspNetSecurityContext = System.Runtime.PartialTrustHelpers.CaptureSecurityContextNoIdentityFlow();
}
finally
{
CodeAccessPermission.RevertPermitOnly();
}
}
isInitialized = true;
}
return aspNetSecurityContext != null;
}
}
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "Users cannot pass arbitrary data to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts AspNetHostingPermission.")]
[SecurityCritical]
[AspNetHostingPermission(SecurityAction.Assert, Level = AspNetHostingPermissionLevel.Unrestricted)]
static NamedPermissionSet GetHttpRuntimeNamedPermissionSet()
{
return HttpRuntime.GetNamedPermissionSet();
}
[Fx.Tag.SecurityNote(Critical = "Touches aspNetSecurityContext.",
Safe = "Ok to invoke the user's delegate under the PT context.")]
[SecuritySafeCritical]
internal static void PartialTrustInvoke(ContextCallback callback, object state)
{
if (NeedPartialTrustInvoke)
{
SecurityContext.Run(aspNetSecurityContext.CreateCopy(), callback, state);
}
else
{
callback(state);
}
}
/// <summary>
/// Used to guard usage of System.Web types in partial trust outside the ASP.NET context (because they are not secure),
/// in which case we shutdown the process.
/// </summary>
[Fx.Tag.SecurityNote(Critical = "Critical because it uses security critical fields.",
Safe = "Safe because it doesn't take user input and it doesn't leak security sensitive information.")]
[SecuritySafeCritical]
internal static void FailIfInPartialTrustOutsideAspNet()
{
if (!isInPartialTrustOutsideAspNetInitialized)
{
// The HostingEnvironment.IsHosted property is safe to be called in partial trust outside the ASP.NET context.
isInPartialTrustOutsideAspNet = !(PartialTrustHelpers.AppDomainFullyTrusted || HostingEnvironment.IsHosted);
isInPartialTrustOutsideAspNetInitialized = true;
}
if (isInPartialTrustOutsideAspNet)
{
throw FxTrace.Exception.AsError(new SecurityException(Activation.SR.CannotRunInPartialTrustOutsideAspNet));
}
}
}
}

View File

@ -0,0 +1,60 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Runtime;
using System.Security;
using System.ServiceModel;
using System.Web;
using System.Web.SessionState;
class AspNetRouteServiceHttpHandler : IHttpAsyncHandler, IRequiresSessionState
{
string serviceVirtualPath;
public AspNetRouteServiceHttpHandler(string virtualPath)
{
this.serviceVirtualPath = virtualPath;
}
public bool IsReusable
{
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called outside PermitOnly context.")]
get
{
return true;
}
}
[Fx.Tag.SecurityNote(Critical = "Entry-point from asp.net, called outside PermitOnly context. ASP.NET calls are critical." +
"ExecuteSynchronous is critical because it captures HostedImpersonationContext (and makes it available later) " +
"so caller must ensure that this is called in the right place.")]
[SecurityCritical]
public void ProcessRequest(HttpContext context)
{
ServiceHostingEnvironment.SafeEnsureInitialized();
HostedHttpRequestAsyncResult.ExecuteSynchronous(context.ApplicationInstance, this.serviceVirtualPath, true, false);
}
[Fx.Tag.SecurityNote(Critical = "Entry-point from asp.net, called outside PermitOnly context. ASP.NET calls are critical." +
"ExecuteSynchronous is critical because it captures HostedImpersonationContext (and makes it available later) " +
"so caller must ensure that this is called in the right place.")]
[SecurityCritical]
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback callback, object extraData)
{
ServiceHostingEnvironment.SafeEnsureInitialized();
return new HostedHttpRequestAsyncResult(context.ApplicationInstance, this.serviceVirtualPath, true, false, callback, extraData);
}
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - called outside PermitOnly context.")]
public void EndProcessRequest(IAsyncResult result)
{
HostedHttpRequestAsyncResult.End(result);
}
}
}

View File

@ -0,0 +1,383 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Diagnostics;
using System.Runtime;
using System.Diagnostics.CodeAnalysis;
// This class implements an LRU cache that support recycling of oldest items.
//
// The read path is very light-weighted. It takes the reader lock, do a cache lookup, and increment the counter to
// make sure the item is up-to-date.
//
// It exposes the writer lock through an IDisposable object through CreateWriterLockScope(). Whenever a modification
// is required to the cache, we create a scope to perform the work.
//
// It exposes a list of "unsafe" methods for cache modifications. These operations should be invoked only inside a
// WriterLockScope.
//
// Recycling happens in batches. The method UnsafeBeginBatchCollect() finds a batch of items, remove them from the
// cache, and have them closed. The counter is updated whenever Collect happens.
//
// It supports the recycling for the whole cache. In order to avoid blocking the closing, the asynchronous method
// UnsafeBeginCollectAll() is used to initiate the close operations for all of the nodes.
//
// Since the cache favors reads than writes, the items in the cache are not sorted until a Collect operation happens.
// When the Collect operation happens, items are sorted by the LastCounter field of CollectibleNode. Oldest items which
// are collectible (CanClose returns true) are moved into the batch for collection.
//
// Here are some fields of the class that control the recycling logic to achieve best results:
// - collectPercentageInOneBatch: This defines how many items the batch can have for a single Collect operation.
// We need to best leverage the machine capacity but at the same time have an efficient recycling result. This
// number defines the percentage of items in the cache to be collected. The value is hard-coded to be 25%.
// - minSkipCountForWrites: This defines the consecutive writes (service activation, for example) before the next
// Collect operation.
class CollectibleLRUCache<TKey, TValue>
{
// Collect x% of items when a collection happens
readonly double collectPercentageInOneBatch = 0.25;
// After an immediate collection, we skip this number of new writes before performing another collection
readonly int minSkipCountForWrites = 4;
// The look up counter that simulates the timestamp
int counter;
ReaderWriterLockSlim rwLock;
// Records the current counter for write
int writeCounter;
Dictionary<TKey, CollectibleNode> directory;
CollectibleBatch currentCollectibleBatch;
public CollectibleLRUCache(int capacity, IEqualityComparer<TKey> comparer)
{
rwLock = new ReaderWriterLockSlim();
directory = new Dictionary<TKey, CollectibleNode>(capacity, comparer);
currentCollectibleBatch = new CollectibleBatch();
}
public CollectibleNode this[TKey key]
{
get
{
rwLock.EnterReadLock();
try
{
CollectibleNode node = UnsafeGet(key);
if (node != null)
{
// Record the last counter in the node. We don't take a writer lock here because the counter does
// not have to be very accurate.
node.LastCounter = Interlocked.Increment(ref counter);
}
return node;
}
finally
{
rwLock.ExitReadLock();
}
}
}
// This method must be called inside a lock. The counter is not updated
public CollectibleNode UnsafeGet(TKey key)
{
CollectibleNode node;
if (directory.TryGetValue(key, out node))
{
return node;
}
return node;
}
public void Touch(TKey key)
{
rwLock.EnterReadLock();
try
{
CollectibleNode node = UnsafeGet(key);
if (node != null)
{
// Record the last counter in the node. We don't take a writer lock here because the counter does
// not have to be very accurate.
node.LastCounter = Interlocked.Increment(ref counter);
}
}
finally
{
rwLock.ExitReadLock();
}
}
public void UnsafeRemove(CollectibleNode node)
{
if (directory.ContainsKey(node.GetKey()))
{
directory.Remove(node.GetKey());
}
}
// This method must be called inside a writable lock
public void UnsafeAdd(CollectibleNode node)
{
Fx.Assert(rwLock.IsWriteLockHeld, "This method can be called only when the WriterLock is acquired");
writeCounter++;
directory.Add(node.GetKey(), node);
node.LastCounter = Interlocked.Increment(ref counter);
}
// This method must be called inside a writable lock
public bool UnsafeBeginBatchCollect()
{
return UnsafeBeginBatchCollect(false);
}
public bool UnsafeBeginBatchCollect(bool collectingAll)
{
Fx.Assert(rwLock.IsWriteLockHeld, "This method can be called only when the WriterLock is acquired");
if (collectingAll)
{
AbortExistingBatch();
if (this.directory.Count > 0)
{
this.currentCollectibleBatch.AddRange(this.directory.Values);
this.directory.Clear();
}
}
else
{
// We need to avoid collecting items in a consecutive order.
if (minSkipCountForWrites >= writeCounter)
{
return true;
}
CollectibleNode[] array = ResetCountersAndToArray();
Array.Sort<CollectibleNode>(array, CollectibleNode.CounterComparison);
// Collect the items here.
int collectTargetCount = (int)(array.Length * collectPercentageInOneBatch);
for (int i = 0; i < array.Length; i++)
{
if (array[i].CanClose())
{
currentCollectibleBatch.Add(array[i]);
}
if (currentCollectibleBatch.Count >= collectTargetCount)
{
break;
}
}
if (currentCollectibleBatch.Count == 0)
{
return false;
}
for (int i = 0; i < currentCollectibleBatch.Count; i++)
{
directory.Remove(currentCollectibleBatch[i].GetKey());
}
}
currentCollectibleBatch.BeginCollect();
// Wrapping WriterCounter to 0 to avoid integer overflow.
writeCounter = 0;
return true;
}
[SuppressMessage(FxCop.Category.Reliability, FxCop.Rule.AvoidCallingProblematicMethods,
Justification = "Calling GC.Collect to control memory usage more explicitly.")]
public void EndBatchCollect()
{
currentCollectibleBatch.WaitForRecyclingCompletion();
// Force garbage collection
GC.Collect(2, GCCollectionMode.Optimized);
}
public void Abort()
{
using (this.CreateWriterLockScope())
{
AbortExistingBatch();
if (this.directory.Count > 0)
{
this.currentCollectibleBatch.AddRange(this.directory.Values);
this.currentCollectibleBatch.Abort();
}
}
}
void AbortExistingBatch()
{
if (this.currentCollectibleBatch.Count > 0)
{
this.currentCollectibleBatch.Abort();
}
}
public int Count
{
get
{
return this.directory.Count;
}
}
public IDisposable CreateWriterLockScope()
{
return new WriterLockScope(this.rwLock);
}
CollectibleNode[] ResetCountersAndToArray()
{
CollectibleNode[] array = directory.Values.ToArray();
// Reset the counters so that the integer counters are not wrapped (overflow from positive to negative)
for (int i = 0; i < array.Length; i++)
{
array[i].LastCounter -= this.counter;
}
this.counter = 0;
return array;
}
internal abstract class CollectibleNode
{
public static Comparison<CollectibleNode> CounterComparison = new Comparison<CollectibleNode>(CounterLessThan);
public int LastCounter;
public abstract TKey GetKey();
public abstract IAsyncResult BeginClose(AsyncCallback callback, object state);
public abstract void EndClose(IAsyncResult result);
public abstract void Abort();
public abstract bool CanClose();
public TValue Value { get; set; }
public static int CounterLessThan(CollectibleNode x, CollectibleNode y)
{
return x.LastCounter - y.LastCounter;
}
}
class WriterLockScope : IDisposable
{
ReaderWriterLockSlim rwLock;
public WriterLockScope(ReaderWriterLockSlim rwLock)
{
this.rwLock = rwLock;
rwLock.EnterWriteLock();
}
public void Dispose()
{
rwLock.ExitWriteLock();
}
}
class CollectibleBatch : List<CollectibleNode>
{
ManualResetEvent recyclingCompletedWaitHandle;
AsyncCallback collectibleNodeClosedCallback;
int totalCollectCount;
public CollectibleBatch()
{
// The event is initially set when the batch is empty.
recyclingCompletedWaitHandle = new ManualResetEvent(true);
collectibleNodeClosedCallback = Fx.ThunkCallback(new AsyncCallback(OnCollectibleNodeClosed));
}
public void BeginCollect()
{
this.totalCollectCount = this.Count;
if (this.totalCollectCount == 0)
{
return;
}
recyclingCompletedWaitHandle.Reset();
for (int i = 0; i < this.Count; i++)
{
IAsyncResult result = this[i].BeginClose(collectibleNodeClosedCallback, this[i]);
if (result == null)
{
DecrementCollectCount();
}
else if (result.CompletedSynchronously)
{
HandleCollectibleNodeClosed(result);
}
}
}
public void WaitForRecyclingCompletion()
{
recyclingCompletedWaitHandle.WaitOne();
this.Clear();
}
public void Abort()
{
for (int i = 0; i < this.Count; i++)
{
this[i].Abort();
}
this.Clear();
recyclingCompletedWaitHandle.Set();
}
void DecrementCollectCount()
{
int currentCount = Interlocked.Decrement(ref this.totalCollectCount);
if (currentCount == 0)
{
this.recyclingCompletedWaitHandle.Set();
}
}
void OnCollectibleNodeClosed(IAsyncResult result)
{
if (result == null || result.CompletedSynchronously)
{
return;
}
HandleCollectibleNodeClosed(result);
}
void HandleCollectibleNodeClosed(IAsyncResult result)
{
CollectibleNode node = result.AsyncState as CollectibleNode;
if (node != null)
{
node.EndClose(result);
}
DecrementCollectCount();
}
}
}
}

View File

@ -0,0 +1,61 @@
// <copyright>
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
namespace System.ServiceModel.Activation.Configuration
{
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics.CodeAnalysis;
using System.Runtime;
internal static class AppSettings
{
private const string UseClassicReadEntityBodyModeString = "wcf:serviceHostingEnvironment:useClassicReadEntityBodyMode";
private static bool useClassicReadEntityBodyMode = false;
private static volatile bool settingsInitalized = false;
private static object appSettingsLock = new object();
internal static bool UseClassicReadEntityMode
{
get
{
EnsureSettingsLoaded();
return useClassicReadEntityBodyMode;
}
}
[SuppressMessage(FxCop.Category.ReliabilityBasic, "Reliability104:CaughtAndHandledExceptionsRule",
Justification = "Handle the configuration exceptions here to avoid regressions on customer's existing scenarios")]
private static void EnsureSettingsLoaded()
{
if (!settingsInitalized)
{
lock (appSettingsLock)
{
if (!settingsInitalized)
{
NameValueCollection appSettingsSection = null;
try
{
appSettingsSection = ConfigurationManager.AppSettings;
}
catch (ConfigurationErrorsException)
{
}
finally
{
if ((appSettingsSection == null) || !bool.TryParse(appSettingsSection[UseClassicReadEntityBodyModeString], out useClassicReadEntityBodyMode))
{
useClassicReadEntityBodyMode = false;
}
settingsInitalized = true;
}
}
}
}
}
}
}

View File

@ -0,0 +1,24 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation.Diagnostics
{
using System;
using System.Diagnostics;
using System.Runtime.Diagnostics;
using System.Collections.Generic;
static class TraceCode
{
// WebHost trace codes
public const int Activation = 0X90000;
public const int WebHostFailedToCompile = TraceCode.Activation | 0X0001;
public const int WebHostServiceActivated = TraceCode.Activation | 0X0002;
public const int WebHostFailedToActivateService = TraceCode.Activation | 0X0003;
public const int WebHostCompilation = TraceCode.Activation | 0X0004;
public const int WebHostDebugRequest = TraceCode.Activation | 0X0005;
public const int WebHostProtocolMisconfigured = TraceCode.Activation | 0X0006;
public const int WebHostServiceCloseFailed = TraceCode.Activation | 0X0007;
public const int WebHostNoCBTSupport = TraceCode.Activation | 0X0008;
}
}

View File

@ -0,0 +1,51 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation.Diagnostics
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
using System.Runtime.Diagnostics;
static class TraceUtility
{
static Dictionary<int, string> traceCodes = new Dictionary<int, string>(7)
{
{ TraceCode.WebHostFailedToCompile, "WebHostFailedToCompile" },
{ TraceCode.WebHostServiceActivated, "WebHostServiceActivated" },
{ TraceCode.WebHostFailedToActivateService, "WebHostFailedToActivateService" },
{ TraceCode.WebHostCompilation, "WebHostCompilation" },
{ TraceCode.WebHostDebugRequest, "WebHostDebugRequest" },
{ TraceCode.WebHostProtocolMisconfigured, "WebHostProtocolMisconfigured" },
{ TraceCode.WebHostServiceCloseFailed, "WebHostServiceCloseFailed" },
{ TraceCode.WebHostNoCBTSupport, "WebHostNoCBTSupport" },
};
internal static void TraceEvent(TraceEventType severity, int traceCode, string traceDescription, object source)
{
TraceEvent(severity, traceCode, traceDescription, null, source, null);
}
internal static void TraceEvent(TraceEventType severity, int traceCode, string traceDescription, object source, Exception exception)
{
TraceEvent(severity, traceCode, traceDescription, null, source, exception);
}
internal static void TraceEvent(TraceEventType severity, int traceCode, string traceDescription, TraceRecord record, object source, Exception exception)
{
Fx.Assert(traceCodes.ContainsKey(traceCode),
string.Format(CultureInfo.InvariantCulture, "Unsupported trace code: Please add trace code 0x{0} to the dictionary TraceUtility.traceCodes in {1}",
traceCode.ToString("X", CultureInfo.InvariantCulture), typeof(TraceUtility)));
string msdnTraceCode = System.ServiceModel.Diagnostics.LegacyDiagnosticTrace.GenerateMsdnTraceCode("System.ServiceModel.Activation", traceCodes[traceCode]);
DiagnosticUtility.DiagnosticTrace.TraceEvent(severity, traceCode, msdnTraceCode, traceDescription, record, exception, source);
}
internal static string CreateSourceString(object source)
{
return source.GetType().ToString() + "/" + source.GetHashCode().ToString(CultureInfo.CurrentCulture);
}
}
}

View File

@ -0,0 +1,44 @@
//-----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.ServiceModel.Channels;
class HostedBindingBehavior : IServiceBehavior
{
VirtualPathExtension virtualPathExtension;
internal HostedBindingBehavior(VirtualPathExtension virtualPathExtension)
{
this.virtualPathExtension = virtualPathExtension;
}
public VirtualPathExtension VirtualPathExtension
{
get { return this.virtualPathExtension; }
}
void IServiceBehavior.Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
void IServiceBehavior.AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
if (parameters == null)
{
throw FxTrace.Exception.ArgumentNull("parameters");
}
parameters.Add(this.virtualPathExtension);
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
}
}

View File

@ -0,0 +1,282 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
using System.Runtime.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
using System.ServiceModel.Dispatcher;
using System.Threading;
using System.Web;
class HostedHttpTransportManager : HttpTransportManager
{
string scheme;
int port;
string host;
static AsyncCallback onHttpContextReceived = Fx.ThunkCallback(OnHttpContextReceived);
internal HostedHttpTransportManager(BaseUriWithWildcard baseAddress) :
base(baseAddress.BaseAddress, baseAddress.HostNameComparisonMode)
{
base.IsHosted = true;
}
internal override bool IsCompatible(HttpChannelListener factory)
{
return true;
}
internal override void OnClose(TimeSpan timeout)
{
// empty
}
internal override void OnOpen()
{
// empty
}
internal override void OnAbort()
{
// empty
}
internal override string Scheme
{
get
{
return this.scheme ?? (this.scheme = this.ListenUri.Scheme);
}
}
internal string Host
{
get
{
return this.host ?? (this.host = this.ListenUri.Host);
}
}
internal int Port
{
get
{
return this.port == 0 ? (this.port = this.ListenUri.Port) : this.port;
}
}
static bool canTraceConnectionInformation = true;
public void TraceConnectionInformation(HostedHttpRequestAsyncResult result)
{
if (result != null && DiagnosticUtility.ShouldTraceInformation && canTraceConnectionInformation)
{
try
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
IServiceProvider provider = (IServiceProvider)result.Application.Context;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
string localAddress = string.Format(CultureInfo.InvariantCulture,
"{0}:{1}", workerRequest.GetLocalAddress(), workerRequest.GetLocalPort());
string remoteAddress = string.Format(CultureInfo.InvariantCulture,
"{0}:{1}", workerRequest.GetRemoteAddress(), workerRequest.GetRemotePort());
TraceUtility.TraceHttpConnectionInformation(localAddress, remoteAddress, this);
}
catch (SecurityException e)
{
canTraceConnectionInformation = false;
// not re-throwing on purpose
DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
}
}
}
[Fx.Tag.SecurityNote(Critical = "Calls getters with LinkDemands in ASP .NET objects.", Safe = "Only returns the activity, doesn't leak the ASP .NET objects.")]
[SecuritySafeCritical]
public ServiceModelActivity CreateReceiveBytesActivity(HostedHttpRequestAsyncResult result)
{
ServiceModelActivity retval = null;
if (result != null)
{
TraceMessageReceived(result.EventTraceActivity, result.RequestUri);
if (DiagnosticUtility.ShouldUseActivity)
{
IServiceProvider provider = (IServiceProvider)result.Application.Context;
retval = ServiceModelActivity.CreateBoundedActivity(GetRequestTraceIdentifier(provider));
StartReceiveBytesActivity(retval, result.RequestUri);
}
}
return retval;
}
[Fx.Tag.SecurityNote(Critical = "Uses the HttpWorkerRequest to get the trace identifier, which Demands UnamangedCode.", Safe = "Only returns the trace id, doesn't leak the HttpWorkerRequest.")]
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Assert, UnmanagedCode = true)]
static Guid GetRequestTraceIdentifier(IServiceProvider provider)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return ((HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest))).RequestTraceIdentifier;
}
internal void HttpContextReceived(HostedHttpRequestAsyncResult result)
{
using (DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.BoundOperation(this.Activity) : null)
{
using (ServiceModelActivity activity = this.CreateReceiveBytesActivity(result))
{
this.TraceConnectionInformation(result);
HttpChannelListener listener;
if (base.TryLookupUri(result.RequestUri, result.GetHttpMethod(),
this.HostNameComparisonMode, result.IsWebSocketRequest, out listener))
{
HostedHttpContext hostedContext = new HostedHttpContext(listener, result);
object state = DiagnosticUtility.ShouldUseActivity ? (object)new ActivityHolder(activity, hostedContext) : (object)hostedContext;
IAsyncResult httpContextReceivedResult = listener.BeginHttpContextReceived(hostedContext,
null,
onHttpContextReceived,
state);
if (httpContextReceivedResult.CompletedSynchronously)
{
EndHttpContextReceived(httpContextReceivedResult);
}
return;
}
if (DiagnosticUtility.ShouldTraceError)
{
TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.HttpChannelMessageReceiveFailed, SR.TraceCodeHttpChannelMessageReceiveFailed,
new StringTraceRecord("IsRecycling", ServiceHostingEnvironment.IsRecycling.ToString(CultureInfo.CurrentCulture)),
this, null);
}
if (ServiceHostingEnvironment.IsRecycling)
{
throw FxTrace.Exception.AsError(
new EndpointNotFoundException(SR.Hosting_ListenerNotFoundForActivationInRecycling(result.RequestUri.ToString())));
}
else
{
throw FxTrace.Exception.AsError(
new EndpointNotFoundException(SR.Hosting_ListenerNotFoundForActivation(result.RequestUri.ToString())));
}
}
}
}
static void EndHttpContextReceived(IAsyncResult httpContextReceivedResult)
{
using (DiagnosticUtility.ShouldUseActivity ? (ActivityHolder)httpContextReceivedResult.AsyncState : null)
{
HttpChannelListener channelListener =
(DiagnosticUtility.ShouldUseActivity ?
((ActivityHolder)httpContextReceivedResult.AsyncState).context :
(HttpRequestContext)httpContextReceivedResult.AsyncState).Listener;
channelListener.EndHttpContextReceived(httpContextReceivedResult);
}
}
static void OnHttpContextReceived(IAsyncResult httpContextReceivedResult)
{
if (httpContextReceivedResult.CompletedSynchronously)
{
return;
}
Exception completionException = null;
try
{
EndHttpContextReceived(httpContextReceivedResult);
}
catch (Exception exception)
{
if (Fx.IsFatal(exception))
{
throw;
}
completionException = exception;
}
if (completionException != null)
{
HostedHttpContext context =
(HostedHttpContext)(DiagnosticUtility.ShouldUseActivity ?
((ActivityHolder)httpContextReceivedResult.AsyncState).context :
httpContextReceivedResult.AsyncState);
context.CompleteWithException(completionException);
}
}
}
[Fx.Tag.SecurityNote(Critical = "Captures HttpContext.Current on construction, then can apply that state at a later time and reset on Dispose."
+ "Whole object is critical because where it was initially constructed can be used to control HttpContext.set_Current later and HttpContext.set_Current requires an elevation")]
#pragma warning disable 618 // have not moved to the v4 security model yet
[SecurityCritical(SecurityCriticalScope.Everything)]
#pragma warning restore 618
class HostedThreadData
{
CultureInfo cultureInfo;
CultureInfo uiCultureInfo;
HttpContext httpContext;
public HostedThreadData()
{
this.cultureInfo = CultureInfo.CurrentCulture;
this.uiCultureInfo = CultureInfo.CurrentUICulture;
this.httpContext = HttpContext.Current;
}
public IDisposable CreateContext()
{
return new HostedAspNetContext(this);
}
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
static void UnsafeApplyData(HostedThreadData data)
{
// We set the CallContext.HostContext directly instead of setting HttpContext.Current because
// the latter uses a demand instead of a link demand, which is very expensive in partial trust.
System.Runtime.Remoting.Messaging.CallContext.HostContext = data.httpContext;
Thread currentThread = Thread.CurrentThread;
if (currentThread.CurrentCulture != data.cultureInfo)
{
currentThread.CurrentCulture = data.cultureInfo;
}
if (currentThread.CurrentUICulture != data.uiCultureInfo)
{
currentThread.CurrentUICulture = data.uiCultureInfo;
}
}
class HostedAspNetContext : IDisposable
{
HostedThreadData oldData;
public HostedAspNetContext(HostedThreadData newData)
{
oldData = new HostedThreadData();
HostedThreadData.UnsafeApplyData(newData);
}
public void Dispose()
{
HostedThreadData.UnsafeApplyData(oldData);
}
}
}
}

View File

@ -0,0 +1,162 @@
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.ComponentModel;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.ServiceModel.Activation.Interop;
using System.Threading;
[Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - All member methods are security critical. The class might be used outside of the restricted SecurityContext." +
"Ensure they do not accidentally satisfy any demands.")]
class HostedImpersonationContext
{
[Fx.Tag.SecurityNote(Critical = "Stores the impersonation token handle. Since we're allowing 'safe' Impersonation of the token we got from asp.net we need to protect this value.")]
[SecurityCritical]
SafeCloseHandleCritical tokenHandle;
[Fx.Tag.SecurityNote(Critical = "Controls lifetime of token handle, caller must use care.")]
[SecurityCritical]
int refCount = 0;
[Fx.Tag.SecurityNote(Critical = "Security critical field, caller must use care.")]
[SecurityCritical]
bool isImpersonated;
[Fx.Tag.SecurityNote(Critical = "Calls two safe native methods under OpenCurrentThreadTokenCritical: GetCurrentThread and OpenThreadToken." +
"Marshal.GetLastWin32Error captures current thread token in a SecurityCritical field.")]
[SecurityCritical]
public HostedImpersonationContext()
{
if (ServiceHostingEnvironment.AspNetCompatibilityEnabled)
{
int error;
bool isSuccess = SafeNativeMethods.OpenCurrentThreadTokenCritical(TokenAccessLevels.Query | TokenAccessLevels.Impersonate,
true, out tokenHandle, out error);
if (isSuccess)
{
isImpersonated = true;
Interlocked.Increment(ref refCount);
}
else
{
CloseInvalidOutSafeHandleCritical(tokenHandle);
tokenHandle = null;
if (error != SafeNativeMethods.ERROR_NO_TOKEN)
{
throw FxTrace.Exception.AsError(new Win32Exception(error, SR.Hosting_ImpersonationFailed));
}
}
}
}
[Fx.Tag.SecurityNote(Critical = "Calls SetHandleAsInvalid which has a LinkDemand for UnmanagedCode.")]
[SecurityCritical]
static void CloseInvalidOutSafeHandleCritical(SafeHandle handle)
{
// Workaround for 64-bit CLR bug VSWhidbey 546830 - sometimes invalid SafeHandles come back null.
if (handle != null)
{
Fx.Assert(handle.IsInvalid, "CloseInvalidOutSafeHandle called with a valid handle!");
// Calls SuppressFinalize.
handle.SetHandleAsInvalid();
}
}
public bool IsImpersonated
{
[Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical isImpersonated field.", Safe = "Does not leak control or mutable/harmful data, no potential for harm.")]
[SecuritySafeCritical]
get
{
return isImpersonated;
}
}
[Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical tokenHandle field and uses LinkDemanded DangerousGetHandle method as well as UnsafeCreate." +
"Caller should use with care, must take responsibility for reverting impersonation.")]
[SecurityCritical]
public IDisposable Impersonate()
{
if (!isImpersonated)
return null;
Fx.Assert(tokenHandle != null, "The token handle was incorrectly released earlier.");
HostedInnerImpersonationContext context = null;
lock (tokenHandle)
{
context = HostedInnerImpersonationContext.UnsafeCreate(tokenHandle.DangerousGetHandle());
GC.KeepAlive(tokenHandle);
}
return context;
}
[Fx.Tag.SecurityNote(Critical = "Controls lifetime of token handle, caller must use care.")]
[SecurityCritical]
public void AddRef()
{
if (IsImpersonated)
{
Interlocked.Increment(ref refCount);
}
}
[Fx.Tag.SecurityNote(Critical = "Controls lifetime of token handle, caller must use care.")]
[SecurityCritical]
public void Release()
{
if (IsImpersonated)
{
Fx.Assert(tokenHandle != null, "The token handle is incorrectly released earlier.");
int currentCount = Interlocked.Decrement(ref refCount);
if (currentCount == 0)
{
lock (tokenHandle)
{
tokenHandle.Close();
tokenHandle = null;
}
}
}
}
[Fx.Tag.SecurityNote(Critical = "Keeps track of impersonated user, caller must use with care and call Dispose at the appropriate time.")]
#pragma warning disable 618 // have not moved to the v4 security model yet
[SecurityCritical(SecurityCriticalScope.Everything)]
#pragma warning restore 618
class HostedInnerImpersonationContext : IDisposable
{
IDisposable impersonatedContext;
HostedInnerImpersonationContext(IDisposable impersonatedContext)
{
if (impersonatedContext == null)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ImpersonationFailed));
}
this.impersonatedContext = impersonatedContext;
}
public static HostedInnerImpersonationContext UnsafeCreate(IntPtr token)
{
return new HostedInnerImpersonationContext(HostingEnvironmentWrapper.UnsafeImpersonate(token));
}
public void Dispose()
{
if (impersonatedContext != null)
{
impersonatedContext.Dispose();
impersonatedContext = null;
}
}
}
}
}

View File

@ -0,0 +1,182 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Diagnostics;
class HostedNamedPipeTransportManager : NamedPipeTransportManager
{
// Double-checked locking pattern requires volatile for read/write synchronization
volatile bool settingsApplied;
Action<Uri> onViaCallback;
SharedConnectionListener listener;
ConnectionDemuxer connectionDemuxer;
int queueId;
Guid token;
Func<Uri, int> onDuplicatedViaCallback;
// Double-checked locking pattern requires volatile for read/write synchronization
volatile bool demuxerCreated;
public HostedNamedPipeTransportManager(BaseUriWithWildcard baseAddress)
: base(baseAddress.BaseAddress)
{
this.HostNameComparisonMode = baseAddress.HostNameComparisonMode;
this.onViaCallback = new Action<Uri>(OnVia);
this.onDuplicatedViaCallback = new Func<Uri, int>(OnDuplicatedVia);
}
protected override bool IsCompatible(NamedPipeChannelListener channelListener)
{
if (channelListener.HostedVirtualPath == null)
{
return false;
}
return base.IsCompatible(channelListener);
}
internal void Start(int queueId, Guid token, Action messageReceivedCallback)
{
SetMessageReceivedCallback(messageReceivedCallback);
OnOpenInternal(queueId, token);
}
internal override void OnOpen()
{
// This is intentionally empty.
}
internal override void OnAbort()
{
}
internal void Stop(TimeSpan timeout)
{
Cleanup(false, timeout);
}
void Cleanup(bool aborting, TimeSpan timeout)
{
lock (ThisLock)
{
if (listener != null)
{
if (!aborting)
{
listener.Stop(timeout);
}
else
{
listener.Abort();
}
// The listener will be closed by the demuxer.
listener = null;
}
if (connectionDemuxer != null)
{
connectionDemuxer.Dispose();
}
demuxerCreated = false;
settingsApplied = false;
}
}
void CreateConnectionDemuxer()
{
IConnectionListener connectionListener = new BufferedConnectionListener(listener, MaxOutputDelay, ConnectionBufferSize);
if (DiagnosticUtility.ShouldUseActivity)
{
connectionListener = new TracingConnectionListener(connectionListener, this.ListenUri);
}
connectionDemuxer = new ConnectionDemuxer(connectionListener,
MaxPendingAccepts, MaxPendingConnections, ChannelInitializationTimeout,
IdleTimeout, MaxPooledConnections,
OnGetTransportFactorySettings,
OnGetSingletonMessageHandler,
OnHandleServerSessionPreamble,
OnDemuxerError);
connectionDemuxer.StartDemuxing(onViaCallback);
}
void OnOpenInternal(int queueId, Guid token)
{
lock (ThisLock)
{
this.queueId = queueId;
this.token = token;
BaseUriWithWildcard path = new BaseUriWithWildcard(this.ListenUri, this.HostNameComparisonMode);
listener = new SharedConnectionListener(path, queueId, token, this.onDuplicatedViaCallback);
}
}
internal override void OnClose(TimeSpan timeout)
{
}
void OnVia(Uri address)
{
Debug.Print("HostedNamedPipeTransportManager.OnVia() address: " + address + " calling EnsureServiceAvailable()");
ServiceHostingEnvironment.EnsureServiceAvailable(address.LocalPath);
}
protected override void OnSelecting(NamedPipeChannelListener channelListener)
{
if (settingsApplied)
{
return;
}
lock (ThisLock)
{
if (settingsApplied)
{
// Use the setting for the first one.
return;
}
this.ApplyListenerSettings(channelListener);
settingsApplied = true;
}
}
// This method is called only for the first via of the current proxy.
int OnDuplicatedVia(Uri via)
{
OnVia(via);
if (!demuxerCreated)
{
lock (ThisLock)
{
if (listener == null)
{
// The listener has been stopped.
throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.PipeListenerProxyStopped));
}
if (!demuxerCreated)
{
CreateConnectionDemuxer();
demuxerCreated = true;
}
}
}
return this.ConnectionBufferSize;
}
}
}

View File

@ -0,0 +1,82 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.ServiceModel.Channels;
using System.Collections.Generic;
using System.Diagnostics;
class HostedTcpTransportManager : SharedTcpTransportManager
{
// Double-checked locking pattern requires volatile for read/write synchronization
volatile bool settingsApplied;
Action<Uri> onViaCallback;
public HostedTcpTransportManager(BaseUriWithWildcard baseAddress)
: base(baseAddress.BaseAddress)
{
this.HostNameComparisonMode = baseAddress.HostNameComparisonMode;
this.onViaCallback = new Action<Uri>(OnVia);
}
internal void Start(int queueId, Guid token, Action messageReceivedCallback)
{
SetMessageReceivedCallback(messageReceivedCallback);
OnOpenInternal(queueId, token);
}
internal override void OnOpen()
{
// This is intentionally empty.
}
internal override void OnClose(TimeSpan timeout)
{
// This is intentionally empty.
}
internal override void OnAbort()
{
// This is intentionally empty.
}
internal void Stop(TimeSpan timeout)
{
CleanUp(false, timeout);
settingsApplied = false;
}
protected override Action<Uri> GetOnViaCallback()
{
return this.onViaCallback;
}
void OnVia(Uri address)
{
Debug.Print("HostedTcpTransportManager.OnVia() address: " + address + " calling EnsureServiceAvailable()");
ServiceHostingEnvironment.EnsureServiceAvailable(address.LocalPath);
}
protected override void OnSelecting(TcpChannelListener channelListener)
{
if (settingsApplied)
{
return;
}
lock (ThisLock)
{
if (settingsApplied)
{
// Use the first one.
return;
}
this.ApplyListenerSettings(channelListener);
settingsApplied = true;
}
}
}
}

View File

@ -0,0 +1,14 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Runtime.CompilerServices;
[TypeForwardedFrom("System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class HostedTransportConfiguration
{
public abstract Uri[] GetBaseAddresses(string virtualPath);
}
}

View File

@ -0,0 +1,89 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Globalization;
using System.Web.Hosting;
using System.Web;
namespace System.ServiceModel.Activation
{
abstract class HostedTransportConfigurationBase : HostedTransportConfiguration
{
List<BaseUriWithWildcard> listenAddresses;
string scheme;
internal protected HostedTransportConfigurationBase(string scheme)
{
this.scheme = scheme;
this.listenAddresses = new List<BaseUriWithWildcard>();
}
internal string Scheme
{
get
{
return scheme;
}
}
internal protected IList<BaseUriWithWildcard> ListenAddresses
{
get
{
return listenAddresses;
}
}
public override Uri[] GetBaseAddresses(string virtualPath)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
Uri[] addresses = new Uri[listenAddresses.Count];
for (int i = 0; i < listenAddresses.Count; i++)
{
string absoluteVirtualPath = VirtualPathUtility.ToAbsolute(virtualPath, HostingEnvironmentWrapper.ApplicationVirtualPath);
addresses[i] = new Uri(listenAddresses[i].BaseAddress, absoluteVirtualPath);
}
return addresses;
}
internal BaseUriWithWildcard FindBaseAddress(Uri uri)
{
BaseUriWithWildcard foundBaseAddress = null;
BaseUriWithWildcard weakBaseAddress = null;
for (int i = 0; i < listenAddresses.Count; i++)
{
if ((string.Compare(listenAddresses[i].BaseAddress.Scheme, uri.Scheme, StringComparison.OrdinalIgnoreCase) == 0)
&& (listenAddresses[i].BaseAddress.Port == uri.Port))
{
if (listenAddresses[i].HostNameComparisonMode == HostNameComparisonMode.StrongWildcard)
{
return listenAddresses[i];
}
if (listenAddresses[i].HostNameComparisonMode == HostNameComparisonMode.WeakWildcard)
{
weakBaseAddress = listenAddresses[i];
}
if ((listenAddresses[i].HostNameComparisonMode == HostNameComparisonMode.Exact)
&& (string.Compare(listenAddresses[i].BaseAddress.Host, uri.Host, StringComparison.OrdinalIgnoreCase) == 0))
{
foundBaseAddress = listenAddresses[i];
}
}
}
if (foundBaseAddress == null)
foundBaseAddress = weakBaseAddress;
return foundBaseAddress;
}
}
}

View File

@ -0,0 +1,275 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime;
using System.Runtime.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.ServiceModel.Activation.Diagnostics;
using System.ServiceModel.Diagnostics.Application;
using System.Diagnostics.CodeAnalysis;
class HostedTransportConfigurationManager
{
IDictionary<string, HostedTransportConfiguration> configurations = new Dictionary<string, HostedTransportConfiguration>(StringComparer.Ordinal);
// Double-checked locking pattern requires volatile for read/write synchronization
volatile bool initialized = false;
MetabaseSettings metabaseSettings;
// Double-checked locking pattern requires volatile for read/write synchronization
static volatile HostedTransportConfigurationManager singleton;
static object syncRoot = new object();
#pragma warning disable 436
const string WasHostingAssemblyName = "System.ServiceModel.WasHosting, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKey;
const string MetabaseSettingsIis7FactoryTypeName = "System.ServiceModel.WasHosting.MetabaseSettingsIis7Factory, " + WasHostingAssemblyName;
#pragma warning restore 436
const string CreateMetabaseSettingsIis7MethodName = "CreateMetabaseSettings";
HostedTransportConfigurationManager()
{
if (!Iis7Helper.IsIis7)
{
metabaseSettings = new MetabaseSettingsIis6();
}
else
{
metabaseSettings = CreateWasHostingMetabaseSettings();
}
}
HostedTransportConfigurationManager(MetabaseSettings metabaseSettings)
{
this.metabaseSettings = metabaseSettings;
}
[Fx.Tag.SecurityNote(Critical = "Calls Critical methods CreateMetabaseSettings.",
Safe = "Ensures that only the correct, well-known method is called to construct the metabase settings. No other " +
"details are leaked, and no control flow or data is allowed in.")]
[SecuritySafeCritical]
static MetabaseSettingsIis CreateWasHostingMetabaseSettings()
{
Type type = Type.GetType(MetabaseSettingsIis7FactoryTypeName, false);
if (type == null)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_MetabaseSettingsIis7TypeNotFound(MetabaseSettingsIis7FactoryTypeName, WasHostingAssemblyName)));
}
return CreateMetabaseSettings(type);
}
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is a private SecurityCritical method and its only caller passes in non-user data. Users cannot pass arbitrary data to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts full trust in order to call a well-known internal static in WasHosting.dll." +
"Caller must ensure that 'type' argument refers to the trusted, well-known Type.")]
[SecurityCritical]
static MetabaseSettingsIis CreateMetabaseSettings(Type type)
{
object instance = null;
MethodInfo method = type.GetMethod(CreateMetabaseSettingsIis7MethodName, BindingFlags.NonPublic | BindingFlags.Static);
try
{
new PermissionSet(PermissionState.Unrestricted).Assert();
instance = method.Invoke(null, null);
}
finally
{
PermissionSet.RevertAssert();
}
if (!(instance is MetabaseSettingsIis))
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_BadMetabaseSettingsIis7Type(type.AssemblyQualifiedName)));
}
return (MetabaseSettingsIis)instance;
}
internal static void EnsureInitializedForSimpleApplicationHost(HostedHttpRequestAsyncResult result)
{
if (singleton != null)
{
return;
}
lock (syncRoot)
{
if (singleton != null)
return;
singleton = new HostedTransportConfigurationManager(new MetabaseSettingsCassini(result));
}
}
internal static MetabaseSettings MetabaseSettings
{
get
{
return HostedTransportConfigurationManager.Value.metabaseSettings;
}
}
object ThisLock
{
get
{
return this;
}
}
static HostedTransportConfigurationManager Value
{
get
{
if (singleton == null)
{
lock (syncRoot)
{
if (singleton == null)
{
//Ensure ETW tracing is initialized
System.ServiceModel.Diagnostics.TraceUtility.SetEtwProviderId();
if (TD.HostedTransportConfigurationManagerConfigInitStartIsEnabled())
{
TD.HostedTransportConfigurationManagerConfigInitStart();
}
ServiceHostingEnvironment.EnsureInitialized();
singleton = new HostedTransportConfigurationManager();
if (TD.HostedTransportConfigurationManagerConfigInitStopIsEnabled())
{
TD.HostedTransportConfigurationManagerConfigInitStop();
}
}
}
}
return singleton;
}
}
void EnsureInitialized()
{
if (!initialized)
{
lock (ThisLock)
{
if (!initialized)
{
// Register protocols.
foreach (string protocol in metabaseSettings.GetProtocols())
{
// special case HTTP, it's a legacy protocol
if (string.CompareOrdinal(protocol, Uri.UriSchemeHttp) == 0 ||
string.CompareOrdinal(protocol, Uri.UriSchemeHttps) == 0)
{
HttpHostedTransportConfiguration httpConfiguration = null;
if (string.CompareOrdinal(protocol, Uri.UriSchemeHttp) == 0)
{
httpConfiguration = new HttpHostedTransportConfiguration();
}
else
{
httpConfiguration = new HttpsHostedTransportConfiguration();
}
configurations.Add(protocol, httpConfiguration);
}
else
{
if (!Iis7Helper.IsIis7)
{
throw Fx.AssertAndThrowFatal("HostedTransportConfigurationManager.EnsureInitialized() protocols other than http and https can only be configured in IIS7");
}
if (AspNetPartialTrustHelpers.NeedPartialTrustInvoke)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.PartialTrustNonHttpActivation(protocol, HostingEnvironmentWrapper.ApplicationVirtualPath)));
}
AddHostedTransportConfigurationIis7(protocol);
}
}
initialized = true;
}
}
}
}
void AddHostedTransportConfigurationIis7(string protocol)
{
HostedTransportConfiguration configuration = null;
try
{
ServiceHostingEnvironmentSection section = ServiceHostingEnvironmentSection.GetSection();
if (section.TransportConfigurationTypes.ContainsKey(protocol))
{
TransportConfigurationTypeElement element = section.TransportConfigurationTypes[protocol];
Debug.Print("HostedTransportConfigurationManager.AddHostedTransportConfigurationIis7() found TransportConfigurationTypes for protocol: " + protocol + " name: " + element.TransportConfigurationType);
Type type = Type.GetType(element.TransportConfigurationType);
configuration = Activator.CreateInstance(type) as HostedTransportConfiguration;
configurations.Add(protocol, configuration);
}
else
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_ProtocolNoConfiguration(protocol)));
}
}
catch (Exception exception)
{
if (!Fx.IsFatal(exception))
{
Debug.Print("HostedTransportConfigurationManager.AddHostedTransportConfigurationIis7() caught exception: " + exception);
if (DiagnosticUtility.ShouldTraceError)
{
TraceUtility.TraceEvent(TraceEventType.Error, TraceCode.WebHostProtocolMisconfigured, SR.TraceCodeWebHostProtocolMisconfigured,
new StringTraceRecord("Protocol", protocol),
this, exception);
}
}
throw;
}
}
internal static Uri[] GetBaseAddresses(string virtualPath)
{
return HostedTransportConfigurationManager.Value.InternalGetBaseAddresses(virtualPath);
}
internal static HostedTransportConfiguration GetConfiguration(string scheme)
{
return HostedTransportConfigurationManager.Value.InternalGetConfiguration(scheme);
}
Uri[] InternalGetBaseAddresses(string virtualPath)
{
EnsureInitialized();
List<Uri> baseAddresses = new List<Uri>();
foreach (HostedTransportConfiguration configuration in configurations.Values)
{
baseAddresses.AddRange(configuration.GetBaseAddresses(virtualPath));
}
return baseAddresses.ToArray();
}
HostedTransportConfiguration InternalGetConfiguration(string scheme)
{
EnsureInitialized();
if (!configurations.ContainsKey(scheme))
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.Hosting_NotSupportedProtocol(scheme)));
}
return configurations[scheme];
}
}
}

View File

@ -0,0 +1,211 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Web;
using System.Web.Hosting;
// wrapper class that helps with partial trust analysis
// -- HostingEnvironment does a number of Demands and LinkDemands
// -- this wrapper encapsulates access into "Safe" and "Unsafe" methods that do the appropriate asserts
// -- it is recommended that ALL HostingEnvironment access go through this class
// -- "Safe" methods are [SecurityCritical, SecurityTreatAsSafe] or not [SecurityCritical]
// -- "Unsafe" methods are [SecurityCritical]
// -- because each method does precisely one access, we use declarative asserts for clarity
static class HostingEnvironmentWrapper
{
public static string ApplicationVirtualPath
{
get
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.ApplicationVirtualPath;
}
}
public static bool IsHosted
{
get { return HostingEnvironment.IsHosted; }
}
[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.")]
public static VirtualPathProvider VirtualPathProvider
{
[SecuritySafeCritical]
get
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.VirtualPathProvider;
}
}
[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]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void DecrementBusyCount()
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
HostingEnvironment.DecrementBusyCount();
}
// demands SecurityPermission(ControlPrincipal) -- use Unsafe version to assert
public static IDisposable Impersonate()
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.Impersonate();
}
// demands SecurityPermission(Unrestricted) -- use Unsafe version to assert
public static IDisposable Impersonate(IntPtr token)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.Impersonate(token);
}
[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]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void IncrementBusyCount()
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
HostingEnvironment.IncrementBusyCount();
}
public static string MapPath(string virtualPath)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.MapPath(virtualPath);
}
public static string UnsafeApplicationID
{
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "Users cannot pass arbitrary data to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission in order to call HostingEnvironment.get_ApplicationID.")]
[SecurityCritical]
[AspNetHostingPermission(System.Security.Permissions.SecurityAction.Assert, Level = AspNetHostingPermissionLevel.High)]
get
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.ApplicationID;
}
}
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "Users cannot pass arbitrary data to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission in order to call HostingEnvironment.UnsafeImpersonate.")]
[SecurityCritical]
[SecurityPermission(SecurityAction.Assert, ControlPrincipal = true)]
public static IDisposable UnsafeImpersonate()
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.Impersonate();
}
[Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission in order to call HostingEnvironment.UnsafeImpersonate.")]
[SecurityCritical]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public static IDisposable UnsafeImpersonate(IntPtr token)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
return HostingEnvironment.Impersonate(token);
}
[SuppressMessage(FxCop.Category.Security, FxCop.Rule.SecureAsserts, Justification = "This is an internal SecurityCritical method and its only caller passes in non-user data. Users cannot pass arbitrary data to this code.")]
[Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission in order to call HostingEnvironment.RegisterObject.")]
[SecurityCritical]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public static void UnsafeRegisterObject(IRegisteredObject target)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
HostingEnvironment.RegisterObject(target);
}
[Fx.Tag.SecurityNote(Critical = "Asserts SecurityPermission in order to call HostingEnvironment.UnregisterObject.")]
[SecurityCritical]
[SecurityPermission(SecurityAction.Assert, Unrestricted = true)]
public static void UnsafeUnregisterObject(IRegisteredObject target)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
HostingEnvironment.UnregisterObject(target);
}
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeImpersonate in order to check whether the service file exists.",
Safe = "Does not leak anything, does not let caller influence impersonation.")]
[SecuritySafeCritical]
public static bool ServiceFileExists(string normalizedVirtualPath)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
IDisposable unsafeImpersonate = null;
try
{
try
{
try
{
}
finally
{
unsafeImpersonate = HostingEnvironmentWrapper.UnsafeImpersonate();
}
return HostingEnvironment.VirtualPathProvider.FileExists(normalizedVirtualPath);
}
finally
{
if (null != unsafeImpersonate)
{
unsafeImpersonate.Dispose();
}
}
}
catch
{
throw;
}
}
[Fx.Tag.SecurityNote(Critical = "Uses SecurityCritical method UnsafeImpersonate in order to get service file.",
Safe = "Does not leak anything, does not let caller influence impersonation.")]
[SecuritySafeCritical]
public static VirtualFile GetServiceFile(string normalizedVirtualPath)
{
AspNetPartialTrustHelpers.FailIfInPartialTrustOutsideAspNet();
IDisposable unsafeImpersonate = null;
try
{
try
{
try
{
}
finally
{
unsafeImpersonate = HostingEnvironmentWrapper.UnsafeImpersonate();
}
return HostingEnvironment.VirtualPathProvider.GetFile(normalizedVirtualPath);
}
finally
{
if (null != unsafeImpersonate)
{
unsafeImpersonate.Dispose();
}
}
}
catch
{
throw;
}
}
}
}

View File

@ -0,0 +1,107 @@
//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Activation
{
using System.Runtime;
using System.Security;
using System.ServiceModel;
sealed class HostingMessageProperty : IAspNetMessageProperty
{
const string name = "webhost";
[Fx.Tag.SecurityNote(Critical = "Keeps track of impersonated user, caller must use with care and call Dispose at the appropriate time.")]
[SecurityCritical]
HostedImpersonationContext impersonationContext;
[Fx.Tag.SecurityNote(Critical = "Stores a SecurityCritical helper class that controls HttpContext.Current with an elevation." +
"Need to ensure that HostedThreadData is constructed and used properly.")]
[SecurityCritical]
HostedThreadData currentThreadData;
[Fx.Tag.SecurityNote(Critical = "Sets impersonation context from an arbitrary source, caller must guard.")]
[SecurityCritical]
internal HostingMessageProperty(HostedHttpRequestAsyncResult result)
{
Fx.Assert(ServiceHostingEnvironment.IsHosted, "should only be called in the hosted path");
if (ServiceHostingEnvironment.AspNetCompatibilityEnabled)
{
if (result.ImpersonationContext != null && result.ImpersonationContext.IsImpersonated)
{
this.impersonationContext = result.ImpersonationContext;
this.impersonationContext.AddRef();
}
currentThreadData = result.HostedThreadData;
}
this.OriginalRequestUri = result.OriginalRequestUri;
}
public Uri OriginalRequestUri
{
get;
private set;
}
static internal string Name
{
get
{
return name;
}
}
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 impersonationContext;
}
}
[Fx.Tag.SecurityNote(Critical = "Delegates to a SecurityCritical method in HostedThreadData." +
"Caller must ensure that function is called appropriately and result is guarded and Dispose()'d correctly.")]
[SecurityCritical]
public IDisposable ApplyIntegrationContext()
{
if (ServiceHostingEnvironment.AspNetCompatibilityEnabled)
{
return currentThreadData.CreateContext();
}
return null;
}
[Fx.Tag.SecurityNote(Critical = "Accesses SecurityCritical method HostedImpersonationContext.Impersonate." +
"Caller should use with care, must take responsibility for reverting impersonation.")]
[SecurityCritical]
public IDisposable Impersonate()
{
if (this.ImpersonationContext != null)
{
return this.ImpersonationContext.Impersonate();
}
else
{
return null;
}
}
[Fx.Tag.SecurityNote(Critical = "Cleans up impersonationContext, which is critical.", Safe = "Doesn't leak anything.")]
[SecuritySafeCritical]
public void Close()
{
if (impersonationContext != null)
{
impersonationContext.Release();
impersonationContext = null;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More