Skip to content

Commit

Permalink
Pull master branch from daltoniam/Starscream
Browse files Browse the repository at this point in the history
  • Loading branch information
turbulem committed Jul 25, 2018
1 parent ca783db commit 138cfa7
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 14 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ socket.write(pong: Data()) //example on how to write a pong control frame over t

Starscream will automatically respond to incoming `ping` control frames so you do not need to manually send `pong`s.

However if for some reason you need to control this prosses you can turn off the automatic `ping` response by disabling `respondToPingWithPong`.
However if for some reason you need to control this process you can turn off the automatic `ping` response by disabling `respondToPingWithPong`.

```swift
socket.respondToPingWithPong = false //Do not automaticaly respond to incoming pings with pongs.
Expand All @@ -160,6 +160,12 @@ The disconnect method does what you would expect and closes the socket.
socket.disconnect()
```

The socket can be forcefully closed, by specifying a timeout (in milliseconds). A timeout of zero will also close the socket immediately without waiting on the server.

```swift
socket.disconnect(forceTimeout: 10, closeCode: CloseCode.normal.rawValue)
```

### isConnected

Returns if the socket is connected or not.
Expand Down
92 changes: 92 additions & 0 deletions Sources/SSLClientCertificate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//
// SSLClientCertificate.swift
// Starscream
//
// Created by Tomasz Trela on 08/03/2018.
// Copyright © 2018 Vluxe. All rights reserved.
//

import Foundation

public struct SSLClientCertificateError: LocalizedError {
public var errorDescription: String?

init(errorDescription: String) {
self.errorDescription = errorDescription
}
}

public class SSLClientCertificate {
internal let streamSSLCertificates: NSArray

/**
Convenience init.
- parameter pkcs12Path: Path to pkcs12 file containing private key and X.509 ceritifacte (.p12)
- parameter password: file password, see **kSecImportExportPassphrase**
*/
public convenience init(pkcs12Path: String, password: String) throws {
let pkcs12Url = URL(fileURLWithPath: pkcs12Path)
do {
try self.init(pkcs12Url: pkcs12Url, password: password)
} catch {
throw error
}
}

/**
Designated init. For more information, see SSLSetCertificate() in Security/SecureTransport.h.
- parameter identity: SecIdentityRef, see **kCFStreamSSLCertificates**
- parameter identityCertificate: CFArray of SecCertificateRefs, see **kCFStreamSSLCertificates**
*/
public init(identity: SecIdentity, identityCertificate: SecCertificate) {
self.streamSSLCertificates = NSArray(objects: identity, identityCertificate)
}

/**
Convenience init.
- parameter pkcs12Url: URL to pkcs12 file containing private key and X.509 ceritifacte (.p12)
- parameter password: file password, see **kSecImportExportPassphrase**
*/
public convenience init(pkcs12Url: URL, password: String) throws {
let importOptions = [kSecImportExportPassphrase as String : password] as CFDictionary
do {
try self.init(pkcs12Url: pkcs12Url, importOptions: importOptions)
} catch {
throw error
}
}

/**
Designated init.
- parameter pkcs12Url: URL to pkcs12 file containing private key and X.509 ceritifacte (.p12)
- parameter importOptions: A dictionary containing import options. A
kSecImportExportPassphrase entry is required at minimum. Only password-based
PKCS12 blobs are currently supported. See **SecImportExport.h**
*/
public init(pkcs12Url: URL, importOptions: CFDictionary) throws {
do {
let pkcs12Data = try Data(contentsOf: pkcs12Url)
var rawIdentitiesAndCertificates: CFArray?
let pkcs12CFData: CFData = pkcs12Data as CFData
let importStatus = SecPKCS12Import(pkcs12CFData, importOptions, &rawIdentitiesAndCertificates)

guard importStatus == errSecSuccess else {
throw SSLClientCertificateError(errorDescription: "(Starscream) Error during 'SecPKCS12Import', see 'SecBase.h' - OSStatus: \(importStatus)")
}
guard let identitiyAndCertificate = (rawIdentitiesAndCertificates as? Array<Dictionary<String, Any>>)?.first else {
throw SSLClientCertificateError(errorDescription: "(Starscream) Error - PKCS12 file is empty")
}

let identity = identitiyAndCertificate[kSecImportItemIdentity as String] as! SecIdentity
var identityCertificate: SecCertificate?
let copyStatus = SecIdentityCopyCertificate(identity, &identityCertificate)
guard copyStatus == errSecSuccess else {
throw SSLClientCertificateError(errorDescription: "(Starscream) Error during 'SecIdentityCopyCertificate', see 'SecBase.h' - OSStatus: \(copyStatus)")
}
self.streamSSLCertificates = NSArray(objects: identity, identityCertificate!)
} catch {
throw error
}
}
}

