import Foundation import OpenDirectory import os private let log = Logger(subsystem: "com.scarriffleservices.onyx", category: "Face") /// Prüft eine Passworteingabe gegen die echte Anmeldung. /// /// **Und speichert dabei nichts.** Die Zeichenkette geht direkt in /// `ODRecord.verifyPassword`, das Ergebnis ist ein `Bool`, und danach ist sie /// wieder weg. Siehe `docs/spikes/I-passwortpruefung.md`. /// /// Damit fällt der Grund weg, aus dem vergleichbare Programme sich das /// Anmeldepasswort geben lassen und in die Keychain legen. Ein gespeichertes /// Anmeldepasswort ist die Sorte Sicherheitsschuld, die man nicht aufnimmt, /// wenn es auch ohne geht. public struct PasswordVerifier: Sendable { private let username: String public init(username: String = NSUserName()) { self.username = username } /// `true`, wenn die Eingabe stimmt. /// /// Ein Fehler beim Nachschlagen gilt als **falsch**, nicht als richtig: wer /// hier großzügig ist, öffnet den Sperrbildschirm, sobald der /// Verzeichnisdienst hakt. public func verify(_ password: String) -> Bool { guard !password.isEmpty else { return false } do { let node = try ODNode(session: ODSession.default(), type: ODNodeType(kODNodeTypeAuthentication)) let record = try node.record(withRecordType: kODRecordTypeUsers, name: username, attributes: nil) try record.verifyPassword(password) return true } catch { return false } } /// Ob der Weg zum Benutzerdatensatz überhaupt offensteht. /// /// Getrennt von `verify`, damit die Einstellungen es prüfen können, ohne /// ein Passwort zu verlangen — und damit ein kaputter Verzeichnisdienst /// nicht erst am Sperrbildschirm auffällt, wo man ihn am wenigsten /// gebrauchen kann. public var isAvailable: Bool { do { let node = try ODNode(session: ODSession.default(), type: ODNodeType(kODNodeTypeAuthentication)) _ = try node.record(withRecordType: kODRecordTypeUsers, name: username, attributes: nil) return true } catch { log.error("Benutzerdatensatz nicht erreichbar — Sperrbildschirm ohne Rückfall") return false } } }