Delete file from system location with app-scoped security bookmark - macos

I've got an OS X App where I request app-scoped security bookmarks from the user using an NSOpenPanel - this works great.
Now I want to delete the file as well - this works for ALL files except for those stored in system locations, e.g. /private/var/log. Even though the user granted me a (not stale) security bookmark.
Is there any entitlement that allows me to delete user-selected files from those locations?
Just for reference, the following entitlements are set:
<key>com.apple.security.temporary-exception.files.home-relative-path.read-write</key>
<array>
<string>/.Trash</string>
</array>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.bookmarks.app-scope</key>
<true/>
<key>com.apple.security.app-sandbox</key>
<true/>
Cheers!

Most of the files in system locations belong to user root and no one else has write permission. In order to delete such files, they need to have the appropriate permissions set. You can check this using terminal:
cd /private/var/log
ls -la
Just because your app has permission by sandbox doesn't mean it has permission by filesystem to write and remove. Sorry to say.

I believe all you need is access to the file's (parent) directory, as it's the directory that is modified when a file is deleted.
I assume you can do this using the same permission-granting mechanism you currently use.
Of course the user themselves don't have read/write access to all the files in the system, so that will limit the ability to delete system files. If you wanted to delete those then you need to implement privilege escalation.

Related

Add read permission for all administrators to a copied file

Problem is simple my application copies some file from one location to another.
File at destination folder should be readable by all administrators of computer without elevating privileges.
I've found an API which should do it:
SetNamedSecurityInfoW
SetKernelObjectSecurity
But I'm not fluent with Windows API and this security API is quite complex, so I need help ho to use this API.
Main problem I have is how to get psidGroup? Other stuff is obvious or I can just provide a NULL.
Or is there a better API so I can add this read permission for administrators while file is copied?
psidGroup in SetNamedSecurityInfo is used to change owner or group of the file. There is an example on msdn, get the old Security Info first, then modify(SetEntriesInAcl) and submit(SetNamedSecurityInfo). If you want to set the permission of the a group, set the EXPLICIT_ACCESS.Trustee.TrusteeType to TRUSTEE_IS_GROUP, then you can set the a permission for a group.

AppleScript App entitlement for access-group identifier="*"

I am developing a Mac app that makes use of App Scripting. The is Sandboxed and thus needs the proper entitlements in order to get permissions to send AppleScript events to other apps. I have gotten this working properly for apps (like Mail and spotify) which specify access-group identifiers like this:
<access-group identifier="com.apple.mail.compose" access="rw"/>
<access-group identifier="com.spotify.playback"/>
However, a few other of the Apple made apps (like Xcode) specify their identifiers like this:
<access-group identifier="*"/>
I have tried to configure my entitlement file like this:
<key>com.apple.security.scripting-targets</key>
<dict>
<key>com.apple.dt.Xcode</key>
<array>
<string>*</string>
</array>
</dict>
, but when doing this it does not work and I get this error message in the console:
AppleEvents/sandbox: Returning errAEPrivilegeError/-10004 and denying dispatch of event xcod/buld from process '-------'/0x0-0x1a05a04, pid=82514, because it is not entitled to send an AppleEvent to this process.
Does anyone know how to properly configure this?
Actually I found the answer myself. In the sdef Man pages it states:
An identifier of "*" means the element is usable by any application,
without an explicit entitlement.
This means that you do not have to add the identifiers in your entitlements file and it should work regardless. The reason why I got the error was because I accidentally used commands that were not included in those particular access-groups.

Create user independent logfiles in C:\ProgramData

I would like to create logfiles for my application in an user independent lactation. AFAIK C:\ProgramData is good place for that.
I've tried it this way:
if not DirectoryExists('C:\ProgramData\MyApp') then
CreateDirectory('C:\ProgramData\MyApp', nil);
LogFileStream := TFileStream.Create('C:\ProgramData\MyApp\LogFile01.txt', fmCreate, (fmOpenRead or fmShareDenyNone));
The problem with this approach is that the created filed does not have Authenticated Users nor Everyone in Properties->Security->Group or user names.
This results in other users being unable to modify the created files.
But how can I achieve this, also other users being albe to modify the created files.
I think it must be possible to have files with this permission there. Some files do have this permission e.g. C:\ProgramData\Microsoft\Windows\Ringtones\Ringtone *.wav
Maybe either in
1.) somehow creating a 'MyApp' folder in C:\ProgramData with Authenticated Users or Everyone permission which would result in TFileStream automatically creating files with the same permission or
2.) somehow telling TFileStream to create the files with the required permission or
3.) somehow changing the files permission with some API function after its creation or
4.) some other way??
The default permissions in C:\ProgramData, aka FOLDERID_ProgramData allow any user to create new files and folders. However, only the user who creates the file or folder has permission to write to it.
So, if you wish to allow any user to modify objects under FOLDERID_ProgramData then you need to add a permissive ACL to grant those rights. You would typically do that when you installed your program. Create a folder under FOLDERID_ProgramData and add an ACL to grant rights to whichever class of users you wish to allow full access.
As an aside, clearly you should not be hard coding C:\ProgramData, but instead using FOLDERID_ProgramData with the known folder API. I guess the code in the question is just for testing, and your real program code does it correctly.

