1

I trying to make a https call to my web service from a ios application. So I used:

//...
func sendMessage() {
        let defaults = UserDefaults.standard
        let url = URL(string: defaults.string(forKey:"host")! + ":" + defaults.string(forKey:"port")! + "/garage")!
        var request = URLRequest(url: url)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        let parameters: [String: String] = [
            "identifier": defaults.string(forKey: "secret")!
        ]
        request.httpBody = parameters.percentEncoded()

        let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
        let task = session.dataTask(with: request) { data, response, error in
            guard let data = data,
                let response = response as? HTTPURLResponse,
                error == nil else {                                              // check for fundamental networking error
                print("error", error ?? "Unknown error")
                return
            }

            guard (200 ... 299) ~= response.statusCode else {                    // check for http errors
                print("statusCode should be 2xx, but is \(response.statusCode)")
                print("response = \(response)")
                return
            }

            let responseString = String(data: data, encoding: .utf8)
            debugPrint("responseString = \(responseString)")
        }

        task.resume()
    }
    
    

//...

extension ViewController: URLSessionDelegate {
    public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
       //Trust the certificate even if not valid
       let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
        
       completionHandler(.useCredential, urlCredential)
      
    }
}

I installed the ca at on the target system too. But I also try to ignore the certificate.

I always get following error instead of a response:

2020-07-03 14:41:27.742361+0200 GarageOpener[5177:223905] ATS failed system trust
2020-07-03 14:41:27.742484+0200 GarageOpener[5177:223905] Connection 1: system TLS Trust evaluation failed(-9802)
2020-07-03 14:41:27.742642+0200 GarageOpener[5177:223905] Connection 1: TLS Trust encountered error 3:-9802
2020-07-03 14:41:27.742776+0200 GarageOpener[5177:223905] Connection 1: encountered error(3:-9802)
2020-07-03 14:41:27.746709+0200 GarageOpener[5177:223905] Task <63EC553D-485C-478D-813B-AF0C1D3D3223>.<1> HTTP load failed, 0/0 bytes (error code: -1200 [3:-9802])
2020-07-03 14:41:27.749778+0200 GarageOpener[5177:223905] Task <63EC553D-485C-478D-813B-AF0C1D3D3223>.<1> finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600002b187e0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
), NSUnderlyingError=0x600001773cf0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600002b187e0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://subdomain.mydomain.de:443/garage, NSErrorFailingURLStringKey=https://subdomain.mydomain.de:443/garage, NSErrorClientCertificateStateKey=0}
"3"
error Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600002b187e0>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, NSErrorPeerCertificateChainKey=(
    "<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
), NSUnderlyingError=0x600001773cf0 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600002b187e0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9802, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9802, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x7fd6f2035600) s: *.mydomain.de i: *.mydomain.de>"
)}}, NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://subdomain.mydomain.de:443/garage, NSErrorFailingURLStringKey=https://subdomain.mydomain.de:443/garage, NSErrorClientCertificateStateKey=0}

I know ignore isn't a good idea and it would allow man in the middle attacks. But at least the connection would be encrypted. And if somebody has the ability to make a man in the middle attack in my WLAN I have bigger problems than this. Please help ;)

Tim
  • 71
  • 1
  • 9

1 Answers1

0

Okay, maybe it's time to answer my question.

The first I did wrong was the signing of the certificate. I just set the domain/ip-address of the server in the Common Name (CN) entry of the certificate. That is an outdated solution. You need to set the subjectAltName for modern applications: http://wiki.cacert.org/FAQ/subjectAltName .

But it feels very ugly to use the instructions from that wiki site to self-sign a certificate. So I used the awesome tool certstrap: https://github.com/square/certstrap

After that:

h3t1
  • 1,126
  • 2
  • 18
  • 29
Tim
  • 71
  • 1
  • 9