Can NSURLConnection use a client certificate installed in profiles on the device? - ios

I have this setup:
A tomcat server configured to use ssl client certificate authentication (clientAuth=true)
An ipad with a valid client certificate installed on it (emailed as a .p12 file and visible under profiles)
When browsing via ios safari, the ipad uses the client cert and authenticates against the server fine.
However in code, using a NSURLConnection, it won't connect. Debugging on the server shows the client isnt sending and cert at all.
On the client I get an error like this:
Request(https://192.168.1.5:8443/device/security/policy>, 0, 0)) didFailWithError:Error Domain=NSURLErrorDomain Code=-1205 "The server “192.168.1.5” did not accept the certificate." UserInfo=0xe2eae30
{NSErrorFailingURLStringKey=https://192.168.1.5:8443/device/security/policy>, NSErrorFailingURLKey=https://192.168.1.5:8443/device/security/policy>, NSLocalizedDescription=The server “192.168.1.5” did not accept the certificate.,
NSUnderlyingError=0xe2eb250 "The server “192.168.1.5” did not accept the certificate.", NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0xe6ab010>}
I understand I can implement the delegate method for the challenge for the NSURLAuthenticationMethodClientCertificate protection space, but if I do that I dont have the certificate to send, its installed on the device and that isnt accessible via code (is it??)
I tried calling [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge] but that appeared to have no effect.
I was expecting that NSURLConnection would behave as per safari and access the installed certificate, but it appears not. I dont want to have to install the certificate into my app somehow - thats what the built in certificate management is for!
Or am I missing something? Any help appreciated.

Fundamentally you can't get at globally installed certificates from within an app in iOS (as of iOS 8), and the operating system won't help you out by sending them with an NSURLConnection. Safari has special rights to access the certificates. So the only way to use them from within an app is to install them into the app somehow, which makes the whole thing difficult.

Related

iOS NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."

My app fetches resources from AWS bucket (accessed thru a cloudfront).
Some of the users fails to fetch the data due to
NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made."
As we use AWS service I assume that the SSL certificate is fine, the fact that it happens to a small (but not small enough) portion of the users should say that the SSL certificate is OK.
Any other post I saw about this issue suggested to add a flag to App Transport Security Settings in info.plist file that will allow unsecured connection. This is not something I can (or want) to do.
Thanks for the help :)
This might happen if you're using a VPN.
But will also happen if you're using a proxy tool like Charles Proxy but haven't installed/trusted the Charles Proxy certificate.
It also happened to me when I was on a public wifi network. It seemed that some how the public wifi was doing some sort of a MITM to maybe add some ads. I didn't face the same problem when I was using LTE or a non-public wifi
I found this solution from the Apple Developer Forums which does not involve modifying the App Transport Security Settings:
And you shouldn’t need an ATS exception in your scenario. The
approach I recommend is as follows:
Set up a custom certificate authority (CA) within your organisation (many organisations already have this).
Have it issue a certificate for your private server.
Use MDM to install your organisation CA’s root certificate on your devices.

Security of SSL Pinning

I have an iOS app which implements SSL Pinning. I compare the remote certificate against the locally stored certificate and proceed depending on the result of the comparison. If both certificates are equal, the URL connection is permitted. Otherwise, it is denied. My question is this: Can an attacker change the local certificate stored in the app (.ipa) with another certificate?
This would allow the attacker to see all of my requests and responses.
Thanks.
Yes, but only on jailbroken device, since on non-jailbroken device you can't view the content of the installed application.

Install TLS 1.2 Certificate on iOS App

How do I install a certified TLS certificate on an iOS app?
I assume there also needs to be the ability to send a new certificate over the network to the app in the future, if need be, and how exactly would that work?
I assume once it's installed that Apple will handle the entire handshake process of the device side?
Had some trouble finding explicit answers to these questions online.
Assuming that what you are describing is a signed SSL certificate for your domain name, the only thing you will need to do is install it on your web server. When your application makes a request to your web server, the server will send the certificate to the client during the initial HTTPS handshake, and the client will verify it automatically.

API only works when fiddler is running

I've written a utility app for loading data into shopify through the rest API.
Having a strange error where the api only works when I'm running Fiddler.
Any idea what's going on? I'm sure it's a configuration issue rather than a code issue.
When Fiddler is running web access is through a proxy on 127.0.01:8888.
I'm not advanced enough on SSL to figure this one out. Do you need a self signed certificate to connect to an SSL API.
I found a few posts suggesting setting ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls but that didn't fix it!
>> Do you need a self-signed certificate to connect to an SSL API.
We faced similar issue with our application. If API has any certificate errors (In our case, we are using self-signed certificate), Browser will not allow you to interact with API.
Solution : Install your root Certificate, so that browser will start honoring your self-signed certificate.
>> Having a strange error where the api only works when I'm running Fiddler. Any idea what's going on? I'm sure it's a configuration issue rather than a code issue.
Whenever you enable HTTPs traffic decryption in fiddler (see below image for enabling this setting in fiddler), below things will happen.
Fiddler will automatically install its root certificate
"DO_NOT_TRUST_FiddlerRoot" to Browser's CA list.
Fiddler will use your API's self-signed certificate to decrypt HTTP traffic.
Again fiddler will encrypt same HTTP traffic using fiddler signed
certificate, i.e, for all your API calls will have fiddler signed
certificate
As fiddler signed certificates are trusted by user browser (due to step#a), you will not see any certificate errors.
Hope this information helps you!
Turns out I was setting SSL type to SSL3.
i.e. I had this code
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
and shopify doesn't use SSL3 any more.
Turns out it was nothing to do with installing certificates.

How to accept trusted certificate added to iOS device via iPhone Configuration Utility in application

I want my application to have the ability to accept trusted root certificates that have been added to an iOS device by using the iPhone Configuration Utility.
I added a trusted certificate to an iOS device using the iPhone Configuration Utility and confirmed that Safari accepts my self-signed certificate by sending my server a https request. However, when I make a simple test app that uses NSURLConnection to make a GET request to my server using HTTPS, I get the following error message:
"
Error - The certificate for this server is invalid. You might be connecting to a server enter code here`that is pretending to be “myserver” which could put your confidential information at risk.
"
I imagine that my iOS app is sandboxed, and does not accept the self-signed certificate by default. I've tried manipulating code in willSendRequestForAuthenticationChallenge to accept the self signed certificate without success. I was hoping that someone else has figured out how to do this. I do not want to accept all self-signed certificates. I only want to accept self-signed certificates that have been configured to be trusted on the device.

Resources