65. pepsi-whitelist

Verwaltet die weiße Absenderliste von Hand.

65.1. Rolle

pepsi-whitelist verwaltet die pepsi.whitelist-Tabelle — die benannten Mengen von Absender-Mustern, die eine Nachricht als vertrauenswürdig (Nicht-Spam) markieren. Es verbindet sich über den gemeinsamen [pepsi-postgres]-Abschnitt und liest den optionalen [pepsi-whitelist]-Abschnitt. Dieselbe Tabelle wird von pepsi-stage-check-whitelist gelesen und von pepsi-stage-auto-whitelist automatisch befüllt; dieses Werkzeug erlaubt einem Administrator, Einträge direkt hinzuzufügen, aufzulisten und zu entfernen, und jedem Benutzer, aus der bereits von ihm gesendeten Mail eine eigene weiße Liste zu befüllen. Es ist keine Stage. Referenz: pepsi-whitelist(1).

Anders als die übrigen Operator-Werkzeuge, die als root gestartet schlicht zum Dienstkonto pepsi werden, behält dieses die aufrufende Identität und wechselt nur seine effektiven IDs rund um jeden Datenbankaufruf: import --user und --all-users brauchen root, um das Postfach eines anderen Benutzers mit dessen Zugangsdaten zu durchsuchen.

65.2. Funktionen

  • add — einen Eintrag einfügen: eine whitelist_name-Gruppe und einen whitelist_regex (einen erweiterten regulären POSIX-Ausdruck, wörtlich gespeichert — von der Prüf-Stage unabhängig von der Groß-/Kleinschreibung gegen die aus dem From:-Header geparste addr-spec abgeglichen, nie gegen den rohen Header-Text). --no-dkim-required löscht das datensatzweise dkim_required-Flag (standardmäßig gesetzt); --signature-required setzt signature_required (standardmäßig gelöscht); --sealer DOMAIN verlangt zusätzlich, dass die validierte ARC-Kette der Nachricht von dieser Domain gesiegelt wurde. Idempotent: Einen vorhandenen Eintrag (name, match field, regex) erneut hinzuzufügen ist eine No-Op und lässt seine Flags unverändert.

  • add-list / remove-list — dasselbe für eine Mailingliste, die über die List-Id ihrer Beiträge statt über ein From:-Muster erkannt wird, was jeden Beitrag trifft, gleich wer ihn geschrieben hat. --pattern behandelt das Argument als POSIX-ERE statt als einen exakten Bezeichner. Eine List-Id ist ein Header, den jeder kopieren kann, kombinieren Sie sie daher mit --sealer.

  • list — Einträge geordnet nach Name, Abgleichsfeld und Regex auflisten, optional auf einen einzelnen whitelist_name beschränkt, als Tabelle oder --json.

  • remove — den Eintrag löschen, der durch seinen genauen whitelist_name und whitelist_regex identifiziert wird.

  • import — eine weiße Liste aus einem Postfach befüllen: Jede Nachricht, deren From:/Sender: auf einer lokalen Domain liegt und deren Header-Block kein Zustellspur-Feld (Received:, Return-Path:, Delivered-To:, X-Original-To:) trägt, hat der Benutzer gesendet, also sind ihre To:-/Cc:-/Bcc:-Adressen Leute, mit denen er korrespondiert, und werden als Einträge hinzugefügt. Empfangene Mail wird ignoriert (jeden auf die weiße Liste zu setzen, der Ihnen geschrieben hat, würde den Zweck zunichte machen), ebenso Empfänger auf einer lokalen Domain. Liest mbox, Maildir (einschließlich seiner Unterordner), IMAP (--imap, mit --imap-user / --imap-password-file) und Dovecots eigene Formate (--doveadm, --doveadm-path); es werden nur Header-Blöcke gelesen, nie Nachrichtentexte. --dry-run meldet, was hinzugefügt würde, und ändert nichts; --own-address grenzt ein, was als von Ihnen gesendete Mail zählt; --max-entries / --max-messages begrenzen den Lauf; und --user / --all-users lassen root andere Konten befüllen, jedes in seinen eigenen Namensraum. --include-delivered liest auch empfangene Mail und ist aus dem naheliegenden Grund als unsicher gekennzeichnet: Ein gefälschtes From: würde dann die weiße Liste befüllen.

  • import –auto-wildcard — bietet an, die einzelnen Adressen einer Domain durch einen einzigen *@domain-Eintrag zu ersetzen, sobald dort mindestens WILDCARD_THRESHOLD (10, je Lauf mit --threshold überschreibbar) verschiedene Adressen gesehen wurden. Vorschläge werden auf einem Terminal einzeln bestätigt, mit --yes alle angenommen und alle abgelehnt, wenn es kein Terminal gibt — ein unbeaufsichtigter Lauf weitet eine weiße Liste nie von sich aus auf eine ganze Domain aus. Öffentliche E-Mail-Hoster (HOSTERS_FILE, /usr/share/pepsi/hosters.txt, mit --hosters überschreibbar und mit --no-hosters abschaltbar) werden nie vorgeschlagen, wie viele Korrespondenten ein Benutzer dort auch haben mag: „alle bei gmail.com“ ist keine Menge von Leuten, die der Benutzer kennt, und es würde jedem Spammer mit einem kostenlosen Konto eine Umgehung der Bezahlschranke in die Hand geben. Ihre Adressen werden weiterhin einzeln importiert.

