Setting the web.config tag will cause Exchange Poweshell cmdlets to fail and crash the MSExchangeServicesAppPool

When Exchange 2007 is installed it will create the following application pools within IIS 6.0:

  • MSExchangeAutodiscoverAppPool         
  • MSExchangeOWAAppPool                                         
  • MSExchangeServicesAppPool                   
  • MSExchangeSyncAppPool
  • MSExchangeUMAAppPool

What is an Application Pool?
An application pool is a feature of IIS 6.0 that allows one or more applications to be configured to run with a level of isolation between different Web applications. If you want to isolate all of your custom Web applications you would create a separate application pool for each of your Web application and placing them in their corresponding application pool.

Each application pool will run in its own worker process, and by default the Exchange Application pools run under the identity of the local system.

In previous versions of IIS all worker processes ran under the Local System account. This account has system administrator privileges (god rights) on the local server. Because LocalSystem has god rights over a system it can cause security risks. In IIS 6.0 you can set the identity of the worker process at the application pool level.

What is an identity?
An Identity is the account that the application pool is running under. When you install IIS 6.0 all application pools run under the NetworkService account. The NetworkService user account has very low-level access rights.

The NetworkService account has the following privileges:

  • Adjust memory quotas for a process
  • Generate security audits
  • Log on as a service
  • Replace process level token
  • Impersonate a client after authentication
  • Allow logon locally
  • Access this computer from the network

By running your application pools under the NetworkService you can minimize your servers security risks. In IIS you can configure your application pools to run under one of the following three accounts:

  • NetworkService
  • LocalSystem
  • LocalService

When you install Exchange 2007 all Exchange application pools run under the LocalSystem account. This is needed for access across domains, etc. Often administrators have the need to create customer asp .net applications that need different access rights. One way to get this to work is to make some configuration changes to the web.config file for the application pool and change the following tag from:<identity impersonate="false" /> to: <identity impersonate="true" />

By default the web.config file in the exchange virtual directories have the impersonate flag set to false. When you set this tag to 'True' you are allowing code to impersonate a different Windows user, including when you run the Powershell cmdlets.

Windows authentication allows us to use the windows user accounts. This provider uses IIS to perform the actual authentication, and then passes the authenticated identity to your code. In this case we are running a cmdlet as the domain administrator and not the system's local service account. Once you do this the application pool will force a crash which is used to protect us from a security exploit. For those of you who like to debug managed code here is the call stack:

0:000> !clrstack

