I'm also interested in this, I'd like to be able to detect music playing and pause it for a task, then resume it after. Would you mind sharing how you simulated the play/pause media key?
Post
Replies
Boosts
Views
Activity
Hola Quinn,
Thanks for the terrific reply.
It’s hard to say without more context. Most notably, why are you escalating privileges in the first place?
One of the many things App Wrapper does as part of it's process is to ensure correct permissions on the files within the application bundle, but it fails when the customer doesn't have permission to alter to the permissions of a file.
Another task it does it does is to strip ACLs and Xattrs, sometimes customers have screwed up ACLs that prevent the ACLs from being removed, and/or prevent xattrs from being removed.
In this case, these actions can be done via API or via system commandline tools.
No. The point of SMJobBless is that you can avoid the installer package.
If you already have an installer package in play, there’s no need for SMJobBless. The package can install a launchd daemon directly.
That's good to know, as I don't use an installer package for my apps, and it means I misunderstood some aspects.
That depends on how you look at it. The problem with AEWP is that there’s no secure link between the code asking to elevate privileges and the code that’s run with elevated privileges. SMJobBless fixes that.
I kinda guessed that when I saw how complicated it was to interact with the helper, v.s. just using AEWP. I don't know if it's really that necessary for my current needs. However it looks like it might be the only recommended choice.
However, its design, where the privileged helper tool retains its privileges, certainly engenders some security risks. You must write that code securely.
This scares the crap outa me, as it makes me afraid that I do something wrong, I put my customers at risk, I guess you could say that with all the mechanisms we've discussed, but this feels like a big red flag.
Thanks Quinn, you've given me some more information to ponder. I still currently don't know which direction to take, but hopefully after some percolation, I'll make be able to make a better decision.
Sam Rowlands
p.s. I guess you've seen the appreciation thread happening on Twitter :)
I have been able to get SKReceiptRefreshRequest working, but it's a PITA because it is asynchronous, so it can pop-in while the user is working in the app, which means you can't just terminate any more and must think of how to handle the app's flow for the App Store DRM.
Thank you Quinn,
The reason this creates some complication is that I and several others are used to wrapping for App Store Submission, and before we "Submit for Review", move the application to the Applications folder and launch it, just to give it a final check (including the receipt).
I've been trying to see if I can test the receipt verification code when using "Apple Development" but it doesn't work, I think there is a failure somewhere with testing receipts in general as I see others having problems testing receipts at the moment.
As for TestFlight, as a Mac only developer, I've never used it before and therefore I need to learn how to interact with it. However I'd feel more comfortable being able to test our apps locally before submitting it to a testing service, especially things like the receipt verification.
let infoCF = try secCall { SecCodeCopySigningInformation(meStatic, [], $0) }
let info = infoCF as NSDictionary
let entitlements = info[kSecCodeInfoEntitlementsDict] as? NSDictionary
Thank you for this code snippet. I have been using the same API with SecStaticCode to read the application after it has been signed (a sort of code sign diagnostics tool), I am sorry to have to ask, but I don't currently see how this can tell me if the macOS knows this is signed with a profile or not as (in my tests) this API returns the apps Entitlements regardless.
I've looked through "SecCode.h" at the constants listed under "SecCodeCopySigningInformation" to see if there's a key, but it is not obvious to me.
However if the rule of thumb is that "Apple Distribution cert + provision profile + certain entitlements" == "can't be run locally", then I guess I don't really need to know at this point.
Thank you for taking your time to assist me. You must be getting tired of me asking questions and sometimes clearly not understanding things.
Addendum: So for this time around I was able to actually figure out the crashing!
ProvisionedDevices - When using the "Apple Developer" certificate and provision profile, the machine being used for testing must be registered at Apple and included in the Provision Profile.
Am still not able to test with a Apple Distribution certificate and matching profile, it also does not include a ProvisionedDevices section.
I'll keep at it, nice to finally get somewhere.
Hi Quinn,
It's been a while and I am sorry for the late response, I've had other things and I've also been trying to discuss this with other developers, it seems like it is something that I am doing wrong because no-one else appears to be running in to it :(
So in summary, adding a Provisioning Profile to the application doesn't cause a problem, until the keys from the Provisioning Profile are added to the applications entitlements, keys such as "com.apple.application-identifier" or "com.apple.developer.team-identifier".
I have tested it with both the "Apple Distribution" and "Apple Development" certificates.
I have also removed the Provisioning Profile from the application and I of course get the same crash, so my guess is that I'm not inserting it correctly into the application. It is added to the root of the "Contents" subfolder of the application bundle and is called "embedded.provisionprofile", which is done BEFORE any code signing.
So this raises two questions.
Do I need to provide some extra information at signing time to notify code sign to use the profile?
Is there a way that the Security framework can tell me that it knows the profile is there, some sort of validation?
Thank you Quinn for your help.
On a hunch I tried CFEqual to compare the two certs and it appears to do what I want... Sorry that I took up your time, if only I tied this earlier.
The profile was created using Apple's web portal https://developer.apple.com/account/resources/profiles/list
If you'd like I can make the profile and the application available to download, it is signed with my App Store submission cert, which is the cert specified in the profile.
One final thing, clutching at staws, the permissions of the executables are all 755, while the provisionprofile is 666, I guess it should be 644.
Tested this (the profiles permissions are 644), I also ensured that all the ACLs and xattrs are being stripped from the provisionprofile. However it made no change :(
Morning Quinn,
Are you building your Info.plist and .entitlements file with Apple tools? Modern systems apply additional constraints on security-sensitive XML files. See Ensure Properly Formatted Entitlements for more on this.
I am not building either the info.plist or the entitlements file using Apple's tools.
I am using [NSPropertyListSerialization dataWithPropertyList:format:options:error:] to create a NSData object of format kCFPropertyListXMLFormat_v1_0 which is then written to the file using a stream.
plutil -lint ~/mainEntitlementsAppStore.entitlements
~/mainEntitlementsAppStore.entitlements: OK
codesign -d --entitlements :- ~/Aqua\ Swatch.app
Executable= ~/Aqua Swatch.app/Contents/MacOS/Aqua Swatch
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.application-identifier</key>
<string>QXAFMEPH6X.com.ohanaware.aquaSwatch</string>
<key>com.apple.developer.team-identifier</key>
<string>QXAFMEPH6X</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>QXAFMEPH6X.com.ohanaware.aquaSwatch</string>
</array>
</dict>
</plist>
If the mainEntitlements only consists of com.apple.security keys, the application launches.
Once "com.apple.application-identifier", "com.apple.developer.team-identifier" or "keychain-access-groups" is added to the entitlements the application crashes on launch.
Below is the console information from just this moment.
default 10:18:19.639377+0800 amfid /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch signature not valid: -67671
default 10:18:19.639463+0800 kernel mac_vnode_check_signature: /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch: code signature validation failed fatally: When validating /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch:
Code has restricted entitlements, but the validation of its code signature failed.
Unsatisfied Entitlements:
default 10:18:19.639513+0800 kernel proc 32652: load code signature error 4 for file "Aqua Swatch"
default 10:18:19.640376+0800 kernel ASP: Security policy would not allow process: 32652, /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch
default 10:18:19.640408+0800 kernel Aqua Swatch[32652] Corpse allowed 1 of 5
default 10:18:19.647641+0800 ReportCrash Parsing corpse data for process Aqua Swatch [pid 32652]
error 10:18:19.704941+0800 CoreServicesUIAgent handle LS launch error: {\n Action = oapp;\n AppMimimumSystemVersion = "10.11";\n AppPath = "/Applications/Aqua Swatch.app";\n ErrorCode = "-10826";\n}
default 10:18:19.808839+0800 *** Non-fatal error enumerating at <private>, continuing: Error Domain=NSCocoaErrorDomain Code=260 "The file “PlugIns” couldn’t be opened because there is no such file." UserInfo={NSURL=PlugIns/ -- file:///Applications/Aqua%20Swatch.app/Contents/, NSFilePath=/Applications/Aqua Swatch.app/Contents/PlugIns, NSUnderlyingError=0x7f9dfb91f9e0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
default 10:18:19.969116+0800 *** Non-fatal error enumerating at <private>, continuing: Error Domain=NSCocoaErrorDomain Code=260 "The file “PlugIns” couldn’t be opened because there is no such file." UserInfo={NSURL=PlugIns/ -- file:///Applications/Aqua%20Swatch.app/Contents/, NSFilePath=/Applications/Aqua Swatch.app/Contents/PlugIns, NSUnderlyingError=0x7f9dfb843d80 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
default 10:18:19.998976+0800 ReportCrash Saved crash report for Aqua Swatch[32652] version ??? to Aqua Swatch_2021-10-26-101819_Mariposa.crash
default 10:18:20.008882+0800 analyticsd Received event: com.apple.stability.crash {"appVersion":"???","exceptionType":13,"incidentID":"1B2F176A-1FCA-47CC-AE21-9A4EA88E0C81","logwritten":1,"process":"Aqua Swatch","responsibleApp":"Aqua Swatch"}
default 10:18:20.008759+0800 ReportCrash Sending event: com.apple.stability.crash {"appVersion":"???","exceptionType":13,"incidentID":"1B2F176A-1FCA-47CC-AE21-9A4EA88E0C81","logwritten":1,"process":"Aqua Swatch","responsibleApp":"Aqua Swatch"}
default 10:18:20.014245+0800 analyticsd Aggregated. Transform: StabilityCrashNumerator3WithIncidentID Dirty: 1 Event: com.apple.stability.crash {"appVersion":"???","exceptionType":13,"incidentID":"1B2F176A-1FCA-47CC-AE21-9A4EA88E0C81","logwritten":1,"process":"Aqua Swatch","responsibleApp":"Aqua Swatch","timestamp":1635214700008705}
default 10:18:20.014302+0800 analyticsd Aggregated. Transform: StabilityCrashNumerator3 Dirty: 1 Event: com.apple.stability.crash {"appVersion":"???","exceptionType":13,"incidentID":"1B2F176A-1FCA-47CC-AE21-9A4EA88E0C81","logwritten":1,"process":"Aqua Swatch","responsibleApp":"Aqua Swatch","timestamp":1635214700008705}
default 10:18:20.014359+0800 analyticsd Aggregated. Transform: StabilityCrashNumerator3WithBundleVersion Dirty: 1 Event: com.apple.stability.crash {"appVersion":"???","exceptionType":13,"incidentID":"1B2F176A-1FCA-47CC-AE21-9A4EA88E0C81","logwritten":1,"process":"Aqua Swatch","responsibleApp":"Aqua Swatch","timestamp":1635214700008705}
% security error -67671
Error: 0xFFFEF7A9 -67671 An internal error has occurred.
If I remove these keys, and rewrap the application, it launches with no error. "com.apple.application-identifier", "com.apple.developer.team-identifier" and "keychain-access-groups".
One final thing, clutching at staws, the permissions of the executables are all 755, while the provisionprofile is 666, I guess it should be 644.
Thank you for your patience and willingness to assist me.
Hi Quinn,
Thank you for trying to help me.
There is something I must have fundamentally wrong. When trying to launch the application, console reports a load of information about the crash, but I can only see two things that appear to give any indication.
mac_vnode_check_signature: /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch: code signature validation failed fatally: When validating /Applications/Aqua Swatch.app/Contents/MacOS/Aqua Swatch:
Code has restricted entitlements, but the validation of its code signature failed.
Unsatisfied Entitlements:
But no entitlements are listed.
Console also lists the error "signature not valid: -67030". To which I can find no public information on.
Entitlements extracted from the application's code signature (via codesign -d --entitlements :- )
<dict>
<key>com.apple.application-identifier</key>
<string>QXAFMEPH6X.com.ohanaware.aquaSwatch</string>
<key>com.apple.developer.team-identifier</key>
<string>QXAFMEPH6X</string>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array>
<string>QXAFMEPH6X.com.ohanaware.aquaSwatch</string>
</array>
</dict>
Entitlements extracted from /Contents/embedded.provisionprofile (via security cms -D -i )
<key>Entitlements</key>
<dict>
<key>com.apple.application-identifier</key>
<string>QXAFMEPH6X.com.ohanaware.aquaSwatch</string>
<key>keychain-access-groups</key>
<array>
<string>QXAFMEPH6X.*</string>
</array>
<key>com.apple.developer.team-identifier</key>
<string>QXAFMEPH6X</string>
</dict>
The profile has weird spacing when listing the entitlements.
If I remove "keychain-access-groups", it still crashes. It only stops crashing when I have removed "com.apple.application-identifier" and "com.apple.developer.team-identifier" from the code sign entitlements (so the code sign entitlements only contain the com.apple.security elements).
Is there anything else I can check?
Does the profile need to be installed somewhere on the machine as well as within the application?
Hola Quinn,
Thank you so much for pointing me tin the right direction.
Question 2, was poorly worded as I was asking if the various services would accept a locally made provision profile, which is not signed by Apple. I don't think they would to be honest.
Question 3, fantastic. I have a lot of work ahead of me, but I am pleased there is a way that I can update provision profiles from within a 3rd Party application.
Once again, thank you man. You are a real help.
@Quinn As always, thank you for your prompt and helpful response. I have forwarded the information on to the customer. I'll swap out my code to use this to validate customer entered in user names and passwords in a future update.
@Quinn
It works from a new user account on the same machine.
The customer's main user account was moved (using the options in macOS) to an external drive. The customer states that it was working earlier in the year, only recently has altool started spewing errors.
We have tried different locations for the source files (what altool submits to Apple), including "/Users/Shared" so that the source files are on the same volume as altool. However altool still reported this error, which leads me to believe that something internal to altool (prefs, cache or other) is attempting to access a location within the user folder, to which it phreaks out because it's not on the same volume.
Thanks for taking the time to assist, I hope that this information maybe useful to others.
Sam Rowlands
I haven't heard from the customer for a while, so I don't know the outcome (yet).
However I wanted to say Thank you for helping out.
Sam Rowlands