Comment utiliser LogonUser correctement pour imiter l'utilisateur du domaine du client workgroup

ASP.NET: Impersonate contre un domaine sur VMWare

cette question Est ce que je demande, mais la réponse ne fournit pas de détails sur la façon dont le _token est dérivé. Il semble n'utiliser que WindowsIdentity.GetCurrent().Token donc il n'y a pas d'usurpation d'identité.

puis-je imiter un utilisateur sur un autre domaine Active Directory dans .NET?

Cette question a des réponses contradictoires, avec celui accepté portant un commentaire "je commence à soupçonner que mon problème réside ailleurs."Pas utile.

LogonUser ne fonctionne que pour mon domaine

cette question suivante semble impliquer que ce n'est pas possible, mais elle traite de 2 domaines, donc je ne suis pas sûr si elle est pertinente.

ma vraie question Est:

  • est-ce possible? et si oui,
  • comment? ou Où ai-je mal tourné?

ce que j'ai essayé jusqu'à présent est, en utilisant le code 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

L'erreur Win32 est

échec de connexion: nom d'utilisateur inconnu ou mauvais mot de passe

37
demandé sur Community 2011-02-17 02:48:03

6 réponses

très peu de billets suggèrent d'utiliser LOGON_TYPE_NEW_CREDENTIALS au lieu de LOGON_TYPE_NETWORK ou LOGON_TYPE_INTERACTIVE . J'ai eu un problème d'usurpation d'identité avec une machine connectée à un domaine et une autre non, et cela l'a corrigé. Le dernier extrait de code dans ce post suggère que l'usurpation d'identité à travers une forêt fonctionne, mais il ne dit pas spécifiquement quoi que ce soit sur la confiance étant mis en place. Cela vaut donc peut-être la peine d'essayer:

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 dit que LOGON_TYPE_NEW_CREDENTIALS ne fonctionne qu'avec LOGON32_PROVIDER_WINNT50 .

54
répondu takrl 2013-01-28 10:08:37

cela fonctionne pour moi, exemple de travail complet (je souhaite que plus de gens feraient cela):

//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");
    }
}
17
répondu JJ_Coder4Hire 2013-06-20 15:02:54

j'ai réussi à imiter des utilisateurs dans un autre domaine, mais seulement avec une confiance établie entre les deux domaines.

var token = IntPtr.Zero;
var result = LogonUser(userID, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token);
if (result)
{
    return WindowsIdentity.Impersonate(token);
}
1
répondu Jason 2011-12-01 06:38:20

j'avais le même problème. Je ne sais pas si vous avez résolu ceci ou non, mais ce que j'essayais vraiment de faire était d'accéder à un partage de réseau avec des identifiants publicitaires. WNetAddConnection2() est ce que vous devez utiliser dans ce cas.

0
répondu Conrad 2011-10-07 20:28:55

Connexion/Mot de passe invalide pourrait aussi être lié à des problèmes dans votre serveur DNS - c'est ce qui m'est arrivé et m'a coûté bon 5 heures de ma vie. Voir si vous pouvez spécifier l'adresse ip à la place sur le nom de domaine.

0
répondu Dan 2014-03-20 22:27:30

il est préférable d'utiliser une sécurisation:

var password = new SecureString();
var phPassword phPassword = Marshal.SecureStringToGlobalAllocUnicode(password);
IntPtr phUserToken;
LogonUser(username, domain, phPassword, LOGON32_LOGON_INTERACTIVE,  LOGON32_PROVIDER_DEFAULT, out phUserToken);

et:

Marshal.ZeroFreeGlobalAllocUnicode(phPassword);
password.Dispose();

définition de la fonction:

private static extern bool LogonUser(
  string pszUserName,
  string pszDomain,
  IntPtr pszPassword,
  int dwLogonType,
  int dwLogonProvider,
  out IntPtr phToken);
0
répondu Tovich 2017-08-11 12:25:52