Problem with Asserted Permissions

I have code that is hosted in IEEXEC. The same code can be run from a local or remote file and it will work. When it runs from IEEXEC it fails because of code access permissions. (The code is trying to use remoting to connect to a host that is other then the one it is loaded from.) The assemblies are strongly named and fully trusted.

I found an article that indicates the following line of code will allow code in a fully trusted assembly to do anything that it wants regradless of the AppDomain or previous deny settings.

(new PermissionSet(System.Security.Permissions.PermissionState.Unrestricted)).Assert();

AS A TEST
I have put this code in the Main() of an application that is being hosted in IEEXEC. I have also put this code at the begining of the function FinishCreateServerCAO (see stack below).

This application (the one hosted in IEEXEC) is using remoting to connect to a server and the server is connecting back to handle leases and remote events.
FinishCreateServerCAO is the lastpoint in the 'connect back path' before the connection is done.

I receive the following stack trace. Please point me in the right direction.
(PS. This code works if the .exe is run locally either from the local drive or from a remote server share.)

Exception:
An error occurred while processing the request on the server: System.Security.SecurityException: Request for the permission of type System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed.
at System.Security.PermissionListSet.CheckDemand(CodeAccessPermission demand, PermissionToken permToken)
at System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride)
at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark, PermissionType permType)
at System.Security.CodeAccessPermission.DemandInternal(PermissionType permissionType)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CoreChannel.SerializeBinaryMessage(IMessage msg, Boolean includeVersions)
at System.Runtime.Remoting.Channels.BinaryServerFormatterSink.ProcessMessage(IServerChannelSinkStack sinkStack, IMessage requestMsg, ITransportHeaders requestHeaders, Stream requestStream, IMessage& responseMsg, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.Tcp.TcpServerTransportSink.ServiceRequest(Object state)
at System.Runtime.Remoting.Channels.SocketHandler.ProcessRequestNow()

Server stack trace:
at System.Runtime.Remoting.Channels.Tcp.TcpSocketHandler.ReadToEndOfHeaders(BaseTransportHeaders headers)
at System.Runtime.Remoting.Channels.Tcp.TcpClientSocketHandler.ReadHeaders()
at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)

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 KMS.Core.Remoting.Shared.SponsoredCAOSponsor.Register(ILease lease, SponsoredCAOBase cao)
at KMS.Core.Remoting.Shared.RemotingManagerBase.FinishCreateServerCAO(Type cao_type, SponsoredCAOSponsor cao_sponsor, Object[] args_to_pass)
at KMS.Core.Remoting.Shared.RemotingManagerBase.CreateServerCAO(String cao_type_name, SponsoredCAOSponsor cao_sponsor, LeaseTime cao_lease_time, Object[] args)
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 [1]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at KMS.Core.Remoting.Shared.RemotingManagerBase.CreateServerCAO(String cao_type_name, SponsoredCAOSponsor cao_sponsor, LeaseTime cao_lease_time, Object[] args)
at KMS.HGS.Admin.MonitorPanel.ConnectToServer(String server_name, Int32 remote_port)
at KMS.HGS.Admin.AdminMonitorMain.mnu_File_Connect_Click(Object sender, EventArgs e)

Thanks




Answer this question

