Fix unsafe user defaults usage

This commit is contained in:
Niels Andriesse 2020-02-19 16:45:38 +11:00
parent 7dcd2f2353
commit d99efa1c57
14 changed files with 76 additions and 22 deletions

View File

@ -12,8 +12,9 @@ final class LokiPushNotificationManager : NSObject {
@objc(registerWithToken:)
func register(with token: Data) {
let hexEncodedToken = token.map { String(format: "%02.2hhx", $0) }.joined()
let oldToken = UserDefaults.standard.string(forKey: "deviceToken")
let lastUploadTime = UserDefaults.standard.double(forKey: "lastDeviceTokenUploadTime")
let userDefaults = UserDefaults.standard
let oldToken = userDefaults[.deviceToken]
let lastUploadTime = userDefaults[.lastDeviceTokenUpload]
let now = Date().timeIntervalSince1970
if hexEncodedToken == oldToken && now - lastUploadTime < 2 * 24 * 60 * 60 {
print("[Loki] Device token hasn't changed; no need to upload.")
@ -29,8 +30,8 @@ final class LokiPushNotificationManager : NSObject {
guard json["code"] as? Int != 0 else {
return print("[Loki] An error occured during device token registration: \(json["message"] as? String ?? "nil").")
}
UserDefaults.standard.set(hexEncodedToken, forKey: "deviceToken")
UserDefaults.standard.set(now, forKey: "lastDeviceTokenUploadTime")
userDefaults[.deviceToken] = hexEncodedToken
userDefaults[.lastDeviceTokenUpload] = now
}, failure: { _, error in
print("[Loki] Couldn't register device token.")
})

View File

@ -92,7 +92,7 @@ final class DeviceNameModal : Modal {
@objc private func changeName() {
let name = nameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if !name.isEmpty {
UserDefaults.standard.set(name, forKey: "\(device.hexEncodedPublicKey)_display_name")
UserDefaults.standard[.slaveDeviceName(device.hexEncodedPublicKey)] = name
delegate?.handleDeviceNameChanged(to: name, for: device)
} else {
let alert = UIAlertController(title: NSLocalizedString("Error", comment: ""), message: NSLocalizedString("Please pick a name", comment: ""), preferredStyle: .alert)

View File

@ -88,8 +88,9 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
navigationItem.titleView = titleLabel
// Set up seed reminder view if needed
let hasViewedSeed = UserDefaults.standard.bool(forKey: "hasViewedSeed")
let isMasterDevice = (UserDefaults.standard.string(forKey: "masterDeviceHexEncodedPublicKey") == nil)
let userDefaults = UserDefaults.standard
let hasViewedSeed = userDefaults[.hasViewedSeed]
let isMasterDevice = userDefaults.isMasterDevice
if !hasViewedSeed && isMasterDevice {
view.addSubview(seedReminderView)
seedReminderView.pin(.leading, to: .leading, of: view)
@ -145,14 +146,14 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
isViewVisible = true
// let hasSeenOpenGroupSuggestionSheet = UserDefaults.standard.bool(forKey: "hasSeenOpenGroupSuggestionSheet")
// let hasSeenOpenGroupSuggestionSheet = UserDefaults.standard[.hasSeenOpenGroupSuggestionSheet]
// if !hasSeenOpenGroupSuggestionSheet {
// let openGroupSuggestionSheet = OpenGroupSuggestionSheet()
// openGroupSuggestionSheet.modalPresentationStyle = .overFullScreen
// openGroupSuggestionSheet.modalTransitionStyle = .crossDissolve
// present(openGroupSuggestionSheet, animated: true, completion: nil)
// }
UserDefaults.standard.set(true, forKey: "hasLaunchedOnce")
UserDefaults.standard[.hasLaunchedOnce] = true
}
override func viewWillDisappear(_ animated: Bool) {

View File

@ -100,7 +100,7 @@ final class LandingVC : UIViewController, LinkDeviceVCDelegate, DeviceLinkingMod
mainStackView.pin(to: view)
topSpacer.heightAnchor.constraint(equalTo: bottomSpacer.heightAnchor, multiplier: 1).isActive = true
// Show device unlinked alert if needed
if UserDefaults.standard.bool(forKey: "wasUnlinked") {
if UserDefaults.standard[.wasUnlinked] {
let alert = UIAlertController(title: NSLocalizedString("Device Unlinked", comment: ""), message: NSLocalizedString("Your device was unlinked successfully", comment: ""), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
present(alert, animated: true, completion: nil)
@ -190,8 +190,7 @@ final class LandingVC : UIViewController, LinkDeviceVCDelegate, DeviceLinkingMod
}
func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) {
let userDefaults = UserDefaults.standard
userDefaults.set(deviceLink.master.hexEncodedPublicKey, forKey: "masterDeviceHexEncodedPublicKey")
UserDefaults.standard[.masterHexEncodedPublicKey] = deviceLink.master.hexEncodedPublicKey
fakeChatViewContentOffset = fakeChatView.contentOffset
DispatchQueue.main.async {
self.fakeChatView.contentOffset = self.fakeChatViewContentOffset

View File

@ -155,7 +155,7 @@ private final class EnterPublicKeyVC : UIViewController {
weak var newPrivateChatVC: NewPrivateChatVC!
private lazy var userHexEncodedPublicKey: String = {
if let masterHexEncodedPublicKey = UserDefaults.standard.string(forKey: "masterDeviceHexEncodedPublicKey") {
if let masterHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] {
return masterHexEncodedPublicKey
} else {
return getUserHexEncodedPublicKey()

View File

@ -71,7 +71,7 @@ final class OpenGroupSuggestionSheet : Sheet {
}
override func close() {
UserDefaults.standard.set(true, forKey: "hasSeenOpenGroupSuggestionSheet")
UserDefaults.standard[.hasSeenOpenGroupSuggestionSheet] = true
super.close()
}
}

View File

@ -152,7 +152,7 @@ private final class ViewMyQRCodeVC : UIViewController {
private var bottomConstraint: NSLayoutConstraint!
private lazy var userHexEncodedPublicKey: String = {
if let masterHexEncodedPublicKey = UserDefaults.standard.string(forKey: "masterDeviceHexEncodedPublicKey") {
if let masterHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] {
return masterHexEncodedPublicKey
} else {
return getUserHexEncodedPublicKey()

View File

@ -187,7 +187,7 @@ final class RegisterVC : UIViewController {
databaseConnection.setObject(keyPair!, forKey: OWSPrimaryStorageIdentityKeyStoreIdentityKey, inCollection: OWSPrimaryStorageIdentityKeyStoreCollection)
TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair!.hexEncodedPublicKey
OWSPrimaryStorage.shared().setRestorationTime(0)
UserDefaults.standard.set(false, forKey: "hasViewedSeed")
UserDefaults.standard[.hasViewedSeed] = false
let displayNameVC = DisplayNameVC()
navigationController!.pushViewController(displayNameVC, animated: true)
}

View File

@ -178,7 +178,7 @@ final class RestoreVC : UIViewController {
databaseConnection.setObject(keyPair, forKey: OWSPrimaryStorageIdentityKeyStoreIdentityKey, inCollection: OWSPrimaryStorageIdentityKeyStoreCollection)
TSAccountManager.sharedInstance().phoneNumberAwaitingVerification = keyPair.hexEncodedPublicKey
OWSPrimaryStorage.shared().setRestorationTime(Date().timeIntervalSince1970)
UserDefaults.standard.set(true, forKey: "hasViewedSeed")
UserDefaults.standard[.hasViewedSeed] = true
mnemonicTextField.resignFirstResponder()
Timer.scheduledTimer(withTimeInterval: 0.25, repeats: false) { _ in
let displayNameVC = DisplayNameVC()

View File

@ -62,7 +62,7 @@ final class SeedModal : Modal {
contentView.pin(.trailing, to: .trailing, of: stackView, withInset: Values.largeSpacing)
contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.largeSpacing)
// Mark seed as viewed
UserDefaults.standard.set(true, forKey: "hasViewedSeed")
UserDefaults.standard[.hasViewedSeed] = true
NotificationCenter.default.post(name: .seedViewed, object: nil)
}

View File

@ -182,7 +182,7 @@ final class SeedVC : UIViewController {
self.seedReminderView.subtitle = NSLocalizedString("Make sure to store your recovery phrase in a safe place", comment: "")
}, completion: nil)
seedReminderView.setProgress(1, animated: true)
UserDefaults.standard.set(true, forKey: "hasViewedSeed")
UserDefaults.standard[.hasViewedSeed] = true
NotificationCenter.default.post(name: .seedViewed, object: nil)
}

View File

@ -5,7 +5,7 @@ final class SettingsVC : UIViewController, AvatarViewHelperDelegate {
private var isEditingDisplayName = false { didSet { handleIsEditingDisplayNameChanged() } }
private lazy var userHexEncodedPublicKey: String = {
if let masterHexEncodedPublicKey = UserDefaults.standard.string(forKey: "masterDeviceHexEncodedPublicKey") {
if let masterHexEncodedPublicKey = UserDefaults.standard[.masterHexEncodedPublicKey] {
return masterHexEncodedPublicKey
} else {
return getUserHexEncodedPublicKey()
@ -180,7 +180,7 @@ final class SettingsVC : UIViewController, AvatarViewHelperDelegate {
getSeparator(),
getSettingButton(withTitle: NSLocalizedString("Notifications", comment: ""), color: Colors.text, action: #selector(showNotificationSettings))
]
let isMasterDevice = (UserDefaults.standard.string(forKey: "masterDeviceHexEncodedPublicKey") == nil)
let isMasterDevice = UserDefaults.standard.isMasterDevice
if isMasterDevice {
result.append(getSeparator())
result.append(getSettingButton(withTitle: NSLocalizedString("Devices", comment: ""), color: Colors.text, action: #selector(showLinkedDevices)))

View File

@ -18,7 +18,7 @@ public final class DeviceLink : NSObject, NSCoding {
@objc public let signature: Data?
@objc public var displayName: String {
if let customDisplayName = UserDefaults.standard.string(forKey: "\(hexEncodedPublicKey)_display_name") {
if let customDisplayName = UserDefaults.standard[.slaveDeviceName(hexEncodedPublicKey)] {
return customDisplayName
} else {
return NSLocalizedString("Unnamed Device", comment: "")

View File

@ -0,0 +1,53 @@
import Foundation
public enum LKUserDefaults {
public enum Bool : Swift.String {
case hasLaunchedOnce
case hasSeenOpenGroupSuggestionSheet
case hasViewedSeed
/// Whether the device was unlinked as a slave device (used to notify the user on the landing screen).
case wasUnlinked
}
public enum Double : Swift.String {
case lastDeviceTokenUpload = "lastDeviceTokenUploadTime"
}
public enum String {
case slaveDeviceName(Swift.String)
case deviceToken
/// `nil` if this is a master device or if the user hasn't linked a device.
case masterHexEncodedPublicKey
public var key: Swift.String {
switch self {
case .slaveDeviceName(let hexEncodedPublicKey): return "\(hexEncodedPublicKey)_display_name"
case .deviceToken: return "deviceToken"
case .masterHexEncodedPublicKey: return "masterDeviceHexEncodedPublicKey"
}
}
}
}
public extension UserDefaults {
public subscript(bool: LKUserDefaults.Bool) -> Bool {
get { return self.bool(forKey: bool.rawValue) }
set { set(newValue, forKey: bool.rawValue) }
}
public subscript(double: LKUserDefaults.Double) -> Double {
get { return self.double(forKey: double.rawValue) }
set { set(newValue, forKey: double.rawValue) }
}
public subscript(string: LKUserDefaults.String) -> String? {
get { return self.string(forKey: string.key) }
set { set(newValue, forKey: string.key) }
}
public var isMasterDevice: Bool {
return (self[.masterHexEncodedPublicKey] == nil)
}
}