Skip to content

Commit

Permalink
Add custom certs for AMC on OS X 10.10 - 10.12
Browse files Browse the repository at this point in the history
  • Loading branch information
tagavari committed Aug 8, 2022
1 parent c987382 commit 44d975b
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 31 deletions.
12 changes: 11 additions & 1 deletion AirMessage/Connection/Connect/DataProxyConnect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Foundation
import NIO
import NIOSSL
import NIOWebSocket
import WebSocketKit
import Sentry
Expand Down Expand Up @@ -90,7 +91,16 @@ class DataProxyConnect: DataProxy {
headers.add(name: "Origin", value: "app")

//Create the WebSocket connection
WebSocket.connect(to: components.url!, headers: headers, configuration: WebSocketClient.Configuration(), on: eventLoopGroup, onUpgrade: { [weak self] webSocket in
var tlsConfiguration = TLSConfiguration.makeClientConfiguration()
if #available(macOS 10.13, *) {

} else {
let certificates = CertificateTrust.certificateFiles.map { certificateURL in try! NIOSSLCertificate(file: certificateURL.path, format: .der) }
tlsConfiguration.additionalTrustRoots = [.certificates(certificates)]
tlsConfiguration.trustRoots = .certificates([])
}

WebSocket.connect(to: components.url!, headers: headers, configuration: WebSocketClient.Configuration(tlsConfiguration: tlsConfiguration), on: eventLoopGroup, onUpgrade: { [weak self] webSocket in
//Report open event
self?.processingQueue.async { [weak self] in
guard let self = self else { return }
Expand Down
52 changes: 26 additions & 26 deletions AirMessage/Security/CertificateTrust.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,34 @@

import Foundation

/**
Gets all locally-stored certificates
*/
func loadBundleCertificates() -> [SecCertificate] {
//Get all local root certificates
let certificatesDir = Bundle.main.resourceURL!.appendingPathComponent("Certificates", isDirectory: true)
let certificates = try! FileManager.default.contentsOfDirectory(at: certificatesDir, includingPropertiesForKeys: nil)
.map { fileURL in
class CertificateTrust {
///An array of all certificate files
static var certificateFiles: [URL] = {
let certificatesDir = Bundle.main.resourceURL!.appendingPathComponent("Certificates", isDirectory: true)
return try! FileManager.default.contentsOfDirectory(at: certificatesDir, includingPropertiesForKeys: nil)
}()

///All locally-stored certificates
static var secCertificates: [SecCertificate] = {
return certificateFiles.map { fileURL in
SecCertificateCreateWithData(nil, try! Data(contentsOf: fileURL) as CFData)!
}
return certificates
}
}
}()

/**
Evaluates the trust against the root certificates
*/
func evaluateCertificate(allowing rootCertificates: [SecCertificate], for trust: SecTrust) -> Bool {
//Apply our custom root to the trust object.
var err = SecTrustSetAnchorCertificates(trust, rootCertificates as CFArray)
guard err == errSecSuccess else { return false }
///Evaluates the trust against the root certificates
static func evaluateCertificate(allowing rootCertificates: [SecCertificate], for trust: SecTrust) -> Bool {
//Apply our custom root to the trust object.
var err = SecTrustSetAnchorCertificates(trust, rootCertificates as CFArray)
guard err == errSecSuccess else { return false }

//Re-enable the system's built-in root certificates.
err = SecTrustSetAnchorCertificatesOnly(trust, false)
guard err == errSecSuccess else { return false }
//Re-enable the system's built-in root certificates.
err = SecTrustSetAnchorCertificatesOnly(trust, false)
guard err == errSecSuccess else { return false }

//Run a trust evaluation and only allow the connection if it succeeds.
var trustResult: SecTrustResultType = .invalid
err = SecTrustEvaluate(trust, &trustResult)
guard err == errSecSuccess else { return false }
return [.proceed, .unspecified].contains(trustResult)
//Run a trust evaluation and only allow the connection if it succeeds.
var trustResult: SecTrustResultType = .invalid
err = SecTrustEvaluate(trust, &trustResult)
guard err == errSecSuccess else { return false }
return [.proceed, .unspecified].contains(trustResult)
}
}
Binary file not shown.
5 changes: 1 addition & 4 deletions AirMessage/Security/ForwardCompatURLSessionDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,10 @@ class ForwardCompatURLSessionDelegate: NSObject, URLSessionDelegate {
#endif

if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
//Get all local root certificates
let certificates = loadBundleCertificates()

//We override server trust evaluation (`NSURLAuthenticationMethodServerTrust`) to allow the
//server to use a custom root certificate (`isrgrootx1.der`).
let trust = challenge.protectionSpace.serverTrust!
if evaluateCertificate(allowing: certificates, for: trust) {
if CertificateTrust.evaluateCertificate(allowing: CertificateTrust.secCertificates, for: trust) {
completionHandler(.useCredential, URLCredential(trust: trust))
} else {
completionHandler(.cancelAuthenticationChallenge, nil)
Expand Down

0 comments on commit 44d975b

Please sign in to comment.