What I am trying to do is allow a machine that is not on the domain access to run a registry check tool by Impersonating Domain Credentials....It works fine for any machine on my domain but anyone off the domain gets a bad username and password error, even though they are using the domain admin account. Same credentials, just one machine is on the domain and one is not. Here is my code that calls the impersonation...(Impersonation code below it)
private void button1_Click(object sender, EventArgs e)
{
//Variables for Authentication
string userName;
userName = txtUser.Text;
string password;
password = txtPass.Text;
string domain;
domain = txtDomain.Text;
//Start Authentication
using ( new Impersonator( userName, domain, password ) )
{
//Clears last run result
txtResult.Clear();
//Begin Error Handling
try
{
//Variable for remote machine field
string remotemachine;
remotemachine = txtComputer.Text;
// hourglass cursor
Cursor.Current = Cursors.WaitCursor;
//Begin Code to check Registry
RegistryKey hive = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, remotemachine, RegistryView.Registry64);
var key = hive.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI");
if (key == null)
{
}
object oVal = key.GetValue("LastLoggedOnUser"); if (null != oVal)
{
txtResult.Text = oVal.ToString();
//End Registry Check
//Return Cursor
Cursor.Current = Cursors.Default;
}
}
catch (System.IO.IOException)
{
MessageBox.Show("You entered an invalid PC or the firewall is blocking you (Remote Registry Service must be running on remote host and the following ports must be open: TCP 445)", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
catch (System.NullReferenceException)
{
MessageBox.Show("This is not a Windows 7 Device", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
catch (System.UnauthorizedAccessException)
{
MessageBox.Show("Unauthorized Access, run app as Domain Admin or Machine is not on your Domain", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
catch (System.Security.SecurityException)
{
MessageBox.Show("Unauthorized Access, run app as Domain Admin or Machine is not on your Domain", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
catch (System.Exception excep)
{
MessageBox.Show(excep.GetType().ToString());
}
}
Here is the Impersonation file..
namespace Tools
{
using System;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.ComponentModel;
public class Impersonator :
IDisposable
{
#region Public methods.
// ------------------------------------------------------------------
public Impersonator(
string userName,
string domainName,
string password )
{
ImpersonateValidUser( userName, domainName, password );
}
// ------------------------------------------------------------------
#endregion
#region IDisposable member.
// ------------------------------------------------------------------
public void Dispose()
{
UndoImpersonation();
}
// ------------------------------------------------------------------
#endregion
#region P/Invoke.
// ------------------------------------------------------------------
[DllImport("advapi32.dll", SetLastError=true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern int DuplicateToken(
IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(
IntPtr handle);
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
// ------------------------------------------------------------------
#endregion
#region Private member.
// ------------------------------------------------------------------
/// <summary>
/// Does the actual impersonation.
/// </summary>
/// <param name="userName">The name of the user to act as.</param>
/// <param name="domainName">The domain name of the user to act as.</param>
/// <param name="password">The password of the user to act as.</param>
private void ImpersonateValidUser(
string userName,
string domain,
string password )
{
WindowsIdentity tempWindowsIdentity = null;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
try
{
if ( RevertToSelf() )
{
if ( LogonUser(
userName,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref token ) != 0 )
{
if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
{
tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
impersonationContext = tempWindowsIdentity.Impersonate();
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
else
{
throw new Win32Exception( Marshal.GetLastWin32Error() );
}
}
finally
{
if ( token!= IntPtr.Zero )
{
CloseHandle( token );
}
if ( tokenDuplicate!=IntPtr.Zero )
{
CloseHandle( tokenDuplicate );
}
}
}
/// <summary>
/// Reverts the impersonation.
/// </summary>
private void UndoImpersonation()
{
if ( impersonationContext!=null )
{
impersonationContext.Undo();
}
}
private WindowsImpersonationContext impersonationContext = null;