SecTrustEvaluate always returns kSecTrustResultRecoverableTrustFailure with SecPolicyCreateSSL(SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecTrustResultRecoverableTrustFailure)
问题描述
我的应用程序尝试为自签名证书评估服务器信任证书.这适用于 SecPolicyCreateBasicX509,但不适用于 SecPolicyCreateSSL
My application tries to evaluate a server trust certificate for a self signed certificate. This is working fine with SecPolicyCreateBasicX509 but not working for SecPolicyCreateSSL
这是我的代码:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// policyRef = SecPolicyCreateBasicX509(); this is working
policyRef = SecPolicyCreateSSL(NO, (CFStringRef)
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:@"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else {
// evaluation failed
// ask user to add certificate to keychain
} else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
经过大量研究,我已经通过添加本文中提到的扩展名对自签名证书进行了更改:无法信任 iphone 上的自签名证书
After a lot of research i have already made changes to the self-signed certificate by adding extension like mentioned in this post: Unable to trust a self signed certificate on iphone
还有人提示这里可能缺少什么吗?
Does anyone have another hint what might be missing here?
推荐答案
经过大量测试,我已经解决了这个问题.以下内容已更改.
After a lot of testing I have worked out this problem. The following has been changed.
该策略设置为 NO 以进行服务器评估.这意味着检查证书以进行客户端身份验证.显然服务器证书不会有这个!将此设置为 YES 将实际检查
extendedKeyUsage是否为服务器证书设置为serverAuth.
The policy is set to NO for server evaluation. This means the certificate is checked for client authentication. Obviously the server certificate will not have this! Setting this to YES will actually check if
extendedKeyUsageis set toserverAuthfor the server certificate.
SecTrustSetAnchorCertificates 和 SecTrustSetAnchorCertificatesOnly 应始终在评估之前调用,而不仅仅是在您提供自己的锚证书时.您需要使用空数组调用它,否则系统已知的锚证书不会用于评估.即使从 MDM 安装的受信任根证书也可以正常工作.
SecTrustSetAnchorCertificates and SecTrustSetAnchorCertificatesOnly should always be called before evaluation and not only if you are providing your own anchor certificates. You need to call this with an empty array, otherwise the system known anchor certificates are not used for evaluation. Even installed trusted root certificates from MDM are working then.
这是基于第一个代码的工作示例:
Here is a working sample based on the first code:
if (challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// create trust from protection space
SecTrustRef trustRef;
int trustCertificateCount = SecTrustGetCertificateCount(challenge.protectionSpace.serverTrust);
NSMutableArray* trustCertificates = [[NSMutableArray alloc] initWithCapacity:trustCertificateCount];
for (int i = 0; i < trustCertificateCount; i++) {
SecCertificateRef trustCertificate = SecTrustGetCertificateAtIndex(challenge.protectionSpace.serverTrust, i);
[trustCertificates addObject:(id) trustCertificate];
}
// set evaluation policy
SecPolicyRef policyRef;
// set to YES to verify certificate extendedKeyUsage is set to serverAuth
policyRef = SecPolicyCreateSSL(YES, (CFStringRef) challenge.protectionSpace.host);
SecTrustCreateWithCertificates((CFArrayRef) trustCertificates, policyRef, &trustRef);
[trustCertificates release];
// load known certificates from keychain and set as anchor certificates
NSMutableDictionary* secItemCopyCertificatesParams = [[NSMutableDictionary alloc] init];
[secItemCopyCertificatesParams setObject:(id)kSecClassCertificate forKey:(id)kSecClass];
[secItemCopyCertificatesParams setObject:@"Server_Cert_Label" forKey:(id)kSecAttrLabel];
[secItemCopyCertificatesParams setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef];
[secItemCopyCertificatesParams setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
CFArrayRef certificates;
certificates = nil;
SecItemCopyMatching((CFDictionaryRef) secItemCopyCertificatesParams, (CFTypeRef*) &certificates);
if (certificates != nil && CFGetTypeID(certificates) == CFArrayGetTypeID()) {
SecTrustSetAnchorCertificates(trustRef, certificates);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
} else {
// set empty array as own anchor certificate so system anchos certificates are used too!
SecTrustSetAnchorCertificates(trustRef, (CFArrayRef) [NSArray array]);
SecTrustSetAnchorCertificatesOnly(trustRef, NO);
}
SecTrustResultType result;
OSStatus trustEvalStatus = SecTrustEvaluate(trustRef, &result);
if (trustEvalStatus == errSecSuccess) {
if (result == kSecTrustResultConfirm || result == kSecTrustResultProceed || result == kSecTrustResultUnspecified) {
// evaluation OK
[challenge.sender useCredential:[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
else {
// evaluation failed
// ask user to add certificate to keychain
}
}
else {
// evaluation failed - cancel authentication
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}
希望这会对某人有所帮助.
Hope this will help someone.
这篇关于SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecTrustResultRecoverableTrustFailure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:SecTrustEvaluate 始终使用 SecPolicyCreateSSL 返回 kSecT
基础教程推荐
- iPhone - 获取给定地点/时区的当前日期和时间并将其与同一地点的另一个日期/时间进行比较的正确方法 2022-01-01
- 通过重定向链接在 Google Play 中打开应用 2022-01-01
- NSString intValue 不能用于检索电话号码 2022-01-01
- iOS4 创建后台定时器 2022-01-01
- navigator.geolocation.getCurrentPosition 在 Android 浏览器上 2022-01-01
- AdMob 广告未在模拟器中显示 2022-01-01
- libGDX 从精灵或纹理中获取像素颜色 2022-01-01
- Android:getLastKnownLocation(LocationManager.NETWORK_PROVIDER 2022-01-01
- Cocos2d iPhone 非矩形精灵触摸检测 2022-01-01
- 如何从 logcat 中删除旧数据? 2022-01-01