65.3. Namensräume der weißen Liste

Ein whitelist_name ist entweder global (ein Segment, z. B. correspondents — der des Operators) oder einem Benutzer gehörend: <login>/<segment>, z. B. alice/correspondents. Segmente bestehen aus Buchstaben, Ziffern, _, . und - (ein Punkt, weil alice.smith ein gewöhnlicher Login ist); das Trennzeichen ist /, weil kein POSIX-artiges System es in einem Login-Namen zulässt, -, _, . und ein abschließendes $ dagegen schon. Ein Segment, das nur aus Punkten besteht, wird abgelehnt, sodass .. — und damit jeder relative Pfad — undarstellbar ist.

Gewöhnliche Benutzer dürfen nur ihren eigenen Namensraum lesen und schreiben, geschlüsselt auf den passwd-Login der realen uid (nie $USER oder ein Argument). Das schließt list ein: Die gemeinsame weiße Liste hält fest, mit wem die Organisation korrespondiert, und ein Programm, das jeder Benutzer ausführen darf, darf sie nicht ausgeben. root und die Konten pepsi/pepsi-owner/pepsi-whitelist dürfen alles verwalten.

Damit eine benutzereigene weiße Liste überhaupt etwas bewirkt, muss eine Prüf-Stage sie konsultieren — siehe die Platzhalter {localpart} / {login} im WHITELIST_NAME von pepsi-stage-check-whitelist.

65.4. Privilegienmodell

Die gemeinsame Tabelle zu erreichen erfordert eine Datenbank-Identität, die gewöhnliche Benutzer nicht haben; ein Postfach zu lesen erfordert ihres. Daher ist pepsi-whitelist setuid pepsi-whitelist installiert (Modus 4755) und senkt seine effektiven IDs sofort auf den aufrufenden Benutzer ab, um sie nur für die wenigen Millisekunden wieder anzuheben, in denen es mit PostgreSQL spricht (die Peer-Authentifizierung richtet sich nach der effektiven uid).

Dieses Konto ist bewusst nicht das pepsi-Dienstkonto: pepsi-setup gewährt seiner Rolle nur SELECT/INSERT/DELETE auf pepsi.whitelist, sodass die Kompromittierung eines Binärprogramms, das jeder lokale Benutzer ausführen kann, weder die Nachrichten-Warteschlange noch die Signierschlüssel erreicht.

Das Parsen des Postfachs — Megabytes an angreiferkontrolliertem RFC 5322 — geschieht in pepsi-helper-mailbox-scan(1), gestartet mit setresuid, das die reale, effektive und gespeicherte ID auf den Zielbenutzer setzt. Diesem Prozess bleibt in seinen Zugangsdaten keine privilegierte ID, sodass er nicht einmal im Prinzip pepsi-whitelist werden kann; er ist das einzige eigenständige pepsi-helper-*-Programm ganz ohne setuid-Bit. Schließlich wird -c/--config für unprivilegierte Aufrufer abgelehnt, und die Umgebungsvariablen, die die Konfigurationssuche (HOME, XDG_CONFIG_HOME), die ${DATADIR}-Expansion (PATH) und libpq (PG*) steuern, werden entfernt, bevor die Konfiguration gelesen wird.

Anders als pepsi-stage-auto-whitelist (das eine Adresse zu einem verankerten Muster maskiert) speichert add den whitelist_regex genau wie angegeben, sodass der Operator den Abgleich direkt steuert.

65.5. Konfiguration

[pepsi-whitelist] (alles optional): HOSTERS_FILE (Standardwert ${DATADIR}/hosters.txt), WILDCARD_THRESHOLD (Standardwert 10), MAX_ENTRIES (die Obergrenze der Datensätze, die ein import hinzufügen darf, Standardwert 5000), SCAN_HELPER (Standardwert pepsi-helper-mailbox-scan) und MAILBOX (das Postfach, aus dem standardmäßig importiert wird), dazu die gemeinsamen Lokalitätsoptionen (LOCAL_DOMAINS, TARGETS, RECIPIENT_DELIMITER), die entscheiden, welche Adressen als unsere zählen. Die Datenbankverbindung stammt aus [pepsi-postgres]. Siehe pepsi-whitelist(1).

65.6. Siehe auch

pepsi-stage-check-whitelist, pepsi-stage-auto-whitelist, pepsi-queue, Architektur, pepsi-whitelist(1), pepsi-helper-mailbox-scan(1), pepsi.conf(5).