Click here to Skip to main content
15,881,757 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I've currently got an issue where I have a website which is running as a specific user. I'm not able to run the website using impersonation.

I have a SQL analysis service database which returns different data depending on the connected user.

How can I override the windows user being used to connect to analysis services?

Regards,

Steve
Posted

1 solution

Well I beat all you experts to an answer.

The following is the class I constructed. This class changes the current windows identity for the duration of the classes life span. Disposal and deconstruction is used to revert to the previous user.

A usage example will follow after.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using System.Management;


public class Impersonate : IDisposable
  {

    private const int SERVICE_ALL_ACCESS = 0xF01FF;
    private const int SC_MANAGER_ALL_ACCESS = 0xF003F;
    private const int SERVICE_CONFIG_DESCRIPTION = 0x1;
    private const int SERVICE_CONFIG_FAILURE_ACTIONS = 0x2;
    private const int SERVICE_NO_CHANGE = -1;
    private const int ERROR_ACCESS_DENIED = 5;

    // logon types
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_LOGON_NETWORK = 3;
    public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

    // logon providers
    public const int LOGON32_PROVIDER_DEFAULT = 0;
    public const int LOGON32_PROVIDER_WINNT50 = 3;
    public const int LOGON32_PROVIDER_WINNT40 = 2;
    public const int LOGON32_PROVIDER_WINNT35 = 1;


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SERVICE_FAILURE_ACTIONS
    {
      public int dwResetPeriod;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string lpRebootMsg;
      [MarshalAs(UnmanagedType.LPWStr)]
      public string lpCommand;
      public int cActions;
      public IntPtr lpsaActions;
    }

    [StructLayout(LayoutKind.Sequential)]
    public class SC_ACTION
    {
      public Int32 type;
      public UInt32 dwDelay;
    }

    // Win32 function to open the service control manager
    [DllImport("advapi32.dll")]
    public static extern IntPtr OpenSCManager(string lpMachineName, string lpDatabaseName, int dwDesiredAccess);

    // Win32 function to open a service instance
    [DllImport("advapi32.dll")]
    public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, int dwDesiredAccess);

    // Win32 function to change the service config for the failure actions.
    [DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2")]
    public static extern bool ChangeServiceFailureActions(IntPtr hService, int dwInfoLevel,
    [MarshalAs(UnmanagedType.Struct)]
ref SERVICE_FAILURE_ACTIONS lpInfo);

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "QueryServiceConfig2W")]
    public static extern Boolean QueryServiceConfig2(IntPtr hService, UInt32 dwInfoLevel, IntPtr buffer, UInt32 cbBufSize, out UInt32 pcbBytesNeeded);

    [DllImport("kernel32.dll")]
    public static extern int GetLastError();

    [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 unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource, int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* arguments);
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern 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);

    IntPtr token = IntPtr.Zero;
    IntPtr dupToken = IntPtr.Zero;
    WindowsImpersonationContext impersonatedUser = null;

    public Impersonate(string username, string computerName, string password)
    {

      try
      {
        bool isSuccess = LogonUser(username.Replace(@".\", ""), computerName, password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref token);

        if (!isSuccess)
          throw new Exception("Error impersonating");

        isSuccess = DuplicateToken(token, 2, ref dupToken);

        if (!isSuccess)
        {
          throw new Exception("Error impersonating");
        }

        WindowsIdentity newIdentity = new WindowsIdentity(dupToken);
        impersonatedUser = newIdentity.Impersonate();

      }
      catch (Exception ex)
      {
        throw ex;
      }

    }

    
    ~Impersonate()
    {
      Dispose(false);
    }

    public void Dispose()
    {
      Dispose(true);
      GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (impersonatedUser != null)
        impersonatedUser.Undo();

      CloseHandle(token);
    }



  }


Usage example:

C#
using (new Impersonate.Impersonate("Adam", "Eden", "Pa$$w0rd"))
{

  AdomdConnection connection = new AdomdConnection(Settings.OlapConnectionString);
  connection.Open();

  // do command work

}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900