C# where to write safely in registry for all users - c#

I 've a Windows Service which writes somes of this parameters in registry.
I want these parameters to be common to any users, means, whatever the Windows Service "RunAs".
Where you'd you recommand to write them?
I tried to write them in SOFTWARE\MyWindowsService\Server but I've permissions issues as you can see in this code.
For example here, I try to read and write in SOFTWARE\MyWindowsService\Server\Key1 and type of Key1 is string (REG_SZ)...
//Get current user for windows Service
_windowsIdentity = WindowsIdentity.GetCurrent().Name;
MessageBox.Show("Try to change registry permissions for" + _windowsIdentity); //==> LocalSystem is my current account
//Get Main windows service registry
_WindowsServiceRegKeys = Registry.LocalMachine.CreateSubKey("SOFTWARE\\THIS_WINDOWS_SERVICE_FOLDER\\SERVER", RegistryKeyPermissionCheck.ReadWriteSubTree);
RegistrySecurity rs = new RegistrySecurity();
rs = _WindowsServiceRegKeys.GetAccessControl();
//Add new permissions
rs.AddAccessRule(new RegistryAccessRule(_windowsIdentity
, RegistryRights.FullControl
, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
, PropagationFlags.InheritOnly, AccessControlType.Allow));
_WindowsServiceRegKeys.SetAccessControl(rs);
//Try to read a var
object objRetRegistryKeyValue = _WindowsServiceRegKeys.GetValue("Key1"); //ERROR: object is null
_WindowsServiceRegKeys.SetValue("Key1", "Test", RegistryValueKind.String);
Could you help me on this bug?
Thanks and regards,

Related

Windows Worker Service Folder Permissions (C#)

Quick question if anyone happens to know. I'm working on a Worker app in dotnet6 that is intended to be made into a service and I need to store a json file somewhere. Doing some research it seems like CommonApplicationData(ex: "C:/ProgramData") is the place to go. My question is, I can't seem to write a file to that folder. I am able to create a directory just fine. But my access is denied to creating an actual file.
This service will be used on servers in the field right now and cannot answer UAC prompts. I'm unsure what else to do. I can have the file created manually and access, edit it. That seems to work fine. But I'd like to have a logs files dynamically created and more.
Heres the code("its pretty basic")
var dirPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MyServerService");
var path = dirPath + "\\service.json";
var doesDirExist = Directory.Exists(dirPath);
var doesFileExist = File.Exists(path);
if (!doesDirExist || !doesFileExist)
{
Directory.CreateDirectory(dirPath); //<- directory is created just fine
using var file = File.Create(dirPath); // <- fails here (access is denied)
//do stuff
}
This bit of code worked for me. It was indeed a permission issue with the directory being created.
public static bool CreateDirWithAccess(string fullPath, bool readOnly)
{
var dInfo = Directory.CreateDirectory(fullPath);
DirectorySecurity dSecurity = dInfo.GetAccessControl();
dSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), readOnly ? FileSystemRights.Read : FileSystemRights.FullControl, InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(dSecurity);
return true;
}

How to delete registry key for specific user?

I have two users: SuperUser and MyUser. How can I delete some registry key for MyUser when I am logged in as SuperUser.
In my C# application I want to delete key by path: MyUser\Software\Microsoft\Windows\CurrentVersion\Run\MyApp.
Note I am runnnig my C# application when I am logged as SuperUser.
It seems that Microsoft.Win32.Registry class doesn't have a possibility to do that.
The profile may or may not be loaded. In order to ensure that it is loaded, you'll need to logon the user. Then you can load the profile and make changes. You'll need to pinvoke LogonUser() and LoadUserProfile().
// log on user
UserToken usertoken = null;
LogonUser(user, domain, pass, LogonType.LOGON32_LOGON_NETWORK,
LogonProvider.LOGON32_PROVIDER_DEFAULT, out usertoken));
// load the profile
PROFILEINFO p = new PROFILEINFO();
p.dwFlags = 1;
p.lpUserName = user;
p.dwSize = Marshal.SizeOf(p);
LoadUserProfile(usertoken, ref profile);
// get a handle to the registry
Microsoft.Win32.SafeHandles.SafeRegistryHandle saferh =
new Microsoft.Win32.SafeHandles.SafeRegistryHandle(profile.hProfile, false);
Microsoft.Win32.RegistryKey rk =
Microsoft.Win32.RegistryKey.FromHandle(m_RegHandle, Microsoft.Win32.RegistryView.Default);

How to assign new rights (ACL) to existing registry key without inheriting rights from parent

New rights can be set using RegistryKey.SetAccessControl(new RegistrySecurity(...)). But after that the inheritance is turned on.
Is there a way to assign new rights without turning the inheritance on?
The whole code:
void test
{
SecurityIdentifier sidAccUser = new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null);
NTAccount ntAccUser = sidAccUser.Translate(typeof(NTAccount)) as NTAccount;
RegistryAccessRule regAcRule = new RegistryAccessRule(
ntAccUser
, RegistryRights.FullControl
, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
, PropagationFlags.None
, AccessControlType.Allow);
RegistrySecurity regSecurity = new RegistrySecurity();
regSecurity.AddAccessRule(regAcRule);
RegistryKey regKey = Registry.CurrentUser.OpenSubKey(#"ZZTEST", true);
// after that the inheritance is turned on
regKey.SetAccessControl(regSecurity);
}
I found this solution but don't want to use a COM-Server: Setting permissions and blocking inheritance from C# with SetACL
Use SetAccessRuleProtection to protect the DACL from inheritance..
regSecurity.SetAccessRuleProtection(true, false);
http://msdn.microsoft.com/en-us/library/vstudio/system.security.accesscontrol.objectsecurity.setaccessruleprotection(v=vs.100).aspx

