views:

111

answers:

2

I've create Impersonation class which are include WindowsIdentity and WindowsImpersonationContext and I've add the Impersonation in my authentication application after the service is running for a while the lsass.exe process is consuming a lot of memory and CPU Could you please advice me how to solve this issue?

public class Impersonation : IDisposable

{
    #region external
    // Declare signatures for Win32 LogonUser and CloseHandle APIs

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool LogonUser(
      string principal,
      string authority,
      string password,
      LogonSessionType logonType,
      LogonProvider logonProvider,
      out IntPtr token);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr handle);

    enum LogonSessionType : uint
    {
        Interactive = 2,
        Network,
        Batch,
        Service,
        NetworkCleartext = 8,
        NewCredentials
    }

    enum LogonProvider : uint
    {
        Default = 0, // default for platform (use this!)
        WinNT35,     // sends smoke signals to authority
        WinNT40,     // uses NTLM
        WinNT50      // negotiates Kerb or NTLM
    }

    #endregion

    #region variables

    private WindowsIdentity m_userWindowsID;

    private WindowsImpersonationContext m_userImpersonationContext;

    #endregion

    public void LogonWindowsUser(string domain, string userLogin, string password)
    {
        IntPtr token;
        // Create a token for DomainName\Bob
        // Note: Credentials should be encrypted in configuration file
        bool result = LogonUser(userLogin, domain, password,
                                LogonSessionType.NewCredentials,
                                LogonProvider.Default,
                                out token);
        if (result)
        {
           m_userWindowsID = new WindowsIdentity(token);
        }
    }

    public void ImpersonateUser()
    {
        if (m_userWindowsID == null)
        {
            throw new Exception("User is not loged on");
        }
        m_userImpersonationContext = m_userWindowsID.Impersonate();
    }

    #region IDisposable Members

    public void Dispose()
    {
        if (m_userImpersonationContext != null)
        {
            m_userImpersonationContext.Undo();
            m_userImpersonationContext.Dispose();
        }
        if (m_userWindowsID != null)
        {
            CloseHandle(m_userWindowsID.Token);
            m_userWindowsID.Dispose();
            //m_userWindowsID.Token = IntPtr.Zero;
        }
    }
    #endregion
}
A: 

Below is what am I coding, please advise

public class Impersonation : IDisposable

{
    #region external
    // Declare signatures for Win32 LogonUser and CloseHandle APIs

    [DllImport("advapi32.dll", SetLastError = true)]
    static extern bool LogonUser(
      string principal,
      string authority,
      string password,
      LogonSessionType logonType,
      LogonProvider logonProvider,
      out IntPtr token);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool CloseHandle(IntPtr handle);

    enum LogonSessionType : uint
    {
        Interactive = 2,
        Network,
        Batch,
        Service,
        NetworkCleartext = 8,
        NewCredentials
    }

    enum LogonProvider : uint
    {
        Default = 0, // default for platform (use this!)
        WinNT35,     // sends smoke signals to authority
        WinNT40,     // uses NTLM
        WinNT50      // negotiates Kerb or NTLM
    }

    #endregion

    #region variables

    private WindowsIdentity m_userWindowsID;

    private WindowsImpersonationContext m_userImpersonationContext;

    #endregion

    public void LogonWindowsUser(string domain, string userLogin, string password)
    {
        IntPtr token;
        // Create a token for DomainName\Bob
        // Note: Credentials should be encrypted in configuration file
        bool result = LogonUser(userLogin, domain, password,
                                LogonSessionType.NewCredentials,
                                LogonProvider.Default,
                                out token);
        if (result)
        {
           m_userWindowsID = new WindowsIdentity(token);
        }
    }

    public void ImpersonateUser()
    {
        if (m_userWindowsID == null)
        {
            throw new Exception("User is not loged on");
        }
        m_userImpersonationContext = m_userWindowsID.Impersonate();
    }

    #region IDisposable Members

    public void Dispose()
    {
        if (m_userImpersonationContext != null)
        {
            m_userImpersonationContext.Undo();
            m_userImpersonationContext.Dispose();
        }
        if (m_userWindowsID != null)
        {
            CloseHandle(m_userWindowsID.Token);
            m_userWindowsID.Dispose();
            //m_userWindowsID.Token = IntPtr.Zero;
        }
    }
    #endregion
}
A: 

I don't know if you are still having this issue, but I was having a very similar issue and it had to do with not calling the CloseHandle(...) at the appropriate time.

Try moving the CloseHandle(...) after the m_userWindowsID = new WindowsIdentity(token); line in the LogonWindowsUser method.

Example:

public void LogonWindowsUser(string domain, string userLogin, string password)  
{  
    IntPtr token;  
    // Create a token for DomainName\Bob  
    // Note: Credentials should be encrypted in configuration file  
    bool result = LogonUser(userLogin, domain, password,  
                            LogonSessionType.NewCredentials,  
                            LogonProvider.Default,  
                            out token);  
    if (result)  
    {  
       m_userWindowsID = new WindowsIdentity(token);
       CloseHandle(token);   
    }  
}  

Hope this helps!

Chris

Chris Yokley