È possibile duplicare il seguente processo di credenziali in VB.NET?
-
03-07-2019 - |
Domanda
Soluzione (kinda):
Si scopre che questa rappresentazione della sicurezza di .NET consente solo l'accesso a livello di applicazione. Poiché l'oggetto COM è a livello di sistema, l'utente impersonato non può ancora istanziarlo. L'ho capito facendo clic con il pulsante destro del mouse sull'eseguibile e selezionando " Esegui come ... " ;, il programma ha funzionato bene. Ho scoperto che avvia il programma con accesso al sistema (supponendo che l'utente con cui lo stai eseguendo abbia tali credenziali). Ora sto creando un programma esterno che avvierà questa applicazione usando questo metodo.
Grazie per i suggerimenti: D
Ho un'installazione di Windows XP su una macchina virtuale. Fa parte del mio dominio, ma l'utente che ha effettuato l'accesso è solo un utente locale. Ovviamente, se provo ad accedere a una condivisione di rete, verrà richiesto un utente / password:
Il programma che sto testando sulla macchina virtuale utilizza un oggetto COM per interfacciarsi con i dati di un altro programma. Se non impersono, ricevo errori perché non ho le credenziali appropriate.
Ho fatto qualche ricerca sulla questione e ho trovato un numero di siti Web che contenevano una discreta quantità di informazioni su VB.NET. Il problema che sto riscontrando con il codice che ho scritto è che posso accedere alle risorse di rete, ma non posso creare un'istanza dell'oggetto COM.
Se compilo e invio il prompt delle credenziali (sopra) prima di provare a crearne un'istanza, funziona perfettamente. Questo mi porta a credere che ci debba essere qualcosa che il prompt delle credenziali di WinXP sta facendo, ma non lo sono. Di seguito è riportato il codice che sto usando per la rappresentazione:
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()
_impersonating = True
End Sub
Ho anche provato a inviare diversi flag al metodo imitatore, ma nulla sembra funzionare. Ecco le diverse bandiere che ho trovato:
Enum LOGON32_LOGON
INTERACTIVE = 2
NETWORK = 3
BATCH = 4
SERVICE = 5
UNLOCK = 7
NETWORK_CLEARTEXT = 8
NEW_CREDENTIALS = 9
End Enum
Enum LOGON32_PROVIDER
[DEFAULT] = 0
WINNT35 = 1
WINNT40 = 2
WINNT50 = 3
End Enum
Enum SECURITY_LEVEL
Anonymous = 0
Identification = 1
Impersonation = 2
Delegation = 3
End Enum
Soluzione
Mi sono imbattuto in questo in precedenza e ho usato due diversi assoli: il più semplice era usare un'app di terze parti: TqcRunas: http://www.quimeras.com/Products/products.asp che consente di impacchettare le credenziali richieste in un file crittografato. Tuttavia è un problema se la password è forzata a scadere.
L'altra soluzione che ho usato è quella di chiamare un nuovo processo con credenziali alternative:
Dim myProcessStartInfo As ProcessStartInfo = New ProcessStartInfo
With myProcessStartInfo
.FileName = "file path and name"
.Domain = "domainname"
.UserName = "username"
'password needs to be a SerureString
Using NewPassword As New Security.SecureString
With NewPassword
For Each c As Char In "password".ToCharArray
.AppendChar(c)
Next c
.MakeReadOnly()
End With
.Password = NewPassword.Copy
End Using
'UseShellExecute must be false for impersonated process
.UseShellExecute = False
End With
Using Process As New System.Diagnostics.Process
With Process
.StartInfo = myProcessStartInfo
.Start()
End With
End Using
Altri suggerimenti
Con le tue definizioni, io uso
LogonUser(_username, _domainname, _password, LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50, _tokenHandle)
nel mio codice che si sta autenticando attraverso la rete. Sto impersonando un utente locale sulla scatola remota, come te. È stato tanto tempo fa che non ricordo la logica per l'utilizzo di questi valori.
Faccio una cosa simile per mappare le unità di rete per copiare file tra macchine. Non ho scritto il codice ma è praticamente uguale al tuo, tranne due cose:
-
Dopo che il metodo Impersonate ritorna chiudo entrambi i token usando la routine CloseHandle, prima di uscire dal mio metodo di rappresentazione.
-
Nella parte superiore dell'imitatore la prima cosa che succede è una chiamata a RevertToSelf, presumibilmente per annullare qualsiasi imitazione precedente.
Non so se farebbero la differenza, ma vale la pena provare. Ecco le dichiarazioni pertinenti:
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long