How can I pass the name of the file that was changed in launchd?

I am trying to watch a directory for changes via launchd. My plist
file looks like this:
<key>ProgramArguments</key>
<array>
<string>/Users/myname/bin/boink</string>
<string>path modified</string>
</array>
All this works OK, but I would like to pass the name of the file that
was changed as an argument to the script /Users/myname/bin/boink
Is that possible? the man page isn't very helpful, nor did googling help a lot.
Thanks.
The short answer is: no. launchd(8) uses Kqueue (http://en.wikipedia.org/wiki/Kqueue) to receive this kind of notification. Unfortunately kqueue(2) does not return which item has triggered the event.
You may want to use the launchd(8) key QueueDirectories instead. It works essentially the same way WatchPaths works, but it assumes that the processing agent/daemon is moving the processed items from the directory being monitored to another one. So whenever an event is triggered your job can process every file in the monitored directory. Just make sure you move them after processing.

Non in-place saving in OS X sandbox

I'm developing a sandboxed app for Mac OS X 10.7 and I'm trying to implement file saving in a way similar to NSDocument:
Rewrite the file's new contents to a temporary file
Overwrite the original file with the temporary file
The issue I'm having is that the sandbox is denying step 2. I see the following line in Console:
sandboxd: XXXX deny file-write-create /Volumes/Home/sbooth/Test Files/Test
I already have this file open for reading and writing, and I have the File System Read/Write Access entitlement enabled. I know NSDocument does this with no special entitlements so I'm trying to figure out what I've missed.
Here is how I'm doing things now (this portion of the app is in C++, not Objective-C/C++):
FSRef tempFileFSRef;
if(noErr != FSPathMakeRef((const UInt8 *)tempFileName, &tempFileFSRef, NULL))
; // Handle it
CFURLRef destinationDirURL = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, mURL);
FSRef destinationDirFSRef;
if(!CFURLGetFSRef(destinationDirURL, &destinationDirFSRef))
; // Handle it
CFRelease(destinationDirURL), destinationDirURL = NULL;
CFStringRef destinationName = CFURLCopyLastPathComponent(mURL);
FSRef target;
OSStatus result = FSCopyObjectSync(&tempFileFSRef, &destinationDirFSRef, destinationName, &target, kFSFileOperationOverwrite | kFSFileOperationSkipSourcePermissionErrors);
if(noErr != result)
; // Handle it
The code works correctly if I disable sandboxing.
Edit: Additional information was requested by Femi. I open the file using C stdio:
FILE *f = fopen(reinterpret_cast<const char *>(buf), "r");
and it closed using fclose before the temp file is created.
My entitlements are:
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.assets.music.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
It's also worth noting that Apple says in their App Sandbox Design Guide that:
If you are managing documents using any technology other than the
NSDocument class, you must convert to using this class. The NSDocument
class automatically works with Powerbox. NSDocument also provides
support for keeping documents within your sandbox if the user moves
them using Finder.
The sandbox only allows you to read and write from your application's container. If you have the read/write entitlement enabled, then you only have access to the files that are opened via the OpenSavePanel (or some method like dragging an icon to the dock where the user has specifically opened the file). This will severely limit how the application works with files on the file system.
So, as long as your application has permission to write over the document in question, you can write your temporary file to your applications container and then retrieve the temp file contents to then save to the original location. However, this assumes that you app maintains permissions to the original file throughout the process.
So, my suggestion is to make sure any writing you do is done in the application container and then verify that you app still has permission to write to the real file location before calling the save function.
I recently wrote a similar question where my app lost access to files that were open because another (non-sandboxed) app saved to the same file. The sandbox then gave that app access to my doc and removed permissions from the app.

Resources