views:

202

answers:

1

Hopefully I'm not missing something obvious here, but I have a class that needs to create some directories on a UNC share and then move files to the new directory. When we connect using LogonUser things work fine with no errors, but when we try and use the user indicated by Integrated Windows authentication we run into problems. Here's some working and non-working code to give you an idea what is going on.

The following works and logs the requested information:

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

IntPtr token;
WindowsIdentity wi;

if (LogonUser("user", "network", "password",
              8, // LOGON32_LOGON_NETWORK_CLEARTEXT
              0, // LOGON32_PROVIDER_DEFAULT
              out token))
{
    wi = new WindowsIdentity(token);
    WindowsImpersonationContext wic = wi.Impersonate();
    Logging.LogMessage(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
    DirectoryInfo info = new DirectoryInfo(path);
    Logging.LogMessage(info.Exists.ToString());
    Logging.LogMessage(info.Name);
    Logging.LogMessage("LastAccessTime:" + info.LastAccessTime.ToString());
    Logging.LogMessage("LastWriteTime:" + info.LastWriteTime.ToString());
    wic.Undo();
    CloseHandle(token);
}

The following fails and gives an error message indicating the network name is not available, but the correct user name is indicated by GetCurrent().Name:

WindowsIdentity identity = (WindowsIdentity)HttpContext.Current.User.Identity;
using (identity.Impersonate())
{
    Logging.LogMessage(System.Security.Principal.WindowsIdentity.GetCurrent().Name);
    DirectoryInfo info = new DirectoryInfo(path);
    Logging.LogMessage(info.Exists.ToString());
    Logging.LogMessage(info.Name);
    Logging.LogMessage("LastAccessTime:" + info.LastAccessTime.ToString());
    Logging.LogMessage("LastWriteTime:" + info.LastWriteTime.ToString());
}
A: 

Please spare some time and completely review this article,

http://msdn.microsoft.com/en-us/library/ms998351.aspx

Lex Li
I must still be missing something because we've double checked to make sure that Network Service is acting as part of the OS and we are still getting the "The specified network name is no longer available." error when running the code in the second example. Granted that since that isn't allowed for production we need to use LogonUser anyway, but there is some academic interest in why one is working and not the other.
Rob