Configuring Security



Configuring Security

Implement security for a Windows service, a serviced component, a .NET Remoting object, and an XML Web service.

The .NET Framework offers a wide variety of security features. You can choose to run your machine in wide-open mode, with every user allowed to execute any .NET code, or you can lock down things selectively. You can control which programs have access to which resources, or which users have the right to execute which programs.

Broadly speaking, .NET security breaks down into two separate areas:

  • Code access security— This type of security manages the security of .NET source code itself. You can tell the .NET Framework the resources your code needs to execute properly, and the .NET Framework will check for permission to access those resources on the machine at runtime. Code access security is very flexible and includes the capability to define your own sets of necessary permissions. Code access security can also be used by administrators to ensure that undesired code never gets the chance to run on a system.

  • Role-based security— This type of security manages the user rather than the code. Using role-based security allows you to provide (or deny) access to resources based on an identity provided by the user running the code. In practical terms, this means you can limit program execution to particular users or groups on the computer.

I'll cover both these types of security in this chapter, beginning with code access security. The .NET Framework also includes other security features, notably public key and private key encryption, which are not a part of the 70-320 exam.

Understanding Code Access Security

Code access security controls what code can do on your computer. Code access security is centered around permissions to use resources. The .NET Framework has an entire object-oriented system for managing code access security and the associated permissions. In the following sections, you'll learn about concepts involved in code access security:

  • Permissions

  • Code groups

  • Permission sets

You'll also learn how to manage code access security. In particular, code can request permissions on a very fine-grained scale, and the administrator can choose to allow permissions on an equally fine-grained scale.

Understanding Permissions

Code access security is based on specific permissions that the Common Language Runtime (CLR) can grant to or deny from code. For example, the authorization to read or write information in the Windows Registry requires the RegistryPermission permission on that part of your code. As you'll see later in the chapter, code can make four different types of permission requests:

  • It can request the minimum permissions that it requires to run.

  • It can request optional permissions that it would like but does not require.

  • It can refuse permissions to ensure that it does not have access to particular resources.

  • It can demand permissions on the part of calling code.

The CLR decides, based on a variety of factors (including the origin of the code and the information in the machine and application configuration files), whether a particular permission should be granted. If a piece of code is unable to obtain the minimum permissions that it requires, that piece of code does not execute. The security settings of the computer determine the maximum permissions that code can be granted, but code is allowed to request (and receive) fewer permissions than the maximum.

The .NET Framework groups permissions into three types:

  • Code access permissions represent access to a protected resource or the capability to perform a protected operation.

  • Identity permissions represent access based on credentials that are a part of the code itself.

  • Role-based permissions represent access based on the user who is running the code.

Each permission in the .NET Framework is represented by a particular class that derives from System.Security.CodeAccessPermission. Figure lists the permissions, which are the most important for controlling the actions that code can take on a particular computer.

Code Access Permissions in the .NET Framework

Permission

Explanation

DirectoryServicesPermission

Controls access to the System.DirectoryServices namespace.

DnsPermission

Controls access to domain name system (DNS) services.

EnvironmentPermission

Controls access to environment variables.

EventLogPermission

Controls access to the Windows event log.

FileDialogPermission

Controls access to files selected from the Open dialog box.

FileIOPermission

Controls access to reading and writing files and directories.

IsolatedStorageFilePermission

Controls access to private virtual file systems.

IsolatedStoragePermission

Controls access to generic isolated storage.

MessageQueuePermission

Controls access to message queuing via MSMQ.

OleDbPermission

Controls access to data via the System.Data.OleDb namespace.

PerformanceCounterPermission

Controls access to performance counters.

PrintingPermission

Controls access to printers.

ReflectionPermission

Controls access to the reflection features of .NET.

RegistryPermission

Controls access to the Windows Registry.

SecurityPermission

Controls access to unmanaged code.

ServiceControllerPermission

Controls access to starting and stopping services.

SocketPermission

Controls access to Windows sockets.

SqlClientPermission

Controls access to data via the System.Data.SqlClient namespace.

UIPermission

Controls access to the user interface.

WebPermission

Controls access to making Web connections.

NOTE

Custom Permissions If none of the code access permissions in Figure are quite right for your application, you can also define custom permissions. Custom permissions are discussed later in this chapter, in the section "Using Custom Security Attributes."


Requesting Minimum Permissions

