c# - How can I get elevated permissions (UAC) via impersonation under a non-interactive login? -
i have class library keeps system-wide configuration data in registry (hklm\software\xxx). library used in various applications (services, windows forms, web apps, console apps) on various versions of windows (xp, 2003, 7, 2008 r2). because of this, identity of app not consistent , may not member of machine's administrators group. i've created ad domain admin user , impersonation gain write access registry. works in xp/2003, not in uac-enabled systems (7/2008r2). understanding interactive logins split tokens imply non-interactive logins (service identities, app pool identities, etc.) not. can't find confirm that, working assumption, impersonation i'm doing should work.
i wrote wrapper class impersonation using native logonuser (network logontype, default provider) , duplicatetokenex (impersonation, primary token) windowsidentity.impersonate(). reference root key:
using (ecr.impersonator imp = new ecr.impersonator("xxx", "xxx", "xxx")) { _root = registry.localmachine.createsubkey("software\\xxx", registrykeypermissioncheck.readwritesubtree); }
according msdn, using readwritesubtree, should time security check done. can write values key, create sub-keys (also using readwritesubtree) , writing values sub-keys without ever needing security check. thought need costly impersonation 1 time - getting reference root key.
i can write values root key fine:
_root.setvalue("cacheddate", value.tobinary(), registryvaluekind.qword); }
but when create/open sub-key readwritesubtree:
registrykey key = _root.createsubkey("xxx", registrykeypermissioncheck.readwritesubtree);
it bombs access registry key 'hkey_local_machine\software\xxx\xxx' denied
.
while i'm curious why security check done when msdn says shouldn't, question how can elevated permissions via impersonation applications may not running under interactive login?
it brought logonuser() returns restricted token. searching confirmation, impression got logonuser() returned restricted token interative sessions. created couple of tests find out.
the first 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 , no error opening subkey. when run in non-elevated console, isinrole() returned true , errored opening subkey:
unhandled exception: system.io.ioexception: unknown error "1346". @ microsoft.win32.registrykey.win32error(int32 errorcode, string str) @ microsoft.win32.registrykey.createsubkey(string subkey, registrykeypermissioncheck permissioncheck, registrysecurity registrysecurity) @ test.program.test14() @ test.program.main(string[] args)
so appears in non-elevated interactive session, logonuser() indeed return restricted token. it's interesting normal test of doing isinrole() unexpectedly returned true.
the second test website. put same code in (replaced console.write 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 seems confirm impression logonuser() returns restricted token interactive sessions, non-interactive sessions full token.
doing these tests helped me answer own question. class library used in web applications, , consistently bomb when applying config updates (access denied opening subkey). changed test more accurately reflect i'm doing (impersonating reference 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 errors:
[unauthorizedaccessexception: access registry key 'hkey_local_machine\software\xxx\xxx' 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 projects\test\webtest\imptest.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 root key, opening subkeys. appears using registrykeypermissioncheck.readwritesubtree indeed not further security checks when writing key, doing security check when opening subkey, registrykeypermissioncheck.readwritesubtree (though docs doesn't).
the answer question appropriately give elevated permissions via impersonation under non-interactive login. problem had assumed registrykeypermissioncheck.readwritesubtree wouldn't further security checks (like docs say) on reference after impersonation ends.
i guess i'm going have impersonation every time need write registry. :(
Comments
Post a Comment