miércoles, 19 de enero de 2011

Clase para ejecutar Impersonificación NTLM de forma programática C#


En algunas aplicaciones sobre todo Web  es necesario hacer uso de lo que se conoce como impersonificación, y existen diferentes formas de hacerla, una es de forma programática y en seguida coloco una clase en C# que facilita esa labor. Para mayor información ver http://msdn.microsoft.com/en-us/library/ff647404.aspx.



using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Security;
using System.Security.Principal;
using Microsoft.CSharp;

namespace F.Security.NTLM
{
    public enum ImpersonificationLevel { 
        SecurityAnonymous = 0,
        SecurityIdentification = 1,
        SecurityImpersonification = 2,
        SecurityDelegation = 3
        
    }
    /// <summary>
    /// This class let's you to implement impersonation programatically. Usefull to grant special permissions of
    /// a local account from the web in a protected context. You must be carefull to use this approach.
    /// </summary>
    public sealed class NTLogin
    {
        public const int LOGON32_PROVIDER_DEFAULT = 0;

        public const int LOGON32_LOGON_INTERACTIVE = 2;

        public const int LOGON32_LOGON_NETWORK = 3;

        public const int LOGON32_LOGON_BATCH = 4;

        public const int LOGON32_LOGON_SERVICE = 5;

        public const int LOGON32_LOGON_UNLOCK = 7;

        public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;

        public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

        public static WindowsImpersonationContext ImpersonationContext;

        // '' -----------------------------------------------------------------------------
        // '' <summary>
        // '' Low level OS function to Logon on the system using NT credentials.
        // '' </summary>
        // '' <param name="lpszUsername">NT User name</param>
        // '' <param name="lpszDomain">NT Domain name</param>
        // '' <param name="lpszPassword">User password</param>
        // '' <param name="dwLogonType">Logon Type</param>
        // '' <param name="dwLogonProvider">Logon Provider</param>
        // '' <param name="phToken">Handler to access token</param>
        // '' <returns></returns>
        // '' <remarks>
        // '' </remarks>
        // '' <history>
        // ''     [bonifacio]    1/19/2007    Created
        // '' </history>
        // '' -----------------------------------------------------------------------------
        [DllImport("advapi32.dll")]
        static extern int LogonUserA(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

        [DllImport("advapi32.dll")]
        static extern int DuplicateToken(IntPtr ExistingTokenHandle, int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

        [DllImport("advapi32.dll")]
        static extern long RevertToSelf();

        [DllImport("kernel32.dll")]
        static extern long CloseHandle(IntPtr handle);

        //  NOTE:
        //  The identity of the process that impersonates a specific user on a thread must have 
        //  "Act as part of the operating system" privilege. If the the Aspnet_wp.exe process runs
        //  under a the ASPNET account, this account does not have the required privileges to 
        //  impersonate a specific user. This information applies only to the .NET Framework 1.0. 
        //  This privilege is not required for the .NET Framework 1.1.
        // 
        //  Sample call:
        // 
        //     If impersonateValidUser("username", "domain", "password") Then
        //         'Insert your code here.
        // 
        //         undoImpersonation()
        //     Else
        //         'Impersonation failed. Include a fail-safe mechanism here.
        //     End If
        // 
        public static bool ImpersonateValidUser(string strUserName, string strDomain, string strPassword)
        {
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;
            WindowsIdentity tempWindowsIdentity;
            bool toret = false;

            if ((RevertToSelf() != 0))
            {
                if (LogonUserA(strUserName, strDomain, strPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {
                    if (DuplicateToken(token, (int)ImpersonificationLevel.SecurityImpersonification  , ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        ImpersonationContext = tempWindowsIdentity.Impersonate();
                        if (!(ImpersonationContext == null))
                        {
                            toret = true;
                        }
                    }
                }
            }
            if (!tokenDuplicate.Equals(IntPtr.Zero))
            {
                CloseHandle(tokenDuplicate);
            }
            if (!token.Equals(IntPtr.Zero))
            {
                CloseHandle(token);
            }
            return toret;
        }

        // '' -----------------------------------------------------------------------------
        // '' <summary>
        // '' Undo the impersonation
        // '' </summary>
        // '' <remarks>
        // '' </remarks>
        // '' <history>
        // ''     [bonifacio]    1/19/2007    Created
        // '' </history>
        // '' -----------------------------------------------------------------------------
        public static void UndoImpersonation()
        {
            if (ImpersonationContext != null)
            {
                ImpersonationContext.Undo();
            }
        }

    }

}

Transacciones Fiori

  /UI2/CACHE Register service for UI2 cache use /UI2/CACHE_DEL Delete cache entries /UI2/CHIP Chip Registration /UI2/CUST Customizing of UI ...