Impersonate not working for DirectoryServices

2019-08-12 07:29发布

问题:

I'm trying to execute the following code

using System.DirectoryServices;

public bool HasVirtualDirectory(string serverName, string virtualDirectoryName)
{
    try
    {
        DirectoryEntry directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root");
        return directoryEntry.Children.Find(virtualDirectoryName, directoryEntry.SchemaClassName.ToString()) != null;
    }
    catch (Exception)
    {
        return false;
    }
}

As I need adminstrator rights on the server to execute this code, I used this class to impersonate the correct user:

using (Impersonator impersonator = new Impersonator("username", "domain", "password"))
{
    server.HasAccess = HasVirtualDirectory(server.HostName, virtualDirectory);
}

But I still get the COMException: Access is denied. On the other hand, if I don't use the impersonate but I run the program directly with the same credentials I used in the impersonate (by using "Run as different user" in the context menu) it works as expected.

Running the program as administrator (administrator on the machine running the program, but not administrator on the server) did not change anything, the exception still occured.

I also tried ImpersonationLevel.SecurityDelegation (=3) instead of ImpersonationLevel.SecurityImpersonation (=2) in the DuplicateToken call, but that did not change anything either (both as normal or administrator user executing the program).

To test the impersonate code, I tried the following code, and that worked. (the user executing the program does not have the rights to create the directory, but the impersonated user does).

using (Impersonator impersonator = new Impersonator("username", "domain", "password"))
{
    Directory.CreateDirectory(@"\\servername\c$\tmp");
}

I'm using Windows 7 Professional with UAC activated. The server is a Windows Server 2003 R2 SP2.

Does anyone have any ideas ?

回答1:

Use the DirectoryEntry Constructor (String, String, String, AuthenticationTypes) that takes a username and password instead of impersonation.

DirectoryEntry directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root", @"domain\username", "password", AuthenticationTypes.Secure | AuthenticationTypes.Sealing);


回答2:

Assuming you are using the Impersonator class from CodeProject, try changing the logon type as indicated in this posting from page 4 of the comments:

Hi Uwe,

it only works for remote access from vista when you change the logontype in the logonuser function to LOGON32_LOGON_NEW_CREDENTIALS.

const int LOGON32_LOGON_NEW_CREDENTIALS = 9;

see LogonUser function

Regards Uwe