none
When shall I use SafeWaitHandle? RRS feed

  • Question

  • Hi,

    My ASP.NET web application runs under local system user and it often needs to access resources such as network files. So, we are using impersonation (identity section in web.config). The problem is, for all new threads, we have to do the impersonation manually.

    I am using WindowsImpersonationContext to impersonate. My code looks like this (and works fine):

     

    /*** CODE START ***/

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Security.Principal;
    using System.Runtime.InteropServices;
    using System.Web.Configuration;
    using System.Configuration;
    using System.ComponentModel;

    namespace Jeevan.Security
    {   
        public sealed class WindowsImpersonator : IDisposable
        {
            #region Construction/Instantiation

            public WindowsImpersonator ( string userName, string pwd, string domain )
            {
                BeginImpersonation(userName, pwd, domain);
            }

            #endregion Construction/Instantiation

            #region P/Invoke

            private IntPtr _Token = IntPtr.Zero;

            [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)]
            static extern bool CloseHandle ( IntPtr handle );

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

            enum LogonProvider : uint
            {
                Default = 0,
                WinNT35,    
                WinNT40,    
                WinNT50     
            }

            #endregion P/Invoke

            #region Fields

            private WindowsImpersonationContext _Context = null;
           
            #endregion Fields

            private void BeginImpersonation ( string userName, string pwd, string domain )
            {
                _Token = IntPtr.Zero;
               
                try
                {
                    bool result = LogonUser(userName,
                                            domain,
                                            pwd,
                                            LogonSessionType.Network,
                                            LogonProvider.Default,
                                            out _Token);
                    if (result)
                    {
                        WindowsIdentity id = new WindowsIdentity(_Token);

                        // Begin impersonation
                        _Context = id.Impersonate();                   
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }
                }
                catch(Exception ex)
                {
                    throw new ApplicationException(string.Format("BeginImpersonation failed for user {0}/{1}", userName, domain), ex);
                }
            }

            private void StopImpersonation ()
            {
                if (_Context != null)
                    _Context.Undo();
                if (_Token != IntPtr.Zero)
                    CloseHandle(_Token);
            }

            #region IDisposable Members

            public void Dispose ()
            {
                StopImpersonation();
            }

            #endregion
        }
    }

    /*** CODE END ***/

    Lately, I read about the SafeXXXHandle classes. I have tested my code using SafeWaitHandle instead of the raw Token. But, unfortunately, the constructor of WindowsIdentity class always expect a raw token. I can use DangerousGetHandle(), but how safe is this?

    All I want to know is, is there a better way to achieve the same as my code above? "Better" in terms of performance and reliability.

    Thanks in advance.

    -- Jeevan

     

     

     

    Wednesday, May 25, 2011 9:50 AM

Answers

All replies