Cocoa Sandbox App: Spawn FFMPEG - objective-c

I have an application which uses FFMPEG and FFPROBE to perform some tasks on a video the user can open with my application.
For non-sandboxed applications everything works fine, but when my app is running in a sandbox FFPROBE doesn't seem to get started.
The Console says the following:
08.06.15 12:27:55,803 secinitd[281]: ffprobe[4049]: registration request failed: (0x11, 0x0) Container object initialization failed.
failed to get bundleid for app "/Users/Alex/.../ffprobe"
The path to ffprobe mentioned in this messages points to the MacOS directory within the app bundle (a Build Phase copies these two binaries into the executable directory).
I've searched a lot and found some hints regarding entitlements. Of course my sandboxed app has its entitlements and when building my application it gets signed (with --deep signing flag). It even passes the technical App Store check for entitlements.
Now I'm stuck and wonder why my application is not able to launch FFPROBE (and FFMPEG).
Does anybody have a clue?

It seems like I've found a solution. I don't know whether all of these steps are necessary, but here is what I've tried and what seems (!) to work:
I added an entitlements file which contains true for the keys com.apple.security.inheritand com.apple.security.app-sandbox
I added a plist file for each used binary and filled the keys CFBundleName and CFBundleIdentifier with suitable values (I don't know whether this step is necessary)
I added a Run Script build phase which executes codesign -f -s "your certificate" --entitlements ./ffmpeg.entitlements ./Build/Intermediates/ArchiveIntermediates/App\ Store/InstallationBuildProductsLocation/Applications/<my app>/Contents/MacOS/ffmpeg
for each binary used.
These steps result in suitable entitlements when trying to submit the app to the Mac App Store and it results in a correct usage of the embedded binaries (at least on my development Mac and the Mac of some colleagues).

Related

How to run/debug open-source macOS `Privileges` app w/ XPC service/daemon and DockTile plugin

I'm attempting to try out some modifications in SAP's Privileges.app. Unfortunately, their (understandable) Support policy is
This project is 'as-is' with no support, no changes being made. You are welcome to make changes to improve it but we are not available for questions or support of any kind.
Unfortunately, this app uses two constructs I've never come across before in my professional experience, an XPC service + helper (Launch daemon?) and a DockTile plugin. I'm having a hard time just fundamentally getting the app to work when launched from Xcode - it launches, but it seems that there are issues between (maybe?) sandboxing, signing and perhaps entitlements? I've updated the signing to use my own team, of course, and everything compiles/links/launches properly, but when the XPC service tries to install the helper tool it fails
2022-06-29 17:03:56.284544-0500 PrivilegesXPC[13079:128535] [logging-persist] cannot open file at line 45530 of [9ff244ce07]
2022-06-29 17:03:56.284570-0500 PrivilegesXPC[13079:128535] [logging-persist] os_unix.c:45530: (0) open(/var/db/DetachedSignatures) - Undefined error: 0
2022-06-29 17:04:21.060214-0500 PrivilegesXPC[13079:128537] SAPCorp: ERROR! Failed to connect to helper tool: NSCocoaErrorDomain / 4097
2022-06-29 17:04:31.471555-0500 Privileges[13064:127420] SAPCorp: ERROR! Error Domain=NSPOSIXErrorDomain Code=25 "Inappropriate ioctl for device"
2022-06-29 17:04:45.717751-0500 Privileges[13064:129162] SAPCorp: ERROR! Installation of the helper tool failed: Error Domain=CFErrorDomainLaunchd Code=4 "(null)"
As near as I can tell, the last two errors are thrown from a failure in
success = SMJobBless(
kSMDomainSystemLaunchd,
CFSTR("corp.sap.privileges.helper"),
self->_authRef,
&error
);
but I haven't been able to ascertain why this is failing. Searching for errors around Inappropriate ioctl for device has not been fruitful, unfortunately.
If there's anyone out there with some experience in dealing with apps using some of these more esoteric moving parts that can share some things to try, I'd be much obliged. Bonus points if there's any way to debug code running in a DockTile plugin - as near as I can tell, it's running in SystemUIServer, but I can't attach to that (even as root) from Xcode.
I think I've sorted out getting this running. Here's a few roadblocks I encountered.
SMJobBless has some very particular expectations around code-signing - you'll find references to this in some forum posts and there's a sample project that's also referenced with a utility script - which doesn't run on modern macOS because it's written for Python 2 -- which isn't installed by default anymore and a bit difficult to come by. But, after agonizingly converting Python 2-isms over to Python 3, you'll come to find out that that's not the only thing that's changed, a number of the tools (codesign and otool) don't output the same on ARM64 at which time you'll finally stumble across a kind soul that converted SMJobBless.py ... only to find out that it's not actually needed for this project?! Not sure if it's because the Launch Service is contained in the XPC and not the app, but either way - it seems to not be needed.
If you've run Privileges before, it'll have installed it's escalated helper, which will stand in the way of a local Xcode build copying itself over - which matters because of the aforementioned code signing. You'll need to clear away these artifacts
$ sudo rm -rf /Library/PrivilegedHelperTools/corp.sap.privileges.helper
$ sudo rm /Library/LaunchDaemons/corp.sap.privileges.helper.plist
Just deleting them isn't enough, it seems some sort of runtime launchd state needs to be wiped. It's unclear to me if some incantation of launchctl will clear this out, maybe an invocation of launchctl kickstart -k <foo> or something? I ended up rebooting and that seemed to do the trick anyway.
It seems like you need a particular signing certificate to allow the various signing validations that SMJobBless and the XPC communications are doing to be valid. Particularly, it seems you'll need a Developer ID Application, which happens to match what's encoded in the .xcodeproj pulled down from the GitHub repo. This means you can't enable Automatically manage signing as you won't get this type of certificate (as near as I can tell - please correct me if I'm wrong).
Once you've got all that sorted, since you aren't signing with the SAP developer's certificate, your certificate will have a different unique Team ID, so you'll need to update SMAuthorizedClients and SMPrivilegedExecutables, respectively, (look for 7R5ZEU67FQ and replace with your team ID) in
PrivilegesHelper/PrivilegesHelper-Info.plist
PrivilegesXPC/Info.plist
I think that's basically got it. Hope that helps someone else

Notarize process for macos application not working

I have developed an application for MacOS. I am including notarization process as part of its distribution. I have followed all the steps and I have run:
xcrun altool --notarize-app --primary-bundle-id "${APP_BUNDLE_ID}" --username "${APPLE_DEV_ID}" --password "${DEV_APP_SPECIFIC_PASSWORD}" --file "${DMG_PATH}"
Then I check notarization progress using:
xcrun altool --notarization-info "${notarize_uuid}" -u "${APPLE_DEV_ID}" -p "${DEV_APP_SPECIFIC_PASSWORD}
Output of it is:
RequestUUID: =<Request>
Date: 2019-05-26 09:40:34 +0000
Status: success
LogFileURL: <Log file>
Status Code: 0
Status Message: Package Approved =~ success ]]
Then I launch staple command:
xcrun stapler staple -v <dmg file>
It also ends with success:
The staple and validate action worked!
However when I extract the .app file and run:
spctl --assess --verbose ./macos/MyApp.app
./macos/MyApp.app/: accepted
According to the docs I have read it should say something like: “source=Notarized Developer ID”, right?
I am running this on MacOS Mojave 10.14.5
What am I missing??
Could someone help me?
Thanks in advance
In case someone faces the same problem I will post the solution to this:
First of all you must staple .app file not the dmg. This means you must extract the binary and staple it
Also in order to check if application has been notarized, in
`System Preferences - Security and Privacy`
Option Allow apps downloaded from: must have Apple Store and identifier developers option checked
Hope this helps
Both the app and the dmg may be notarized and stapled, seperately, one after the other. Try doing that and the error should go away.
Short answer
It could be due to an RPATH referencing a path outside the App bundle. Removing this RPATH would resolve the issue.
Inspecting log files
You can find extra information about the rejection (after trying to launch the blocked app) in the Console.app. Note that you should open the Console.app, before trying to open your blocked app, otherwise not all messages may be logged. You should look for process XprotectService in the logs of your device (i.e. choose your device in the left side bar of the Console.app). If the RPATH is indeed the problem, you should find a record like this:
XprotectService: [com.apple.xprotect:xprotect] File /path/to/your/executable/or/library failed on rPathCmd /rpath/causing/the/problem (rpath resolved to: (path not found), bundleURL: /path/to/your/bundle.app)
Inspecting these log files may give you a key to solve other issues too.
Note that I received the following information from an Apple engineer:
Gatekeeper does not inform users via UI about the specifics of the
error, though it is in the logs for developers to look at. The
notarization process is purely about a detecting malicious software
and does not replicate Gatekeeper enforcement. You still need to get
software notarized and test with Gatekeeper.
We are looking to provide better tooling for developers in the future
to pre-flight some of these common errors.
Contact Apple
If you are not able to solve your issue with the above information, you may want to contact Apple itself using the Feedback Assistant. They do not respond very quickly (~1-2 weeks), but the answers are rather to the point.

