Index: src/SSLConnectionFailedException.h ================================================================== --- src/SSLConnectionFailedException.h +++ src/SSLConnectionFailedException.h @@ -20,35 +20,53 @@ * POSSIBILITY OF SUCH DAMAGE. */ #import +OF_ASSUME_NONNULL_BEGIN + @class SSLSocket; @interface SSLConnectionFailedException: OFConnectionFailedException { unsigned long _SSLError; long _verifyResult; } -@property (readonly) unsigned long SSLError; -@property (readonly) long verifyResult; +@property (readonly, nonatomic) unsigned long SSLError; +@property (readonly, nonatomic) long verifyResult; + (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port + socket: (id)socket OF_UNAVAILABLE; ++ (instancetype)exceptionWithHost: (OFString *)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo OF_UNAVAILABLE; ++ (instancetype)exceptionWithHost: (OFString *)host + port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError; + (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError verifyResult: (long)verifyResult; - initWithHost: (OFString *)host port: (uint16_t)port + socket: (SSLSocket *)socket OF_UNAVAILABLE; +- initWithHost: (OFString *)host + port: (uint16_t)port + socket: (SSLSocket *)socket + errNo: (int)errNo OF_UNAVAILABLE; +- initWithHost: (OFString *)host + port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError; - initWithHost: (OFString *)host port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError - verifyResult: (long)verifyResult; + verifyResult: (long)verifyResult OF_DESIGNATED_INITIALIZER; @end + +OF_ASSUME_NONNULL_END Index: src/SSLConnectionFailedException.m ================================================================== --- src/SSLConnectionFailedException.m +++ src/SSLConnectionFailedException.m @@ -42,10 +42,25 @@ @implementation SSLConnectionFailedException @synthesize SSLError = _SSLError, verifyResult = _verifyResult; + (instancetype)exceptionWithHost: (OFString *)host port: (uint16_t)port + socket: (id)socket +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithHost: (OFString *)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithHost: (OFString *)host + port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError { return [[[self alloc] initWithHost: host port: port @@ -67,20 +82,33 @@ verifyResult: verifyResult] autorelease]; } - initWithHost: (OFString *)host port: (uint16_t)port + socket: (id)socket +{ + OF_INVALID_INIT_METHOD +} + +- initWithHost: (OFString *)host + port: (uint16_t)port + socket: (id)socket + errNo: (int)errNo +{ + OF_INVALID_INIT_METHOD +} + +- initWithHost: (OFString *)host + port: (uint16_t)port socket: (SSLSocket *)socket SSLError: (unsigned long)SSLError { - self = [super initWithHost: host - port: port - socket: socket]; - - _SSLError = SSLError; - - return self; + return [self initWithHost: host + port: port + socket: socket + SSLError: SSLError + verifyResult: 0]; } - initWithHost: (OFString *)host port: (uint16_t)port socket: (SSLSocket *)socket Index: src/SSLInvalidCertificateException.h ================================================================== --- src/SSLInvalidCertificateException.h +++ src/SSLInvalidCertificateException.h @@ -21,16 +21,22 @@ * POSSIBILITY OF SUCH DAMAGE. */ #import #import + +OF_ASSUME_NONNULL_BEGIN @interface SSLInvalidCertificateException: OFException { OFString *_reason; } @property (readonly, nonatomic) OFString *reason; -+ exceptionWithReason: (OFString *)reason; -- initWithReason: (OFString *)reason; ++ (instancetype)exception; ++ (instancetype)exceptionWithReason: (OFString *)reason; +- init OF_UNAVAILABLE; +- initWithReason: (OFString *)reason OF_DESIGNATED_INITIALIZER; @end + +OF_ASSUME_NONNULL_END Index: src/SSLInvalidCertificateException.m ================================================================== --- src/SSLInvalidCertificateException.m +++ src/SSLInvalidCertificateException.m @@ -28,25 +28,23 @@ #import @implementation SSLInvalidCertificateException @synthesize reason = _reason; -+ exceptionWithReason: (OFString *)reason ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithReason: (OFString *)reason { return [[[self alloc] initWithReason: reason] autorelease]; } - init { - @try { - [self doesNotRecognizeSelector: _cmd]; - } @catch (id e) { - [self release]; - @throw e; - } - - abort(); + OF_INVALID_INIT_METHOD } - initWithReason: (OFString *)reason { self = [super init]; Index: src/SSLSocket.h ================================================================== --- src/SSLSocket.h +++ src/SSLSocket.h @@ -24,10 +24,12 @@ #include #import #import +OF_ASSUME_NONNULL_BEGIN + @class X509Certificate; @interface SSLSocket: OFTCPSocket { SSL *_SSL; @@ -35,14 +37,16 @@ const char *_privateKeyPassphrase; bool _certificateVerificationEnabled; bool _requestClientCertificatesEnabled; } -@property (getter=isRequestClientCertificatesEnabled) +@property (nonatomic, getter=isRequestClientCertificatesEnabled) bool requestClientCertificatesEnabled; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) + X509Certificate *peerCertificate; - initWithSocket: (OFTCPSocket *)socket; -- (void)SSL_super_close; - (OFDataArray *)channelBindingDataWithType: (OFString *)type; -- (X509Certificate *)peerCertificate; -- (void)verifyPeerCertificate; +- (nullable X509Certificate *)peerCertificate; @end + +OF_ASSUME_NONNULL_END Index: src/SSLSocket.m ================================================================== --- src/SSLSocket.m +++ src/SSLSocket.m @@ -87,10 +87,14 @@ if (mode & CRYPTO_LOCK) of_mutex_lock(&ssl_mutexes[n]); else of_mutex_unlock(&ssl_mutexes[n]); } + +@interface SSLSocket () +- (void)SSL_super_close; +@end @implementation SSLSocket @synthesize delegate = _delegate, certificateFile = _certificateFile; @synthesize privateKeyFile = _privateKeyFile; @synthesize privateKeyPassphrase = privateKeyPassphrase; @@ -442,11 +446,11 @@ - (X509Certificate *)peerCertificate { X509 *certificate = SSL_get_peer_certificate(_SSL); - if (!certificate) + if (certificate == NULL) return nil; return [[[X509Certificate alloc] initWithX509Struct: certificate] autorelease]; } Index: src/X509Certificate.h ================================================================== --- src/X509Certificate.h +++ src/X509Certificate.h @@ -24,11 +24,11 @@ #include #import #import -@class OFDictionary; +OF_ASSUME_NONNULL_BEGIN /* OIDs: */ #define OID_commonName @"2.5.4.3" #define OID_surname @"2.5.4.4" #define OID_serialNumber @"2.5.4.5" @@ -38,17 +38,20 @@ #define OID_streetAddress @"2.5.4.9" #define OID_organizationName @"2.5.4.10" #define OID_organizationalUnitName @"2.5.4.11" #define OID_SRVName @"1.3.6.1.5.5.7.8.7" + +@class OFDictionary; @interface X509OID: OFObject { OFString *_string; } -- initWithUTF8String: (const char *)string; +- init OF_UNAVAILABLE; +- initWithUTF8String: (const char *)string OF_DESIGNATED_INITIALIZER; @end @interface X509Certificate: OFObject { X509 *_certificate; @@ -55,20 +58,19 @@ OFDictionary *_issuer; OFDictionary *_subject; OFDictionary *_subjectAlternativeName; } +@property (readonly, nonatomic) OFDictionary *issuer; +@property (readonly, nonatomic) OFDictionary *subject; +@property (readonly, nonatomic) OFDictionary *subjectAlternateName; + +- init OF_UNAVAILABLE; - initWithFile: (OFString *)file; - initWithX509Struct: (X509 *)cert; -- (OFDictionary *)issuer; -- (OFDictionary *)subject; -- (OFDictionary *)subjectAlternativeName; - (bool)hasCommonNameMatchingDomain: (OFString *)domain; - (bool)hasDNSNameMatchingDomain: (OFString *)domain; - (bool)hasSRVNameMatchingDomain: (OFString *)domain service: (OFString *)service; -- (bool)X509_isAssertedDomain: (OFString *)asserted - equalDomain: (OFString *)domain; -- (OFDictionary *)X509_dictionaryFromX509Name: (X509_NAME *)name; -- (X509OID *)X509_stringFromASN1Object: (ASN1_OBJECT *)obj; -- (OFString *)X509_stringFromASN1String: (ASN1_STRING *)str; @end + +OF_ASSUME_NONNULL_END Index: src/X509Certificate.m ================================================================== --- src/X509Certificate.m +++ src/X509Certificate.m @@ -45,15 +45,32 @@ #import #import #import #import + +OF_ASSUME_NONNULL_BEGIN + +@interface X509Certificate () +- (bool)X509_isAssertedDomain: (OFString *)asserted + equalDomain: (OFString *)domain; +- (OFDictionary *)X509_dictionaryFromX509Name: (X509_NAME *)name; +- (X509OID *)X509_stringFromASN1Object: (ASN1_OBJECT *)obj; +- (OFString *)X509_stringFromASN1String: (ASN1_STRING *)str; +@end + +OF_ASSUME_NONNULL_END @implementation X509Certificate +- init +{ + OF_INVALID_INIT_METHOD +} + - initWithFile: (OFString *)path { - self = [self init]; + self = [super init]; @try { OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFDataArray *data = [OFDataArray dataArrayWithContentsOfFile: path]; @@ -73,11 +90,11 @@ return self; } - initWithX509Struct: (X509 *)certificate { - self = [self init]; + self = [super init]; @try { _certificate = X509_dup(certificate); if (_certificate == NULL) @throw [OFInitializationFailedException @@ -263,16 +280,13 @@ return ret; } - (bool)hasCommonNameMatchingDomain: (OFString *)domain { - OFString *name; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFList *CNs = [[self subject] objectForKey: OID_commonName]; - OFEnumerator *enumerator = [CNs objectEnumerator]; - while ((name = [enumerator nextObject]) != nil) { + for (OFString *name in [[self subject] objectForKey: OID_commonName]) { if ([self X509_isAssertedDomain: name equalDomain: domain]) { [pool release]; return true; } @@ -282,17 +296,14 @@ return false; } - (bool)hasDNSNameMatchingDomain: (OFString *)domain { - OFString *name; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; - OFDictionary *SANs = [self subjectAlternativeName]; - OFList *assertedNames = [SANs objectForKey: @"dNSName"]; - OFEnumerator *enumerator = [assertedNames objectEnumerator]; - while ((name = [enumerator nextObject]) != nil) { + for (OFString *name in + [[self subjectAlternativeName] objectForKey: @"dNSName"]) { if ([self X509_isAssertedDomain: name equalDomain: domain]) { [pool release]; return true; } @@ -304,24 +315,22 @@ - (bool)hasSRVNameMatchingDomain: (OFString *)domain service: (OFString *)service { size_t serviceLength; - OFString *name; OFAutoreleasePool *pool = [[OFAutoreleasePool alloc] init]; OFDictionary *SANs = [self subjectAlternativeName]; OFList *assertedNames = [[SANs objectForKey: @"otherName"] objectForKey: OID_SRVName]; - OFEnumerator *enumerator = [assertedNames objectEnumerator]; if (![service hasPrefix: @"_"]) service = [service stringByPrependingString: @"_"]; service = [service stringByAppendingString: @"."]; serviceLength = [service length]; - while ((name = [enumerator nextObject]) != nil) { + for (OFString *name in assertedNames) { if ([name hasPrefix: service]) { OFString *asserted; asserted = [name substringWithRange: of_range( serviceLength, [name length] - serviceLength)]; if ([self X509_isAssertedDomain: asserted @@ -441,13 +450,18 @@ return ret; } @end @implementation X509OID +- init +{ + OF_INVALID_INIT_METHOD +} + - initWithUTF8String: (const char *)string { - self = [self init]; + self = [super init]; @try { _string = [[OFString alloc] initWithUTF8String: string]; } @catch (id e) { [self release];