Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Receipt validation from Mac App Store fails on macOS 15 beta #16031

Closed
Bettarg opened this issue Jun 15, 2024 · 11 comments · Fixed by #16230
Closed

Receipt validation from Mac App Store fails on macOS 15 beta #16031

Bettarg opened this issue Jun 15, 2024 · 11 comments · Fixed by #16230
Assignees
Labels
appstore Mac App Store cyberduck Cyberduck mountainduck Mountain Duck thirdparty Issue caused by third party

Comments

@Bettarg
Copy link

Bettarg commented Jun 15, 2024

This ticket system is to report bugs and feature requests. For support, visit the help page first.

Very simple , the App crash on Startup. In Detail, MacOS claimed the App is corrupted. Reinstall does not help.

@dkocher dkocher self-assigned this Jun 15, 2024
@dkocher
Copy link
Contributor

dkocher commented Jun 15, 2024

I cannot reproduce on 15.0 beta, 24A5264n.

@dkocher dkocher closed this as completed Jun 15, 2024
@matthewberryman
Copy link

matthewberryman commented Jun 20, 2024

To reproduce, you need the version from the App Store:
Screenshot 2024-06-20 at 10 25 55

The version from outside the App Store doesn't have this issue.

Edit: it's to do with MAC address rotation, see my later comment

@matthewberryman
Copy link

Looking through the logs:

2024-06-17 07:40:31,446 [main] ERROR ch.cyberduck.core.aquaticprime.ReceiptVerifier - Failed verification. Hash with GUID redacted_hex_string does not match hash in receipt
2024-06-17 14:00:48,063 [main] ERROR ch.cyberduck.core.aquaticprime.ReceiptVerifier - Failed verification. Hash with GUID different_redacted_hex_string not match hash in receipt

@matthewberryman
Copy link

matthewberryman commented Jun 20, 2024

matthew@MacBookPro /A/C/C/MacOS> codesign -vvv --deep --strict ./Cyberduck
--prepared:/Applications/Cyberduck.app/Contents/PlugIns/Runtime.jre
--validated:/Applications/Cyberduck.app/Contents/PlugIns/Runtime.jre
--prepared:/Applications/Cyberduck.app/Contents/Frameworks/librococoa.dylib
--validated:/Applications/Cyberduck.app/Contents/Frameworks/librococoa.dylib
--prepared:/Applications/Cyberduck.app/Contents/Frameworks/libjdns_sd.dylib
--validated:/Applications/Cyberduck.app/Contents/Frameworks/libjdns_sd.dylib
--prepared:/Applications/Cyberduck.app/Contents/Library/Spotlight/Cyberduck Spotlight Importer.mdimporter
--prepared:/Applications/Cyberduck.app/Contents/Frameworks/libjnidispatch.dylib
--validated:/Applications/Cyberduck.app/Contents/Frameworks/libjnidispatch.dylib
--prepared:/Applications/Cyberduck.app/Contents/Frameworks/libcore.dylib
--validated:/Applications/Cyberduck.app/Contents/Frameworks/libcore.dylib
--prepared:/Applications/Cyberduck.app/Contents/Frameworks/JavaNativeFoundation.framework/Versions/Current/.
--validated:/Applications/Cyberduck.app/Contents/Library/Spotlight/Cyberduck Spotlight Importer.mdimporter
--validated:/Applications/Cyberduck.app/Contents/Frameworks/JavaNativeFoundation.framework/Versions/Current/.
./Cyberduck: valid on disk
./Cyberduck: satisfies its Designated Requirement
matthew@MacBookPro /A/C/C/MacOS [1]> spctl -a -vv ./Cyberduck
./Cyberduck: accepted
source=Mac App Store
origin=Apple Mac OS Application Signing

@matthewberryman
Copy link

matthewberryman commented Jun 20, 2024

So starting it from the CLI, I get an exit status of 173,

private static final int APPSTORE_VALIDATION_FAILURE = 173;

which at the GUI level obviously flags it as "corrupt"

