Tải bản đầy đủ - 0 (trang)
11-11. Restrict Which Users Can Execute Your Code

11-11. Restrict Which Users Can Execute Your Code

Tải bản đầy đủ - 0trang

CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



The benefit of this approach is that you can implement a user and an RBS model within your

application using a proprietary user accounts database, without the need for all users to have Windows

user accounts. This is a particularly useful approach in large-scale, publicly accessible Internet

applications.

By default, the Thread.CurrentPrincipal property is undefined. Because obtaining user-related

information can be time-consuming, and only a minority of applications use this information, the .NET

designers opted for lazy initialization of the CurrentPrincipal property. The first time code gets the

Thread.CurrentPrincipal property, the runtime assigns an IPrincipal instance to the property using the

following logic:





If the application domain in which the current thread is executing has a default

principal, the runtime assigns this principal to the Thread.CurrentPrincipal

property. By default, application domains do not have default principals.

You can set the default principal of an application domain by calling the

SetThreadPrincipal method on a System.AppDomain object that represents the

application domain you want to configure. Code must have the ControlPrincipal

element of SecurityPermission to call SetThreadPrincipal. You can set the default

principal only once for each application domain; a second call to

SetThreadPrincipal results in the exception System.Security.Policy.

PolicyException.







If the application domain does not have a default principal, the application

domain’s principal policy determines which IPrincipal implementation to create

and assign to Thread.CurrentPrincipal. To configure principal policy for an

application domain, obtain an AppDomain object that represents the application

domain and call the object’s SetPrincipalPolicy method. The

SetPrincipalPolicy method accepts a member of the enumeration

System.Security.Principal.PrincipalPolicy, which specifies the type of

IPrincipal object to assign to Thread.CurrentPrincipal. Code must have the

ControlPrincipal element of SecurityPermission to call SetPrincipalPolicy.

Table 11-3 lists the available PrincipalPolicy values; the default value is

UnauthenticatedPrincipal.







If your code has the ControlPrincipal element of SecurityPermission, you can

instantiate your own IPrincipal object and assign it to the Thread.

CurrentPrincipal property directly. This will prevent the runtime from assigning

default IPrincipal objects or creating new ones based on principal policy.



569



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



Table 11-3. Members of the PrincipalPolicy Enumeration



Member Name



Description



NoPrincipal



No IPrincipal object is created. Thread.CurrentPrincipal returns a null

reference.



UnauthenticatedPrincipal



An empty System.Security.Principal.GenericPrincipal object is created

and assigned to Thread.CurrentPrincipal.



WindowsPrincipal



A WindowsPrincipal object representing the currently logged-on Windows

user is created and assigned to Thread.CurrentPrincipal.



Whatever method you use to establish the IPrincipal for the current thread, you must do so before

you use RBS demands, or the correct user (IPrincipal) information will not be available for the runtime

to process the demand. Normally, when running on the Windows platform, you would set the principal

policy of an application domain to PrincipalPolicy.WindowsPrincipal (as shown here) to obtain

Windows user information.

// Obtain a reference to the current application domain.

AppDomain appDomain = System.AppDomain.CurrentDomain;

// Configure the current application domain to use Windows-based principals.

appDomain.SetPrincipalPolicy(

System.Security.Principal.PrincipalPolicy.WindowsPrincipal);



The Code

The following example demonstrates the use of imperative and declarative RBS demands. The example

shows three methods protected using imperative RBS demands (Method1, Method2, and Method3), and

then three other methods protected using the equivalent declarative RBS demands (Method4, Method5,

and Method6).

using System;

using System.Security.Permissions;

namespace Apress.VisualCSharpRecipes.Chapter11

