NSURLErrorDomain - even when NSAllowsArbitraryLoads = true;

Hi there!

I’m developing an RSS app, which fetches feeds from unknown sources. Most of the websites fail, even if I have NSAllowsArbitraryLoads = true;


Diagnostics example:

nscurl --ats-diagnostics --verbose http://www.kathimerini.gr/rss

Allow All Loads
ATS Dictionary:
{
    NSAllowsArbitraryLoads = true;
}
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “www.kathimerini.gr” which could put your confidential information at risk." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x7fecc2d0e9d0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, NSErrorPeerCertificateChainKey=(
    "<cert(0x7fecc3801200) s: *.kathimerini.gr i: *.kathimerini.gr>"
), NSUnderlyingError=0x7fecc2d167f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x7fecc2d0e9d0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9813, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9813, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x7fecc3801200) s: *.kathimerini.gr i: *.kathimerini.gr>"
)}}, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “www.kathimerini.gr” which could put your confidential information at risk., NSErrorFailingURLKey=https:/


How can I bypass this? I don't have access to the servers of the feeds of course


best!

d.

Diagnostics example:

nscurl --ats-diagnostics --verbose http://www.kathimerini.gr/rss

I’m going to presume you meant

https://
in the above example (-:

The issue here is that this server has a self-signed certificate. You can see this by poking at the server with the TLSTool sample code:

$ TLSTool s_client -connect www.kathimerini.gr:443 -noverify -showcerts
*  input stream did open
* output stream did open
* output stream has space
* protocol: TLS 1.2
* cipher: ECDHE_RSA_WITH_AES_256_GCM_SHA384
* trust result: recoverable trust failure
* certificate info:
*  0 + rsaEncryption 2048 sha256-with-rsa-signature '*.kathimerini.gr'
* certificate data:
*  0 308203cf308202b7a003020102020900e5d5a4bd14d87b1b300d06092a86…
^C

If you take the pile of hex goo and use Hex Fiend to put it in a

.cer
file, you can then dump it as shown below:
$ certtool d tmp.cer
Serial Number      : 00 E5 D5 A4 BD 14 D8 7B 1B
Issuer Name        :
  Country        : GR
  State          : Athens, Greece
  Locality        : Athens
  Org            : EWORX S.A
  OrgUnit        : IT Department
  Common Name    : *.kathimerini.gr
Subject Name      :
  Country        : GR
  State          : Athens, Greece
  Locality        : Athens
  Org            : EWORX S.A
  OrgUnit        : IT Department
  Common Name    : *.kathimerini.gr
…

Note that the issuer and the subject are the same, which is the very definition of a self-signed certificate.

Disabling ATS’s enhanced security checks won’t help with this because system APIs (like NSURLSession) still do standard (RFC 2818) server trust evaluation. To learn how to disable the standard checks, read Technote 2232 HTTPS Server Trust Evaluation. For an RSS reader I recommend the approach outlined in the Trust Exceptions section.

IMPORTANT In general I strongly recommend against disabling HTTPS server trust evaluation. There are usually better paths you can follow (“better” as in both easier to code and more secure). However, if you’re building an app that connects to arbitrary sites at the user’s behest — a web browser is a classic example of this, but an RSS reader fits the bill as well — this is the expected model.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
NSURLErrorDomain - even when NSAllowsArbitraryLoads = true;
 
 
Q