Trouble deploying iOS app from a secure server - ios

I've been successfully deploying, over-the-air, an iOS app that I developed for a client. I'm using my client's own Enterprise Developer credentials.
I've been doing tests from my own http server, housing all of the requisite files (.plist, .ipa, and of course the html page); and also from a combination of servers: a secure one holding the html, re-directing to another, un-secure, server holding the .plist and .ipa. All's well with all of this.
But I run into trouble when I move everything to a secure server. There, the html opens properly, but on attempt to download (by tapping on the same link that works on my un-secure server), I get a "Cannot connect to "
I've changed the URL in both the html and .plist to reflect the new actual https:// address at the secure site. The site certificate seems to be valid and recognized. Another tester has also had the same problem when trying this for me.
Does anyone have any idea what this might be about?
UPDATE - this problem can be expressed in a slightly simpler way. .ipa files will not download if they are placed on a secure (https://) server.
Versions of iOS earlier than 7.1 don't seem to care if the html and .plist manifest files are on secure or un-secure servers. But 7.1 cares -- html and .plist MUST be on https.
Why can't the .ipa be there too?

This turns out to be an easy, but hard to find, solution. If the .ipa is served by Microsoft's IIS server software v6.0 or later, the MIME-type settings must include .ipa as 'application/octet-stream'. Otherwise no file is served. Apache servers are a little smarter -- they'll deliver in any event.
So this is not really a http - https issue. I was fooled because my https attempts were all happening on IIS servers that weren't set up properly.

Related

What could be causing epub, mobi and zip files to fail to download on an iPhone running ios 13?

I am having problems on my local server when trying to serve files to an iPhone running ios13. The problems only occur with file types that cannot be rendered in the browser, by that I mean files such as epub, mobi and zip that require me to manually click on download.
Files such as text and pdf have no issue in any browser.
Safari is able to download Mobi, Epub and Zip files, but Chrome, Firefox and Edge all fail giving vague messages like “Couldn’t Download” or “Download Failed”. Try Again.
Originally I was serving the files using Nginx, X-Accel-Redirect and PHP, but I found that using a direct url had the same problem. The server is running HTTPS and HTTP2. Mime types are properly configured in Nginx.
In each case, regardless of whether the file was successfully downloaded or not, the access logs showed status code 200.
My questions are:
What could be causing the failed downloads and how can I fix it?
What other things should I investigate to shed more light on this
issue?
It seems that the SSL certificate on the local server was causing the download issues. It was a self signed certificate and it often causes warnings to be displayed in the browser.
I uploaded the epub/mobi/zip files to a server that didn’t use HTTPS and found that mobi, epub and zip files successfully downloaded regardless of the mobile browser used.
I did the same with another server using a properly signed HTTPS certificate (letsencrypt) and again found that the mobi, epub and zip files successfully downloaded regardless of the mobile browser used.

AssetManifests + Signing: Tricking iOS into getting OS assets from custom sources by circumventing AssetManifestSigning?

The main question:
iOS verifies that system downloads (custom voices for Siri, over-the-air updates, etc.) have been signed by Apple. Would it be possible for me to generate a certificate (and make iOS trust that certificate) to make iOS download operating system assets from a custom source? If so, how?
Background
I have recently been missing Siri's old voice circa iOS 11 (I am using iOS 12). iOS 7-10 used a voice known as "Nicky," while iOS 11 introduced a new voice called "Nora". On my Mac, I was able to get Siri to use the old voice by simply swapping some of the files for Nicky's voice into the folder for Nora's voice in /System/Library/Speech/NoraSiri.SpeechVoice/Resources. Wanting to do the same thing for my iPhone, I realized it wouldn't be as easy, as without a jailbreak I would be unable to modify the necessary system files in iOS. I reasoned that instead, I could possibly trick my iPhone into downloading Siri's voice files (which I would modify to include Nicky's voice) from my computer.
Using a proxy utility called Charles (and installing the Charles Root Certificate on my iPhone in Settings>General>Certificate Trust Settings), I was able to intercept web traffic coming from my iPhone. It turns out that in downloading a new voice for Siri, iOS makes a request to an Apple server over HTTPS to download a manifest file that contains information about all the downloadable voices, their URLs on Apple's servers, their SHA-1 hashes, and more. Then, using the URL in the manifest file for the desired asset (voice), iOS downloads the asset (over HTTP) and then verifies that the SHA-1 of the downloaded file matches the one in the manifest before actually installing the files.
After using my Charles Proxy to serve my iPhone the custom Nicky voice files for the URL that would normally download Nora's, I (obviously) ran into the problem that the custom Nicky files I served from my computer to my iPhone didn't have the expected SHA-1 hash as specified in the manifest for Nora's voice. I then tried to use Charles to serve a modified manifest file to my iPhone.
But upon inspecting the logs from my iPhone, it appeared that iOS was smart enough to recognize that the manifest file is fake, as messages like the following appeared:
iPhone mobileassetd[8810] <Error>: mobileassetd - _MobileAssetDecryptAndVerifySignature: Could not verify signature using public key: -9809
iPhone mobileassetd[8810] <Error>: mobileassetd - _MobileAssetVerifyAssetMapSignature: Could not validate asset map signature
Here is where my understanding is very fuzzy (especially given my little knowledge in cryptography). It appears that the manifest XMLs include several important fields that help to verify that the manifest XML itself is valid:
Certificate : Appears to be a certificate that will help verify the signature of the XML.
Signature : This is the actual signature of the XML, presumably after being signed by private key.
Signing Key : This field is usually "AssetManifestSigning," and it appears to be an instruction to iOS verify the signature of the XML with the "AssetManifestSigning" public key stored on the device.
My Questions
I have several main questions:
Why is Certificate included in the XML when the Signing Key field seems to tell iOS which internal certificate to use in verification? I don't see the point of even having Certificate -- it would seem ridiculous to conclude that the certificate needed to verify the file would be included in the very file that needs to be verified.
Suppose that only Certificate is used to verify the XML (which I doubt as described above). How might I generate my own certificate, include it in the XML, and sign my own XML?
Suppose that iOS actually uses an internal certificate specified by "AssetManifestSigning" to verify the XML. Would it be possible for me to generate my own "AssetManifestSigning" certificate and install it onto iOS to make it trust any asset manifests that I create?
(Bonus) Suppose (2) and (3) are impossible. Any other suggestions on how to get Nicky instead of Nora? I really miss Nicky ...
I am happy to provide more information if necessary. I understand that my knowledge of certificates/keys/cryptography is severely lacking, but any pointers in the right direction are appreciated!
Further references
An example asset manifest file:
https://mesu.apple.com/assets/com_apple_MobileAsset_VoiceServices_GryphonVoice/com_apple_MobileAsset_VoiceServices_GryphonVoice.xml
Some related information about iOS asset manifests:
http://web.archive.org/web/20131101032903/http://www.hydrantlabs.com/Security/iOS/OTA/
https://www.reddit.com/r/ReverseEngineering/comments/1n7h3u/i_reversed_the_ios_ota_update_protocol_enjoy/ccg55uq/?context=8&depth=9

