LogonUser issues

Discussion in 'Microsoft C# .NET' started by Guest, Jan 27, 2005.

  1. Guest

    Guest Guest

    Having a few strage behaviours with this function, mainly in that when I try
    to logon to another computer with a different name/pass to the current user
    of the local machine, it tries to impersonate me, not the credentials I gave
    it.

    LogonUser succeeds only when using LOGON32_LOGON_NEW_CREDENTIALS (9). Any
    other LogonType causes error 126: Specified module could not be found -
    whatever that means...

    The initial WindowsIdentity.GetCurrent() reveals "DELLWING\Trent" as the
    user, which is my local account. Upon success of LogonUser I create a new
    WindowsIdentity with the received token. Printing out the details reveals
    "DELLWING\Trent" as the user, even though I supplied "Administrator" and the
    password of the remote box. I then get "Unable to Impersonate User" when
    trying Impersonate().

    Why would the token come back represent me when I specified a whole nother
    user and computer?

    My code looks like this currently (thanks to Willy Denoyette).
    -----------------------
    using System;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    using System.Security.Permissions;

    namespace SecurityTest
    {
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class SecurityTest
    {
    [DllImport("advapi32.DLL")]
    public static extern int LogonUser(string lpszUsername, string lpszDomain,
    string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr
    phToken);

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
    IntPtr admin_token;

    // This works fine
    WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
    Console.WriteLine("Current Name: " + wid_current.Name);
    Console.WriteLine("Current Token: " + wid_current.Token);

    if (LogonUser("Administrator", "192.168.0.5", "password", 9, 0, out
    admin_token) != 0)
    {
    WindowsIdentity wid_admin = new WindowsIdentity(admin_token);
    Console.WriteLine("Remote Name: " + wid_admin.Name);
    Console.WriteLine("Remote Token: " + wid_admin.Token);


    WindowsImpersonationContext wic = null;
    try
    {
    wic = wid_admin.Impersonate();
    // Always get an exception here after Impersonate

    System.IO.File.Copy("C:\\test_read\\test.txt",
    "\\\\192.168.0.5\\trent\\test.txt", true);

    }
    catch (System.Exception se)
    {
    Console.WriteLine(se.Message);
    }
    finally
    {
    if (wic != null) wic.Undo();
    }
    }
    else
    {
    int ret = Marshal.GetLastWin32Error();
    Console.WriteLine(ret.ToString(), "Error");
    }
    }
    }
     
    Guest, Jan 27, 2005
    #1
    1. Advertisements

  2. "BLiTZWiNG" <> wrote in message
    news:D...
    > Having a few strage behaviours with this function, mainly in that when I
    > try
    > to logon to another computer with a different name/pass to the current
    > user
    > of the local machine, it tries to impersonate me, not the credentials I
    > gave
    > it.
    >
    > LogonUser succeeds only when using LOGON32_LOGON_NEW_CREDENTIALS (9). Any
    > other LogonType causes error 126: Specified module could not be found -
    > whatever that means...
    >
    > The initial WindowsIdentity.GetCurrent() reveals "DELLWING\Trent" as the
    > user, which is my local account. Upon success of LogonUser I create a new
    > WindowsIdentity with the received token. Printing out the details reveals
    > "DELLWING\Trent" as the user, even though I supplied "Administrator" and
    > the
    > password of the remote box. I then get "Unable to Impersonate User" when
    > trying Impersonate().
    >
    > Why would the token come back represent me when I specified a whole nother
    > user and computer?
    >
    > My code looks like this currently (thanks to Willy Denoyette).
    > -----------------------
    > using System;
    > using System.Runtime.InteropServices;
    > using System.Security.Principal;
    > using System.Security.Permissions;
    >
    > namespace SecurityTest
    > {
    > /// <summary>
    > /// Summary description for Class1.
    > /// </summary>
    > class SecurityTest
    > {
    > [DllImport("advapi32.DLL")]
    > public static extern int LogonUser(string lpszUsername, string lpszDomain,
    > string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr
    > phToken);
    >
    > /// <summary>
    > /// The main entry point for the application.
    > /// </summary>
    > [STAThread]
    > static void Main(string[] args)
    > {
    > IntPtr admin_token;
    >
    > // This works fine
    > WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
    > Console.WriteLine("Current Name: " + wid_current.Name);
    > Console.WriteLine("Current Token: " + wid_current.Token);
    >
    > if (LogonUser("Administrator", "192.168.0.5", "password", 9, 0, out
    > admin_token) != 0)
    > {
    > WindowsIdentity wid_admin = new WindowsIdentity(admin_token);
    > Console.WriteLine("Remote Name: " + wid_admin.Name);
    > Console.WriteLine("Remote Token: " + wid_admin.Token);
    >
    >
    > WindowsImpersonationContext wic = null;
    > try
    > {
    > wic = wid_admin.Impersonate();
    > // Always get an exception here after Impersonate
    >
    > System.IO.File.Copy("C:\\test_read\\test.txt",
    > "\\\\192.168.0.5\\trent\\test.txt", true);
    >
    > }
    > catch (System.Exception se)
    > {
    > Console.WriteLine(se.Message);
    > }
    > finally
    > {
    > if (wic != null) wic.Undo();
    > }
    > }
    > else
    > {
    > int ret = Marshal.GetLastWin32Error();
    > Console.WriteLine(ret.ToString(), "Error");
    > }
    > }
    > }


    A few remarks:
    LogonUser returns or a "direct" token or an "impersonation" token. A direct
    token kan be used to impersonate, an impersonation token cannot and will
    return an error.
    Both LOGON32_LOGON_NEW_CREDENTIALS (9) and LOGON32_LOGON_NETWORK_CLEARTEXT
    Logontypes returns a direct token, but LOGON32_LOGON_NETWORK does not.

    Why the error 126? The reason is that the original error code is lost in the
    call chain. To prevent this you should add SetLastError=true in the
    DllImport.

    [DllImport("advapi32.DLL"), SetLastError=true]

    Why is the local identity still the same, simply because logontype 9 returns
    a clone of the current token but also creates a hidden secondary token.
    The clone will be used to access local resources while the secondary token
    will ONLY be used when accessing remote resources.

    Logontype 9 requires a "negotiate" logon provider (W2K or higher), when
    running on W2K the default however is NTLM, so it's better to specify
    LOGON32_PROVIDER_WINNT50 (5) a logon provider to make sure negotiate is used
    in all cases.

    if (LogonUser("Administrator", "192.168.0.5", "password", 9, 5, out
    admin_token) != 0)

    Willy.
     
    Willy Denoyette [MVP], Jan 27, 2005
    #2
    1. Advertisements

  3. Guest

    Guest Guest

    Thanks again Willy. I will try what you have suggested here.

    However note that I used unmanaged function ImpersonateLoggedOnUser and
    succeeded with the copy, so I at least have a solution. I'm not sure if there
    are downsides to that way though. I am still going to persist with the
    managed way.

    Also note that the 2k3 server I'm trying to copy to is now suffering UserEnv
    errors 1058 (unable to save group policy object) :/ I can see there is a fix
    for it but I have to discuss it with my boss.

    "Willy Denoyette [MVP]" wrote:

    >
    > "BLiTZWiNG" <> wrote in message
    > news:D...
    > > Having a few strage behaviours with this function, mainly in that when I
    > > try
    > > to logon to another computer with a different name/pass to the current
    > > user
    > > of the local machine, it tries to impersonate me, not the credentials I
    > > gave
    > > it.
    > >
    > > LogonUser succeeds only when using LOGON32_LOGON_NEW_CREDENTIALS (9). Any
    > > other LogonType causes error 126: Specified module could not be found -
    > > whatever that means...
    > >
    > > The initial WindowsIdentity.GetCurrent() reveals "DELLWING\Trent" as the
    > > user, which is my local account. Upon success of LogonUser I create a new
    > > WindowsIdentity with the received token. Printing out the details reveals
    > > "DELLWING\Trent" as the user, even though I supplied "Administrator" and
    > > the
    > > password of the remote box. I then get "Unable to Impersonate User" when
    > > trying Impersonate().
    > >
    > > Why would the token come back represent me when I specified a whole nother
    > > user and computer?
    > >
    > > My code looks like this currently (thanks to Willy Denoyette).
    > > -----------------------
    > > using System;
    > > using System.Runtime.InteropServices;
    > > using System.Security.Principal;
    > > using System.Security.Permissions;
    > >
    > > namespace SecurityTest
    > > {
    > > /// <summary>
    > > /// Summary description for Class1.
    > > /// </summary>
    > > class SecurityTest
    > > {
    > > [DllImport("advapi32.DLL")]
    > > public static extern int LogonUser(string lpszUsername, string lpszDomain,
    > > string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr
    > > phToken);
    > >
    > > /// <summary>
    > > /// The main entry point for the application.
    > > /// </summary>
    > > [STAThread]
    > > static void Main(string[] args)
    > > {
    > > IntPtr admin_token;
    > >
    > > // This works fine
    > > WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
    > > Console.WriteLine("Current Name: " + wid_current.Name);
    > > Console.WriteLine("Current Token: " + wid_current.Token);
    > >
    > > if (LogonUser("Administrator", "192.168.0.5", "password", 9, 0, out
    > > admin_token) != 0)
    > > {
    > > WindowsIdentity wid_admin = new WindowsIdentity(admin_token);
    > > Console.WriteLine("Remote Name: " + wid_admin.Name);
    > > Console.WriteLine("Remote Token: " + wid_admin.Token);
    > >
    > >
    > > WindowsImpersonationContext wic = null;
    > > try
    > > {
    > > wic = wid_admin.Impersonate();
    > > // Always get an exception here after Impersonate
    > >
    > > System.IO.File.Copy("C:\\test_read\\test.txt",
    > > "\\\\192.168.0.5\\trent\\test.txt", true);
    > >
    > > }
    > > catch (System.Exception se)
    > > {
    > > Console.WriteLine(se.Message);
    > > }
    > > finally
    > > {
    > > if (wic != null) wic.Undo();
    > > }
    > > }
    > > else
    > > {
    > > int ret = Marshal.GetLastWin32Error();
    > > Console.WriteLine(ret.ToString(), "Error");
    > > }
    > > }
    > > }

    >
    > A few remarks:
    > LogonUser returns or a "direct" token or an "impersonation" token. A direct
    > token kan be used to impersonate, an impersonation token cannot and will
    > return an error.
    > Both LOGON32_LOGON_NEW_CREDENTIALS (9) and LOGON32_LOGON_NETWORK_CLEARTEXT
    > Logontypes returns a direct token, but LOGON32_LOGON_NETWORK does not.
    >
    > Why the error 126? The reason is that the original error code is lost in the
    > call chain. To prevent this you should add SetLastError=true in the
    > DllImport.
    >
    > [DllImport("advapi32.DLL"), SetLastError=true]
    >
    > Why is the local identity still the same, simply because logontype 9 returns
    > a clone of the current token but also creates a hidden secondary token.
    > The clone will be used to access local resources while the secondary token
    > will ONLY be used when accessing remote resources.
    >
    > Logontype 9 requires a "negotiate" logon provider (W2K or higher), when
    > running on W2K the default however is NTLM, so it's better to specify
    > LOGON32_PROVIDER_WINNT50 (5) a logon provider to make sure negotiate is used
    > in all cases.
    >
    > if (LogonUser("Administrator", "192.168.0.5", "password", 9, 5, out
    > admin_token) != 0)
    >
    > Willy.
    >
    >
    >
    >
    >
     
    Guest, Jan 27, 2005
    #3
    1. Advertisements

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. LongRunner

    LogonUser function continue

    LongRunner, Aug 5, 2003, in forum: Microsoft C# .NET
    Replies:
    0
    Views:
    224
    LongRunner
    Aug 5, 2003
  2. Dan

    LogonUser API

    Dan, Oct 29, 2003, in forum: Microsoft C# .NET
    Replies:
    3
    Views:
    515
    Willy Denoyette [MVP]
    Oct 31, 2003
  3. logonuser api

    , Jan 3, 2006, in forum: Microsoft C# .NET
    Replies:
    3
    Views:
    979
    Willy Denoyette [MVP]
    Jan 3, 2006
  4. schaf

    Impersonate and LogonUser()

    schaf, Jun 23, 2006, in forum: Microsoft C# .NET
    Replies:
    9
    Views:
    217
    schaf
    Jun 26, 2006
  5. nild
    Replies:
    6
    Views:
    175
    Willy Denoyette [MVP]
    Dec 28, 2006
Loading...

Share This Page