c# - respuesta - Cómo usar LogonUser correctamente para suplantar al usuario del dominio del cliente del grupo de trabajo
modelo de respuesta a quejas y reclamos (6)
El inicio de sesión / contraseña inválido también podría estar relacionado con problemas en su servidor DNS; eso es lo que me sucedió y me costó 5 horas de mi vida. Vea si puede especificar la dirección IP en lugar del nombre de dominio.
ASP.NET: Suplantar contra un dominio en VMWare
Esta pregunta es lo que estoy preguntando, pero la respuesta no proporciona detalles sobre cómo se deriva el _token. Parece que solo usa WindowsIdentity.GetCurrent().Token
para que no ocurra ninguna suplantación.
¿Puedo suplantar a un usuario en un dominio diferente de Active Directory en .NET?
Esta próxima pregunta tiene respuestas contradictorias, y la aceptada contiene un comentario: "Estoy empezando a sospechar que mi problema está en otra parte". No es útil.
LogonUser solo funciona para mi dominio
La siguiente pregunta parece implicar que no es posible, pero trata con 2 dominios, por lo que no estoy seguro de si es relevante.
Mi verdadera pregunta es:
- ¿Es posible? Y de ser así,
- ¿Cómo? o ¿Dónde me equivoqué?
Lo que he intentado hasta ahora es usar el código de http://msdn.microsoft.com/en-us/library/chf6fbt4%28v=VS.80%29.aspx
bool returnValue = LogonUser(user, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
// after this point, returnValue = false
El error de Win32 es
Error de inicio de sesión: nombre de usuario desconocido o contraseña incorrecta
Es mejor usar un SecureString:
var password = new SecureString();
var phPassword phPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
IntPtr phUserToken;
LogonUser(username, domain, phPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out phUserToken);
Y:
Marshal.ZeroFreeGlobalAllocUnicode(phPassword);
password.Dispose();
Definición de la función:
private static extern bool LogonUser(
string pszUserName,
string pszDomain,
IntPtr pszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
Estaba teniendo el mismo problema. No sé si ha resuelto esto o no, pero lo que realmente estaba tratando de hacer era acceder a una red compartida con credenciales de AD. WNetAddConnection2()
es lo que necesita usar en ese caso.
He logrado suplantar a usuarios en otro dominio, pero solo con una configuración de confianza entre los 2 dominios.
var token = IntPtr.Zero;
var result = LogonUser(userID, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);
if (result)
{
return WindowsIdentity.Impersonate(token);
}
Muy pocas publicaciones sugieren el uso de LOGON_TYPE_NEW_CREDENTIALS
lugar de LOGON_TYPE_NETWORK
o LOGON_TYPE_INTERACTIVE
. Tuve un problema de suplantación con una máquina conectada a un dominio y otra no, y esto lo solucionó. El último fragmento de código en esta publicación sugiere que la suplantación en un bosque funciona, pero no dice nada específicamente sobre la configuración de la confianza. Así que esto puede valer la pena intentarlo:
const int LOGON_TYPE_NEW_CREDENTIALS = 9;
const int LOGON32_PROVIDER_WINNT50 = 3;
bool returnValue = LogonUser(user, domain, password,
LOGON_TYPE_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50,
ref tokenHandle);
MSDN dice que LOGON_TYPE_NEW_CREDENTIALS
solo funciona cuando se usa LOGON32_PROVIDER_WINNT50
.
esto funciona para mí, ejemplo completo de trabajo (ojalá más personas lo hicieran):
//logon impersonation
using System.Runtime.InteropServices; // DllImport
using System.Security.Principal; // WindowsImpersonationContext
using System.Security.Permissions; // PermissionSetAttribute
...
class Program {
// obtains user token
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
// closes open handes returned by LogonUser
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
public void DoWorkUnderImpersonation() {
//elevate privileges before doing file copy to handle domain security
WindowsImpersonationContext impersonationContext = null;
IntPtr userHandle = IntPtr.Zero;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
string domain = ConfigurationManager.AppSettings["ImpersonationDomain"];
string user = ConfigurationManager.AppSettings["ImpersonationUser"];
string password = ConfigurationManager.AppSettings["ImpersonationPassword"];
try {
Console.WriteLine("windows identify before impersonation: " + WindowsIdentity.GetCurrent().Name);
// if domain name was blank, assume local machine
if (domain == "")
domain = System.Environment.MachineName;
// Call LogonUser to get a token for the user
bool loggedOn = LogonUser(user,
domain,
password,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
ref userHandle);
if (!loggedOn) {
Console.WriteLine("Exception impersonating user, error code: " + Marshal.GetLastWin32Error());
return;
}
// Begin impersonating the user
impersonationContext = WindowsIdentity.Impersonate(userHandle);
Console.WriteLine("Main() windows identify after impersonation: " + WindowsIdentity.GetCurrent().Name);
//run the program with elevated privileges (like file copying from a domain server)
DoWork();
} catch (Exception ex) {
Console.WriteLine("Exception impersonating user: " + ex.Message);
} finally {
// Clean up
if (impersonationContext != null) {
impersonationContext.Undo();
}
if (userHandle != IntPtr.Zero) {
CloseHandle(userHandle);
}
}
}
private void DoWork() {
//everything in here has elevated privileges
//example access files on a network share through e$
string[] files = System.IO.Directory.GetFiles(@"//domainserver/e$/images", "*.jpg");
}
}