To start working in the .NET security framework, your code can request the minimum permissions that it needs to function correctly. Step-by-Step 11.1 demonstrates the syntax for making such a request.

STEP BY STEP

11.1 Requesting Minimum Permissions

  1. Launch Visual Studio .NET. Select File, New, Blank Solution and name the new solution 320C11.

  2. Add a new Visual C# .NET Windows application named StepByStep11_1 to the solution.

  3. In the Solution Explorer, rename the default Form1.cs to StepByStep11_1.cs. Open the form in code view and change all occurrences of Form1 to refer to StepByStep11_1 instead.

  4. Place a Label control, a TextBox control (txtFileName), and a Button control (btnGetFile) on the form. Add an OpenFileDialog component (dlgOpen). Figure shows a design for this form.

    1. Design a form that requests the minimum permissions required to run this form.

    graphics/11fig01.jpg

  5. Switch to the code view and add the following code at the top after the using directives:

    
    using System.Security.Permissions;
    
    [assembly:FileDialogPermissionAttribute(
    
        SecurityAction.RequestMinimum, Unrestricted=true)]
    
    
  6. Double-click the Button control and add the following code to handle the Click event of the Button control:

    
    private void btnGetName_Click(object sender,
    
         System.EventArgs e)
    
    {
    
        try
    
        {
    
            if(dlgOpen.ShowDialog() == DialogResult.OK)
    
                txtFileName.Text = dlgOpen.FileName;
    
        }
    
        catch (Exception ex)
    
        {
    
            MessageBox.Show("Exception: " + ex.Message);
    
        }
    
    }
    
    
  7. Compile the project. Launch the executable file from Windows Explorer (you'll find it in the project's bin\Debug directory) and verify that you can browse for a file.

The code in Step-by-Step 11.1 requests permissions by applying an attribute to an assembly. The FileDialogPermissionAttribute enables the assembly to request the FileDialogPermission permission, which in turn allows access to the system's file dialog boxes. In this particular case, the code runs without any problem, which means that it was granted the requested permission. By default you have full permissions to run any code that originates on your own computer. To see code access security in action, you need to learn how to manage the permissions granted to code on your computer. But first, you need to understand the concepts of code groups and permission sets.

Code Groups and Permission Sets

A code group is a set of assemblies that share a security context. You define a code group by specifying the membership condition for the group. Every assembly in a code group receives the same permissions from that group. However, because an assembly could be a member of multiple code groups, two assemblies in the same group might end up with different permissions.

The .NET Framework supports seven different membership conditions for code groups:

  • Application directory— The application directory membership condition selects all the code in the installation directory of the running application.

  • Cryptographic hash— The cryptographic hash membership condition selects all the code that matches a specified cryptographic hash. Practically speaking, this is a way to define a code group that consists of a single assembly.

  • Software publisher— The software publisher membership condition selects all the code from a specified publisher, as verified by Authenticode signing.

    NOTE

    Cryptographic Hashing To calculate a cryptographic hash, the compiled code of an assembly is run through a cryptographic algorithm that generates a string of digits as a result. The string of digits is much shorter than the original assembly, and is therefore easier to evaluate. If you run the same assembly through the algorithm, you get the same hash out, but two different assemblies are extremely unlikely to generate an identical hash value.


  • Site— The site membership condition selects all the code from a particular Internet domain.

  • Strong name— The strong name membership condition selects all the code that has a specified strong name.

  • URL— The URL membership condition selects all the code from a specified URL.

  • Zone— The zone membership condition selects all the code from a specified security zone (Internet, local intranet, Trusted sites, My Computer, or Untrusted sites).

Permissions are granted in permission sets. A permission set is a set of one or more code access permissions that are granted as a unit. If you want to grant only a single permission, you must construct a permission set that contains only that single permission; you can't grant permissions directly. The .NET Framework supplies seven built-in permission sets:

  • Nothing— The Nothing permission set grants no permissions.

  • Execution— The Execution permission set grants permission to run but not to access protected resources.

  • Internet— The Internet permission set grants limited permissions designed for code of unknown origin.

  • LocalIntranet— The LocalIntranet permission set grants high permissions designed for code within an enterprise.

  • Everything— The Everything permission set grants all permissions except for the permission to skip verification.

  • SkipVerification— The SkipVerification permission set grants the permission to skip security checks.

  • FullTrust— The FullTrust permission set grants full access to all resources. This permission set includes all permissions.

You can also create your own custom permission sets, as described in the "Granting Permission" section.

