I am facing OpenSSL certificate creation and installation related problem or it may be due to NSURLConnection, I have create OpenSSL certificate following this.
Here is error's localizedDescription
2015-07-24 14:47:32.279 SSLTest[7657:60489] CFNetwork SSLHandshake failed (-9824 -> -9829)
2015-07-24 14:47:32.347 SSLTest[7657:60489] NSURLConnection/CFURLConnection
HTTP load failed (kCFStreamErrorDomainSSL, -9829)
2015-07-24 14:47:32.576 SSLTest[7657:60350] The server “localhost” requires a client certificate.
Every time I get "The server 'localhost' requires a client certificate" error.
Here is my .m
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *url = @"https://localhost/Test.php";
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[theRequest setHTTPMethod:@"POST"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
[theConnection start];
}
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodServerTrust) {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
} else if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodClientCertificate) {
SecIdentityRef identity = [self getClientCertificate];
SecCertificateRef certificateRef;
SecIdentityCopyCertificate(identity, &certificateRef);
CFArrayRef certificateArray = CFArrayCreate(NULL, (const void **)certificateRef, 1, NULL);
NSURLCredential *identityCredential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray *)certificateArray persistence:NSURLCredentialPersistenceForSession];
[challenge.sender useCredential:identityCredential forAuthenticationChallenge:challenge];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%@",[error localizedDescription]);
}
#pragma mark - Certificates
- (SecIdentityRef)getClientCertificate {
SecIdentityRef identityApp = nil;
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"];
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:thePath];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = CFSTR("abcXYZ123");
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
CFRelease(password);
if (securityError == errSecSuccess) {
NSLog(@"Success opening p12 certificate. Items: %ld", CFArrayGetCount(items));
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
} else {
NSLog(@"Error opening Certificate.");
}
return identityApp;
}
My httpd.config looking like this (I have BITNAMI XAMPP 5.6.8 on my local mac-mini system)
Alias /bitnami/ "/Applications/XAMPP/xamppfiles/apache2/htdocs/"
Alias /bitnami "/Applications/XAMPP/xamppfiles/apache2/htdocs"
SSLEngine on
SSLCertificateFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca.crt
SSLCertificateKeyFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca_withoutPassword.key
SSLCACertificateFile /Applications/XAMPP/xamppfiles/apache2/htdocs/ca.crt
SSLVerifyClient require
<Directory "/Applications/XAMPP/xamppfiles/apache2/htdocs">
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
I had tried with both SSLCertificateChainFile and SSLCACertificateFile but no luck.
If I remove 'SSLVerifyClient require' and hit service then I receive authenticationMethod 'NSURLAuthenticationMethodServerTrust' and server response properly.
If I add 'SSLVerifyClient require' in .config file, then NSURLConnection delegate method 'willSendRequestForAuthenticationChallenge' will call twice, once with 'NSURLAuthenticationMethodServerTrust' and second time with 'NSURLAuthenticationMethodClientCertificate' and then I will get above error.
I think your Apache setup is wrong; You point SSLCACertificateFile to your client certificate, while the client certificate should only be at the client side; You should point it to your CA certificate instead. This is what's used to verify the client certificate.
As a side note, your configuration above is REALLY insecure. Never put any SSL certificates on your public htdocs folder. They should be placed somewhere only readable by root and definitely nowhere accessible by remote users. You're exposing yourself to the worst kind of attacks this way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With