ios – 对于具有不匹配主题名称的自签名CA,使用kSecTrustResultRecoverableTrustFailure时,SecTrustEvaluate失败

前端之家收集整理的这篇文章主要介绍了ios – 对于具有不匹配主题名称的自签名CA,使用kSecTrustResultRecoverableTrustFailure时,SecTrustEvaluate失败前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这是我使用自签名证书进行身份验证的非常标准的NSURLConnection回调:
  1. - (SecCertificateRef)certRefFromDerNamed:(NSString*)derFileName resultingDataRef:(CFDataRef*)dataRefPtr{
  2. NSString *thePath = [[NSBundle mainBundle] pathForResource:derFileName ofType:@"der"];
  3. NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath];
  4. CFDataRef certDataRef = (__bridge_retained CFDataRef)certData;
  5. SecCertificateRef cert = SecCertificateCreateWithData(NULL,certDataRef);
  6. *dataRefPtr = certDataRef;
  7. return cert;
  8. }
  9.  
  10. - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
  11.  
  12. if (connection == self.connection) {
  13.  
  14. BOOL trusted = NO;
  15. if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
  16.  
  17. SecPolicyRef policyRef = SecPolicyCreateBasicX509();
  18.  
  19. SecCertificateRef cert1;
  20. CFDataRef certData1;
  21.  
  22. cert1 = [self certRefFromDerNamed:@"some3rdpartycacert" resultingDataRef:&certData1];
  23.  
  24. SecCertificateRef certArray[1] = { cert1 };
  25. CFArrayRef certArrayRef = CFArrayCreate(NULL,(void *)certArray,1,NULL);
  26.  
  27. SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
  28. SecTrustSetAnchorCertificates(serverTrust,certArrayRef);
  29. SecTrustResultType trustResult;
  30.  
  31. SecTrustEvaluate(serverTrust,&trustResult);
  32.  
  33. trusted = (trustResult == kSecTrustResultUnspecified);
  34.  
  35. CFRelease(certArrayRef);
  36. CFRelease(policyRef);
  37. CFRelease(cert1);
  38. CFRelease(certData1);
  39. }
  40. if (trusted) {
  41. [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
  42. } else {
  43. [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
  44. }
  45. }
  46. }

而且trustResult总是kSecTrustResultRecoverableTrustFailure.

证书本身有点问题.根据服务器上的curl cert主题名称与我正在连接的url不匹配.我已经联系了第三方公司,他们告诉我,我需要在我的代码中接受这个url不匹配.问题是我不知道如何在iOS上这样做.我可以完全绕过证书检查(通过简单地假设trusted = YES并调用useCredential)或完全失败.从安全角度来看,第一种解决方案显然是错误的,并且容易发生MITM攻击.

这是CURL输出(我在这里使用了相同证书的PEM版本):

  1. ukaszs-iMac:Preferences lukasz$ curl --verbose --cacert ~/Desktop/some3rdpartycacert.txt https://dev-service.some3rdparty.com:50101/
  2. * About to connect() to dev-service.some3rdparty.com port 50101 (#0)
  3. * Trying XXX.XXX.XXX.XXX...
  4. * connected
  5. * Connected to dev-service.some3rdparty.com (XXX.XXX.XXX.XXX) port 50101 (#0)
  6. * successfully set certificate verify locations:
  7. * CAfile: /Users/lukasz/Desktop/some3rdpartycacert.txt
  8. CApath: none
  9. * SSLv3,TLS handshake,Client hello (1):
  10. * SSLv3,Server hello (2):
  11. * SSLv3,CERT (11):
  12. * SSLv3,Request CERT (13):
  13. * SSLv3,Server finished (14):
  14. * SSLv3,Client key exchange (16):
  15. * SSLv3,TLS change cipher,Finished (20):
  16. * SSLv3,Finished (20):
  17. * SSL connection using AES256-SHA
  18. * Server certificate:
  19. * subject: C=CA; ST=Ontario; O=Some 3rdParty Corporation; CN=otherpage.some3rdparty.com; emailAddress=noc@some3rdparty.com
  20. * start date: 2013-10-30 16:52:14 GMT
  21. * expire date: 2013-10-30 16:52:14 GMT
  22. * SSL: certificate subject name 'otherpage.some3rdparty.com' does not match target host name 'dev-service.some3rdparty.com'
  23. * Closing connection #0
  24. * SSLv3,TLS alert,Client hello (1):
  25. curl: (51) SSL: certificate subject name 'otherpage.some3rdparty.com' does not match target host name 'dev-service.some3rdparty.com'

那么,如何忽略iOS上的这个特殊错误

解决方法

您需要使用实际主机名创建特殊策略,然后从中创建和评估serverTrust.大致:
  1. SecPolicyRef policyRef = SecPolicyCreateSSL(true,CFSTR("otherpage.some3rdparty.com"));
  2.  
  3. OSStatus status;
  4. SecTrustRef serverTrust;
  5. status = SecTrustCreateWithCertificates(certificatesFromOriginalServerTrust,policyRef,& serverTrust);
  6. // noErr == status?
  7.  
  8. status = SecTrustSetAnchorCertificates(serverTrust,certArrayRef);
  9. // noErr == status?
  10.  
  11. SecTrustResultType trustResult;
  12. status = SecTrustEvaluate(serverTrust,&trustResult);
  13. // noErr == status?
  14.  
  15. if(kSecTrustResultProceed == trustResult || kSecTrustResultUnspecified == trustResult) {
  16. // all good
  17. }

附:您没有使用您创建的政策.

我刚刚找到了一个更完整的解释here.

猜你在找的iOS相关文章