Compare commits

..

No commits in common. "signal-release" and "master" have entirely different histories.

3 changed files with 31 additions and 66 deletions

View File

@ -80,12 +80,10 @@ class Decompressor {
strm.avail_in = CUnsignedInt(count)
repeat {
buffer.withUnsafeMutableBytes { (bufferPtr) in
strm.next_out = bufferPtr.bindMemory(to: UInt8.self).baseAddress
strm.avail_out = CUnsignedInt(bufferPtr.count)
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer)
strm.avail_out = CUnsignedInt(buffer.count)
res = inflate(&strm, 0)
}
res = inflate(&strm, 0)
let byteCount = buffer.count - Int(strm.avail_out)
out.append(buffer, count: byteCount)
@ -144,12 +142,10 @@ class Compressor {
strm.avail_in = CUnsignedInt(data.count)
repeat {
buffer.withUnsafeMutableBytes { (bufferPtr) in
strm.next_out = bufferPtr.bindMemory(to: UInt8.self).baseAddress
strm.avail_out = CUnsignedInt(bufferPtr.count)
strm.next_out = UnsafeMutablePointer<UInt8>(&buffer)
strm.avail_out = CUnsignedInt(buffer.count)
res = deflate(&strm, Z_SYNC_FLUSH)
}
res = deflate(&strm, Z_SYNC_FLUSH)
let byteCount = buffer.count - Int(strm.avail_out)
compressed.append(buffer, count: byteCount)

View File

@ -149,10 +149,7 @@ open class SSLSecurity : SSLTrustValidator {
} else {
policy = SecPolicyCreateBasicX509()
}
guard SecTrustSetPolicies(trust, policy) == errSecSuccess else {
assertionFailure("unable to set trust policies")
return false
}
SecTrustSetPolicies(trust,policy)
if self.usePublicKeys {
if let keys = self.pubKeys {
let serverPubKeys = publicKeyChain(trust)
@ -170,15 +167,9 @@ open class SSLSecurity : SSLTrustValidator {
for cert in certs {
collect.append(SecCertificateCreateWithData(nil,cert as CFData)!)
}
guard SecTrustSetAnchorCertificates(trust, collect as NSArray) == errSecSuccess else {
assertionFailure("unable to set trust anchor certificates")
return false
}
SecTrustSetAnchorCertificates(trust,collect as NSArray)
var result: SecTrustResultType = .unspecified
guard SecTrustEvaluate(trust, &result) == errSecSuccess else {
assertionFailure("unable to evaluate trust")
return false
}
SecTrustEvaluate(trust,&result)
if result == .unspecified || result == .proceed {
if !validateEntireChain {
return true
@ -222,17 +213,11 @@ open class SSLSecurity : SSLTrustValidator {
*/
public func extractPublicKey(_ cert: SecCertificate, policy: SecPolicy) -> SecKey? {
var possibleTrust: SecTrust?
guard SecTrustCreateWithCertificates(cert, policy, &possibleTrust) == errSecSuccess else {
assertionFailure("failed to create trust with certificate")
return nil
}
SecTrustCreateWithCertificates(cert, policy, &possibleTrust)
guard let trust = possibleTrust else { return nil }
var result: SecTrustResultType = .unspecified
guard SecTrustEvaluate(trust, &result) == errSecSuccess else {
assertionFailure("failed to evaluate trust")
return nil
}
SecTrustEvaluate(trust, &result)
return SecTrustCopyPublicKey(trust)
}

View File

@ -49,7 +49,6 @@ public enum ErrorType: Error {
case protocolError //There was an error parsing the WebSocket frames
case upgradeError //There was an error during the HTTP upgrade
case closeError //There was an error during the close (socket probably has been dereferenced)
case osError // There was an error with the underlying OS
}
public struct WSError: Error {
@ -70,7 +69,6 @@ public protocol WebSocketClient: class {
#else
var security: SSLTrustValidator? {get set}
var enabledSSLCipherSuites: [SSLCipherSuite]? {get set}
var socketSecurityLevel: StreamSocketSecurityLevel { get set }
#endif
var isConnected: Bool {get}
@ -115,7 +113,6 @@ public struct SSLSettings {
#if os(Linux)
#else
public let cipherSuites: [SSLCipherSuite]?
public var socketSecurityLevel: StreamSocketSecurityLevel
#endif
}
@ -146,11 +143,6 @@ open class FoundationStream : NSObject, WSStream, StreamDelegate {
public var enableSOCKSProxy = false
deinit {
inputStream?.delegate = nil
outputStream?.delegate = nil
}
public func connect(url: URL, port: Int, timeout: TimeInterval, ssl: SSLSettings, completion: @escaping ((Error?) -> Void)) {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
@ -174,8 +166,8 @@ open class FoundationStream : NSObject, WSStream, StreamDelegate {
inStream.delegate = self
outStream.delegate = self
if ssl.useSSL {
inStream.setProperty(ssl.socketSecurityLevel as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
outStream.setProperty(ssl.socketSecurityLevel as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject, forKey: Stream.PropertyKey.socketSecurityLevelKey)
#if os(watchOS) //watchOS us unfortunately is missing the kCFStream properties to make this work
#else
var settings = [NSObject: NSObject]()
@ -424,7 +416,6 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
#else
public var security: SSLTrustValidator?
public var enabledSSLCipherSuites: [SSLCipherSuite]?
public var socketSecurityLevel: StreamSocketSecurityLevel = .negotiatedSSL
#endif
public var isConnected: Bool {
@ -442,6 +433,7 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
private struct CompressionState {
var supportsCompression = false
var messageNeedsDecompression = false
var serverMaxWindowBits = 15
var clientMaxWindowBits = 15
var clientNoContextTakeover = false
@ -455,10 +447,6 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
private var isConnecting = false
private let mutex = NSLock()
private var compressionState = CompressionState()
// `currentMessageNeedsDecompression` is not part of the `compressionState` struct
// because currentMessageNeedsDecompression can be mutated in the read queue concurrently
// with other `compressionState` fields being accesseed on the write queue.
private var currentMessageNeedsDecompression = false
private var writeQueue = OperationQueue()
private var readStack = [WSResponse]()
private var inputQueue = [Data]()
@ -601,8 +589,8 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
}
request.setValue(headerWSUpgradeValue, forHTTPHeaderField: headerWSUpgradeName)
request.setValue(headerWSConnectionValue, forHTTPHeaderField: headerWSConnectionName)
headerSecKey = generateWebSocketKey()
request.setValue(headerWSVersionValue, forHTTPHeaderField: headerWSVersionName)
headerSecKey = try! generateWebSocketKey()
request.setValue(headerSecKey, forHTTPHeaderField: headerWSKeyName)
if enableCompression {
@ -639,16 +627,16 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
/**
Generate a WebSocket key as needed in RFC.
*/
private func generateWebSocketKey() throws -> String {
let kSocketKeyByteLength = 16
var randomData = Data(count: kSocketKeyByteLength)
try randomData.withUnsafeMutableBytes { (bytes: UnsafeMutablePointer<UInt8>) throws -> Void in
guard SecRandomCopyBytes(kSecRandomDefault, kSocketKeyByteLength, bytes) == errSecSuccess else {
throw WSError(type: .osError, message: "unable to generate random bytes", code: 0)
}
private func generateWebSocketKey() -> String {
var key = ""
let seed = 16
for _ in 0..<seed {
let uni = UnicodeScalar(UInt32(97 + arc4random_uniform(25)))
key += "\(Character(uni!))"
}
return randomData.base64EncodedString()
let data = key.data(using: String.Encoding.utf8)
let baseKey = data?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
return baseKey!
}
/**
@ -669,16 +657,15 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
let settings = SSLSettings(useSSL: useSSL,
disableCertValidation: disableSSLCertValidation,
overrideTrustHostname: overrideTrustHostname,
desiredTrustHostname: desiredTrustHostname,
sslClientCertificate: sslClientCertificate)
desiredTrustHostname: desiredTrustHostname),
sslClientCertificate: sslClientCertificate
#else
let settings = SSLSettings(useSSL: useSSL,
disableCertValidation: disableSSLCertValidation,
overrideTrustHostname: overrideTrustHostname,
desiredTrustHostname: desiredTrustHostname,
sslClientCertificate: sslClientCertificate,
cipherSuites: enabledSSLCipherSuites,
socketSecurityLevel: socketSecurityLevel)
cipherSuites: self.enabledSSLCipherSuites)
#endif
certValidated = !useSSL
let timeout = request.timeoutInterval * 1_000_000
@ -1009,9 +996,9 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
let payloadLen = (PayloadLenMask & baseAddress[1])
var offset = 2
if compressionState.supportsCompression && receivedOpcode != .continueFrame {
currentMessageNeedsDecompression = (RSV1Mask & baseAddress[0]) > 0
compressionState.messageNeedsDecompression = (RSV1Mask & baseAddress[0]) > 0
}
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .pong && !currentMessageNeedsDecompression {
if (isMasked > 0 || (RSVMask & baseAddress[0]) > 0) && receivedOpcode != .pong && !compressionState.messageNeedsDecompression {
let errCode = CloseCode.protocolError.rawValue
doDisconnect(WSError(type: .protocolError, message: "masked and rsv data is not currently supported", code: Int(errCode)))
writeError(errCode)
@ -1072,7 +1059,7 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
len -= UInt64(size)
}
let data: Data
if currentMessageNeedsDecompression, let decompressor = compressionState.decompressor {
if compressionState.messageNeedsDecompression, let decompressor = compressionState.decompressor {
do {
data = try decompressor.decompress(bytes: baseAddress+offset, count: Int(len), finish: isFin > 0)
if isFin > 0 && compressionState.serverNoContextTakeover {
@ -1263,10 +1250,7 @@ open class WebSocket : NSObject, StreamDelegate, WebSocketClient, WSStreamDelega
}
buffer[1] |= self.MaskMask
let maskKey = UnsafeMutablePointer<UInt8>(buffer + offset)
guard SecRandomCopyBytes(kSecRandomDefault, Int(MemoryLayout<UInt32>.size), maskKey) == errSecSuccess else {
self.doDisconnect(WSError(type: .osError, message: "unable to generate random bytes", code: 0))
return
}
_ = SecRandomCopyBytes(kSecRandomDefault, Int(MemoryLayout<UInt32>.size), maskKey)
offset += MemoryLayout<UInt32>.size
for i in 0..<dataLength {