SSL/TLS Add-in for BlueSocket using Secure Transport and OpenSSL

Overview

APIDoc Build Status - Master macOS iOS Linux Apache 2 Slack Status

BlueSSLService

SSL/TLS Add-in framework for BlueSocket in Swift using the Swift Package Manager. Works on supported Apple platforms (using Secure Transport) and on Linux (using OpenSSL).

Prerequisites

Swift

  • Swift Open Source swift-4.0.0-RELEASE toolchain (Minimum REQUIRED for latest release)
  • Swift Open Source swift-4.2-RELEASE toolchain (Recommended)
  • Swift toolchain included in Xcode Version 10.0 (10A255) or higher.

macOS

  • macOS 10.11.6 (El Capitan) or higher.
  • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
  • Xcode Version 10.0 (10A255) or higher using the included toolchain (Recommended).
  • Secure Transport is provided by macOS.

iOS

  • iOS 10.0 or higher
  • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
  • Xcode Version 10.0 (10A255) or higher using the included toolchain (Recommended).
  • Secure Transport is provided by iOS.

Linux

  • Ubuntu 16.04 (or 16.10 but only tested on 16.04) and 18.04.
  • One of the Swift Open Source toolchain listed above.
  • OpenSSL is provided by the distribution. Note: 1.0.x, 1.1.x and later releases of OpenSSL are supported.
  • The appropriate libssl-dev package is required to be installed when building.

Other Platforms

  • BlueSSLService is NOT supported on watchOS since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
  • BlueSSLService should work on tvOS but has NOT been tested.

Note: See Package.swift for details.

Build

To build SSLService from the command line:

% cd <path-to-clone>
% swift build

Testing

To run the supplied unit tests for SSLService from the command line:

% cd <path-to-clone>
% swift build
% swift test

Using BlueSSLService

Before starting

The first you need to do is import both the Socket and SSLService frameworks. This is done by the following:

import Socket
import SSLService

Creating the Configuration

Both clients and server require at a minimum the following configuration items:

  • CA Certficate (either caCertificateFile or caCertificateDirPath)
  • Application certificate (certificateFilePath)
  • Private Key file (keyFilePath)

or

  • Certificate Chain File (chainFilePath)

or, if using self-signed certificates:

  • Application certificate (certificateFilePath)
  • Private Key file (keyFilePath)

or, if running on Linux (for now),

  • A string containing a PEM formatted certificate

or, if running on macOS:

  • Certificate Chain File (chainFilePath) in PKCS12 format

or,

  • No certificate at all.

BlueSSLService provides five ways to create a Configuration supporting the scenarios above. Only the last version is supported on Apple platforms. On Linux, ALL versions are supported. This is due to the limits imposed on the current implementation of Apple Secure Transport.

  • init() - This API allows for the creation of default configuration. This is equivalent to calling the next initializer without changing any parameters.
  • init(withCipherSuite cipherSuite: String? = nil, clientAllowsSelfSignedCertificates: Bool = true) - This API allows for the creation of configuration that does not contain a backing certificate or certificate chain. You can optionally provide a cipherSuite and decide whether to allow, when in client mode, use of self-signed certificates by the server.
  • init(withCACertificatePath caCertificateFilePath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) - This API allows you to create a configuration using a self contained Certificate Authority (CA) file. The second parameter is the path to the Certificate file to be used by application to establish the connection. The next parameter is the path to the Private Key file used by application corresponding to the Public Key in the Certificate. If you're using self-signed certificates, set the last parameter to true.
  • init(withCACertificateDirectory caCertificateDirPath: String?, usingCertificateFile certificateFilePath: String?, withKeyFile keyFilePath: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) - This API allows you to create a configuration using a directory of Certificate Authority (CA) files. These CA certificates must be hashed using the Certificate Tool provided by OpenSSL. The following parameters are identical to the previous API.
  • init(withPEMCertificateString certificateString: String, usingSelfSignedCerts selfSigned: Bool = true, cipherSuite: String? = nil) - This API used when supplying a PEM formatted certificate presented as a String. NOTE: At present, this API is only available on Linux.
  • init(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true, clientAllowsSelfSignedCertificates: Bool = false, cipherSuite: String? = nil) - This API allows you to create a configuration using a single Certificate Chain File (see note 2 below). Add an optional password (if required) using the third parameter. Set the third parameter to true if the certificates you are using are self-signed, otherwise set it to false. If configuring a client and you want that client to be able to connect to servers using self-signed certificates, set the fourth parameter to true.

Note 1: All Certificate and Private Key files must be PEM format. If supplying a certificate via a String, it must be PEM formatted.

Note 2: If using a certificate chain file, the certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA.

Note 3: For the first two versions of the API, if your Private key is included in your certificate file, you can omit this parameter and the API will use the same file name as specified for the certificate file.

Note 4: If you desire to customize the cipher suite used, you can do so by specifying the cipherSuite parameter when using one of the above initializers. If not specified, the default value is set to DEFAULT on Linux. On macOS, setting of this parameter is currently not supported and attempting to set it will result in unpredictable results. See the example below.

Note 5: If you're running on macOS, you must use the last form of init for the Configuration and provide a certificate chain file in PKCS12 format, supplying a password if needed.

Example

The following illustrates creating a configuration (on Linux) using the second form of the API above using a self-signed certificate file as the key file and not supplying a certificate chain file. It also illustrates setting the cipher suite to ALL from the default:

import SSLService

...

let myCertPath = "/opt/myApp/config/myCertificate.pem"
let myKeyPath = "/opt/myApp/config/myKeyFile.pem"

let myConfig = SSLService.Configuration(withCACertificateDirectory: nil, usingCertificateFile: myCertPath, withKeyFile: myKeyFile)

myConfig.cipherSuite = "ALL"

