attempt to handle tls handshake failure properly

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@37274 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2013-10-25 09:34:35 +00:00
parent cd76262056
commit f769807665
3 changed files with 59 additions and 13 deletions

View file

@ -1,3 +1,9 @@
2013-10-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSSocketStream.m:
* Source/GSTLS.m:
Attempt to better handle TLS handshake failure.
2013-10-24 Richard Frith-Macdonald <rfm@gnu.org> 2013-10-24 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSHTTPURLHandle.m: * Source/GSHTTPURLHandle.m:

View file

@ -504,7 +504,30 @@ static NSArray *keys = nil;
if ([session handshake] == YES) if ([session handshake] == YES)
{ {
handshake = NO; // Handshake is now complete. handshake = NO; // Handshake is now complete.
active = [session active]; // The TLS session is now active. active = [session active]; // Is the TLS session now active?
if (NO == active)
{
NSString *problem = [session problem];
NSError *theError;
if (nil == problem)
{
problem = @"TLS handshake failure";
}
theError = [NSError errorWithDomain: NSCocoaErrorDomain
code: 0
userInfo: [NSDictionary dictionaryWithObject: problem
forKey: NSLocalizedDescriptionKey]];
if ([istream streamStatus] != NSStreamStatusError)
{
[istream _recordError: theError];
}
if ([ostream streamStatus] != NSStreamStatusError)
{
[ostream _recordError: theError];
}
[self bye];
}
} }
} }
} }

View file

@ -1269,7 +1269,7 @@ static NSMutableDictionary *credentialsCache = nil;
- (BOOL) active - (BOOL) active
{ {
return active; return active;
} }
- (void) dealloc - (void) dealloc
@ -1805,30 +1805,35 @@ static NSMutableDictionary *credentialsCache = nil;
ret = gnutls_certificate_verify_peers2 (session, &status); ret = gnutls_certificate_verify_peers2 (session, &status);
if (ret < 0) if (ret < 0)
{ {
NSLog(@"Error %s", gnutls_strerror(ret)); str = [NSString stringWithFormat:
@"TLS verification: error %s", gnutls_strerror(ret)];
ASSIGN(problem, str);
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
if (YES == debug) if (YES == debug)
{ {
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
NSLog(@"The certificate hasn't got a known issuer."); NSLog(@"TLS verification: certificate hasn't got a known issuer.");
if (status & GNUTLS_CERT_REVOKED) if (status & GNUTLS_CERT_REVOKED)
NSLog(@"The certificate has been revoked."); NSLog(@"TLS verification: certificate has been revoked.");
/* /*
if (status & GNUTLS_CERT_EXPIRED) if (status & GNUTLS_CERT_EXPIRED)
NSLog(@"The certificate has expired"); NSLog(@"TLS verification: certificate has expired");
if (status & GNUTLS_CERT_NOT_ACTIVATED) if (status & GNUTLS_CERT_NOT_ACTIVATED)
NSLog(@"The certificate is not yet activated"); NSLog(@"TLS verification: certificate is not yet activated");
*/ */
} }
if (status & GNUTLS_CERT_INVALID) if (status & GNUTLS_CERT_INVALID)
{ {
NSLog(@"The remote certificate is not trusted."); ASSIGN(problem,
@"TLS verification: remote certificate is not trusted.");
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
@ -1838,26 +1843,34 @@ static NSMutableDictionary *credentialsCache = nil;
*/ */
if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509)
{ {
NSLog(@"The remote certificate is not of the X509 type."); ASSIGN(problem,
@"TLS verification: remote certificate not of the X509 type.");
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
if (gnutls_x509_crt_init(&cert) < 0) if (gnutls_x509_crt_init(&cert) < 0)
{ {
NSLog(@"error in certificate initialization"); ASSIGN(problem, @"TLS verification: error in certificate initialization");
gnutls_x509_crt_deinit(cert);
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
cert_list = gnutls_certificate_get_peers(session, &cert_list_size); cert_list = gnutls_certificate_get_peers(session, &cert_list_size);
if (cert_list == NULL) if (cert_list == NULL)
{ {
NSLog(@"No certificate form remote end was found!"); ASSIGN(problem, @"TLS verification: no certificate from remote end!");
gnutls_x509_crt_deinit(cert);
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0) if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
{ {
NSLog(@"error parsing certificate"); ASSIGN(problem, @"TLS verification: error parsing certificate");
gnutls_x509_crt_deinit(cert);
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
@ -1889,8 +1902,12 @@ static NSMutableDictionary *credentialsCache = nil;
} }
if (NO == found) if (NO == found)
{ {
NSLog(@"The certificate's owner does not match '%@'", names); str = [NSString stringWithFormat:
@"TLS verification: certificate's owner does not match '%@'",
names];
ASSIGN(problem, str);
gnutls_x509_crt_deinit(cert); gnutls_x509_crt_deinit(cert);
if (YES == debug) NSLog(@"%@", problem);
return GNUTLS_E_CERTIFICATE_ERROR; return GNUTLS_E_CERTIFICATE_ERROR;
} }
} }