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)
}
}