IIS6 with all WindowsUpdate patches
ASP.NET 1.1-SP1
using identity impersonate="true" and authentication mode="Windows" in
web.config
Application is not in the local intranet, it is externally hosted for
an internal company
Web app with a reference to an external Assembly (it has no strong
name). The external Assembly contains a class with a method for
creating a new AppDomain and then placing a new Singleton instance of
another class (defined in the same Assembly) in the new AppDomain.
In the Session_Start event in Global.Asax, I check if the user has
authenticated, and if so the external Assembly is loaded and an
instance of the class is unwrapped and placed in the Remoted domain.
Web pages can make Remoted calls as needed and do their work.
However, that only works from a local XP desktop (where the developer
is an Administrator or Power User). The below Exception is thrown when
run from a Windows 2003 server. I think there is a problem is related
to Evidence for loading the Assembly. What could be wrong?
The code looks like this:
Evidence appEvidence = null;
AppDomainSetup aaD = new AppDomainSetup();
aaD.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory +"bin";
aaD.PrivateBinPath = aaD.ApplicationBase;
aaD.ApplicationName = "AppStorage";
aaD.ShadowCopyDirectories = aaD.ApplicationBase;
aaD.ShadowCopyFiles = "true";
AppDomain appdoma = AppDomain.CreateDomain("Dummy");
AppStorage appStorage = new AppStorage();
try
{
appdoma = AppDomain.CreateDomain( "AppStorage" , appEvidence , aaD );
this._hostHandle = appdoma.CreateInstance( "TestDev.AppServices" ,
"TestDev.AppServices.AppStorage" );
appStorage = (AppStorage)this._hostHandle.Unwrap();
ObjectHandle _hostHandle = appdoma.CreateInstance(
"TestDev.AppServices" , "TestDev.AppServices.AppStorage" );
// Above line is where Exception is thrown
Problem:
System.IO.FileLoadException: Access is denied: 'TestDev.AppServices'.
File name: "TestDev.AppServices"
Server stack trace:
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String
codeBase, Boolean isStringized,
Evidence assemblySecurity, Boolean
throwOnFileNotFound, Assembly locationHint, StackCrawlMark& stackMark)
at System.Reflection.Assembly.InternalLoad(AssemblyName
assemblyRef, Boolean stringized,
Evidence assemblySecurity, StackCrawlMark&
stackMark)
at System.Reflection.Assembly.InternalLoad(String assemblyString,
Evidence
assemblySecurity, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(String assemblyName, String
typeName,
Boolean ignoreCase, BindingFlags bindingAttr,
Binder binder, Object[] args,
CultureInfo culture, Object[]
activationAttributes, Evidence securityInfo,
StackCrawlMark& stackMark)
at System.Activator.CreateInstance(String assemblyName, String
typeName)
at System.AppDomain.CreateInstance(String assemblyName, String
typeName)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.PrivateProcessMessage(
MethodBase mb, Object[] args, Object server,
Int32 methodPtr, Boolean
fExecuteInContext, Object[]& outArgs)
at
System.Runtime.Remoting.Messaging.StackBuilderSink.SyncProcessMessage(IMessage
msg,
Int32 methodPtr, Boolean fExecuteInContext)
Exception rethrown at [0]:
at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg)
at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type)
at System.AppDomain.CreateInstance(String assemblyName, String
typeName)
at TestDev.AppServices.EnterpriseServices.StoragePrep.Prepare(
String remoteServerLocation, Int32
localClientPort)
in .....storageprep.cs:line 106
=== Pre-bind state information ===
LOG: DisplayName = TestDev.AppServices
(Partial)
LOG: Appbase = E:/inetpub/wwwsites/TestSite/bin
LOG: Initial PrivatePath = E:/inetpub/wwwsites/TestSite/bin
Calling assembly : (Unknown).
===
LOG: Application configuration file does not exist.
LOG: Policy not being applied to reference at this time (private,
custom, partial, or location-based assembly bind).
LOG: Post-policy reference: TestDev.AppServices
LOG: Attempting download of new URL
file:///E:/inetpub/wwwsites/TestSite/bin/TestDev.AppServices.DLL.
LOG: Policy not being applied to reference at this time (private,
custom, partial, or location-based assembly bind).
LOG: Post-policy reference: TestDev.AppServices, Version=6.2.0.0,
Culture=neutral, PublicKeyToken=null
______________________________________________________________________
Call Stack:
Method Global.StoragePrep
Method Global.Application_Start
sender: System.Object
e: System.EventArgs
Method RuntimeMethodInfo.InternalInvoke
obj: System.Object
invokeAttr: System.Reflection.BindingFlags
binder: System.Reflection.Binder
parameters: System.Object[]
culture: System.Globalization.CultureInfo
isBinderDefault: System.Boolean
caller: System.Reflection.Assembly
verifyAccess: System.Boolean
Method RuntimeMethodInfo.InternalInvoke
obj: System.Object
invokeAttr: System.Reflection.BindingFlags
binder: System.Reflection.Binder
parameters: System.Object[]
culture: System.Globalization.CultureInfo
verifyAccess: System.Boolean
Method RuntimeMethodInfo.Invoke
obj: System.Object
invokeAttr: System.Reflection.BindingFlags
binder: System.Reflection.Binder
parameters: System.Object[]
culture: System.Globalization.CultureInfo
Method HttpApplication.ProcessSpecialRequest
context: System.Web.HttpContext
method: System.Reflection.MethodInfo
paramCount: System.Int32
eventSource: System.Object
eventArgs: System.EventArgs
session: System.Web.SessionState.HttpSessionState
Method HttpApplicationFactory.FireApplicationOnStart
context: System.Web.HttpContext
Runtime CLI Information: .NET Runtime
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\
NET Version v1.1.4322 Release Build
[MSFT] - 16 Dec 2005 08:17 GMT
From your description, it seems to be a security issue. Your ASP.NET
application will use the current user's acount to load the app domain. To
confirm this, you can logon on as a local administrator, and browse to the
ASP.NET web page, what will be the result?
Luke
xenophon - 16 Dec 2005 14:40 GMT
Yes, I agree there is a security issue.
This is not an issue where a page can be browsed by one user and not
by another. The AppDomain work occurs in the Session_Start event,
presumably before any page is instanced. It appears to me that an
unknown user account does not have permissions to load or Reflect over
the external DLL for Remoting.
I am unable to properly debug this because if I am in the VS.NET 2003
debugger (where I develop as a local Administrator), the problem does
not occur. It occurs only when the app content is xcopy-deployed to
the remote web server and the site is then accessed by an unprivileged
user. I set up the web app to send an email when an Exception is
thrown, that is the only reason I have the info I previously posted.
The ACLs on the bin directory (where the external DLL is located)
allow "R"ead for the local group that can otherwise access the site.
Do I need to create custom Evidence so "everyone" can load the
Assembly?
>From your description, it seems to be a security issue. Your ASP.NET
>application will use the current user's acount to load the app domain. To
>confirm this, you can logon on as a local administrator, and browse to the
>ASP.NET web page, what will be the result?
>
>Luke
[MSFT] - 19 Dec 2005 05:52 GMT
To make the code in Session_start running under a powerful account, you may
change the account for the application pool: In IIS 6. 0 Manager, expand
"Applications Pools" and find the pool for your ASP.NET application, in its
properties page, change its identity to a powerful account, for example, a
local administrator and with network access permission. Will this fix the
problem?
Luke