HTML5 Video Does Not Play on iOS over HTTPS when deployed to Firebase Hosting

I am using the the HTML5 Video tag on a PWA created in angular 6 and for the life of me I can't get it to work. At first I thought it was an issue with encoding since it works on FF, Chrome (Desktop and Mobile), and Safari Desktop. I have checked the encoding and the use of the video tag. I believe that all is in order. I am able to play the video on iOS when serving it using HTTP from my local.
ng serve --host 0.0.0.0
It fails to play when trying to use HTTPS and a cert generated from openssl.
http-server dist/marcel-webapp/ -S
This leads me to believe that the issue is only with untrusted certificates. The problem that I having a very hard time finding the solution to is that I am hosting it on Firebase, and google handles the provisioning of the SSL certificates automatically. I checked my version of the trust store on my phone and the neither the root or intermediate certificates in use are listed.
Here is the link to the video my site
The question is... If really do have a certificate issue on firebase, what can be do about it?
Thanks in advance for any guidance on this.
Update and actual problem identified! I eliminated an untrusted certificate as the problem by deploying to AWS. The problem is actually related to the service worker created when adding PWA support to the project. The reason the video works over HTTP is that service workers are only enabled in HTTPS. I'm using Angular 6 to create the PWA, however it seems that other frameworks have the same problem. Turning off services workers in the Safari allows the video to display as expected
Settings > Safari > Advanced > Experimental Features > Service Workers
I found this post describes the problem in great detail. View Post Here

