RFC: Alamofire Server Trust Errors


(Jon Shier) #1

In Alamofire 5, Alamofire will finally gain the ability to produce a specific error for server trust failures, including a detailed reason as to why the trust evaluation failed (as detailed as the Security APIs allow, at least). I've got a nearly complete PR ready to go, but wanted to seek comment from the community regarding the errors they'd like to see and allow review of the errors currently produced.

All of Alamofire's errors are currently produced through the AFError enum, which is used for all errors Alamofire produces internally, but is not used to encapsulate the errors returned from system libraries. Each case has a reason associated with it, which is another enum used to capture particular information about an error. For the serverTrustEvaluationFailed case, the following reason type was added:

public enum ServerTrustFailureReason {
    public struct Output {
        public let host: String
        public let trust: SecTrust
        public let status: OSStatus
        public let result: SecTrustResultType

        init(_ host: String, _ trust: SecTrust, _ status: OSStatus, _ result: SecTrustResultType) {
            self.host = host
            self.trust = trust
            self.status = status
            self.result = result
        }
    }
    case unknown(host: String)
    case noRequiredEvaluator(host: String)
    case noCertificatesFound
    case noPublicKeysFound
    case policyApplicationFailed(trust: SecTrust, policy: SecPolicy, status: OSStatus)
    case settingAnchorCertificatesFailed(status: OSStatus, certificates: [SecCertificate])
    case revocationPolicyCreationFailed
    case defaultEvaluationFailed(output: Output)
    case hostValidationFailed(output: Output)
    case revocationCheckFailed(output: Output, options: RevocationTrustEvaluator.Options)
    case certificatePinningFailed(host: String, trust: SecTrust, pinnedCertificates: [SecCertificate], serverCertificates: [SecCertificate])
    case publicKeyPinningFailed(host: String, trust: SecTrust, pinnedKeys: [SecKey], serverKeys: [SecKey])
}

Some of these cases are particular to Alamofire's implementation, some are for more general trust errors. Due to the opacity of the Security APIs, this type does not attempt to dig into the various status and result types to produce an exact reason but instead give the user the full output of the evaluation and allow them to dig in themselves.

This RFC seeks comment on the failure reasons, as well as the particular implementation seen the PR. Additionally, we'd like suggestions for any other types of trust evaluations possible using the Security APIs that could be useful.