Question

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.

Was it helpful?

Solution 3

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.

OTHER TIPS

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).

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.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top