using System;
using System.Threading;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Runtime.InteropServices;
class SecurityContextSample
{
static void Main()
{
try
{
Console.WriteLine("Executing the Main method in the primary " +
"thread.");
FileDialogPermission fdp = new FileDialogPermission(
FileDialogPermissionAccess.OpenSave);
fdp.Deny();
// Do not allow the security context to pass across threads;
// suppress its flow.
AsyncFlowControl aFC = SecurityContext.SuppressFlow();
Thread t1 = new Thread(new ThreadStart(DemandPermission));
t1.Start();
t1.Join();
Console.WriteLine("Is the flow suppressed? " +
SecurityContext.IsFlowSuppressed());
Console.WriteLine("Restore the flow.");
aFC.Undo();
Console.WriteLine("Is the flow suppressed? " +
SecurityContext.IsFlowSuppressed());
Thread t2 = new Thread(new ThreadStart(DemandPermission));
t2.Start();
t2.Join();
CodeAccessPermission.RevertDeny();
// Show the Deny is no longer present.
Thread t3 = new Thread(new ThreadStart(DemandPermission));
t3.Start();
t3.Join();
ImpersonateUser iU = new ImpersonateUser();
iU.Impersonate();
Thread t5 = new Thread(new ThreadStart(CheckIdentity));
t5.Start();
t5.Join();
Console.WriteLine("Suppress the flow of the Windows identity.");
AsyncFlowControl aFC2 =
SecurityContext.SuppressFlowWindowsIdentity();
Console.WriteLine("Has the Windows identity flow been suppressed?"
+ SecurityContext.IsWindowsIdentityFlowSuppressed());
Thread t6 = new Thread(new ThreadStart(CheckIdentity));
t6.Start();
t6.Join();
// Restore the flow of the Windows identity for the impersonated
// user.
aFC2.Undo();
Console.WriteLine("User name after restoring the Windows identity"
+ " flow with Undo: \n" + WindowsIdentity.GetCurrent().Name);
iU.Undo();
Console.WriteLine("This sample completed successfully;" +
" press Enter to exit.");
Console.Read();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
// Test method to be called on a second thread.
static void DemandPermission()
{
try
{
Console.WriteLine("This is the thread executing the " +
"DemandPermission method.");
new FileDialogPermission(
FileDialogPermissionAccess.OpenSave).Demand();
Console.WriteLine("FileDialogPermission was successsfully" +
" demanded.");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
static void CheckIdentity()
{
Console.WriteLine("Current user: " +
WindowsIdentity.GetCurrent().Name);
}
}
// Perform user impersonation.
public class ImpersonateUser
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
String lpszUsername,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle);
private static IntPtr tokenHandle = new IntPtr(0);
private static IntPtr dupeTokenHandle = new IntPtr(0);
private static WindowsImpersonationContext impersonatedUser;
// If you incorporate this code into a DLL, be sure to demand that it
// runs with FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void Impersonate()
{
try
{
string userName, domainName;
// Use the unmanaged LogonUser function to get the user token for
// the specified user, domain, and password.
// To impersonate a user on this machine, use the local machine
// name for the domain name.
Console.Write("Enter the name of the domain to log on to: ");
domainName = Console.ReadLine();
Console.Write("Enter the logon name of the user that you wish to"
+ " impersonate on {0}: ", domainName);
userName = Console.ReadLine();
Console.Write("Enter the password for {0}: ", userName);
const int LOGON32_PROVIDER_DEFAULT = 0;
// Passing this parameter causes LogonUser to create a primary
// token.
const int LOGON32_LOGON_INTERACTIVE = 2;
tokenHandle = IntPtr.Zero;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(
userName,
domainName,
Console.ReadLine(),
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
Console.WriteLine("LogonUser has been called.");
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser call failed with error code : " +
ret);
throw new System.ComponentModel.Win32Exception(ret);
}
Console.WriteLine("Did LogonUser succeed? " +
(returnValue ? "Yes" : "No"));
Console.WriteLine("Value of the Windows NT token: " +
tokenHandle);
// Check the identity.
Console.WriteLine("User name before the impersonation: " +
WindowsIdentity.GetCurrent().Name);
WindowsIdentity newId = new WindowsIdentity(tokenHandle);
impersonatedUser = newId.Impersonate();
// Check the identity.
Console.WriteLine("User name after the impersonation: " +
WindowsIdentity.GetCurrent().Name);
}
catch (Exception ex)
{
Console.WriteLine("Exception occurred. " + ex.Message);
}
}
public void Undo()
{
impersonatedUser.Undo();
// Check the identity.
Console.WriteLine("After Undo: " + WindowsIdentity.GetCurrent().Name);
// Free the tokens.
if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);
}
}