{"id":26932,"date":"2019-10-16T15:34:15","date_gmt":"2019-10-16T19:34:15","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=26932"},"modified":"2023-05-29T10:16:10","modified_gmt":"2023-05-29T14:16:10","slug":"receipt-validation-and-airplay-2","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2019\/10\/16\/receipt-validation-and-airplay-2\/","title":{"rendered":"Receipt Validation and AirPlay 2"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/liscio\/status\/1182687495760293891\">Chris Liscio<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/liscio\/status\/1182687495760293891\">\n<p>I hear rumblings about some App Store receipt validation issues relating to MAC addresses on macOS Catalina. The commonly-used Apple sample code has busted logic that&mdash;in the presence of a strange condition on a (small?) number of systems&mdash;will fail to return a value.<\/p>\n<p>[&#8230;]<\/p>\n<p>I don&rsquo;t know yet, but it manifests on my machine as a service match for both <code>en0<\/code> as well as <code>IOTimeSyncEthernetModernInterfaceAdapter<\/code> (see attached screenshot.) The latter causes a second go-around in the while loop, causing the MAC address to get overwritten with <code>NULL<\/code>.<\/p>\n<\/blockquote>\n\n<p>It makes no sense for Apple to provide buggy sample code for getting the MAC address when every app in the store needs to do this. With some other aspects of receipt validation, one could argue that you want each app to do it slightly differently to make them harder to crack. But the point of checking the MAC address is that you want to match it with the address provided by Apple when it generated the receipt. So you <em>want<\/em> to use the exact same logic they did.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/tapbot_paul\/status\/1182709154311561216\">Paul Haddad<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/tapbot_paul\/status\/1182709154311561216\">\n<p>BTW I don&rsquo;t think this is a Catalina issue, have seen reports of what sounds like this for several OS versions. Also seems to work if tested right after reboot, but breaks if tested later.<\/p>\n<\/blockquote>\n\n<p><a href=\"https:\/\/twitter.com\/liscio\/status\/1183777723979894784\">Chris Liscio<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/liscio\/status\/1183777723979894784\"><p>The plot thickens!<\/p><p>After a reboot, my system no longer exhibits this &ldquo;strange condition&rdquo;.<\/p><p>Immediately after playing audio over AirPlay 2? BOOM&mdash;&ldquo;strange condition&rdquo;! &#x1F92F;<\/p><p>The &ldquo;strange condition&rdquo; appears to be the presence of IOTimeSyncEthernetModernInterfaceAdapter in ioreg.<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2017\/07\/28\/receipt-validation-in-swift\/\">Receipt Validation in Swift<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/02\/28\/apple-blacklists-own-ethernet-driver\/\">Apple Blacklists Its Own Ethernet Driver<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2013\/10\/18\/modern-receipt-validation\/\">Modern Receipt Validation<\/a><\/li>\n<\/ul>\n\n<p id=\"receipt-validation-and-airplay-2-update-2019-10-22\">Update (2019-10-22): <a href=\"http:\/\/supermegaultragroovy.com\/2019\/10\/22\/check-your-receipt-validation-code\/\">Chris Liscio<\/a> (<a href=\"https:\/\/twitter.com\/liscio\/status\/1186672862335307777\">tweet<\/a>, <a href=\"https:\/\/twitter.com\/jamesthomson\/status\/1186658190500466688\">James Thomson<\/a>):<\/p>\n<blockquote cite=\"http:\/\/supermegaultragroovy.com\/2019\/10\/22\/check-your-receipt-validation-code\/\"><p>While playing audio using AirPlay 2, there are <em>two devices<\/em> that have a <code>BSD Name<\/code> equal to <code>en0<\/code>. Both the <em>actual<\/em> <code>en0<\/code> interface, and a new device called <code>IOTimeSyncEthernetModernInterfaceAdapter<\/code> (or <code>IOTimeSyncWiFiInterfaceAdapter<\/code>, depending on your Mac) that is only present while AirPlay is active.<\/p><p>[&#8230;]<\/p><p>When <code>copy_mac_address<\/code> returns <code>NULL<\/code>, your receipt validation code fails, and <em>probably<\/em> results in your application calling <code>exit(173)<\/code> to ask the App Store for a new receipt. Unfortunately, a new receipt isn&rsquo;t going to help, and you get stuck in a very strange loop.<\/p><p>For me, this resulted in the app repeatedly appearing &amp; disappearing in the Dock for quite some time. Eventually, the system finally gave up and told me the app was &ldquo;Damaged&rdquo; and needed to be re-downloaded.<\/p><p>[&#8230;]<\/p><p>The keys to this alternate approach are as follows:<\/p><ol><li>It specifies the <code>kIOEthernetInterfaceClass<\/code>, which only matches network interfaces. (Before you ask&mdash;yes, this includes Wi-Fi adapters.)<\/li><li>It also specifies that <code>kIOPrimaryInterface<\/code> is set to <strong>true<\/strong>, which matches the built-in, primary network interface.<\/li><\/ol><\/blockquote>\n\n<p id=\"receipt-validation-and-airplay-2-update-2021-10-20\">Update (2021-10-20): <a href=\"https:\/\/pfandrade.me\/blog\/pitfalls-when-validating-app-store-receipts-on-macos\/\">Paulo Andrade<\/a>:<\/p>\n<blockquote cite=\"https:\/\/pfandrade.me\/blog\/pitfalls-when-validating-app-store-receipts-on-macos\/\">\n<p>In reality the device identifier for macOS is the MAC for the primary network interface, which might not actually be named <code>en0<\/code>. To be on the safe side, instead of trying to determine which interface is the primary, I just grab all the MACs on that Mac and attempt validation with each one. Problem solved! Right?<\/p>\n<p>Well&#8230; not yet. There&rsquo;s another issue I just encountered recently. The <code>IOBSDNameMatching<\/code> call to get an interface by name can actually return nil even when <code>ifconfig<\/code> shows an interface with that name. I haven&rsquo;t been able to understand why this happens (it&rsquo;s very rare), but on one occasion <a href=\"https:\/\/www.vallumfirewall.com\">Vallum Firewall<\/a> seemed to be the culprit and on another, a simple restart seemed to fix it.<\/p>\n<p>I finally ended up with a solution based on Apple&rsquo;s source code <a href=\"https:\/\/opensource.apple.com\/source\/DirectoryService\/DirectoryService-655\/CoreFramework\/Private\/GetMACAddress.c.auto.html\">here<\/a>. Instead of getting a list of interface names and then getting the MAC for each by name I just iterate all the interfaces irrespective of what they&rsquo;re called and collect the MACs for each.<\/p>\n<\/blockquote>","protected":false},"excerpt":{"rendered":"<p>Chris Liscio: I hear rumblings about some App Store receipt validation issues relating to MAC addresses on macOS Catalina. The commonly-used Apple sample code has busted logic that&mdash;in the presence of a strange condition on a (small?) number of systems&mdash;will fail to return a value. [&#8230;] I don&rsquo;t know yet, but it manifests on my [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2019-10-16T19:34:18Z","apple_news_api_id":"65fd612e-ac9f-445e-8bf2-f8db81dfdbef","apple_news_api_modified_at":"2023-05-29T14:16:13Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAg==","apple_news_api_share_url":"https:\/\/apple.news\/AZf1hLqyfRF6L8vjbgd_b7w","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[222,2392,30,39,1666,71],"class_list":["post-26932","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-airplay","tag-app-store-receipt-validation","tag-mac","tag-macappstore","tag-macos-10-15","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/26932","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=26932"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/26932\/revisions"}],"predecessor-version":[{"id":33974,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/26932\/revisions\/33974"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=26932"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=26932"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=26932"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}