8

I tried all previous answers before but none worked for me. I maybe know the problem and the error is misleading I guess. I am trying to make api request to a server which is https but does not have SSL. Also the apis work only through VPN. So I am disabling SSL verification and it works fine everywhere (in a simulator, postman, android, mac) except a real iOS device.

What leads I get so far is :

  • DNS Pollution - I tried many times on many devices it never works. If it is DNS how it is working on other android and mac.
  • VPN Tunneling - I saw the release logs of VPN software this exact error was a bug but which is fixed now. Still I am using their app I tried my mac internet with the VPN on iPhone still same error.

The error literally seems like to me is with my code or something logical which needs to be done on iOS to actually work on real device for security(if it is there).

So here I'll share the implementation which made it work on simulator so far (prior to which I was getting same error on simulator).

I am implemented URLSessionDelegate to my router class and allowed arbitrary loads in info.plist. So all are fine url, request etc.

The delegate is not getting called on real device.

 func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}

Before making request:

let config = URLSessionConfiguration.default
let session = URLSession(configuration: config, delegate: self, delegateQueue: .main)

Info plist file contents

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>*my.domain*.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.0</string>
        </dict>
    </dict>
</dict>

Console errors:

[] nw_proxy_resolver_create_parsed_array PAC evaluation error: 

NSURLErrorDomain: -1003
2018-06-26 20:12:08.646042+0530 MyApp[806:161960] TIC TCP Conn Failed [1:0x1c416f000]: 12:8 Err(-65554)
2018-06-26 20:12:08.646740+0530 MyApp[806:161964] Task <DCE45907-5758-4CC0-91A1-9EFD53FFDA0A>.<1> HTTP load failed (error code: -1003 [12:8])
2018-06-26 20:12:08.646971+0530 MyApp[806:161964] Task <DCE45907-5758-4CC0-91A1-9EFD53FFDA0A>.<1> finished with error - code: -1003
Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified hostname could not be found." UserInfo={NSUnderlyingError=0x1c044cfc0 {Error Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)" UserInfo={_kCFStreamErrorCodeKey=8, _kCFStreamErrorDomainKey=12}}, NSErrorFailingURLStringKey=https://my.domain.com/myurl/public/api, NSErrorFailingURLKey=https://my.domain.com/myurl/public/api, _kCFStreamErrorDomainKey=12, _kCFStreamErrorCodeKey=8, NSLocalizedDescription=A server with the specified hostname could not be found.}
2018-06-26 20:14:17.727091+0530 MyApp[806:161970] Received XPC error Connection interrupted for message type 3 kCFNetworkAgentXPCMessageTypePACQuery
2018-06-26 20:14:17.727533+0530 MyApp[806:161970] Received XPC error Connection invalid for message type 3 kCFNetworkAgentXPCMessageTypePACQuery
Amber K
  • 700
  • 1
  • 5
  • 20
  • https **is** SSL. How do you expect to use one without the other? – Stephen R Jun 26 '18 at 04:15
  • @StephenR But its a client side preference, on browser, postman, android, mac anywhere im able to bypass this. On simulator too it's working fine with no errors. – Amber K Jun 26 '18 at 04:17
  • Are you sure your VPN is correctly set up on your phone? I'm asking because this is clearly not an error in your code but actually a network configuration problem since your device can't reach the specified host. Your phone won't use your computer's VPN connection even when debugging via Xcode, so make sure your VPN is correctly setup and connected on your phone first – Mihai Fratu Jun 26 '18 at 10:34
  • Hi @MihaiFratu Here what I tried the vpn company provides an ios app for the vpn connection I tried with that it's not working. I shared my vpn connected mac internet with my iOS device using usb sharing, no luck either. Also i ran the vpn with hotspot from android still same error. – Amber K Jun 26 '18 at 10:48
  • I tried it on ipa as well..I guess vpn is setup properly..but working on simulator or an issue with vpn don't know but sure the code is fine. – Amber K Jun 26 '18 at 10:54
  • Allow arbitrary loads too in plist and give a try. – Abu Ul Hassan Jun 29 '18 at 06:07

1 Answers1

1

check By Replacing

 func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
            completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
            }

with following

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod == (NSURLAuthenticationMethodServerTrust) {
            let serverTrust:SecTrust = challenge.protectionSpace.serverTrust!
            var localCertificateTrust = SSLCertificateCreateTrustResult(serverTrust)
            SecTrustEvaluate(serverTrust, &localCertificateTrust)
            if true
            {
                let credential:URLCredential = URLCredential(trust: serverTrust)
                challenge.sender?.use(credential, for: challenge)
                completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))

            } else {
                completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil)
            }
        }
        else
        {
            completionHandler(URLSession.AuthChallengeDisposition.cancelAuthenticationChallenge, nil);
        }
    }
  fileprivate func SSLCertificateCreateTrustResult(_ serverTrust: SecTrust)->SecTrustResultType {
    let certificate: SecCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0)!
    let remoteCertificateData = CFBridgingRetain(SecCertificateCopyData(certificate))!
    let cerPath: String = Bundle.main.path(forResource: "cert", ofType: "der")!
    let localCertificateData = NSData(contentsOfFile:cerPath)!
    print(localCertificateData.length)
    print((remoteCertificateData as! NSData).length)
    let certDataRef = localCertificateData as CFData
    let cert = (SecCertificateCreateWithData(nil, certDataRef))
    let certArrayRef = [cert] as CFArray
    SecTrustSetAnchorCertificates(serverTrust, certArrayRef)
    SecTrustSetAnchorCertificatesOnly(serverTrust, false)
    let trustResult: SecTrustResultType = SecTrustResultType.invalid
    return trustResult
}

also here is whole transport security in my case.

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>dev-domainserver/portal</key>
        <dict>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>
Abu Ul Hassan
  • 1,340
  • 11
  • 28
  • Hi, I tried the above code, actually the delegate is not being called on device. And the code is crashing on simulator. Also I see `let trustResult: SecTrustResultType = SecTrustResultType.invalid return trustResult` the last line is returning invalid.. – Amber K Jun 26 '18 at 14:39
  • have you placed any cert.der in you project > – Abu Ul Hassan Jun 28 '18 at 06:52
  • also check below this helped me when i was stuck ... change if (trustResult == SecTrustResultType.unspecified || trustResult == SecTrustResultType.proceed) To if true .... in following help https://stackoverflow.com/questions/35592572/swift-ssl-error-with-self-signed-certificate – Abu Ul Hassan Jun 28 '18 at 07:01
  • No I haven't placed any certificate..I dont have any knowledge about this.. – Amber K Jun 30 '18 at 05:07
  • hnmmm so if you can share your code share it once. – Abu Ul Hassan Jul 02 '18 at 05:02
  • 1
    NSExceptionAllowsInsecureHTTPLoads is key solution for me after struggling 5 hrs – Apple_Magic Jun 03 '21 at 14:17