C
cbtg2006
HI guys,
I'm relatively new to the .net development realm. I am creating an
application in vb.net to monitor services on remote servers.
The application works great when I am logged in and using it - I am a
Domain Admin, and as a result a local admin on the remote computers.
However when I try to run the application as a standard domain user I
receive a priviledges error.
I have attempted to implement impersonation, using credentials
supplied by the application under 'My.Settings' however this seems not
to work either; I recieve a bad username or password error, despite
the fact I know that the passwords and username are correct.
The error clearly displays a valid username in the form of server_name
\userName (note that these remote machines are not part of a domain)
but my username and password are the same for the domain and remote
machines.
I have attched the relevant areas of my code for your viewing, and I
would be really grateful if anyone can point me in the right
direction!
Thanks,
-Chris
NB: Please note the error occurs on the line "aa.BeginImpersonation()"
------------------------------ Beging Code ------------------
Function service2(ByVal srvname)
Dim aa As New AliasAccount(My.Settings.userName,
My.Settings.password, serverName)
Try
aa.BeginImpersonation()
arrRemoteServices =
System.ServiceProcess.ServiceController.GetServices(serverName)
For Each Service In arrRemoteServices
Dim x As New ListViewItem
Dim y As New ListViewItem
If Service.ServiceName = srvname Then
'Can use DisplayName (long name of service)
If Service.Status =
System.ServiceProcess.ServiceControllerStatus.Running Then
If chkLogging.Checked = True Then
x.Text = TimeOfDay & "," & serverName & "
" & Service.ServiceName & ": Running"
x.BackColor = Color.Green
x.ForeColor = Color.White
lstView1.Items.Add(x)
End If
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Running"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
serverStatus = serverStatus + 1
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.StartPending Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Starting"
x.BackColor = Color.Blue
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Starting"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.Stopped Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopped"
x.BackColor = Color.Red
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopped"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.StopPending Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopping"
x.BackColor = Color.Red
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopping"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
End If
Failures2()
End If
Next
Catch x As Exception
MsgBox("Failed to obtain service information on server: "
& serverName & ", the error returned was: " & Err.Description)
Timer1.Enabled = False
End Try
aa.EndImpersonation()
End Function
Public Class AliasAccount
Private _username, _password, _domainname As String
Private _tokenHandle As New IntPtr(0)
Private _dupeTokenHandle As New IntPtr(0)
Private _impersonatedUser As
System.Security.Principal.WindowsImpersonationContext
Public Sub New(ByVal username As String, ByVal password As String)
Dim nameparts() As String = username.Split("\")
If nameparts.Length > 1 Then
_domainname = nameparts(0)
_username = nameparts(1)
Else
_username = username
End If
_password = password
End Sub
Public Sub New(ByVal username As String, ByVal password As String,
ByVal domainname As String)
_username = username
_password = password
_domainname = domainname
End Sub
Public Sub BeginImpersonation()
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim win32ErrorNumber As Integer
_tokenHandle = IntPtr.Zero
_dupeTokenHandle = IntPtr.Zero
If Not LogonUser(_username, _domainname, _password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle)
Then
win32ErrorNumber =
System.Runtime.InteropServices.Marshal.GetLastWin32Error()
Throw New ImpersonationException(win32ErrorNumber,
GetErrorMessage(win32ErrorNumber), _username, _domainname)
End If
If Not DuplicateToken(_tokenHandle, SecurityImpersonation,
_dupeTokenHandle) Then
win32ErrorNumber =
System.Runtime.InteropServices.Marshal.GetLastWin32Error()
CloseHandle(_tokenHandle)
Throw New ImpersonationException(win32ErrorNumber, "Unable
to duplicate token!", _username, _domainname)
End If
Dim newId As New
System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
_impersonatedUser = newId.Impersonate()
End Sub
Public Sub EndImpersonation()
If Not _impersonatedUser Is Nothing Then
_impersonatedUser.Undo()
_impersonatedUser = Nothing
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
End If
End Sub
Public ReadOnly Property username() As String
Get
Return _username
End Get
End Property
Public ReadOnly Property domainname() As String
Get
Return _domainname
End Get
End Property
Public ReadOnly Property currentWindowsUsername() As String
Get
Return
System.Security.Principal.WindowsIdentity.GetCurrent().Name
End Get
End Property
#Region "Exception Class"
Public Class ImpersonationException
Inherits System.Exception
Public ReadOnly win32ErrorNumber As Integer
Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As
String, ByVal username As String, ByVal domainname As String)
MyBase.New(String.Format("Impersonation of {1}\{0} failed!
[{2}] {3}", username, domainname, win32ErrorNumber, msg))
Me.win32ErrorNumber = win32ErrorNumber
End Sub
End Class
#End Region
#Region "External Declarations and Helpers"
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
Private Declare Auto Function DuplicateToken Lib
"advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Boolean
Private Declare Auto Function CloseHandle Lib
"kernel32.dll" (ByVal handle As IntPtr) As Boolean
<System.Runtime.InteropServices.DllImport("kernel32.dll")> _
Private 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
Private 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 System.Exception("Failed to format message for
error code " + errorCode.ToString() + ". ")
End If
Return lpMsgBuf
End Function
#End Region
End Class
I'm relatively new to the .net development realm. I am creating an
application in vb.net to monitor services on remote servers.
The application works great when I am logged in and using it - I am a
Domain Admin, and as a result a local admin on the remote computers.
However when I try to run the application as a standard domain user I
receive a priviledges error.
I have attempted to implement impersonation, using credentials
supplied by the application under 'My.Settings' however this seems not
to work either; I recieve a bad username or password error, despite
the fact I know that the passwords and username are correct.
The error clearly displays a valid username in the form of server_name
\userName (note that these remote machines are not part of a domain)
but my username and password are the same for the domain and remote
machines.
I have attched the relevant areas of my code for your viewing, and I
would be really grateful if anyone can point me in the right
direction!
Thanks,
-Chris
NB: Please note the error occurs on the line "aa.BeginImpersonation()"
------------------------------ Beging Code ------------------
Function service2(ByVal srvname)
Dim aa As New AliasAccount(My.Settings.userName,
My.Settings.password, serverName)
Try
aa.BeginImpersonation()
arrRemoteServices =
System.ServiceProcess.ServiceController.GetServices(serverName)
For Each Service In arrRemoteServices
Dim x As New ListViewItem
Dim y As New ListViewItem
If Service.ServiceName = srvname Then
'Can use DisplayName (long name of service)
If Service.Status =
System.ServiceProcess.ServiceControllerStatus.Running Then
If chkLogging.Checked = True Then
x.Text = TimeOfDay & "," & serverName & "
" & Service.ServiceName & ": Running"
x.BackColor = Color.Green
x.ForeColor = Color.White
lstView1.Items.Add(x)
End If
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Running"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
serverStatus = serverStatus + 1
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.StartPending Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Starting"
x.BackColor = Color.Blue
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Starting"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.Stopped Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopped"
x.BackColor = Color.Red
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopped"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
ElseIf Service.Status =
System.ServiceProcess.ServiceControllerStatus.StopPending Then
x.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopping"
x.BackColor = Color.Red
x.ForeColor = Color.White
lstView1.Items.Add(x)
y.Text = TimeOfDay & "," & serverName & " " &
Service.ServiceName & ": Stopping"
y.BackColor = Color.Green
y.ForeColor = Color.White
frmHist.lstView1.Items.Add(y)
End If
Failures2()
End If
Next
Catch x As Exception
MsgBox("Failed to obtain service information on server: "
& serverName & ", the error returned was: " & Err.Description)
Timer1.Enabled = False
End Try
aa.EndImpersonation()
End Function
Public Class AliasAccount
Private _username, _password, _domainname As String
Private _tokenHandle As New IntPtr(0)
Private _dupeTokenHandle As New IntPtr(0)
Private _impersonatedUser As
System.Security.Principal.WindowsImpersonationContext
Public Sub New(ByVal username As String, ByVal password As String)
Dim nameparts() As String = username.Split("\")
If nameparts.Length > 1 Then
_domainname = nameparts(0)
_username = nameparts(1)
Else
_username = username
End If
_password = password
End Sub
Public Sub New(ByVal username As String, ByVal password As String,
ByVal domainname As String)
_username = username
_password = password
_domainname = domainname
End Sub
Public Sub BeginImpersonation()
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim win32ErrorNumber As Integer
_tokenHandle = IntPtr.Zero
_dupeTokenHandle = IntPtr.Zero
If Not LogonUser(_username, _domainname, _password,
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle)
Then
win32ErrorNumber =
System.Runtime.InteropServices.Marshal.GetLastWin32Error()
Throw New ImpersonationException(win32ErrorNumber,
GetErrorMessage(win32ErrorNumber), _username, _domainname)
End If
If Not DuplicateToken(_tokenHandle, SecurityImpersonation,
_dupeTokenHandle) Then
win32ErrorNumber =
System.Runtime.InteropServices.Marshal.GetLastWin32Error()
CloseHandle(_tokenHandle)
Throw New ImpersonationException(win32ErrorNumber, "Unable
to duplicate token!", _username, _domainname)
End If
Dim newId As New
System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
_impersonatedUser = newId.Impersonate()
End Sub
Public Sub EndImpersonation()
If Not _impersonatedUser Is Nothing Then
_impersonatedUser.Undo()
_impersonatedUser = Nothing
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
End If
End Sub
Public ReadOnly Property username() As String
Get
Return _username
End Get
End Property
Public ReadOnly Property domainname() As String
Get
Return _domainname
End Get
End Property
Public ReadOnly Property currentWindowsUsername() As String
Get
Return
System.Security.Principal.WindowsIdentity.GetCurrent().Name
End Get
End Property
#Region "Exception Class"
Public Class ImpersonationException
Inherits System.Exception
Public ReadOnly win32ErrorNumber As Integer
Public Sub New(ByVal win32ErrorNumber As Integer, ByVal msg As
String, ByVal username As String, ByVal domainname As String)
MyBase.New(String.Format("Impersonation of {1}\{0} failed!
[{2}] {3}", username, domainname, win32ErrorNumber, msg))
Me.win32ErrorNumber = win32ErrorNumber
End Sub
End Class
#End Region
#Region "External Declarations and Helpers"
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
Private Declare Auto Function DuplicateToken Lib
"advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Boolean
Private Declare Auto Function CloseHandle Lib
"kernel32.dll" (ByVal handle As IntPtr) As Boolean
<System.Runtime.InteropServices.DllImport("kernel32.dll")> _
Private 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
Private 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 System.Exception("Failed to format message for
error code " + errorCode.ToString() + ". ")
End If
Return lpMsgBuf
End Function
#End Region
End Class