Let -[checkCertificate] return a BOOL and a reason.

Throwing an exception there was strange.
This commit is contained in:
Jonathan Schleifer 2012-02-03 16:46:06 +01:00
parent 788a35838e
commit 1b9c63195a
3 changed files with 33 additions and 23 deletions

View file

@ -218,11 +218,15 @@
- (void)close; - (void)close;
/** /**
* \brief Checks the certificate presented by the server. * \brief Checks the certificate presented by the server and sets the specified
* pointer to the reason why the certificate is not valid
* *
* \throw SSLInvalidCertificateException Thrown if the certificate is invalid * \param reason A pointer to an OFString which is set to a reason in case the
* certificate is not valid (otherwise, it does not touch it).
* Passing NULL means the reason is not stored anywhere.
* \return Whether the certificate is valid
*/ */
- (void)checkCertificate; - (BOOL)checkCertificateAndGetReason: (OFString**)reason;
/** /**
* \brief Starts a loop handling incomming data. * \brief Starts a loop handling incomming data.

View file

@ -346,32 +346,40 @@
return streamOpen; return streamOpen;
} }
- (void)checkCertificate - (BOOL)checkCertificateAndGetReason: (OFString**)reason
{ {
X509Certificate *cert; X509Certificate *cert;
OFDictionary *SANs; OFDictionary *SANs;
BOOL serviceSpecific = NO; BOOL serviceSpecific = NO;
[sock verifyPeerCertificate]; @try {
[sock verifyPeerCertificate];
} @catch (SSLInvalidCertificateException *e) {
if (reason != NULL)
*reason = [[[e reason] copy] autorelease];
return NO;
}
cert = [sock peerCertificate]; cert = [sock peerCertificate];
SANs = [cert subjectAlternativeName]; SANs = [cert subjectAlternativeName];
if ([[SANs objectForKey: @"otherName"] if ([[SANs objectForKey: @"otherName"]
objectForKey: OID_SRVName] || objectForKey: OID_SRVName] != nil ||
[SANs objectForKey: @"dNSName"] || [SANs objectForKey: @"dNSName"] != nil ||
[SANs objectForKey: @"uniformResourceIdentifier"]) [SANs objectForKey: @"uniformResourceIdentifier"] != nil)
serviceSpecific = YES; serviceSpecific = YES;
if ([cert hasSRVNameMatchingDomain: domainToASCII if ([cert hasSRVNameMatchingDomain: domainToASCII
service: @"xmpp-client"] || service: @"xmpp-client"] ||
[cert hasDNSNameMatchingDomain: domainToASCII]) [cert hasDNSNameMatchingDomain: domainToASCII])
return; return YES;
if (serviceSpecific || if (!serviceSpecific &&
![cert hasCommonNameMatchingDomain: domainToASCII]) [cert hasCommonNameMatchingDomain: domainToASCII])
@throw [SSLInvalidCertificateException return YES;
exceptionWithClass: isa
reason: @"No matching identifier"]; return NO;
} }
- (void)sendStanza: (OFXMLElement*)element - (void)sendStanza: (OFXMLElement*)element

View file

@ -24,7 +24,6 @@
#include <assert.h> #include <assert.h>
#import <ObjFW/ObjFW.h> #import <ObjFW/ObjFW.h>
#import <ObjOpenSSL/SSLInvalidCertificateException.h>
#import "XMPPConnection.h" #import "XMPPConnection.h"
#import "XMPPJID.h" #import "XMPPJID.h"
@ -168,16 +167,15 @@ OF_APPLICATION_DELEGATE(AppDelegate)
- (void)connectionDidUpgradeToTLS: (XMPPConnection*)conn_ - (void)connectionDidUpgradeToTLS: (XMPPConnection*)conn_
{ {
@try { OFString *reason;
[conn_ checkCertificate];
} @catch (SSLInvalidCertificateException *e) { if (![conn_ checkCertificateAndGetReason: &reason]) {
OFString *answer;
[of_stdout writeString: @"Couldn't verify certificate: "]; [of_stdout writeString: @"Couldn't verify certificate: "];
[of_stdout writeFormat: @"%@\n", e]; [of_stdout writeFormat: @"%@\n", reason];
[of_stdout writeString: @"Do you want to continue [y/N]? "]; [of_stdout writeString: @"Do you want to continue [y/N]? "];
answer = [of_stdin readLine];
if (![answer hasPrefix: @"y"]) if (![[of_stdin readLine] hasPrefix: @"y"])
@throw e; [OFApplication terminateWithStatus: 1];
} }
} }