Reputation: 11
With iOS 9's improved security we are not able to connect to https://test.salesforce.com
We get
NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
which based on SecureTransport.h is related to a handshake failure
errSSLPeerHandshakeFail = -9824, /* handshake failure */
We can disable security and still connect (using NSAllowsArbitraryLoads) but we would prefer to use the new more secure ios features.
We tried making an exception just for Salesforce but still get same error
<key>NSExceptionDomains</key>
<dict>
<key>salesforce.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
edit(to add a question): What is the best way to make requests from ios apps to https://test.salesforce.com as securely as possible? (Do I need to wait for Salesforce to update their certificates? Or is there something more under my control?)
Upvotes: 1
Views: 475
Reputation: 16256
I ran the nscurl
command line utility on the OAuth 2.0 endpoint (ROPC flow, sandbox environment):
nscurl --ats-diagnostics --verbose https://test.salesforce.com/services/oauth2/token
TL; DR:
I found out that the most secure setup that will PASS is the following:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>salesforce.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
</dict>
</dict>
</dict>
(No need to lower the minimum required TLS version. Also, Salesforce is dropping support for TLS 1.0)
The full results of the nscurl
diagnostic:
Starting ATS Diagnostics
Configuring ATS Info.plist keys and displaying the result of HTTPS loads to https://test.salesforce.com/services/oauth2/token.
A test will "PASS" if URLSession:task:didCompleteWithError: returns a nil error.
================================================================================
Default ATS Secure Connection
---
ATS Default Connection
ATS Dictionary:
{
}
2016-06-17 10:49:21.533 nscurl[975:53055] CFNetwork SSLHandshake failed (-9824)
2016-06-17 10:49:21.533 nscurl[975:53055] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fd67d100230 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://test.salesforce.com/services/oauth2/token, NSErrorFailingURLStringKey=https://test.salesforce.com/services/oauth2/token, _kCFStreamErrorDomainKey=3}
---
================================================================================
Allowing Arbitrary Loads
---
Allow All Loads
ATS Dictionary:
{
NSAllowsArbitraryLoads = true;
}
Result : PASS
---
================================================================================
Configuring TLS exceptions for test.salesforce.com
---
TLSv1.2
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.2";
};
};
}
2016-06-17 10:49:21.760 nscurl[975:53055] CFNetwork SSLHandshake failed (-9824)
2016-06-17 10:49:21.760 nscurl[975:53055] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fd67d000aa0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://test.salesforce.com/services/oauth2/token, NSErrorFailingURLStringKey=https://test.salesforce.com/services/oauth2/token, _kCFStreamErrorDomainKey=3}
---
---
TLSv1.1
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.1";
};
};
}
2016-06-17 10:49:21.817 nscurl[975:53055] CFNetwork SSLHandshake failed (-9824)
2016-06-17 10:49:21.817 nscurl[975:53055] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fd67b49bf10 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://test.salesforce.com/services/oauth2/token, NSErrorFailingURLStringKey=https://test.salesforce.com/services/oauth2/token, _kCFStreamErrorDomainKey=3}
---
---
TLSv1.0
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.0";
};
};
}
2016-06-17 10:49:21.878 nscurl[975:53055] CFNetwork SSLHandshake failed (-9824)
2016-06-17 10:49:21.879 nscurl[975:53055] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
Result : FAIL
Error : Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={_kCFStreamErrorCodeKey=-9824, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, NSUnderlyingError=0x7fd67d1002c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9824, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://test.salesforce.com/services/oauth2/token, NSErrorFailingURLStringKey=https://test.salesforce.com/services/oauth2/token, _kCFStreamErrorDomainKey=3}
---
================================================================================
Configuring PFS exceptions for test.salesforce.com
---
Disabling Perfect Forward Secrecy
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring PFS exceptions and allowing insecure HTTP for test.salesforce.com
---
Disabling Perfect Forward Secrecy and Allowing Insecure HTTP
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled for test.salesforce.com
---
TLSv1.2 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.2";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.1 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.1";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.0 with PFS disabled
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionMinimumTLSVersion = "TLSv1.0";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Configuring TLS exceptions with PFS disabled and insecure HTTP allowed for test.salesforce.com
---
TLSv1.2 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.2";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.1 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.1";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
---
TLSv1.0 with PFS disabled and insecure HTTP allowed
ATS Dictionary:
{
NSExceptionDomains = {
"test.salesforce.com" = {
NSExceptionAllowsInsecureHTTPLoads = true;
NSExceptionMinimumTLSVersion = "TLSv1.0";
NSExceptionRequiresForwardSecrecy = false;
};
};
}
Result : PASS
---
================================================================================
Upvotes: 1
Reputation: 1
To continue down the path of making an exception, try adding force.com to the exception list (instead of only salesforce.com) So... add this as another exception key:
<key>NSExceptionDomains</key>
<dict>
<key>force.com</key>
<dict>
<key>NSExceptionMinimumTLSVersion</key>
<string>TLSv1.0</string>
<key>NSExceptionRequiresForwardSecrecy</key>
<false/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
I also await a more permanent solution.
Upvotes: 0