0

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;
user1564238
  • 1
  • 1
  • 1
  • Have you tried interactively login with that user on that machine? – Alexei Levenkov Jul 30 '12 at 22:49
  • You're trying to use domain credentials on a machine that's not on the domain? How is LogonUser supposed to validate the credentials you've passed in? I could be wrong, but I think this can't possibly work. – bmm6o Jul 31 '12 at 16:20
  • Hey did you figure this out? I am having the exact same issue..app works fine on domain but a PC off domain it will not work with the same credentials. – user1564238 Aug 28 '12 at 20:58

0 Answers0