How do I test whether I could write to a filename? - file-io

The title may seem trivial, but this isn't as easy as it sounds. You can't just check the permissions on the file, because the file may not exist, and you may have the necessary permissions to create it and then write to it. But only if you have write permissions on the directory, and maybe execute permissions, and maybe permissions for all the parent directories. Or maybe not. I'm not sure.
So, given a filename, what are all the cases that I need to account for in order to correctly test whether I could open and write to a file with that filename? This isn't specific to any one programming language. I just want the logic. But examples in real programming languages are welcome.

Such a test wouldn't necessarily be very useful -- you're just setting yourself up
for a race condition, if the file becomes unwriteable for some reason between your check
and the write attempt. (Some other process could change the permissions, move or delete
the parent directory, use up the last free space on the device, etc...)
I'd just go ahead and attempt the write, and be diligent about checking for errors
at each step (opening, each write attempt, closing) where an operation could conceivably
fail.

It depends on the owner of the process who runs the program, whether the owner has permissions to write to that directory or not. For example, apache running as www user may not be able to write to a directory owned by root and no permissions for other or group.
You may do it hit or trail way, like try creating the file to see if it's successful or not, in case it fails to catch the proper error code and like no permission or directory full and take corrective action.
You may programmatically check if the user has permissions to write into directory if the directory has space, if the file already exists etc. By using certain apis the system exposes and the language exposes, this much better approach taking care of cases rather than handling failure cases.

Related

Multiple users executing the same workflow

Are there guidelines regarding how to share a Snakemake workflow among multiple users on the same data under Linux, or is the whole thing considered bad practice?
Let me explain in case it's not clear:
Suppose user A executes a workflow in directory dir/. Assume the workflow terminates successfully, and he/she then properly sets file/directory permissions recursively on all output and intermediate files and the .snakemake/ subdirectory for other users to read/write, of course.
User B subsequently navigates to dir/, adds input files to the workflow, then executes it. Can anything go wrong?
TL;DR: I'm asking about non-concurrent execution of the same workflow by distinct users on the same system, and on the same data on disk. Is Snakemake designed for such use cases?
It's possible to run snakemake --nolock which will prevent locking of the directory, so multiple runs can be made from inside the same directory. However, without lock, there's now an opening for errors due to concurrent runs trying to modify the same files. It's probably OK, if you are certain that this will be avoided, e.g. if you are in constant communication with another user about which files will be modified.
An alternative option is to create a third directory/path, and put all the data there. This way you can work from separate directories/path and avoid costly recomputes.
I would say that from the point of view of snakemake, and workflow management in general, it's ok for user B to add or update input files and re-run the pipeline. After all, one of the advantages of a workflow management system is to update results according to new input. The problem is that user A could find her results updated without being aware of it.
From the top of my head and without more detail this is what I would suggest. Make snakemake read the list of input files from a table (pandas comes in handy for this) or from some configuration file. Keep this sample sheet under version control (with git/github) together with the Snakefile and other source code.
When users update the working directory with new files, they will also need to update the sample sheet in order for snakemake to "see" the new input and other users will know about it via version control. I prefer this setup over dumping files in a directory and letting snakemake process whatever is in there.

Giving write permissions to a program

I've written a Python program with some UI and froze it using PyInstaller. The program writes to an xml document in the same directory, but not all of the users on the network have write permissions to this file. Rather than give everyone permissions to write to this file, is there a way to set the program's permissions to enable it to write there? That way regardless of who runs it the program will write to the xml, but any user who didn't originally have write permissions won't be able to go manually change any of the data in the file.
A stated by #c_str in the comments you can run the process as another user on windows.
On Linux you can also use setuid and setguid to let process have his owner´s permission instead of runner user permissions.
Even though this works, both methods are questionable as stated by #c_str in the comments above.

Setting permissions based on the program trying to access a kernel module

