This commit is contained in:
Max Goedjen 2022-01-01 22:01:01 -08:00
parent da2c460c60
commit c61436fda3
No known key found for this signature in database
GPG Key ID: E58C21DD77B9B8E8
4 changed files with 44 additions and 0 deletions

View File

@ -1,9 +1,11 @@
import Foundation import Foundation
/// A namespace for the SSH Agent Protocol, as described in https://tools.ietf.org/id/draft-miller-ssh-agent-01.html
public enum SSHAgent {} public enum SSHAgent {}
extension SSHAgent { extension SSHAgent {
/// The type of the SSH Agent Request, as described in https://tools.ietf.org/id/draft-miller-ssh-agent-01.html#rfc.section.5.1
public enum RequestType: UInt8, CustomDebugStringConvertible { public enum RequestType: UInt8, CustomDebugStringConvertible {
case requestIdentities = 11 case requestIdentities = 11
case signRequest = 13 case signRequest = 13
@ -18,6 +20,7 @@ extension SSHAgent {
} }
} }
/// The type of the SSH Agent Response, as described in https://tools.ietf.org/id/draft-miller-ssh-agent-01.html#rfc.section.5.1
public enum ResponseType: UInt8, CustomDebugStringConvertible { public enum ResponseType: UInt8, CustomDebugStringConvertible {
case agentFailure = 5 case agentFailure = 5
case agentIdentitiesAnswer = 12 case agentIdentitiesAnswer = 12

View File

@ -4,11 +4,15 @@ import Security
import SecretKit import SecretKit
import SecretAgentKitHeaders import SecretAgentKitHeaders
/// An object responsible for generating ``SecretKit.SigningRequestProvenance`` objects.
struct SigningRequestTracer { struct SigningRequestTracer {
} }
extension SigningRequestTracer { extension SigningRequestTracer {
/// Generates a ``SecretKit.SigningRequestProvenance`` from a ``FileHandleReader``.
/// - Parameter fileHandleReader: The reader involved in processing the request.
/// - Returns: A ``SecretKit.SigningRequestProvenance`` describing the origin of the request.
func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance { func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance {
let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess) let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess)
@ -19,6 +23,9 @@ extension SigningRequestTracer {
return provenance return provenance
} }
/// Generates a `kinfo_proc` representation of the provided process ID.
/// - Parameter pid: The process ID to look up.
/// - Returns: a `kinfo_proc` struct describing the process ID.
func pidAndNameInfo(from pid: Int32) -> kinfo_proc { func pidAndNameInfo(from pid: Int32) -> kinfo_proc {
var len = MemoryLayout<kinfo_proc>.size var len = MemoryLayout<kinfo_proc>.size
let infoPointer = UnsafeMutableRawPointer.allocate(byteCount: len, alignment: 1) let infoPointer = UnsafeMutableRawPointer.allocate(byteCount: len, alignment: 1)
@ -27,6 +34,9 @@ extension SigningRequestTracer {
return infoPointer.load(as: kinfo_proc.self) return infoPointer.load(as: kinfo_proc.self)
} }
/// Generates a ``SecretKit.SigningRequestProvenance.Process`` from a provided process ID.
/// - Parameter pid: The process ID to look up.
/// - Returns: A ``SecretKit.SigningRequestProvenance.Process`` describing the process.
func process(from pid: Int32) -> SigningRequestProvenance.Process { func process(from pid: Int32) -> SigningRequestProvenance.Process {
var pidAndNameInfo = self.pidAndNameInfo(from: pid) var pidAndNameInfo = self.pidAndNameInfo(from: pid)
let ppid = pidAndNameInfo.kp_eproc.e_ppid != 0 ? pidAndNameInfo.kp_eproc.e_ppid : nil let ppid = pidAndNameInfo.kp_eproc.e_ppid != 0 ? pidAndNameInfo.kp_eproc.e_ppid : nil
@ -41,6 +51,9 @@ extension SigningRequestTracer {
return SigningRequestProvenance.Process(pid: pid, processName: procName, appName: appName(for: pid), iconURL: iconURL(for: pid), 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)
} }
/// Looks up the URL for the icon of a process ID, if it has one.
/// - Parameter pid: The process ID to look up.
/// - Returns: A URL to the icon, if the process has one.
func iconURL(for pid: Int32) -> URL? { func iconURL(for pid: Int32) -> URL? {
do { do {
if let app = NSRunningApplication(processIdentifier: pid), let icon = app.icon?.tiffRepresentation { if let app = NSRunningApplication(processIdentifier: pid), let icon = app.icon?.tiffRepresentation {
@ -54,6 +67,9 @@ extension SigningRequestTracer {
return nil return nil
} }
/// Looks up the application name of a process ID, if it has one.
/// - Parameter pid: The process ID to look up.
/// - Returns: The process's display name, if the process has one.
func appName(for pid: Int32) -> String? { func appName(for pid: Int32) -> String? {
NSRunningApplication(processIdentifier: pid)?.localizedName NSRunningApplication(processIdentifier: pid)?.localizedName
} }

View File

@ -1,9 +1,23 @@
import Foundation import Foundation
import SecretKit import SecretKit
/// A protocol that allows conformers to be notified of access to secrets, and optionally prevent access.
public protocol SigningWitness { public protocol SigningWitness {
/// A ridiculously named method that notifies the callee that a signing operation is about to be performed using a secret. The callee may `throw` an `Error` to prevent access from occurring.
/// - Parameters:
/// - secret: The ``SecretKit.Secret`` that will be used to sign the request.
/// - store: The ``SecretKit.Store`` being asked to sign the request..
/// - provenance: A ``SecretKit.SigningRequestProvenance`` object describing the origin of the request.
/// - Note: This method being called does not imply that the requst has been authorized. If a secret requires authentication, authentication will still need to be performed by the user before the request will be performed. If the user declines or fails to authenticate, the request will fail.
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws
/// Notifies the callee that a signing operation has been performed for a given secret.
/// - Parameters:
/// - secret: The ``SecretKit.Secret`` that will was used to sign the request.
/// - store: The ``SecretKit.Store`` that signed the request..
/// - provenance: A ``SecretKit.SigningRequestProvenance`` object describing the origin of the request.
/// - requiredAuthentication: A boolean describing whether or not authentication was required for the request.
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, requiredAuthentication: Bool) throws func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, requiredAuthentication: Bool) throws
} }

View File

@ -103,9 +103,20 @@ class Notifier {
extension Notifier: SigningWitness { extension Notifier: SigningWitness {
/// <#Description#>
/// - Parameters:
/// - secret: <#secret description#>
/// - store: <#store description#>
/// - provenance: <#provenance description#>
func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws { func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance) throws {
} }
/// <#Description#>
/// - Parameters:
/// - secret: <#secret description#>
/// - store: <#store description#>
/// - provenance: <#provenance description#>
/// - requiredAuthentication: <#requiredAuthentication description#>
func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, requiredAuthentication: Bool) throws { func witness(accessTo secret: AnySecret, from store: AnySecretStore, by provenance: SigningRequestProvenance, requiredAuthentication: Bool) throws {
notify(accessTo: secret, from: store, by: provenance, requiredAuthentication: requiredAuthentication) notify(accessTo: secret, from: store, by: provenance, requiredAuthentication: requiredAuthentication)
} }