Code Access Security


.NET brings with it a new security model for deployed code. Instead of an assembly getting the permissions of the process running the code, the .NET Code Access Security (CAS) model grants code permissions based on where the code originates. [2] To view the current permission settings on your machine, use the Microsoft .NET Framework Configuration tool (available in your Administration Tools menu). Drilling into the Permission Sets for the Machine's Runtime Security Policy reveals a number of entries, including FullTrust, LocalIntranet, Internet, and so on. Figure 15.3 shows the set of Internet permissions.

[2] For a much more detailed discussion of CAS, you'll want to read Essential .NET (Addison-Wesley, 2003), by Don Box, with Chris Sells.

Figure 15.3. Default Internet Permission Set

Table 15.1 compares the LocalIntranet permission set to the Internet permission set.

Assemblies are associated with a permission set in any number of ways: according to the publisher, the site, the strong name , the security zone, and so on. Most of the default code groups associate code with a zone. For example, the My_Computer_Zone is associated with the FullTrust permission set, and the Local_Intranet_Zone is associated with the LocalIntranet permission set. In release 1.0 of .NET, the Internet_Zone was associated with the Internet permission set, but as of service pack 1 of the .NET runtime, code from the Internet_Zone is associated with the Nothing permission set by default. This change in SP1 reflects some doubt that Microsoft had as to the full safety of the .NET Framework Class Library code. As of .NET 1.1, the doubts have been resolved, and the Internet_Zone is again associated with the Internet permission set.

Table 15.1. Intranet and Internet CAS Permissions

Permission

Level

LocalIntranet

Internet

FileDialog

Unrestricted

Yes

No

FileDialog

Access=Open

Yes

Yes

IsolatedStorageFile

Allow=AssemblyIsolationByUser

Yes

No

IsolatedStorageFile

Allow=DomainIsolationByUser

Yes

Yes

Printing

Level=DefaultPrinting

Yes

No

Printing

Level=SafePrinting

Yes

Yes

Reflection

Flags=ReflectionEmit

Yes

No

Security

Flags=Assertion

Yes

No

Security

Flags=Execution

Yes

Yes

UI

Unrestricted

Yes

No

UI

Clipboard=OwnClipboard

Yes

Yes

UI

Window=SafeSubWindows

Yes

Yes

UI

Window=SafeTopLevelWindows

Yes

Yes

Web

Connect=http to originating site

Yes

Yes

Web

Connect= https to originating site

Yes

Yes

The zone where an assembly originates is determined by the path used to find the assembly, as shown in Table 15.2.

If an assembly needs to know the zone it's running in, it can access the zone via the Zone class in System.Security.Policy:

 using System.Security; using System.Security.Policy; ... string appbase = AppDomain.CurrentDomain.BaseDirectory; SecurityZone zone = Zone.CreateFromUrl(appbase).SecurityZone; 

By default, the loaded assembly gets the union of all the permissions from all the code groups to which it belongs and must live within the confines of those permissions. Any attempt to perform an action for which the assembly does not have the corresponding permission will result in a security exception.

Checking for Permissions

Although an application can catch a SecurityException if it violates its set of permissions, it can also check first to see whether it's got the permissions it's after. This allows an application to downgrade its capabilities if appropriate permissions aren't available. Checking for permission is a matter of creating a permission object, demanding that permission, and catching the security exception if the demand fails.

Table 15.2. How an Assembly's Zone Is Determined

Path

Example

Zone

Local file

c:\ foo\foo.exe

MyComputer

UNC name or non- dotted site URL

\\server\foo\foo.exe or http://server/foo/foo.exe or http://localhost/foo/foo.exe or z:\foo\foo.exe if z is mapped to a network share

LocalIntranet

All numeric IP address or dotted-site URL

http://1115768663/foo/foo.exe or http://www.sellsbrothers.com/foo/foo.exe or http://127.0.0.1/foo/foo.exe

Internet

For example, to check whether your control is allowed to fire an event into unmanaged code, you use an instance of the SecurityPermission class from the System.Security.Permissions namespace:

 using System.Security; using System.Security.Permissions;  bool HavePermission(IPermission perm) {   try { perm.Demand(); }   catch( SecurityException ) { return false; }   return true;   }  void label1_Click(object sender, EventArgs e) {  SecurityPermissionFlag flag = SecurityPermissionFlag.UnmanagedCode;   SecurityPermission perm = new SecurityPermission(flag);   if( !HavePermission(perm) ) return;  ... // Fire event } 

If you wonder which permission you need for a specific call, you should start with the security exception itself. Unfortunately, unlike most other exceptions in .NET, the security exception provides somewhat terse information. That's to prevent bad people from learning too much about an application's implementation, although it does tend to make debugging security exceptions a bit harder. In these cases, I check the documentation, which is surprisingly good about telling you which permissions are needed and when. [3]

[3] To check on all kinds of details, including permissions, for a WinForms control hosted in IE, you might try adjusting the undocumented DebugIEHost Registry setting as discussed at http://discuss.develop.com/archives/wa.exe?A2=ind0109A&L=DOTNET&P=R9256.

Awarding Permissions

Even if your assembly has permission to perform an action, such as calling unmanaged code, it's not necessarily the case that another assembly calling your assembly has those permissions. CAS is set up so that a request for a permission will be denied unless everyone in the call chain has the needed permission. For example, even if an assembly hosted in IE has permission to call into unmanaged code, as of .NET 1.x the managed code hosting that assembly does not have that permission. If the control needs to exercise a permission that the code above it in the call chain doesn't have, the control must grant the permission it has to everyone hosting it. You do this using the Assert method on the permission object:

 void label1_Click(object sender, EventArgs e) {   // Make sure we have permission to call unmanaged code  SecurityPermissionFlag flag = SecurityPermissionFlag.UnmanagedCode;   SecurityPermission perm = new SecurityPermission(flag);  if( !HavePermission(perm) ) return;  // Grant managed hosting code permission to call unmanaged code   perm.Assert();  if( OuchEvent != null ) OuchEvent(10); } 

In this code, we create a permission object again, but after checking to make sure we have the appropriate permission, we also grant that permission, albeit temporarily, until the method returns. In general, granting permissions in this way is a really bad idea and should be used only in a very narrow scope. The reason that .NET is checking everyone in the call chain is to make sure that bad assemblies don't coerce good assemblies into performing their evil deeds. By asserting permission, you're telling .NET that you'll vouch for everyone in the call chain ”a weighty responsibility to take onto your shoulders.



Windows Forms Programming in C#
Windows Forms Programming in C#
ISBN: 0321116208
EAN: 2147483647
Year: 2003
Pages: 136
Authors: Chris Sells

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net