10

In our WSS 3.0 application, we have a document library that has an elevated folder called "Approved". It has different permissions from the rest of the Document Library in order to prevent people from normal access to it for uploads or editing. The only entities that have full access to that folder are an Administration group, including myself.

However, we do have a scenario where it is necessary to upload straight to it. I devised a simple ASPX page with a FileUpload control, which then uses SPSecurity.RunWithElevatedPrivileges (in itself inside of a SPLongOperation) to attempt an upload to that folder. If I run it, the thing runs smoothly, the file is uploaded, everything is green. But whenever one of our engineers tries it, they get an "Access Denied" error for having insufficient privileges.

This is despite running the entire thing inside of the elevated privileges of the System Account, and an extra measure I took to remove the original uploading user entirely from the equation and pretend it was the System Account. I don't understand why this is failing, as for all intents and purposes the System Account is running everything and it has sufficient privilege to post in that library (and does so in a workflow that can be triggered by any user at a different stage in the process!)

Below is the code that I use inside of the SPSecurity.RunWithElevatedPrivileges block. It's a very simple upload code, and yet it seems to be insufficient. Am I missing some security bits or anything? Am I going about it wrong?

using (SPSite site = new SPSite(webUrl))
{
    using (SPWeb web = site.OpenWeb())
    {
        bool oldAllow = web.AllowUnsafeUpdates;
        try 
        {
            SPList l = web.Lists[_targetList];
            SPFile file;

            int tID = int.Parse(hdIdent.Value);
            SPListItem task = web.Lists["Tasks"].GetItemById(tID);

            int targetID = int.Parse(hdRef.Value);
            SPListItem target = web.Lists[_targetList].GetItemById(targetID);

            web.AllowUnsafeUpdates = true;

            //Grab file from the FileUpload control "upDrawing"
            System.IO.Stream fStream;
            byte[] contents = new byte[upDrawing.PostedFile.InputStream.Length];
            fStream = upDrawing.PostedFile.InputStream;
            fStream.Read(contents, 0, (int)fStream.Length);
            fStream.Close();

            //Original values are in comments, switched to the System Account
            //in case this was the cause, but it still fails.
            SPUser u1 = siteAdmin; //target.GetSPUser("Created By");
            SPUser u2 = siteAdmin; //currentUser;

            file = web.Files.Add(webUrl + "/" + _targetList + "/Approved/" + upDrawing.FileName, contents, u1, u2, (DateTime)target["Created"], DateTime.Now);
            target = web.Lists[_targetList].GetItemById(targetID);
            target["File Flag"] = 1;
            target.NonfiringUpdate();
        }
        finally
        {
            web.AllowUnsafeUpdates = oldAllow;
        }
    }
}
10
  • For the curious, GetSPUser just extracts the SPUser from an SPUserValue that has a user, while NonfiringUpdate is just a System.Update(false) inside of the DisableEventFiring of an event receiver template. Everything else is just normal functions and ideally intuitive variable names.
    – Grace Note
    Commented May 9, 2011 at 14:18
  • Why are you calling web.Update() twice?
    – Dave Wise
    Commented May 9, 2011 at 16:49
  • @Dave Mostly out of not remembering whether I have to call web.Update() after changing the value of web.AllowUnsafeUpdates (which is set to true before the upload, then set back to false). I figured that it'd be safer to call the updates than to assume that changing the boolean alone was enough.
    – Grace Note
    Commented May 9, 2011 at 16:52
  • My concern is that the two updates might be causing some sort of concurrency/deadlock issue which might come back up through the UI as a permissions error... I've seen that before.
    – Dave Wise
    Commented May 9, 2011 at 16:57
  • 2
    Offtopic: always call allowunsafeupdates inside a try/finally Commented May 9, 2011 at 18:45

4 Answers 4

1

Have you tried:

l.RootFolder.Files.Add(l.RootFolder.Url + "/Approved/" + upDrawing.FileName, contents )
2
  • I will try this variant out. Next time we run into the situation, we'll see if it works out.
    – Grace Note
    Commented May 9, 2011 at 15:39
  • No go. I've tried both the fewer arguments on SPFileCollection.Add(), and then adding also the swap to use l.RootFolder, and neither worked. Thanks for the suggestion, though.
    – Grace Note
    Commented May 13, 2011 at 14:25
0

Check the permissions on the "Tasks" list as well as whatever list _targetList is pointing to in order to verify that the engineers have at least 'contribute' permissions there. FWIW, you are also fetching 'target' twice.

You should enable detailed error messages in order to identify the exact line that is failing

0

Instead of creating a new SPSite object from the URL, can you retrieve it from a current context? I see it's an aspx page, use SPContext? I read somewhere when you create a new site object you get permissions of the current user and not the admin account.

Otherway to test, since this is an aspx page, access the page when logged in as a admin user (Site Collection Admin/System Account) and then try upload. Does it go through?

I'll try and look up the references.

Edit: Please ignore the suggestion in first paragraph. The current implementation quoted in the original question is correct with respect to use of 'RunWithElevatedPrivileges'. Following article highlights it http://blog.bugrapostaci.com/2010/04/28/sharepoint-runwithelevatedprivileges-and-access-denied-error/

The only addition I can suggest is using Site-wide AllowUnsafeUpdates.

3
  • I'd like to see those references, because my recollection is that SPContext is guaranteed to be the current user, while generating a new SPSite inside of RunWithElevatedPrivileges is supposed to be created under the admin privileges, not the current user (if created outside of RunWithElevatedPrivileges, it would indeed use the current user). I'll give it a shot, though. Next time we run into the situation, I'll see if it works better.
    – Grace Note
    Commented May 13, 2011 at 18:58
  • Apologies are in order. I got that completely on it's head. You are doing it right from the 'RunWithElevatedPrivileges' point to view. How about doing site.AllowUnsafeUpdates = true and then opening the web? One good reference link (that brought be back on track) blog.bugrapostaci.com/2010/04/28/…
    – sumitkm
    Commented May 13, 2011 at 20:30
  • Hm... I'll try that instead, and treat that as your answer. Though, if it turns out to solve the problem, you'll need to revise your answer to reflect the contents of your comment here. ♪
    – Grace Note
    Commented May 13, 2011 at 20:43
0

we're having the same problem..

Grace Note, the reason why SPSecurity.RunWithElevatedPrivileges does not work because you have to create SPSite & SPWeb inside that elevated block again.

If you're using an instance of spweb/spsite that is created outside RunWithElevatedPrivileges block, then the objects are not elevated. so in that case it does not matter if you try to cal files.add(..) inside the elevated block..

in our case, we're trying to add a file programaticall in a event receiver. If the user is contributor, even though he/she has the upload right we got "access denied" error.. creating an elevated site/web instance in event receiver is a bad practice so we're mostly stuck on that.

any updates ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.