2LeggedSpider

Upload files to UNC share using ASP.NET

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

[tweetmeme style=”compact”]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

Advertisements
Tagged with: , ,

9 Responses

Subscribe to comments with RSS.

  1. rekha said, on February 16, 2011 at 6:55 pm

    Thaks u sumit..very useful post…

  2. Chet Kutzer said, on October 5, 2011 at 6:57 pm

    This site is really a stroll-through for all of the data you wished about this and didn?t know who to ask. Glimpse here, and also you?ll definitely uncover it.

  3. Jill Borozny said, on October 10, 2011 at 6:20 pm

    Aw, this was a very nice post. In thought I would like to put in writing like this moreover ? taking time and precise effort to make a very good article? but what can I say? I procrastinate alot and under no circumstances appear to get one thing done.

  4. earn money said, on November 10, 2011 at 9:43 pm

    I savor, result in I discovered exactly what I was taking a look for. You’ve ended my 4 day lengthy hunt! God Bless you man. Have a great day. Bye

  5. John said, on September 19, 2012 at 10:48 pm

    You should mention the source http://support.microsoft.com/kb/306158

  6. maricaelultimo.wordpress.com said, on May 14, 2013 at 11:07 pm

    Very good information. Lucky me I recently found your
    site by chance (stumbleupon). I’ve book-marked it for later!

  7. Leola said, on March 17, 2014 at 3:48 pm

    It’s an awesome article for all the web users; they will get benefit from it I am sure.

  8. Vikram said, on October 21, 2014 at 8:44 am

    Wonderful post. Could you please explain me the link between the Impersonation and file path in the code. I tried on my development server it works whereas in IIS it doesn’t. I have placed tag under my in the web.config file and my Pool identity is set to ApplicationPoolIdentity.

  9. Vikram said, on October 21, 2014 at 8:46 am

    Sorry all the “” markups have been truncated . ** I have placed the identity impersonate tag under system.web section of my web.config file.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: