From 79409e8a52a9d3f5153053be8eab92b31e7f8292 Mon Sep 17 00:00:00 2001 From: Dariusz Rybicki <dariusz@elixxir.io> Date: Mon, 15 Aug 2022 20:21:16 +0100 Subject: [PATCH] Implement certificate pinning for report requests --- Sources/ReportingFeature/SendReport.swift | 34 +++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Sources/ReportingFeature/SendReport.swift b/Sources/ReportingFeature/SendReport.swift index 41c6f159..e79214dd 100644 --- a/Sources/ReportingFeature/SendReport.swift +++ b/Sources/ReportingFeature/SendReport.swift @@ -45,6 +45,36 @@ extension SendReport { ) } -private class SessionDelegate: NSObject, URLSessionDelegate { - // TODO: handle TLS +private final class SessionDelegate: NSObject, URLSessionDelegate { + func urlSession( + _ session: URLSession, + didReceive challenge: URLAuthenticationChallenge, + completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void + ) { + let authenticationMethod = challenge.protectionSpace.authenticationMethod + if authenticationMethod == NSURLAuthenticationMethodServerTrust, + let serverTrust = challenge.protectionSpace.serverTrust, + handleServerTrustChallenge(serverTrust) { + completionHandler(.useCredential, URLCredential(trust: serverTrust)) + return + } + completionHandler(.cancelAuthenticationChallenge, nil) + } +} + +private func handleServerTrustChallenge(_ serverTrust: SecTrust) -> Bool { + guard let serverCert = SecTrustGetCertificateAtIndex(serverTrust, 0) else { + return false + } + + let serverCertCFData = SecCertificateCopyData(serverCert) + let serverCertNSData = NSData( + bytes: CFDataGetBytePtr(serverCertCFData), + length: CFDataGetLength(serverCertCFData) + ) + + let localCertPath = Bundle.module.path(forResource: "report_cert", ofType: "crt")! + let localCertNSData = NSData(contentsOfFile: localCertPath)! + + return serverCertNSData.isEqual(to: localCertNSData as Data) } -- GitLab