Search code examples
iossslnsstreamsnicfstream

setting CFStream property failing


I'm trying to set up TLS connection with SNI. Problem is that the first property setting call returns 1 indicating that it was accepted. The following two return 0, which means they didn't go through. What could be the reasoning be?

At some point I have to add my own cert to be trusted, but as far as I understand, that will be done after opening the streams, so it shouldn't be any cause here.

Also, does kCFStreamSocketSecurityLevelNegotiatedSSL support tls1.2 as there are no constants to choose that directly?

    var tempInputStream: Unmanaged<CFReadStream>?
    var tempOutputStream: Unmanaged<CFWriteStream>?

    CFStreamCreatePairWithSocketToHost(nil, address as CFStringRef, port, &tempInputStream, &tempOutputStream)

    let cfInputStream: CFReadStream = tempInputStream!.takeRetainedValue()
    let cfOutputStream: CFWriteStream = tempOutputStream!.takeRetainedValue()

//setting properties
    print(CFReadStreamSetProperty(cfInputStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelNegotiatedSSL))
    print(CFReadStreamSetProperty(cfInputStream, kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse))
    print(CFReadStreamSetProperty(cfInputStream, kCFStreamSSLPeerName, "peer.address"))


    let inputStream: NSInputStream = cfInputStream
    let outputStream: NSOutputStream = cfOutputStream

    inputStream.delegate = self
    inputStream.delegate = self

    inputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
    outputStream.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)

    inputStream.open()
    outputStream.open()

Solution

  • kCFStreamSSLValidatesCertificateChain and kCFStreamSSLPeerName are not stream properties. They are SSL Settings properties. You need to collect them all together into a dictionary and assign it to kCFStreamPropertySSLSettings:

    let ssl = [
        String(kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse, // You an probably use "false" here
        String(kCFStreamSSLPeerName): "peer.address"
    ]
    
    print(CFReadStreamSetProperty(cfInputStream, kCFStreamPropertySSLSettings, ssl))