SetAccessControl "unauthorized operation" even when run as administrator - c#

I am trying to take ownership and change the ACL of a file in C#, but even as an administrator I am getting the exception:
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.
The user running the program has the ability to take ownership and change permissions through Windows interface.
My code:
string fileName = #"C:\temp\mount\Windows\System32\Boot\en-US\winload.exe.mui";
FileSecurity fileSec = File.GetAccessControl(fileName);
fileSec.SetOwner(WindowsIdentity.GetCurrent().User);
File.SetAccessControl(fileName, fileSec); //exception thrown here
I even added a check to make sure the current user is member of administrator group:
WindowsIdentity wi = WindowsIdentity.GetCurrent();
WindowsPrincipal wp = new WindowsPrincipal(wi);
bool isAdmin = wp.IsInRole(WindowsBuiltInRole.Administrator); //returns true
Background information: I am creating a WinPE image and need to replace the winload.exe.mui file.
Also, the current permissions on this file only give full access to "Trusted Installer".
I am running on Windows 7

I solved this issue by running takeown in a command shell using a System.Diagnostics.Process. Then I was able to set the access control without error.
Strange that takeown works but the equivalent .NET libraries don't.

You can still use File.SetAccessControl() in your new method in place of FileStream.SetAccessControl(). I'd be willing to bet it works, too. MSDN actually recommends this practice:
"While the FileStream class and SetAccessControl can be used on an existing file, consider using the File.SetAccessControl method as it is easier to use."
http://msdn.microsoft.com/en-us/library/system.io.filestream.setaccesscontrol.aspx[^]

Related

Transactional NTFS wrapper

I'm using transactional NTFS wrapper that is available on msdn here to support atomic transactions of file system operations, the available example only shows how to work with transactedFiles but I need also to create, move and copy transacted Directories, I don't know how to use TransactedDirectory Class, can you please help?
I tried this code but it doesn't seem to be correct:
if (Transaction.Current == null)
{
throw new Exception("Must be within a transaction scope");
}
using (TransactionScope folderTransaction = new TransactionScope(Transaction.Current))
{
TransactedDirectory.StartTxFResource("D:\\New");
folderTransaction.Complete();
TransactedDirectory.StopTxFResource("D:\\New");
}
it gives an error "access denied, the folder is being used by another process".
Under which User Account is your process running? Check if it has access to the D:\New folder.
For a quick check, run the process as Administrator (Right click myprocess.exe > Run As Administrator), and if it works then, you should either set the correct permissions, or setup your code to require admin level access.

C# code to automatically give IIS write access to a folder on Windows Server 2008? Currently throws exception

