views:

298

answers:

2

Short Version: Can anyone say whether it's possible or not to use impersonation in ASP.NET to access mapped drives?

Long Version:
I'm currently using impersonation in ASP.NET to gain access to network files. This is working perfectly for any network file using a UNC path, but it is failing to access any files on mapped drives defined for the user account I'm impersonating.

For example, let's say a file lives on the network at "\machine\folder\file.txt", and let's also say that drive S: is mapped to "\machine\folder". We need to be able to access both the full UNC path, "\machine\folder\file.txt", as well as the shorter, mapped drive path, "S:\file.txt".

Obviously the standard ASP.NET process cannot access either.

Using a console application that runs under the local account with the mapped S: drive, calling File.Exists(@"\machine\folder\file.txt") returns true, and File.Exists(@"S:\file.txt") also returns true.

However, when impersonating in an ASP.NET context with the same local account, only File.Exists(@"\machine\folder\file.txt") returns true. File.Exists(@"S:\file.txt") returns false.

I'm testing with IIS 7 running on my local Windows 7 Professional box, though this will need to run in both IIS 6 and IIS 7.

Impersonation is handled with a couple of classes in C# which I'll include here:

public static class Impersonation
{
    private static WindowsImpersonationContext context;

    public static void ImpersonateUser(string username, string password)
    {
        ImpersonateUser(".", username, password);
    }

    public static void ImpersonateUser(string domain, string username, string password)
    {             
        StopImpersonating();

        IntPtr userToken;
        var returnValue = ImpersonationImports.LogonUser(username, domain, password,
                                                  ImpersonationImports.LOGON32_LOGON_INTERACTIVE,
                                                  ImpersonationImports.LOGON32_PROVIDER_DEFAULT,
                                                  out userToken);
        context = WindowsIdentity.Impersonate(userToken);
    }

    public static void StopImpersonating()
    {
        if (context != null)
        {
            context.Undo();
            context = null;
        }
    }
}

public static class ImpersonationImports
{
    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_LOGON_NETWORK = 3;
    public const int LOGON32_LOGON_BATCH = 4;
    public const int LOGON32_LOGON_SERVICE = 5;
    public const int LOGON32_LOGON_UNLOCK = 7;
    public const int LOGON32_LOGON_NETWORK_CLEARTEXT = 8;
    public const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int LogonUser(
        string lpszUsername,
        string lpszDomain,
        string lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        out IntPtr phToken
        );
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int ImpersonateLoggedOnUser(
        IntPtr hToken
    );

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int RevertToSelf();

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern int CloseHandle(IntPtr hObject);
}

Then, during Page_Load, we basically do something like this:

Impersonation.ImpersonateUser("DOMAIN", "username", "password");

if (!File.Exists(@"S:\file.txt"))
     throw new WeCannotContinueException();

I realize using mapped drives isn't a best practice, but for legacy reasons it's desirable for our business. Can anyone say whether it's possible or not to use impersonation in ASP.NET to access mapped drives?

A: 

No. You can however use a symbolic link instead. Mklink /d will create a directory link. Hth.

Scott
Thanks. The only way mklink helps is if we can continue to use the mapped drive path (i.e. "S:\file.txt"). But unless I'm mistaken, I don't believe mklink allows this.
adamjcooper
And, for myself and anyone else who's interested, can you elaborate on why this isn't possible?
adamjcooper
I would think this would work. We have a (native C++) service that runs as LocalSystem and impersonates users where necessary; it is able to access mapped drives just fine. I just verified on Windows 7 to double check. I don't know why this wouldn't work under ASP.NET.
Luke
A: 

You can only access mapped drives that were created by the user being impersonated.

So if you were to impersonate user X then map the share (e.g., via net use) then that share will be visible for as long as the impersonation is in effect.

You can determine which mapped drives are currently accessible via DriveInfo.GetDrives(). Drives with a DriveType of Network are accessible in the current security context.

Arnshea