1

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 ?

Marc
  • 983
  • 2
  • 12
  • 28
  • You should reference where you got the Impersonator class from, since it's not part of the .NET Framework. I'm guessing it's this one, http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User from Code Project? – JamieSee Mar 08 '12 at 16:00
  • 1
    Have you tried using the DirectoryEntry Constructor (String, String, String, AuthenticationTypes) that takes a username and password instead of impersonation? – JamieSee Mar 08 '12 at 16:38
  • @JamieSee: If you look closely to my question, you will see I provided a link to the Impersonator class I used. In fact I started with the CodeProject class, but I also added an enum for the ImpersonationLevel, just like in the class I linked, so I prefered linking that one, as it was easer to explain my experimentation with the ImpersonationLevel. – Marc Mar 08 '12 at 18:39
  • @JamieSee(2): I didn't notice the other contructors as the HasVirtualDirectory function was written by a co-worker and I didn't check it :(. I tried using `DirectoryEntry directoryEntry = new DirectoryEntry("IIS://" + serverName + "/W3SVC/1/Root", @"domain\username", "password", AuthenticationTypes.Secure | AuthenticationTypes.Sealing);` and it worked ! Thanks. Put up your suggestion as answer and I'll accept it gladly :) – Marc Mar 08 '12 at 18:59
  • I'm glad that helped you. I've posted it as an answer. – JamieSee Mar 08 '12 at 19:43

2 Answers2

2

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);
JamieSee
  • 12,696
  • 2
  • 31
  • 47
  • Thanks, that worked. But if anyone still can tell me why the Impersonate didn't work, go ahead :) – Marc Mar 08 '12 at 19:51
0

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

JamieSee
  • 12,696
  • 2
  • 31
  • 47
  • I forgot to mention it in my question, but I read that comment too and I tried using LOGON32_LOGON_NEW_CREDENTIALS, it gave the same exception. I now tried it again, and tried combining it with ImpersonationLevel.SecurityDelegation in Duplicatetoken and/or running the program as Administrator, but I always get the same exception. – Marc Mar 08 '12 at 18:48