2012-05-23 10 views
6

Sto provando ad accettare certificati autofirmati in un NSURLConnection, come molti hanno prima di me. Il problema è che voglio solo accettare certs da una whitelist di certs di cui mi fido. Mi accontenterei di capire come accettare un singolo certificato. Ecco il codice che ho finora nella mia NSURLConnectionDelegate:Come posso accettare certificati server autofirmati da una whitelist in iOS?

- (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]; 
    } 
} 

Come si può vedere nel commento, non ho mai effettivamente ottenere kSecTrustResultUnspecified, che è quello che mi aspetto di ottenere. Ho verificato che il mio certificato è corretto e nel formato corretto (DER).

risposta

14

Ok, ho capito. Si scopre che è sufficiente controllare il trust del server e utilizzare effettivamente i dati della cert.

- (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]; 
    } 
} 
+0

come si ottiene il file 'trusted.der'? – Hlung

+0

Puoi cercare un tutorial online per crearne uno, quindi inserirlo nella tua app. Google dovrebbe essere in grado di aiutare con il resto. –

+0

Sono solo curioso che ci possa essere un modo, come Google Chrome, di generare automaticamente questo all'interno dell'app stessa. Grazie a tutti – Hlung