Move app name + iconurl to tracer. (#149)

This commit is contained in:
Max Goedjen 2020-09-27 23:09:23 -07:00 committed by GitHub
parent 3328ada3bf
commit dc5c21c568
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 26 deletions

View File

@ -26,9 +26,9 @@ class Notifier {
func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) { func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) {
let notificationCenter = UNUserNotificationCenter.current() let notificationCenter = UNUserNotificationCenter.current()
let notificationContent = UNMutableNotificationContent() 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)\"" 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] notificationContent.attachments = [attachment]
} }
let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil) 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 { extension Notifier: SigningWitness {
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws { func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws {

View File

@ -4,6 +4,9 @@ import Security
import SecretKit import SecretKit
struct SigningRequestTracer { struct SigningRequestTracer {
}
extension SigningRequestTracer {
func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance { func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance {
let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess) let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess)
@ -34,7 +37,24 @@ struct SigningRequestTracer {
let flags: SecCSFlags = [.considerExpiration, .enforceRevocationChecks] let flags: SecCSFlags = [.considerExpiration, .enforceRevocationChecks]
SecCodeCreateWithPID(pid, SecCSFlags(), &secCode) SecCodeCreateWithPID(pid, SecCSFlags(), &secCode)
let valid = SecCodeCheckValidity(secCode.takeRetainedValue(), flags, nil) == errSecSuccess 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
} }
} }

View File

@ -106,7 +106,7 @@ class AgentTests: XCTestCase {
let agent = Agent(storeList: list, witness: witness) let agent = Agent(storeList: list, witness: witness)
agent.handle(reader: stubReader, writer: stubWriter) agent.handle(reader: stubReader, writer: stubWriter)
XCTAssertEqual(witnessTrace, speakNowTrace) XCTAssertEqual(witnessTrace, speakNowTrace)
XCTAssertEqual(witnessTrace.origin.name, "Finder") XCTAssertEqual(witnessTrace.origin.displayName, "Finder")
XCTAssertEqual(witnessTrace.origin.validSignature, true) XCTAssertEqual(witnessTrace.origin.validSignature, true)
XCTAssertEqual(witnessTrace.origin.parentPID, 1) XCTAssertEqual(witnessTrace.origin.parentPID, 1)
} }

View File

@ -27,19 +27,27 @@ extension SigningRequestProvenance {
public struct Process: Equatable { public struct Process: Equatable {
public let pid: Int32 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 path: String
public let validSignature: Bool public let validSignature: Bool
public let parentPID: Int32? 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.pid = pid
self.name = name self.processName = processName
self.appName = appName
self.iconURL = iconURL
self.path = path self.path = path
self.validSignature = validSignature self.validSignature = validSignature
self.parentPID = parentPID self.parentPID = parentPID
} }
public var displayName: String {
appName ?? processName
}
} }
} }

View File

@ -78,7 +78,7 @@ extension SecureEnclave {
public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data {
let context = LAContext() 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" context.localizedCancelTitle = "Deny"
let attributes = [ let attributes = [
kSecClass: kSecClassKey, kSecClass: kSecClassKey,

View File

@ -47,7 +47,7 @@ extension SmartCard {
public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data {
guard let tokenID = tokenID else { fatalError() } guard let tokenID = tokenID else { fatalError() }
let context = LAContext() 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" context.localizedCancelTitle = "Deny"
let attributes = [ let attributes = [
kSecClass: kSecClassKey, kSecClass: kSecClassKey,