Check if app is ad-hoc|dev|app-store build at run time - ios

I'd like to check this for build information in a debugging screen. Is there a way to check this at runtime?
I realize that I could set compiler flags for the builds or similar, but if there is an existing method that I could leverage I'd like to take advantage of that.

While I would agree with Abhi Beckert that runtime is the wrong time to be doing this (use preprocessor directives and build settings!), I wanted to clarify some of the details and speculations in the previous answer/comments and shine some light on things you could do. Bear with me, this is going to be a longer answer...
There are a bunch of pieces of data that could go under the generic umbrella of 'Build Information'. A non-exhaustive list of such things would include: Build Configuration, Code Signing Identity, Build Time, Build Date, Marketing Version Number, SCM Revision Number, SCM Branch Name, Provisioning Profile Team Identity, Provisioning Profile Expiration, CI Build Number...the list goes on and on.
Assuming for the moment your question was narrowly focused on gaining information as to the type of iOS certificate and Provisioning Profile used for the build, then I will have to go with a very firm 'No' as the answer to the question: Is there a way to check [build information using an existing API method] at runtime? As a brief aside: Collectively these two data points are called the "Code Signing Identity" in Xcode 4.6.x Build Settings or "CODE_SIGN_IDENTITY" for you command-line build setting enthusiasts.
As of the time this question was asked, there is no singular public iOS API that you can call to get information about the code signature type for the currently running app. The likely reasons behind this are numerous, but here are a few examples:
Developers are permitted to construct their own build schemes and build configurations. This means that we can have one scheme and one build configuration, or one scheme and dozens of build configurations, or even thousands of each. Naturally each scheme can be assigned a different build configuration, and those configurations can each be assigned a different code signing identity. As you might guess, it doesn't take much customization by a developer or team for this to quickly get chaotic.
Code signing identities only require that a non-expired Provisioning Profile issued for the current app identifier, contains a copy of the public key for the certificate used to sign the binary. For those working on a team, you might have a single Provisioning Profile containing all the certificates of the developers on the team, or you might make individual Provisioning Profiles for each developer on the team containing only their certificates. This is yet another point of variation in how developers can elect to build their app.
Developers may share a single certificate (tsk tsk) or be issued their own certificates...yep, you guessed it, even more variation.
This hypothetical one-stop API would then need to have access at runtime to all of your build configuration data, certificates, and provisioning profiles to be able to untwist the 'effective' settings applied at compile time and reduce all of that data down to a finite string...simply for a developer diagnostics view...not an impossible feat by any stretch of the imagination, but such a potentially computationally intense operation for negligible developer benefit would definitely rank low on just about anybody's priority list. It would get kicked even further down the priority list given that other options (like compile-time flags!) are more reliable, cheaper to setup, and simpler to maintain in the long run.
Now, as to the semi-lurking question of "Could I do it at runtime?" I would emphatically say 'Yes you can.'
As you know, device builds are the only kinds of builds that require code signing. Part of the process creates a file in the main bundle called 'embedded.mobileprovision'. This is a file owned by your app's sandbox and thus is something you absolutely have the ability to open programmatically:
[[NSBundle mainBundle] pathForResource:#"embedded.mobileprovision" ofType:nil]
.mobileprovision files are PCKS#7 encoded and contain both binary and text data. The info you seek is that of the text-based plist embedded within the PCKS#7 data. First, using OS X let's take a look at this text data out of one of your device builds:
Right click on your build for device .app bundle and select 'Show Package Contents'
Copy the embedded.mobileprovision file someplace easily accessible.
Open that file with your preferred text editor.
You notice right away that there's a lot of binary data but you can make out parts of the text data. Scrolling to the right, you'll see plist-styled xml, only it isn't so easy to read in this view. We can use an OS X command line tool to look at this data in a more organized manner:
Open Terminal and 'cd' to the folder containing your copy of the embedded.mobileprovision.
Run: security cms -D -i embedded.mobileprovision
This will display the plist xml to the terminal window for your perusal in a nicely tabbed format. If you repeat this process for an Ad-Hoc build, Dev build, and an App Store build you'll start to notice the keys in this text that are indicative of the respective types of builds. For builds signed with an 'iPhone Developer: ...' certificate (or 'Dev' builds as you listed in the original post), look for:
<key>get-task-allow</key>
<true/>
The 'get-task-allow' key is what is used to instruct iOS if the app will allow a debugger to attach to it. In the case of an 'iPhone Developer' signed binary this makes sense - You would typically need to be able to debug on the device when pushing code from Xcode to your device for testing purposes.
The difference between 'Ad-Hoc' and 'App Store' require some additional checks. This same 'get-task-allow' key will be set to false for both of these kinds of distributions:
<key>get-task-allow</key>
<false/>
However, 'Ad-Hoc' builds have a defined set of 'ProvisionedDevices'not present in 'App Store' builds:
<key>ProvisionedDevices</key>
<array>
<string>abcdef01234567890abcdef01234567890abacde</string>
<string>1abcdef01234567890abcdef01234567890abacd</string>
<string>2abcdef01234567890abcdef01234567890abacd</string>
</array>
So what does this mean in practical terms for the runtime checking question? Yes you can do it, by opening up the embedded.mobileprovision file out of the main bundle, and parsing data out of it to make an informed decision, but that is something you'd be entirely responsible for implementing yourself. You'll need to add logic to handle cases where that file is missing (ex. Simulator builds) and to either parse the PCKS#7 data or reliably extract the ASCII content of the file upon which your code can run a series of string searches. As is likely evident, this will require non-trivial effort for a somewhat brittle solution that can otherwise be easily accommodated by build settings and pre-processor macros at as Abhi Beckert outlined in the previous answer.
What about the risk of App Store rejection? Is this 'illegal' or 'subversive'?
Presuming that you use all public API when reading and parsing the contents of the embedded.mobileprovision file, this is perfectly allowable by the current terms of the App Store. Anything in your app's sandbox is fair game including embedded.mobileprovision if it happens to be present. I still strongly caution against going down this road, echoing Abhi Beckert's comments. It is a considerable amount of effort for less than 1% of use cases and there are far easier solutions out there! Furthermore, developer diagnostic views shouldn't be in App Store release builds, however the decision to include extraneous code is entirely in your hands.
I hope this clears up any lingering questions, but if not, please toss in a comment and we can see what we can do.

This is probably what you're looking for. Abhi has a good, thorough explanation and this gist has the actual code:
https://github.com/blindsightcorp/BSMobileProvision

Runtime is the wrong time to do this.
Your app may get rejected from the store if you try doing it. Or it might be approved, and then you do an urgent bugfix release and that one might get rejected.
As #rmaddy suggested in a comment, you should do it at compile time.
Edit your project settings to define this constant: CONFIGURATION_$(CONFIGURATION), then do this in your code:
#if defined (CONFIGURATION_Debug) || defined (CONFIGURATION_Adhoc)
NSLog( #"Warning message");
#endif
Source/more details: http://ios-dev.gravitini.com/2009/02/identifying-current-xcode-configuration.html
You can wrap a runtime function around it if you want. Perhaps:
void debugLog(NSString *str)
{
#if defined (CONFIGURATION_Debug)
NSLog(#"%#", str);
#endif
}

Related

What are an iOS app's Compiled/Build Files?

I am delivering an iOS app for a client and they are asking for the compiled/build files for the app and not the source code or an exported .ipa. I am wondering what compiled/build files are.
Is it just the .app that is created in /products whenever I build my app or something else that I need to do? I believe they are after these files so they can sign the app with their own production provisioning profile and to create a .ipa themselves.
What is an iOS app's compiled/build files and if it is just the .app how it differs from an exported .ipa?
Although vague, it's also possible they're looking for an Xcode Archive. This includes the compiled .app file as well as symbol information. You can build an archive to seed an application for testing or to validate and submit an application to iTunes Connect. If they want to submit or distribute the app without the source code, this is how you would do it.
"Building" is a fairly general term, and it can refer to anything that is needed to go from editable source material (source code, scripts, raw data files, etc.) to a shippable software product. Building can (and usually does) involve several steps, such as pre-processing, compiling, linking, converting data files, running automated tests, packaging, etc.
"Compiling" is more specific, and almost invariably refers to a process that takes source code as its input, and outputs something runnable, typically machine code for either a physical or virtual machine, or source code in a different language.
I bet they are wanting the .app. Unfortunately, since they are being relatively vague with their request, I think you should confirm this with them. I wouldn't feel uncomfortable asking, because their terminology is not some universally accepted way of refering to some method of building iOS applications. Or, if you can find out what they plan to do with the compiled binary, that might help understand what they need.
FYI, here's a brief description of the difference between a .app or .ipa.

How can i add single app in two organisations? client-team and dev-team

In my iOS App, i want two separate teams for Crashlytics reporting. One for internal testing and other for client team. During Development, if crashes will come then it should report in dev-team and if app will be live then crashes should be report in client-team. dev-team and client-team can have common members. How can i achieve this behaviour.
According to mine, if i create two organisations and register my app in two organisations and just switch the API keys in the app when i needed; I think it can be the solution for it. Need your suggestion/solution; Many thanks.
If any other solution exists for this problem then your direction will be more anticipated.
Since Crashlytics differentiates apps using the bundle ID, you can just change that. In order to make your bundle ID dynamic, go to your info.plist file for your project and change the Bundle Identifier key to the value:
com.yourcompany.${CUSTOM_BUNDLE_ID}
Then in your build settings, add a user-defined key called (you guessed it):
CUSTOM_BUNDLE_ID
And then you can specify a different setting for debug, release, distribution:
This will let Crashlytics register different "apps" for the same binary.
To make things even easier, use the same approach to specify a custom product name so that apps will appear with different names and devs/qa can easily identify what "version" of an app they're testing.
We generally don't upload our dev binaries to Crashlytics because we build so many times and we QA on builds from our CI server. That's why we actually specify the product name and bundle ID dynamically at build time on our CI server. This allows (for bigger projects) many parallel apps with different bundle IDs to be distributed/tracked by Crashlytics and all it takes is a new build config.

Can I add a entitlements.plist to jailbreak tweaks?

I'd like to restrict how much access to resources jailbreak tweaks receive. Things like network/keychain/location access... Is it possible to manually add a entitlements plist per tweak?
Many thanks.
Tweak is a dylib - it will be loaded in a process. That process may have entitlements and those entitlements will be used for the tweak. That's it. Tweak doesn't have it's own entitlements.
As for your question. Because of what I said before you can't restrict just a tweak - your restrictions will be applied to the whole process that is being tweaked. You can't do anything about that. That's how tweaks work - they are dylibs dynamically loaded into process address space. After that the tweak becomes a part of the process. So any restrictions will be applied to the whole process which includes the tweak, application code and any other dylib/framework application is linked to.
So if you want to develop an application which will help a user put restrictions on tweaks, I don't think you can do such a thing. What you can do is to analyze which application are being tweaked, what entitlements does they have, what frameworks and dylibs are used by a tweak (mainly the private ones). And from that user can either enable or disable that tweak. You can even analyze import section and string literals of the tweak to determine exactly which APIs does it use.
Update
Could you explain to me how a native process communicates with a
tweak, before being loaded within the process space?
It doesn't. Before injecting tweak is a separate dylib that is not linked to any binary. CydiaSubstrate does all the injecting. The main part of the CydiaSubstrate is a special loader dylib. It's linked dynamically to launchd process on device start, to the process which is the first process in the iOS that starts all other processes. When a new process is spawned CydiaSubstrate loader dylib checks all tweak filters to see which ones it needs to inject into the process and injects them. After that tweak is loaded into process address space (becomes a part of the process) and tweak's constructor is called where usually all the hooks are being setup.
Could you explain to me as to how this is accomplished?
Suppose you have an array of objc class names, C/C++ functions, frameworks and dylibs as strings usage of which you would like to detect. There's easy solution. You can open tweak's file and just search through it for any matches. As tweaks are usually not very large it shouldn't take much time. And there's more difficult solution. Use dyld or any other API to parse mach-o sections to find imported symbols and string literals and then search through them for any matches.
I'm not sure if this answers your question from a user side, but if you are making a tweak, you can add XXX_CODESIGN_FLAGS = -Sentitlements.xml to your Makefile to add the entitlements described in entitlements.xml.

can we create a pass (.pkpass file) programmatically in Xcode?

Though we can add a pass in the pass application in iOS 6.0 programmatically given we have .pkpass file in our document directory or we get it from the server. But i have searched all the apple documentation in which steps are given to generate the .pkpass file manually.
Is this feasible to create a .pkpass file programmatically using Xcode.
The .pkpass file is composed of several components. The most difficult component that must be done programmatically is the signature of the manifest file. The other parts are trivial to assemble on the iPhone platform programmatically. You may note that Apple's documentation uses a shell command to compute this value using the OpenSSL library. I had to manually write a function that signed the manifest files using the OpenSSL C library, however it is not trivial due to a lack of examples and the complexity of the library. The signing function selected by Apple for the manifest is not present in their CommonCrypto framework.
Also, in order to sign these passes on the phone, the credentials must be present in the binary's bundle or compiled assets which is probably not a good idea to distribute if you would like to protect the integrity of your profile and signing identities.
So in summary: This is certainly possible, and is doable using the existing specifications and libraries. However, I would not recommend doing this on the phone. It is fairly difficult, and may introduce security risks if not done properly. Additionally, if you incorporate the OpenSSL library in your binary then you must report to Apple that you incorporate encryption in your device and must register for an ERN with the government. There may also be other export conditions on your code depending on your locality (but of course I am not a lawyer so this is a guess).

How do I build multiple versions of the same iOS application for OEMs

I have an existing iOS application that I need to be able to build and release multiple versions of for different clients.
This application interfaces with hardware that is available from a handful of different companies, the hardware is identical but each company sells the hardware under a different name
This is a free app, the goal is not to spam the appstore with multiple versions of the same app, the goal is to allow companies that sell rebranded hardware to have a mobile app that uses the brand name that they use for the hardware.
What I need to be able to do:
Build multiple versions of the same application that can be submitted to the Appstore, each version would be submitted under a different companies apple account. I would assume that means multiple projects so that each project can use a company specific provisioning profile
Each version has some different images (Icon, startup image, maybe a few others)
Each version has some different strings (Company name, Product Name, maybe a few others)
With Android I just create a library project and I can override strings and images with a trivial amount of effort.
With iOS I haven't found an obvious answer.
I looked into adding a new target to my existing project but I don't think that will work:
- I can't figure out how to replace images beyond the icon and starting screen
- I can't figure out how to replace strings
- Would I be able to use different provisioning profiles for the different apps that compile with the same project? I know the target settings allow different provisioning profiles, but doesn't the project settings have its own set of provisioning profiles?
Can I package the current application into a library that other projects can use and replace images/strings? So each version would have its own xCode project but use the same code.
Maybe I need to work more with the idea of multiple targets...
I am using xCode 4.2, but I am prepared to move to a newer version if necessary
Create multiple targets that use different Info.plist files. The biggest difference will be different bundle identifiers. You can also define different preprocessor macros that will control the conditional compilation of various chunks of code.
Alternatively/additionally, you can put your build configuration settings (including the changing location of the Info.plist file) into *.xcconfig files and reference those in your project, info, configurations area. Then, you can build a different version of your app by simply by changing your scheme. Putting build configration settings into files is a huge win for configuration control too.
Here's a link to setting up *.xcconfig files: http://itcoding.blogspot.com/2011/03/using-xcconfig-abandoning-build-panel.html. I've seen other articles like this as well -- but this one will get you started.
Good luck.
I did this differently at my last company, where we generated around 8 apps from one primary source repository.
We created one project that required one external class, call it Config. That class vended the unique info that makes each app unique.
Then to spin one app you create your App project, include the common "library", provide the Config.m file (Config.h is common), add the unique images etc.
This was very helpful for me. It is essentially the multi-target approach but you customize it for a company and you upload to their account.
https://developer.apple.com/videos/play/wwdc2019/304/ See from the 17 minute mark.
To summarize, you partner with the company you are developing for, from their Apple Connect account, they assign you as the developer and marketing role for the specific apps you are developing for them. You upload your builds to their account. They get ultimate decision of when they will release it and who will test it with TestFlight.

Resources