Error when enabling auto login of macOS app using a helper

I'm trying to have my app auto launch on login following Tim's tutorial: http://blog.timschroeder.net/2012/07/03/the-launch-at-login-sandbox-project/
I followed the instructions to the letter but I'm getting an error when I re-login to my computer as follows:
Jan 10 12:55:01 pc61 com.apple.xpc.launchd[1] (com.myApp.macgap.helper[25725]): Could not resolve CFBundleIdentifier specified by service: -10814: com.myApp.macgap.helper
Jan 10 12:55:01 pc61 com.apple.xpc.launchd[1] (com.myApp.macgap.helper): Service only ran for 0 seconds. Pushing respawn out by 10 seconds.
To outline:
I have my main app called "myApp" (ID: com.myApp.macgap )
In that app I have a helper app with ID: com.myApp.macgap.helper
When you launch the main app and go to preferences, you have an option to enable auto login (to fit to the Apple compliance rules)
I log out of my computer, log back in and look at the console to see what's going on (that's how I get the code above)
Another point worth mentioning, is when I do "Show package content" on the app and double click the helper app, it does launch the main app...
It all comes down to how launchd and launchctl work, as already answered, the regular use case often can be solved by reinstalling the app and ensuring the app is inside the applications folder. But there's another case that #byb is talking about, when this happens on your development machine – this can be caused by invalid launchd configuration.
When you run SMLoginItemSetEnabled it registers your bundle identifier along with other information in launchd service. At some point later, when your app changes, gets cleaned, or something else happens to it, which gets picked up by launchd, launchd may disable that particular login item. Apparently, sometimes this doesn't go smoothly, and consecutive calls with SMLoginItemSetEnabled will not work as expected or the agent / helper app simply won't launch.
The first thing to try is simply changing the bundle identifier for your launcher. If this solves the issue, try figuring out what's wrong with the original. Run launchctl print-disabled "user/$(id -u)" to display disabled services and login item associations. If the output contains your troubling bundle identifier – you are in luck.
I didn't find a way of removing disabled services by name using launchctl and had to do it by manually editing configuration files. Because they system-owned, you won't be able to simply click and edit, instead launch Xcode as root and remove the necessary references.
sudo /Applications/Xcode.app/Contents/MacOS/Xcode "/private/var/db/com.apple.xpc.launchd/loginitems.$(id -u).plist"
sudo /Applications/Xcode.app/Contents/MacOS/Xcode "/private/var/db/com.apple.xpc.launchd/disabled.$(id -u).plist"
Restart, run launchctl print-disabled "user/$(id -u)" to confirm removed items are no longer in the list. Try SMLoginItemSetEnabled again, hopefully now it will work as expected.
I had the exact same problem just now, and while looking for a solution found this (unanswered) question.
At least in my case, this desired functionality of the worked fine when I copied the app (exported from Xcode as a dev-id signed .app) to a fresh OS X install/account without all my development stuff on it. Of course it must also be in /Applications, as stated in the tutorial referred to in the question.
I am not sure why this feature of the app did not work on my development machine. Perhaps the problem could be due to some form of conflict with all the other near-identical copies of my app I have on disk (I have an archive of different versions of the app, plus the copies Xcode stores itself), all with the same bundle id of course.
Hope this helps in one way or another!
I had the same problem, removing other copies of app except one in /Applications solved the problem for me. To remove .app files generated by Xcode you can run Product->Clean.
I was struggling with this for hours. I had many apps with auto login but a new one just did not want to work.
Strangely this worked on the development machine:
Build App as normal
Move it to Application directory
Clean Xcode (CMD+k)!!
Enable auto login in the app.
Logout Login
I accidentally noticed that the system started the app (it tries in every 10 sec) when I clean Xcode :)
I can't find the duplicate copy but did find you can remove the service:
In a terminal window:
launchctl remove com.annoying.service
As it was already stated if there are more then one copies of service bundle on the machine launchd cannot resolve which one must be started by bundle identifier.
What I would recommend to you is find all copies of your service and then remove not desired ones.
For this you need to run following Swift code (It works even in Swift Playground):
import Cocoa
let bundleId = "com.your.bundleId"
let paths = LSCopyApplicationURLsForBundleIdentifier(bundleId as CFString, nil)
print("Available service instances by bundle id: \(paths)")
In my case it produces:
Available service instances by bundle id:
Optional(Swift.Unmanaged<__ObjC.CFArray>(_value: <__NSArrayI 0x6000002234a0>(
file:///Applications/MyApp.app/Contents/Library/LoginItems/MyService.app/,
file:///Users/igor/Library/Developer/Xcode/Archives/2017-12-27/MyApp%2027-12-2017,%2016.06.xcarchive/Products/Applications/MyService.app/
)
))
So I easely identified copy to be removed:
file:///Users/igor/Library/Developer/Xcode/Archives/2017-12-27/MyApp%2027-12-2017,%2016.06.xcarchive/Products/Applications/MyService.app/
Hope it help.
Assuming that you followed Tim Schroeder's recipe at: http://blog.timschroeder.net/2012/07/03/the-launch-at-login-sandbox-project/ :
What actually ended up working for me, was, in Xcode, to change my main project's build number from 1 to 2. I also tried a build number of 1000 and that worked fine as well.
In Xcode, select your main project target. Then, select the 'General' tab. If you see your Build is set to 1, change it to 2 and then rebuild, redeploy and see if that resolves the issue for you.
This was probably one of the screwiest bugs I have run into, in a while.

