views:

286

answers:

2

I have a webpage that allows a user to upload a file to a network share. When I run the webpage locally (within VS 2008) and try to upload the file, it works! However, when I deploy the website to the webserver and try to upload the file through the webpage, it doesn't work!

The error being returned to me on the webserver says "Access to the path '\05prd1\emp\test.txt' is denied. So, obviously, this is a permissions issue.

The network share is configured to allow full access both to me (NT authentication) and to the NETWORK SERVICE (which is .NET's default account and what we have set in our IIS application pool as the default user for this website).

I have tried this with and without impersonation upon the webserver and neither way works, yet both ways work on my local machine (in other words, with and without impersonation works on my local machine).

The code that does the file upload is below. Please note that the code below includes impersonation, but like I said above, I've tried it with and without impersonation and it's made no difference.

if (fuCourses.PostedFile != null && fuCourses.PostedFile.ContentLength > 0) {
    System.Security.Principal.WindowsImpersonationContext impCtx;
    impCtx =
        ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

    try {
        lblMsg.Visible = true;

        // The courses file to be uploaded
        HttpPostedFile file = fuCourses.PostedFile;
        string fName = file.FileName;
        string uploadPath = "\\\\05prd1\\emp\\";

        // Get the file name
        if (fName.Contains("\\")) {
            fName = fName.Substring(
                fName.LastIndexOf("\\") + 1);
        }

        // Delete the courses file if it is already on \\05prd1\emp
        FileInfo fi = new FileInfo(uploadPath + fName);
        if (fi != null && fi.Exists) {
            fi.Delete();
        }

        // Open new file stream on \\05prd1\emp and read bytes into it from file upload
        FileStream fs = File.Create(uploadPath + fName, file.ContentLength);

        using (Stream stream = file.InputStream) {
            byte[] b = new byte[4096];
            int read;

            while ((read = stream.Read(b, 0, b.Length)) > 0) {
                fs.Write(b, 0, read);
            }
        }

        fs.Close();

        lblMsg.Text = "File Successfully Uploaded";
        lblMsg.ForeColor = System.Drawing.Color.Green;
    }
    catch (Exception ex) {
        lblMsg.Text = ex.Message;
        lblMsg.ForeColor = System.Drawing.Color.Red;
    }
    finally {
        impCtx.Undo();
    }
}

Any help on this would be very appreciated!

A: 

You don't mention what kind of authentication you are using in IIS.

If you are relying on Windows Integrated/NTLM authentication then I think you will have a problem in that unless you can configure Kerberos on your servers, the user's authentication token can't be used beyond the current (web) server - the "double-hop" problem.

If you use Basic (in IIS) or Forms (via ASP.NET), then you will have access to the user's password in clear text. You can then call the Impersonation code using the username/password and should be able to access the shared folder as that user.

I'm also pretty certain that if you use Basic authentication, then the <identity impersonate="true"> tag will work for network share access.

Check out KB 306158 for some more info and code samples too.

David Gardiner
Yes, our domain uses NTLM for authentication, and within my website I use Windows authentication as well. I tried using programmatic impersonation in order to authenticate the user at the file server (on the 2nd hop), but it didn't work. I was able to verify this by going to the security logs on the file server. The security logs showed that the request came from the webserver and that it tried to use the webserver to authenticate and not the user that was being impersonated.
Jagd
Just to clarify, impersonation doesn't work on the 2nd hop. It works up to the webserver, but after that it gets shot down. And I believe this happens because, as we said earlier, Kerberos is not being delegated properly (which is out of my control).
Jagd
That's correct. If you're stuck with NTLM then the second hop will bite you.
David Gardiner
A: 

The problem exists in the fact that Kerberos is not being delegated from the webserver to the file server. The ideal solution would be to delegate Kerberos to the file server. Unfortunately, this is not something that I have the power to change. Too much red tape and too much politics. However, I have come up with a hack of sorts.

I created a temporary folder located at the root of the website. Using impersonation, I write the file to this temporary folder (it gets uploaded to this temp folder, in other words).

Having wrote the file to the temp folder, I then copy the file to the file server UNC. This is the 2nd hop, and this is where it makes no difference whether I'm using impersonation or not - because the credentials being sent to the file server are those of the webserver itself. So, what this forced me to do was to give read/write access to the webserver on the UNC share. After doing all of this, the file copy worked as expected.

Jagd