How debug Universal links

I use the cordova plugin "ionic-plugin-deeplinks" (to my knowledge also works with a plain cordova app).
On Android, links when clicked let users choice between chrome and my application.
=> I suppose that app links works
=> As I'm able to access window.IonicDeeplink and redirect the user to the right page
I'm not able to have the same behavior on iOS, when I click a link I always get the app open in Safari.
How can I find clue on issues ?
More context:
apple-app-site-association is got with a HTTP 200 (over https only), it's located in /.well-known/apple-app-site-association:
I checked TeamID and BundleID 5 times (at least);
with the branch.io validator i get all validations green:
Your domain is valid (valid DNS).
Your file is served over HTTPS.
Your server does not return error status codes greater than 400.
Your file's 'content-type' header was found :)
Your JSON is validated.
with the apple validator, I got : "Action required
Could not extract required information for Universal Links. Learn how to implement the recommended Universal Links.
Error no apps with domain entitlements
The entitlement data used to verify deep link dual authentication is from the current released version of your app. This data may take 48 hours to update." (but some devs said that working app add the same error) what to do with that result?
when monitoring server's log while installing the app with Xcode I see a request get a HTTP 200 on apple-app-site-association
while installing the app with Xcode I got no logs referring to swcd in Xcode (I read here that I should if I had error while installing the app). Is a successful installation silent?
I followed that guide to setup entitlements, but some things feel odd with it:
Unlike the snapshot in the guide, I didn't found any *.entitlements file in my project. Should I have one with cordova? (my xCode seems to remember my setting though). Is it possible to check that installed app get entitlements?
I did set my domain in Xcode like this: applinks:mydomain.com and the switch is ON. But I never uploaded any thing from my local dev environment to apple services. Should I have? If yes, how ?
My current interrogations are highlighted but any explanations on any lack of understanding will be more than welcome!!!
Until then I started a verification for testFlight looking for more info.
while installing the app with Xcode I got no logs referring to swcd in xCode
I implemented Universal Links manually, but situation was similar. Particularly I mentioned empty swcd process log while installing the app, and it turned out that most likely iOS didn't even try to download apple-app-site-association file, like if responsible process wasn't run. In my case device restart helped and deep-linking began to work.
Thus I think restarting device is one another step in troubleshooting when you are sure about all your setup.
For anyone trying to debug this in development:
In XCode, ensure you're editing the Debug version of Signing & Capabilities.
To bypass the Apple Universal Links CDN, configure your Debug domains like applinks:?mode=developer -- adding that query string in development is important.
On your iOS Device, go to Settings->Developer->Universal Links and ensure the Associated Domains Development toggle is switched on.
On your iOS Device in Settings->Developer->Universal Links->Diagnostics, enter your Universal Links URL and ensure you get a green checkmark.
After following all of these steps, Universal Links work locally.

how to test universal links on local server?

I am developing an app on Android and IOS and I would like it to support universal links.
I already have an apple-app-site-association file deployed on my PROD server (which is something like www.example.com), but I need to redeploy a new one with some restrictions inside (to NOT allow some paths).
Before redeploying it, I would like to test it on my test server. So I deployed it on the test server (which is www.example.test.local).
To test, I modified my IOS app by changing in Associated Domains the param applinks:.example.com by applinks:.example.test.local. Then I builded my app and tried to click on an url which is www.example.test.local/myPath?myQueryParam=toto (which is not a 'NOT allowed' one). But instead of opening the app, it opened the index of my test server (if I rollback everything and click on an url like www.example.com/myPath, it works perfectly but it is the old apple-app-site-association file).
So did I miss something? What do I have to change to make it work on my test server?
Late to the party here, but most likely your .local server was running on HTTP. You need to use HTTPS, with a valid certificate that the iOS device recognises (try fetching the AASA file by just typing in the URL, including https:// prefix, into Safari; if you get "This Connection Is Not Private", then your cert isn't good enough - stepping through warnings and forcing Safari to visit the site anyway may be enough to get the trust store updated and have the wider system accept your cert).
Unfortunately, like everything to do with app links on iOS and Android, it's a huge pain and exceptionally developer-hostile. There does not seem to be any kind of easier test option for local machine development - or at least, nothing that I can find documented.

Resources