| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Transactions
- {
- using System;
- using System.Diagnostics.CodeAnalysis;
- using System.Runtime;
- using System.ServiceModel.Channels;
- using System.ServiceModel;
- using System.IO;
- using System.Net;
- using System.Security;
- using System.ServiceModel.ComIntegration;
- using System.ServiceModel.Security;
- using System.Transactions;
- using Microsoft.Transactions.Wsat.Messaging;
- using Microsoft.Transactions.Wsat.Protocol;
- using Microsoft.Transactions.Wsat.Recovery;
- class TransactionManagerConfigurationException : TransactionException
- {
- public TransactionManagerConfigurationException(string error, Exception e)
- :
- base(error, e)
- {
- }
- public TransactionManagerConfigurationException(string error)
- :
- base(error)
- {
- }
- }
- class WsatConfiguration
- {
- static readonly string DisabledRegistrationPath;
- const string WsatKey = @"Software\Microsoft\WSAT\3.0";
- const string OleTxUpgradeEnabledValue = "OleTxUpgradeEnabled";
- const bool OleTxUpgradeEnabledDefault = true;
- bool oleTxUpgradeEnabled;
- EndpointAddress localActivationService10;
- EndpointAddress localActivationService11;
- EndpointAddress remoteActivationService10;
- EndpointAddress remoteActivationService11;
- Uri registrationServiceAddress10;
- Uri registrationServiceAddress11;
- bool protocolService10Enabled = false;
- bool protocolService11Enabled = false;
- bool inboundEnabled;
- bool issuedTokensEnabled;
- TimeSpan maxTimeout;
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to BindingStrings are safe.")]
- static WsatConfiguration()
- {
- DisabledRegistrationPath = string.Concat(BindingStrings.AddressPrefix, "/", BindingStrings.RegistrationCoordinatorSuffix(ProtocolVersion.Version10), BindingStrings.DisabledSuffix);
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to ProtocolInformationReader.IsV10Enabled and IsV11Enabled are safe.")]
- public WsatConfiguration()
- {
- // Get whereabouts
- WhereaboutsReader whereabouts = GetWhereabouts();
- ProtocolInformationReader protocol = whereabouts.ProtocolInformation;
- if (protocol != null)
- {
- this.protocolService10Enabled = protocol.IsV10Enabled;
- this.protocolService11Enabled = protocol.IsV11Enabled;
- }
- Initialize(whereabouts);
- // Read local registry flag
- this.oleTxUpgradeEnabled = ReadFlag(WsatKey, OleTxUpgradeEnabledValue, OleTxUpgradeEnabledDefault);
- }
- void Initialize(WhereaboutsReader whereabouts)
- {
- // MB 47153: don't throw system exception if whereabouts data is broken
- try
- {
- InitializeForUnmarshal(whereabouts);
- InitializeForMarshal(whereabouts);
- }
- catch (UriFormatException e)
- {
- // UriBuilder.Uri can throw this if the URI is ultimately invalid
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new TransactionManagerConfigurationException(SR.GetString(SR.WsatUriCreationFailed), e));
- }
- catch (ArgumentOutOfRangeException e)
- {
- // UriBuilder constructor can throw this if port < 0
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new TransactionManagerConfigurationException(SR.GetString(SR.WsatUriCreationFailed), e));
- }
- }
- public bool OleTxUpgradeEnabled
- {
- get { return this.oleTxUpgradeEnabled; }
- }
- public TimeSpan MaxTimeout
- {
- get { return this.maxTimeout; }
- }
- public bool IssuedTokensEnabled
- {
- get { return this.issuedTokensEnabled; }
- }
- public bool InboundEnabled
- {
- get { return this.inboundEnabled; }
- }
- public bool IsProtocolServiceEnabled(ProtocolVersion protocolVersion)
- {
- switch (protocolVersion)
- {
- case ProtocolVersion.Version10:
- return this.protocolService10Enabled;
- case ProtocolVersion.Version11:
- return this.protocolService11Enabled;
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion)));
- }
- }
- public EndpointAddress LocalActivationService(ProtocolVersion protocolVersion)
- {
- switch (protocolVersion)
- {
- case ProtocolVersion.Version10:
- return this.localActivationService10;
- case ProtocolVersion.Version11:
- return this.localActivationService11;
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion)));
- }
- }
- public EndpointAddress RemoteActivationService(ProtocolVersion protocolVersion)
- {
- switch (protocolVersion)
- {
- case ProtocolVersion.Version10:
- return this.remoteActivationService10;
- case ProtocolVersion.Version11:
- return this.remoteActivationService11;
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion)));
- }
- }
- public EndpointAddress CreateRegistrationService(AddressHeader refParam, ProtocolVersion protocolVersion)
- {
- switch (protocolVersion)
- {
- case ProtocolVersion.Version10:
- return new EndpointAddress(this.registrationServiceAddress10, refParam);
- case ProtocolVersion.Version11:
- return new EndpointAddress(this.registrationServiceAddress11, refParam);
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion)));
- }
- }
- public bool IsLocalRegistrationService(EndpointAddress endpoint, ProtocolVersion protocolVersion)
- {
- if (endpoint.Uri == null)
- return false;
- switch (protocolVersion)
- {
- case ProtocolVersion.Version10:
- return endpoint.Uri == this.registrationServiceAddress10;
- case ProtocolVersion.Version11:
- return endpoint.Uri == this.registrationServiceAddress11;
- default:
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new ArgumentException(SR.GetString(SR.InvalidWsatProtocolVersion)));
- }
- }
- public bool IsDisabledRegistrationService(EndpointAddress endpoint)
- {
- return endpoint.Uri.AbsolutePath == DisabledRegistrationPath;
- }
- //
- // Internals
- //
- WhereaboutsReader GetWhereabouts()
- {
- try
- {
- return new WhereaboutsReader(TransactionInterop.GetWhereabouts());
- }
- catch (SerializationException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new TransactionManagerConfigurationException(SR.GetString(SR.WhereaboutsReadFailed), e));
- }
- // If GetWhereabouts throws TransactionException, let it propagate
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to the ProtocolInformationReader properties and to BindingStrings.RegistrationCoordinatorSuffix(..) are safe.")]
- void InitializeForUnmarshal(WhereaboutsReader whereabouts)
- {
- ProtocolInformationReader protocol = whereabouts.ProtocolInformation;
- if (protocol != null && protocol.NetworkInboundAccess)
- {
- this.inboundEnabled = true;
- bool isTmLocal = string.Compare(Environment.MachineName,
- protocol.NodeName,
- StringComparison.OrdinalIgnoreCase) == 0;
- string spnIdentity;
- string activationCoordinatorSuffix10 =
- BindingStrings.ActivationCoordinatorSuffix(ProtocolVersion.Version10);
- string activationCoordinatorSuffix11 =
- BindingStrings.ActivationCoordinatorSuffix(ProtocolVersion.Version11);
- if (protocol.IsClustered ||
- (protocol.NetworkClientAccess && !isTmLocal))
- {
- if (protocol.IsClustered)
- {
- // We cannot reliably perform mutual authentication against a clustered resource
- // See MB 43523 for more details on this
- spnIdentity = null;
- }
- else
- {
- spnIdentity = "host/" + protocol.HostName;
- }
- if (protocol.IsV10Enabled)
- {
- this.remoteActivationService10 = CreateActivationEndpointAddress(protocol,
- activationCoordinatorSuffix10,
- spnIdentity,
- true);
- }
- if (protocol.IsV11Enabled)
- {
- this.remoteActivationService11 = CreateActivationEndpointAddress(protocol,
- activationCoordinatorSuffix11,
- spnIdentity,
- true);
- }
- }
- if (isTmLocal)
- {
- spnIdentity = "host/" + protocol.NodeName;
- // The net.pipe Activation endpoint uses the host name as a discriminant
- // for cluster scenarios with more than one service on a node.
- if (protocol.IsV10Enabled)
- {
- this.localActivationService10 = CreateActivationEndpointAddress(protocol,
- activationCoordinatorSuffix10,
- spnIdentity,
- false);
- }
- if (protocol.IsV11Enabled)
- {
- this.localActivationService11 = CreateActivationEndpointAddress(protocol,
- activationCoordinatorSuffix11,
- spnIdentity,
- false);
- }
- }
- }
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to the ProtocolInformationReader properties (HostName, HttpsPort, BasePath) are safe.")]
- EndpointAddress CreateActivationEndpointAddress(ProtocolInformationReader protocol,
- string suffix,
- string spnIdentity,
- bool isRemote)
- {
- string uriScheme;
- string host;
- int port;
- string path;
- if (isRemote)
- {
- uriScheme = Uri.UriSchemeHttps;
- host = protocol.HostName;
- port = protocol.HttpsPort;
- path = protocol.BasePath + "/" + suffix + BindingStrings.RemoteProxySuffix;
- }
- else
- {
- uriScheme = Uri.UriSchemeNetPipe;
- host = "localhost";
- port = -1;
- path = protocol.HostName + "/" + protocol.BasePath + "/" + suffix;
- }
- UriBuilder builder = new UriBuilder(uriScheme, host, port, path);
- if (spnIdentity != null)
- {
- EndpointIdentity identity = EndpointIdentity.CreateSpnIdentity(spnIdentity);
- return new EndpointAddress(builder.Uri, identity);
- }
- else
- {
- return new EndpointAddress(builder.Uri);
- }
- }
- [SuppressMessage(FxCop.Category.Security, FxCop.Rule.AptcaMethodsShouldOnlyCallAptcaMethods, Justification = "The calls to the ProtocolInformationReader properties and to BindingStrings.RegistrationCoordinatorSuffix(..) are safe.")]
- void InitializeForMarshal(WhereaboutsReader whereabouts)
- {
- ProtocolInformationReader protocol = whereabouts.ProtocolInformation;
- if (protocol != null && protocol.NetworkOutboundAccess)
- {
- // We can marshal outgoing transactions using a valid address
- if (protocol.IsV10Enabled)
- {
- UriBuilder builder10 = new UriBuilder(Uri.UriSchemeHttps,
- protocol.HostName,
- protocol.HttpsPort,
- protocol.BasePath + "/" +
- BindingStrings.RegistrationCoordinatorSuffix(ProtocolVersion.Version10));
- this.registrationServiceAddress10 = builder10.Uri;
- }
- // when we have a WSAT1.1 coordinator
- if (protocol.IsV11Enabled)
- {
- UriBuilder builder11 = new UriBuilder(Uri.UriSchemeHttps,
- protocol.HostName,
- protocol.HttpsPort,
- protocol.BasePath + "/" +
- BindingStrings.RegistrationCoordinatorSuffix(ProtocolVersion.Version11));
- this.registrationServiceAddress11 = builder11.Uri;
- }
- this.issuedTokensEnabled = protocol.IssuedTokensEnabled;
- this.maxTimeout = protocol.MaxTimeout;
- }
- else
- {
- // Generate an address that will not work
- // We do this in order to generate coordination contexts that can be propagated
- // between processes on the same node even if WS-AT is disabled
- UriBuilder builder = new UriBuilder(Uri.UriSchemeHttps,
- whereabouts.HostName,
- 443,
- DisabledRegistrationPath);
- this.registrationServiceAddress10 = builder.Uri;
- this.registrationServiceAddress11 = builder.Uri;
- this.issuedTokensEnabled = false;
- this.maxTimeout = TimeSpan.FromMinutes(5);
- }
- }
- static object ReadValue(string key, string value)
- {
- try
- {
- using (RegistryHandle regKey = RegistryHandle.GetNativeHKLMSubkey(key, false))
- {
- if (regKey == null)
- return null;
- return regKey.GetValue(value);
- }
- }
- catch (SecurityException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new TransactionManagerConfigurationException(SR.GetString(SR.WsatRegistryValueReadError, value), e));
- }
- catch (IOException e)
- {
- throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
- new TransactionManagerConfigurationException(SR.GetString(SR.WsatRegistryValueReadError, value), e));
- }
- }
- static int ReadInt(string key, string value, int defaultValue)
- {
- object regValue = ReadValue(key, value);
- if (regValue == null || !(regValue is Int32))
- return defaultValue;
- return (int)regValue;
- }
- static bool ReadFlag(string key, string value, bool defaultValue)
- {
- return (int)ReadInt(key, value, defaultValue ? 1 : 0) != 0;
- }
- }
- }
|