Code Signing issue for Project with Multiple Targets

I'm trying to get my application, which does not appear in the Dock, to have an option to launch at login. This is tricky, and involves creating a second, helper application which you add as a startup item. This helper app is only responsible for launching the main app and then exiting.
I've followed the instructions here and here and it works like a charm - the problem is, of course, code signing. I have two targets; the helper app target is copied to the Contents/Library/LoginItems subdirectory of the main bundle at compile time. Each bundle has its own bundle identifier and own deployment provisioning profile, but when I validate my archive for the app store, I get the following error:
Invalid provisioning profile. The provisioning profile included in the bundle BUNDLE NAME [BUNDLE NAME.app] is invalid. For more information, visit the Mac OS Developer Portal.
If I remove the helper bundle from my main target, there's no problem. It looks like the presence of another provisioning profile is setting off the error.
How can I include two signed bundles and pass the validation?
I was finally able to resolve this problem by using codesign on a coworker's computer (there must have been something wrong with my Keychain) and deleting the embedded.provisionprofile file from the helper app by adding the following run script:
if [ -f "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/embedded.provisionprofile" ];
then
rm "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/embedded.provisionprofile"
echo "Removed embedded provisioning profile."
else
echo "No profile found"
fi
You should use the same Mac App Store Production Certificate to sign both the helper app and the main application. I haven't tried this in Xcode — we have a helper app that's a bundle resource, but our code signing is a command line script. We didn't have any problems with the app store system.
I'm not sure why you're ending up with a provisioning profile in the built product, and I don't think this is required for app store submission. You can try using codesign manually:
codesign -f -s "3rd Party Mac Developer Application: My Company" \
-i "com.mycompany.loginitem" \
--entitlements path/to/loginitem.entitlements" \
path/to/appname.app/Contents/Library/LoginItems/loginitem.app
codesign -f -s "3rd Party Mac Developer Application: My Company" \
-i "com.mycompany.appname" \
--entitlements path/to/app.entitlements" \
path/to/appname.app
I had the same problem. Instead of removing embedded.provisionprofile from the helper app I've just disabled provisioning (Provision profile: None) leaving code signing identify and entitlements in place. Submitted my app for review without any issues.

