|
security
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Assembly.Load fails after assembly preloaded using Assembly.LoadFrom (v1.1.4322)full trust. The second appdomain has a different ApplicationBase path then the host. I created a "DomainBroker" instance that implements MarshalByRefObject to instruct load and execute the less then full trust assemblies in the seperate domain so that the extra assembly will not be loaded into the hosting domain. This broker class is defined in the hosting assembly so the host assembly will be loaded into the second domain as well. I used AppDomain.CreateInstanceFromAndUnwrap(brokerType.Assembly.Location, brokerType.FullName) to create the broker and this works fine. However when I send a serializable object also defined in the host assembly to the broker it fails to deserialize with FileNotFoundExcetion because it cannot find the hosting assembly, which is already loaded into the remote domain. I discovered it seems that when LoadFrom(path) is used, future resolutions for that same assembly using Assembly.Load(fullname) will still fail. Here is a simple test that demonstrates the issue: Create anotherAssembly.dll just a basic new class library solution with a strong name. Then create a console app with the following code: using System.Reflection; class Class1 { [STAThread] static void Main(string[] args) { try { Test(); Console.WriteLine("TEST PASSED"); } catch(System.Exception ex) { Console.WriteLine("TEST FAILED"); Console.WriteLine(ex.ToString()); } Console.ReadLine(); } static void Test() { string anotherAssemblyLocation = "../../../AnotherAssembly/bin/debug/AnotherAssembly.dll"; Assembly anotherAssembly = Assembly.LoadFrom(anotherAssemblyLocation); if(!IsLoaded(anotherAssembly.FullName)) throw new ApplicationException("Assembly is not loaded"); if(anotherAssembly.GetName().GetPublicKey().Length == 0) throw new ApplicationException("Assembly does not have strong name"); Assembly.Load(anotherAssembly.FullName); } static bool IsLoaded(string assemblyName) { foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { if(a.FullName == assemblyName) return true; } return false; } } The LoadFrom works fine I verify that it has been loaded into the domain (however pointless this seems) and that it has a strong name. When assembly Assembly.Load() (as I'm assuming the serilizer is doing when I pass my across my host object) fails even when the assembly is already loaded. I've also created another test where anotherAssembly.dll is placed in the application directory or GAC and the result is that the assembly is loaded into the application domain twice. Is this a bug? or is there a good reason why the framework behaves this way? There are a couple of solutions I've found: Place the host assembly in the GAC and use Load instead of LoadFrom (to prevent loading same assembly twice). Disadvantage: Additional deployment steps and requires admin rights to update GAC (so much for using a post-build script when running VS as least privalaged user! well I guess I can write a post build utility to impersonate admin before running gacutil.. there's always something to making LPU dev more difficult then it needs be..., anyway) Copy the host assembly to the ApplicationBase directory of the secondary domain. Disadvantage: versioning nightmare if not kept in sync, and deserialization will fail; Restricting CAS permissions with Url security policy doens't seem to work correctly. (I found that if I create a level final code group with url policy file://scriptdir/* with only execution permission and a child code group with file://scriptdir/hostassembly.dll with fulltrust then hostassembly.dll still only recieves execute permission not the union of fulltrust and execution... even though evaluate assembly policy shows the hostassembly code group being applied.. perhaps I missed something, anyways the first reason is bad enough). Create an AssemblyResolve event handler with this pointless looking code: foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies()) { if(args.Name == a.FullName && a.GetName().GetPublicKey().Length > 0) return a; } return null; Disadvantage: Only runs after resolution fails thus slightly degrading performance; and ? (is there some valid reason the Assembly.Load does not check the currently loaded assemblies, a security issue perhaps? and would doing this expose that vunerability? without strong name I might see this being an issue where a fulltrust assembly loads an assembly from a different path into the app domain and then a non-fulltrust assembly attempts to use a differenet assembly with same name from its applicationbase but instead gets the preloaded one, so I guess that could be bad. However, with a strong named assembly I don't see this being an issue?) Thanks, - Kurt <kurbylo***@hotmail.com> wrote in message
news:1109915702.864652.123600@o13g2000cwo.googlegroups.com... <snip>> Is this a bug? or is there a good reason why the framework behaves this Your LoadFrom/Load test is behaving as I would expect given that the target > way? assembly is not located in a Fusion search location for the Load call. As for the double-loading, it's quite normal. See http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx for more information concerning both of these behaviours. > It's quite normal to require that applications that are to be run as LPU be > There are a couple of solutions I've found: > Place the host assembly in the GAC and use Load instead of LoadFrom (to > prevent loading same assembly twice). > Disadvantage: Additional deployment steps and requires admin rights to > update GAC (so much for using a post-build script when running VS as > least privalaged user! well I guess I can write a post build utility to > impersonate admin before running gacutil.. there's always something to > making LPU dev more difficult then it needs be..., anyway) installed while running as an admin. Besides allowing actions such as GACing, it also ensure that the application files cannot be altered by LPUs (at least under default ACLs on program files directory on appropriate OSes). > Copy the host assembly to the ApplicationBase directory of the What's the versioning issue? The file is presumably written once at > secondary domain. > Disadvantage: versioning nightmare if not kept in sync, and > deserialization will fail; installation time. When you prepare patch/upgrade deployments, your testing should very quickly catch any problems due to failure to copy the assembly to both locations. > Restricting CAS permissions with Url Not sure I really understand what you're getting at here. If this is still > security policy doens't seem to work correctly. (I found that if I > create a level final code group with url policy file://scriptdir/* with > only execution permission and a child code group with > file://scriptdir/hostassembly.dll with fulltrust then hostassembly.dll > still only recieves execute permission not the union of fulltrust and > execution... even though evaluate assembly policy shows the > hostassembly code group being applied.. perhaps I missed something, > anyways the first reason is bad enough). a problem, could you please post sample code for a simple repro? > Create an AssemblyResolve event handler with this pointless looking Two assemblies with equivalent strong names are not guaranteed to be > code: > foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies()) > { > if(args.Name == a.FullName && a.GetName().GetPublicKey().Length > 0) > return a; > } > return null; > > Disadvantage: Only runs after resolution fails thus slightly degrading > performance; and ? identical under all circumstances. The folks who worked on the Fusion mechanism presumably spent a great deal of time thinking about all the repercussions alternative behaviours of Load, and it might be best to trust that they made the right decisions even if it's inconvenient... Show quoteHide quote > (is there some valid reason the Assembly.Load does > not check the currently loaded assemblies, a security issue perhaps? > and would doing this expose that vunerability? without strong name I > might see this being an issue where a fulltrust assembly loads an > assembly from a different path into the app domain and then a > non-fulltrust assembly attempts to use a differenet assembly with same > name from its applicationbase but instead gets the preloaded one, so I > guess that could be bad. However, with a strong named assembly I don't > see this being an issue?) > > Thanks, > > - Kurt > Nicole Calinoiu wrote:
> <kurbylo***@hotmail.com> wrote in message call. As> news:1109915702.864652.123600@o13g2000cwo.googlegroups.com... > <snip> > > Is this a bug? or is there a good reason why the framework behaves this > > way? > > Your LoadFrom/Load test is behaving as I would expect given that the target > assembly is not located in a Fusion search location for the Load Show quoteHide quote > for the double-loading, it's quite normal. See Okay not a "versioning nightmare" wrong words, a "deployment concern".> http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx for more > information concerning both of these behaviours. > > > > > There are a couple of solutions I've found: > > Place the host assembly in the GAC and use Load instead of LoadFrom (to > > prevent loading same assembly twice). > > Disadvantage: Additional deployment steps and requires admin rights to > > update GAC (so much for using a post-build script when running VS as > > least privalaged user! well I guess I can write a post build utility to > > impersonate admin before running gacutil.. there's always something to > > making LPU dev more difficult then it needs be..., anyway) > > It's quite normal to require that applications that are to be run as LPU be > installed while running as an admin. Besides allowing actions such as > GACing, it also ensure that the application files cannot be altered by LPUs > (at least under default ACLs on program files directory on appropriate > OSes). > > > > Copy the host assembly to the ApplicationBase directory of the > > secondary domain. > > Disadvantage: versioning nightmare if not kept in sync, and > > deserialization will fail; > > What's the versioning issue? The file is presumably written once at > installation time. When you prepare patch/upgrade deployments, your testing > should very quickly catch any problems due to failure to copy the assembly > to both locations. > The concern is essentially that the exact same version of the file must exist in 2 seperate physical locations and both must be exactly the same or the application will not run properly. Tus easily be caught during testing. As you said this only needs to be done once during installation but also included in any patch/upgrade deployments, my mistake. It is still a disadvantage as if I must have to have 2 copies of the same file I'd much rather use the GAC. Show quoteHide quote > Create a folder c:\scriptdir> > Restricting CAS permissions with Url > > security policy doens't seem to work correctly. (I found that if I > > create a level final code group with url policy file://scriptdir/* with > > only execution permission and a child code group with > > file://scriptdir/hostassembly.dll with fulltrust then hostassembly.dll > > still only recieves execute permission not the union of fulltrust and > > execution... even though evaluate assembly policy shows the > > hostassembly code group being applied.. perhaps I missed something, > > anyways the first reason is bad enough). > > Not sure I really understand what you're getting at here. If this is still > a problem, could you please post sample code for a simple repro? Create a strong named assembly and place it in the directory. Open the .Net configuration tool Create a URL CodeGroup file://c:/scriptdir/* with execute permission set. Check level final. Create a child code group using strongname permission and import public key from the assembly placed in the directory, grant full trust. Using the Evaluate Assemlby select the strong named assembly previously copied to this directory. It should have recieved the FullTrust (union of Execute and FullTrust), however it only recieves execute permission. This is the code group section from the policy file, obviously your strong name will differ so if you copy and paste you'll need to update that. <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="All_Code" Description="Code group grants all code full trust and forms the root of the code group tree."> <IMembershipCondition class="AllMembershipCondition" version="1"/> <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="Execution" Attributes="Exclusive" Name="ScriptDir" Description=""> <IMembershipCondition class="UrlMembershipCondition" version="1" Url="file://C:/scriptdir/*"/> <CodeGroup class="UnionCodeGroup" version="1" PermissionSetName="FullTrust" Name="ScriptHost" Description="FullTrust to host assembly"> <IMembershipCondition class="StrongNameMembershipCondition" version="1" PublicKeyBlob="0024000004800000940000000602000000240000525341310004000001000100E7D3DD7E620B266EA32514C042881CE1905B0CCC968DC543B20286740D3B881B3BCCE3FB6EBC4B256DAB41512BE874B33658683CDCCF47D1A4532E60D54B7F1E6432B9700AC319FAF2B4592D4C13D146913395E19C64BB4DF474227855952D5F5E191DDFC1ECA667B5D52C6D08480D2579A9B1C868796227343EF44856B72ACC"/> </CodeGroup> </CodeGroup> </CodeGroup> Show quoteHide quote > I was looking for a bit more than "presumably thought of" as if MS> > > Create an AssemblyResolve event handler with this pointless looking > > code: > > foreach(Assembly a in AppDomain.CurrentDomain.GetAssemblies()) > > { > > if(args.Name == a.FullName && a.GetName().GetPublicKey().Length > 0) > > return a; > > } > > return null; > > > > Disadvantage: Only runs after resolution fails thus slightly degrading > > performance; and ? > > Two assemblies with equivalent strong names are not guaranteed to be > identical under all circumstances. The folks who worked on the Fusion > mechanism presumably spent a great deal of time thinking about all the > repercussions alternative behaviours of Load, and it might be best to trust > that they made the right decisions even if it's inconvenient... > thinks of everything. I don't think that the possiblility of two assemblies with the same strong name was the underlying issue however, otherwise I would think Fusion not check the GAC before probing the applicatonbase if a conflict were to occur then I would choose to use assembly deployed with the app vs the one in the gac deployed by whomever. I also would not have expected the security team to use the StrongNameMembershipCondition as a source of evidence to grant full trust to the system assemblies. I suspect the issue is rather subtle if it is an issue at all, which I suspect not. The duplicate loading is probably not only expected but desired for non-strongnamed assembiles, my suspision is that loading two instances of a strong-named assembly into the same appdomain is unnecessary but because it was desired for non-strong named assemblies there did not seem to be any reason not allow strong-named to be loaded twice even if unnecessary it probably was not thought of (aside from the small amount of extra memory usage) to have any observable affects to the application. So personally I think its a bug. Although minor concidering I can use the GAC, so I guess I'll quit whining and just place the assembly in the GAC. The link you provided also mentioned another source used during Load that even though I probably read this artical two or three times the last few days I didn't notice before... "..., a host assembly store (if hosted),..." It sounds like that is exactly what I need, but I don't see a "HostAssemblyStore" or something like it in AppDomainSetup class, any idea how this store(location/path?) is set or how assemblies added to it? Show quoteHide quote > > > (is there some valid reason the Assembly.Load does > > not check the currently loaded assemblies, a security issue perhaps? > > and would doing this expose that vunerability? without strong name I > > might see this being an issue where a fulltrust assembly loads an > > assembly from a different path into the app domain and then a > > non-fulltrust assembly attempts to use a differenet assembly with same > > name from its applicationbase but instead gets the preloaded one, so I > > guess that could be bad. However, with a strong named assembly I don't > > see this being an issue?) > > > > Thanks, > > > > - Kurt > > <kurbylo***@hotmail.com> wrote in message
news:1109957195.859924.19410@g14g2000cwa.googlegroups.com... <snip>> Okay not a "versioning nightmare" wrong words, a "deployment concern". Your application, your call. Personally, I suspect that I would prefer to > The concern is essentially that the exact same version of the file must > exist in 2 seperate physical locations and both must be exactly the > same or the application will not run properly. Tus easily be caught > during testing. As you said this only needs to be done once during > installation but also included in any patch/upgrade deployments, my > mistake. It is still a disadvantage as if I must have to have 2 copies > of the same file I'd much rather use the GAC. use a different assembly entirely as the "director" in the second app domain, but that's a different discussion entirely. <g> > Create a folder c:\scriptdir You marked the parent group as final, so why are you expecting the child > Create a strong named assembly and place it in the directory. > Open the .Net configuration tool > Create a URL CodeGroup file://c:/scriptdir/* with execute permission > set. > Check level final. > Create a child code group using strongname permission and import public > key from the assembly placed in the directory, grant full trust. > Using the Evaluate Assemlby select the strong named assembly previously > copied to this directory. It should have recieved the FullTrust (union > of Execute and FullTrust), however it only recieves execute permission. group to be considered at all? If you don't mark the URL group as final, the assembly should be granted full trust. Of course, under default policy, it would have been granted full trust anyway since it's running from a local drive. > I was looking for a bit more than "presumably thought of" as if MS Sorry about that. I'd been having a discussion elsewhere with someone who > thinks of everything. was being rather obstinate about a particular design decision in which he hadn't participated, and I guess my frustration about that unrelated issue leaked through to my post... > I don't think that the possiblility of two I get the impression that Microsoft folks think that the GACed assembly is > assemblies with the same strong name was the underlying issue however, > otherwise I would think Fusion not check the GAC before probing the > applicatonbase if a conflict were to occur then I would choose to use > assembly deployed with the app vs the one in the gac deployed by > whomever. likely to be more reliable than the one deployed in whatever directory might happen to be used by any given applicatio. Of course, if you go the route of using the GAC as your deployment point, your chances of using the same assembly in both app domains does increase considerably. <g> > I also would not have expected the security team to use the It's actually just a backup (presumably in folks naively meddle with the > StrongNameMembershipCondition as a source of evidence to grant full > trust to the system assemblies. policy) since all local code is fully trusted by default. Personally, I think full trust by default is even worse than the use of the StrongNameMembershipCondition, but ymmv... > I suspect the issue is rather subtle You might want to keep in mind that this is a mechanism that is primarily > if it is an issue at all, which I suspect not. The duplicate loading > is probably not only expected but desired for non-strongnamed > assembiles, my suspision is that loading two instances of a > strong-named assembly into the same appdomain is unnecessary but > because it was desired for non-strong named assemblies there did not > seem to be any reason not allow strong-named to be loaded twice even if > unnecessary it probably was not thought of (aside from the small amount > of extra memory usage) to have any observable affects to the > application. So personally I think its a bug. Although minor > concidering I can use the GAC, so I guess I'll quit whining and just > place the assembly in the GAC. meant to support remoting, where there's no reason to expect that both app domains would be using the same source assembly. Given this, I would tend to see your prefered behaviour as an unsupported scenario rather than viewing the double-loading as a bug. > The link you provided also mentioned another source used during Load I believe that she's referring to hosting of the CLR (e.g.: > that even though I probably read this artical two or three times the > last few days I didn't notice before... "..., a host assembly store > (if hosted),..." > It sounds like that is exactly what I need, but I don't see a > "HostAssemblyStore" or something like it in AppDomainSetup class, any > idea how this store(location/path?) is set or how assemblies added to > it? http://msdn.microsoft.com/msdnmag/issues/01/03/clr/default.aspx). Not necessarily something you want to be doing just to avoid double-loading... > I've run into the same issue before. You might be able to use codebase hints > > The LoadFrom works fine I verify that it has been loaded into the > domain (however pointless this seems) and that it has a strong name. > When assembly Assembly.Load() (as I'm assuming the serilizer is doing > when I pass my across my host object) fails even when the assembly is > already loaded. I've also created another test where > anotherAssembly.dll is placed in the application directory or GAC and > the result is that the assembly is loaded into the application domain > twice. in the app.config file to tell the fusion layer where to look when locating assemblies.
API to access loaded assembly hash
Medium Level Trust and Reflection Active Directory Machine Account Permissions Make Security to Directory DESCryptoServiceProvider Authentication/Impersonation Inconsistency Encrypting data using System.Security.Cryptography/ Decrypting w/PGP Assymetric Encryption - Interorperability between Java2, .NET and Openssl XmlSerialization of classes with declarative Security Windows user controls in a web page: Security |
|||||||||||||||||||||||