mirror of https://github.com/oxen-io/session-ios
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.3 KiB
Swift
197 lines
6.3 KiB
Swift
7 years ago
|
//
|
||
|
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||
|
//
|
||
|
|
||
|
import Foundation
|
||
|
import PromiseKit
|
||
|
|
||
|
public enum OWSUDError: Error {
|
||
|
case assertionError(description: String)
|
||
|
}
|
||
|
|
||
|
@objc public protocol OWSUDManager: class {
|
||
|
|
||
7 years ago
|
@objc func setup()
|
||
|
|
||
|
// MARK: - Recipient state
|
||
|
|
||
7 years ago
|
@objc func isUDRecipientId(_ recipientId: String) -> Bool
|
||
|
|
||
|
// No-op if this recipient id is already marked as a "UD recipient".
|
||
|
@objc func addUDRecipientId(_ recipientId: String)
|
||
|
|
||
|
// No-op if this recipient id is already marked as _NOT_ a "UD recipient".
|
||
|
@objc func removeUDRecipientId(_ recipientId: String)
|
||
7 years ago
|
|
||
|
@objc func ensureServerCertificateObjC(success:@escaping (Data) -> Void,
|
||
|
failure:@escaping (Error) -> Void)
|
||
7 years ago
|
}
|
||
|
|
||
|
// MARK: -
|
||
|
|
||
|
@objc
|
||
|
public class OWSUDManagerImpl: NSObject, OWSUDManager {
|
||
|
|
||
|
private let dbConnection: YapDatabaseConnection
|
||
|
|
||
|
private let kUDRecipientModeCollection = "kUDRecipientModeCollection"
|
||
|
private let kUDCollection = "kUDCollection"
|
||
|
private let kUDCurrentServerCertificateKey = "kUDCurrentServerCertificateKey"
|
||
|
|
||
|
@objc
|
||
|
public required init(primaryStorage: OWSPrimaryStorage) {
|
||
|
self.dbConnection = primaryStorage.newDatabaseConnection()
|
||
|
|
||
|
super.init()
|
||
|
|
||
|
SwiftSingletons.register(self)
|
||
|
}
|
||
|
|
||
7 years ago
|
@objc public func setup() {
|
||
|
AppReadiness.runNowOrWhenAppIsReady {
|
||
|
guard TSAccountManager.isRegistered() else {
|
||
|
return
|
||
|
}
|
||
|
self.ensureServerCertificate().retainUntilComplete()
|
||
|
}
|
||
|
NotificationCenter.default.addObserver(self,
|
||
|
selector: #selector(registrationStateDidChange),
|
||
|
name: .RegistrationStateDidChange,
|
||
|
object: nil)
|
||
|
}
|
||
|
|
||
|
@objc
|
||
|
func registrationStateDidChange() {
|
||
|
AssertIsOnMainThread()
|
||
|
|
||
|
ensureServerCertificate().retainUntilComplete()
|
||
|
}
|
||
|
|
||
7 years ago
|
// MARK: - Singletons
|
||
|
|
||
|
private var networkManager: TSNetworkManager {
|
||
|
return SSKEnvironment.shared.networkManager
|
||
|
}
|
||
|
|
||
|
// MARK: - Recipient state
|
||
|
|
||
|
@objc
|
||
|
public func isUDRecipientId(_ recipientId: String) -> Bool {
|
||
|
return dbConnection.bool(forKey: recipientId, inCollection: kUDRecipientModeCollection, defaultValue: false)
|
||
|
}
|
||
|
|
||
|
@objc
|
||
|
public func addUDRecipientId(_ recipientId: String) {
|
||
|
dbConnection.setBool(true, forKey: recipientId, inCollection: kUDRecipientModeCollection)
|
||
|
}
|
||
|
|
||
|
@objc
|
||
|
public func removeUDRecipientId(_ recipientId: String) {
|
||
|
dbConnection.removeObject(forKey: recipientId, inCollection: kUDRecipientModeCollection)
|
||
|
}
|
||
|
|
||
|
// MARK: - Server Certificate
|
||
|
|
||
|
#if DEBUG
|
||
|
@objc
|
||
|
public func hasServerCertificate() -> Bool {
|
||
|
return serverCertificate() != nil
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
private func serverCertificate() -> Data? {
|
||
7 years ago
|
return nil
|
||
7 years ago
|
guard let certificateData = dbConnection.object(forKey: kUDCurrentServerCertificateKey, inCollection: kUDCollection) as? Data else {
|
||
|
return nil
|
||
|
}
|
||
7 years ago
|
|
||
|
// Parse certificate and ensure that it is still valid.
|
||
|
guard !isCertificateExpired(certificateData: certificateData) else {
|
||
|
Logger.warn("Current server certificate has expired.")
|
||
|
return nil
|
||
|
}
|
||
|
|
||
7 years ago
|
return certificateData
|
||
|
}
|
||
|
|
||
|
private func setServerCertificate(_ certificateData: Data) {
|
||
|
dbConnection.setObject(certificateData, forKey: kUDCurrentServerCertificateKey, inCollection: kUDCollection)
|
||
|
}
|
||
|
|
||
|
@objc
|
||
|
public func ensureServerCertificateObjC(success:@escaping (Data) -> Void,
|
||
|
failure:@escaping (Error) -> Void) {
|
||
|
ensureServerCertificate()
|
||
|
.then(execute: { certificateData in
|
||
|
success(certificateData)
|
||
|
})
|
||
|
.catch(execute: { (error) in
|
||
|
failure(error)
|
||
|
}).retainUntilComplete()
|
||
|
}
|
||
|
|
||
|
public func ensureServerCertificate() -> Promise<Data> {
|
||
|
return Promise { fulfill, reject in
|
||
7 years ago
|
// If there is a valid cached server certificate, use that.
|
||
7 years ago
|
if let certificateData = serverCertificate() {
|
||
|
fulfill(certificateData)
|
||
|
return
|
||
|
}
|
||
|
// Try to obtain a new server certificate.
|
||
|
requestServerCertificate()
|
||
|
.then(execute: { certificateData in
|
||
|
fulfill(certificateData)
|
||
|
})
|
||
|
.catch(execute: { (error) in
|
||
|
reject(error)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private func requestServerCertificate() -> Promise<Data> {
|
||
|
return Promise { fulfill, reject in
|
||
|
let request = OWSRequestFactory.udServerCertificateRequest()
|
||
|
self.networkManager.makeRequest(
|
||
|
request,
|
||
|
success: { (_: URLSessionDataTask?, responseObject: Any?) -> Void in
|
||
|
do {
|
||
|
let certificateData = try self.parseServerCertificateResponse(responseObject: responseObject)
|
||
|
|
||
7 years ago
|
guard !self.isCertificateExpired(certificateData: certificateData) else {
|
||
|
reject (OWSUDError.assertionError(description: "Invalid server certificate returned by server"))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
// Cache the current server certificate.
|
||
|
self.setServerCertificate(certificateData)
|
||
|
|
||
7 years ago
|
fulfill(certificateData)
|
||
|
} catch {
|
||
|
reject(error)
|
||
|
}
|
||
|
},
|
||
|
failure: { (_: URLSessionDataTask?, error: Error?) in
|
||
|
guard let error = error else {
|
||
|
Logger.error("Missing error.")
|
||
|
return
|
||
|
}
|
||
|
|
||
|
reject(error)
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private func parseServerCertificateResponse(responseObject: Any?) throws -> Data {
|
||
|
guard let parser = ParamParser(responseObject: responseObject) else {
|
||
|
throw OWSUDError.assertionError(description: "Invalid server certificate response")
|
||
|
}
|
||
|
|
||
|
return try parser.requiredBase64EncodedData(key: "certificate")
|
||
|
}
|
||
7 years ago
|
|
||
|
private func isCertificateExpired(certificateData: Data) -> Bool {
|
||
|
// TODO:
|
||
|
return false
|
||
|
}
|
||
7 years ago
|
}
|