Respond to CR.

pull/1/head
Matthew Chen 7 years ago
parent e98c572158
commit dca46e019f

@ -24,6 +24,11 @@ public enum OWSUDError: Error {
// No-op if this recipient id is already marked as _NOT_ a "UD recipient". // No-op if this recipient id is already marked as _NOT_ a "UD recipient".
@objc func removeUDRecipientId(_ recipientId: String) @objc func removeUDRecipientId(_ recipientId: String)
// We use completion handlers instead of a promise so that message sending
// logic can access the certificate data.
@objc func ensureSenderCertificateObjC(success:@escaping (Data) -> Void,
failure:@escaping (Error) -> Void)
} }
// MARK: - // MARK: -
@ -99,7 +104,6 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
#endif #endif
private func senderCertificate() -> Data? { private func senderCertificate() -> Data? {
return nil
guard let certificateData = dbConnection.object(forKey: kUDCurrentSenderCertificateKey, inCollection: kUDCollection) as? Data else { guard let certificateData = dbConnection.object(forKey: kUDCurrentSenderCertificateKey, inCollection: kUDCollection) as? Data else {
return nil return nil
} }
@ -129,54 +133,29 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
} }
public func ensureSenderCertificate() -> Promise<Data> { public func ensureSenderCertificate() -> Promise<Data> {
return Promise { fulfill, reject in // If there is a valid cached sender certificate, use that.
// If there is a valid cached sender certificate, use that. if let certificateData = senderCertificate() {
if let certificateData = senderCertificate() { return Promise(value: certificateData)
fulfill(certificateData)
return
}
// Try to obtain a new sender certificate.
requestSenderCertificate()
.then(execute: { certificateData in
fulfill(certificateData)
})
.catch(execute: { (error) in
reject(error)
})
} }
// Try to obtain a new sender certificate.
return requestSenderCertificate()
} }
private func requestSenderCertificate() -> Promise<Data> { private func requestSenderCertificate() -> Promise<Data> {
return Promise { fulfill, reject in let request = OWSRequestFactory.udSenderCertificateRequest()
let request = OWSRequestFactory.udSenderCertificateRequest() return self.networkManager.makePromise(request: request)
self.networkManager.makeRequest( .then(execute: { (_, responseObject) -> Data in
request, let certificateData = try self.parseSenderCertificateResponse(responseObject: responseObject)
success: { (_: URLSessionDataTask?, responseObject: Any?) -> Void in
do { guard self.isValidCertificate(certificateData: certificateData) else {
let certificateData = try self.parseSenderCertificateResponse(responseObject: responseObject) throw OWSUDError.assertionError(description: "Invalid sender certificate returned by server")
}
guard self.isValidCertificate(certificateData: certificateData) else {
reject (OWSUDError.assertionError(description: "Invalid sender certificate returned by server")) // Cache the current sender certificate.
return self.setSenderCertificate(certificateData)
}
return certificateData
// Cache the current sender certificate.
self.setSenderCertificate(certificateData)
fulfill(certificateData)
} catch {
reject(error)
}
},
failure: { (_: URLSessionDataTask?, error: Error?) in
guard let error = error else {
Logger.error("Missing error.")
return
}
reject(error)
}) })
}
} }
private func parseSenderCertificateResponse(responseObject: Any?) throws -> Data { private func parseSenderCertificateResponse(responseObject: Any?) throws -> Data {
@ -190,9 +169,13 @@ public class OWSUDManagerImpl: NSObject, OWSUDManager {
private func isValidCertificate(certificateData: Data) -> Bool { private func isValidCertificate(certificateData: Data) -> Bool {
do { do {
let certificate = try SMKSenderCertificate.parse(data: certificateData) let certificate = try SMKSenderCertificate.parse(data: certificateData)
let expirationDate = NSDate.ows_date(withMillisecondsSince1970: certificate.expirationTimestamp) let expirationMs = certificate.expirationTimestamp
// TODO: What's the cutoff for rotating your sender cert? A day or two before expiration? let nowMs = NSDate.ows_millisecondTimeStamp()
return (expirationDate as NSDate).isAfterNow() // Ensure that the certificate will not expire in the next hour.
// We want a threshold long enough to ensure that any outgoing message
// sends will complete before the expiration.
let isValid = nowMs + kHourInMs < expirationMs
return isValid
} catch { } catch {
OWSLogger.error("Certificate could not be parsed: \(error)") OWSLogger.error("Certificate could not be parsed: \(error)")
return false return false

@ -29,6 +29,20 @@ public class OWSFakeUDManager: NSObject, OWSUDManager {
public func removeUDRecipientId(_ recipientId: String) { public func removeUDRecipientId(_ recipientId: String) {
udRecipientSet.remove(recipientId) udRecipientSet.remove(recipientId)
} }
// MARK: - Server Certificate
// Tests can control the behavior of this mock by setting this property.
@objc public var nextSenderCertificate: Data?
@objc public func ensureSenderCertificateObjC(success:@escaping (Data) -> Void,
failure:@escaping (Error) -> Void) {
guard let certificateData = nextSenderCertificate else {
failure(OWSUDError.assertionError(description: "No mock server certificate data"))
return
}
success(certificateData)
}
} }
#endif #endif

@ -5,9 +5,6 @@
#import "Contact.h" #import "Contact.h"
#import "SSKBaseTestObjC.h" #import "SSKBaseTestObjC.h"
//#import "SignalServiceKit_Unit_Tests-Swift.h"
//#import <SignalServiceKit_Unit_Tests/SignalServiceKit_Unit_Tests-Swift.h>
@import Contacts; @import Contacts;
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN

Loading…
Cancel
Save