diff --git a/SecretAgent/Notifier.swift b/SecretAgent/Notifier.swift index cf580f7..8167a54 100644 --- a/SecretAgent/Notifier.swift +++ b/SecretAgent/Notifier.swift @@ -26,9 +26,9 @@ class Notifier { func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) { let notificationCenter = UNUserNotificationCenter.current() let notificationContent = UNMutableNotificationContent() - notificationContent.title = "Signed Request from \(provenance.origin.name)" + notificationContent.title = "Signed Request from \(provenance.origin.displayName)" notificationContent.subtitle = "Using secret \"\(secret.name)\"" - if let iconURL = iconURL(for: provenance), let attachment = try? UNNotificationAttachment(identifier: "icon", url: iconURL, options: nil) { + if let iconURL = provenance.origin.iconURL, let attachment = try? UNNotificationAttachment(identifier: "icon", url: iconURL, options: nil) { notificationContent.attachments = [attachment] } let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil) @@ -54,23 +54,6 @@ class Notifier { } -extension Notifier { - - func iconURL(for provenance: SigningRequestProvenance) -> URL? { - do { - if let app = NSRunningApplication(processIdentifier: provenance.origin.pid), let icon = app.icon?.tiffRepresentation { - let temporaryURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("\(UUID().uuidString).png")) - let bitmap = NSBitmapImageRep(data: icon) - try bitmap?.representation(using: .png, properties: [:])?.write(to: temporaryURL) - return temporaryURL - } - } catch { - } - return nil - } - -} - extension Notifier: SigningWitness { func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws { diff --git a/SecretAgentKit/SigningRequestTracer.swift b/SecretAgentKit/SigningRequestTracer.swift index 04bbfb8..54923ce 100644 --- a/SecretAgentKit/SigningRequestTracer.swift +++ b/SecretAgentKit/SigningRequestTracer.swift @@ -4,6 +4,9 @@ import Security import SecretKit struct SigningRequestTracer { +} + +extension SigningRequestTracer { func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance { let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess) @@ -34,7 +37,24 @@ struct SigningRequestTracer { let flags: SecCSFlags = [.considerExpiration, .enforceRevocationChecks] SecCodeCreateWithPID(pid, SecCSFlags(), &secCode) let valid = SecCodeCheckValidity(secCode.takeRetainedValue(), flags, nil) == errSecSuccess - return SigningRequestProvenance.Process(pid: pid, name: procName, path: path, validSignature: valid, parentPID: ppid) + return SigningRequestProvenance.Process(pid: pid, processName: procName, appName: appName(for: pid), iconURL: iconURL(for: pid), path: path, validSignature: valid, parentPID: ppid) + } + + func iconURL(for pid: Int32) -> URL? { + do { + if let app = NSRunningApplication(processIdentifier: pid), let icon = app.icon?.tiffRepresentation { + let temporaryURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("\(UUID().uuidString).png")) + let bitmap = NSBitmapImageRep(data: icon) + try bitmap?.representation(using: .png, properties: [:])?.write(to: temporaryURL) + return temporaryURL + } + } catch { + } + return nil + } + + func appName(for pid: Int32) -> String? { + NSRunningApplication(processIdentifier: pid)?.localizedName } } diff --git a/SecretAgentKitTests/AgentTests.swift b/SecretAgentKitTests/AgentTests.swift index e068b7b..2c3e29e 100644 --- a/SecretAgentKitTests/AgentTests.swift +++ b/SecretAgentKitTests/AgentTests.swift @@ -106,7 +106,7 @@ class AgentTests: XCTestCase { let agent = Agent(storeList: list, witness: witness) agent.handle(reader: stubReader, writer: stubWriter) XCTAssertEqual(witnessTrace, speakNowTrace) - XCTAssertEqual(witnessTrace.origin.name, "Finder") + XCTAssertEqual(witnessTrace.origin.displayName, "Finder") XCTAssertEqual(witnessTrace.origin.validSignature, true) XCTAssertEqual(witnessTrace.origin.parentPID, 1) } diff --git a/SecretKit/Common/Types/SigningRequestProvenance.swift b/SecretKit/Common/Types/SigningRequestProvenance.swift index c6a3c99..271c8c0 100644 --- a/SecretKit/Common/Types/SigningRequestProvenance.swift +++ b/SecretKit/Common/Types/SigningRequestProvenance.swift @@ -27,19 +27,27 @@ extension SigningRequestProvenance { public struct Process: Equatable { public let pid: Int32 - public let name: String + public let processName: String + public let appName: String? + public let iconURL: URL? public let path: String public let validSignature: Bool public let parentPID: Int32? - public init(pid: Int32, name: String, path: String, validSignature: Bool, parentPID: Int32?) { + public init(pid: Int32, processName: String, appName: String?, iconURL: URL?, path: String, validSignature: Bool, parentPID: Int32?) { self.pid = pid - self.name = name + self.processName = processName + self.appName = appName + self.iconURL = iconURL self.path = path self.validSignature = validSignature self.parentPID = parentPID } + public var displayName: String { + appName ?? processName + } + } } diff --git a/SecretKit/SecureEnclave/SecureEnclaveStore.swift b/SecretKit/SecureEnclave/SecureEnclaveStore.swift index 9bc2ec3..c355553 100644 --- a/SecretKit/SecureEnclave/SecureEnclaveStore.swift +++ b/SecretKit/SecureEnclave/SecureEnclaveStore.swift @@ -78,7 +78,7 @@ extension SecureEnclave { public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { let context = LAContext() - context.localizedReason = "sign a request from \"\(provenance.origin.name)\" using secret \"\(secret.name)\"" + context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\"" context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey, diff --git a/SecretKit/SmartCard/SmartCardStore.swift b/SecretKit/SmartCard/SmartCardStore.swift index 133447f..236ec0c 100644 --- a/SecretKit/SmartCard/SmartCardStore.swift +++ b/SecretKit/SmartCard/SmartCardStore.swift @@ -47,7 +47,7 @@ extension SmartCard { 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.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\"" context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey,