From bbae36a29c8f97a2f650d6caaa84b91c96de98d8 Mon Sep 17 00:00:00 2001 From: Max Goedjen Date: Wed, 23 Sep 2020 21:32:36 -0700 Subject: [PATCH] Prompting for access. --- SecretAgentKit/Agent.swift | 2 +- SecretAgentKit/SigningRequestTracer.swift | 1 + SecretKit/Common/Erasers/AnySecretStore.swift | 8 ++++---- SecretKit/Common/Types/SecretStore.swift | 2 +- .../Common/Types}/SigningRequestProvenance.swift | 6 +++--- SecretKit/SecureEnclave/SecureEnclaveStore.swift | 4 ++-- SecretKit/SmartCard/SmartCardStore.swift | 7 ++++++- Secretive.xcodeproj/project.pbxproj | 6 +++--- 8 files changed, 21 insertions(+), 15 deletions(-) rename {SecretAgentKit => SecretKit/Common/Types}/SigningRequestProvenance.swift (79%) diff --git a/SecretAgentKit/Agent.swift b/SecretAgentKit/Agent.swift index 879ca92..02727c3 100644 --- a/SecretAgentKit/Agent.swift +++ b/SecretAgentKit/Agent.swift @@ -93,7 +93,7 @@ extension Agent { } let dataToSign = reader.readNextChunk() - let derSignature = try store.sign(data: dataToSign, with: secret) + let derSignature = try store.sign(data: dataToSign, with: secret, for: provenance) let curveData = writer.curveType(for: secret.algorithm, length: secret.keySize).data(using: .utf8)! diff --git a/SecretAgentKit/SigningRequestTracer.swift b/SecretAgentKit/SigningRequestTracer.swift index 8c6288d..04bbfb8 100644 --- a/SecretAgentKit/SigningRequestTracer.swift +++ b/SecretAgentKit/SigningRequestTracer.swift @@ -1,6 +1,7 @@ import Foundation import AppKit import Security +import SecretKit struct SigningRequestTracer { diff --git a/SecretKit/Common/Erasers/AnySecretStore.swift b/SecretKit/Common/Erasers/AnySecretStore.swift index 12b1ea0..99f88cb 100644 --- a/SecretKit/Common/Erasers/AnySecretStore.swift +++ b/SecretKit/Common/Erasers/AnySecretStore.swift @@ -8,7 +8,7 @@ public class AnySecretStore: SecretStore { private let _id: () -> UUID private let _name: () -> String private let _secrets: () -> [AnySecret] - private let _sign: (Data, AnySecret) throws -> Data + private let _sign: (Data, AnySecret, SigningRequestProvenance) throws -> Data private var sink: AnyCancellable? public init(_ secretStore: SecretStoreType) where SecretStoreType: SecretStore { @@ -17,7 +17,7 @@ public class AnySecretStore: SecretStore { _name = { secretStore.name } _id = { secretStore.id } _secrets = { secretStore.secrets.map { AnySecret($0) } } - _sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType) } + _sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType, for: $2) } sink = secretStore.objectWillChange.sink { _ in self.objectWillChange.send() } @@ -39,8 +39,8 @@ public class AnySecretStore: SecretStore { return _secrets() } - public func sign(data: Data, with secret: AnySecret) throws -> Data { - try _sign(data, secret) + public func sign(data: Data, with secret: AnySecret, for provenance: SigningRequestProvenance) throws -> Data { + try _sign(data, secret, provenance) } } diff --git a/SecretKit/Common/Types/SecretStore.swift b/SecretKit/Common/Types/SecretStore.swift index ef0488d..2ab51aa 100644 --- a/SecretKit/Common/Types/SecretStore.swift +++ b/SecretKit/Common/Types/SecretStore.swift @@ -9,7 +9,7 @@ public protocol SecretStore: ObservableObject, Identifiable { var name: String { get } var secrets: [SecretType] { get } - func sign(data: Data, with secret: SecretType) throws -> Data + func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data } diff --git a/SecretAgentKit/SigningRequestProvenance.swift b/SecretKit/Common/Types/SigningRequestProvenance.swift similarity index 79% rename from SecretAgentKit/SigningRequestProvenance.swift rename to SecretKit/Common/Types/SigningRequestProvenance.swift index b112ae5..c6a3c99 100644 --- a/SecretAgentKit/SigningRequestProvenance.swift +++ b/SecretKit/Common/Types/SigningRequestProvenance.swift @@ -17,7 +17,7 @@ extension SigningRequestProvenance { } public var intact: Bool { - return chain.reduce(true) { $0 && $1.validSignature } + chain.allSatisfy { $0.validSignature } } } @@ -30,9 +30,9 @@ extension SigningRequestProvenance { public let name: String public let path: String public let validSignature: Bool - let parentPID: Int32? + public let parentPID: Int32? - init(pid: Int32, name: String, path: String, validSignature: Bool, parentPID: Int32?) { + public init(pid: Int32, name: String, path: String, validSignature: Bool, parentPID: Int32?) { self.pid = pid self.name = name self.path = path diff --git a/SecretKit/SecureEnclave/SecureEnclaveStore.swift b/SecretKit/SecureEnclave/SecureEnclaveStore.swift index aedb586..0e2e0c1 100644 --- a/SecretKit/SecureEnclave/SecureEnclaveStore.swift +++ b/SecretKit/SecureEnclave/SecureEnclaveStore.swift @@ -76,9 +76,9 @@ extension SecureEnclave { reloadSecrets() } - public func sign(data: Data, with secret: SecretType) throws -> Data { + public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { let context = LAContext() - context.localizedReason = "sign a request from Terminal using secret \"\(secret.name)\"" + context.localizedReason = "sign a request from \(provenance.origin) using secret \"\(secret.name)\"" context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey, diff --git a/SecretKit/SmartCard/SmartCardStore.swift b/SecretKit/SmartCard/SmartCardStore.swift index 2fdbe4d..7940b58 100644 --- a/SecretKit/SmartCard/SmartCardStore.swift +++ b/SecretKit/SmartCard/SmartCardStore.swift @@ -1,6 +1,7 @@ import Foundation import Security import CryptoTokenKit +import LocalAuthentication // TODO: Might need to split this up into "sub-stores?" // ie, each token has its own Store. @@ -43,13 +44,17 @@ extension SmartCard { fatalError("Keys must be deleted on the smart card.") } - public func sign(data: Data, with secret: SecretType) throws -> Data { + public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { guard let tokenID = tokenID else { fatalError() } + let context = LAContext() + context.localizedReason = "sign a request from \(provenance.origin.name) using secret \"\(secret.name)\"" + context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey, kSecAttrKeyClass: kSecAttrKeyClassPrivate, kSecAttrApplicationLabel: secret.id as CFData, kSecAttrTokenID: tokenID, + kSecUseAuthenticationContext: context, kSecReturnRef: true ] as CFDictionary var untyped: CFTypeRef? diff --git a/Secretive.xcodeproj/project.pbxproj b/Secretive.xcodeproj/project.pbxproj index bc24f35..cdc7716 100644 --- a/Secretive.xcodeproj/project.pbxproj +++ b/Secretive.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 50153E20250AFCB200525160 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E1F250AFCB200525160 /* UpdateView.swift */; }; 50153E22250DECA300525160 /* SecretListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListView.swift */; }; 5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; }; + 501B7AE1251C56F700776EC7 /* SigningRequestProvenance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */; }; 50524B442420969E008DBD97 /* OpenSSHWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50524B432420969D008DBD97 /* OpenSSHWriterTests.swift */; }; 50571E0324393C2600F76F6C /* JustUpdatedChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */; }; 50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0424393D1500F76F6C /* LaunchAgentController.swift */; }; @@ -49,7 +50,6 @@ 507CE4ED2420A3C70029F750 /* Agent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50A3B79F24026B9900D209EA /* Agent.swift */; }; 507CE4EE2420A3CA0029F750 /* SocketController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50A3B79D24026B9900D209EA /* SocketController.swift */; }; 507CE4F02420A4C50029F750 /* SigningWitness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4EF2420A4C50029F750 /* SigningWitness.swift */; }; - 507CE4F42420A8C10029F750 /* SigningRequestProvenance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */; }; 507CE4F62420A96F0029F750 /* SigningRequestTracer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F52420A96F0029F750 /* SigningRequestTracer.swift */; }; 507EE34224281E12003C4FE3 /* FileHandleProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507EE34124281E12003C4FE3 /* FileHandleProtocols.swift */; }; 507EE34624281F89003C4FE3 /* StubFileHandleReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507EE34524281F89003C4FE3 /* StubFileHandleReader.swift */; }; @@ -361,6 +361,7 @@ 504BA92D243171F20064740E /* Types */ = { isa = PBXGroup; children = ( + 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */, 50617DCA23FCECA10099B055 /* Secret.swift */, 50617DC623FCE4EA0099B055 /* SecretStore.swift */, ); @@ -562,7 +563,6 @@ 5099A089240242C20062B6F2 /* SSHAgentProtocol.swift */, 50A3B79D24026B9900D209EA /* SocketController.swift */, 507CE4EF2420A4C50029F750 /* SigningWitness.swift */, - 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */, 507CE4F52420A96F0029F750 /* SigningRequestTracer.swift */, 50A3B79F24026B9900D209EA /* Agent.swift */, 507EE34124281E12003C4FE3 /* FileHandleProtocols.swift */, @@ -966,6 +966,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 501B7AE1251C56F700776EC7 /* SigningRequestProvenance.swift in Sources */, 50617DC723FCE4EA0099B055 /* SecretStore.swift in Sources */, 5099A02723FE34FA0062B6F2 /* SmartCard.swift in Sources */, 50617DCB23FCECA10099B055 /* Secret.swift in Sources */, @@ -1010,7 +1011,6 @@ 507CE4ED2420A3C70029F750 /* Agent.swift in Sources */, 507CE4F02420A4C50029F750 /* SigningWitness.swift in Sources */, 507CE4F62420A96F0029F750 /* SigningRequestTracer.swift in Sources */, - 507CE4F42420A8C10029F750 /* SigningRequestProvenance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };