Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the magic to Windows impersonation with LOGON32_LOGON_NEW_CREDENTIALS?

From my reading on user impersonation on Windows, one should properly use the LOGON32_LOGON_NEW_CREDENTIALS logon type for impersonating a user to a database. Using Matt Johnson's nice impersonation wrapper (originally posted here and then polished up here), I tried to test this out--here is my entire program except for constants defining my particular DOMAIN, USER, PWD, and CONN_STRING.

using System;
using System.Data.SqlClient;
using SimpleImpersonation;

namespace ImpersonationDemo
{
    class Program
    {
        private static SqlConnection _connection;

        static void Main(string[] args)
        {
            using (Impersonation.LogonUser(
                    DOMAIN, USER, PWD, LogonType.NewCredentials))
            {
                GetOpenConnection();
                CheckDbCredentials();
                CloseConnection();
            }
            Console.WriteLine("Press return to exit");
            Console.ReadLine();
        }

        private static void CheckDbCredentials()
        {
            using (
                var command = new SqlCommand(
                    "SELECT nt_user_name, SUSER_SNAME() "
                    +"FROM sys.dm_exec_sessions WHERE session_id = @@SPID",
                    _connection))
            {
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Console.WriteLine("{0}, {1}",
                            reader.GetString(0), reader.GetString(1));
                    }
                }
            }
        }


        private static void GetOpenConnection()
        {
            _connection = new SqlConnection(CONN_STRING);
            _connection.Open();
        }

        private static void CloseConnection()
        {
            _connection.Close();
        }
    }
}

But that does not work. The output reports me (my underlying logged in user) from both nt_user_name and SUSER_NAME(). (And SQL Profiler reports exactly the same thing; the query in code is simply a convenient way to see what SQL Profiler tells me.)

If I change from LogonType.NewCredentials to LogonType.Interactive (these enums have the values you would expect, as defined on pinvoke.net), then it does work--the above code reports the correct DOMAIN and USER impersonation. But this also means the current session is being impersonated which I do not want--I only want the DB connection to be impersonated.

I thought I found one glitch in the above--Johnson's Impersonation wrapper hard-codes the logon provider as LOGON32_PROVIDER_DEFAULT, when the LogonUser API clearly states that the LOGON32_LOGON_NEW_CREDENTIALS logon type is supported only by the LOGON32_PROVIDER_WINNT50 logon provider. So I grabbed the source and added a parameter to allow specifying the requisite logon provider... but that made no difference.

So what am I missing?

like image 608
Michael Sorens Avatar asked Aug 06 '13 22:08

Michael Sorens


People also ask

What is impersonate user C#?

The term "Impersonation" in a programming context refers to a technique that executes the code under another user context than the user who originally started an application, i.e. the user context is temporarily changed once or multiple times during the execution of an application.

What is LOGON32_LOGON_INTERACTIVE?

LOGON32_LOGON_INTERACTIVE. This logon type is intended for users who will be interactively using the computer, such as a user being logged on by a terminal server, remote shell, or similar process.


1 Answers

The answer, I am ashamed to say, was right in front of me all along. The LogonUser API states:

This logon type allows the caller to clone its current token and specify new credentials for outbound connections. The new logon session has the same local identifier but uses different credentials for other network connections. [emphasis mine]

But my database is on the same machine as my running program so by definition it will not show the new credentials! I am confident the impersonation will work correctly with LOGON32_LOGON_NEW_CREDENTIALS once I move my database to a different box. Sigh.

like image 177
Michael Sorens Avatar answered Sep 28 '22 01:09

Michael Sorens