Re: Console Application Alternate Windows Credentials



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
.



Relevant Pages

  • Re: Printing from an ASP.NET page
    ... webservice or even simple network socket programming is ok(or if you ... For the console application, do not call it from your ASP.NET application, ... you are doing the samething as you try calling winform printing ... The following code fails at "Dim p As System.Diagnostics.Process." ...
    (microsoft.public.dotnet.framework.aspnet)
  • Re: vb6 run from and output to command window
    ... VB doesn't really create true console applications (because the linker ... allocate the console window, and read/write from/to it. ... Private Declare Function AllocConsole Lib "kernel32" As Long ... Dim lResult As Long ...
    (microsoft.public.vb.general.discussion)
  • Re: vb6 run from and output to command window
    ... > VB doesn't really create true console applications (because the linker ... AllocConsole to allocate the console window, ... > Dim lResult As Long ... > Function ConsoleWriteLn(sOutput As String) As Boolean ...
    (microsoft.public.vb.general.discussion)
  • RE: Strange behavour of Process
    ... | Dim p as New Process ... | This works (as well as when i run exactly the same command in a console). ... | But I don't want the console window to pop up so therefore I add the ... | this strange by Process? ...
    (microsoft.public.dotnet.framework)