Avalon browser hosted applications get trust based on the zone from which they deploy. This means Xbaps coming from Internet zone get Internet zone permission only and ones from Intranet zone get Intranet zone permissions etc…
These applications don’t have support for permission elevation where user can choose to give higher privileges than ones that application can get based on zone of deployment. There are three ways applications can demand more trust that default permissionset allowed for the zone of deployment and demand can get satisfied.
- Deploy a custom CLR Security policy that modifies the default permissionset for the given zone
- Use a trusted publisher mechanism
- Use a fully trusted GAC‘ed assembly which allows partially trusted callers.
First way, is the most intrusive in terms of its impact. Only place it could be done is company intranet which is guaranteed to be secure. This means all the applications from anybody from that particular zone will get modified permission set. This can’t really work for Internet zone application because you would not deploy a custom CLR security policy on your machine that allows more trust to all the applications in the world.
Second way, is less intrusive than first one but it is still more open than the third one. By trusted publisher mechanism, you essentially say that all applications signed with that cert (which means all applications from particular publisher) can get permission set that they demand irrespective of their zone. This is still open check from end user’s perspective. because once this is granted anything from that publisher will run without a prompt. User needs to run full trust code (installer) on the machine to be able to do this.
Third way, can be less intrusive where installer runs to install a full trust assembly in the GAC which allows partially trusted callers. This in itself can be seen as worse than second option because GAC‘ed assembly that allows partially trusted caller means any code on Internet can call into that assembly. The security bar for this kind of assembly would/should be very high and it would mean you will need to think about not only bad used of your application calling that code but also *any* application calling that code. But you could lock down the code in this third way in such a way so that only your application and nobody else. It involves use of concept of Friend Assembly.
For this to work three things need to happen…
- Assembly needs to be in the GAC to be found by Partially Trusted Code
- Assembly needs to to have AllowPartiallyTrustedCallers (assembly level) attribute so that it can be called by Partially Trusted Code
- Assembly needs to be marked InternalsVisibleTo (Assembly level) attribute so that it can be ONLY called by your Partially Trusted Code.
Doing first part, is pretty straightforward because on dev machine it can be done by GACUTIL or on user’s machine it can be done by installer.
Second part involves putting a assembly level attribute. You could put this in AssemblyInfo.cs that VS generates. It looks something like this…
//allows partially trusted caller
Third part involves some more steps…
To use the InternalsVisibleTo in such a way that only your assembly can call into it, caller assembly needs to be strongly name signed. So lets say you will use FriendCaller.snk file that you can generate using sn.exe tool. You will use Public Key of that key to specific InternalsVisibleTo attribute. So it looks something like this…
//uses the strongname of the assembly to make internals visible
Note: I put line breaks to make it readable. In real code it would be one big line unless you have wrap set.
First part of the attribute is pretty straight forward, it is the name of your assembly without the extension (.dll or .exe etc).
Here is how you generate second part…
- sn -k FriendCaller.snk // Generate strong name key
- sn -p FriendCaller.snk key.publickey // Extract public key from key.snk into key.publickey
- sn -tp key.publickey > test.txt // dump the public key to text file instead of screen.
- Copy paste in the public Key = part of the code above
Apart from these attributes the only code that I had in my sample FriendsCallee.dll is
internal string PrivateFriendlyCall()
return (“My friend is calling me”);
so all the classese and methods in my assembly are internal so nobody else could call into it from outside. As part of the post build process I added Gacutil command so that it gets added to GAC on my machine automatically. On users machine it would be installer doing it. Since you need to put this assembly in the GAC, it also needs to be strongly named signed but since it is irrelevant here, I am skipping that part.
Here is what I did to create an application…
- Create an XBAP from Visual Studio Template.(Assembly name FriendCaller.exe)
- I will add reference to GAC’ed dll
- I will use the FriendCaller.snk to sign the assembly from Project/Properties Signing Tab.
Page1.xaml of my applications looks like this…
Page.xaml.cs looks like this…
public partial class Page1 : System.Windows.Controls.Page
void OnPageLoaded(object sender, RoutedEventArgs e)
FriendCallee.MyPrivateClass mp = new FriendCallee.MyPrivateClass();
this.lblMessage.Text = mp.PrivateFriendlyCall();
When you compile this application, I would have expected it to run and be able to call into a GAC’ed APTCA marked DLL even though I am calling internal method because FriendCaller.exe is friends with FriendsCallee.dll.
Unfortunately it did not work. CLR still threw security exception. For some reason, I needed to mark my application EXE (FriendCaller.exe) which was calling into that assembly also APTCA.
So when I added following code to AssemblyInfo.cs of my XBAP, it worked well as expected.
//allows partially trusted caller
I have not yet figured out why I needed to add it or if there is better way to do this but once I do, I will post it.
Till then…you have a work around.