It was brought up that LogonUser() only returns the restricted token. Searching for confirmation, the impression I got was that LogonUser() returned the restricted token only for interative sessions. I created a couple of tests to find out.
The first is a console application:
using (ECR.Impersonator imp = new ECR.Impersonator("XXX", "XXX", "XXX"))
{
WindowsIdentity ident = WindowsIdentity.GetCurrent();
WindowsPrincipal princ = new WindowsPrincipal(ident);
Console.WriteLine("{0}, {1}", ident.Name, princ.IsInRole(WindowsBuiltInRole.Administrator));
RegistryKey root = Registry.LocalMachine.CreateSubKey("SOFTWARE\Connection Strings", RegistryKeyPermissionCheck.ReadWriteSubTree);
RegistryKey key = root.CreateSubKey("AbacBill", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
When run in elevated console, IsInRole() returned true and no error opening the subkey. When run in non-elevated console, IsInRole() returned true and errored opening the subkey:
Unhandled Exception: System.IO.IOException: Unknown error "1346".
at Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str)
at Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
at test.Program.test14()
at test.Program.Main(String[] args)
So it appears that in a non-elevated interactive session, LogonUser() does indeed return the restricted token. It's interesting that the normal test of doing IsInRole() unexpectedly returned true.
The second test is a website. I put the same code in (replaced Console.Write with literal1.Text = string.Format): IsInRole() returned true, no error opening subkey, IIS7.5: anonymous authentication, app pool: classic pipeline, ApplicationPoolIdentity, 2.0 framework, web.config: authentication mode = none, no impersonation.
So this seems to confirm my impression that LogonUser() returns the restricted token only for interactive sessions, but non-interactive sessions get the full token.
Doing these tests helped me answer my own question. My class library is mostly used in web applications, and they consistently bomb when applying config updates (access denied opening the subkey). So I changed my test to more accurately reflect what I'm doing (impersonating only to get the reference to my root key):
protected void Page_Load(object sender, EventArgs e)
{
RegistryKey root = null;
using (ECR.Impersonator imp = new ECR.Impersonator("XXX", "XXX", "XXX"))
{
WindowsIdentity ident = WindowsIdentity.GetCurrent();
WindowsPrincipal princ = new WindowsPrincipal(ident);
lit.Text = string.Format("{0}, {1}", ident.Name, princ.IsInRole(WindowsBuiltInRole.Administrator));
root = Registry.LocalMachine.CreateSubKey("SOFTWARE\XXX", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
root.SetValue("test", "test");
RegistryKey key = root.CreateSubKey("XXX", RegistryKeyPermissionCheck.ReadWriteSubTree);
}
and it errors:
[UnauthorizedAccessException: Access to the registry key 'HKEY_LOCAL_MACHINESOFTWAREXXXXXX' is denied.]
Microsoft.Win32.RegistryKey.Win32Error(Int32 errorCode, String str) +3803431
Microsoft.Win32.RegistryKey.CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity) +743
webtest.impTest.Page_Load(Object sender, EventArgs e) in D:VS 2008 ProjectsestwebtestimpTest.aspx.cs:28
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +25
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +42
System.Web.UI.Control.OnLoad(EventArgs e) +132
System.Web.UI.Control.LoadRecursive() +66
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2428
Again, no problems writing values to my root key, just opening subkeys. So it appears that using RegistryKeyPermissionCheck.ReadWriteSubTree does indeed not do any further security checks when writing to that key, but IS doing another security check when opening a subkey, even with RegistryKeyPermissionCheck.ReadWriteSubTree (though the docs say it doesn't).
The answer to my question is that it does appropriately give elevated permissions via impersonation under a non-interactive login. My problem is I had assumed that RegistryKeyPermissionCheck.ReadWriteSubTree wouldn't do any further security checks (like the docs say) on that reference even after impersonation ends.
I guess I'm going to have to do the impersonation every time I need to write to the registry. :(