Remove all default file permissions

I have an C# network application that prompts admins for network proxy authentication information. I ask the user if they want to save this information, which if they choose yes, I encrypt in a unique local file for the user. I would then like to remove all file permissions except the user that created it, but all other users to have the ability to delete the file.
Now, I found MS article below, but it's not helping if I don't know the default users that were setup on the file in the first place. Is there a remove all file permissions? I can then add the individual rights I'm wanting to setup for full access by current user and delete permissions for "All Users" or "Authenticated Users", which looks to be different depending on version of Windows.
http://msdn.microsoft.com/en-us/library/system.io.file.setaccesscontrol.aspx
I figured it out..
public void SetFileSecurity(String filePath, String domainName, String userName)
{
//get file info
FileInfo fi = new FileInfo(filePath);
//get security access
FileSecurity fs = fi.GetAccessControl();
//remove any inherited access
fs.SetAccessRuleProtection(true, false);
//get any special user access
AuthorizationRuleCollection rules = fs.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount));
//remove any special access
foreach (FileSystemAccessRule rule in rules)
fs.RemoveAccessRule(rule);
//add current user with full control.
fs.AddAccessRule(new FileSystemAccessRule(domainName + "\\" + userName, FileSystemRights.FullControl, AccessControlType.Allow));
//add all other users delete only permissions.
fs.AddAccessRule(new FileSystemAccessRule("Authenticated Users", FileSystemRights.Delete, AccessControlType.Allow));
//flush security access.
File.SetAccessControl(filePath, fs);
}
If you need to remove for the specific group , you can use this method ;
public static void RemoveGroupPermission(string path, string group_name)
{
long begin = Datetime.Now.Ticks;
DirectoryInfo dirInfo = new DirectoryInfo(path);
DirectorySecurity dirSecurity = dirInfo.GetAccessControl();
dirSecurity.RemoveAccessRuleAll(new FileSystemAccessRule(Environment.UserDomainName +
#"\" + group_name, 0, 0));
dirInfo.SetAccessControl(dirSecurity);
long end = DateTime.Now.Ticks;
Console.WriteLine("Tick : " + (end - begin));
}
Impersonation may be help you to solve this out.
The term "Impersonation" in a programming context refers to a technique that executes the code under another user context than the user who originally started an application, i.e. the user context is temporarily changed once or multiple times during the execution of an application.
click Here to see implimentation

RegistryKeyPremissionsCheck and LocalMachine does not exist in current context

I tried to write a simple C# program with UI to add my own key and value in registry. I was adding it to registry so that my program can read it later when it starts and does not reconfigure itself.
RegistryKey rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", RegistryKeyPremissionsCheck.ReadWriteSubTree, RegistryRights.ChangePermissions | RegistryRights.ReadKey);//Get the registry key desired with ChangePermissions Rights.
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule("Administrator", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));//Create access rule giving full control to the Administrator user.
rk.SetAccessControl(rs); //Apply the new access rule to this Registry Key.
rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", RegistryKeyPremissionsCheck.ReadWriteSubTree, RegistryRights.FullControl); // Opens the key again with full control.
rs.SetOwner(new NTAccount("Administrator"));// Set the securitys owner to be Administrator
rk.SetAccessControl(rs);// Set the key with the changed permission so Administrator is now owner.
This is the code I picked up from some question at Stackoverflow. I was trying to resolve permission issue while adding/deleting/modifying the keys.
Am I missing anything?
in you first line you are using RegistryKeyPremissionsCheck which is a variable you haven't defined yet. same goes to LocalMachine.
write the line
RegistryKey LocalMachine = Registry.LocalMachine;
before your code for LocalMachine
as for RegistryKeyPremissionsCheck.ReadWriteSubTree replace it with true if you want to edit the values under the sub key you are opening, otherwise you can put false there
if you just want to add key to the registry i would just use -
int MyNumber = 0; // Your value, doesnt have to be a number
Registry.SetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", "My User Name", MyNumber);
and to get the value
object val = Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC", "My User Name", -1);
now i put this code and it works if you have the correct permissions (you are the administrator)
RegistryKey LocalMachine = Registry.LocalMachine;
RegistryKey rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC",
RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions | RegistryRights.ReadKey);//Get the registry key desired with ChangePermissions Rights.
RegistrySecurity rs = new RegistrySecurity();
rs.AddAccessRule(new RegistryAccessRule("Administrator", RegistryRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));//Create access rule giving full control to the Administrator user.
rk.SetAccessControl(rs); //Apply the new access rule to this Registry Key.
rk = LocalMachine.OpenSubKey("HKEY_LOCAL_MACHINE\\SOFTWARE\\AMC",
RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl); // Opens the key again with full control.
rs.SetOwner(new NTAccount("Administrator"));// Set the securities owner to be Administrator
rk.SetAccessControl(rs);
int MyNumber = 0; // Your value, doesn't have to be a number
rk.SetValue("username", MyNumber);// The username should by the dynamic part

Categories

Resources