I've got a console program written in C# which runs under user foo. The program creates a file. In some situations a web application running under the IUSR needs to be able to delete the files created by the console app.
I'd like to grant DELETE (or anything equivalent) to IUSR when the file is created. How can I do that in C# ?
I've found FileIOPermission and I'm not sure what that's for but as you can't specify a particular user I'm pretty sure that's now what I need.
Anyone got a good pointer on how to do this ?
[By the way I realise that in some circs granting the IUSR DELETE rights on any files would be a reasonably dodgy thing to do but in this case the nature of the files involved means I'm happy to grant these rights to IUSR]
#Sabau: thanks for the amendment to your answer - it inspired me to try again and this time I seem to have got it worked out. I wrote a little test program so that others can see how it's done. For my testing I gave the IUSR full control but obviously you can add/deny whatever you like.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security.AccessControl;
namespace GrantingFilePermsTests
{
class Program
{
static void Main(string[] args)
{
string strFilePath1 = "E:/1.txt";
string strFilePath2 = "E:/2.txt";
if (File.Exists(strFilePath1))
{
File.Delete(strFilePath1);
}
if (File.Exists(strFilePath2))
{
File.Delete(strFilePath2);
}
File.Create(strFilePath1);
File.Create(strFilePath2);
// Get a FileSecurity object that represents the
// current security settings.
FileSecurity fSecurity = File.GetAccessControl(strFilePath1);
// Add the FileSystemAccessRule to the security settings.
fSecurity.AddAccessRule(new FileSystemAccessRule("IUSR_SOMESERVER",FileSystemRights.FullControl,AccessControlType.Allow));
// Set the new access settings.
File.SetAccessControl(strFilePath1, fSecurity);
}
}
}
Thanks to all for their replies.
Use the Windows Explorer -> select the directory where the file resides -> right-click -> Properties -> Security tab -> give the "Modify" right to the IUSR_xxx user account.
I presume that you have physical access to the computer that runs both the console app and the web app.
Edited: for programmatic setting of ntfs permissions you need to fiddle around with the System.Security.AccessControl.FileSecurity class and the File.SetAccessControl method.
Hope it helps.
A quick google search produced Setting NTFS Permissions with C#
Related
In windows server 2016, I create a text file inside "Windows" folder for some reasons, and in special cases I need to delete it from my website which is built in C# MVC, is there any way to do that using C# (MVC or Core)? I know that it is illogical but I need that if applicable.
The answer for your solution is fairly simple, yes it is indeed possible to remove a Windows file or folder. However, this is costly! Allowing an application to have Administrator permissions can lead to malicious behaviors. Such as UAC Bypassing from other malware.
All you need to do in order to delete that file programming using C# is to first off run your application with administrator rights. Here's source the code for it:
using System;
using System.IO;
public class Program {
public static void Main() {
String myPath = #"<DRIVE_LETTER>:\Windows\<FILENAME>"; // E.g: #"C:\Windows\MyText.txt";
try{ // For stability purposes,
File.Delete(myPath);
} catch (IOException ERROR){ // If any errors occurs, it will print it out!
Console.WriteLine(ERROR.Message);
}
}
}
Documentation for Permission(s) Risks: Risks of Admin Rights
Documentation for File.Delete: File.Delete(String) Method C#
Hello fellow developers,
I'm trying to give a C# application that I'm creating the ability to delete the files from a flash-drive or other folder, for which admin priv is needed. But it's not working!
I am an admin user on my Win10 box. I can delete the files in File Explorer. But the program throws an IOException when it tries to do it (I'm using any of several methods to delete the files, including interoping to Win32).
I did create and embed an Application Manifest for the program project (I'm using Visual Studio 2017), and set the level attribute of the requestedExecutionLevel element to "requireAdministrator". And within the project-properties it does show this file, app.manifest, as part of it. But that seems to accomplish nothing -- the program can still be launched NOT as administrator.
Btw, I see two different methods to detect whether the program is running as with administrator priv:
public bool IsRunAsAdmin1()
{
return Thread.CurrentPrincipal.IsInRole( WindowsBuiltInRole.Administrator.ToString() );
}
This does NOT seem to be working (always returning false).
and..
public bool IsRunAsAdmin2()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal( id );
return principal.IsInRole( WindowsBuiltInRole.Administrator );
}
which does work.
Regardless, even when I right-click on the program and run it as administrator -- it returns Win32 error 5 (access denied) for Hidden files.
I want to make this delete files robustly, regardless of the file's attributes. How can I do this?
Thank you for your help and insights, James
I'm not sure what do you mean by
the program can still be launched NOT as administrator.
If you setup the app.manifest file properly (see this) then it always will be running as administrator.
I'm not sure about the hidden files. My quick advice would be just to remove the hidden/readonly flag (like this) and then call File.Delete.
I am working as a trainee engineer in a networking firm and am getting annoyed by having to change the IP information from time to time.
I am in need of building a software to help me change these details easily. I have managed to set the IP information. But I still have problems.
I need to run the program as Administrator [right click], is there a way to program to prompt for it at startup?
How can I change adapter to DHCP?
The code is quite long, and I hope not to fill bore you with it. But I have been using Management
Management Class
Management Base Object
Management Object Collection in my development.
I'd prefer to make my own program to develop my programming skills. But if there is an application to do it, I don't mind knowing.
I hope this answer gives you some insisght and direction to go.
Okay, the network adapter one isn't that straight forward, but I believe you can achieve it with WMI, specially this WMI object here. The MSDN documentation tells you all the properties, methods (which there are for setting DHCP etc) and the datatypes and values it takes. This may be one approach as using WMI through C# is pretty easy. I wish I could provide you an example, but I've never used that specific WMI class before. You can also access the above WMI class through the Visual Studio Server Explorer, which you can see here. ..and it has your "EnableDHCP" method you are probably looking for.
As far as asking for your program to run with administrative priviledges, here is the code from my setup project in my framework. What this does is before it runs any sort of form or logic, requests the "runas" verb which invokes UAC (if Windows has its Vista/7, and requests admin priviledges from the user)
namespace Setup {
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Setup.Forms;
using System.Security.Principal;
using System.Diagnostics;
static class Program {
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
WindowsPrincipal principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
bool administrativeMode = principal.IsInRole(WindowsBuiltInRole.Administrator);
if (!administrativeMode) {
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Verb = "runas";
startInfo.FileName = Application.ExecutablePath;
try {
Process.Start(startInfo);
}
catch {
return;
}
return;
}
Application.Run(new ShellForm());
}
}
}
As far as a program to do it, Windows Network Connection Manager? I know its cumbersome because of all the dialogs, but.. its already there.
I once had to write a very similar program. I used some of the source code from these two projects to help me get started: Chameleon Project and Configuring TCP/IP Settings using WMI and C#
The Chameleon Project is a C# project to help change network settings of a particular adapter. The other project is a tutorial on how to use C# to change network settings using WMI and C#. You can look at the source code and learn from it to help you make your own software that does what you need.
I'm writing a service monitoring ASP .NET app and I'm having issues particularly with getting the service descriptions. My current method (reading from registry) is not going to work due to registry read permissions on the production server.
For example:
Microsoft.Win32.RegistryKey system, currentControlSet, services, service;
system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
currentControlSet = system.OpenSubKey("CurrentControlSet");
services = currentControlSet.OpenSubKey("Services");
service = services.OpenSubKey(scTemp.ServiceName, true);
row["service_description"] = service.GetValue("Description");
Produces:
System.Security.SecurityException: Requested registry access is not allowed.
My question is:
Is there a work-around with another .NET class (maybe under System.ServiceProcess namespace?) or will it always end with a security exception error?
I have no issues getting Service names and states with the System.ServiceProcess namespace but I can't find any classes contained to get descriptions which is why I resorted to reading from registry.
I think this should work.
EDIT: I should read questions closer. The code below gets the description for the first service in the array.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceProcess;
using System.Management;
namespace ServiceNames
{
class Program
{
static void Main(string[] args)
{
ServiceController[] services = ServiceController.GetServices();
string serviceName = services[0].ServiceName;
string objPath = string.Format("Win32_Service.Name='{0}'", serviceName);
using (ManagementObject service = new ManagementObject(new ManagementPath(objPath)))
{
Console.WriteLine(service["Description"]);
}
Console.Read();
}
}
}
The previous answer showing the WMI solution is a good alternative and worth trying first.
--
I am not aware of a .NET Framework class that exposes the service description.
The first thing I would consider is requiring authenticated connections (e.g. NTLM) and impersonate the caller. As long as you don't do a double-hop (i.e. make a remote call with your impersonated credentials) you may find that you are able to successfully make the registery read.
If that is not possible then making a P/Invoke call may work.
If the credentials your web service has the SERVICE_QUERY_CONFIG permission you could do the following:
Find the service you are interested in using the ServiceController class
Using the ServiceHandle property make a P/Invoke call to QueryServiceConfig2 using the SERVICE_CONFIG_DESCRIPTION info level passing in null for the buffer and 0 for the lenght, reading the required buffer length from pcbBytesNeeded.
Allocate the proper buffer length and call QueryServiceConfig2 a second time getting the service description.
Obviously reading from the registery is a little more straight-forward (and in the end the permissions issues may be similar in both cases) - but using a supported API seems like a less fragile solution.
Side question: is there something you are trying to accomplish that PerfMon and logging can't tell you?
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.