How do I symbolicate a crash report of a Mac OS X app that a user emailed to me?

I am working on an app that I have sent to a few beta testers. Within just a few minutes of launching the app a user got a crash. When the window poped up saying the app had crashed he copied all of the text in the details section and emailed it to me. I have saved the text into a plain text file and given it the .crash extension which causes it to be opened by console like a regular crash report so I think I have the extension right (but maybe not).
The version I sent out was built by Xcode with the Archive option so Xcode knows where the app and .dSYM are.
I know that with iPhone apps you can drag a crash report to the organizer and Xcode will symbolicate it for you. I can not find anywhere that will take a Mac crash report.
I have looked at atos but it talks about memory locations including the location the app was running at and I don't see that information listed in the report I have. Looking at the raw crash report it looks like a view controller was released early but I can't really tell if that was the cause or a symptom.
My real question is; is there a way to have Xcode symbolicate the report or a tool that I can just hand over the .dSYM file, app, and report and get back a symbolicated report?
I've looked all over Google but everything I find (other than the previously mentioned man pages for atos) is about symbolicating iPhone reports, not Mac OS X ones.
Or as in answer https://stackoverflow.com/a/18354072/317461
Put your release build and your .dSYM file in the same directory and open terminal
$cd directory
$lldb MyApp.app
(lldb) image lookup -v --address 0x00085f3c
We had the same problem with our app and I was symbolicating the crash reports manually line by line with atos.
I now tweaked Apple's symbolicate script such that it works with Mac apps and crash reports from PLCrashReporter.
https://github.com/lksnmnn/Symbolicate-CrashReports
How to use it:
Make sure you have all of the following files on your computer:
The crash report: report.crash
The dSYM file of your app: MyApp.dSYM
The executable / app folder of your app: MyApp.app
The improved symbolicate script: symbolicatecrash
Now go in the command line (Terminal) and do the following:
# set the developer directory
export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"
# Now run the script
/Path/To/symbolicatecrash /Path/To/report.crash > /Path/To/readable_report.crash
# Use -v for verbose logging.
The script will find your dSYM and your executable and symbolicates as much as it cans. You will now find your symbolicated report in the stated output file readable_report.crash
Build settings:
For proper reports and symbols, set your build settings to this:
Strip Debug Symbols During Copy: Yes
Strip Style: All Symbols
Strip Linked Product: Yes
Edit: Improved the answer such that it aligns with the Stack Overflow answer policy.
You can use GDB for Symbolication, Put your release build and your .dSYM file in the same directory
open terminal
$ cd directory
$ gdb MyApp.app
(gdb) info line *0x00085f3c