I am trying to write a command line tool that will give IIS7.5 on windows server 2008 write access to a folder in the wwwroot, so that a web application has access to write to a specific folder within it's base directory. Formerly, you would do this by assigning the IIS_WPG group on the folder giving that group Modify access.
In Server 2008 I'm trying to do the same thing with IIS_IUSRS, but an exception is ocurring.
Here is the code:
private static void ManagePermissions(string directory, string account, FileSystemRights rights, AccessControlType controlType, bool addAccess)
{
DirectoryInfo directoryInfo = new DirectoryInfo(directory);
DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
if (addAccess)
directorySecurity.AddAccessRule(
new FileSystemAccessRule(account, rights, controlType));
else
directorySecurity.RemoveAccessRule(
new FileSystemAccessRule(account, rights, controlType));
directoryInfo.SetAccessControl(directorySecurity);
}
The call to this method is as follows:
ManagePermissions(
"c:\inetpub\wwwroot",
"MACHINENAME\IIS_IUSRS",
FileSystemRights.Modify,
AccessControlType.Allow,
true);
When execute that call to ManagePermissions an exception is thrown with the following type and message:
System.Security.Principal.IdentityNotMappedException:
Some or all identity references could not be translated.
I've checked multiple times to ensure that MACHINENAME\IIS_IUSRS is an exact match with the user in the local user manager on the machine this code is executing on. This machine does not participate in a windows domain.
Let me know if you need any further clarification.
IIS_IUSRS is a built in group, so it should not be referenced with [machinename]\IIS_IUSRS but with BUILTIN\IIS_IUSRS. Like so:
ManagePermissions(
"c:\inetpub\wwwroot",
"BUILTIN\IIS_IUSRS",
FileSystemRights.Modify,
AccessControlType.Allow,
true);
Switching to that way of referencing the user fixed my code. I get the account in a slightly different way than referenced in your example:
IdentityReference user = new NTAccount(UserDomain + #"\" + UserName);
And then use it via a different constructor so that may affect the translation as well but I doubt it:
var rule = new FileSystemAccessRule(user, ..., ..., ..., ...);
Update: recently I've seen error with adding full control to user IIS_IUSRS on non-english windows (Windows server 2008 R2 x64 IIS7).
Despite that IIS_IUSRS is not translated, 'BUILTIN' in front of it can cause an error
So, be aware of using "BUILTIN\IIS_IUSRS", use just 'IIS_IUSRS' instead - its working on both english and non-english windows

a required privilege is not held by the client while uploading a temporary registry (C#)

While I am trying to upload a registry in my registries using the C# code , the application is throwing the error "a required privilege is not held by the client". If I am using the same code on some other machine it is working fine but not particularly on my machine
I am using below mentioned code to upload the registry files
Process my_p = new Process();
my_p.StartInfo.FileName = "reg";
my_p.StartInfo.Arguments = "load HKLM\TEST C:\Documents and Settings\Administrator\NTUSER.DAT";
my_p.Start();
my_p.WaitForExit();
System.IO.StreamReader srOutPut = my_p.StandardOutput;
System.IO.StreamReader srError = my_p.StandardError;
my_p.Close();
results = srOutPut.ReadToEnd().Trim();
Errors = srError.ReadToEnd().Trim();
Moreover One thing I have noticed that the above code I am using in http based web site, but when I am using it in a File Syatem based web site it is working fine. Please help I am not getting the error.
Regards,
Vikram
You can load RegLoadKey function directly to load the hive as a subkey. Another API is RegLoadAppKey but it works only starting from Windows Vista. Different versions of Reg.exe use the API. How you can read in the description the RegLoadKey you need have SE_RESTORE_NAME and SE_BACKUP_NAME privileges and enable these (see http://msdn.microsoft.com/en-us/library/ms717797.aspx). If you are in the Group of Administrators or Backup Operators you have these privileges. One more problem can be if Reg.exe use RegLoadKey function and you have a local administrative rights, but you start on Vista or Windows 7 a command without admin rights because of UAC (User Account Control).

How does RegistryPermission works?

I am trying to check if I have write access to a specific key in the registry before displaying a form that allow the user to change some settings that are written in that key.
code sanitized for clarity
public bool CanWrite()
{
string key = #"HKEY_LOCAL_MACHINE\SOFTWARE\MyHaccpPlan, Inc.\2.0";
try
{
RegistryPermission permission = new RegistryPermission(RegistryPermissionAccess.Write, key);
permission.Demand();
return true;
}
catch(SecurityException)
{
return false;
}
}
I am running the application using a user that has read access only. The problem is that this function return true, even if the user don't have write access.
Later, a call like
Registry.SetValue(#"HKEY_LOCAL_MACHINE\SOFTWARE\MyHaccpPlan, Inc.\2.0", "Language", "fr-CA");
will fail with UnauthorizedAccessException.
How do I properly check for registry rights before attempting to write to it?
Edit
I don't want the current user to be able to write there. I want to use this registry entry as a flag that a feature in the software should be disabled. But if the user is an administrator, I want the software to allow the feature. The goal is that a network administrator could be able to preset the settings and that the users will be unable to change them.
But beside actually writing and waiting for it to crash, I want to check the security using the permission system offered in .NET if that is possible.
You shouldn't rely on .NET code access security for managing access control to the registry; let alone should you have explicit checks in your code. With that approach, the user can still use the registry editor and bypass all your access checks.
Instead, you should use proper ACLs to restrict what users can write to a key.
If you want to test at run-time whether you have access to a key, you should try to open the key for writing, and catch SecurityException (in which case the user running the application has no permission to modify the key).
mmm you can try using a tool like Lutz Roeder's Reflector for viewing the content of the Registry.SetValue Method.
Looking a bit to it, it seems to do it with next line of code:
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

How to get registry write permissions in C#

I'm trying to write to the windows registry at HKEY_CURRENT_USER\Software\appname however I keep getting a permissions error when I attempt to write to the key, I have added the following to my assembly:
[assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum, Write = #"HKEY_CURRENT_USER\\Software")]
but this has not resolved the issue, is there something else that I should be doing?
I don't suppose it's something as simple as you having opened the key without specifying that you want write access? The OpenSubKey(string) method only gives read-only access.
The RegistryPermissionAttribute is part of the Code Access Security aka CAS, this is a permission system which checks the permission you have inside of the .NET framework, these permissions are defined by the security policy. There are 4 security policies:
Enterprise - policy for a family of machines that are part of an Active Directory installation.
Machine - policy for the current machine.
User - policy for the logged on user.
AppDomain - policy for the executing application domain.
The first 3 are configured in the configuration screen in the .NET Configuration tool, and the last is configured at runtime.
The reason why I explain this first is because the RegistryPermissionAttribute only checks your .NET permissions, it does not check the Operating System permissions.
You could use the System.Security.AccessControl to check the operating system permissions, but to get the permissions you'll probably need to either elevate or impersonate.
Make sure the app runs using the user-account that has enough rights to access the registry.
I don't see an answer or resolution here. I found this question when searching for something else.
The one thing I think that may be needed is that you need to be running as administrator if you're running from the exe. If you're running from VS you'll need to make sure that VS is running as administrator. VS will show "(Administrator) in the window title if it is.
This works for me. With key already there and without it. Without any special assembly attributes.
using System;
using Microsoft.Win32;
namespace WriteToRegistry {
class Program {
static void Main(string[] args) {
const string csRootKey = #"Software\MyCompany\Test";
using (RegistryKey loRegistryKey = Registry.CurrentUser.CreateSubKey(csRootKey)) {
if (loRegistryKey == null)
throw new InvalidOperationException("Could not create sub key " + csRootKey);
loRegistryKey.SetValue("CurrentTime", DateTime.Now.ToString(), RegistryValueKind.String);
}
}
}
}
EDIT: After rereading the question it seems that the problem could be OS permissions.

Categories

Resources