0

I must be an idiot programmer without an example. I am migrating a batch file to a asp.net app, using VB, trying to figure out how in asp.net has wasted almost a day.

There is a specific registry key/item I want to change that, by default in Server 2008 and newer, Administrators do NOT have FullControl on. The SetAccessControl function works, as long as I can first set Administrators as the object owner. From the command line it was easy to set the owner as Administrators, then grant FullControl, so I know it is possible.

Edit: the command-line works because I am logged in as a member of the Administrators group, meaning permissions should not be an issue running the code.

Edit2: to be clear, this is a "Windows Forms Application" (NOT a Web Application, NOT a Console Application).

Imports Microsoft.Win32
Imports System.Security.AccessControl
Imports System.Security.Principal

Public Sub GrantRegistyPermission()
  Dim Hive As RegistryKey = Registry.ClassesRoot
  Dim KeyName As String = "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
  ' next line FAILS, "Requested registry access is not allowed"
  'Dim SubKey As RegistryKey = Hive.OpenSubKey(KeyName, True)
  ' try without specifying the "writable" overload
  Dim SubKey As RegistryKey = Hive.OpenSubKey(KeyName)
  Dim rs As RegistrySecurity = Hive.GetAccessControl()
  rs.SetOwner(New NTAccount("BUILTIN\Administrators"))
  ' next line FAILS, "Attempted to perform an unauthorized operation."
  Hive.SetAccessControl(rs)
  rs.AddAccessRule(New RegistryAccessRule(User, RegistryRights.FullControl, _
                   InheritanceFlags.ContainerInherit, _
                   PropagationFlags.InheritOnly, AccessControlType.Allow))
  Hive.SetAccessControl(rs)
  Hive.Close()
End Sub
JayRO-GreyBeard
  • 149
  • 2
  • 7
  • It's been some time since I've accessed _Registry_ from ASP.net :) You have to think in what _context_ (user) ASP.net is running as. You need to give that user (ASP.net) permissions to it. That statement in/of itself is also a **warning** :) Why not just _console_ ? – EdSF Jul 14 '14 at 18:50
  • Yep, context was implied by stating it works from the command-line, I just edited the post for clarity. I'm not sure how that applies to my GUI application: "why not just console". (which probably explains why I don't just). Sorry, still a bit newb at asp.net, thanks though! – JayRO-GreyBeard Jul 14 '14 at 19:11
  • No problem. To clarify, you will need to give your application (ASP.net or Console) the appropriate permission to into the Registry. ASP.Net, is [`NETWORK SERVICE` and/or the `APPPOOL USER`](http://www.iis.net/learn/manage/configuring-security/application-pool-identities) or [impersonate](http://msdn.microsoft.com/en-us/library/vstudio/xh507fc5(v=vs.100).aspx). If Console, it would be the user executing the console app (like invoking a command line command) – EdSF Jul 14 '14 at 21:06
  • I have done impersonation from an ASP program to do stuff like write files to protected locations so it should work for the registry. Try this: http://stackoverflow.com/questions/2808928/how-to-impersonate-a-user-in-managed-code – Steve Jul 14 '14 at 22:15
  • @EdSF your suggestions are appreciated, thanks! I just addd a clarity edit that this is a "Windows Forms Application". It would seem my application already has the appropriate permissions, running as a member of Administrators. I can use the Registry GUI and the SetACL command-line tool just fine to take ownership. – JayRO-GreyBeard Jul 15 '14 at 12:49
  • @Steve: Your suggestion prompted me to look at the option of impersonation, but those solutions all seemed too complicated (and difficult for me to understand written in C#). – JayRO-GreyBeard Jul 15 '14 at 12:51

1 Answers1

0

In the end, the only method I could get to work was to launch in a new process the SetACL.exe (or SetACLx64.exe) command that I was using in the batch file. Be sure the SetACL command-file is in the same directory, or it needs to be fully pathed (and quoted?).

Sub GrantRegKeyFullPermCmd()
  Dim RegKey As String = "HKLM\Software\Classes\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
  Dim UserGroup As String = "Administrators"
  Dim p As Process = Nothing
  Dim ps1 As ProcessStartInfo = New ProcessStartInfo
  ps1.FileName = "cmd.exe"
  ps1.Verb = "runas"
  ps1.WindowStyle = ProcessWindowStyle.Normal
  ps1.UseShellExecute = False
  ps1.RedirectStandardOutput = True
  ps1.Arguments = "/C SetACLx64.exe -on """ & RegKey & """ -ot reg -actn setowner -ownr ""n:" & UserGroup & """"
  Try
    p = Process.Start(ps1)
    Dim Results As String = p.StandardOutput.ReadToEnd
    p.WaitForExit()
    MsgBox("ExitCode: " & p.ExitCode & vbCrLf & "Set owner results: " & Results)
    Dim ps2 As ProcessStartInfo = ps1
    ps1.Arguments = "/C SetACLx64.exe -on """ & RegKey & """ -ot reg -actn ace -ace ""n:" & UserGroup & ";p:full"""
    p = Process.Start(ps1)
    Results = p.StandardOutput.ReadToEnd
    p.WaitForExit()
    MsgBox("ExitCode: " & p.ExitCode & vbCrLf & "Set permission results: " & Results)
  Catch ex As Exception
    MsgBox(ex.Message)
  End Try
End Sub

Steps I tried that did NOT work:

  • apply local policy and/or GPO "User Account Control: Behavior of the elevation prompt for administrators in Admin Approval Mode" = "Elevate without prompting"

  • right-click "Run as Administrator"

  • launch from elevated command prompt

  • run the SetACL command as the ProcessStartInfo.FileName

  • changed project properties, UAC Settings: requestedExecutionLevel level="requireAdministrator"

Nimantha
  • 6,405
  • 6
  • 28
  • 69
JayRO-GreyBeard
  • 149
  • 2
  • 7