Re: Console Application Alternate Windows Credentials
- From: Andy <anedza@xxxxxxxxxxxxxxxxxxxxxx>
- Date: Mon, 18 Aug 2008 10:25:00 -0700 (PDT)
Thanks Joe,
That seems to work. I've adapted the example you pointed to, to work
with a plain main sub of a console application.
For future impersonators, I've added the class
ConsoleApplicationCredentials to the module of my console application
and made sure that security.Principal, Permissions, and
Runtime.interopservices .NET 1.1 libraries were imported.
ConsoleApplicationCredentials contains wrappers to Windows kernel
functions for credential management. You call these functions to
login and logout the default credentials of the console application.
In the main sub I've declared a variable as a new instance of the
ConsoleApplicationCredentials class. I then called the routines in
the class to first logon the new user, and then passed their
authentication token to WindowsIdentity and called the Impersonate
method to make that authentication token the default credentials.
The typical method of doing the same thing is by specifying the
account you want the console application to run under when you
schedule it. Allowing the console application to accept alternative
credentials allows you to also debug and test it outside of a
scheduler.
Imports System.Security.Principal ' console application credentials
Imports System.Security.Permissions ' console application credentials
Imports System.Runtime.interopservices '<DllImport>
Public Class ConsoleApplicationCredentials
Friend Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal
ipszUsername 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
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 retVal = 0 Then
Throw New Exception("Failed to format message for error
code " + errorCode.ToString() + ". ")
End If
Return lpMsgBuf
End Function
End Class
Public Sub Main(ByVal args() As System.String)
Dim c As New ConsoleApplicationCredentials
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim tokenHandle As New IntPtr(0)
Dim dupeTokenHandle As New IntPtr(0)
Dim impersonatedUser As WindowsImpersonationContext
tokenHandle = IntPtr.Zero
dupeTokenHandle = IntPtr.Zero
Dim returnValue As Boolean = c.LogonUser(userName, domain,
password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
tokenHandle)
If returnValue = False Then
Dim ret As Integer = Marshal.GetLastWin32Error()
Console.WriteLine("LogonUser failed with error code: {0}",
ret)
Console.WriteLine("Error: [{0}] {1}", ret,
c.GetErrorMessage(ret))
Else
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 = c.DuplicateToken(tokenHandle,
SecurityImpersonation, dupeTokenHandle)
If retVal = False Then
c.Closehandle(tokenHandle)
Console.WriteLine("Exception thrown in trying to duplicate
token.")
End If
'the 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)
impersonatedUser = newId.Impersonate()
'check the identity
Console.WriteLine(("After impersonation: " +
WindowsIdentity.GetCurrent().Name))
'at this point console application is running under the
impersonated user
'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
c.CloseHandle(tokenHandle)
End If
If Not System.IntPtr.op_Equality(dupeTokenHandle, IntPtr.Zero)
Then
c.CloseHandle(dupeTokenHandle)
End If
End If ' TRUE c.LogonUser(userName, domain, password,
End Sub
.
- References:
- Console Application Alternate Windows Credentials
- From: Andy
- Re: Console Application Alternate Windows Credentials
- From: Joe Kaplan
- Console Application Alternate Windows Credentials
- Prev by Date: Re: Running vb.net app (1.1) from a network share
- Next by Date: Firewalls
- Previous by thread: Re: Console Application Alternate Windows Credentials
- Next by thread: Firewalls
- Index(es):
Relevant Pages
|