override fun invoke()

in ktor-client/ktor-client-ios/darwin/src/io/ktor/client/engine/ios/certificates/CertificatePinner.kt [116:179]


    override fun invoke(
        session: NSURLSession,
        task: NSURLSessionTask,
        challenge: NSURLAuthenticationChallenge,
        completionHandler: (NSURLSessionAuthChallengeDisposition, NSURLCredential?) -> Unit
    ) {
        val hostname = challenge.protectionSpace.host
        val matchingPins = findMatchingPins(hostname)

        if (matchingPins.isEmpty()) {
            println("CertificatePinner: No pins found for host")
            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, null)
            return
        }

        if (challenge.protectionSpace.authenticationMethod !=
            NSURLAuthenticationMethodServerTrust
        ) {
            println("CertificatePinner: Authentication method not suitable for pinning")
            completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, null)
            return
        }

        val trust = challenge.protectionSpace.serverTrust
        if (trust == null) {
            println("CertificatePinner: Server trust is not available")
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, null)
            return
        }

        if (validateTrust) {
            val hostCFString = CFStringCreateWithCString(null, hostname, kCFStringEncodingUTF8)
            hostCFString?.use {
                SecPolicyCreateSSL(true, hostCFString)?.use { policy ->
                    SecTrustSetPolicies(trust, policy)
                }
            }
            if (!trust.trustIsValid()) {
                println("CertificatePinner: Server trust is invalid")
                completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, null)
                return
            }
        }

        val certCount = SecTrustGetCertificateCount(trust)
        val certificates = (0 until certCount).mapNotNull { index ->
            SecTrustGetCertificateAtIndex(trust, index)
        }

        if (certificates.size != certCount.toInt()) {
            println("CertificatePinner: Unknown certificates")
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, null)
            return
        }

        val result = areCertificatesPinned(certificates)
        if (result) {
            completionHandler(NSURLSessionAuthChallengeUseCredential, challenge.proposedCredential)
        } else {
            val message = buildErrorMessage(certificates, hostname)
            println(message)
            completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, null)
        }
    }