iOS – Installer le certificate SSL par programme

J'écris un plugin phonegap qui installe à la fois le certificate racine CA et le certificate user dans le trousseau d'applications.

Voici le code utilisé pour installer le certificate:

NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:certpath]; CFDataRef inPKCS12Data = (CFDataRef)PKCS12Data; CFSsortingngRef password = (CFSsortingngRef)certPassword; const void *keys[] = { kSecImportExportPassphrase }; const void *values[] = { password }; CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items); if (securityError == 0) { NSLog(@" *** Certificate install Success ***"); } else { NSLog(@" *** Certificate install Failure ***"); } 

Le code ci-dessus fonctionne bien (securityError est égal à 0). Cependant, j'obtiens ces erreurs:

 unknown apsd[59] <Warning>: <APSCourier: 0xee1ba80>: Stream error occurred for <APSTCPStream: 0x126940>: TLS Error Code=-9844 "peer dropped connection before responding" unknown securityd[638] <Error>: CFReadStream domain: 12 error: 8 

Cela indique que le périphérique n'accepte pas le certificate installé, donc je me request si le certificate n'est pas validé par rapport au certificate CA racine installé sur le périphérique.

Dois-je installer le certificate CA racine pour l'application?

Des idées ?

PS: Je suis nouveau dans les environnements Objective-C et XCode.

MODIFIER:

Le code ci-dessous est utilisé pour stocker le certificate racine CA dans le trousseau:

 NSSsortingng *rootCertPath = [[NSBundle mainBundle] pathForResource:@"rootca" ofType:@"cer"]; NSData *rootCertData = [NSData dataWithContentsOfFile:rootCertPath]; OSStatus err = noErr; SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData); CFTypeRef result; NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: (id)kSecClassCertificate, kSecClass, rootCert, kSecValueRef, nil]; err = SecItemAdd((CFDictionaryRef)dict, &result); if( err == noErr) { NSLog(@"Install root certificatee success"); } else if( err == errSecDuplicateItem ) { NSLog(@"duplicate root certificatee entry"); } else { NSLog(@"install root certificatee failure"); } 

EDITER :

Il semble que le certificate n'est pas envoyé au server. Je pense que je dois envoyer le certificate manuellement chaque fois qu'une request https est faite … Je cherche un moyen d'attraper chaque appel https dans le téléphone.

Il ne suffit pas d'importer le certificate dans le trousseau. Le nouveau certificate racine a également été approuvé par l'user ou le système.

En supposant que vous ayez toujours SecCertificateRef dans le certificatee variable, utilisez le code suivant pour augmenter le niveau de confiance:

 NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]}; status = SecTrustSettingsSetTrustSettings(certificatee, kSecTrustSettingsDomainUser, (__bridge CFTypeRef)(newTrustSettings)); if (status != errSecSuccess) { NSLog(@"Could not change the trust setting for a certificatee. Error: %d", status); exit(0); } 

Changer le niveau de confiance requestra à l'user dans une window contextuelle s'il accepte la modification.

Ce que je cherchais, en définissant "Toujours faire confiance" pour le certificate de trousseau système,

 // Trust always, as root certificateed. NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]}; status = SecTrustSettingsSetTrustSettings(myCertificate, kSecTrustSettingsDomainAdmin, (__bridge CFTypeRef)(newTrustSettings));