Re: impersonation problem - any good resources ?

From: Shel Blauman [MSFT] (sheldonb@online.microsoft.com)
Date: 04/13/03

  • Next message: Shel Blauman [MSFT]: "Re: UnauthorizedAccessException Help"
    From: "Shel Blauman [MSFT]" <sheldonb@online.microsoft.com>
    Date: Sun, 13 Apr 2003 08:50:49 -0700
    
    

    The sample that has been on MSDN was recently updated. The version you are
    running may not be working properly. Here's the latest sample code:

    ' This sample demonstrates the use of the WindowsIdentity class to
    impersonate a user. ' IMPORTANT NOTES:
    ' This sample can be run only on Windows XP. The default Windows 2000
    security policy
    ' prevents this sample from executing properly, and changing the policy to
    allow ' proper execution presents a security risk.
    ' This sample requests the user to enter a password on the console screen. '
    Because the console window does not support methods allowing the password to
    be masked,
    ' it will be visible to anyone viewing the screen.

    Imports System
    Imports System.Runtime.InteropServices
    Imports System.Security.Principal
    Imports System.Security.Permissions
    Imports Microsoft.VisualBasic
    <Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum,
    UnmanagedCode:=True), _
     Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum,
    Name:="FullTrust")>
    Module Module1

        Public Class ImpersonationDemo

            Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal
    lpszUsername As [String], _
                ByVal lpszDomain As [String], ByVal lpszPassword As [String], _
                ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer,
    _
                ByRef phToken As IntPtr) As Boolean

            <DllImport("kernel32.dll")> _
            Public Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef
    lpSource As IntPtr, _
                ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer,
    ByRef lpBuffer As [String], _
                ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer

            End Function

            Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal
    handle As IntPtr) As Boolean

            Public Declare Auto Function DuplicateToken Lib "advapi32.dll"
    (ByVal ExistingTokenHandle As IntPtr, _
                    ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
                    ByRef DuplicateTokenHandle As IntPtr) As Boolean

            'GetErrorMessage formats and returns an error message
            'corresponding to the input errorCode.
            Public Shared Function GetErrorMessage(ByVal errorCode As Integer)
    As String
                Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
                Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
                Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000

                Dim messageSize As Integer = 255
                Dim lpMsgBuf As String
                Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or
    FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS

                Dim ptrlpSource As IntPtr = IntPtr.Zero
                Dim prtArguments As IntPtr = IntPtr.Zero

                Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource,
    errorCode, 0, lpMsgBuf, _
                    messageSize, prtArguments)
                If 0 = retVal Then
                    Throw New Exception("Failed to format message for error code
    " + errorCode.ToString() + ". ")
                End If

                Return lpMsgBuf
            End Function 'GetErrorMessage
            ' Test harness.
            ' If you incorporate this code into a DLL, be sure to demand
    FullTrust.
            <PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
            Public Overloads Shared Sub Main(ByVal args() As String)

                Dim tokenHandle As New IntPtr(0)
                Dim dupeTokenHandle As New IntPtr(0)
                Try

                    Dim UserName, MachineName As String

                    ' Get the user token for the specified user, machine, and
    password using the
                    ' unmanaged LogonUser method.
                    Console.Write("Enter the name of a machine on which to log
    on: ")
                    MachineName = Console.ReadLine()

                    Console.Write("Enter the login of a user on {0} that you
    wish to impersonate: ", MachineName)
                    UserName = Console.ReadLine()

                    Console.Write("Enter the password for {0}: ", UserName)

                    Const LOGON32_PROVIDER_DEFAULT As Integer = 0
                    'This parameter causes LogonUser to create a primary token.
                    Const LOGON32_LOGON_INTERACTIVE As Integer = 2
                    Const SecurityImpersonation As Integer = 2

                    tokenHandle = IntPtr.Zero
                    dupeTokenHandle = IntPtr.Zero

                    ' Call LogonUser to obtain a handle to an access token.
                    Dim returnValue As Boolean = LogonUser(UserName,
    MachineName, Console.ReadLine(), LOGON32_LOGON_INTERACTIVE,
    LOGON32_PROVIDER_DEFAULT, tokenHandle)

                    Console.WriteLine("LogonUser called.")

                    If False = returnValue Then
                        Dim ret As Integer = Marshal.GetLastWin32Error()
                        Console.WriteLine("LogonUser failed with error code :
    {0}", ret)
                        Console.WriteLine(ControlChars.Cr + "Error: [{0}] {1}" +
    ControlChars.Cr, ret, GetErrorMessage(ret))

                        Return
                    End If

                    Dim success As String
                    If returnValue Then success = "Yes" Else success = "No"
                    Console.WriteLine(("Did LogonUser succeed? " + success))
                    Console.WriteLine(("Value of Windows NT token: " +
    tokenHandle.ToString()))

                    ' Check the identity.
                    Console.WriteLine(("Before impersonation: " +
    WindowsIdentity.GetCurrent().Name))

                    Dim retVal As Boolean = DuplicateToken(tokenHandle,
    SecurityImpersonation, dupeTokenHandle)
                    If False = retVal Then
                        CloseHandle(tokenHandle)
                        Console.WriteLine("Exception thrown in trying to
    duplicate token.")
                        Return
                    End If

                    ' TThe token that is passed to the following constructor
    must
                    ' be a primary token in order to use it for impersonation.
                    Dim newId As New WindowsIdentity(dupeTokenHandle)
                    Dim impersonatedUser As WindowsImpersonationContext =
    newId.Impersonate()

                    ' Check the identity.
                    Console.WriteLine(("After impersonation: " +
    WindowsIdentity.GetCurrent().Name))

                    ' Stop impersonating the user.
                    impersonatedUser.Undo()

                    ' Check the identity.
                    Console.WriteLine(("After Undo: " +
    WindowsIdentity.GetCurrent().Name))

                    ' Free the tokens.
                    If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero)
    Then
                        CloseHandle(tokenHandle)
                    End If
                    If Not System.IntPtr.op_Equality(dupeTokenHandle,
    IntPtr.Zero) Then
                        CloseHandle(dupeTokenHandle)
                    End If
                Catch ex As Exception
                    Console.WriteLine(("Exception occurred. " + ex.Message))
                End Try
            End Sub 'Main
        End Class 'Class1

    --
    This posting is provided "AS IS" with no warranties, and confers no rights.
    Use of included script samples are subject to the terms specified at
    http://www.microsoft.com/info/cpyright.htm
    "Support" <RemoveThis_Support@mail.oci.state.ga.us> wrote in message
    news:esh45F5$CHA.1600@TK2MSFTNGP10.phx.gbl...
    > Hello:
    >
    > I have a vb.net app that needs to copy a file from the local machine to a
    > directory on a file server.
    > There is only one domain account that has fullcontrol on the server's
    > directory.  All others only have read rights only.
    > The client is running XP and the server runs NT2000.
    > I used the impersonation methodology provided in MSDN's
    > WindowsIdentity.Impersonate Method.
    > I impersonated the fullcontrol domain account and tried a simple:
    > System.IO.File.Move(currentfilename, newfilename)
    > I tested the impersonation, and it shows that it took, but I still get: An
    > unhandled exception of type 'System.UnauthorizedAccessException' in
    > mscorlib.  Access to Path is denied.
    >
    > Looking at the server security logs, I do not see where the impersonated
    > account is hitting the machine but i do see many hits from my loging
    account
    > on XP. It seems to me that it means that if the impersonation took, it
    took
    > only locally but not domain-wide.
    >
    > Is that a correct assessment ?
    >
    > Are there any good resources to understand this stuff out there  - books
    or
    > sites ?
    > Thanks
    > Terry
    >
    >
    

  • Next message: Shel Blauman [MSFT]: "Re: UnauthorizedAccessException Help"

    Relevant Pages

    • Re: impersonation problem - any good resources ?
      ... "The LogonUser function attempts to log a user on to the local computer. ... > allow ' proper execution presents a security risk. ... > Imports System.Runtime.InteropServices ... It seems to me that it means that if the impersonation took, ...
      (microsoft.public.dotnet.security)
    • Impersonation Problem
      ... I'm having a difficult time with impersonation. ... Imports System.Runtime.InteropServices ... lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword ... Dim tokenHandle As IntPtr = New IntPtr ...
      (microsoft.public.dotnet.framework.aspnet)
    • Re: System.IO.Directoryinfo throwing exception
      ... With basic authentication and impersonation you need to ... use a domain account which can delegate and you can check how to mark your ... ASP.NET MVP ...
      (microsoft.public.dotnet.framework.aspnet)
    • Re: Impersonate user from ASP.NET - access to network file share
      ... I have tried putting the impersonation code into a Class ... > Imports System.String ... > Shared Function impersonateValidUser(ByVal userName As String, ... > End Sub ...
      (microsoft.public.dotnet.general)
    • Re: Using LogonUser API in ASP.net with an account other than ASPNet account
      ... Impersonate but without connection to OLAP Server. ... I have another application with impersonation set manually at ... Imports System.Web ... Protected WithEvents txbUserName As System.Web.UI.WebControls.TextBox ...
      (microsoft.public.dotnet.framework.aspnet.security)