OS Thread Id: 0x117c (0)
Child-SP RetAddr Call Site
000000000681d6e0 0000064220206ef1 System.Environment.Exit(Int32)
000000000681d730 00000642243cc4ca Microsoft.Exchange.Common.ExDiagnostics.FailFast(System.String, Boolean)
000000000681d7a0 00000642243cc7e0 Microsoft.Exchange.Data.Directory.ConnectionPoolManager.BlockImpersonatedCallers()
000000000681d8b0 00000642243cdcc5 Microsoft.Exchange.Data.Directory.ConnectionPoolManager.GetConnection(Microsoft.Exchange.Data.Directory.ConnectionType, Int32 ByRef)
000000000681d900 00000642243cdde9 Microsoft.Exchange.Data.Directory.ADSession.GetConnection(System.String, Boolean, Boolean, Microsoft.Exchange.Data.Directory.ADObjectId ByRef, Int32 ByRef)
000000000681db20 00000642243d1b8b Microsoft.Exchange.Data.Directory.ADSession.GetReadConnection(System.String, Microsoft.Exchange.Data.Directory.ADObjectId ByRef, Int32 ByRef)
000000000681db60 00000642243d2a8f Microsoft.Exchange.Data.Directory.ADSession.Find(Microsoft.Exchange.Data.Directory.ADObjectId, System.String, Microsoft.Exchange.Data.Directory.ADObjectId, Microsoft.Exchange.Data.Directory.QueryScope, Microsoft.Exchange.Data.QueryFilter, Microsoft.Exchange.Data.SortBy, Int32, System.Collections.Generic.IEnumerable`1<Microsoft.Exchange.Data.PropertyDefinition>, Microsoft.Exchange.Data.Directory.CreateObjectDelegate, Microsoft.Exchange.Data.Directory.CreateObjectsDelegate)
000000000681df20 00000642243d2c54 Microsoft.Exchange.Data.Directory.ADSession.Find(Microsoft.Exchange.Data.Directory.ADObjectId, Microsoft.Exchange.Data.Directory.QueryScope, Microsoft.Exchange.Data.QueryFilter, Microsoft.Exchange.Data.SortBy, Int32, System.Collections.Generic.IEnumerable`1<Microsoft.Exchange.Data.PropertyDefinition>, Microsoft.Exchange.Data.Directory.CreateObjectDelegate, Microsoft.Exchange.Data.Directory.CreateObjectsDelegate)
000000000681df90 000006427f668a37 Microsoft.Exchange.Data.Directory.ADSession.Find[[System.__Canon, mscorlib]](Microsoft.Exchange.Data.Directory.ADObjectId, Microsoft.Exchange.Data.Directory.QueryScope, Microsoft.Exchange.Data.QueryFilter, Microsoft.Exchange.Data.SortBy, Int32, System.Collections.Generic.IEnumerable`1<Microsoft.Exchange.Data.PropertyDefinition>)
000000000681e0a0 00000642221a928a Microsoft.Exchange.Data.Directory.Recipient.ADRecipientSession.FindBySid(System.Security.Principal.SecurityIdentifier)
000000000681e180 00000642221a96c1 Microsoft.Exchange.Data.Storage.ExchangePrincipal.FromUserSid(Microsoft.Exchange.Data.Directory.Recipient.ADRecipientSession, System.Security.Principal.SecurityIdentifier)
000000000681e220 0000064280203d53 Microsoft.Exchange.Data.Storage.ExchangePrincipal.FromWindowsIdentity(System.Security.Principal.WindowsIdentity)
000000000681e260 0000064280203a42 Microsoft.Exchange.Services.Core.Types.ExchangePrincipalCache.CreateExchangePrincipal(System.Security.Principal.WindowsIdentity)
000000000681e2f0 00000642802037f5 Microsoft.Exchange.Services.Core.Types.ExchangePrincipalCache.GetFromCache(System.Security.Principal.WindowsIdentity)
000000000681e330 0000064280203107 Microsoft.Exchange.Services.Core.Types.CallContext.Initialize(System.Security.Principal.IPrincipal, Microsoft.Exchange.Services.Core.Types.AppWideMailboxSessionCache, Microsoft.Exchange.Services.AcceptedDomainCache, Microsoft.Exchange.Services.Core.Types.MailboxAccessType, Microsoft.Exchange.Services.Core.Subscriptions, System.Globalization.CultureInfo, System.Globalization.CultureInfo, System.String)
000000000681e3b0 0000064280202b0d Microsoft.Exchange.Services.Core.Types.CallContext..ctor(System.Security.Principal.IPrincipal, Microsoft.Exchange.Services.Core.Types.AppWideMailboxSessionCache, Microsoft.Exchange.Services.AcceptedDomainCache, Microsoft.Exchange.Services.Core.Types.MailboxAccessType, System.String, System.String, System.String, Microsoft.Exchange.Services.Core.SerializedSecurityAccessToken, Microsoft.Exchange.Services.Core.Subscriptions, System.Globalization.CultureInfo, System.Globalization.CultureInfo, System.String)
000000000681e440 000006428020276b Microsoft.Exchange.Services.RequestSoapHeaderServiceExtension.ConfigureCaches(Microsoft.Exchange.Services.Core.Types.MailboxAccessType, System.String, System.String, System.String, Microsoft.Exchange.Services.Core.SerializedSecurityAccessToken, System.String)
000000000681e540 0000064280202046 Microsoft.Exchange.Services.RequestSoapHeaderServiceExtension.ProcessSoapHeaders(System.Web.Services.Protocols.SoapMessage, System.Object)
000000000681e600 00000642801fad99 Microsoft.Exchange.Services.ServiceExtensionManager.DoAfterDeserializeRequest(System.Web.Services.Protocols.SoapMessage)
000000000681e690 0000000005432798 Microsoft.Exchange.Services.ServiceExtensionManager+<>c__DisplayClass1.<ProcessMessage>b__0()
000000000681e6e0 000006422087918b Microsoft.Exchange.Common.IL.ILUtil.DoTryFilterCatch(Microsoft.Exchange.Common.IL.TryDelegate, Microsoft.Exchange.Common.IL.FilterDelegate, Microsoft.Exchange.Common.IL.CatchDelegate)
000000000681e720 00000642801faccc Microsoft.Exchange.Diagnostics.ExWatson.SendReportOnUnhandledException(MethodDelegate, IsExceptionInteresting)
000000000681e770 0000064253282b49 Microsoft.Exchange.Services.Core.ServiceDiagnostics.TraceErrorOnUnhandledException(MethodDelegate)
000000000681e7b0 00000642532773fb System.Web.Services.Protocols.SoapMessage.RunExtensions(System.Web.Services.Protocols.SoapExtension[], Boolean)
000000000681e810 000006425326f611 System.Web.Services.Protocols.SoapServerProtocol.CreateServerInstance()
000000000681e860 000006425326fcfb System.Web.Services.Protocols.WebServiceHandler.Invoke()
000000000681e8d0 00000642bcaee322 System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
000000000681e930 00000642bcaf1e41 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
000000000681e9f0 00000642bcaed472 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
000000000681ea90 00000642bcaf54b0 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception)
000000000681eb50 00000642bcac103e System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object)
000000000681ebb0 00000642bc8c4eb1 System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest)
000000000681ec50 00000642bc9525d8 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
000000000681ec90 000006427f66a6f2 System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)

If you look in the application log you after you run a powershell cmdlet such as Test-OutlookWebServices you will see the following error:

Event Type: Error
Event Source: MSExchange Common
Event Category: General
Event ID: 4999
Date: 10/27/2007
Time: 3:08:56 PM
User: N/A
Computer: Exchange2007
Description:
Watson report about to be sent to dw20.exe for process id: 4228, with parameters: E12IIS, c-RTL-AMD64, 08.00.0685.020, WS, M.E.D.Directory, M.E.D.D.ConnectionPoolManager.BlockImpersonatedCallers, M.E.Common.FailFastException, 78ac, 08.00.0685.024

For more information, see Help and Support Center at https://go.microsoft.com/fwlink/events.asp.

The key piece of information here is the following: M.E.D.D.ConnectionPoolManager.BlockImpersonatedCallers.

How to Fix
1. Modify the web.config file in the root of the virtual directory and change the following tag from: <identity impersonate="True" /> back to: <identity impersonate="false" />.
2. Restart your Exchange application pool.
3. Re-run your Powershell cmdlet.

Dave