2012-05-23 14 views
6

Estoy tratando de aceptar certificados autofirmados en NSURLConnection, como muchos tienen antes que yo. El problema es que solo quiero aceptar certificados de una lista blanca de certs en los que confío. Me conformaría con averiguar cómo aceptar un solo certificado. Aquí está el código que tengo hasta ahora en mi NSURLConnectionDelegate:¿Cómo puedo aceptar certificados de servidor autofirmados de una lista blanca en 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]; 
    } 
} 

Como se puede ver en el comentario, en realidad nunca consiguen kSecTrustResultUnspecified, que es lo que esperan conseguir. Verifiqué que mi certificado es correcto y en el formato correcto (DER).

Respuesta

14

Bien, lo descubrí. Resulta que solo necesita verificar la confianza del servidor y, de hecho, utilizar los datos del certificado.

- (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

¿cómo se obtiene el archivo 'trusted.der'? – Hlung

+0

Puede buscar un tutorial en línea para crear uno, y luego empacarlo con su aplicación. Google debería poder ayudar con el resto. –

+0

Tengo curiosidad de que haya una manera, como Google Chrome, de generar automáticamente esto dentro de la aplicación. Gracias por cierto. – Hlung

Cuestiones relacionadas