I'm trying to Implement The Bell-La Padula Model on local windows accounts in C# , and in this model the user in lower security level can write to files that belong to higher security level without read it !!
I've Added permissions to files like this
file.txt : read [deny] - write [Allow]
Now I'm working on allow user to append text to file.txt without read it .
I used this :
using (FileStream aFile = new FileStream(filename, FileMode.Append, FileAccess.Write))
using (StreamWriter sw = new StreamWriter(aFile))
{
sw.WriteLine(DateTime.Now.ToString() + " Modified BY :" + username + Environment.NewLine);
sw.WriteLine(textBox1.Text);
sw.WriteLine("---------- END User Edition --------------");
}
It worked when I run The program from the Admin account ,but when I tried to run it from Guset account it raise exception : you can't access this file !
I've tried to add read permissions before Start Editing and remove it after finish , but the the file permissions never changed .
Is there any programmatic way that I can implement that , or allow my application to make effect on file when run it within Guest account ?
Took a little time but got it figured out. Had to use procmon to figure it out. Your code is fine. However, you need to setup permissions properly.
For your text file, you need to grant the limited account rights to Write only. Do not check anything under the deny column. Because if you do, the deny access will trump anything else. You also need to grant that account access to Read Attributes and Read Extended Attributes permissions as well.
You can probably accomplish the same thing using icacls or cacls. Here are the manual instructions on how to do it manually. This is based on Windows 10 (Win7 should be similar):
Right click on the file
click on properties.
switch to Security tab.
Click on "Edit" button
Click on "Add..." button
Find the limited user account.
Back in the permissions tab, select the account.
uncheck everything except "Write" checkbox.
Click "OK" to close this dialog box.
Click on "Advanced" button.
Select the account and click "Edit" button.
On the next dialog box, click "Show advanced permissions"
Make sure that the following check boxes are checked.
Read Attributes
Read extended attributes
Create files / write data
Create folders / append data
Write attributes
Write extended attributes
Click OK on all the dialog boxes.
To do this programmatically, you need to allow these:
System.Security.AccessControl.FileSystemRights.AppendData
System.Security.AccessControl.FileSystemRights.CreateFiles
System.Security.AccessControl.FileSystemRights.ReadAttributes
System.Security.AccessControl.FileSystemRights.ReadExtendedAttributes
System.Security.AccessControl.FileSystemRights.WriteAttributes
System.Security.AccessControl.FileSystemRights.WriteExtendedAttributes
Extra info here
Read/Write(Extended)Attributes are necessary for write operations, above will let users to create log files and append text to them without being able to read anything, If you add Delete permission, that will make rolling of the log files possible as well (i'd say most of people will need it as having unlimited size logs without rolling is quite dangerous)
This can be done via any .NET language, PowerShell example (create and write logs files and roll them permissions):
$acl = Get-Acl "C:\logs"
$acl.SetAccessRuleProtection($true, $false) # Remove inherited
$acl.Access | % { $acl.RemoveAccessRule($_) } | Out-Null # Remove existing
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("SYSTEM", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Administrators", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
$logsRights = [System.Security.AccessControl.FileSystemRights]::AppendData -bor `
[System.Security.AccessControl.FileSystemRights]::CreateFiles -bor `
[System.Security.AccessControl.FileSystemRights]::Delete -bor `
[System.Security.AccessControl.FileSystemRights]::ReadAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::ReadExtendedAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::WriteAttributes -bor `
[System.Security.AccessControl.FileSystemRights]::WriteExtendedAttributes
$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule("Users", $logsRights, "ContainerInherit, ObjectInherit", "None", "Allow")))
Set-Acl "C:\logs" $acl
Write-Host "logs ACL"
$acl.Access
Depending on your use case you may or may not need to clear existing rules and add SYSTEM/Administrators, but you get the idea
Related
so i'm trying to automate some reporting in Access 2013. When I run a report I get a dialog asking for a parameter (Enter Plant:), something like this.
What I want is to run this code without asking the query for a plant name. The code works but if I run it, it pops a dialog asking for a Plant name, and if I type the Plant Name it runs and saves the pdf file just like I want to. The report in Access works by giving a different Plant name and it outputs a different report depending on the given Plant. My idea is to put this code on a loop and in each iteration pass a different plant name and save a different new file. But it always pop a dialog asks for a plant name to be added manually.
Microsoft.Office.Interop.Access.Application oAccess = null;
// Start a new instance of Access for Automation:
oAccess = new Microsoft.Office.Interop.Access.Application();
// Open a database in exclusive mode:
oAccess.OpenCurrentDatabase(
"route DB", //filepath
true //Exclusive
);
//This doesnt work
// oAccess.DoCmd.SetParameter("[Enter Plant:]", "Arlington");
oAccess.DoCmd.OpenReport(
"06 - Security Report - Plants",
AcView.acViewReport,
"qry Security Report - Plant",
//This doesnt work either, still asks me for a plant name
"[Enter Plant:] ='Arlington'",
AcWindowMode.acWindowNormal
);
//If I give the plant name to the dialog it works correctly en saves a pdf file wit the report
oAccess.DoCmd.OutputTo(
AcOutputObjectType.acOutputReport,
System.Reflection.Missing.Value,
"PDF Format (*.pdf)",
"route to save file",
false,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
AcExportQuality.acExportQualityPrint
);
oAccess.Quit();
I can access the query but unfortunately i cant modify it, also its pretty long thats why I will not be able to show it(looks like it was created by a the Access Wizard, so its preeety long) though here its an example where the asked parameter is being used:
AND ((Signers.Location)=[Enter Plant:])
This parameters is in the query like 40+ times.
Any ideas? Thanks in advance!
I have faced this many times at work, and the solution I used most often is to have a TextBox in a form somewhere that can be referenced directly.
AND ((Signers.Location)=[Forms]![frmMyForm]![txtMyPlantTextBox])
NOTE: You would need to have the form open and data entered into the TextBox before you run the query.
I am writing an extension for the Unity Editor..
I need to programmatically access and check the current Device Filter that have been selected from the "other settings" tab that appears in "player settings" option when you select build.
I need to selectively add a few files in the project based on this check. I have no direction as of now. Would appreciate any sort of help. Thanks
Unfortunately, it is not named PlayerSettings.deviceFilter like one would expect since that's what it is displayed as in the Editor. It is called targetDevice and can be accessed from PlayerSettings.Android.targetDevice.
Example of accessing it:
AndroidTargetDevice targetDevice = PlayerSettings.Android.targetDevice;
Can also be changed:
PlayerSettings.Android.targetDevice = AndroidTargetDevice.ARMv7;
PlayerSettings.Android.targetDevice = AndroidTargetDevice.FAT;
PlayerSettings.Android.targetDevice = AndroidTargetDevice.x86;
I have a c# program which open *.postfix file.
If a user runs a (.lnk)shortcut which points to my type of file, my program will open the target.
So, how could my program know it is started by a (.lnk)shortcut (and get it's file path)?
In some circumstances,i need to replace the .lnk file.
Thanks!
Edited
First, thanks to guys who answered my question.
By following #Anders answer, i find out my problem lays here.
I made some changes to windows registry, so browser knows to throw customized protocol string to certain program.
some thing like this..
[InternetShortcut]
URL=myProtocol://abcdefg.....
That's maybe why i lost lpTitle. :(
I'm going to try this way:
Whenever my program invoked, of course fed with %1, program checks current opened explorer(Window), and try to get it's current path with IWebBrowserApp. With that path and desktop of course, scan and analyze *.lnk to determine which one to replace.
I think this will probably work, but not be sure. I will try.
continued
In native code you can call GetStartupInfo, if the STARTF_TITLEISLINKNAME bit is set in STARTUPINFO.dwFlags then the path to the .lnk is in STARTUPINFO.lpTitle. I don't know if there is a .NET way to get this info, you probably have to P/Invoke...
You don't. There's no way to do it. End of story.
So this has been brought to my attention due to a recent downvote. There's an accepted answer showing an idea that gets the path to the launching shortcut most of the time. However my answer is to the whole. OP wants the link to the shortcut so he can change it. That is what can't be done most of the time.
Most likely case is the shortcut file exists in the start menu but is unwritable. However other cases involve the shortcut coming from another launching application that didn't even read it from a disk but from a database (I've seen a lot of corporate level restricted application launch tools). I also have a program that launches programs from shortcuts not via IShellLink but by parsing the .lnk file (because it must not start COM for reasons) and launching the program contained. It doesn't pass STARTF_TITLEISLINKNAME because it's passing an actual title.
If you're using Visual Studio Setup Project to build an installer and do the file type association, you should follow these instructions http://www.dreamincode.net/forums/topic/58005-file-associations-in-visual-studio/
Open up your solution in Visual studio.
Add a Setup Project to your solution by file , add project,New project, Setup & Deployment projects,Setup project
Right-click on your setup project in the "Solution Explorer" window,Select view,then select file types.
you'll see the "file types" window displayed in Visual studio.At the top of the window will be "File types on target machine"
Right-click on "File types on target machine".the menu will pop up with Add "file type" Click on this.
you'll see "New document Type#1" added,and "&open"underneath it.
The "new document type#1" can be anything you want - change it to something descriptive.although the user never sees this,never use something common- be as unique as possible,Because you can overlay current file associations without even realizing it.For example,you might think"pngfile" might be a useful name- but using that will now send all"*.png" files to your application,instead of to an image viewer.A good practice maybe "YourCompantName.Filetype",where your company name is your name of your company's name, and "Filetype" is a descriptive text of your file.
In the "properties" window for your new type,you will need to change a few properties.:
Command:Change to the application that you want to run.If you click on the "..." and you will proberly want to locate and use the "primary Output..." File
Description: This is the description of the file type(if it doesn't describe it's self"
Extensions:This your list of extensions for you chosen Program.Separate each one with a ","
Icon:This will associate the icon with your file type,This shows up in the window explorer.
Now we move to that "&open ".This is an action that is available if your right-click on the file.The default action("&Open" is currently set as the default) is what happens when you double click on the file.Right click on your "New document type#1" to add actions,but for the moment,lets define our "&open" action
Click on "&Open".You will see in the properties window "Name","Arguments","Verbs". Verb is hidden from the user,but is the key that is stored in the registry.Leave it same as the name,But without the "&".The default for"Arguments" is "%1",Which means to pass the full path and filename to your application.You can add other stuff here as well,if you need to pass flags to your application to do special stuff.All this infomaton is getting passed to your application on the command line,so you'll need to be familiar with the "Environment.CommandLine" object.
If you need to set a different action as your default,just right click on the action and "set as default"
Basically, you'll pass the file path as an argument to your program. Then if it's a console application or Windows Forms , you should check the arguments in Program.Main
static void Main(string[] args)
{
//if file association done with Arguments %1 as per forum post above
//you file path should be in args[0]
string filePath = null;
if(args != null && args.Length > 0)
filePath = args[0];
}
For a WPF application you'll need to handle that in the StartUp event for your Application
void App_Startup(object sender, StartupEventArgs e)
{
string filePath = null;
if ((e.Args != null) && (e.Args.Length > 0))
{
filePath = e.Args[0];
}
}
I have tried to create a custom action for a Visual Studio Installer project to modify the permissions for a config file.
The Installer.cs is as follows:
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
// Get path of our installation (e.g. TARGETDIR)
//string configPath = System.IO.Path.GetDirectoryName(Context.Parameters["AssemblyPath"]) + #"\config.xml";
string configPath = #"C:\Program Files\Blueberry\Serial Number Reservation\config.xml";
// Get a FileSecurity object that represents the current security settings.
FileSecurity fSecurity = File.GetAccessControl(configPath);
//Get SID for 'Everyone' - WellKnownSidType works in non-english systems
SecurityIdentifier everyone = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
// Add the FileSystemAccessRule to the security settings.
fSecurity.AddAccessRule(new FileSystemAccessRule(everyone, FileSystemRights.Modify | FileSystemRights.Synchronize, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow));
// Set the new access settings.
File.SetAccessControl(configPath, fSecurity);
}
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
}
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
}
Then I add the Primary Output (Installer class = true) into the Commit section of the setup project's Custom Actions.
When I run the installer, I get the following error:
Error 1001: Could not find file 'c:\mypath\myapp.InstallState'
Scouring the web I've found a few examples of similar experiences, but none of the solutions offered have worked for me.
Any ideas?
You can find a solution here
To quote:
The problem is that the MSI infrastructure is looking for the installation state file which is usually created during the Install
phase. If the custom action does not participate in the Install phase,
no file is created.
The solution is to add the custom action to both the Install and the
Commit phases, although it does nothing during the install phase.
I had this problem when I didn't specify a custom action in my installer project for all four overrides (Install, Uninstall, Commit, and Rollback). As soon as I specified my project output as the custom action for all four, the issue went away.
The only overrides in my installer class that did anything were Commit and Uninstall; I think that Install was in charge of creating the InstallState file in the first place, and since it was never called the InstallState file was never created.
Sometimes this happens when the installer class is not created correctly. Here is a tutorial which may help you: http://devcity.net/Articles/339/1/article.aspx
Make sure that your custom action follows the tutorial recommendations.
Sometimes, "Debugger.Launch();" is put at those overwritten functions for debugging. If you build the installer with the statement there, and during your installation, a dialog will popup to ask you whether debug is needed, if you press 'cancel debugging', you'll get this error dialog. Because you added the 'Debugger.Launch()' at your function, then that function will be considered as 'missed' by installer. So, don't forget to remove it.
Try installing this as in an administrator command prompt. This worked for me.!
For me, the issue was as simple as just adding a closing quote around one of the textbox names in my CustomActionData string.
I was using the "Textboxes (A)" and "Textboxes (B)" windows in the User Interface section. A has 1 box, EDITA1, where I get the path to a file, and B has 2 boxes, EDITB1 and EDITB2, for some database parameters. My CustomActionData string looked like this:
/filepath="[EDITA1]" /host="[EDITB1] /port="[EDITB2]"
It should have been:
/filepath="[EDITA1]" /host="[EDITB1]" /port="[EDITB2]"
(closing quote on [EDITB1])
I used the Install override in my Installer class to get the values (i.e. string filepath = Context.Parameters["filepath"];) and used it to write them to an INI file for my app to use once installed. I put the "Primary output" under all of the phases in the Custom Actions GUI, but did nothing with the InstallerClass property (default: True) and only set the CustomActionData string on the Install one. I didn't even include override functions in my Installer class, since I was doing nothing that was custom in the other phases.
create your post install executable as you would a console app ex: "mypostinstallapp.exe".
install the "mypostinstallapp.exe" with your msi product. maybe put it with the Application Folder or a shared folder if you want to use it with multiple installs.
in the custom actions (rightclick the msi project and view custom actions) and add an action in the Commit section. assuming you want it to run towards the end.
then select your "mypostinstallapp.exe" from the actions view and in its properties set InstallerClass False.
what I do in "mypostinstallapp.exe" is look for a cmd file and run it as a process.
so i can add stuff to the cmd file and try to forget about the custom action process.
Make sure in the output properties you check installer class to false
You can set a register key to the installation path. Click on the Setup Project, View Register, and set the value as: [ProgramFiles64Folder][Manufacturer][ProductName].
Then you can create a Console App to get in to the register and take this information and run your program. Just need to add as a custom action on Commit the Console App you created.
Try setting Installer class = false instead of true in the properties for your custom action. That fixed this problem for me.
I have created the program which is monitoring a directory (e.g. \\server\share\folderXYZ) for changed events (like created, deleted, renamed and permission changes). I also got the notification if anything changed but I can't get exact details what has changed.
For example I have changed the permission for above directory from folder properties (Properties -> Security -> Edit ->Add new user or group or change permission for user and groups). File system watcher give notification if something changed but I can't get other details like:
For which user permission has changed?
Who changed the user permissions?
If any new group has been added(need to get all users in the group if new group added)?
If any new user is added to group and who added and need to get added user details?
If any user or group is removed than removed group or user details?
If any permission is added or changed for user than what permission are added or changed?
If any permission are changed for group than what permission changed?
Example Scenarios:
Action: At 11am, the Admin added User A to Trainees (Existing group)
Expected Result:
Access to \\server\share\folderXYZ changed: User A now has Read access, given by Admin at 11am, because he is now member of Trainees, which has Read Access.
Hope question is clear. I have done lots of search and couldn't find the solution. Please let me know if any API or Service available or any alternatives available?
-Thanks
The way to get the information you want is to use Windows Security Auditing, esp. since you want to know who made a change, not just what the change was.
The following code (and settings), produce output like this:
11-07-2011 17:43:10: 'Fujitsu\Grynn' changed security descriptor on file 'C:\Users\Grynn\Documents\ExcelTools\test.txt' from
'D:AI(A;;0x1200a9;;;BU)(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
to
'D:ARAI(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
using 'C:\Windows\explorer.exe'
12-07-2011 17:55:10: 'Fujitsu\Grynn' changed security descriptor on file 'C:\Users\Grynn\Documents\ExcelTools\test.txt' from
'D:AI(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
to
'D:ARAI(D;;FA;;;S-1-5-21-559386011-2179397067-1987725642-1001)(A;ID;FA;;;S-1-5-21-559386011-2179397067-1987725642-1000)(A;ID;FA;;;SY)(A;ID;FA;;;BA)'
using 'C:\Windows\explorer.exe'
Turning on Auditing has 2 steps:
1. Use gpedit.msc to turn on "Audit Object access"
2. Modify "Auditing" for the folder you want to watch
Now whenever a File System Change event occurs (or via polling) query the security event log.
Code to query 'Security' event log:
var props = new EventLogPropertySelector(new string[] {
"Event/System/TimeCreated/#SystemTime",
"Event/EventData/Data[#Name='SubjectDomainName']",
"Event/EventData/Data[#Name='SubjectUserName']",
"Event/EventData/Data[#Name='ObjectName']",
"Event/EventData/Data[#Name='OldSd']",
"Event/EventData/Data[#Name='NewSd']",
"Event/EventData/Data[#Name='ProcessName']" });
using (var session = new System.Diagnostics.Eventing.Reader.EventLogSession())
{
//4670 == Permissions on an object were changed
var q = new EventLogQuery("Security", PathType.LogName, "*[System[(EventID=4670)]]");
q.Session = session;
EventLogReader rdr = new EventLogReader(q);
for (EventRecord eventInstance = rdr.ReadEvent();
null != eventInstance; eventInstance = rdr.ReadEvent())
{
var elr = ((EventLogRecord)eventInstance);
Console.WriteLine(
"{0}: '{1}\\{2}' changed security descriptor on file '{3}' from \n'{4}' \nto \n'{5}' \nusing '{6}'\n----\n",
elr.GetPropertyValues(props).ToArray());
}
}
From what i know/been reading, FileSystemWatcher can only tell you the file that was affected along with the change type only.
One way to go is for you to maintain a cache of the file attributes you're interested in, an in the presence of an event notifying a change, you query the cache to get the changes made and update it as necessary.