Granting Permission

The easiest way to grant or deny permissions in the .NET Framework is to use the Microsoft .NET Framework Configuration tool, as in Step-by-Step 11.2.

STEP BY STEP

11.2 Granting Permissions by Using the .NET Framework Configuration Tool

  1. Open the Microsoft .NET Framework Configuration tool from the Administrative Tools section of the Windows Control Panel.

  2. Expand the Runtime Security node, then the User node, and then the Permission Sets node to see the built-in .NET permission sets.

  3. Right-click the Everything permission set and select Duplicate. A new permission set named Copy of Everything is created.

  4. Right-click the Copy of Everything permission set and select Rename. Rename the permission set No FileDialog.

  5. With the No FileDialog permission set selected, click the Change Permissions link in the right panel of the configuration tool. In the Create Permission Set dialog box, select File Dialog and click Remove. Click Finish to save your changes.

  6. Expand the Code Groups node and click the default All Code code group. Click the Add a Child Code Group link in the right panel of the configuration tool.

  7. In the Create Code Group dialog box, name the new group StepByStep11_1. Enter a description and click Next.

  8. Choose the Hash condition. Click the Import button and browse to StepByStep11_1.exe. Click Open to calculate the hash for this file. Click Next.

  9. Select the No FileDialog permission set and click Next. Click Finish to create the new code group.

  10. Right-click the StepByStep11_1 code group and select Properties. Check the box to make this code group exclusive, as shown in Figure. Click OK.

    2. You can create a code group and grant or deny permissions in a GUI interface by using the Microsoft .NET Framework Configuration tool.

    graphics/11fig02.jpg

  11. Run the StepByStep11_1.exe application by double-clicking it in Windows Explorer. A policy exception error box appears, indicating that the code cannot be run. Click No to dismiss the error box.

In Step-by-Step 11.2, you first create a permission set (based on the built-in Everything permission set) that includes every permission except for the permission to use the file dialog boxes. You then create a code group that contains the executable file for the StepByStep11.1 example, and then you assign the No FileDialog permission set to this code group. The result is that the code cannot run because it requires at a minimum the one permission that the new security policy cannot grant to it.

Imperative Security

Requesting permissions through the use of attributes is known as declarative security. There's a second method to request permissions, known as imperative security. With imperative security, you create objects to represent the permissions that your code requires (see Step-by-Step 11.3). Guided Practice Exercise 11.1 will give you additional practice with imperative security.

NOTE

Recalculate Hash If you create a code group with the cryptographic hash membership condition, you need to recalculate the hash whenever you make a change in the code. Compiling the project with changed code results in a different hash value than the one that you calculated previously (while creating a code group).

You can recalculate the hash by using the Microsoft .NET Framework Configuration tool. Locate the node for the code group and then right-click the code group and select Properties. On the Membership Condition tab, select Import. Browse to the project's executable file, click Open, and then click OK.


STEP BY STEP

11.3 Imperative Security

  1. Add a new Visual C# .NET Windows application named StepByStep11_3 to the solution.

  2. In the Solution Explorer, rename the default Form1.cs to StepByStep11_3.cs. Open the form in code view and change all occurrences of Form1 to refer to StepByStep11_3 instead.

  3. Place a Label control, a TextBox control (txtFileName), and a Button control (btnGetFile) on the form. Add an OpenFileDialog component (dlgOpen). You can reuse the design from Figure for this form.

    EXAM TIP

    Command-line Permissions The .NET Framework SDK also includes the Code Access Security Policy tool, caspol.exe, that can manipulate code groups and permission sets from the command line. If you're trying to automate security operations, you can make good use of this tool from a batch file.

  4. Switch to the code view and add the following using directive:

    
    using System.Security.Permissions;
    
    
  5. Add this code to allow the user to browse for a filename when he clicks the button:

    
    private void btnGetName_Click(object sender,
    
        System.EventArgs e)
    
    {
    
        try
    
        {
    
            FileDialogPermission fdp = new
    
            FileDialogPermission(
    
                  PermissionState.Unrestricted);
    
            // Check to see whether the code
    
            // has the specified permission
    
            fdp.Demand();
    
    
    
            if(dlgOpen.ShowDialog() == DialogResult.OK)
    
                txtFileName.Text = dlgOpen.FileName;
    
        }
    
        catch(Exception ex)
    
        {
    
            MessageBox.Show("Exception: " + ex.Message);
    
        }
    
    }
    
    
  6. Compile the project. Launch the executable file from Windows Explorer and verify that you can browse for a file.

  7. Run the Microsoft .NET Framework Configuration tool. Expand the Runtime Security node, then the User node, and then the Code Groups node and click the default All Code code group. Click the Add a Child Code Group link in the right panel of the configuration tool.

  8. In the Create Code Group dialog box, name the new group StepByStep11_3. Enter a description and click Next.

  9. Choose the Hash condition. Click the Import button and browse to StepByStep11_3.exe. Click Open to calculate the hash for this file. Click Next.

  10. Select the No FileDialog permission set (created in Step-by-Step 11.2) and click Next. Click Finish to create the new code group.

  11. Right-click the StepByStep11_3 code group and select Properties. Check the first check box to make this code group exclusive. Click OK.

  12. Launch the StepByStep11_3.exe file from Windows Explorer again. Click the Get File button. You'll see the security exception shown in Figure.

    3. An exception is generated if the requested permission cannot be granted according to the security policy's current setting.

    graphics/11fig03.jpg

