// // MQTTSSLSecurityPolicyTransport.m // MQTTClient // // Created by Christoph Krey on 06.12.15. // Copyright © 2015-2017 Christoph Krey. All rights reserved. // #import "MQTTSSLSecurityPolicyTransport.h" #import "MQTTSSLSecurityPolicyEncoder.h" #import "MQTTSSLSecurityPolicyDecoder.h" #import "MQTTLog.h" @interface MQTTSSLSecurityPolicyTransport() @property (strong, nonatomic) MQTTSSLSecurityPolicyEncoder *encoder; @property (strong, nonatomic) MQTTSSLSecurityPolicyDecoder *decoder; @end @implementation MQTTSSLSecurityPolicyTransport @synthesize state; @synthesize delegate; - (instancetype)init { self = [super init]; self.securityPolicy = nil; return self; } - (void)open { DDLogVerbose(@"[MQTTSSLSecurityPolicyTransport] open"); self.state = MQTTTransportOpening; NSError* connectError; CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)self.host, self.port, &readStream, &writeStream); CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); if (self.tls) { NSMutableDictionary *sslOptions = [[NSMutableDictionary alloc] init]; // Delegate certificates verify operation to our secure policy. // by disabling chain validation, it becomes our responsibility to verify that the host at the other end can be trusted. // the server's certificates will be verified during MQTT encoder/decoder processing. sslOptions[(NSString *)kCFStreamSSLValidatesCertificateChain] = @NO; sslOptions[(NSString *)kCFStreamSSLLevel] = self.streamSSLLevel; if (self.certificates) { sslOptions[(NSString *)kCFStreamSSLCertificates] = self.certificates; } if (!CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(sslOptions))){ connectError = [NSError errorWithDomain:@"MQTT" code:errSSLInternal userInfo:@{NSLocalizedDescriptionKey : @"Fail to init ssl input stream!"}]; } if (!CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)(sslOptions))){ connectError = [NSError errorWithDomain:@"MQTT" code:errSSLInternal userInfo:@{NSLocalizedDescriptionKey : @"Fail to init ssl output stream!"}]; } } if (!connectError) { self.encoder = [[MQTTSSLSecurityPolicyEncoder alloc] init]; CFWriteStreamSetDispatchQueue(writeStream, self.queue); self.encoder.stream = CFBridgingRelease(writeStream); self.encoder.securityPolicy = self.tls ? self.securityPolicy : nil; self.encoder.securityDomain = self.tls ? self.host : nil; self.encoder.delegate = self; if (self.voip) { [self.encoder.stream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; } [self.encoder open]; self.decoder = [[MQTTSSLSecurityPolicyDecoder alloc] init]; CFReadStreamSetDispatchQueue(readStream, self.queue); self.decoder.stream = CFBridgingRelease(readStream); self.decoder.securityPolicy = self.tls ? self.securityPolicy : nil; self.decoder.securityDomain = self.tls ? self.host : nil; self.decoder.delegate = self; if (self.voip) { [self.decoder.stream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType]; } [self.decoder open]; } else { [self close]; } } @end