10 changes: 5 additions & 5 deletions Sources/SSLSecurity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ open class SSLSecurity : SSLTrustValidator {

- returns: if the key was successfully validated
*/
public func isValid(_ trust: SecTrust, domain: String?) -> Bool {
open func isValid(_ trust: SecTrust, domain: String?) -> Bool {

var tries = 0
while !self.isReady {
Expand Down Expand Up @@ -198,7 +198,7 @@ open class SSLSecurity : SSLTrustValidator {

- returns: a public key
*/
func extractPublicKey(_ data: Data) -> SecKey? {
public func extractPublicKey(_ data: Data) -> SecKey? {
guard let cert = SecCertificateCreateWithData(nil, data as CFData) else { return nil }

return extractPublicKey(cert, policy: SecPolicyCreateBasicX509())
Expand All @@ -211,7 +211,7 @@ open class SSLSecurity : SSLTrustValidator {

- returns: a public key
*/
func extractPublicKey(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? {
public func extractPublicKey(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? {
var possibleTrust: SecTrust?
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)

Expand All @@ -228,7 +228,7 @@ open class SSLSecurity : SSLTrustValidator {

- returns: the certificate chain for the trust
*/
func certificateChain(_ trust: SecTrust) -> [Data] {
public func certificateChain(_ trust: SecTrust) -> [Data] {
let certificates = (0..<SecTrustGetCertificateCount(trust)).reduce([Data]()) { (certificates: [Data], index: Int) -> [Data] in
var certificates = certificates
let cert = SecTrustGetCertificateAtIndex(trust, index)
Expand All @@ -246,7 +246,7 @@ open class SSLSecurity : SSLTrustValidator {

- returns: the public keys from the certifcate chain for the trust
*/
func publicKeyChain(_ trust: SecTrust) -> [SecKey] {
public func publicKeyChain(_ trust: SecTrust) -> [SecKey] {
let policy = SecPolicyCreateBasicX509()
let keys = (0..<SecTrustGetCertificateCount(trust)).reduce([SecKey]()) { (keys: [SecKey], index: Int) -> [SecKey] in
var keys = keys
Expand Down
17 changes: 14 additions & 3 deletions Sources/WebSocket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public protocol WebSocketClient: class {
var disableSSLCertValidation: Bool {get set}
var overrideTrustHostname: Bool {get set}
var desiredTrustHostname: String? {get set}
var sslClientCertificate: SSLClientCertificate? {get set}
#if os(Linux)
#else
var security: SSLTrustValidator? {get set}
Expand Down Expand Up @@ -107,6 +108,7 @@ public struct SSLSettings {
public let disableCertValidation: Bool
public var overrideTrustHostname: Bool
public var desiredTrustHostname: String?
public let sslClientCertificate: SSLClientCertificate?
#if os(Linux)
#else
public let cipherSuites: [SSLCipherSuite]?
Expand Down Expand Up @@ -178,6 +180,10 @@ open class FoundationStream : NSObject, WSStream, StreamDelegate {
settings[kCFStreamSSLPeerName] = kCFNull
}
}
if let sslClientCertificate = ssl.sslClientCertificate {
settings[kCFStreamSSLCertificates] = sslClientCertificate.streamSSLCertificates
}

inStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
outStream.setProperty(settings, forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
#endif
Expand Down Expand Up @@ -263,8 +269,10 @@ open class FoundationStream : NSObject, WSStream, StreamDelegate {
#if os(Linux) || os(watchOS)
#else
public func sslTrust() -> (trust: SecTrust?, domain: String?) {
let trust = outputStream!.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust?
var domain = outputStream!.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as? String
guard let outputStream = outputStream else { return (nil, nil) }

let trust = outputStream.property(forKey: kCFStreamPropertySSLPeerTrust as Stream.PropertyKey) as! SecTrust?
var domain = outputStream.property(forKey: kCFStreamSSLPeerName as Stream.PropertyKey) as! String?
if domain == nil,
let sslContextOut = CFWriteStreamCopyProperty(outputStream, CFStreamPropertyKey(rawValue: kCFStreamPropertySSLContext)) as! SSLContext? {
var peerNameLen: Int = 0
Expand Down Expand Up @@ -399,6 +407,7 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
public var disableSSLCertValidation = false
public var overrideTrustHostname = false
public var desiredTrustHostname: String? = nil
public var sslClientCertificate: SSLClientCertificate? = nil

public var enableCompression = true
#if os(Linux)
Expand Down Expand Up @@ -646,12 +655,14 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
let settings = SSLSettings(useSSL: useSSL,
disableCertValidation: disableSSLCertValidation,
overrideTrustHostname: overrideTrustHostname,
desiredTrustHostname: desiredTrustHostname)
desiredTrustHostname: desiredTrustHostname),
sslClientCertificate: sslClientCertificate
#else
let settings = SSLSettings(useSSL: useSSL,
disableCertValidation: disableSSLCertValidation,
overrideTrustHostname: overrideTrustHostname,
desiredTrustHostname: desiredTrustHostname,
sslClientCertificate: sslClientCertificate,
cipherSuites: self.enabledSSLCipherSuites)
#endif
certValidated = !useSSL
Expand Down
14 changes: 10 additions & 4 deletions Starscream.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
33CCF08A1F5DDC030099B092 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D88EAF811ED4DFD3004FE2C3 /* libz.tbd */; };
33CCF08C1F5DDC030099B092 /* Starscream.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C1360001C473BEF00AA3A01 /* Starscream.h */; settings = {ATTRIBUTES = (Public, ); }; };
33CCF08D1F5DDC030099B092 /* include.h in Headers */ = {isa = PBXBuildFile; fileRef = D85927D71ED76F25003460CB /* include.h */; settings = {ATTRIBUTES = (Private, ); }; };
BB8A648020E1105C00527BA5 /* NSString+SHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = BB8A647E20E1105C00527BA5 /* NSString+SHA1.h */; settings = {ATTRIBUTES = (Private, ); }; };
BB8A648120E1105C00527BA5 /* NSString+SHA1.m in Sources */ = {isa = PBXBuildFile; fileRef = BB8A647F20E1105C00527BA5 /* NSString+SHA1.m */; };
BB1018E421087DEF00BA9E60 /* NSString+SHA1.h in Headers */ = {isa = PBXBuildFile; fileRef = BB8A647E20E1105C00527BA5 /* NSString+SHA1.h */; settings = {ATTRIBUTES = (Private, ); }; };
BB1018E521087DF300BA9E60 /* NSString+SHA1.m in Sources */ = {isa = PBXBuildFile; fileRef = BB8A647F20E1105C00527BA5 /* NSString+SHA1.m */; };
BB1018E621087E7E00BA9E60 /* SSLClientCertificate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACFF1BE2052FE8F00B95FFF /* SSLClientCertificate.swift */; };
EACFF1BF2052FE8F00B95FFF /* SSLClientCertificate.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACFF1BE2052FE8F00B95FFF /* SSLClientCertificate.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -39,6 +41,7 @@
D88EAF7E1ED4DFB5004FE2C3 /* Compression.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Compression.swift; path = Sources/Compression.swift; sourceTree = SOURCE_ROOT; };
D88EAF811ED4DFD3004FE2C3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
D88EAF831ED4E7D8004FE2C3 /* CompressionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompressionTests.swift; sourceTree = "<group>"; };
EACFF1BE2052FE8F00B95FFF /* SSLClientCertificate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SSLClientCertificate.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -88,6 +91,7 @@
5C135FFF1C473BEF00AA3A01 /* SSLSecurity.swift */,
5C1360011C473BEF00AA3A01 /* WebSocket.swift */,
D88EAF7E1ED4DFB5004FE2C3 /* Compression.swift */,
EACFF1BE2052FE8F00B95FFF /* SSLClientCertificate.swift */,
6B3E79E919D48B7F006071F7 /* Supporting Files */,
);
path = Sources;
Expand Down Expand Up @@ -153,8 +157,8 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
BB8A648020E1105C00527BA5 /* NSString+SHA1.h in Headers */,
33CCF08C1F5DDC030099B092 /* Starscream.h in Headers */,
BB1018E421087DEF00BA9E60 /* NSString+SHA1.h in Headers */,
33CCF08D1F5DDC030099B092 /* include.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -261,6 +265,7 @@
335FA1F81F5DF71D00F6D2EC /* WebSocket.swift in Sources */,
335FA1F91F5DF71D00F6D2EC /* CompressionTests.swift in Sources */,
335FA1FA1F5DF71D00F6D2EC /* StarscreamTests.swift in Sources */,
BB1018E621087E7E00BA9E60 /* SSLClientCertificate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -269,8 +274,9 @@
buildActionMask = 2147483647;
files = (
33CCF0861F5DDC030099B092 /* Compression.swift in Sources */,
BB1018E521087DF300BA9E60 /* NSString+SHA1.m in Sources */,
EACFF1BF2052FE8F00B95FFF /* SSLClientCertificate.swift in Sources */,
33CCF0871F5DDC030099B092 /* WebSocket.swift in Sources */,
BB8A648120E1105C00527BA5 /* NSString+SHA1.m in Sources */,
33CCF0881F5DDC030099B092 /* SSLSecurity.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
3 changes: 2 additions & 1 deletion Tests/CompressionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ class CompressionTests: XCTestCase {
// 2 Gigs!
// var rawData = Data(repeating: 0, count: 0x80000000)
var rawData = Data(repeating: 0, count: 0x80000)
let rawDataLen = rawData.count
rawData.withUnsafeMutableBytes { (ptr: UnsafeMutablePointer<UInt8>) -> Void in
arc4random_buf(ptr, rawData.count)
arc4random_buf(ptr, rawDataLen)
}

let compressed = try! compressor.compress(rawData)
Expand Down

0 comments on commit 138cfa7

Please sign in to comment.