2LeggedSpider

Upload files to UNC share using ASP.NET

Posted in ASP.NET, C# by Sumit Thomas on May 28, 2007

SCENARIO 1: Your ASP.NET website should upload files to a File Server accessible via an UNC share

SOLUTION

  1. Create a Local User Account in the Web server with Username say “TestUser” and Password say “Secret” of your choice
  2. Create a Local User Account in File server with the same Username “TestUser” and Password “Secret” as the one created in the Web server.
  3. In Web.config set the impersonation to true for the above Local User Account as follows…
    
    

    And your upload script will be something like this…

                    if ((FileUpload1.PostedFile != null) && (FileUpload1.PostedFile.ContentLength > 0))
                    {
                        string fileName = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
                        string folderPath = @"\\MyUNCShare\MyFolder\";
    
                        string locationToSave = folderPath + "\\" + fileName ;
                        try
                        {
                            FileUpload1.PostedFile.SaveAs(locationToSave );
                            Response.Write("The file has been uploaded.");
                        }
                        catch (Exception ex)
                        {
                            Response.Write("Error: " + ex.Message);
                        }
                    }
                    else
                    {
                        Response.Write("Please select a file to upload.");
                    }
    
    

    Run the code and test the upload and it should work.

    SCENARIO 2:
    Now this is fine for a demo. But what if I want to setup Windows authentication for my application but restrict the authenticated users of the application from directly accessing the UNC share to copy files? Any uploads to the UNC share should be done only using the Local User Account that I created earlier.

    To solve this issue do the following…

    1) Change the identity impersonate tag in Web.config to

    <identity impersonate="true" />

    , assuming that you have enabled Windows authentication in IIS as well.

    2) Change the impersonation at runtime to the Local User Account, upload the file and then undo the impersonation. To do this use the following code…

    
    using System.Security.Principal;
    using System.Runtime.InteropServices;
    
    namespace FileUploadUNCShare
    {
        public partial class _Default : System.Web.UI.Page
        {
    
            public const int LOGON32_LOGON_INTERACTIVE = 2;
            public const int LOGON32_PROVIDER_DEFAULT = 0;
    
            WindowsImpersonationContext impersonationContext;
    
            [DllImport("advapi32.dll")]
            public static extern int LogonUserA(String lpszUserName,
                String lpszDomain,
                String lpszPassword,
                int dwLogonType,
                int dwLogonProvider,
                ref IntPtr phToken);
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern int DuplicateToken(IntPtr hToken,
                int impersonationLevel,
                ref IntPtr hNewToken);
    
            [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            public static extern bool RevertToSelf();
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
            public static extern bool CloseHandle(IntPtr handle);
    
            private bool ImpersonateUser(String userName, String domain, String password)
            {
                WindowsIdentity tempWindowsIdentity;
                IntPtr token = IntPtr.Zero;
                IntPtr tokenDuplicate = IntPtr.Zero;
    
                if (RevertToSelf())
                {
                    if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                        LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                    {
                        if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                        {
                            tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                            impersonationContext = tempWindowsIdentity.Impersonate();
                            if (impersonationContext != null)
                            {
                                CloseHandle(token);
                                CloseHandle(tokenDuplicate);
                                return true;
                            }
                        }
                    }
                }
                if (token != IntPtr.Zero)
                    CloseHandle(token);
                if (tokenDuplicate != IntPtr.Zero)
                    CloseHandle(tokenDuplicate);
                return false;
            }
    
            private void UndoImpersonation()
            {
                impersonationContext.Undo();
            }
    
            protected void Page_Load(object sender, EventArgs e)
            {
    
            }
    
            protected void Button1_Click(object sender, EventArgs e)
            {
                if (ImpersonateUser("Test_Share", "", "@Dell123"))
                {
    
                    if ((FileUpload1.PostedFile != null) &amp;&amp; (FileUpload1.PostedFile.ContentLength &gt; 0))
                    {
                        string fileName = System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName);
                        string folderPath = @"\\MyUNCShare\MyFolder\";
    
                        string locationToSave = folderPath + "\\" + fileName;
                        try
                        {
                            FileUpload1.PostedFile.SaveAs(locationToSave);
                            Response.Write("The file has been uploaded.");
                        }
                        catch (Exception ex)
                        {
                            Response.Write("Error: " + ex.Message);
                        }
                    }
                    else
                    {
                        Response.Write("Please select a file to upload.");
                    }
    
                    UndoImpersonation();
                }
                else
                {
                    Response.Write("Failed");
                }
    
            }
        }
    }
    

    This will ensure that the impersonation you need to upload the file does not interfere with the Application level impersonation you may want to use.

    Hope it is useful!

    Cheers!

    ref: http://support.microsoft.com/kb/306158

Tagged with: , ,
Follow

Get every new post delivered to your Inbox.