In Step-by-Step 11.3 you construct a FileDialogPermission object that represents unrestricted access to the file dialog boxes. It then calls the Demand() method of that object to demand the permission from the operating system. When the security policy is such that the permission cannot be granted, the code throws an exception.

EXAM TIP

Imperative Versus Declarative Security The only time you absolutely have to use imperative security is when you need to make security decisions based on factors that are known only at runtime, such as the name of a particular file. In many other cases declarative security is easier to use.


Computing Permissions

Determining the actual permissions applied to any given piece of code is a complex process. To begin the process, you should think about permissions at the Enterprise level only. The CLR starts by examining the evidence that a particular piece of code presents to determine its membership in code groups at that level. Evidence is just an overall term for the various identity permissions (publisher, strong name, hash, and so on) that can go into code group membership.

Code groups are organized into a hierarchy; in Step-by-Step 11.2 you create the StepByStep11_1 code group as a child of the All Code code group. In general, the CLR examines all the code groups in the hierarchy to determine membership. However, any code group in the hierarchy may be marked as Exclusive (that's the effect of the check box that you select when creating the StepByStep11_1 code group). The CLR stops checking for group membership if code is found to be a member of an Exclusive code group. Either way, code is determined to be a member of zero or more code groups as a first step.

Next, the CLR retrieves the permission set for each code group that contains the code. If the code is a member of an Exclusive code group, only the permission set of that code group is taken into account. If the code is a member of more than one code group and none of them is an Exclusive code group, all the permission sets of those code groups are taken into account. The permission set for the code is the union of the permission sets of all relevant code groups. That is, if the code is a member of two code groups and one code group grants FileDialog permission but the other does not, the code has FileDialog permission from this step.

The process accounts for the permissions at one level (the Enterprise level). But there are actually four levels of permissions: Enterprise, Machine, User, and Application Domain. Only the first three of these levels can be managed within the .NET Framework Configuration tool. However, if you need specific security checking within an application domain (which, roughly speaking, is a session in which code runs), you can do this in code. An application domain can reduce the permissions granted to code within that application domain, but it cannot expand them.

The CLR determines which of the four levels are relevant by starting at the top (the Enterprise level) and working down. Any given code group can have the LevelFinal property, in which case the examination stops there. For example, if code is a member of a code group on the Machine level and that group has the LevelFinal property, only the Enterprise and Machine levels are considered when security is assigned. The CLR computes the permissions for each level separately and then assigns the code the intersection of the permissions of all relevant levels. That is, if code is granted FileDialog permission on the Enterprise and Machine levels but is not granted FileDialog permission on the User level, the code does not have FileDialog permission.

At this point, the CLR knows what permissions should be granted to the code in question, considered in isolation. But code does not run in isolation; it runs as part of an application. The final step of evaluating code access permissions is to perform a stack walk. In a stack walk, the CLR examines all code in the calling chain from the original application to the code being evaluated. The final permission set for the code is the intersection of the permission sets of all code in the calling chain. That is, if code is granted FileDialog permission but the code that called it was not granted FileDialog permission, the code is not granted FileDialog permission.

EXAM TIP

Determining Permissions The Microsoft .NET Framework Configuration tool can help you determine the effective permissions for a piece of code. To determine the effective permissions, right-click the Runtime Security Policy node and select Evaluate Assembly. You can see the effective permissions for an assembly here, or you can get a list of all the code groups that contribute to the assembly's permissions.


Requesting Other Types of Permissions

You might at times want to request a particular permission even though your application doesn't absolutely require that permission for a user to proceed. Optional permissions are used in such a case. If you refer to the code in Step-by-Step 11.1, you see that part of the permission attribute is the SecurityAction.RequestMinimum action. To request optional permissions, you use the SecurityAction.RequestOptional action.

To make use of optional permissions in Visual C# .NET, your code must have a Main() method with a try-catch block. If optional permissions for the assembly can't be granted, this block catches the exception. If minimum permissions can't be granted, the program is shut down, whether this block is present or not.

WARNING

RequestOptional Versus RequestMinimum When you request minimum permissions, the CLR gives your assembly any other permissions it can in addition to the minimum permissions. When you request optional permissions, the CLR gives the assembly only those permissions, and no others. So if you make an optional permissions request, you must be sure to request all the permissions that your code requires, including user interface permissions if you display any user interface.


You can also tell the CLR about permissions that you do not want your code to have. This can be useful if the code is potentially available to untrusted callers (for example, users who invoke the code over the Internet) and you want to limit the potential harm that they can do. The action for this is SecurityAction.RequestRefuse.

Finally, you might want to ensure that all the code that calls your code has a particular permission. For example, you might want to raise an exception if any code in the calling stack doesn't have the RegistryPermission permission. You can do this by specifying SecurityAction.Demand in the declaration of the security attribute.

GUIDED PRACTICE EXERCISE 11.1

One reason you might choose to use imperative security rather than declarative security is to be able to easily catch security violations and respond to them automatically.

In this exercise, you are required to extend the "browse for file" example in Step-by-Step 11.1 and use imperative security to selectively disable part of a user interface that the user isn't able to activate under the current security policy.

How would you use imperative security in this form?

You should try working through this problem on your own first. If you get stuck, or if you'd like to see one possible solution, follow these steps:

  1. Add a new Visual C# .NET Windows application named GuidedPracticeExercise11_1 to the solution.

  2. In the Solution Explorer, rename the default Form1.cs to GuidedPracticeExercise11_1.cs. Open the form in code view and change all occurrences of Form1 to refer to GuidedPracticeExercise11_1 instead.

  3. Place two Label controls, one TextBox control (txtFileName), and one Button control (btnGetFile) on the form. Name one of the Label controls lblMessage and empty its Text property. Add an OpenFileDialog component (dlgOpen). Refer to Figure for the design of this form.

    4. Choosing imperative security allows you to easily check for permissions and respond to them by taking custom actions, such as customizing the user interface in the current instance.

    graphics/11fig04.jpg

  4. Switch to the code view and add the following using directive:

    
    using System.Security.Permissions;
    
    
  5. Attach default event handlers to the form and the Button control. Add the following code to the event handlers to check security at load time and to enable the user to browse for a filename when he clicks the button:

    
    private void GuidedPracticeExercise11_1_Load(
    
         object sender, System.EventArgs e)
    
    {
    
        try
    
        {
    
            FileDialogPermission fdp = new
    
            FileDialogPermission(
    
                  PermissionState.Unrestricted);
    
            // Check to see whether the code
    
            // has the specified permission
    
            fdp.Demand();
    
        }
    
        catch(Exception ex)
    
        {
    
            btnGetFile.Enabled = false;
    
            lblMessage.Text =
    
                "You do not have permission " +
    
                "to browse for file names";
    
        }
    
    }
    
    
    
    private void btnGetFile_Click(object sender,
    
        System.EventArgs e)
    
    {
    
        try
    
        {
    
            if(dlgOpen.ShowDialog() == DialogResult.OK)
    
                txtFilename.Text = dlgOpen.FileName;
    
        }
    
        catch (Exception ex)
    
        {
    
            MessageBox.Show("Exception: " + ex.Message);
    
        }
    
    }
    
    
  6. Set the project as the startup project.

  7. Compile the project. Run the compiled project from Windows Explorer. You should find it possible to browse for a file by clicking the button.

  8. Select Start, Programs, Administrative Tools, Microsoft .NET Framework Configuration. Navigate to the User node beneath the Runtime Security Policy node.

  9. Expand the Code Groups node under the User node and click the default All Code code group. Click the Add a Child Code Group link in the right panel of the Configuration tool.

  10. In the Create Code Group dialog box, name the new group GuidedPracticeExercise11_1. Enter a description and click Next.

  11. Choose the Hash condition. Click the Import button and browse to the executable file from this exercise. Click Open to calculate the hash for this file. Click Next.

  12. Select the No FileDialog permission set (created in the Step-by-Step 11.2) and click Next. Click Finish to create the new code group.

  13. Right-click the GuidedPracticeExercise11_1 code group and select Properties. Check the first check box to make this code group exclusive. Click OK.

  14. Run the program from Windows Explorer again. The Button control should be disabled, and the message shown in Figure should appear.

In Guided Practice Exercise 11.1, the imperative security object is used to check the permissions that the application has as soon as the form is loaded. If the call to the Demand() method fails, you know that the user is not able to invoke the File dialog box. In that case, the code disables the button that would otherwise launch the File dialog box and shows a warning message instead.

If you had difficulty following this exercise, you should review the sections "Code Groups and Permission Sets" and "Imperative Security," earlier in this chapter. After this review, you should try this exercise again.

Using Custom Security Attributes

In some cases, you might find that the built-in security permissions do not fit your needs. For example, say you have designed a custom class that retrieves confidential information from your company's database and you'd like to be able to restrict permission on it by a more specific means than by limiting SQL permissions.

In such cases, you can create your own custom permissions and add them to the .NET security framework. This requires quite a bit of code, and most developers never need to perform this task. But just in case you do, I outline the process here. You'll find more in-depth information, including all the code for a simple custom permission, in the "Securing Applications" section of the .NET Framework Developer's Guide.

To implement a custom permission, you must create a class that inherits from the CodeAccessPermission class. Your new class must override five key methods to provide its own interfaces to the security system:

  • Copy()— This method creates an exact copy of the current instance.

  • Intersect()— This method returns the intersection of permissions between the current instance and a passed-in instance of the class.

  • IsSubsetOf()— This method returns true if a passed-in instance includes everything allowed by the current instance.

  • FromXml()— This method decodes an XML representation of the permission.

  • ToXml()— This method encodes the current instance as XML.

Your class must support a constructor that accepts an instance of the PermissionState enumeration (which has a value of Unrestricted or None). You might also want to implement custom constructors related to your particular business needs. For example, a database-related permission might require a constructor that accepts a server name, if permissions should be handled differently on test and development servers.

Although it's not strictly required, your code should also implement a method named IsUnrestricted(), which returns true if the particular instance represents unrestricted access to the resource. This makes your custom permission more compatible with the built-in permissions in the .NET Framework.

To support declarative security, you should also implement an attribute class for your permission. This attribute class should derive from CodeAccessSecurityAttribute (which in turn derives from SecurityAttribute). The class should override the CreatePermission() method of the IPermission interface. Within this function, you should create an instance of your base custom permission class and set its properties according to the parameters from the declarative security invocation. Any attribute class must be marked with the Serializable attribute so that it can be serialized into metadata, along with the class to which it is applied.

For your custom permission to actually protect the intended resource, you need to make changes to both the resource and to the .NET Framework on the computers where the permission is to be used. The changes to the resource are simple: Whenever an operation that is protected by the custom permission is about to be performed, the code should demand an instance of the permission. If the calling code can't deliver the permission, your class should refuse to perform the operation.

The changes you need to make to the .NET Framework are somewhat more complex than the changes that you make to the resource.

First, you need to create an XML representation of your custom permission in the format that is expected by the Code Access Security Policy tool (caspol.exe). You can create this XML representation by instantiating your permission and calling its ToXml() method. Given this XML representation, caspol.exe can add a permission set to the .NET Framework that contains your custom permission. It also adds the assembly that implements the custom permission to the list of trusted assemblies on the computer. You need to perform this step on every computer where your custom permission is to be used.

REVIEW BREAK

  • Permissions control access to resources.

  • Code can request the minimum permissions that it needs to run and optional permissions that it would like to have. It can also refuse permissions and demand permissions on behalf of calling code.

  • Code access permissions represent access to resources, and identity permissions represent things that the .NET Framework knows about code.

  • The .NET Framework supplies both attribute-based declarative security and class-based imperative security.

  • A code group is a set of assemblies that share a security context.

  • Permission sets are sets of permissions that can be granted as a unit.

  • The CLR computes actual permissions at runtime based on code group membership and the calling chain of the code.

  • Custom permissions enable you to create your own permissions to protect particular resources.