6

equipo,No se puede realizar la autenticación mediante el certificado de cliente en el iPhone

Tengo el servicio REST basado en .NET configurado con SSL bidireccional. En mi lado del iPhone, he instalado el certificado del servidor en los perfiles del dispositivo y el certificado del cliente se incluye como recurso de la aplicación. La validación del certificado del servidor funciona bien, pero la autenticación del certificado del cliente falla. Debajo está mi fragmento de código

- (void)connection:(NSURLConnection *) connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge { 
    NSLog(@"Authentication challenge with host: %@", challenge.protectionSpace.host); 

    if([challenge previousFailureCount] == 0) { 
     NSURLProtectionSpace *protectionSpace = [challenge protectionSpace]; 
     NSString *authMethod = [protectionSpace authenticationMethod]; 
     if(authMethod == NSURLAuthenticationMethodServerTrust) { 
      NSLog(@"Verifying The Trust"); 
      [[challenge sender] useCredential:[NSURLCredential credentialForTrust:[protectionSpace serverTrust]] forAuthenticationChallenge:challenge]; 
     } 
     else if(authMethod == NSURLAuthenticationMethodClientCertificate) { 
      NSLog(@"Trying Certificate"); 
      // load cert 

      NSString *thePath = [[NSBundle mainBundle] 
           pathForResource:@"Myclientcertificate" ofType:@"pfx"]; 
      NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath]; 
      CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data;    

      OSStatus status = noErr; 
      SecIdentityRef myIdentity; 
      SecTrustRef myTrust; 

      status = extractIdentityAndTrust(
              inPKCS12Data, 
              &myIdentity, 
              &myTrust); 

      SecTrustResultType trustResult; 

      if (status == noErr) {          
       status = SecTrustEvaluate(myTrust, &trustResult); 
      } 

      SecCertificateRef myCertificate; 
      SecIdentityCopyCertificate(myIdentity, &myCertificate); 
      const void *certs[] = { myCertificate }; 
      CFArrayRef certsArray = CFArrayCreate(NULL, certs, 1, NULL); 


      NSURLCredential *credential = [NSURLCredential credentialWithIdentity:myIdentity certificates:(NSArray*)certsArray persistence:NSURLCredentialPersistencePermanent]; 

      [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; 


     } 
    } 

} 

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace 
{ 
    BOOL result; 
    NSLog(@"canAuthenticateAgainstProtectionSpace: %@", protectionSpace.authenticationMethod); 
    if ([protectionSpace authenticationMethod] == NSURLAuthenticationMethodServerTrust) { 
     result= YES; 
    } else if([protectionSpace authenticationMethod] == NSURLAuthenticationMethodClientCertificate) { 
     result = YES; 
    } 
    return result; 
} 

OSStatus extractIdentityAndTrust(CFDataRef inPKCS12Data, SecIdentityRef *identity, SecTrustRef *trust){ 
    OSStatus securityError = errSecSuccess; 


    CFStringRef password = CFSTR("1234"); 
    const void *keys[] = { kSecImportExportPassphrase }; 
    const void *values[] = { password }; 
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(
                  NULL, keys, 
                  values, 1, 
                  NULL, NULL); 
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); 
    securityError = SecPKCS12Import(inPKCS12Data, 
            optionsDictionary, 
            &items); 

     if (securityError == 0) {         
     CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0); 
     const void *tempIdentity = NULL; 
     tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, 
              kSecImportItemIdentity); 
     *identity = (SecIdentityRef)tempIdentity; 
     const void *tempTrust = NULL; 
     tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust); 
     *trust = (SecTrustRef)tempTrust; 
    } 

    if (optionsDictionary) { 
     CFRelease(optionsDictionary); 
    } 

    return securityError; 
} 

Mi conexión no es correcta, con error mencionado a continuación.

{ 
    NSErrorFailingURLKey = "https://myIpdaddress/Service1.svc/test/random"; 
    NSErrorFailingURLStringKey = "https://myIpdaddress/Service1.svc/test/random"; 
    NSLocalizedDescription = "The server \U201cmyIpdaddress\U201d requires a client certificate."; 
    NSUnderlyingError = "Error Domain=kCFErrorDomainCFNetwork Code=-1206 \"The server \U201cmyIpdaddress\U201d requires a client certificate.\" UserInfo=0x4b240b0 {NSErrorFailingURLKey=https://myIpdaddress/Service1.svc/test/random, NSErrorFailingURLStringKey=https://myIpdaddress/Service1.svc/test/random, NSLocalizedDescription=The server \U201cmyIpdaddress\U201d requires a client certificate.}"; 
} 

Amablemente me ayuda a cómo reslove esto.

Respuesta

1

Me encontré con exactamente el mismo problema.

La solución para mí fue corregir el encabezado HTTP 'Host'.

El que estaba usando incluía el puerto y una parte de la ruta. Una vez que corregí este encabezado para incluir solo la parte del host de la url, las cosas comenzaron a funcionar.

Creo que el servidor rechazaba mi identidad cuando tenía el encabezado host incorrecto, y creo que el mensaje "requiere un certificado de cliente" es una respuesta general que también puede significar que el servidor no aceptó el certificado presentado.

Cuestiones relacionadas