take ownership of a file c# - c#

I am trying to take ownership of a file and delete it via C#.
The file is iexplorer.exe, current owner by default - TrustedInstaller.
The method FileSecurity.SetOwner seems to set the specified ownership, but actually doesn't change the initial owner and throws no exception.
Obviously, the next attempt to delete the file throws an exception.
What should be changed in the code to take ownership of the file and delete it ?
var fileS = File.GetAccessControl(#"C:\Program Files (x86)\Internet Explorer\iexplore.exe");
fileS.SetOwner(new System.Security.Principal.NTAccount(Environment.UserDomainName, Environment.UserName));
File.Delete(#"C:\Program Files (x86)\Internet Explorer\iexplore.exe");

You must explicitly enable SeTakeOwnershipPrivilege:
Required to take ownership of an object without being granted
discretionary access. This privilege allows the owner value to be set
only to those values that the holder may legitimately assign as the
owner of an object. User Right: Take ownership of files or other
objects.
I suggest you to read the great article written by Mark Novak: Manipulate Privileges in Managed Code Reliably, Securely, and Efficiently.
And/or take a look at his sample.
Update
Example usage:
var fileS = File.GetAccessControl(#"C:\Program Files (x86)\Internet Explorer\iexplore.exe");
Privilege p;
bool ownerChanged = false;
try
{
p = new Privilege(Privilege.TakeOwnership);
p.Enable();
fileS.SetOwner(new System.Security.Principal.NTAccount(
Environment.UserDomainName, Environment.UserName));
ownerChanged = true;
}
catch(PrivilegeNotHeldException e)
{
// privilege not held
// TODO: show an error message, write logs, etc.
}
finally
{
p.Revert();
}
if (ownerChanged)
File.Delete(#"C:\Program Files (x86)\Internet Explorer\iexplore.exe");

string filepath = #"C:\Program Files (x86)\Internet Explorer\iexplore.exe";
//Get Currently Applied Access Control
FileSecurity fileS = File.GetAccessControl(filepath);
//Update it, Grant Current User Full Control
SecurityIdentifier cu = WindowsIdentity.GetCurrent().User;
fileS.SetOwner(cu);
fileS.SetAccessRule(new FileSystemAccessRule(cu, FileSystemRights.FullControl, AccessControlType.Allow));
//Update the Access Control on the File
File.SetAccessControl(filepath, fileS);
//Delete the file
File.Delete(filepath);
Add the following imports
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;
Run the Code in Elevated Mode.

Powered in Windows 8.1 using class Privilege from example:
Manipulate Privileges in Managed Code Reliably, Securely, and Efficiently
private bool TryDeleteFile(string fileName)
{
string filePath = Path.GetFullPath(fileName);
var fi = new FileInfo(filePath);
bool ownerChanged = false;
bool accessChanged = false;
bool isDelete = false;
FileSecurity fs = fi.GetAccessControl();
Privilege p = new Privilege(Privilege.TakeOwnership);
try
{
p.Enable();
fs.SetOwner(WindowsIdentity.GetCurrent().User);
File.SetAccessControl(filePath, fs); //Update the Access Control on the File
ownerChanged = true;
}
catch (PrivilegeNotHeldException ex) { }
finally { p.Revert(); }
try
{
fs.SetAccessRule(new FileSystemAccessRule(WindowsIdentity.GetCurrent().User, FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(filePath, fs);
accessChanged = true;
}
catch (UnauthorizedAccessException ex) { }
if (ownerChanged && accessChanged)
{
try
{
fi.Delete();
isDelete = true;
}
catch (Exception ex) { }
}
return isDelete;
}

See these registry entries for adding a context menu. I was able to rename the folder as well as iexplorer_OFF.exe on Windows 7.
You can probably shell/execute the same from your code.
https://www.howtogeek.com/howto/windows-vista/add-take-ownership-to-explorer-right-click-menu-in-vista/

Related

throwing UnauthorizedAccessException when accessing an image file

I have a problem with accessing and copying an image file. Here my code
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.ShowDialog();
string fileName = "";
fileName = openFileDialog1.FileName;
string newPath = #"C:\Users\grafik5\source\repos\ConsoleApplication1\x64\Debug";
string newFileName = #"image";
string ext = Path.GetExtension(fileName);
openFileDialog1.Dispose();
newPath = Path.Combine(newPath, newFileName + ext);
if (fileName != "")
{
try
{
FileSecurity oFileSecurity = new FileSecurity();
oFileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow));
File.SetAccessControl(fileName, oFileSecurity);
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Error");
}
File.Copy(fileName, newPath, true);
Process process = new Process();
process.StartInfo.FileName = #"C:\Users\grafik5\source\repos\ConsoleApplication1\x64\Debug\ConsoleApplication1.exe";
process.Start();
process.WaitForExit();
flag1 = true;
}
}
I don't know what I need to do. My program always throws the error message.
Another process will read the copied image. It will do image processing.
There is no problem with the process of working. I checked it.
Error is at File.SetAccessControl(fileName, oFileSecurity);
Any young Codeling Jedi should have looked at the documentation, which i assume you have. However -
File.SetAccessControl Method (String, FileSecurity)
Applies access control list (ACL) entries described by a FileSecurity
object to the specified file.
Exceptions
UnauthorizedAccessException
The path parameter specified a file that is read-only.
This operation is not supported on the current platform.
The path parameter specified a directory.
The caller does not have the required permission.
This is probably a permissions thing. The easiest fix, is make sure your application has the appropriate permissions to do this.
Either
Elevate your app by running it as Administrator,
Give your user the appropriate permissions to set the ACL
However it should be wise and prudent, to check if the other conditions apply

UnauthorizedAccessException When trying get access rules using DirectorySecurity library

I am trying to get a particular folder write access for users using a method that gets access rules and checks wheather the logged in user has write access for that folder. But when trying to do this I am getting an error stating UnauthorizedException.I have checked the folder access and everything looks good.I Below is the screenshot of the error:
private bool AccessPackerPlanTemplate()
{
bool result = true;
UserBUList userBUList = new UserBUList();
try
{
string PackerPlanTemplate = System.Configuration.ConfigurationSettings.AppSettings["PackerPlanTemplate"];
userBUList.UserName = (HttpContext.Current.User.Identity).Name.Split('\\')[1].ToString();
string path = PackerPlanTemplate;
string NtAccountName = userBUList.UserName;
DirectoryInfo di = new DirectoryInfo(path);
DirectorySecurity acl = di.GetAccessControl(AccessControlSections.All); //I AM GETTING ERROR ON THIS LINE
System.Security.AccessControl.AuthorizationRuleCollection rules = acl.GetAccessRules(true, true, typeof(NTAccount));
//Go through the rules returned from the DirectorySecurity
foreach (System.Security.AccessControl.AuthorizationRule rule in rules)
{
//If we find one that matches the identity we are looking for
if (rule.IdentityReference.Value.Equals(NtAccountName, StringComparison.CurrentCultureIgnoreCase))
{
//Cast to a FileSystemAccessRule to check for access rights
if ((((FileSystemAccessRule)rule).FileSystemRights & FileSystemRights.WriteData) > 0)
{
result = true ;
}
}
}
}
catch (UnauthorizedAccessException)
{
result = false;
}
return result;
}
Does somebody has any suggestion regarding Where am I going wrong? Is there a better way to do this?

what is the best way to check in C# .NET if a directory has access to list files or a unauthorized access exception would rise

how would I check in the best way in .NET 2.0 C# if I have access to a specified directory
for listing top directory files e.g. a system directory or system volume information folder etc.
My code for it looks now like this, but I think it is not the best way to check for it since it produces an exception each time which is handled by the check function and returning based on it a result.
I would like to use a function which doesn't throw an error to check if in the specified directory is access to list files or maybe my code can be improved or optimized. I might have to check through a thousand directories if exists an access or not. Raising thousand exceptions might cause a problem, but I don't know.
//here my code using System.IO;
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(DirectoryCanListFiles("C:\\Windows\\Prefetch").ToString());
}
public static bool DirectoryCanListFiles(string DirectoryPath)
{
try
{
Directory.GetFiles(DirectoryPath, "*", SearchOption.TopDirectoryOnly);
}
catch { return false; }
return true;
}
The best way to check the permission, is try to access the direcoty (read/write/list) & catch the UnauthorizedAccessException.
However for some reason out there, if you want to check permissions, following code should satisfy your need.
You need to read Access Rules for the directory.
private bool DirectoryCanListFiles(string folder)
{
bool hasAccess = false;
//Step 1. Get the userName for which, this app domain code has been executing
string executingUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
NTAccount acc = new NTAccount(executingUser);
SecurityIdentifier secId = acc.Translate(typeof(SecurityIdentifier)) as SecurityIdentifier;
DirectorySecurity dirSec = Directory.GetAccessControl(folder);
//Step 2. Get directory permission details for each user/group
AuthorizationRuleCollection authRules = dirSec.GetAccessRules(true, true, typeof(SecurityIdentifier));
foreach (FileSystemAccessRule ar in authRules)
{
if (secId.CompareTo(ar.IdentityReference as SecurityIdentifier) == 0)
{
var fileSystemRights = ar.FileSystemRights;
Console.WriteLine(fileSystemRights);
//Step 3. Check file system rights here, read / write as required
if (fileSystemRights == FileSystemRights.Read ||
fileSystemRights == FileSystemRights.ReadAndExecute ||
fileSystemRights == FileSystemRights.ReadData ||
fileSystemRights == FileSystemRights.ListDirectory)
{
hasAccess = true;
}
}
}
return hasAccess;
}

C# Linq for files user has read access to

How would I use Linq on list.Items = directoryInfo.GetFiles("\\server\share\folder\"); to include only the files the user has read access to?
...
So far only suggestions are using try/catches, or APIs that are obsolete in .NET 4.0? I'd prefer something to read the ACL's and see if the specific user or a group the user is a member of has been granted read access. I'm trying to do this for simplified management of granting reports to users on a website that won't be high traffic, so the logic that "who knows if you can actually read it when you try to open the file" doesn't pertain to this case. I sense that Microsoft should really make this task easier.
You run the risk of a race condition if you check for read permission prior to opening the file.
If you're attempting to read all of the files you have access to in a folder, better to just try opening each one and catch the UnauthorizedAccessException.
See:
how can you easily check if access is denied for a file in .NET?
How do you check for permissions to write to a directory or file?
just try this out .should work .haven't tested though
var fw = from f in new DirectoryInfo("C:\\Users\\User\\Downloads\\").GetFiles()
where SecurityManager.IsGranted(new FileIOPermission
(FileIOPermissionAccess.Write, f.FullName))
select f;
EDIT if it is just read only files then try this
var fe = from f in new DirectoryInfo("C:\\Users\\ashley\\Downloads\\").GetFiles()
where f.IsReadOnly==true
select f
Note: I haven't tested it, but in theory it should work
First, define a predicate to determine read access
bool CanRead(FileInfo file)
{
try {
file.GetAccessControl();
//Read and write access;
return true;
}
catch (UnauthorizedAccessException uae)
{
if (uae.Message.Contains("read-only"))
{
//read-only access
return true;
}
return false;
}
}
Then, it should be a simple case of using a where clause in a linq query
from file in directoryInfo.GetFiles("\\server\share\folder\")
where HaveAccess(f) == true
select f;
Tested and working, but will return false if the file is in use
void Main()
{
var directoryInfo = new DirectoryInfo(#"C:\");
var currentUser = WindowsIdentity.GetCurrent();
var files = directoryInfo.GetFiles(".").Where(f => CanRead(currentUser, f.FullName));
}
private bool CanRead(WindowsIdentity user, string filePath)
{
if(!File.Exists(filePath))
return false;
try
{
var fileSecurity = File.GetAccessControl(filePath, AccessControlSections.Access);
foreach(FileSystemAccessRule fsRule in fileSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)))
{
foreach(var usrGroup in user.Groups)
{
if(fsRule.IdentityReference.Value == usrGroup.Value)
return true;
}
}
} catch (InvalidOperationException) {
//File is in use
return false;
}
return false;
}

TFS / File Checkout from C#

I don't have a great deal of experience with TFS, other than using it for source control. I am working on a C# application that will need to modify files that are being controlled by TFS. From within my C# application, how can I check out a file that is controlled via TFS?
Thanks - Randy
You can use PendEdit to make your files writables, make your changes to it, then you add it to the pending changes, and finally check it in.
Here is some code where a folder structure is created and then checked in (Very similar to what you will need).
private static void CreateNodes(ItemCollection nodes)
{
using (var tfs = TeamFoundationServerFactory.GetServer("http://tfsserver:8080"))
{
var versionControlServer = tfs.GetService(typeof (VersionControlServer)) as VersionControlServer;
versionControlServer.NonFatalError += OnNonFatalError;
// Create a new workspace for the currently authenticated user.
var workspace = versionControlServer.CreateWorkspace("Temporary Workspace", versionControlServer.AuthenticatedUser);
try
{
// Check if a mapping already exists.
var workingFolder = new WorkingFolder("$/testagile", #"c:\tempFolder");
// Create the mapping (if it exists already, it just overides it, that is fine).
workspace.CreateMapping(workingFolder);
// Go through the folder structure defined and create it locally, then check in the changes.
CreateFolderStructure(workspace, nodes, workingFolder.LocalItem);
// Check in the changes made.
workspace.CheckIn(workspace.GetPendingChanges(), "This is my comment");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Cleanup the workspace.
workspace.Delete();
// Remove the temp folder used.
Directory.Delete("tempFolder", true);
}
}
}
private static void CreateFolderStructure(Workspace workspace, ItemCollection nodes, string initialPath)
{
foreach (RadTreeViewItem node in nodes)
{
var newFolderPath = initialPath + #"\" + node.Header;
Directory.CreateDirectory(newFolderPath);
workspace.PendAdd(newFolderPath);
if (node.HasItems)
{
CreateFolderStructure(workspace, node.Items, newFolderPath);
}
}
}
Using the other solution gave me permission problems.
Here's an alternative way to checkout your files using tf.exe:
//Checkout file
Process proc = new Process();
proc.StartInfo =
new ProcessStartInfo(
#"C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe",
string.Format("checkout \"{0}\"", fileLocation)
);
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
For those looking to use the first solution and resolve the permission issue you can use the following code to use the current credentials, this replaces the "TeamFoundationServerFactory.GetServer" call then use the TfsTeamProjectCollection (tmPrjColl) to get the VersionControlServer:
using Microsoft.TeamFoundation.Client;
using MTVC = Microsoft.TeamFoundation.VersionControl.Client;
using MVSC = Microsoft.VisualStudio.Services.Common;
MVSC.VssCredentials creds = new MVSC.VssCredentials(new MVSC.WindowsCredential(true));
using (TfsTeamProjectCollection tmPrjColl = new TfsTeamProjectCollection(new Uri("<source control URL>"), creds))
{
MTVC.VersionControlServer verCtrlSvr = tmPrjColl.GetService<MTVC.VersionControlServer>();
...
}

Categories