...

Note: This example takes advantage of the default parameters available on the SSLService.Configuration.init function. Also, changing of the cipher suite on macOS is currently not supported.

Creating and using the SSLService

The following API is used to create the SSLService:

  • init?(usingConfiguration config: Configuration) throws - This will create an instance of the SSLService using a previously created Configuration.

Once the SSLService is created, it can applied to a previously created Socket instance that's just been created. This needs to be done before using the Socket. The following code snippet illustrates how to do this (again using Linux). Note: Exception handling omitted for brevity.

import Socket
import SSLService

...

// Create the configuration...
let myCertPath = "/opt/myApp/config/myCertificate.pem"
let myKeyPath = "/opt/myApp/config/myKeyFile.pem"

let myConfig = SSLService.Configuration(withCACertificateDirectory: nil, usingCertificateFile: myCertPath, withKeyFile: myKeyFile)

// Create the socket...
var socket = try Socket.create()
guard let socket = socket else {
  fatalError("Could not create socket.")
}

// Create and attach the SSLService to the socket...
//  - Note: if you're going to be using the same 
//          configuration over and over, it'd be 
//          better to create it in the beginning 
//          as `let` constant.
socket.delegate = try SSLService(usingConfiguration: myConfig)

// Start listening...
try socket.listen(on: 1337)

The example above creates a SSL server socket. Replacing the socket.listen function with a socket.connect would result in an SSL client being created as illustrated below:

// Connect to the server...
try socket.connect(to: "someplace.org", port: 1337)

SSLService handles all the negotiation and setup for the secure transfer of data. The determining factor for whether or not a Socket is setup as a server or client Socket is API which is used to initiate a connection. listen() will cause the Socket to be setup as a server socket. Calling connect() results a client setup.

Extending Connection Verification

SSLService provides a callback mechanism should you need to specify additional verification logic. After creating the instance of SSLService, you can set the instance variable verifyCallback. This instance variable has the following signature:

public var verifyCallback: ((_ service: SSLService) -> (Bool, String?))? = nil

Setting this callback is not required. It defaults to nil unless set. The first parameter passed to your callback is the instance of SSLService that has this callback. This will allow you to access the public members of the SSLService instance in order to do additional verification. Upon completion, your callback should return a tuple. The first value is a Bool indicating the sucess or failure of the routine. The second value is an optional String value used to provide a description in the case where verification failed. In the event of callback failure, an exception will be thrown by the internal verification function. Important Note: To effectively use this callback requires knowledge of the platforms underlying secure transport service, Apple Secure Transport on supported Apple platforms and OpenSSL on Linux.

Skipping Connection Verification

If desired, SSLService can skip the connection verification. To accomplish this, set the property skipVerification to true after creating the SSLService instance. However, if the verifyCallback property (described above) is set, that callback will be called regardless of this setting. The default for property is false. It is NOT recommended that you skip the connection verification in a production environment unless you are providing verification via the verificationCallback.

Community

We love to talk server-side Swift and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. Full license text is available in LICENSE.

