Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

Is there a way to detect if my code is running inside SPSecurity.RunWithElevatedPrivileges?

class Foo
{
  public static void Bar()
  {
     if (CODE_RUNS_ELEVATED)
     {
       Debug.WriteLine("You are elevated");
     }
     else
     {
       Debug.WriteLine("You are not elevated");
     }
  }
}

SPSecurity.RunWithElevatedPrivileges(() => Foo.Bar()); // Prints:  You are elevated
Foo.Bar(); // Prints: You are not elevated

My problem is how to resolve CODE_RUNS_ELEVATED.

UPDATE: Some observations I did so far:

  • Thread.CurrentPrincipal: logged on identity
  • WindowsIdentity: application pool identity
  • HttpContext.Current.User.Identity: logged on identity

So the only thing, which changes when doing the 'RWEP' is the WindowsIdentity.GetCurrent() from NT AUTHORITY\IUSR (with claims authentication) or from the logged on user (with windows integrated authentication) to the application pool identity.

share|improve this question
    
Did you ever get an answer to this question ? I have the same requirement, but can't find a way to detect if the code is elevated or not. –  Steve B Jun 1 '12 at 7:42
    
Please see my posted answer. –  Matthias Jun 1 '12 at 8:52
add comment

5 Answers

I'm not entirely certain this will work, but you could try inspecting HttpContext.User.Identity within the RunWithElevatedPrivileges delegate, and see if it returns the application pool identity.

If so, you could provide some way of retrieving the application pool identity for a given SPWebApplication (possibly via SPWebApplication.ApplicationPool?), and compare the Identity name to that of what you get via HttpContext.User.Identity (if what we tried in the above paragraph works).

share|improve this answer
1  
HttpContext.Current.User.Identity returns the current logged on identity. But WindowsIdentity.GetCurrent() returns the application pool identity. –  Matthias Feb 9 '12 at 17:01
    
It does? Wicked. Use that and see if you can get a username or something to identify that identity. Then see if you can get the identity for the current SPWebApplication.ApplicationPool. Then you should be sorted. –  James Love Feb 9 '12 at 17:06
    
RunWithElevated's basically does a thread impersonation to the application pool identity of the web app, executes the CodeToRunElevated delegate method and flips it back to the original user when the method returns. –  James Love Feb 9 '12 at 17:07
    
Yes, up to now this is my only solution. But I did hope to find a more straight forward one... –  Matthias Feb 9 '12 at 17:15
    
@Matthias just to be clear, you are saying that when with normal privs that the IDs are the same but when run with elevated privs they differ? –  Dave Wise Feb 9 '12 at 17:34
show 2 more comments
up vote 2 down vote accepted

This is finally the solution I came to:

public static bool IsPrivilegedMode()
{
  using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
  {
    return identity != null && GetProcessIdentity().User == identity.User;
  }
}

private const uint processToken = 0x0008;
public static WindowsIdentity GetProcessIdentity()
{
  IntPtr handle = IntPtr.Zero;
  try
  {
    Process process = Process.GetCurrentProcess();              
    OpenProcessToken(process.Handle, processToken, out handle);
    return new WindowsIdentity(handle);
  }
  finally
  {
    if (handle != IntPtr.Zero)
    {
      CloseHandle(handle);
    }
  }
}

[DllImport("kernel32.dll")]
public static extern Boolean CloseHandle(IntPtr hObject);

[DllImport ("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken (IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);

I recommend that you do some static caching of the process identity, in order to improve performance.

share|improve this answer
    
This seems to works only for web application. if I ran this code within a console application (or from unit tests in my case), the process identity is owned by the current user. –  Steve B Jun 1 '12 at 9:09
add comment

The bigger question is why do you need to know?

If your code requires that it run with elevated privileges why not simply include that in the block? If that is not practical then let it throw an error if it attempts to do something without sufficient privilege. An error of that level would get certainly get caught and corrected in basic testing and the caller would be modified to increase privilege prior to the call.

If this is just a check to see if it is running with higher privs then you could simply wrap a call to some light duty higher-permission function (maybe something in Microsoft.SharePoint.Administration) in a try-catch block and return true/false based on that.

share|improve this answer
    
I need to know, since I want to do some custom permission handling independently of the SharePoint permissions. So your second suggestion could be a solution, but I guess that it is hard to find a function that will not have an impact on the performance. –  Matthias Feb 9 '12 at 17:13
    
I would start with James' suggestion below and do a side-by-side comparison of both the SPContext and HttpContext objects as they appear normally and with elevated privileges. There has to be something there to indicate the difference. If there isn't or it invokes some high overhead method (like loading a Site) then try the above options –  Dave Wise Feb 9 '12 at 17:16
    
If you do find a difference on the SPContext or HttpContext objects, please post it here as I am curious now as well –  Dave Wise Feb 9 '12 at 17:18
    
Since SPContext doesn't inherit from HttpContext, and therefore run as completely separate entities with different roles, not sure if it is possible to compare them (internally there'll be some reference to HttpContext but that's surfaced nowhere in the API I don't think). EDIT: I just realised you want to see how they're both different when in different context modes, rather than a direct object to object comparison. –  James Love Feb 9 '12 at 17:26
    
Correct. I have to think that there would be something different on one of those objects when run with elevated privs versus when run normally. –  Dave Wise Feb 9 '12 at 17:31
add comment

The easy thing and which is working 100% is to get CurrentUser from a SPWeb object and compare it against 'SHAREPOINT/SYSTEM'.

100% agree there are cases when is needed to detect if code is already running under elevated privs. Cuz you might have classes calling other methods from other classes and so on and you can't elevate 2 or more times a context. Strange behavior results from that.

share|improve this answer
    
Yes you are right, but then you have to open a SPWeb specially for that, which is a perfomance killer... –  Matthias Feb 10 '12 at 11:06
    
No, you don't have to open, you might have a SPList or a SPListItem object and navigate from property to the SPWeb. Like: SPList.ParentWeb or SPListItem.Web. –  Ovidiu Becheş-Puia Feb 10 '12 at 12:41
add comment

I found this code is working (even in a unit test project) :

    private static readonly PropertyInfo g_OriginatingUserTokenProperty = typeof(SPSecurity).GetProperty(
                    "OriginatingUserToken",
                    System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic
                    );

    public static bool IsElevated
    {
        get
        {
            return g_OriginatingUserTokenProperty.GetValue(null, null) != null;
        }
    }

However, I'm not sure this will actually tells me if I'm elevated, or just impersonated with another user token.

share|improve this answer
    
After some test, this method is not reliable. This methds is telling if the context is impersonated. This can occur, for example, if we are in a event receiver. –  Steve B Jul 4 '12 at 7:55
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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