I have NSInputStream and NSOutputStream from this code
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocket(kCFAllocatorDefault, sslSocket!, &readStream, &writeStream)
if readStream != nil && writeStream != nil {
CFReadStreamSetProperty(readStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)
CFWriteStreamSetProperty(writeStream!.takeUnretainedValue(), kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
// Create strong delegate reference to stop ARC deallocating the object
inputDelegate = self
outputDelegate = self
// Now that we have a strong reference, assign the object to the stream delegates
inputStream!.delegate = inputDelegate
outputStream!.delegate = outputDelegate
// Schedule our run loops. This is needed so that we can recieve NSStreamEvents
inputStream!.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSDefaultRunLoopMode)
inputStream!.open()
outputStream!.open()
}
Issue: How do I convert those stream to SSL after it was opened ?
I tried following, but I get NSOSStatusErrorDomain
:
The operation couldn't be completed. (OSStatus error -9801)
if (sslEnable) {
let sslSettings = [
NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse,
NSString(format: kCFStreamSSLPeerName): kCFNull,
NSString(format: kCFStreamSSLIsServer): kCFBooleanTrue,
]
CFReadStreamSetProperty(inputStream, kCFStreamPropertySSLSettings, sslSettings)
CFWriteStreamSetProperty(outputStream, kCFStreamPropertySSLSettings, sslSettings)
}
As you know, NSStream
does not support connecting to a remote host on iOS natively ; you create instances of CFStream
with CFStreamCreatePairWithSocketToHost
, then bridge over to NSStream
. The code is correct.
Furthermore, you do not convert a stream to ssl
after it is opened ; you set its properties and configure the connection first, then open it.
For SSL security, NSStream defines various security-level properties [...]
You must set the property before you open the stream. Once it opens, it goes through a handshake protocol to find out what level of SSL security the other side of the connection is using.
Before you open a stream object, you might want to set security and other features for the connection to the remote host (Stream Programming Guide).
if let inputStream = inputStream, let outputStream = outputStream {
inputStream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
outputStream.schedule(in: RunLoop.main, forMode: RunLoopMode.defaultRunLoopMode)
if (sslEnable) {
inputStream.setProperty(StreamSocketSecurityLevel.tlSv1,
forKey: Stream.PropertyKey.socketSecurityLevelKey)
outputStream.setProperty(StreamSocketSecurityLevel.tlSv1,
forKey: Stream.PropertyKey.socketSecurityLevelKey)
let sslSettings = [
NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse,
NSString(format: kCFStreamSSLPeerName): kCFNull,
NSString(format: kCFStreamSSLIsServer): kCFBooleanTrue,
] as [NSString : Any]
inputStream.setProperty(sslSettings,
forKey: Stream.PropertyKey(rawValue:
kCFStreamPropertySSLSettings as String))
outputStream.setProperty(sslSettings,
forKey: Stream.PropertyKey(rawValue:
kCFStreamPropertySSLSettings as String))
}
inputStream.open()
outputStream.open()
}
This is the error for errSSLNegotiation
in SecureTransport.h
in the Security
framework
-9801 The cipher suite negotiation failed.
Maybe the server that you are trying to connect to has a really old SSL implementation or your server cipher suite configuration doesn't match the phone's configuration.
Source
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With