-
-
Save lukaskubanek/cbfcab29c0c93e0e9e0a16ab09586996 to your computer and use it in GitHub Desktop.
| /// MIT License | |
| /// | |
| /// Copyright (c) 2021 Lukas Kubanek, Structured Path GmbH | |
| /// | |
| /// Permission is hereby granted, free of charge, to any person obtaining a copy | |
| /// of this software and associated documentation files (the "Software"), to deal | |
| /// in the Software without restriction, including without limitation the rights | |
| /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| /// copies of the Software, and to permit persons to whom the Software is | |
| /// furnished to do so, subject to the following conditions: | |
| /// | |
| /// The above copyright notice and this permission notice shall be included in all | |
| /// copies or substantial portions of the Software. | |
| /// | |
| /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| /// SOFTWARE. | |
| import Foundation | |
| import Security | |
| extension Bundle { | |
| /// Returns whether the bundle was signed for TestFlight beta distribution by checking | |
| /// the existence of a specific extension (marker OID) on the code signing certificate. | |
| /// | |
| /// This routine is inspired by the source code from ProcInfo, the underlying library | |
| /// of the WhatsYourSign code signature checking tool developed by Objective-See. Initially, | |
| /// it checked the common name but was changed to an extension check to make it more | |
| /// future-proof. | |
| /// | |
| /// For more information, see the following references: | |
| /// - https://github.com/objective-see/ProcInfo/blob/master/procInfo/Signing.m#L184-L247 | |
| /// - https://gist.github.com/lukaskubanek/cbfcab29c0c93e0e9e0a16ab09586996#gistcomment-3993808 | |
| internal var isTestFlight: Bool { | |
| var status = noErr | |
| var code: SecStaticCode? | |
| status = SecStaticCodeCreateWithPath(bundleURL as CFURL, [], &code) | |
| guard status == noErr, let code = code else { return false } | |
| var requirement: SecRequirement? | |
| status = SecRequirementCreateWithString( | |
| "anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.25.1]" as CFString, | |
| [], // default | |
| &requirement | |
| ) | |
| guard status == noErr, let requirement = requirement else { return false } | |
| status = SecStaticCodeCheckValidity( | |
| code, | |
| [], // default | |
| requirement | |
| ) | |
| return status == errSecSuccess | |
| } | |
| } |
Months later, I wanted to add that I've been using this trick on my public macOS beta for a while, to restrict in-app features. It has worked like a charm since.
@lukaskubanek Thanks for figuring this out. Very handy to have while publicly testing new features!
I feel like sharing what I ended up doing, as it might help other readers:
Beyond being a multiplatform check, I made this observable because Xcode has been complaining about SecStaticCodeCheckValidity for a while, as it is a potentially slow call.
Also notice that the Mac condition appears first, because #if os(iOS) is also met on Catalyst and would take over.
@keeshux Thanks, but it's a shame it's GPL as I don't particularly want to open source my whole application just to check if I'm running on Testflight or not. I think for most people the one in this thread is a safer bet.
@jaanus: Thanks for sharing your findings!