{

class Recipe11_11

{

public static void Method1()

{

// An imperative role-based security demand for the current principal

// to represent an identity with the name Anya. The roles of the

// principal are irrelevant.

PrincipalPermission perm =

new PrincipalPermission(@"MACHINE\Anya", null);



570



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



// Make the demand.

perm.Demand();

}

public static void Method2()

{

// An imperative role-based security demand for the current principal

// to be a member of the roles Managers OR Developers. If the

// principal is a member of either role, access is granted. Using the

// PrincipalPermission, you can express only an OR-type relationship.

// This is because the PrincipalPolicy.Intersect method always

// returns an empty permission unless the two inputs are the same.

// However, you can use code logic to implement more complex

// conditions. In this case, the name of the identity is irrelevant.

PrincipalPermission perm1 =

new PrincipalPermission(null, @"MACHINE\Managers");

PrincipalPermission perm2 =

new PrincipalPermission(null, @"MACHINE\Developers");

// Make the demand.

perm1.Union(perm2).Demand();

}

public static void Method3()

{

// An imperative role-based security demand for the current principal

// to represent an identity with the name Anya AND be a member of the

// Managers role.

PrincipalPermission perm =

new PrincipalPermission(@"MACHINE\Anya", @"MACHINE\Managers");

// Make the demand.

perm.Demand();

}

// A declarative role-based security demand for the current principal

// to represent an identity with the name Anya. The roles of the

// principal are irrelevant.

[PrincipalPermission(SecurityAction.Demand, Name = @"MACHINE\Anya")]

public static void Method4()

{

// Method implementation . . .

}

// A declarative role-based security demand for the current principal

// to be a member of the roles Managers OR Developers. If the

// principal is a member of either role, access is granted. You

// can express only an OR type relationship, not an AND relationship.

// The name of the identity is irrelevant.

[PrincipalPermission(SecurityAction.Demand, Role = @"MACHINE\Managers")]



571



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



[PrincipalPermission(SecurityAction.Demand, Role = @"MACHINE\Developers")]

public static void Method5()

{

// Method implementation . . .

}

// A declarative role-based security demand for the current principal

// to represent an identity with the name Anya AND be a member of the

// Managers role.

[PrincipalPermission(SecurityAction.Demand, Name = @"MACHINE\Anya",

Role = @"MACHINE\Managers")]

public static void Method6()

{

// Method implementation . . .

}

}

}



11-12. Impersonate a Windows User

Problem

You need your code to run in the context of a Windows user other than the currently active user account.



Solution

Obtain a System.Security.Principal.WindowsIdentity object representing the Windows user you need

to impersonate, and then call the Impersonate method of the WindowsIdentity object.



How It Works

Every Windows thread has an associated access token, which represents the Windows account on whose

behalf the thread is running. The Windows operating system uses the access token to determine whether

a thread has the appropriate permissions to perform protected operations on behalf of the account, such

as read and write files, reboot the system, and change the system time.

By default, a managed application runs in the context of the Windows account that executed the

application. This is normally desirable behavior, but sometimes you will want to run an application in

the context of a different Windows account. This is particularly true in the case of server-side

applications that process transactions on behalf of the users remotely connected to the server.

It’s common for a server application to run in the context of a Windows account created specifically

for the application—a service account. This service account will have minimal permissions to access

system resources. Enabling the application to operate as though it were the connected user permits the

application to access the operations and resources appropriate to that user’s security clearance. When

an application assumes the identity of another user, it’s known as impersonation. Correctly

implemented, impersonation simplifies security administration and application design while

maintaining user accountability.



572



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



■ Note As discussed in recipe 11-11, a thread’s Windows access token and its .NET principal are separate

entities and can represent different users. The impersonation technique described in this recipe changes only the

Windows access token of the current thread; it does not change the thread’s principal. To change the thread’s

principal, code must have the ControlPrincipal element of SecurityPermission and assign a new

System.Security.Principal.IPrincipal object to the CurrentPrincipal property of the current

System.Threading.Thread.



The System.Security.Principal.WindowsIdentity class provides the functionality through which

you invoke impersonation. However, the exact process depends on which version of Windows your

application is running. If it’s running on Windows Server 2003 or later, the WindowsIdentity class

supports constructor overloads that create WindowsIdentity objects based on the account name of the

user you want to impersonate. On all previous versions of Windows, you must first obtain a

System.IntPtr containing a reference to a Windows access token that represents the user to

impersonate. To obtain the access token reference, you must use a native method such as the LogonUser

function from the Win32 API.

Once you have a WindowsIdentity object representing the user you want to impersonate, call its

Impersonate method. From that point on, all actions your code performs occur in the context of the

impersonated Windows account. The Impersonate method returns a System.Security.Principal.

WindowsSecurityContext object, which represents the active account prior to impersonation. To revert to

the original account, call the Undo method of this WindowsSecurityContext object.



The Code

The following example demonstrates impersonation of a Windows user. The example uses the LogonUser

function of the Win32 API to obtain a Windows access token for the specified user, impersonates the

user, and then reverts to the original user context.

using

using

using

using

using



System;

System.IO;

System.Security.Principal;

System.Security.Permissions;

System.Runtime.InteropServices;



// Ensure the assembly has permission to execute unmanaged code

// and control the thread principal.

[assembly:SecurityPermission(SecurityAction.RequestMinimum,

UnmanagedCode=true, ControlPrincipal=true)]

namespace Apress.VisualCSharpRecipes.Chapter11

{

class Recipe11_12

{



573



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

11-11. Restrict Which Users Can Execute Your Code

Tải bản đầy đủ ngay(0 tr)

×