OpenSSL "Серверу" localhost "требуется сертификат клиента.": IOS 8 с сервером Apache localhost
Я сталкиваюсь с проблемой, связанной с созданием и установкой сертификата OpenSSL, или это может быть связано с NSURLConnection, после этого я создал сертификат OpenSSL.
Вот ошибка 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.
Каждый раз, когда я получаю сообщение об ошибке "Сервер" localhost "требует сертификат клиента".
Вот мой.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;
}
Мой httpd.config выглядит следующим образом (у меня в локальной системе Mac-Mini BITNAMI XAMPP 5.6.8)
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>
Я пытался с SSLCertificateChainFile и SSLCACertificateFile, но не повезло.
Если я удаляю "SSLVerifyClient require" и нажимаю на сервис, я получаю аутентификационный метод "NSURLAuthenticationMethodServerTrust" и ответ сервера должным образом.
Если я добавлю 'SSLVerifyClient require' в файл.config, то метод делегата NSURLConnection 'willSendRequestForAuthenticationChallenge' будет вызываться дважды, один раз с NSURLAuthenticationMethodServerTrust' и второй раз с 'NSURLAuthenticationMethodClientCertificate', а затем получит ошибку, а затем получит ошибку.
1 ответ
Я думаю, что ваш Apache настроен неправильно; Вы указываете SSLCACertificateFile
к вашему клиентскому сертификату, тогда как клиентский сертификат должен быть только на стороне клиента; Вместо этого вы должны указать свой сертификат CA. Это то, что используется для проверки сертификата клиента.
Как примечание, ваша конфигурация ДЕЙСТВИТЕЛЬНО небезопасна. Никогда не размещайте SSL-сертификаты в вашей общедоступной папке htdocs. Они должны быть размещены где-то только для чтения с правами root и определенно недоступны для удаленных пользователей. Таким образом вы подвергаете себя худшим видам атак.