Problem with Asserted Permissions

  • Michael J. Fuhrman

    Okay, what you suggest sounds promising. What I don't know however is excatly what command I have to enter into CASPOL

    I gather it will have a -site in it as part of the membership option, but I don't know rest of it. Would you please put the rest of the pieces in place for me

    Also, is the path (ie website in this case) part of the equation In otherwords, if I do this to makeTestApp.exe a FullTrust is it full trust anywhere that it is found or is it fullstrust only when a the website address given inthe site option. If only at the site, than can I put in mutiple sites for the same exe

    Thanks



  • dstock

    Hello Roy,

    There are a few issues going on here.

    1) Zone-based security permissions are granted

    Your code/assembly is only given permission [to perform certain operations] based on the zone/location where it was loaded from. If the code was loaded from the local machine, then it is assumed the user intentionally copied the app/code to their machine and the code is granted FullTrust (all permissions to do anything).

    However, by default code that is loaded from network shares and the internet/intranet are granted FAR fewer/more restricted permissions. For example, no ability to use unmanaged code, access private variables (Reflection), Registry access, FileIOPermissions, "unsafe" code, etc.. One very high trust permission is the ability to disable [temporarily via Assert] the security checks. SecurityPermisison.Assert is generally granted to ONLY high-trust apps (not Internet or Intranet).

    2) IEExec is a code launcher [that mimics IE's behavior]

    Effectively, you can launch an exe as though it were in IE, with the permissions granted based on the zone. In your case, the permissions granted are based on the location of the app [command line argument to IEExec].

    3) Assert permission is not granted to virtually all partial trust code

    Your code is being run in a highly restricted environment (network share, Intranet, or Internet), and Assert isn't available.

    4) Elevating permissions for your assembly/application

    If you trust your application [i.e. you are confident it secure, non-malicious, and trusted], you can elevate permissions to the code based on the strongname and/or a public key. First you will need to sign the application (e.g. using sn.exe), then you will need to grant the application elevated permissions (e.g. FullTrust would be most straighforward if you completely trust the app). You can use caspol.exe to grant your application elevated permissions (i.e. FullTrust).

    Hope that helps,
    Stephen
    Microsoft Common Language Runtime- Security: Developer
    http://blogs.msdn.com/stfisher



  • Marcelius

    I think that you have restated what I thought I understood.

    The code must be fully trusted to allow me to get around the built-in CAS policies.

    I have elevated the code to full trust via a CAS policy based on the code signing key. (That is why it will work from a network share. Yes )

    Again, why does it not work.



  • Thomas van der Heijden

    Okay, I think I am getting the point that it will never work.

    In your reply you said Since you are using IEExec and running off of a network share, I would not be surprised to find out that the zone your AppDomain policy is using is Intranet or Internet. You can use caspol or the MMC.exe snap-in (.NET Framework Configuration) to configure the policy for that network share/site.

    You have mis-understood part of what I said.

    The program works when it is run from a remote share. When I try to run it from a web server via IE, which gets it hosted in IEEXEC, it fails as indicated.

    I think what you are telling me that the application will never work in IE because of the AppDomain issue. Is that correct



  • LoicBaroux

    Thanks for the followup, Roy.

    If your app runs inside of an AppDomain [sandbox] that is less than FullTrust, then demands that are triggered from any thread/assembly, and are not Asserted [by a high-trust/FullTrust assembly], will eventually hit the AppDomain boundary. If those demands are for permissions that are not granted to your AppDomain, then you will still see security failures/exceptions.

    For example:

    The .NET Framework assemblies for the most part are granted FullTrust - they are installed locally, and signed by Microsoft's key. A very low trust application (such as a browser-based applet) that calls the .NET FRX assemblies can still fail when full demands are triggered (e.g. RegistryPermission) as you would expect. Interestingly, even if every assembly on the callstack is of sufficient permission grant set (e.g. all assemblies on the callstack are granted RegistryPermission, but the AppDomain itself is not) then the demand will still fail/trigger a security exception.

    The current design of Code Access Security demand satisfaction is effectively:

    - demand is triggered

    - check first caller of method that is demanding, along with all callers on the callstack

    - if any caller is not granted that permission, then fail with SecurityException

    - if all callers are granted that permission, then check the AppDomain grant set itslf

    - if the AppDomain is not granted that permission, then fail with a SecurityException

    - Caveat: if any method on the callstack has been granted both the specific permission, and SecurityPermission.Assert, and has asserted the specific permission on their stack frame, then the AppDomain and callers above the Assert'ing frame are not checked. This is what is called an "elevation of privilege", and is a fairly high trust security action. It is necessary for building partial trust services, but must be closely audited by someone knowledgeable about the application, assemblies, and security.

    Based on your comments, I would suggest looking at the AppDomain policy itself. Granting the assembly FullTrust will allow your assembly to Assert and satisfy all demands, but it will not [in and of itself] guarantee demands will succeed, since the AppDomain may be lower trust.

    Since you are using IEExec and running off of a network share, I would not be surprised to find out that the zone your AppDomain policy is using is Intranet or Internet. You can use caspol or the MMC.exe snap-in (.NET Framework Configuration) to configure the policy for that network share/site.

    The helpful tools in the snap-in are:

    - Adjust Zone Security (to elevate the AppDomain permissions for that specific network share)

    - Evaluate Assembly (to determine what permissions your assembly will get based on your url and code)

    Hope that helps,
    Stephen
    Microsoft Common Language Runtime: Security - Developer
    http://blogs.msdn.com/stfisher



  • Reinhold_Fischer

    Hello Roy,

    I don't believe your scenario should not be impossible, as it's certainly common to want to launch an more trusted executable from a network location (whether share or via ASP.NET/web-server).

    You can use caspol to elevate the actual exe name itself - a la the "site" switch - to FullTrust.

    You can use "caspol -rsg" to check out the current policy for your exe.

    This is slightly different than elevating the strong name/key, in that IEExec will create the AppDomain with a sandbox/policy that matches your exe.

    Think of like adding the exact EXE path to your "Trusted Sites" in IE.

    Let me know if that works for you.

    Thanks!
    Stephen
    http://blogs.msdn.com/stfisher



  • Problem with Asserted Permissions