locked
impersonation for Citrix Anon users RRS feed

  • Question

  • I've developed a very simple ASP.net page that needs to access network resources. It is an internal app, so windows authentication can (and does) work well except for users of a particular Citrix app. When they run this app, they are logged in to the Citrix server as Anon001, Anon002, etc. These are anonymous local users on the server.

    My app needs to impersonate the credentials that the App Pool is running under to be able to reach all of the necessary network shares. How do I deal with these anonymous users?

    When I enable anonymous logon, I get the response that anonymous users cannot impersonate. With windows authentication enabled, they are challenged for credentials. This needs to be seemless.

    Thanks, Jim

    Monday, October 1, 2012 5:38 PM

Answers

  • You can use the following code to impersonate users:

    using System;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    
    public class Impersonator : IDisposable
    {
        #region API
    
        [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 LogonInteractive = 2;
        private const int LogonDefaultProvider = 0;
    
        #endregion
    
        private WindowsImpersonationContext m_impersonationContext = null;
    
        public Impersonator(string userName, string domainName, string password)
        {
            ImpersonateValidUser(userName, domainName, password);
        }
    
        public void Dispose()
        {
            UndoImpersonation();
        }
    
        private void ImpersonateValidUser(string userName, string domain, string password)
        {
            WindowsIdentity tempWindowsIdentity = null;
            var token = IntPtr.Zero;
            var tokenDuplicate = IntPtr.Zero;
    
            try
            {
                if (RevertToSelf())
                {
                    if (LogonUser(userName, domain, password, LogonInteractive, LogonDefaultProvider, ref token) != 0)
                    {
                        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                            m_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);
                }
            }
        }
    
        private void UndoImpersonation()
        {
            if (m_impersonationContext != null)
            {
                m_impersonationContext.Undo();
            }
        }
    }
    

    The way to use it is very easy:

    using (var impersonator = new Impersonator("userName", "domainName", "password"))
    {
        // Place your code here
    }

    Hope this helps,

    Miguel.

    • Proposed as answer by Bob Shen Thursday, October 4, 2012 3:07 AM
    • Marked as answer by Bob Shen Monday, October 8, 2012 4:59 AM
    Monday, October 1, 2012 5:44 PM