none
UnauthorizedAccessException when using FileStream to open remote file from SharePoint web app

    Question

  • I have a simple SharePoint application page that opens a file on a button click event (using FileStream()). 

    It works fine when I try to read a local file (\\thishost\foo.txt), but throws an UnauthorizedAccessException if I try to read a remote file (\\remotehost\foo.txt).

     

    I created the same program as an ASP .NET Web Application and it works fine reading both local and remote files. 

     

    The remote directory's permissions are set so "Everyone" has full control and the directory is shared.

     

    The page displays the current user.  Both the SharePoint app page and the .NET web app page show the current user as my domain account.

     

    How can I tell which user the FileStream gets run as?  WindowsIdentity.GetCurrent()?

     

    Is there some setting in SharePoint or IIS that is restricting the File IO access permissions on remote shares?

     

    Any help is greatly appreciated.

    Thanks

     

     

    System.UnauthorizedAccessException: Access to the path '\\remotehost\foo.txt' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access) at MyApp.Select_Button_OnClick(Object sender, EventArgs e)

     

    // Simple on click method that display the current user and tries

    // to open a read filestream on the specified file.

    protected void Select_Button_OnClick(object sender, EventArgs e)

    {

        Status_Label.Text = "";

        string fileName = FilePath_TextBox.Text;

        User_Label.Text = WindowsIdentity.GetCurrent().Name + "(" +

             System.Environment.UserDomainName + "\\" + System.Environment.UserName + ")";

        try {

            using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {

                Status_Label.Text = "Success!";

            }

        } catch (Exception e1) {

           Status_Label.Text = "Problem. " + e1.ToString();

        }

    }

    Friday, April 25, 2008 7:51 PM

Answers

  •  

    By default ASP.NET code in a sharepoint server (Win 2003) runs with system account Network Service and will throw an Access Denied! error on writing a file to a network share. The best way is to Impersonate windows idenetity to do the network activity. http://support.microsoft.com/kb/306158
    Thursday, May 01, 2008 4:52 PM

All replies

  • Try to use System.Net.NetworkCredential namepace

    Saturday, April 26, 2008 7:12 AM
  • How do you use NetworkCredentials with a FileStream?  FileStream doesn't seem to have a way to set credentials. 

    I don't think impersontation will help, because when I call the page, I am logged in as a valid user and everyone has permission to read and write to the share.

    It seems like it might be a permission issue related to trust levels.  Because the same code works as a .NET web application on the same web site, but doesn't work as a SharePoint application page in the _layouts directory.  I tried changing the trust level in SharePoint's web.config files to "Full" but that didn't help either.

      C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\CONFIG\web.config
      C:\Inetpub\wwwroot\wss\VirtualDirectories\80\web.config


    I am able to read a file on a network share and pass credentials using the FileWebRequest class.
    But I need to be able to write files as well, that is why I am hoping to use FileStream.

      FileWebRequest request = (FileWebRequest)WebRequest.Create(fileName);
      request.Method = "GET";
      request.Credentials = new NetworkCredential("username", "password", "domain"); 
      WebProxy proxy = new WebProxy("http://proxy.company.com:3128", true);
      request.Proxy = proxy;
      request.Timeout = (1000 * 60 * 2); // timeout in milliseconds (2 minutes)
      using (WebResponse webResponse = request.GetResponse())
      {
          using (Stream stream = webResponse.GetResponseStream())
          {
              ...


    Here is the SharePoint app page code (_layouts/foo.aspx) that fails.  All the code is in one aspx page (no code behind).

      <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
      <%@ Page Language="C#" MasterPageFile="~/_layouts/application.master" EnableViewState="false" EnableViewStateMac="false" %>
      <%@ Import Namespace="System.IO" %>
      <%@ Import Namespace="System.Security.Principal" %>
      <asp:Content ID="PageTitle" runat="server" ContentPlaceHolderID="PlaceHolderPageTitle">Test FileStream</asp:Content>
      <asp:Content ID="PageTitleInTitleArea" runat="server" ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea">Test FileStream</asp:Content>
      <asp:Content ID="Main" contentplaceholderid="PlaceHolderMain" runat="server">
       <h2>Test using FileStream from SharePoint application page</h2>
       <asp:Label ID="Status_Label" runat="server"></asp:Label>    
      </asp:Content>
      <script runat="server" language="C#">
          protected override void OnLoad(EventArgs e)
          {
              //string fileName = @"\\localmachine\dir\test.txt"; // works fine
              string fileName = @"\\remotemachine\dir\test.txt";  // throws unauthorized
              using (FileStream fw = new FileStream(fileName, FileMode.Create, FileAccess.Write))
              {
                 byte[] buf = new byte[100];
                 System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                 buf = encoding.GetBytes("Test string " + DateTime.Now.ToLongTimeString());
                 fw.Write(buf, 0, buf.Length);    
              }
              base.OnLoad(e);
          }
      </script>



     
    Sunday, April 27, 2008 7:21 AM
  • It was a problem with the WSS or IIS user not having permission.  Calling WindowsIdentity.Impersonate() before calling DirectoryInfo and FileStream did the trick.


    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();

    Sunday, April 27, 2008 11:13 PM
  •  

    By default ASP.NET code in a sharepoint server (Win 2003) runs with system account Network Service and will throw an Access Denied! error on writing a file to a network share. The best way is to Impersonate windows idenetity to do the network activity. http://support.microsoft.com/kb/306158
    Thursday, May 01, 2008 4:52 PM