6

多くの人が私の前に持っているように、NSURLConnection で自己署名証明書を受け入れようとしています。問題は、信頼できる証明書のホワイトリストからの証明書のみを受け入れたいということです。単一の証明書を受け入れる方法を理解することに落ち着きます。NSURLConnectionDelegate でこれまでに取得したコードは次のとおりです。

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"];
        NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath];
        CFDataRef myCertData = (__bridge_retained CFDataRef)certData;
        SecCertificateRef myCert = SecCertificateCreateWithData(NULL, myCertData);
        SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
        SecCertificateRef certArray[1] = { myCert };
        CFArrayRef myCerts = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
        SecTrustRef myTrust;
        OSStatus status = SecTrustCreateWithCertificates(myCerts, myPolicy, &myTrust);

        SecTrustResultType trustResult;
        if (status == noErr) {
            status = SecTrustEvaluate(myTrust, &trustResult);
        }
        BOOL trusted = NO;

        if (trustResult == kSecTrustResultUnspecified) {
            // I never get here.  Instead, trustResult is always kSecTrustResultRecoverableTrustFailure
            trusted = YES; 
        }

        if (trusted) {
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]
                 forAuthenticationChallenge:challenge];
        } else {
            [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
        }
        CFRelease(myTrust);
        CFRelease(myCerts);
        CFRelease(myPolicy);
        CFRelease(myCert);
        CFRelease(myCertData);
    } else {
        [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
    }
}

コメントでわかるように、実際に kSecTrustResultUnspecified を取得することはありません。証明書が正しく、正しい形式 (DER) であることを確認しました。

4

1 に答える 1

14

わかりました。サーバーの信頼を確認し、実際に証明書データを使用するだけでよいことがわかりました。

- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
    BOOL trusted = NO;
    if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
        NSString *thePath = [[NSBundle mainBundle] pathForResource:@"trusted" ofType:@"der"];
        NSData *certData = [[NSData alloc] initWithContentsOfFile:thePath];
        CFDataRef certDataRef = (__bridge_retained CFDataRef)certData;
        SecCertificateRef cert = SecCertificateCreateWithData(NULL, certDataRef);
        SecPolicyRef policyRef = SecPolicyCreateBasicX509();
        SecCertificateRef certArray[1] = { cert };
        CFArrayRef certArrayRef = CFArrayCreate(NULL, (void *)certArray, 1, NULL);
        SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
        SecTrustSetAnchorCertificates(serverTrust, certArrayRef);
        SecTrustResultType trustResult;
        SecTrustEvaluate(serverTrust, &trustResult);
        trusted = (trustResult == kSecTrustResultUnspecified);
        CFRelease(certArrayRef);
        CFRelease(policyRef);
        CFRelease(cert);
        CFRelease(certDataRef);
    }
    if (trusted) {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    } else {
        [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
    }
}
于 2012-05-23T21:39:55.533 に答える