aboutsummaryrefslogtreecommitdiffstats
path: root/WireGuard/WireGuard
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-02-06 03:23:51 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2019-02-06 06:20:23 +0100
commitbebcaa012bfafb5ab1a8ee4db11feffd3843c52c (patch)
treeee89b91f60bd267c356b0931d72bde9a288c8771 /WireGuard/WireGuard
parentLegacyConfig: Remove and support plaintext for .mobileconfig (diff)
downloadwireguard-apple-bebcaa012bfafb5ab1a8ee4db11feffd3843c52c.tar.xz
wireguard-apple-bebcaa012bfafb5ab1a8ee4db11feffd3843c52c.zip
PrivateDataConfirmation: prompt with touch/face/pin/password ID for viewing/exporting keys
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'WireGuard/WireGuard')
-rw-r--r--WireGuard/WireGuard/Base.lproj/Localizable.strings7
-rw-r--r--WireGuard/WireGuard/UI/PrivateDataConfirmation.swift37
-rw-r--r--WireGuard/WireGuard/UI/iOS/Info.plist2
-rw-r--r--WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift31
-rw-r--r--WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift13
-rw-r--r--WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift11
-rw-r--r--WireGuard/WireGuard/UI/macOS/ViewController/TunnelsListTableViewController.swift36
7 files changed, 98 insertions, 39 deletions
diff --git a/WireGuard/WireGuard/Base.lproj/Localizable.strings b/WireGuard/WireGuard/Base.lproj/Localizable.strings
index c93c702f..25d77393 100644
--- a/WireGuard/WireGuard/Base.lproj/Localizable.strings
+++ b/WireGuard/WireGuard/Base.lproj/Localizable.strings
@@ -316,3 +316,10 @@
"macAppVersion (%@)" = "App version: %@";
"macGoBackendVersion (%@)" = "Go backend version: %@";
+
+// Privacy
+
+"macExportPrivateData" = "export tunnel private keys";
+"macViewPrivateData" = "view tunnel private keys";
+"iosExportPrivateData" = "Authenticate to export tunnel private keys.";
+"iosViewPrivateData" = "Authenticate to view tunnel private keys.";
diff --git a/WireGuard/WireGuard/UI/PrivateDataConfirmation.swift b/WireGuard/WireGuard/UI/PrivateDataConfirmation.swift
new file mode 100644
index 00000000..c03e64a7
--- /dev/null
+++ b/WireGuard/WireGuard/UI/PrivateDataConfirmation.swift
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
+
+import Foundation
+import LocalAuthentication
+#if os(macOS)
+import AppKit
+#endif
+
+class PrivateDataConfirmation {
+ static func confirmAccess(to reason: String, _ after: @escaping () -> Void) {
+ let context = LAContext()
+
+ var error: NSError?
+ if !context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
+ guard let error = error as? LAError else { return }
+ if error.code == .passcodeNotSet {
+ // We give no protection to folks who just don't set a passcode.
+ after()
+ }
+ return
+ }
+
+ context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, _ in
+ DispatchQueue.main.async {
+ #if os(macOS)
+ if !NSApp.isActive {
+ NSApp.activate(ignoringOtherApps: true)
+ }
+ #endif
+ if success {
+ after()
+ }
+ }
+ }
+ }
+}
diff --git a/WireGuard/WireGuard/UI/iOS/Info.plist b/WireGuard/WireGuard/UI/iOS/Info.plist
index 2a943eb0..0c2d8b06 100644
--- a/WireGuard/WireGuard/UI/iOS/Info.plist
+++ b/WireGuard/WireGuard/UI/iOS/Info.plist
@@ -122,6 +122,8 @@
</dict>
</dict>
</array>
+ <key>NSFaceIDUsageDescription</key>
+ <string>Face ID is used for authenticating viewing and exporting of private keys</string>
<key>com.wireguard.ios.app_group_id</key>
<string>group.$(APP_ID_IOS)</string>
</dict>
diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift
index 64cd0f7d..3addea46 100644
--- a/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift
+++ b/WireGuard/WireGuard/UI/iOS/ViewController/SettingsTableViewController.swift
@@ -86,22 +86,25 @@ class SettingsTableViewController: UITableViewController {
}
func exportConfigurationsAsZipFile(sourceView: UIView) {
- guard let tunnelsManager = tunnelsManager else { return }
- guard let destinationDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
-
- let destinationURL = destinationDir.appendingPathComponent("wireguard-export.zip")
- _ = FileManager.deleteFile(at: destinationURL)
+ PrivateDataConfirmation.confirmAccess(to: tr("iosExportPrivateData")) { [weak self] in
+ guard let self = self else { return }
+ guard let tunnelsManager = self.tunnelsManager else { return }
+ guard let destinationDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
+
+ let destinationURL = destinationDir.appendingPathComponent("wireguard-export.zip")
+ _ = FileManager.deleteFile(at: destinationURL)
+
+ let count = tunnelsManager.numberOfTunnels()
+ let tunnelConfigurations = (0 ..< count).compactMap { tunnelsManager.tunnel(at: $0).tunnelConfiguration }
+ ZipExporter.exportConfigFiles(tunnelConfigurations: tunnelConfigurations, to: destinationURL) { [weak self] error in
+ if let error = error {
+ ErrorPresenter.showErrorAlert(error: error, from: self)
+ return
+ }
- let count = tunnelsManager.numberOfTunnels()
- let tunnelConfigurations = (0 ..< count).compactMap { tunnelsManager.tunnel(at: $0).tunnelConfiguration }
- ZipExporter.exportConfigFiles(tunnelConfigurations: tunnelConfigurations, to: destinationURL) { [weak self] error in
- if let error = error {
- ErrorPresenter.showErrorAlert(error: error, from: self)
- return
+ let fileExportVC = UIDocumentPickerViewController(url: destinationURL, in: .exportToService)
+ self?.present(fileExportVC, animated: true, completion: nil)
}
-
- let fileExportVC = UIDocumentPickerViewController(url: destinationURL, in: .exportToService)
- self?.present(fileExportVC, animated: true, completion: nil)
}
}
diff --git a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift
index 955bf91e..f65ca237 100644
--- a/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift
+++ b/WireGuard/WireGuard/UI/iOS/ViewController/TunnelDetailTableViewController.swift
@@ -103,11 +103,14 @@ class TunnelDetailTableViewController: UITableViewController {
}
@objc func editTapped() {
- let editVC = TunnelEditTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
- editVC.delegate = self
- let editNC = UINavigationController(rootViewController: editVC)
- editNC.modalPresentationStyle = .formSheet
- present(editNC, animated: true)
+ PrivateDataConfirmation.confirmAccess(to: tr("iosViewPrivateData")) { [weak self] in
+ guard let self = self else { return }
+ let editVC = TunnelEditTableViewController(tunnelsManager: self.tunnelsManager, tunnel: self.tunnel)
+ editVC.delegate = self
+ let editNC = UINavigationController(rootViewController: editVC)
+ editNC.modalPresentationStyle = .formSheet
+ self.present(editNC, animated: true)
+ }
}
func showConfirmationAlert(message: String, buttonTitle: String, from sourceView: UIView, onConfirmed: @escaping (() -> Void)) {
diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift
index 89dcbe8c..d7dcb5ff 100644
--- a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift
+++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelDetailTableViewController.swift
@@ -227,10 +227,13 @@ class TunnelDetailTableViewController: NSViewController {
}
@objc func handleEditTunnelAction() {
- let tunnelEditVC = TunnelEditViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
- tunnelEditVC.delegate = self
- presentAsSheet(tunnelEditVC)
- self.tunnelEditVC = tunnelEditVC
+ PrivateDataConfirmation.confirmAccess(to: tr("macViewPrivateData")) { [weak self] in
+ guard let self = self else { return }
+ let tunnelEditVC = TunnelEditViewController(tunnelsManager: self.tunnelsManager, tunnel: self.tunnel)
+ tunnelEditVC.delegate = self
+ self.presentAsSheet(tunnelEditVC)
+ self.tunnelEditVC = tunnelEditVC
+ }
}
@objc func handleToggleActiveStatusAction() {
diff --git a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelsListTableViewController.swift
index e83e6165..cfeb8f1f 100644
--- a/WireGuard/WireGuard/UI/macOS/ViewController/TunnelsListTableViewController.swift
+++ b/WireGuard/WireGuard/UI/macOS/ViewController/TunnelsListTableViewController.swift
@@ -207,22 +207,26 @@ class TunnelsListTableViewController: NSViewController {
}
@objc func handleExportTunnelsAction() {
- guard let window = view.window else { return }
- let savePanel = NSSavePanel()
- savePanel.allowedFileTypes = ["zip"]
- savePanel.prompt = tr("macSheetButtonExportZip")
- savePanel.nameFieldLabel = tr("macNameFieldExportZip")
- savePanel.nameFieldStringValue = "wireguard-export.zip"
- savePanel.beginSheetModal(for: window) { [weak tunnelsManager] response in
- guard let tunnelsManager = tunnelsManager else { return }
- guard response == .OK else { return }
- guard let destinationURL = savePanel.url else { return }
- let count = tunnelsManager.numberOfTunnels()
- let tunnelConfigurations = (0 ..< count).compactMap { tunnelsManager.tunnel(at: $0).tunnelConfiguration }
- ZipExporter.exportConfigFiles(tunnelConfigurations: tunnelConfigurations, to: destinationURL) { [weak self] error in
- if let error = error {
- ErrorPresenter.showErrorAlert(error: error, from: self)
- return
+ PrivateDataConfirmation.confirmAccess(to: tr("macExportPrivateData")) { [weak self] in
+ guard let self = self else { return }
+ guard let window = self.view.window else { return }
+ let savePanel = NSSavePanel()
+ savePanel.allowedFileTypes = ["zip"]
+ savePanel.prompt = tr("macSheetButtonExportZip")
+ savePanel.nameFieldLabel = tr("macNameFieldExportZip")
+ savePanel.nameFieldStringValue = "wireguard-export.zip"
+ let tunnelsManager = self.tunnelsManager
+ savePanel.beginSheetModal(for: window) { [weak tunnelsManager] response in
+ guard let tunnelsManager = tunnelsManager else { return }
+ guard response == .OK else { return }
+ guard let destinationURL = savePanel.url else { return }
+ let count = tunnelsManager.numberOfTunnels()
+ let tunnelConfigurations = (0 ..< count).compactMap { tunnelsManager.tunnel(at: $0).tunnelConfiguration }
+ ZipExporter.exportConfigFiles(tunnelConfigurations: tunnelConfigurations, to: destinationURL) { [weak self] error in
+ if let error = error {
+ ErrorPresenter.showErrorAlert(error: error, from: self)
+ return
+ }
}
}
}