From a005646054d5be773bc26d9c4d81d15cb5b17be3 Mon Sep 17 00:00:00 2001 From: Erik Date: Sat, 26 Sep 2015 16:49:34 -0400 Subject: [PATCH] bump websocket --- SocketIOClientSwift/SocketEngine.swift | 10 +- SocketIOClientSwift/WebSocket.swift | 351 ++++++++++++------------- 2 files changed, 169 insertions(+), 192 deletions(-) diff --git a/SocketIOClientSwift/SocketEngine.swift b/SocketIOClientSwift/SocketEngine.swift index d8e7020..a152cf3 100644 --- a/SocketIOClientSwift/SocketEngine.swift +++ b/SocketIOClientSwift/SocketEngine.swift @@ -191,8 +191,14 @@ public final class SocketEngine: NSObject, WebSocketDelegate { private func createWebsocketAndConnect(connect: Bool) { let wsUrl = urlWebSocket + (sid == "" ? "" : "&sid=\(sid)") - ws = WebSocket(url: NSURL(string: wsUrl)!, - cookies: cookies) + ws = WebSocket(url: NSURL(string: wsUrl)!) + + if cookies != nil { + let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(cookies!) + for (key, value) in headers { + ws?.headers[key] = value + } + } if extraHeaders != nil { for (headerName, value) in extraHeaders! { diff --git a/SocketIOClientSwift/WebSocket.swift b/SocketIOClientSwift/WebSocket.swift index 016be75..7e4fc7d 100644 --- a/SocketIOClientSwift/WebSocket.swift +++ b/SocketIOClientSwift/WebSocket.swift @@ -8,6 +8,7 @@ import Foundation import CoreFoundation +import Security public protocol WebSocketDelegate: class { func websocketDidConnect(socket: WebSocket) @@ -93,19 +94,18 @@ public class WebSocket : NSObject, NSStreamDelegate { public var headers = Dictionary() public var voipEnabled = false public var selfSignedSSL = false - private var security: Security? + private var security: SSLSecurity? + public var enabledSSLCipherSuites: [SSLCipherSuite]? public var isConnected :Bool { return connected } - - private var cookies:[NSHTTPCookie]? private var url: NSURL private var inputStream: NSInputStream? private var outputStream: NSOutputStream? private var isRunLoop = false private var connected = false private var isCreated = false - private var writeQueue: NSOperationQueue? + private var writeQueue = NSOperationQueue() private var readStack = Array() private var inputQueue = Array() private var fragBuffer: NSData? @@ -115,13 +115,8 @@ public class WebSocket : NSObject, NSStreamDelegate { //init the websocket with a url public init(url: NSURL) { self.url = url + writeQueue.maxConcurrentOperationCount = 1 } - - public convenience init(url: NSURL, cookies:[NSHTTPCookie]?) { - self.init(url: url) - self.cookies = cookies - } - //used for setting protocols. public convenience init(url: NSURL, protocols: Array) { self.init(url: url) @@ -133,23 +128,14 @@ public class WebSocket : NSObject, NSStreamDelegate { if isCreated { return } - - dispatch_async(queue, { [weak self] in - guard let weakSelf = self else { - return - } - - weakSelf.didDisconnect = false - }) + dispatch_async(queue,{ [weak self] in + self?.didDisconnect = false + }) dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), { [weak self] in - guard let weakSelf = self else { - return - } - - weakSelf.isCreated = true - weakSelf.createHTTPRequest() - weakSelf.isCreated = false - }) + self?.isCreated = true + self?.createHTTPRequest() + self?.isCreated = false + }) } ///disconnect from the websocket server @@ -188,30 +174,22 @@ public class WebSocket : NSObject, NSStreamDelegate { port = 80 } } - - if self.cookies != nil { - let headers = NSHTTPCookie.requestHeaderFieldsWithCookies(self.cookies!) - for (key, value) in headers { - self.addHeader(urlRequest, key: key as String, val: value as String) - } - } - - self.addHeader(urlRequest, key: headerWSUpgradeName, val: headerWSUpgradeValue) - self.addHeader(urlRequest, key: headerWSConnectionName, val: headerWSConnectionValue) + addHeader(urlRequest, key: headerWSUpgradeName, val: headerWSUpgradeValue) + addHeader(urlRequest, key: headerWSConnectionName, val: headerWSConnectionValue) if let protocols = optionalProtocols { - self.addHeader(urlRequest, key: headerWSProtocolName, val: protocols.joinWithSeparator(",")) + addHeader(urlRequest, key: headerWSProtocolName, val: protocols.joinWithSeparator(",")) } - self.addHeader(urlRequest, key: headerWSVersionName, val: headerWSVersionValue) - self.addHeader(urlRequest, key: headerWSKeyName, val: self.generateWebSocketKey()) - self.addHeader(urlRequest, key: headerOriginName, val: url.absoluteString) - self.addHeader(urlRequest, key: headerWSHostName, val: "\(url.host!):\(port!)") + addHeader(urlRequest, key: headerWSVersionName, val: headerWSVersionValue) + addHeader(urlRequest, key: headerWSKeyName, val: generateWebSocketKey()) + addHeader(urlRequest, key: headerOriginName, val: url.absoluteString) + addHeader(urlRequest, key: headerWSHostName, val: "\(url.host!):\(port!)") for (key,value) in headers { - self.addHeader(urlRequest, key: key, val: value) + addHeader(urlRequest, key: key, val: value) + } + if let cfHTTPMessage = CFHTTPMessageCopySerializedMessage(urlRequest) { + let serializedRequest = cfHTTPMessage.takeRetainedValue() + initStreamsWithData(serializedRequest, Int(port!)) } - - - let serializedRequest: NSData = CFHTTPMessageCopySerializedMessage(urlRequest)!.takeRetainedValue() - self.initStreamsWithData(serializedRequest, Int(port!)) } //Add a header to the CFHTTPMessage by using the NSString bridges to CFString private func addHeader(urlRequest: CFHTTPMessage,key: String, val: String) { @@ -244,31 +222,48 @@ public class WebSocket : NSObject, NSStreamDelegate { CFStreamCreatePairWithSocketToHost(nil, h, UInt32(port), &readStream, &writeStream) inputStream = readStream!.takeRetainedValue() outputStream = writeStream!.takeRetainedValue() - - inputStream!.delegate = self - outputStream!.delegate = self + guard let inStream = inputStream, let outStream = outputStream else { return } + inStream.delegate = self + outStream.delegate = self if url.scheme == "wss" || url.scheme == "https" { - inputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey) - outputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey) + inStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey) + outStream.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, forKey: NSStreamSocketSecurityLevelKey) } else { certValidated = true //not a https session, so no need to check SSL pinning } - if self.voipEnabled { - inputStream!.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType) - outputStream!.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType) + if voipEnabled { + inStream.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType) + outStream.setProperty(NSStreamNetworkServiceTypeVoIP, forKey: NSStreamNetworkServiceType) } - if self.selfSignedSSL { + if selfSignedSSL { let settings: Dictionary = [kCFStreamSSLValidatesCertificateChain: NSNumber(bool:false), kCFStreamSSLPeerName: kCFNull] - inputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String) - outputStream!.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String) + inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String) + outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as String) + } + if let cipherSuites = self.enabledSSLCipherSuites { + if let sslContextIn = CFReadStreamCopyProperty(inputStream, kCFStreamPropertySSLContext) as! SSLContextRef?, + sslContextOut = CFWriteStreamCopyProperty(outputStream, kCFStreamPropertySSLContext) as! SSLContextRef? { + let resIn = SSLSetEnabledCiphers(sslContextIn, cipherSuites, cipherSuites.count) + let resOut = SSLSetEnabledCiphers(sslContextOut, cipherSuites, cipherSuites.count) + if (resIn != errSecSuccess) { + let error = self.errorWithDetail("Error setting ingoing cypher suites", code: UInt16(resIn)) + disconnectStream(error) + return + } + if (resOut != errSecSuccess) { + let error = self.errorWithDetail("Error setting outgoing cypher suites", code: UInt16(resOut)) + disconnectStream(error) + return + } + } } isRunLoop = true - inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) - outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) - inputStream!.open() - outputStream!.open() + inStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) + outStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) + inStream.open() + outStream.open() let bytes = UnsafePointer(data.bytes) - outputStream!.write(bytes, maxLength: data.length) + outStream.write(bytes, maxLength: data.length) while(isRunLoop) { NSRunLoop.currentRunLoop().runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture() as NSDate) } @@ -283,8 +278,7 @@ public class WebSocket : NSObject, NSStreamDelegate { if sec.isValid(trust as! SecTrustRef, domain: domain as! String?) { certValidated = true } else { - let error = self.errorWithDetail("Invalid SSL certificate", code: 1) - doDisconnect(error) + let error = errorWithDetail("Invalid SSL certificate", code: 1) disconnectStream(error) return } @@ -302,9 +296,7 @@ public class WebSocket : NSObject, NSStreamDelegate { } //disconnect the stream object private func disconnectStream(error: NSError?) { - if writeQueue != nil { - writeQueue!.waitUntilAllOperationsAreFinished() - } + writeQueue.waitUntilAllOperationsAreFinished() if let stream = inputStream { stream.removeFromRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode) stream.close() @@ -316,7 +308,7 @@ public class WebSocket : NSObject, NSStreamDelegate { outputStream = nil isRunLoop = false certValidated = false - self.doDisconnect(error) + doDisconnect(error) connected = false } @@ -329,7 +321,7 @@ public class WebSocket : NSObject, NSStreamDelegate { if !connected { let status = processHTTP(buffer, bufferLen: length) if !status { - self.doDisconnect(self.errorWithDetail("Invalid HTTP upgrade", code: 1)) + doDisconnect(errorWithDetail("Invalid HTTP upgrade", code: 1)) } } else { var process = false @@ -348,7 +340,7 @@ public class WebSocket : NSObject, NSStreamDelegate { if inputQueue.count > 0 { let data = inputQueue[0] var work = data - if (fragBuffer != nil) { + if fragBuffer != nil { let combine = NSMutableData(data: fragBuffer!) combine.appendData(data) work = combine @@ -378,17 +370,18 @@ public class WebSocket : NSObject, NSStreamDelegate { } if totalSize > 0 { if validateResponse(buffer, bufferLen: totalSize) { - dispatch_async(queue, { - self.connected = true - if let connectBlock = self.onConnect { + dispatch_async(queue,{ [weak self] in + guard let s = self else { return } + s.connected = true + if let connectBlock = s.onConnect { connectBlock() } - self.delegate?.websocketDidConnect(self) - }) + s.delegate?.websocketDidConnect(s) + }) totalSize += 1 //skip the last \n let restSize = bufferLen - totalSize if restSize > 0 { - processRawMessage((buffer+totalSize), bufferLen: restSize) + processRawMessage((buffer+totalSize),bufferLen: restSize) } return true } @@ -403,11 +396,12 @@ public class WebSocket : NSObject, NSStreamDelegate { if CFHTTPMessageGetResponseStatusCode(response) != 101 { return false } - let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) - let headers:NSDictionary? = cfHeaders?.takeRetainedValue() - let acceptKey = headers?[headerWSAcceptName] as! NSString - if acceptKey.length > 0 { - return true + if let cfHeaders = CFHTTPMessageCopyAllHeaderFields(response) { + let headers = cfHeaders.takeRetainedValue() as NSDictionary + let acceptKey = headers[headerWSAcceptName] as! NSString + if acceptKey.length > 0 { + return true + } } return false } @@ -443,8 +437,7 @@ public class WebSocket : NSObject, NSStreamDelegate { var offset = 2 if((isMasked > 0 || (RSVMask & buffer[0]) > 0) && receivedOpcode != OpCode.Pong.rawValue) { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("masked and rsv data is not currently supported", code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("masked and rsv data is not currently supported", code: errCode)) writeError(errCode) return } @@ -452,15 +445,13 @@ public class WebSocket : NSObject, NSStreamDelegate { if !isControlFrame && (receivedOpcode != OpCode.BinaryFrame.rawValue && receivedOpcode != OpCode.ContinueFrame.rawValue && receivedOpcode != OpCode.TextFrame.rawValue && receivedOpcode != OpCode.Pong.rawValue) { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("unknown opcode: \(receivedOpcode)", code: errCode)) writeError(errCode) return } if isControlFrame && isFin == 0 { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("control frames can't be fragmented", code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("control frames can't be fragmented", code: errCode)) writeError(errCode) return } @@ -486,8 +477,7 @@ public class WebSocket : NSObject, NSStreamDelegate { } } } - let error = self.errorWithDetail("connection closed by server", code: code) - self.doDisconnect(error) + doDisconnect(errorWithDetail("connection closed by server", code: code)) writeError(code) return } @@ -521,10 +511,13 @@ public class WebSocket : NSObject, NSStreamDelegate { data = NSData(bytes: UnsafePointer((buffer+offset)), length: Int(len)) } if receivedOpcode == OpCode.Pong.rawValue { - dispatch_async(queue, { - self.onPong?() - self.pongDelegate?.websocketDidReceivePong(self) - }) + dispatch_async(queue,{ [weak self] in + guard let s = self else { return } + if let pongBlock = s.onPong { + pongBlock() + } + s.pongDelegate?.websocketDidReceivePong(s) + }) let step = Int(offset+numericCast(len)) let extra = bufferLen-step @@ -539,8 +532,7 @@ public class WebSocket : NSObject, NSStreamDelegate { } if isFin == 0 && receivedOpcode == OpCode.ContinueFrame.rawValue && response == nil { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("continue frame before a binary or text frame", code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("continue frame before a binary or text frame", code: errCode)) writeError(errCode) return } @@ -548,9 +540,8 @@ public class WebSocket : NSObject, NSStreamDelegate { if(response == nil) { if receivedOpcode == OpCode.ContinueFrame.rawValue { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("first frame can't be a continue frame", - code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("first frame can't be a continue frame", + code: errCode)) writeError(errCode) return } @@ -564,9 +555,8 @@ public class WebSocket : NSObject, NSStreamDelegate { response!.bytesLeft = Int(dataLength) } else { let errCode = CloseCode.ProtocolError.rawValue - let error = self.errorWithDetail("second and beyond of fragment message must be a continue frame", - code: errCode) - self.doDisconnect(error) + doDisconnect(errorWithDetail("second and beyond of fragment message must be a continue frame", + code: errCode)) writeError(errCode) return } @@ -608,24 +598,28 @@ public class WebSocket : NSObject, NSStreamDelegate { dequeueWrite(data, code: OpCode.Pong) } else if response.code == .TextFrame { let str: NSString? = NSString(data: response.buffer!, encoding: NSUTF8StringEncoding) - - if let str = str as String? { - dispatch_async(queue, { - self.onText?(str) - self.delegate?.websocketDidReceiveMessage(self, text: str) - }) - } else { + if str == nil { writeError(CloseCode.Encoding.rawValue) return false } + + dispatch_async(queue,{ [weak self] in + guard let s = self else { return } + if let textBlock = s.onText { + textBlock(str! as String) + } + s.delegate?.websocketDidReceiveMessage(s, text: str! as String) + }) } else if response.code == .BinaryFrame { let data = response.buffer! //local copy so it is perverse for writing - dispatch_async(queue) { - self.onData?(data) - self.delegate?.websocketDidReceiveData(self, data: data) - } + dispatch_async(queue,{ [weak self] in + guard let s = self else { return } + if let dataBlock = s.onData { + dataBlock(data) + } + s.delegate?.websocketDidReceiveData(s, data: data) + }) } - readStack.removeLast() return true } @@ -648,31 +642,18 @@ public class WebSocket : NSObject, NSStreamDelegate { } ///used to write things to the stream private func dequeueWrite(data: NSData, code: OpCode) { - if writeQueue == nil { - writeQueue = NSOperationQueue() - writeQueue!.maxConcurrentOperationCount = 1 + if !isConnected { + return } - writeQueue!.addOperationWithBlock { + writeQueue.addOperationWithBlock { [weak self] in //stream isn't ready, let's wait - var tries = 0; - while self.outputStream == nil || !self.connected { - if(tries < 5) { - sleep(1); - } else { - break; - } - tries++; - } - if !self.connected { - return - } + guard let s = self else { return } var offset = 2 - UINT16_MAX let bytes = UnsafeMutablePointer(data.bytes) let dataLength = data.length - let frame = NSMutableData(capacity: dataLength + self.MaxFrameSize) + let frame = NSMutableData(capacity: dataLength + s.MaxFrameSize) let buffer = UnsafeMutablePointer(frame!.mutableBytes) - buffer[0] = self.FinMask | code.rawValue + buffer[0] = s.FinMask | code.rawValue if dataLength < 126 { buffer[1] = CUnsignedChar(dataLength) } else if dataLength <= Int(UInt16.max) { @@ -686,7 +667,7 @@ public class WebSocket : NSObject, NSStreamDelegate { sizeBuffer[0] = UInt64(dataLength).bigEndian offset += sizeof(UInt64) } - buffer[1] |= self.MaskMask + buffer[1] |= s.MaskMask let maskKey = UnsafeMutablePointer(buffer + offset) SecRandomCopyBytes(kSecRandomDefault, Int(sizeof(UInt32)), maskKey) offset += sizeof(UInt32) @@ -697,23 +678,24 @@ public class WebSocket : NSObject, NSStreamDelegate { } var total = 0 while true { - if self.outputStream == nil { + if !s.isConnected { break } + guard let outStream = s.outputStream else { break } let writeBuffer = UnsafePointer(frame!.bytes+total) - let len = self.outputStream?.write(writeBuffer, maxLength: offset-total) - if len == nil || len! < 0 { + let len = outStream.write(writeBuffer, maxLength: offset-total) + if len < 0 { var error: NSError? - if let streamError = self.outputStream?.streamError { + if let streamError = outStream.streamError { error = streamError } else { let errCode = InternalErrorCode.OutputStreamWriteError.rawValue - error = self.errorWithDetail("output stream error during write", code: errCode) + error = s.errorWithDetail("output stream error during write", code: errCode) } - self.doDisconnect(error) + s.doDisconnect(error) break } else { - total += len! + total += len } if total >= offset { break @@ -725,31 +707,20 @@ public class WebSocket : NSObject, NSStreamDelegate { ///used to preform the disconnect delegate private func doDisconnect(error: NSError?) { - if !self.didDisconnect { - dispatch_async(queue) { - self.didDisconnect = true - - self.onDisconnect?(error) - self.delegate?.websocketDidDisconnect(self, error: error) - } + if !didDisconnect { + dispatch_async(queue,{ [weak self] in + guard let s = self else { return } + s.didDisconnect = true + if let disconnect = s.onDisconnect { + disconnect(error) + } + s.delegate?.websocketDidDisconnect(s, error: error) + }) } } } -////////////////////////////////////////////////////////////////////////////////////////////////// -// -// Security.swift -// Starscream -// -// Created by Dalton Cherry on 5/16/15. -// Copyright (c) 2015 Vluxe. All rights reserved. -// -////////////////////////////////////////////////////////////////////////////////////////////////// - -import Foundation -import Security - private class SSLCert { var certData: NSData? var key: SecKeyRef? @@ -757,9 +728,9 @@ private class SSLCert { /** Designated init for certificates - :param: data is the binary data of the certificate + - parameter data: is the binary data of the certificate - :returns: a representation security object to be used with + - returns: a representation security object to be used with */ init(data: NSData) { self.certData = data @@ -768,17 +739,17 @@ private class SSLCert { /** Designated init for public keys - :param: key is the public key to be used + - parameter key: is the public key to be used - :returns: a representation security object to be used with + - returns: a representation security object to be used with */ init(key: SecKeyRef) { self.key = key } } -private class Security { - private var validatedDN = true //should the domain name be validated? +private class SSLSecurity { + var validatedDN = true //should the domain name be validated? var isReady = false //is the key processing done? var certificates: [NSData]? //the certificates @@ -788,11 +759,11 @@ private class Security { /** Use certs from main app bundle - :param: usePublicKeys is to specific if the publicKeys or certificates should be used for SSL pinning validation + - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation - :returns: a representation security object to be used with + - returns: a representation security object to be used with */ - private convenience init(usePublicKeys: Bool = false) { + convenience init(usePublicKeys: Bool = false) { let paths = NSBundle.mainBundle().pathsForResourcesOfType("cer", inDirectory: ".") var collect = Array() for path in paths { @@ -806,12 +777,12 @@ private class Security { /** Designated init - :param: keys is the certificates or public keys to use - :param: usePublicKeys is to specific if the publicKeys or certificates should be used for SSL pinning validation + - parameter keys: is the certificates or public keys to use + - parameter usePublicKeys: is to specific if the publicKeys or certificates should be used for SSL pinning validation - :returns: a representation security object to be used with + - returns: a representation security object to be used with */ - private init(certs: [SSLCert], usePublicKeys: Bool) { + init(certs: [SSLCert], usePublicKeys: Bool) { self.usePublicKeys = usePublicKeys if self.usePublicKeys { @@ -843,12 +814,12 @@ private class Security { /** Valid the trust and domain name. - :param: trust is the serverTrust to validate - :param: domain is the CN domain to validate + - parameter trust: is the serverTrust to validate + - parameter domain: is the CN domain to validate - :returns: if the key was successfully validated + - returns: if the key was successfully validated */ - private func isValid(trust: SecTrustRef, domain: String?) -> Bool { + func isValid(trust: SecTrustRef, domain: String?) -> Bool { var tries = 0 while(!self.isReady) { @@ -912,14 +883,14 @@ private class Security { /** Get the public key from a certificate data - :param: data is the certificate to pull the public key from + - parameter data: is the certificate to pull the public key from - :returns: a public key + - returns: a public key */ func extractPublicKey(data: NSData) -> SecKeyRef? { let possibleCert = SecCertificateCreateWithData(nil,data) if let cert = possibleCert { - return extractPublicKeyFromCert(cert,policy: SecPolicyCreateBasicX509()) + return extractPublicKeyFromCert(cert, policy: SecPolicyCreateBasicX509()) } return nil } @@ -927,16 +898,16 @@ private class Security { /** Get the public key from a certificate - :param: data is the certificate to pull the public key from + - parameter data: is the certificate to pull the public key from - :returns: a public key + - returns: a public key */ func extractPublicKeyFromCert(cert: SecCertificate, policy: SecPolicy) -> SecKeyRef? { - let possibleTrust = UnsafeMutablePointer.alloc(1) - SecTrustCreateWithCertificates( cert, policy, possibleTrust) - if let trust = possibleTrust.memory { + var possibleTrust: SecTrust? + SecTrustCreateWithCertificates(cert, policy, &possibleTrust) + if let trust = possibleTrust { var result: SecTrustResultType = 0 - SecTrustEvaluate(trust,&result) + SecTrustEvaluate(trust, &result) return SecTrustCopyPublicKey(trust) } return nil @@ -945,9 +916,9 @@ private class Security { /** Get the certificate chain for the trust - :param: trust is the trust to lookup the certificate chain for + - parameter trust: is the trust to lookup the certificate chain for - :returns: the certificate chain for the trust + - returns: the certificate chain for the trust */ func certificateChainForTrust(trust: SecTrustRef) -> Array { var collect = Array() @@ -961,9 +932,9 @@ private class Security { /** Get the public key chain for the trust - :param: trust is the trust to lookup the certificate chain and extract the public keys + - parameter trust: is the trust to lookup the certificate chain and extract the public keys - :returns: the public keys from the certifcate chain for the trust + - returns: the public keys from the certifcate chain for the trust */ func publicKeyChainForTrust(trust: SecTrustRef) -> Array { var collect = Array()