Tải bản đầy đủ - 0 (trang)
11-12. Impersonate a Windows User

11-12. Impersonate a Windows User

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

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



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



// Define some constants for use with the LogonUser function.

const int LOGON32_PROVIDER_DEFAULT = 0;

const int LOGON32_LOGON_INTERACTIVE = 2;

// Import the Win32 LogonUser function from advapi32.dll. Specify

// "SetLastError = true" to correctly support access to Win32 error

// codes.

[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]

static extern bool LogonUser(string userName, string domain,

string password, int logonType, int logonProvider,

ref IntPtr accessToken);

public static void Main(string[] args)

{

// Create a new IntPtr to hold the access token returned by the

// LogonUser function.

IntPtr accessToken = IntPtr.Zero;

// Call LogonUser to obtain an access token for the specified user.

// The accessToken variable is passed to LogonUser by reference and

// will contain a reference to the Windows access token if

// LogonUser is successful.

bool success = LogonUser(

args[0],

// Username to log on.

".",

// Use the local account database.

args[1],

// User's password.

LOGON32_LOGON_INTERACTIVE, // Create an interactive login.

LOGON32_PROVIDER_DEFAULT, // Use the default logon provider.

ref accessToken

// Receives access token handle.

);

// If the LogonUser return code is zero, an error has occurred.

// Display the error and exit.

if (!success)

{

Console.WriteLine("LogonUser returned error {0}",

Marshal.GetLastWin32Error());

}

else

{

// Create a new WindowsIdentity from the Windows access token.

WindowsIdentity identity = new WindowsIdentity(accessToken);

// Display the active identity.

Console.WriteLine("Identity before impersonation = {0}",

WindowsIdentity.GetCurrent().Name);

//

//

//

//



Impersonate the specified user, saving a reference to the

returned WindowsImpersonationContext, which contains the

information necessary to revert to the original user

context.



574



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



WindowsImpersonationContext impContext =

identity.Impersonate();

// Display the active identity.

Console.WriteLine("Identity during impersonation = {0}",

WindowsIdentity.GetCurrent().Name);

// *****************************************

// Perform actions as the impersonated user.

// *****************************************

// Revert to the original Windows user using the

// WindowsImpersonationContext object.

impContext.Undo();

// Display the active identity.

Console.WriteLine("Identity after impersonation = {0}",

WindowsIdentity.GetCurrent().Name);

// Wait to continue.

Console.WriteLine("\nMain method complete. Press Enter.");

Console.ReadLine();

}

}

}

}



Usage

The example expects two command-line arguments: the account name of the user on the local machine

to impersonate and the account’s password. For example, the command Recipe11-12 Bob password

impersonates the user Bob, as long as that user exists in the local accounts database and his password is

“password.”



11-13. Create a Cryptographically Random Number

Problem

You need to create a random number that is suitable for use in cryptographic and security applications.



Solution

Use a cryptographic random number generator such as the System.Security.Cryptography.

RNGCryptoServiceProvider class.



575



www.it-ebooks.info



CHAPTER 11 ■ SECURITY AND CRYPTOGRAPHY



How It Works

The System.Random class is a pseudorandom number generator that uses a mathematical algorithm to

simulate the generation of random numbers. In fact, the algorithm it uses is deterministic, meaning that

you can always calculate what the next number will be based on the previously generated number. This

means that numbers generated by the Random class are unsuitable for use in situations in which security

is a priority, such as generating encryption keys and passwords.

When you need a nondeterministic random number for use in cryptographic or security-related

applications, you must use a random number generator derived from the class

System.Security.Cryptography.RandomNumberGenerator. The RandomNumberGenerator class is an abstract

class from which all concrete .NET random number generator classes should inherit. Currently, the

RNGCryptoServiceProvider class is the only concrete implementation provided. The

RNGCryptoServiceProvider class provides a managed wrapper around the CryptGenRandom function of the

Win32 CryptoAPI, and you can use it to fill byte arrays with cryptographically random byte values.



■ Note The numbers produced by the RNGCryptoServiceProvider class are not truly random. However, they are

sufficiently random to meet the requirements of cryptography and security applications in most commercial and

government environments.



As is the case with many of the .NET cryptography classes, the RandomNumberGenerator base class is a

factory for the concrete implementation classes that derive from it. Calling RandomNumberGenerator.

Create("System.Security.Cryptography.RNGCryptoServiceProvider") will return an instance of

RNGCryptoServiceProvider that you can use to generate random numbers. In addition, because

RNGCryptoServiceProvider is the only concrete implementation provided, it’s the default class created if

you call the Create method without arguments, as in RandomNumberGenerator.Create().

Once you have a RandomNumberGenerator instance, the method GetBytes fills a byte array with

random byte values. As an alternative, you can use the GetNonZeroBytes method if you need random

data that contains no zero values.



The Code

The following example instantiates an RNGCryptoServiceProvider object and uses it to generate random

values.

using System;

using System.Security.Cryptography;

namespace Apress.VisualCSharpRecipes.Chapter11

{

class Recipe11_13

{

public static void Main() {

// Create a byte array to hold the random data.

byte[] number = new byte[32];



576



www.it-ebooks.info



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

11-12. Impersonate a Windows User

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

×