Fix clock out of sync error not propagating

pull/220/head
nielsandriesse 5 years ago
parent 042535778b
commit f0d56cdab0

@ -58,7 +58,7 @@ internal class LokiFileServerProxy : LokiHTTPClient {
let parametersAsString: String let parametersAsString: String
if let tsRequest = request as? TSRequest { if let tsRequest = request as? TSRequest {
headers["Content-Type"] = "application/json" headers["Content-Type"] = "application/json"
let parametersAsData = try JSONSerialization.data(withJSONObject: tsRequest.parameters, options: []) let parametersAsData = try JSONSerialization.data(withJSONObject: tsRequest.parameters, options: [ .fragmentsAllowed ])
parametersAsString = !tsRequest.parameters.isEmpty ? String(bytes: parametersAsData, encoding: .utf8)! : "null" parametersAsString = !tsRequest.parameters.isEmpty ? String(bytes: parametersAsData, encoding: .utf8)! : "null"
} else { } else {
headers["Content-Type"] = request.allHTTPHeaderFields!["Content-Type"] headers["Content-Type"] = request.allHTTPHeaderFields!["Content-Type"]
@ -74,7 +74,7 @@ internal class LokiFileServerProxy : LokiHTTPClient {
"method" : request.httpMethod, "method" : request.httpMethod,
"headers" : headers "headers" : headers
] ]
let proxyRequestParametersAsData = try JSONSerialization.data(withJSONObject: proxyRequestParameters, options: []) let proxyRequestParametersAsData = try JSONSerialization.data(withJSONObject: proxyRequestParameters, options: [ .fragmentsAllowed ])
let ivAndCipherText = try DiffieHellman.encrypt(proxyRequestParametersAsData, using: symmetricKey) let ivAndCipherText = try DiffieHellman.encrypt(proxyRequestParametersAsData, using: symmetricKey)
let base64EncodedPublicKey = Data(hex: keyPair.hexEncodedPublicKey).base64EncodedString() // The file server expects an 05 prefixed public key let base64EncodedPublicKey = Data(hex: keyPair.hexEncodedPublicKey).base64EncodedString() // The file server expects an 05 prefixed public key
let proxyRequestHeaders = [ let proxyRequestHeaders = [
@ -103,7 +103,7 @@ internal class LokiFileServerProxy : LokiHTTPClient {
task.resume() task.resume()
return promise return promise
}.map2 { rawResponse in }.map2 { rawResponse in
guard let responseAsData = rawResponse as? Data, let responseAsJSON = try? JSONSerialization.jsonObject(with: responseAsData, options: .allowFragments) as? JSON, let base64EncodedCipherText = responseAsJSON["data"] as? String, guard let responseAsData = rawResponse as? Data, let responseAsJSON = try? JSONSerialization.jsonObject(with: responseAsData, options: [ .fragmentsAllowed ]) as? JSON, let base64EncodedCipherText = responseAsJSON["data"] as? String,
let meta = responseAsJSON["meta"] as? JSON, let statusCode = meta["code"] as? Int, let cipherText = Data(base64Encoded: base64EncodedCipherText) else { let meta = responseAsJSON["meta"] as? JSON, let statusCode = meta["code"] as? Int, let cipherText = Data(base64Encoded: base64EncodedCipherText) else {
print("[Loki] Received an invalid response.") print("[Loki] Received an invalid response.")
throw Error.proxyResponseParsingFailed throw Error.proxyResponseParsingFailed
@ -112,7 +112,7 @@ internal class LokiFileServerProxy : LokiHTTPClient {
guard isSuccess else { throw HTTPError.networkError(code: statusCode, response: nil, underlyingError: Error.fileServerHTTPError(code: statusCode, message: nil)) } guard isSuccess else { throw HTTPError.networkError(code: statusCode, response: nil, underlyingError: Error.fileServerHTTPError(code: statusCode, message: nil)) }
let uncheckedJSONAsData = try DiffieHellman.decrypt(cipherText, using: symmetricKey) let uncheckedJSONAsData = try DiffieHellman.decrypt(cipherText, using: symmetricKey)
if uncheckedJSONAsData.isEmpty { return () } if uncheckedJSONAsData.isEmpty { return () }
let uncheckedJSON = try? JSONSerialization.jsonObject(with: uncheckedJSONAsData, options: .allowFragments) as? JSON let uncheckedJSON = try? JSONSerialization.jsonObject(with: uncheckedJSONAsData, options: [ .fragmentsAllowed ]) as? JSON
guard let json = uncheckedJSON else { throw HTTPError.networkError(code: -1, response: nil, underlyingError: Error.proxyResponseParsingFailed) } guard let json = uncheckedJSON else { throw HTTPError.networkError(code: -1, response: nil, underlyingError: Error.proxyResponseParsingFailed) }
return json return json
}.done2 { rawResponse in }.done2 { rawResponse in

@ -44,7 +44,7 @@ public extension LokiHTTPClient {
if case NetworkManagerError.taskError(_, let underlyingError) = error, let nsError = underlyingError as? NSError { if case NetworkManagerError.taskError(_, let underlyingError) = error, let nsError = underlyingError as? NSError {
var response = nsError.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] var response = nsError.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey]
// Deserialize response if needed // Deserialize response if needed
if let data = response as? Data, let json = try? JSONSerialization.jsonObject(with: data, options: []) as? JSON { if let data = response as? Data, let json = try? JSONSerialization.jsonObject(with: data, options: [ .fragmentsAllowed ]) as? JSON {
response = json response = json
} }
return LokiHTTPClient.HTTPError.networkError(code: error.statusCode, response: response, underlyingError: underlyingError) return LokiHTTPClient.HTTPError.networkError(code: error.statusCode, response: response, underlyingError: underlyingError)

@ -36,11 +36,11 @@ extension OnionRequestAPI {
DispatchQueue.global(qos: .userInitiated).async { DispatchQueue.global(qos: .userInitiated).async {
do { do {
guard JSONSerialization.isValidJSONObject(payload) else { return seal.reject(HTTP.Error.invalidJSON) } guard JSONSerialization.isValidJSONObject(payload) else { return seal.reject(HTTP.Error.invalidJSON) }
let payloadAsData = try JSONSerialization.data(withJSONObject: payload, options: []) let payloadAsData = try JSONSerialization.data(withJSONObject: payload, options: [ .fragmentsAllowed ])
let payloadAsString = String(data: payloadAsData, encoding: .utf8)! // Snodes only accept this as a string let payloadAsString = String(data: payloadAsData, encoding: .utf8)! // Snodes only accept this as a string
let wrapper: JSON = [ "body" : payloadAsString, "headers" : "" ] let wrapper: JSON = [ "body" : payloadAsString, "headers" : "" ]
guard JSONSerialization.isValidJSONObject(wrapper) else { return seal.reject(HTTP.Error.invalidJSON) } guard JSONSerialization.isValidJSONObject(wrapper) else { return seal.reject(HTTP.Error.invalidJSON) }
let plaintext = try JSONSerialization.data(withJSONObject: wrapper, options: []) let plaintext = try JSONSerialization.data(withJSONObject: wrapper, options: [ .fragmentsAllowed ])
let result = try encrypt(plaintext, forSnode: snode) let result = try encrypt(plaintext, forSnode: snode)
seal.fulfill(result) seal.fulfill(result)
} catch (let error) { } catch (let error) {
@ -61,7 +61,7 @@ extension OnionRequestAPI {
] ]
do { do {
guard JSONSerialization.isValidJSONObject(parameters) else { return seal.reject(HTTP.Error.invalidJSON) } guard JSONSerialization.isValidJSONObject(parameters) else { return seal.reject(HTTP.Error.invalidJSON) }
let plaintext = try JSONSerialization.data(withJSONObject: parameters, options: []) let plaintext = try JSONSerialization.data(withJSONObject: parameters, options: [ .fragmentsAllowed ])
let result = try encrypt(plaintext, forSnode: lhs) let result = try encrypt(plaintext, forSnode: lhs)
seal.fulfill(result) seal.fulfill(result)
} catch (let error) { } catch (let error) {

@ -228,12 +228,17 @@ public enum OnionRequestAPI {
let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagSize), mode: .combined) let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagSize), mode: .combined)
let aes = try AES(key: targetSnodeSymmetricKey.bytes, blockMode: gcm, padding: .noPadding) let aes = try AES(key: targetSnodeSymmetricKey.bytes, blockMode: gcm, padding: .noPadding)
let data = Data(try aes.decrypt(ciphertext.bytes)) let data = Data(try aes.decrypt(ciphertext.bytes))
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? JSON, guard let json = try JSONSerialization.jsonObject(with: data, options: [ .fragmentsAllowed ]) as? JSON,
let bodyAsString = json["body"] as? String, let bodyAsData = bodyAsString.data(using: .utf8), let bodyAsString = json["body"] as? String, let statusCode = json["status"] as? Int else { return seal.reject(HTTP.Error.invalidJSON) }
let body = try JSONSerialization.jsonObject(with: bodyAsData, options: []) as? JSON, if statusCode == 406 { // Clock out of sync
let statusCode = json["status"] as? Int else { return seal.reject(HTTP.Error.invalidJSON) } print("[Loki] The user's clock is out of sync with the service node network.")
seal.reject(LokiAPI.LokiAPIError.clockOutOfSync)
} else {
guard let bodyAsData = bodyAsString.data(using: .utf8),
let body = try JSONSerialization.jsonObject(with: bodyAsData, options: [ .fragmentsAllowed ]) as? JSON else { return seal.reject(HTTP.Error.invalidJSON) }
guard 200...299 ~= statusCode else { return seal.reject(Error.httpRequestFailedAtTargetSnode(statusCode: UInt(statusCode), json: body)) } guard 200...299 ~= statusCode else { return seal.reject(Error.httpRequestFailedAtTargetSnode(statusCode: UInt(statusCode), json: body)) }
seal.fulfill(body) seal.fulfill(body)
}
} catch (let error) { } catch (let error) {
seal.reject(error) seal.reject(error)
} }

@ -46,7 +46,7 @@ internal enum HTTP {
if let parameters = parameters { if let parameters = parameters {
do { do {
guard JSONSerialization.isValidJSONObject(parameters) else { return Promise(error: Error.invalidJSON) } guard JSONSerialization.isValidJSONObject(parameters) else { return Promise(error: Error.invalidJSON) }
request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: []) request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [ .fragmentsAllowed ])
} catch (let error) { } catch (let error) {
return Promise(error: error) return Promise(error: error)
} }
@ -70,7 +70,7 @@ internal enum HTTP {
} }
let statusCode = UInt(response.statusCode) let statusCode = UInt(response.statusCode)
var json: JSON? = nil var json: JSON? = nil
if let j = try? JSONSerialization.jsonObject(with: data, options: []) as? JSON { if let j = try? JSONSerialization.jsonObject(with: data, options: [ .fragmentsAllowed ]) as? JSON {
json = j json = j
} else if let result = String(data: data, encoding: .utf8) { } else if let result = String(data: data, encoding: .utf8) {
json = [ "result" : result ] json = [ "result" : result ]

Loading…
Cancel
Save