Posting the code snippet above here as well as I reached word limit above:
sec_protocol_options_set_verify_block(sec_options, ^(sec_protocol_metadata_t metadata, sec_trust_t trust_ref, sec_protocol_verify_complete_t complete){
if (ignoreCertValidation)
{
logger->Info("TLS certificate validation errors will be ignored.");
complete(true);
}
else
{
SecTrustRef peerTrust = NULL;
if (!(peerTrust = sec_trust_copy_ref(trust_ref)))
{
logger->Error("Unable to copy SecTrustRef for SSL verification.");
}
CFArrayRef trustPolicy = NULL;
SecPolicyRef revocationPolicy = NULL;
OSStatus copyPolicyStatus = SecTrustCopyPolicies(peerTrust, &trustPolicy);
if (copyPolicyStatus != errSecSuccess)
{
string errMessage = StringUtils::CFStringRefToString(SecCopyErrorMessageString(copyPolicyStatus, NULL));
logger->Error("Unable to create additional policies for TLS trust evaluation. Reason: %s", errMessage.c_str());
}
else
{
CFMutableArrayRef mPolicies = CFArrayCreateMutableCopy(kCFAllocatorDefault, (CFArrayGetCount(trustPolicy) + 1), trustPolicy);
CFRelease(trustPolicy);
SecPolicyRef sslPolicy = (SecPolicyRef)CFArrayGetValueAtIndex(mPolicies, 0);
CFDictionaryRef sslPolicyProperties = SecPolicyCopyProperties(sslPolicy);
CFStringRef policyType = (CFStringRef)CFDictionaryGetValue(sslPolicyProperties, kSecPolicyOid);
if (policyType && CFEqual(kSecPolicyAppleSSL, policyType)) // Only apply revocation to SSL validation
{
if (crlChecks == CRLChecks::Hard)
{
revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCRLMethod | kSecRevocationRequirePositiveResponse);
}
else
{
revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCRLMethod);
}
if (revocationPolicy)
{
CFArrayAppendValue(mPolicies, revocationPolicy);
OSStatus setPolicyStatus = SecTrustSetPolicies(peerTrust, mPolicies);
if (setPolicyStatus != errSecSuccess)
{
string errMessage = StringUtils::CFStringRefToString(SecCopyErrorMessageString(setPolicyStatus, NULL));
logger->Error("Unable to add additional policies for TLS evaluation. Reason: %s", errMessage.c_str());
}
}
}
if (revocationPolicy)
{
CFRelease(revocationPolicy);
}
if (sslPolicyProperties)
{
CFRelease(sslPolicyProperties);
}
if (mPolicies)
{
CFRelease(mPolicies);
}
}
CFErrorRef trustError = NULL;
if (SecTrustEvaluateWithError(peerTrust, &trustError))
{
logger->Debug("TLS trust evaluation successful");
complete(true);
}
else
{
SecTrustResultType trustResult;
SecTrustGetTrustResult(peerTrust, &trustResult);
switch(trustResult)
{
case kSecTrustResultUnspecified:
logger->Error("Trust evaluation result - kSecTrustResultUnspecified");
break;
case kSecTrustResultProceed:
logger->Error("Trust evaluation result - kSecTrustResultProceed");
break;
case kSecTrustResultDeny:
logger->Error("Trust evaluation result - kSecTrustResultDeny");
break;
case kSecTrustResultRecoverableTrustFailure:
logger->Error("Trust evaluation result - kSecTrustResultRecoverableTrustFailure");
break;
case kSecTrustResultFatalTrustFailure:
logger->Error("Trust evaluation result - kSecTrustResultFatalTrustFailure");
break;
case kSecTrustResultOtherError:
logger->Error("Trust evaluation result - kSecTrustResultOtherError");
break;
case kSecTrustResultInvalid:
logger->Error("Trust evaluation result - kSecTrustResultInvalid");
break;
}
CFDictionaryRef trust_results = NULL;
trust_results = SecTrustCopyResult(peerTrust);
CFBooleanRef revoChecked = (CFBooleanRef)CFDictionaryGetValue(trust_results, kSecTrustRevocationChecked);
if(revoChecked == kCFBooleanTrue)
{
logger->Error("Revocation check returned TRUE");
}
else
{
logger->Error("Revocation check returned FALSE");
}
if(trust_results)
{
CFRelease(trust_results);
}
// Call to CFErrorCopyDescription can sometimes return the wrong error message strings.
// Check the Security.framework error codes at Security.framework/Headers/SecBase.h
CFIndex errCode = CFErrorGetCode(trustError);
const string errMessage = StringUtils::CFStringRefToString(CFErrorCopyDescription(trustError));
logger->Error("TLS trust evaluation failed. Error: %ld '%s'", errCode, errMessage.c_str());
complete(false);
}
if (trustError)
{
CFRelease(trustError);
}
if (peerTrust)
{
CFRelease(peerTrust);
}
}
}, m_connectionQueue);