I have written a kernel module that creates a /proc file and reads values written into it from a user program,say user.c
Now I want restrict permissions for this /proc file.I have restricted permissions based on userid using the 'current' kernel variable by checking current->euid.
My question: Is there a way to restrict this based on the program too? i.e. only user.c should be able to write to this proc file and not any other program.I could not find any parameters in task_struct that would help me do this. Can you please suggest a way to do this?
In your proc writer implementation (that is, inside the kernel module) the best you can do is check the value of current (a struct task *), which holds (among other things) valuable fields such as comm (16-character argv[0]), pid, uid, etc (Basically, everything you see in /proc//status. You can also check the original exe name (like you see in /proc//exe), to see if it's a well known path. You can then return an error.
Caveat: Anyone could rename their opening process to be one of your "allowed" programs, if you go by "comm", and there are ways to defeat the "exe" protection. This will only make it slightly harder, but not impossible for someone to get around. A more comprehensive and stronger solution would require you to peek at the user mode memory of the program, which is possible, but too complicated for a brief answer.
Note: Permission parameters won't work, don't even bother. They go by classic UNIX ACL, which is u/g/o - so you can't filter by PID.

About 'writing to files' and user permissions

I'm working on a VB.NET (2010) project that will need to write text files to the end user's computer. I have read online that due to some user's security settings, that the safest place to write files to is the Application Data folder.
But what I would like to do (if possible) is allow the user to select where they want the files written to, via a SaveToFile dialog (I am using a SaveFileDialog in combination with My.Computer.FileSystem.WriteAllText).
So my question is... if I use a SaveFileDialog (as opposed to saving a file without using a dialog), does that mean that my files will always be written to wherever the user selects?
Or is it possible that the user could select a location (ie their "desktop"), and it would not write the file there, due to their security settings? (UAC, Firewall, etc).
If the latter is possible, is there anything I can suggest to the user that they can do that would enable my program to write files to wherever they select, and it would work 100% of the time?
Like maybe... if they right-click on my program's exe file and go to Properties > Security, and make sure the 'Write' permission is allowed, will that do the trick? Or is there more to it than that?
And does it mke any difference whether or not they are logged into their computer as "admin"?
I've read a lot of conflicting things about all of this online, so I'm just trying to getting a better understanding of it all so that I know how to proceed.
Thanks!
The [Save As] dialog will only let the users select a folder they have read and write acceess to and that is done for you by the Operating system . So that is the best option in my openion

Allowing administrators to modify user's settings from within my program -- what's my best option?

I've been working on making my app easier to use for administrators. One of the things I'd really like to do is allow admins to modify other user's settings from within the program -- while still making it possible for regular ol' users to modify their own settings, as my application isn't necessarily only for administrators who want to force users to use specific settings.
I thought of two possible ways of doing this:
1) Move the user setting file path from where it is now (CLSID_APPDATA, commonly Documents and Settings\Username) to a world-accessible path (CLSID_COMMON_APPDATA , commonly Documents and Settings\All Users). Then, save each user's settings to a unique file for the user (probably having a name which equals that of the user's textual SID), so the folder looks something like:
C:\Documents and Settings\All Users\My Company\My Program\settings\123-abc-456-def.settings
C:\Documents and Settings\All Users\My Company\My Program\settings\234-bcd-477-xyz.settings
C:\Documents and Settings\All Users\My Company\My Program\settings\946-hdc-743-ddd.settings
Pros:This allows an admin to see and directly modify any user's settings, because the COMMON_APPDATA path is the same for all users. This is how I'd really like it to be -- it's the most straightforward -- but there's a major con:
Cons:Permissions could be a problem. To allow regular users to save their settings, you'd have to allow users write access to the program's COMMON_APPDATA setting folder.
Of course, when the settings are saved and the setting file created on disk, you'd want to limit write access on the user's setting file to the user who the settings are for, and for admins, so that other limited user's can't modify them.
However, it could be that before a user has a chance to write their own settings from within the program, a savvy, malicious limited user creates a setting file for that specific user, without the knowledge of the user. If the limited user creates the file, that means they own the file... and then that user (who the settings are for) can't modify the settings anymore, unless an admin changes the permissions on the file.
An unlikely situation perhaps, but it still worries me.
2) Instead of moving the setting file path to a globally-accessible path and modifying the user's setting file directly, have my app create and save an "override" file in the app's CLSID_COMMON_APPDATA folder, to allow the admin to override the user's settings.
When my app loads for that user (who's settings were "overridden") it'll detect this file and load it instead of the regular setting file, which is located in CLSID_APPDATA (Documents and Settings\Username).
Pros:Permissions are easy to deal with.
By default, for the Documents and Settings\Username APPDATA folder, only admins and Username can access the files from within. So that in itself protects the user's own regular personal settings from other limited users.
To protect the "override" settings, my app can simply deny write access to the COMMON_APPDATA folder -- where the override file is written -- to all but administrators, and then that's that. These overriding settings will only be modifiable by admins.
Cons:This method is obviously more roundabout. If a user modifies his own regular personal settings, an admin won't see those changes -- the admin can only see the settings he's overriding the user's regular settings with (which he can force the user to use instead).
In some ways, this might be good, but... the fact that it's roundabout turns me off somewhat.
I'm interested to hear what you guys think about this. Which is my best option? I'm personally leaning more towards #2, because while it's less straightforward, it seems to be more secure and isn't so roundabout where it'd be confusing for an admin.
However, I'm also open to suggestions. Is there a superior option you think would work better?
EDIT 7/6/09: I should note that for option #2, the admin could not only override all user's settings with a single override file, but also override an individual user's settings with an override file specific to that user (just like with option #1, that file name would likely be that of the SID of the user who's settings are being overridden). Not sure if that was completely clear in the original post.
Unless there is more than one user account on each computer (i.e. a computer is used by more than one person), option two is the better choice.
Even if there is more than one user account on each computer, I think option two is still a better choice. Worst case, the administrator will have to change settings on a handful of accounts on the same computer instead of one.
If your facility allows random usage of any computer by any person, then option one is the better choice, since option two will make it too difficult to maintain that many different accounts on every computer.
Of course, you can always put the application settings in user folders on the server. That would make it very convenient for an administrator.
If the administrator already has rights to the user's directory where his setting's file is stored, wouldn't that already solve your problem? Either way though, it sounds like option 2 would be best, then you could have a single file that could override say a group of users, then each user have their own settings as well. Just so long as your application is smart enough to tell when to override a setting and when not too, option 2 shouldn't be that much of an issue.