Comments
  • Feature request: let client compare self-signed server cert against local embedded version

    Feature request: let client compare self-signed server cert against local embedded version

    Added an optional URL with a path to a local DER-encocded certificate. When allowing self-signed certificates, the embedded certificate is loaded as an Anchor Certificate and validated using SecTrustEvaluateWithError()

    Description

    For the user, the only interface change is an optional URL in the Configuration init() method. If not set, the previous behavior is maintained. When the URL is set to a file, and the user has allowed self-signed certificates and is a client, then during the SSLHandshake the server presented trust is validated against the embedded certificate. The certificate must be a DER encoded X.509 certificate.

    Motivation and Context

    I am using BlueSSLService on iOS to connect securely to a server that uses its own root certificate, but I would like to validate the certificate. Previously, you can only accept any server supplied certificate, or the server certificate must be trusted by iOS. (There's no way to programmatically add the certificate to iOS keychain, you must go through a process to have the user install from a browser). If I have the public certificate of the server embedded in the app, I can use this feature to validate it.

    How Has This Been Tested?

    This is an iOS feature only - not implemented on Linux. I verified that when the URL is set to nil, the behavior is unchanged - I can successfully connect to my server when self-signed is true, and I get an errSSLXCertChainInvalid error when self-signed is false. If I embed by server certificate in the app and load it as follows

    let path = Bundle.main.url(forResource: "cert", withExtension: ".der") Then it successfully establishes the SSL connection. If I use a different (dummy) certificate, I again get the errSSLXCertChainInvalid error.

    Note that in order to compile I needed to use

    `swift build -Xswiftc "-target" -Xswiftc "x86_64-apple-macosx10.14"

    because SecTrustEvaluateWithError is a 10.14 feature.

    Checklist:

    • [ ] I have submitted a CLA form
    • [ ] If applicable, I have updated the documentation accordingly.
    • [ ] If applicable, I have added tests to cover my changes.
    opened by kkieffer 25
  • Take TLS Certificates by string

    Take TLS Certificates by string

    Right now the library assumes a file that contains the certificate. It would be helpful to have the library also take a String that's Base64 encoded, as well. Bluemix users will receive a Base64 string for their certificate through the Bluemix environment variables to be used to connect with MongoDB, for instance.

    wontfix 
    opened by rfdickerson 25
  • Connection established, but everythings frozen

    Connection established, but everythings frozen

    Hi

    I got a connection between my server and client using a key chain, the server says the user is signed in, but the app is frozen completely.

    The console just gives me..

    subsystem: com.apple.securityd, category: SecError, enable_level: 0, persist_level: 0, default_ttl: 0, info_ttl: 0, debug_ttl: 0, generate_symptoms: 0, enable_oversize: 0, privacy_setting: 2, enable_private_data: 0

    but i think thats just xcode 8...

    It doenst actually crash, its in some kind of frozen state.

    If the server cancels the connection while "connected but frozen" i actually get a console output saying : Error code: -9806, ERROR: SSLHandshake, code: -9806, reason: errSSLClosedAbort

    App still frozen

    I am really out of any ideas now.. Any idea what went wrong?

    EDIT: i debuged my project and came to the conclusion that the app fleezes at this spot in SSLService.swift:

    
    private func prepareConnection(socket: Socket) throws {
    
    ..
    
    repeat {
    
                status = SSLHandshake(sslContext)
    
            } while status == errSSLWouldBlock
    
    ...
    
    
    opened by Liquidmasl 25
  • SSL accept hang with badly behaved connections

    SSL accept hang with badly behaved connections

    Detail in this Kitura issue: https://github.com/IBM-Swift/Kitura/issues/1143

    An incoming connection that establishes a TCP session but then sends no data will block the server from accepting connections indefinitely.

    Steps to recreate:

    • Start the server, make some SSL requests (demonstrate it is functional)
    • Connect a rogue client, eg: telnet localhost 8443 and leave it doing nothing
    • Try to make further requests. The server appears to be unresponsive

    The problem seems to be that SSL_accept blocks, expecting to read the start of an SSL handshake from the client, which will never time out or allow the server to continue accepting connections. In the Kitura issue above, we block here: https://github.com/IBM-Swift/BlueSSLService/blob/335495c857b7062ecf7e228d8e021d0f7d51c5c9/Sources/SSLService.swift#L493

    opened by djones6 15
  • App Transport Security

    App Transport Security

    It looks like the Apple App Transport Security list of ciphers are not supported currently. By default App Transport Security is enabled and requires the following list of ciphers that support PFS.

    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
    

    I built a Kitura-1.6.1 service on Ubuntu-14.01 and using nmap probe I get the below list of ciphers. Trying to connect using URLSession reports a "no shared ciphers available" error.

    |   TLSv1.2:
    |     ciphers:
    |       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
    |       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
    |       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
    |       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
    |       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
    |       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
    |       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
    |       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
    |       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
    |       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
    |       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - C
    |       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - C
    |       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
    

    I can't seem to find any stack overflow or github issues related to this. Is this a new bug or am i just missing something obvious ?

    opened by samuelnair 12
  • OpenSSL v1.1.0 compatibility issues

    OpenSSL v1.1.0 compatibility issues

    I'm getting the following errors, on Fedora26, which uses OpenSSL v1.1.0:

    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:318:54: error: use of undeclared type 'SSL'
                    public private(set) var cSSL: UnsafeMutablePointer<SSL>? = nil
                                                                       ^~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:322:49: error: use of undeclared type 'SSL_METHOD'
                    public private(set) var method: UnsafePointer<SSL_METHOD>? = nil
                                                                  ^~~~~~~~~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:325:57: error: use of undeclared type 'SSL_CTX'
                    public private(set) var context: UnsafeMutablePointer<SSL_CTX>? = nil
                                                                          ^~~~~~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:1120:80: error: use of undeclared type 'SSL'
            private func prepareConnection(socket: Socket) throws -> UnsafeMutablePointer<SSL> {
                                                                                          ^~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:405:5: error: use of unresolved identifier 'SSL_library_init'
                                    SSL_library_init()
                                    ^~~~~~~~~~~~~~~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:406:5: error: use of unresolved identifier 'SSL_load_error_strings'
                                    SSL_load_error_strings()
                                    ^~~~~~~~~~~~~~~~~~~~~~
    OpenSSL.ERR_lib_error_string:1:13: note: did you mean 'ERR_lib_error_string'?
    public func ERR_lib_error_string(_ e: UInt) -> UnsafePointer<Int8>!
                ^
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:407:5: warning: 'OPENSSL_config' is deprecated
                                    OPENSSL_config(nil)
                                    ^
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:408:5: error: use of unresolved identifier 'OPENSSL_add_all_algorithms_conf'
                                    OPENSSL_add_all_algorithms_conf()
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:415:19: error: use of unresolved identifier 'SSLv23_server_method'
                                    self.method = SSLv23_server_method()
                                                  ^~~~~~~~~~~~~~~~~~~~
    OpenSSL.SSLv3_server_method:2:13: note: did you mean 'SSLv3_server_method'?
    public func SSLv3_server_method() -> OpaquePointer!
                ^
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:419:19: error: use of unresolved identifier 'SSLv23_client_method'
                                    self.method = SSLv23_client_method()
                                                  ^~~~~~~~~~~~~~~~~~~~
    OpenSSL.SSLv3_client_method:2:13: note: did you mean 'SSLv3_client_method'?
    public func SSLv3_client_method() -> OpaquePointer!
                ^
    /homer/leif/swift/Kitura/.build/checkouts/BlueSSLService.git--774207894858193348/Sources/SSLService.swift:853:27: error: use of unresolved identifier 'SSL_CTRL_OPTIONS'
                                    SSL_CTX_ctrl(context, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION, nil)
                                                          ^~~~~~~~~~~~~~~~
    OpenSSL.SSL_CTRL_CHAIN:1:12: note: did you mean 'SSL_CTRL_CHAIN'?
    public var SSL_CTRL_CHAIN: Int32 { get }
               ^
    OpenSSL.SSL_CTRL_SET_MTU:1:12: note: did you mean 'SSL_CTRL_SET_MTU'?
    public var SSL_CTRL_SET_MTU: Int32 { get }
               ^
    error: terminated(1): /opt/swift/usr/bin/swift-build-tool -f /homer/leif/swift/Kitura/.build/debug.yaml
    
    enhancement 
    opened by zwoop 11
  • Adds ALPN support on macOS 10.13+, iOS/tvOS 11+, and watchOS 4+

    Adds ALPN support on macOS 10.13+, iOS/tvOS 11+, and watchOS 4+

    Adds support for ALPN using the new SecureTransport APIs in the fall 2017 OS releases.

    Description

    I've made the static & member ALPN-related variables available to all, not just Linux, and I've added a static Boolean variable which can be used to check whether ALPN is available at all. On Linux it returns true, on Apple platforms it returns true only if on 10.13/11.0/4.0 or above, via the Swift #available() expression.

    Most of the work happens in two new private Apple-only functions, marked as @available only on the above OS revisions. Before the call to SSLHandshake() we take the available ALPN protocols and attach them to the context via SSLSetALPNProtocols(). After the handshake completes, we scan the list from the peer via SSLCopyALPNProtocols(), comparing against our list. The first match is set as our negotiatedALPNProtocol.

    Motivation and Context

    This should enable the Kitura HTTP2 module to function correctly on macOS and friends, since at present it's Linux-only due to the lack of ALPN.

    How Has This Been Tested?

    I have no idea how to test this. Apparently there are no unit tests for this project at all? Perhaps someone who's tested the Linux ALPN code can point me at something they used for that?

    Checklist:

    • [x] I have submitted a CLA form
    • [ ] If applicable, I have updated the documentation accordingly.
    • [ ] If applicable, I have added tests to cover my changes.
    opened by AlanQuatermain 10
  • Failing build under Linux

    Failing build under Linux

    It is not possible to build an Kitura application under Linux using IBM`s Linux docker (Ubuntu 14.04 and Swift 4.2) when BlueSSLService is included alongside Kitura.

    Interestingly enough, theres no problem on macOS, probably related to a fact that some of the Kitura packages uses OpenSSL only for Linux builds.

    Output: 'OpenSSL' /root/VojacekJan/.build/checkouts/OpenSSL.git-8485872258080618489: warning: Ignoring declared target(s) 'OpenSSL' in the system package error: multiple targets named 'OpenSSL' in: OpenSSL, SSLService

    Packages: ` import PackageDescription

    let package = Package( name: "Name", products: [ .executable(name: "Name", targets: ["Name"]), ], dependencies: [ .package(url: "https://github.com/IBM-Swift/Kitura.git", from: "2.5.3"), .package(url: "https://github.com/IBM-Swift/HeliumLogger", from: "1.7.1"), .package(url: "https://github.com/IBM-Swift/Kitura-Session.git", from: "3.2.0"), .package(url: "https://github.com/thevojacek/Kitura-MiniHandlebars", from: "1.2.2"), .package(url: "https://github.com/OpenKitten/MongoKitten", from: "4.1.3"), .package(url: "https://github.com/thevojacek/Kitura-MongoDbSessionStore", from: "0.2.2"), .package(url: "https://github.com/IBM-Swift/Swift-JWT", from: "2.0.0"), .package(url: "https://github.com/krzyzanowskim/CryptoSwift", from: "0.12.0") ], targets: [ .target( name: "Name", dependencies: [ "Kitura", "HeliumLogger", "Kitura-MiniHandlebars", "KituraSession", "MongoKitten", "Kitura-MongoDbSessionStore", "SwiftJWT", "CryptoSwift" ]), ] ) `

    Any help is much appreciated.

    opened by thevojacek 7
  • ALPN implementation for the updated SSLServiceDelegate

    ALPN implementation for the updated SSLServiceDelegate

    Application-Layer Protocol Negotiation (ALPN) is a TLS extension allows the application-layer to negotiate which protocol will by used over the secured socket. The main motivation for adding this support to BlueSSLService is to add support for HTTP/2 which uses this extension to choose the newer version of HTTP over the older ones.

    Description

    This PR follows the BlueSocket PR #67 that added new field/function to the SSLServiceDelegate protocol.

    In this PR the implementation uses the OpenSSL API to register callback functions that will negotiate for a protocol based on ALPN information arriving from the client within the ClientHello message. The implementation tries to match a supported protocol from the availableAlpnProtocols list with the protocols requested by the client. If it will find a match the response will be sent back to the client and the selected protocol will be set in the negotiatedAlpnProtocol field.

    Because of limitations of the Apple Secure Transport it is still unclear how and if ALPN negotiation is possible on MacOS. In this PR we only support the Linux environment by integrating with the OpenSSL API.

    Motivation and Context

    The main motivation for adding this support to BlueSSLService is to add support for HTTP/2 which uses this extension to choose the newer version of HTTP over the older ones.

    How Has This Been Tested?

    It has been tested with broader changes to Kitura-net and a new package under development for adding HTTP/2 support to Kitura.

    Checklist:

    • [ ] I have submitted a CLA form
    • [ ] If applicable, I have updated the documentation accordingly.
    • [ ] If applicable, I have added tests to cover my changes.
    opened by ymesika 7
  • Unable to fetch BlueSSLService

    Unable to fetch BlueSSLService

    Using the following package.swift file:

    import PackageDescription let package = Package( name: "project5", dependencies: [ .Package(url: "https://github.com/IBM-Swift/Kitura.git",majorVersion: 1), .Package(url: "https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git", majorVersion: 1), .Package(url: "https://github.com/IBM-Swift/HeliumLogger.git", majorVersion: 1) > ] )

    running 'swift build' gets stuck on the following and the swift build process

    Fetching https://github.com/IBM-Swift/Kitura.git Fetching https://github.com/IBM-Swift/Kitura-StencilTemplateEngine.git Fetching https://github.com/IBM-Swift/HeliumLogger.git Fetching https://github.com/twostraws/SwiftGD.git Fetching https://github.com/IBM-Swift/Kitura-net.git Fetching https://github.com/IBM-Swift/SwiftyJSON.git Fetching https://github.com/IBM-Swift/Kitura-TemplateEngine.git Fetching https://github.com/IBM-Swift/LoggerAPI.git Fetching https://github.com/IBM-Swift/BlueSocket.git Fetching https://github.com/IBM-Swift/CCurl.git Fetching https://github.com/IBM-Swift/BlueSSLService.git

    The swift-build process then begins to consume memory and CPU usage

    opened by robm92 7
  • Support for OpenSSL 1.1.X

    Support for OpenSSL 1.1.X

    Description

    Currently, BlueSSLService doesn't add support for openssl 1.1.X. This PR aims to add support for both openssl versions 1.0.X and 1.1.X

    Resolves : https://github.com/IBM-Swift/Kitura/issues/1341

    How Has This Been Tested?

    Tested on both Ubuntu 16.04 and 18.04 with openssl 1.0.x and 1.1.x

    Checklist:

    • [x] I have submitted a CLA form
    • [x] If applicable, I have added tests to cover my changes.
    opened by nethraravindran 5
  • Data sending slowed down after using BlueSSLService

    Data sending slowed down after using BlueSSLService

    I actually use the LocalSocketBlue, but I wanted to use this library. After integrating, connecting to the server and sending data was seriously slowed down. How can I solve this?

    opened by SmartSystemElectronics 6
  • `verifyCallback` not being called

    `verifyCallback` not being called

    I am using SSLService like so:

    let listeningSocket = try Socket.create(family: .inet)
    let configuration = ...
    let sslService = try SSLService(usingConfiguration: configuration)
    sslService?.skipVerification = true
    sslService?.verifyCallback = { service in
        return (false, "invalid client cert")
    }
    listeningSocket.delegate = sslService
    let newConnectionSocket = try socketConnection.acceptClientConnection()
    

    Debugging led me to notice that neither skipVerification nor verifyCallback is being copied onto the new socket created by the last line.

    This diff seems to fix it. I can open a PR but first wanted to make sure that a) I am not missing something and b) this won't have any unintended side effects.

    diff --git a/Sources/SSLService/SSLService.swift b/Sources/SSLService/SSLService.swift
    index f64f6fe..644a7ae 100644
    --- a/Sources/SSLService/SSLService.swift
    +++ b/Sources/SSLService/SSLService.swift
    @@ -404,6 +404,8 @@ public class SSLService: SSLServiceDelegate {
            private init?(with source: SSLService) throws {
                    
                    self.configuration = source.configuration
    +               self.skipVerification = source.skipVerification
    +               self.verifyCallback = source.verifyCallback
                    
                    // Validate the config...
                    try self.validate(configuration: source.configuration)
    
    
    opened by jdmarshall90 0
  • SSLRead bad certificate

    SSLRead bad certificate

    Hi all. In my app, I integrate the BluseSocket library and with other ios apps, it works perfectly. Now we are trying to connect to the server from Web with WebSocket. I create a self-signed certificate with this instruction: https://www.ibm.com/docs/en/api-connect/10.0.1.x?topic=overview-generating-self-signed-certificate-using-openssl And now when I want to connect, I am getting an error

    Error code: -9825(0x-2661), ERROR: SSLRead, code: -9825, reason: misc. bad certificate
    

    The common name of the certificate is localhost. Anyone can help me?

    opened by Nahatakyan 0
  • Socket error: PKCS12 file not specified.

    Socket error: PKCS12 file not specified.

    Hi there

    I'm trying to connect and create an ssl socket using the following code snippet:
    let fileCertURL = Bundle.main.url(forResource:"cert", withExtension: "pem")?.path
    let fileKeyURL = Bundle.main.url(forResource:"key", withExtension: "pem")?.path
    let myConfig = SSLService.Configuration(withCACertificateFilePath: nil, usingCertificateFile: fileCertURL, withKeyFile: fileKeyURL, usingSelfSignedCerts: true, cipherSuite: nil)
    var socket = try Socket.create()
    socket.delegate = try SSLService(usingConfiguration: myConfig)
    try socket.connect(to: "******", port: ****)
    

    But I keep getting this error: ERROR: Socket error: PKCS12 file not specified.

    I am running this code on my actual iPhone device (not macOS) and by the documentation it doesn't says that I need to add a .pkcs12 file anywhere

    any help is appreciated

    opened by SodaSurfer 1
  • Socket does not write until data is read

    Socket does not write until data is read

    On iOS, when connected with TLS, if there is a read pending (i.e., it's waiting for data), and I attempt to write data to the socket, the socket will not actually writing anything until something is read. There are no errors when writing to the socket.

    The code I'm using to connect:

    let configuration = SSLService.Configuration() 
    socket.delegate = try SSLService(usingConfiguration: configuration)
    try socket.connect(to: "...", port: 1337)
    

    Everything works fine if I don't connect with TLS. I tried other libraries and this doesn't occur, so it seems to be an issue with BlueSSLService (and not the server).

    opened by manoelfd 2
  • Problem with expired certificate

    Problem with expired certificate

    Hello, In our project we have a standard configuration like this: _configuration = SSLService.Configuration() _socket = try Socket.create(family: .inet6, type: .stream, proto: .tcp) _socket.delegate = try SSLService(usingConfiguration: _configuration)

    and we have a problem that when the certificate on server expires our app still is sending messages. How can we check this or stop sending if we detect that certificate is corrupted?

    opened by impresyjna 0
Releases(2.0.1)
  • 1.0.52(Dec 13, 2018)

    Version 1.0

    SSL/TLS Add-in framework for BlueSocket in Swift using the Swift Package Manager. Works on supported Apple platforms (using Secure Transport) and on Linux (using OpenSSL).

    Prerequisites

    Swift

    • Swift Open Source swift-4.0.0-RELEASE toolchain (Minimum REQUIRED for latest release)
    • Swift Open Source swift-5.0-RELEASE toolchain (Recommended)
    • Swift toolchain included in Xcode Version 10.2 (10E125) or higher.

    macOS

    • macOS 10.11.6 (El Capitan) or higher.
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.2 (10E125) or higher using the included toolchain (Recommended).
    • Secure Transport provided by macOS.

    iOS

    • iOS 10.0 or higher
    • Xcode Version 9.0 (9A325) or higher using one of the above toolchains.
    • Xcode Version 10.2 (10E125) or higher using the included toolchain (Recommended).
    • Secure Transport provided by iOS.

    Linux

    • Ubuntu 16.04 (or 16.10 but only tested on 16.04 and 18.04).
    • One of the Swift Open Source toolchains listed above.
    • OpenSSL is provided by the distribution. Note: 1.0.x, 1.1.x and later releases of OpenSSL are supported.
    • The appropriate libssl-dev package is required to be installed when building.

    Other Platforms

    • BlueSSLService is NOT supported on watchOS since POSIX/BSD/Darwin sockets are not supported on the actual device although they are supported in the simulator.
    • BlueSSLService should work on tvOS but has NOT been tested.

    Changes since 1.0.0

    • Require latest version of BlueSocket.
    • Update to Swift 4.1.
    • Support SSL_OP* constants defined as longs. Use CLong to explicitly cast these options where used. PR #52.
    • Update to include Swift 4.2 in CI builds.
    • Added prerequisite that the libssl-dev package is required to be installed when building on Linux.
    • Minor license update.
    • Updates for Xcode 10 to project.
    • Swift 4.2 support. PR #57
    • Make Swift 4.2 the default compiler in project.
    • Rename Swift 4.2 OpenSSL system library target (#59)
    • Revert (#59) back to using OpenSSL module in 4.2 format. PR #60.
    • Update for Swift 4.2 and Xcode 10.
    • Add support for OpenSSL 1.1.x aa well as OpenSSL 1.0.x. PR #61.
    • Added CI support for building with Swift 5. PR #64.
    • Fixed handshake bug that could prevent a connection when BlueSSLService is used on the client side.
    • Added unit tests for cursory (at least for now) testing BlueSSLService.
    • Removed requirement of Swift 4.2 to support OpenSSL 1.1.x. OpenSSL 1.1.x is now supported using Swift 4.0, 4.1 and 4.2.
    • Provided more explicit documentation in the README for specifying which APIs are supported on which platforms and added warnings to documentation for APIs that are not supported on Apple Platforms.
    • Update CI support to use Swift 4.2.3. PR #72
    • Update to Swift 5.0. PR #73.
    • Fixed for intermittent crash. PR #74
    • Add CI support for Xcode 11.
    • Fix warnings using Swift 5.1. PR #80
    • Update to use Swift 5.1 as default.
    • Added feature when using self signed certificates to allow client to check the server certificate using an embedded local certificate. PR #81.
    Source code(tar.gz)
    Source code(zip)
  • 0.12.84(Oct 10, 2017)

    This release minimally requires use of the swift-3.1.1-RELEASE toolchain or the swift-4.0.0-RELEASE toolchain which is recommended.

    • Compatible with Xcode 9.0 (9A235) General Release or higher using one of the above toolchains.
    • On Linux this release support OpenSSL 1.0.x only.
    • Corrected some issues with SSL error handling on Linux. PR #42.
    • Added framework target to Xcode project, issue #44.
    • Added Cathage support. #44. #45.
    • Remove build on Xcode 8.3.
    • CI updates.
    • Changes to adapt to Swift 4.1.
    Source code(tar.gz)
    Source code(zip)
  • 0.12.5(Sep 29, 2016)

    This release minimally requires use of the swift-3.1.1-RELEASE toolchain or the swift-4.0.0-RELEASE toolchain which is recommended.

    • Compatible with Xcode 9.0 (9A235) General Release or higher using one of the above toolchains.

    • This version supports Apple Secure Transport on Apple Platforms and OpenSSL on Linux.

    • At present on Apple platforms, only PKCS12 files are accepted in the Configuration. You should use the init function described below and further in the README.md.

    • Also, on Apple platforms, changing of the cipherSuite property is not supported. Please use the default.

    • Added new parameter to init function in Configuration that allows optionally specifying a password for the PKCS12 certificate chain file. That signature now looks like this:

      public init(withChainFilePath chainFilePath: String?, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true)
      
    • Loosened up the too stringent certificate verification process.

    • Added client support when using Secure Transport on Apple platforms.

    • Added optional connection verification callback feature. See the section Extending Connection Verification in the README.md.

    • Added optional connection verification bypass feature. See the section Skipping Connection Verification in the README.md.

    • Allow use on iOS, tvOS and watchOS as well as macOS.

    • Use version 0.10.24 on master if you wish to use the version that uses OpenSSL on both platforms.

    • This version now merged onto master.

    • Added CI (PR#2).

    • Fixed Kitura issue -> #852

    • A new, defaulted to nil, optional parameter has been added to the end of each of the Configuration init functions. This feature allows the setting of the cipherSuite. If this parameter is set to nil, the default cipherSuite for the platform will be used. Note: Setting the cipher suite on Apple platforms is currently not supported and attempting to do so may result in unpredictable behavior. See the README.md for more information.

    • Added a new Configuration initializer that allows creating a Configuration that does NOT contain a backing certificate or certificate chain.

    • Fixed issue #959 from Kitura.

    • Added support (currently on Linux only) for creating a configuration that is based on PEM formatted certificate passed in as a string. Issue #10. See the README.md for information about the new configuration API. Note: This functionality has had only minimal testing. Use with caution and report any anomalies.

    • Fixed issue #11 by implementing issue #12 alleviating a performance hit when processing the PKCS12 file on macOS.

    • Fix for issue #983 from Kitura. On macOS, the SSLContext must only be used by one thread at a time. Access to use of it must be protected. Introduced a new SSLReadWriteDispatcher struct that allows for sync'ing access to the context when doing reads and writes. This effectively forces reads and write to occur serially.

    • Related to the above fix, apparently on Linux, simultaneous reads and writes are not thread safe. Used the previously introduced SSLReadWriteDispatcher struct that allows for sync'ing access when doing reads and writes. This effectively forces reads and write to occur serially.

    • Also on Linux, added a check to see if the remote connection has gone away prior to issuing a SSL_shutdown() request. This should alleviate the problem of apps receiving a SIGPIPE when attempting to shutdown SSL after the remote has already terminated.

    • Fixed issue #16. Default cipher suite was not being enabled on macOS.

    • More on issue #16. Enabled ECDH ciphers if linking with OpenSSL 1.0.2 or higher.

    • Fixed issue #18 and #19.

    • Merged PR #20.

    • Bug fixes related to rejected PR #21. On Linux, after SSL_read or SSL_write, need to get the last error using SSL_get_error(). The error is NOT in the return code. If returning from SSL_write and the error is SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, an SSLError.retryNeeded exception is thrown. If we're returning from SSL_read under the same circumstances, we set the errno to EAGAIN and return -1.

    • Add an option to allow clients to connect to servers that are using self-signed certificates. PR #24.

    • The initializer used to create a configuration without a backing certificate should (when being used as a client) allow self-signed certificates. Reference closed PR #25.

    • Added podspec for cocoapod integration. PR #27.

    • Update podspec to include watchOS and tvOS. PR #29

    • Support of Xcode 9 Beta.

    • Fix for problem with using the default Configuration initializer. PR #30

    • Fix for problem when importing PKCS12 that causes index out of bounds and subsequent crash. PR #31

    • Support for ALPN. PR #26. Important Note: Usage of this functionality is dependent on the availability of version 1.0.2 of OpenSSL or higher at build and runtime.

    • Fix for using client certificates (Issue #28) via PR #33.

    • Automatically enabled ECDH ciphers if linking with OpenSSL v1.0.2 or higher. See related issue #16. Previously, this required the setting of a compile time switch. That requirement has been eliminated.

    • Reverted PR #33 to fix issue #36.

    • Changed the default enabled cipher list from "DEFAULT" to "DEFAULT:!DH". This effectively disables DH ciphers which is fine since currently there's no API to allow setup of the required DH keys.

    • Swift 4 Support.

    • Remove support for watchOS. See BlueSocket issue #87 for more information.

    Source code(tar.gz)
    Source code(zip)
  • 0.11.26(Sep 8, 2016)

    This release minimally requires use of the swift-3.0-RELEASE toolchain or the swift-DEVELOPMENT-SNAPSHOT-2016-09-27-a toolchain which is recommended.

    CAUTION: THIS RELEASE IS STILL STABILIZING. USE AT YOUR OWN RISK.

    • Compatible with Xcode 8 General Release using one of the above toolchains.

    • This version supports Apple Secure Transport on macOS and OpenSSL on Linux.

    • At present on macOS, only PKCS12 files are accepted in the Configuration. You should use the init function described below and further in the README.md.

    • Also, on macOS, changing of the cipherSuite property is not supported. Please use the default.

    • Added new parameter to init function in Configuration that allows optionally specifying a password for the PKCS12 certificate chain file. That signature now looks like this:

      public init(withChainFilePath chainFilePath: String? = nil, withPassword password: String? = nil, usingSelfSignedCerts selfSigned: Bool = true)
      
    • Loosened up the too stringent certificate verification process.

    • Added client support when using Secure Transport on macOS.

    • Added optional connection verification callback feature. See the section Extending Connection Verification in the README.md.

    • Allow use on iOS, tvOS and watchOS as well as macOS.

    • This version is experimental and relatively lightly tested.

    • Use version 0.10.x on master if you wish to use the version that uses OpenSSL on both platforms.

    • This version now merged onto master.

    Source code(tar.gz)
    Source code(zip)
  • 0.10.24(Aug 19, 2016)

    This release minimally requires use of the swift-3.0-RELEASE toolchain or the swift-DEVELOPMENT-SNAPSHOT-2016-09-27-a toolchain which is recommended.

    • Compatible with Xcode 8 General Release using one of the above toolchains.
    • Added password property to Configuration.
    • Removed verifyConnection() function from delegate. Now handled internally.
    • Ensured that OpenSSL libraries are only initialized once.
    • Minor change to initialize delegate function of SSLServiceDelegate. SSLService.inititalize(isServer:) became SSLService.initialize(asServer:).
    • Loosened up the too stringent certificate verification process.
    Source code(tar.gz)
    Source code(zip)
  • 0.9.3(Aug 16, 2016)

    This release requires use of the swift-DEVELOPMENT-SNAPSHOT-2016-08-15-a toolchain.

    • Compatible with Xcode 8 Beta 6 using the above toolchain.
    • Added password property to Configuration.
    • Removed verifyConnection() function from delegate. Now handled internally.
    • Ensured that OpenSSL libraries are only initialized once.
    • Minor change to initialize delegate function of SSLServiceDelegate. SSLService.inititalize(isServer:) became SSLService.initialize(asServer:).
    Source code(tar.gz)
    Source code(zip)
  • 0.8.4(Aug 6, 2016)

    This release requires use of the swift-DEVELOPMENT-SNAPSHOT-2016-08-04-a toolchain or the new swift-DEVELOPMENT-SNAPSHOT-2016-08-07-a toolchain.

    • Compatible with Xcode 8 Beta 4 using the above toolchain.
    • Added password property to Configuration.
    • Removed verifyConnection() function from delegate. Now handled internally.
    • Ensured that OpenSSL libraries are only initialized once.
    Source code(tar.gz)
    Source code(zip)
  • 0.7.0(Jul 26, 2016)

    This release requires use of the new swift-DEVELOPMENT-SNAPSHOT-2016-07-25-a toolchain.

    Note: Due to inconsistencies in the implementation of Data on macOS and Linux, this release continues to use the NSData and NSMutableData types. Once these inconsistencies are rectified, the Data type will be adopted.

    Also, note the version jump to 0.7.0 to sync up with BlueSocket.

    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Jun 22, 2016)

  • 0.1.7(May 27, 2016)

    WARNING: This is pre-release software. While it should work, testing is not complete. Not to be used in production code yet.

    • Testing has been completed with self-signed certificates.
    • Testing still in progress for real certificates.
    Source code(tar.gz)
    Source code(zip)
Owner
Kitura
Kitura - Server Side framework written in Swift
Kitura
🌏 A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications.

A zero-dependency networking solution for building modern and secure iOS, watchOS, macOS and tvOS applications. ?? TermiNetwork was tested in a produc

Bill Panagiotopoulos 90 Dec 17, 2022
A native, lightweight and secure time-based (TOTP) & counter-based (HOTP) password client built for iOS

A native, lightweight and secure time-based (TOTP) & counter-based (HOTP) password client built for iOS Built by Tijme Gommers – Buy me a coffee via P

Raivo OTP 770 Jan 8, 2023
TheraForge's Client REST API framework to connect to TheraForge's secure CloudBox Backend-as-a-Service (BaaS)

OTFCloudClientAPI TheraForge's Client REST API Framework to Connect to TheraForg

TheraForge 0 Dec 23, 2021
The fastest iOS app to add a note to your email inbox

Major Key How often are you on the run, or hanging out with friends, only to suddenly think of this really important thing you need to do when you're

Felix Krause 190 Oct 9, 2022
Simple iOS app in Swift to show AQI for some cities using websocket using Combine + MVVM

AQI Simple iOS app in Swift to show AQI for some cities using websocket using Combine + MVVM This app follows MVVM This app uses combine framework The

Amey Vikkram Tiwari 2 Nov 6, 2022
NSURLSession network abstraction layer, using Codable and Decodable for response and Encodable for request. ⚙️🚀

SONetworking NSURLSession network abstraction layer, using Codable and Decodable for response and Encodable for request. Project Folder and File Struc

Ahmad AlSofi 4 Jan 28, 2022
Publish and discover services using Bonjour

Ciao Lib to publish and find services using mDNS Requirements Installation Usage License Requirements iOS 8.0+ / Mac OS X 10.10+ / tvOS 9.0+ Xcode 9.0

Alexandre Mantovani Tavares 55 Dec 14, 2022
Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux.

BlueSocket Socket framework for Swift using the Swift Package Manager. Works on iOS, macOS, and Linux. Prerequisites Swift Swift Open Source swift-5.1

Kitura 1.3k Dec 26, 2022
Plugin and runtime library for using protobuf with Swift

Swift Protobuf Welcome to Swift Protobuf! Apple's Swift programming language is a perfect complement to Google's Protocol Buffer ("protobuf") serializ

Apple 4.1k Jan 6, 2023
Snap Scraper enables users to download media uploaded to Snapchat's Snap Map using a set of latitude and longitude coordinates.

Snap Scraper Description Snap Scraper is an open source intelligence tool which enables users to download media uploaded to Snapchat's Snap Map using

Dr Richard Matthews 58 Dec 12, 2022
This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and AppleTV app.

This generic SOAP client allows you to access web services using a your iOS app, Mac OS X app and Apple TV app. With this Framework you can create iPh

Prioregroup.com 479 Nov 22, 2022
iOS Todo Application using RxSwift and ReactorKit

RxTodo RxTodo is an iOS application developed using ReactorKit. This project is for whom having trouble with learning how to build a RxSwift applicati

Suyeol Jeon 1.3k Jan 3, 2023
A slim implementation of a websocket server using Swift and Vapor 4.0.

Swift Websocket Server Example using Vapor 4.0 This project includes a minimum working example for a websocket server written in Swift. To interact wi

Adrian Hupka 5 Sep 22, 2022
Swift HTTP server using the pre-fork worker model

Curassow Curassow is a Swift Nest HTTP Server. It uses the pre-fork worker model and it's similar to Python's Gunicorn and Ruby's Unicorn. It exposes

Kyle Fuller Archive 397 Oct 30, 2022
WebSocket(RFC-6455) library written using Swift

DNWebSocket Object-Oriented, Swift-style WebSocket Library (RFC 6455) for Swift-compatible Platforms. Tests Installation Requirements Usage Tests Conf

Gleb Radchenko 36 Jan 29, 2022
An awesome Swift HTML DSL library using result builders.

SwiftHtml An awesome Swift HTML DSL library using result builders. let doc = Document(.html5) { Html { Head { Meta()

Binary Birds 204 Dec 25, 2022
Postie - The Next-Level HTTP API Client using Combine

Postie - The Next-Level HTTP API Client using Combine Postie is a pure Swift library for building URLRequests using property wrappers.

kula 28 Jul 23, 2022
macOS VM for Apple Silicon using Virtualization API

MacVM macOS Monterey added support for virtualizing macOS with Apple silicon host. This project provides an example project for the setup. Currently o

Khaos Tian 1.2k Jan 4, 2023
Generic Network Layer created using Swift.

Generic-Network-Layer_iOS Generic Network Layer created using URLSession. Networking is an essential element in app development, and you'll need API c

Shubham Kr. Singh 41 Dec 31, 2022