The error message I was seeing in the logs is coming from here:

log.error(String.format("Failed verification. Hash with GUID %s does not match hash in receipt", hex));

Here you are using the MAC address:

final byte[] mac = en0.getHardwareAddress();

But that won't work for macOS 15, since it randomises the MAC address:
https://www.macrumors.com/2024/06/10/ios-18-rotate-wifi-address/

(Note: this feature is turned off for my workplace wifi network, but maybe macOS 15 uses a different MAC address per wifi network, or has changed it on upgrade, I will explore when I get home)

Maybe the hardware UUID can be used instead, but that introduces a couple of issues:

  1. Migration of users from MAC address to hardware UUID.
  2. Logic board replacements / change of computer (although that would have been an issue with the MAC based way, I'm guessing).

@dkocher dkocher reopened this Jun 20, 2024
@dkocher dkocher added appstore Mac App Store thirdparty Issue caused by third party labels Jun 20, 2024
@dkocher
Copy link
Contributor

dkocher commented Jun 20, 2024

@matthewberryman Thanks for looking into this in detail. I assume this will break many applications as the sample code 1 by Apple uses en0 interface as well for validation. I have filed FB13979956 as I don't know how the implementation would need to be changed.

There is some documentation in 2 not yet updated for macOS 15.

Footnotes

  1. https://developer.apple.com/documentation/appstorereceipts/validating_receipts_on_the_device#3744656

  2. https://support.apple.com/guide/security/wi-fi-privacy-secb9cb3140c/web

@dkocher dkocher changed the title Wont start under MacOS 15 Beta 1 Receipt validation from Mac App Store fails on macOS 15 beta Jun 20, 2024
@matthewberryman
Copy link

@dkocher Ah, the <sarcasm>joy</sarcasm> of being an Apple developer. I'm really curious as to what Apple come back to on FB13979956, as you point out the docs themselves use the MAC address, which is now no longer fixed...
Further up the on-device validation page there's a note suggesting the use of AppTransaction, but:

  1. Only for macOS 13+
  2. Only in swift as far as I can see, so one would have to write a wrapper class in swift, then wrap that up in objective-c, then use JNI to get from there to Java (!).
    There must be an easier path...

@matthewberryman
Copy link

matthewberryman commented Jun 21, 2024

So, although I don't have the MAC address randomisation turned on for my home wifi, I do get a different MAC address.

Forcing this line to if (true) { when building from source (to force the behaviour we want to see), when the app is opened, gives a window with the following message

exit(173) Not Available

The exit(173) API is no longer available. 
You can use Transaction.all or AppTransaction.shared to verify in‑app purchases instead.

before a subsequent window with the message:

“/Users/matthew/code/cyberduck/osx/target/Cyberduck.app” is damaged and can’t be opened. 
Delete “/Users/matthew/code/cyberduck/osx/target/Cyberduck.app” and download it again from the App Store.

There's a swift example here although then you'd need to introduce swift code and expose it by @objc public class... and @objc public func... and then drop in a .h file to expose the interface to obj-c and then do JNI and then Java. Introducing swift would bump up the minimum macOS required from 10.7 to 10.9.

@zeemyself
Copy link

Screenshot 2024-06-27 at 9 42 06 PM

Also affect Mountain Duck downloaded from Mac App Store

@devinbaeten
Copy link

+1 for seeing this issue with mountain duck when downloaded from App Store:
SCR-20240813-oqxf

@dkocher dkocher added mountainduck Mountain Duck cyberduck Cyberduck labels Aug 14, 2024
@dkocher dkocher linked a pull request Aug 14, 2024 that will close this issue
@xhruso00
Copy link

I have just tested Apple sample code and it gives correct "legacy" mac address (works out of the box). The issue is the implementation of en0.getHardwareAddress(); which gives the new randomized mac address.

ioreg on Sequoia gives "IOMACAddress" = <9e36f934XXXX> for AppleBCMWLANSkywalkInterface and "IOMACAddress" = <bcd0744fXXXX> for IOSkywalkLegacyEthernet. This used to be the same value on Sonoma.

Here is the output on macOS Sequoia

MacBook-Pro ~ % ioreg -rl -c AppleBCMWLANSkywalkInterface
+-o AppleBCMWLANSkywalkInterface  <class IOUserNetworkWLAN, id 0x100000e93, registered, matched, active, busy 0 (71 ms), retain 25>
  | {
  |   "kOSBundleDextUniqueIdentifier" = <bf4014f126adca6158d1b91a459f6ba06bff27b96c102b1c09a372baad64d15e>
  |   "IO80211BSSID" = <c0f6ec1a4ad4>
  |   "IO80211RSNDone" = Yes
  |   "IOInterfaceType" = 6
  |   "IO80211ChannelBandwidth" = 80
  |   "IOUserServerPreserveUserspaceReboot" = Yes
  |   "IOUserServerOneProcess" = Yes
  |   "IO80211CountryCode" = "MY"
  |   "mDNS_Keepalive" = Yes
  |   "IO80211SSID" = "TIME_MH"
  |   "IO80211InterfaceRole" = "Infrastructure"
  |   "IOPropertyMatch" = {"IOUserClass"="AppleBCMWLANCore"}
  |   "IOServiceDEXTEntitlements" = "com.apple.developer.driverkit.family.networking"
  |   "IOUserClasses" = ("AppleBCMWLANSkywalkInterface","AppleBCMWLANInfraProtocol","IO80211InfraProtocol","IO80211InfraInterface","IO80211SkywalkInterface","IOUserNetworkWLAN","IOUserNetworkEthernet","IOService","OSObject")
  |   "IOInterfaceNamePrefix" = "en"
  |   "IOUserServerCDHash" = "8f350ddbe6b9c5eb2b9b998fb2dc6452673c1207"
  |   "built-in" = <00>
  |   "IOPersonalityPublisher" = "com.apple.DriverKit-AppleBCMWLAN"
  |   "IOPowerManagement" = {"DevicePowerState"=2,"CurrentPowerState"=2,"CapabilityFlags"=2,"MaxPowerState"=2}
  |   "mDNS_KEY" = "2009-07-30"
  |   "IO80211ChannelFrequency" = 5180
  |   "IOUserServerName" = "com.apple.bcmwlan"
  |   "IOMACAddress" = <9e36f934XXXX>
  |   "IO80211HardwareVersion" = "vendorid: 0x14e4 deviceid: 0x4433 radiorev: 0xc50dd chipnum: 0x4387 chiprev: 0x7 corerev: 0x55 boardid: 0x93c boardvendor: 0x14e4 boardrev: 0x1200 driverrev: 0x0 ucoderev: 0x5c60064 bus: 0x0 "
  |   "IOMatchedPersonality" = {"IOClass"="IOUserNetworkWLAN","CFBundleIdentifier"="com.apple.DriverKit-AppleBCMWLAN","IOProviderClass"="IOUserService","IOPropertyMatch"={"IOUserClass"="AppleBCMWLANCore"},"IO80211InterfaceRole"="Infrastru$
  |   "IO80211Channel" = 36
  |   "CFBundleIdentifier" = "com.apple.DriverKit-AppleBCMWLAN"
  |   "IOInterfaceName" = "en0"
  |   "IO80211APIUserClientProperties" = {"IOClass"="IOUserUserClient","IOUserClass"="IO80211APIUserClient"}
  |   "IOProviderClass" = "IOUserService"
  |   "IOUserClass" = "AppleBCMWLANSkywalkInterface"
  |   "IOPMResetPowerStateOnWake" = Yes
  |   "IO80211DriverVersion" = "wl0: Jul 26 2024 20:03:40 version 20.10.1123.2.8.7.186 FWID 01-94146b8e"
  |   "IOInterfaceUnit" = 0
  |   "CFBundleIdentifierKernel" = "com.apple.iokit.IOSkywalkFamily"
  |   "IOClass" = "IOUserNetworkWLAN"
  |   "IO80211Band" = "5 GHz"
  |   "IO80211Locale" = "Unknown"
  |   "IOMatchCategory" = "IODefaultMatchCategory"
  |   "IOProbeScore" = 0
  | }
  | 
  +-o IOSkywalkLegacyEthernet  <class IOSkywalkLegacyEthernet, id 0x100000f10, !registered, !matched, active, busy 0 (1 ms), retain 8>
  | | {
  | |   "IOClass" = "IOSkywalkLegacyEthernet"
  | |   "CFBundleIdentifier" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOProviderClass" = "IOSkywalkEthernetInterface"
  | |   "IOPacketFilters" = {"IONetworkFilterGroup"=275,"IOEthernetWakeOnLANFilterGroup"=0}
  | |   "IOMACAddress" = <bcd0744fXXXX>
  | |   "IOLinkSpeed" = 0
  | |   "IOProbeScore" = 0
  | |   "IOMatchedAtBoot" = Yes
  | |   "AVBControllerState" = 1
  | |   "IOMatchCategory" = "IOSkywalkLegacyEthernet"
  | |   "IOSelectedMedium" = ""
  | |   "IOClassNameOverride" = "IO80211Controller"
  | |   "IOPersonalityPublisher" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOFeatures" = 0
  | |   "CFBundleIdentifierKernel" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOLinkStatus" = 3
  | |   "IOMaxPacketSize" = 1518
  | |   "IOActiveMedium" = ""
  | |   "IOMinPacketSize" = 64
  | | }
  | | 
  | +-o en0  <class IOSkywalkLegacyEthernetInterface, id 0x100000f12, registered, matched, active, busy 0 (1 ms), retain 13>
  |   | {
  |   |   "IOLocation" = ""
  |   |   "IORequiredPacketFilters" = {"IONetworkFilterGroup"=3,"IOEthernetWakeOnLANFilterGroup"=0}
  |   |   "IOLinkActiveCount" = 0
  |   |   "BSD Name" = "en0"
  |   |   "IOMaxTransferUnit" = 1500
  |   |   "IOInterfaceType" = 6
  |   |   "IOInterfaceFlags" = 2082
  |   |   "IOMediaAddressLength" = 6
  |   |   "IOInterfaceState" = 3
  |   |   "IOMediaHeaderLength" = 14
  |   |   "IOActivePacketFilters" = {"IONetworkFilterGroup"=0,"IOEthernetWakeOnLANFilterGroup"=0}
  |   |   "IOInterfaceExtraFlags" = 0
  |   |   "IOPrimaryInterface" = Yes
  |   |   "IOInterfaceUnit" = 0
  |   |   "IOInterfaceNamePrefix" = "en"
  |   |   "IOBuiltin" = Yes
  |   |   "IONetworkData" = {"IONetworkStatsKey"={"Size"=20,"Data"=<0000000000000000000000000000000000000000>,"Access Types"=9},"IOEthernetStatsKey"={"Size"=216,"Data"=<000000000000000000000000000000000000000000000000000000000000000000000$
  |   | }
  |   | 

Here is the output of ioreg on Sonoma

MacBook-Pro-M1 ~ % ioreg -rl -c AppleBCMWLANSkywalkInterface
+-o AppleBCMWLANSkywalkInterface  <class AppleBCMWLANSkywalkInterface, id 0x100000a7f, registered, matched, active, busy 0 (1115 $
  | {
  |   "mDNS_KEY" = "2009-07-30"
  |   "mDNS_Keepalive" = Yes
  |   "IO80211Channel" = 36
  |   "IO80211Band" = "5 GHz"
  |   "IO80211BSSID" = <000000000000>
  |   "IO80211InterfaceRole" = "Infrastructure"
  |   "IO80211ChannelBandwidth" = 80
  |   "IO80211SSID" = ""
  |   "IOPowerManagement" = {"ChildrenPowerState"=1,"DevicePowerState"=1,"CurrentPowerState"=1,"CapabilityFlags"=32770,"MaxPowerS$
  |   "built-in" = <00>
  |   "IO80211DriverVersion" = "wl0: May 13 2024 23:59:32 version 20.103.15.0.8.7.175 FWID 01-fd39ee3a"
  |   "IOInterfaceName" = "en0"
  |   "IOInterfaceUnit" = 0
  |   "IO80211Locale" = "ETSI"
  |   "IOMACAddress" = <bcd0744fXXXX>
  |   "IOInterfaceType" = 6
  |   "IOPMResetPowerStateOnWake" = Yes
  |   "IO80211RSNDone" = Yes
  |   "IO80211CountryCode" = "MY"
  |   "IO80211ChannelFrequency" = 5180
  |   "IO80211HardwareVersion" = "vendorid: 0x14e4 deviceid: 0x4433 radiorev: 0xc50dd chipnum: 0x4387 chiprev: 0x7 corerev: 0x55 $
  |   "IOInterfaceNamePrefix" = "en"
  | }
  | 
  +-o IOSkywalkLegacyEthernet  <class IOSkywalkLegacyEthernet, id 0x100000a8c, !registered, !matched, active, busy 0 (0 ms), reta$
  | | {
  | |   "IOClass" = "IOSkywalkLegacyEthernet"
  | |   "CFBundleIdentifier" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOProviderClass" = "IOSkywalkEthernetInterface"
  | |   "IOPacketFilters" = {"IONetworkFilterGroup"=275,"IOEthernetWakeOnLANFilterGroup"=0}
  | |   "IOMACAddress" = <bcd0744fXXXX>
  | |   "IOLinkSpeed" = 0
  | |   "IOProbeScore" = 0
  | |   "IOMatchedAtBoot" = Yes
  | |   "AVBControllerState" = 1
  | |   "IOMatchCategory" = "IOSkywalkLegacyEthernet"
  | |   "IOSelectedMedium" = ""
  | |   "IOClassNameOverride" = "IO80211Controller"
  | |   "IOPersonalityPublisher" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOFeatures" = 0
  | |   "CFBundleIdentifierKernel" = "com.apple.iokit.IOSkywalkFamily"
  | |   "IOLinkStatus" = 3
  | |   "IOMaxPacketSize" = 1518
  | |   "IOActiveMedium" = ""
  | |   "IOMinPacketSize" = 64
  | | }
  | | 
  | +-o en0  <class IOSkywalkLegacyEthernetInterface, id 0x100000a8e, registered, matched, active, busy 0 (0 ms), retain 12>
  |   | {
  |   |   "IOLocation" = ""
  |   |   "IORequiredPacketFilters" = {"IONetworkFilterGroup"=3,"IOEthernetWakeOnLANFilterGroup"=0}
  |   |   "BSD Name" = "en0"
  |   |   "IOMaxTransferUnit" = 1500
  |   |   "IOInterfaceFlags" = 2082
  |   |   "IOInterfaceType" = 6
  |   |   "IOMediaAddressLength" = 6
  |   |   "IOInterfaceState" = 3
  |   |   "IOMediaHeaderLength" = 14
  |   |   "IOActivePacketFilters" = {"IONetworkFilterGroup"=0,"IOEthernetWakeOnLANFilterGroup"=0}
  |   |   "IOInterfaceExtraFlags" = 0
  |   |   "IOPrimaryInterface" = Yes
  |   |   "IOInterfaceUnit" = 0
  |   |   "IOInterfaceNamePrefix" = "en"
  |   |   "IOBuiltin" = Yes
  |   |   "IONetworkData" = {"IONetworkStatsKey"={"Size"=20,"Data"=<0000000000000000000000000000000000000000>,"Access Types"=9},"$
  |   | }
  |   | 

dkocher added a commit that referenced this issue Sep 9, 2024
Use IOKit for receipt validation. Drop usage of exit(173) no longer supported.
dkocher added a commit that referenced this issue Sep 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
appstore Mac App Store cyberduck Cyberduck mountainduck Mountain Duck thirdparty Issue caused by third party
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants