Die TCC-Tabelle access in allen macOS-Versionen
Wie sich die Tabelle access in TCC.db von Mojave über Big Sur bis Sonoma verändert hat: allowed, auth_value, auth_reason, pid, last_reminded und Nebentabellen.
Kurz gesagt. Die Tabelle access in TCC.db kennt drei grundlegende Layouts. Mojave und Catalina: allowed (0/1) und prompt_count. Ab Big Sur (11): auth_value, auth_reason und auth_version ersetzen sie, und indirect_object_identifier wird zu TEXT NOT NULL DEFAULT 'UNUSED'. Ab Sonoma (14): pid, pid_version, boot_uuid und last_reminded kommen hinzu. Führen Sie auf jeder Kopie vor der Abfrage .schema access aus. TCC Parser liest die Spaltennamen aus dem Schema jeder Datei, daher funktioniert dieselbe Ansicht über alle Versionen hinweg.
Warum das Schema zählt
Abfragen und Parser scheitern bei falschem Layout stillschweigend. Ein Skript für Big Sur, das auth_value auswählt, schlägt auf einer Catalina-Datenbank fehl; eines für Catalina, das auf allowed = 1 filtert, findet unter Sonoma nichts. Das Plaso-Plugin macostcc etwa setzt die Spalten allowed und prompt_count aus der Zeit vor Big Sur voraus und zielt daher auf Datenbanken von Mojave und Catalina. MacOS.System.TCC von Velociraptor wurde gegen Big Sur geschrieben. Prüfen Sie zuerst:
sqlite3 TCC.db '.tables'
sqlite3 TCC.db '.schema access'
Mojave und Catalina (10.14, 10.15)
Wie im Plaso-Plugin macostcc dokumentiert, hat die Tabelle access folgende Spalten:
| Spalte | Hinweise |
|---|---|
service | Kennung des TCC-Dienstes |
client | Bundle-ID oder absoluter Pfad |
client_type | 0 Bundle-ID, 1 absoluter Pfad |
allowed | 1 erlaubt, 0 nicht erlaubt |
prompt_count | Wie oft der Benutzer gefragt wurde |
csreq | Kompilierte Code-Anforderung des Clients |
policy_id | Verweis auf policies.id bei richtliniengesteuerten Zeilen |
indirect_object_identifier_type, indirect_object_identifier, indirect_object_code_identity | Ziel der Freigabe (Automation) |
flags | Nicht dokumentiert |
last_modified | DEFAULT CAST(strftime('%s','now') AS INTEGER), also Unix-Sekunden, UTC |
Der Primärschlüssel ist (service, client, client_type, indirect_object_identifier). Dieser Schlüssel erklärt ein wichtiges Verhalten: Es gibt eine Zeile pro Client, Dienst und Ziel, und eine neue Entscheidung ersetzt die alte Zeile, statt eine neue hinzuzufügen. Die Datenbank bewahrt den aktuellen Zustand, keinen Verlauf.
Ab Big Sur (11)
Big Sur ersetzte allowed und prompt_count durch drei Spalten:
| Spalte | Werte |
|---|---|
auth_value | 0 verweigert, 1 unbekannt, 2 erlaubt, 3 eingeschränkt |
auth_reason | Warum die Entscheidung getroffen wurde (siehe unten) |
auth_version | Version des Formats des Berechtigungseintrags |
indirect_object_identifier wurde zu TEXT NOT NULL DEFAULT 'UNUSED'. Zeilen ohne Ziel tragen deshalb jetzt die Zeichenkette UNUSED statt eines Nullwerts. Filtern Sie darauf, wenn Sie nach Automation-Zielen suchen.
auth_reason
Apple dokumentiert diese Werte nicht. Die folgende Zuordnung stammt von der Community und ist weit verbreitet. Lesen Sie sie als Hypothese und bestätigen Sie sie auf einem Test-Mac derselben Version oder anhand der Einträge von com.apple.TCC im Unified Log, bevor sie in einen Bericht einfließt.
| auth_reason | Deutung der Community |
|---|---|
| 1 | Fehler |
| 2 | Zustimmung des Benutzers (hat eine Abfrage beantwortet) |
| 3 | Vom Benutzer gesetzt (in den Systemeinstellungen geändert) |
| 4 | Vom System gesetzt |
| 5 | Dienstrichtlinie |
| 6 | MDM-Richtlinie |
| 7 | Override-Richtlinie |
| 8 | Fehlender Usage-String |
| 9 | Zeitüberschreitung der Abfrage |
| 10 | Preflight unbekannt |
| 11 | Per Entitlement |
| 12 | Richtlinie nach App-Typ |
Nützlich ist meist die Unterscheidung zwischen vom Benutzer ausgelösten Gründen (2, 3), richtliniengesteuerten (5, 6, 7) und systemseitigen (4, 11, 12). Glossar: auth_value, auth_reason.
Ab Sonoma (14)
Sonoma fügte vier Spalten hinzu:
| Spalte | Hinweise |
|---|---|
pid | Eine der Zeile zugeordnete Prozess-ID |
pid_version | Begleitet pid |
boot_uuid | Identifiziert eine Boot-Sitzung |
last_reminded | Sekunden der Unix-Epoche; Standardwert im Schema strftime('%s','now') |
Die Namen deuten auf den Prozess und die Boot-Sitzung hin, die an der Entscheidung beteiligt waren, ihre genaue Bedeutung ist aber nicht öffentlich dokumentiert. Nützlich ist boot_uuid trotzdem: Damit gruppieren Sie Zeilen nach Boot-Sitzung und gleichen sie mit anderen Artefakten ab, die eine Boot-UUID erfassen. last_reminded ist ein zweiter Zeitstempel für die Zeitachse; in TCC Parser können Sie das Zeitfeld zwischen Last modified, Last reminded und Expired at umschalten.
Neuere Versionen
Uns ist keine öffentliche Dokumentation von Schemaänderungen an access nach Sonoma bekannt, auch nicht für macOS 26 Tahoe. Genau deshalb arbeitet TCC Parser schemagesteuert: Er liest die Spaltenliste aus jeder Datei und dekodiert die Spalten, die er kennt, statt pro Version ein festes Layout anzunehmen. Sehen Sie eine Spalte, die dieser Artikel nicht erwähnt, prüfen Sie sie auf einem Testsystem, bevor Sie sie deuten.
Die übrigen Tabellen
Die Tabelle access bekommt die ganze Aufmerksamkeit, die Datenbank enthält aber mehr. Im von Plaso dokumentierten Schema von Mojave/Catalina:
| Tabelle | Spalten | Wofür sie dient |
|---|---|---|
admin | key, value | Kleiner Key-Value-Speicher; Inhalt nicht dokumentiert |
policies | id, bundle_id, uuid, display | Richtlinien, auf die access.policy_id verweist (zum Beispiel MDM) |
active_policy | client, client_type, policy_id | Welche Richtlinie für welchen Client gilt |
access_overrides | service (Primärschlüssel) | Overrides pro Dienst; Zweck nicht dokumentiert |
expired | service, client, client_type, csreq, last_modified, expired_at | Abgelaufene Freigaben, mit dem Zeitpunkt des Ablaufs |
Listen Sie die Tabellen auf Ihrer eigenen Kopie mit .tables auf: Spätere Versionen können abweichen. Die Tabelle expired verdient in jedem Fall einen Blick, weil sie Clients bewahrt, die in access nicht mehr erscheinen. Ihr expired_at enthält wie last_modified Unix-Sekunden. TCC Parser verknüpft policy_id mit der Tabelle policies und mit MDMOverrides.plist und zeigt REG.db sowie jede andere SQLite-Datei im Ordner com.apple.TCC als Rohtabellen.
Eine Abfrage pro Layout
Mojave und Catalina:
SELECT service, client, client_type, allowed, prompt_count,
datetime(last_modified, 'unixepoch') AS changed_utc
FROM access ORDER BY last_modified DESC;
Ab Big Sur (ab Sonoma zusätzlich last_reminded):
SELECT service, client, client_type, auth_value, auth_reason,
NULLIF(indirect_object_identifier, 'UNUSED') AS target,
datetime(last_modified, 'unixepoch') AS changed_utc
FROM access ORDER BY last_modified DESC;
Beide liefern Blobs (csreq, indirect_object_code_identity) als Rohbytes; wie Sie sie dekodieren, beschreibt csreq-Code-Anforderungen dekodieren.
Zeitstempel
Alle Zeitstempel in TCC.db sind Sekunden der Unix-Epoche, UTC: last_modified, last_reminded und expired.expired_at. Es handelt sich nicht um Mac Absolute Time, die viele andere Apple-Datenbanken verwenden. last_modified ist der letzte Schreibvorgang auf die Zeile: eine beantwortete Abfrage, ein umgelegter Schalter, eine angewendete Richtlinie. Es ist nicht die erste Freigabe.
Häufige Fragen
In welcher macOS-Version wurde allowed in TCC.db durch auth_value ersetzt?
In macOS 11 Big Sur. Datenbanken von Mojave und Catalina haben die Spalten allowed und prompt_count; ab Big Sur stehen stattdessen auth_value, auth_reason und auth_version darin.
Welche Spalten hat Sonoma der Tabelle access hinzugefügt?
macOS 14 Sonoma fügte pid, pid_version, boot_uuid und last_reminded hinzu. last_reminded enthält wie last_modified Sekunden der Unix-Epoche.
Dokumentiert Apple die Werte von auth_reason?
Nein. Die übliche Zuordnung (1 Fehler, 2 Zustimmung des Benutzers, 3 vom Benutzer gesetzt, 4 vom System gesetzt, 5 Dienstrichtlinie, 6 MDM-Richtlinie, 7 Override-Richtlinie, 8 fehlender Usage-String, 9 Zeitüberschreitung der Abfrage, 10 Preflight unbekannt, 11 per Entitlement, 12 Richtlinie nach App-Typ) stammt aus der Forschung der Community. Bestätigen Sie sie auf einem Testsystem, bevor Sie sich darauf stützen.
Warum schlägt meine Abfrage auf einer älteren TCC.db fehl?
Weil die ausgewählte Spalte in diesem Schema nicht existiert. Führen Sie zuerst .schema access aus und schreiben Sie die Abfrage für die Spalten, die tatsächlich vorhanden sind.