85.1.7. pepsi-stage-decrypt¶
decrypt mail addressed to our users and verify what signed it
- Handbuchabschnitt:
1
85.1.7.1.1. Name¶
pepsi-stage-decrypt - die eingehende Stage der Pepsi-Pipeline für Ende-zu-Ende-Entschlüsselung und Signaturverifikation.
85.1.7.1.2. Übersicht¶
pepsi-stage-decrypt [GLOBAL-OPTIONS] worker
85.1.7.1.3. Beschreibung¶
pepsi-stage-decrypt ist ein Stage-Programm, das von pepsi-dispatch(1) als persistenter Worker ausgeführt wird, der Nachrichten-IDs von der Standardeingabe liest. Für eine Nachricht an einen Empfänger, den dieser Host bedient, öffnet es jedes Chiffrat, das die Nachricht trägt, verifiziert jede Signatur, die sie trägt, gegen eine echte Vertrauenskette, hält das Urteil fest und entfernt jeden Sicherheitsindikator, den der Absender gefälscht hat. Es liest die Zertifikate, die die Nachricht mitführt, um diese Signatur zu prüfen, speichert aber keines davon: Die Schlüssel von Korrespondenten zu lernen ist Sache von pepsi-stage-autocrypt-learn(1), und das ist eine eigene Stage, weil sie nach dem Spam-Urteil laufen muss, das es hier noch nicht gibt.
Dies auf dem Server zu tun ist das, was ein Client-Plugin überflüssig macht: Der Benutzer liest gewöhnliche Mail in seinem üblichen Client. Der Handel ist nur deshalb tragfähig, weil die Nachricht gleich aufhört, ein SMTP-Objekt zu sein, und zu einer Datei in einem Postfach wird — siehe Lokalität. Diese Datei ist Klartext, es sei denn, der Empfänger hat seinen eigenen Mail-Client-Schlüssel registriert und pepsi-stage-reencrypt(1) steht vor der lokalen Zustellung und versiegelt, was diese Stage geöffnet hat, für diesen Schlüssel, sobald die späteren Stages es gelesen haben.
Die Verifikationshälfte ist bei einer Unterscheidung bewusst streng. Eine kryptographisch einwandfreie Signatur sagt Ihnen, dass die Nachricht von irgendeinem Schlüssel signiert wurde; ob dieser Schlüssel dem Absender gehört, ist eine gesonderte Frage. Die beiden werden nie als dasselbe gemeldet (Urteile).
85.1.7.1.4. Lokalität¶
Die Stage läuft nur für Empfänger, die dieser Host bedient, und bei einer Nachricht, die er nicht bedient, versucht sie es gar nicht erst — ein fehlgeschlagener Entschlüsselungsversuch sollte das Urteil nicht färben, und für eine solche Nachricht gibt es ohnehin keinen Schlüssel.
Der Grund ist, dass das Entschlüsseln den Nachrichtentext umschreibt. Die DKIM-Signatur des Absenders verifiziert dann nicht mehr, und ein vor dem Entschlüsseln erstelltes ARC-Siegel (siehe Platzierung) deckt die verschlüsselte Form ab. Bei einer Nachricht, die gleich lokal zugestellt wird, ist das harmlos. Bei einer weitergeleiteten Nachricht ist es das nicht: Sie käme mit kaputter Signatur beim nächsten Hop an, was ein stärkeres negatives Signal ist als gar keine Signatur.
Die Lokalität ist derselbe Test, den die Zustell-Stages verwenden — LOCAL_DOMAINS, TARGETS und RECIPIENT_DELIMITER — mit einem Unterschied. Standardmäßig muss nur die Domain passen, denn diese Stage muss nicht wissen, in wessen Postfach zu schreiben ist; eine gehostete Domain, deren Benutzer Krypto-Identitäten, aber keine Shell-Konten haben, ist eine gewöhnliche Installation. Setzen Sie REQUIRE_ACCOUNT = yes, um zusätzlich einen passwd-Eintrag in TARGETS zu verlangen.
Eine Nachricht mit sowohl lokalen als auch fremden Empfängern wird aufgeteilt: Die fremden Empfänger werden auf einen Geschwisterdatensatz bei NEXT_STAGE abgezogen, der die Nachricht genau so trägt, wie sie ankam, und dieser Datensatz behält die lokalen. Der DSN-Zustand je Empfänger wird im Gleichschritt von demselben Code zerteilt, den jede andere Empfängeraufteilung verwendet.
85.1.7.1.5. Platzierung¶
Die empfohlene eingehende Kette ist:
init = arc -> decrypt -> aliases -> (anti-spam / language / …) -> local delivery
ARC läuft zuerst. Ein ARC-Set versiegelt die Nachricht so, wie sie ankam; zuerst zu entschlüsseln ließe das versiegelte AMS Bytes beschreiben, die sonst niemand je gesehen hat, sodass das Siegel eine Aussage über eine Nachricht wäre, die es nie gab. pepsi-setup(1) warnt, wenn es eine ARC-Stage findet, die von einer Decrypt-Stage aus erreichbar ist.
Die Inhaltsprüfung läuft danach. Spracherkennung, die Pay-to-Send-Schranke und die Prüfung des From:-Headers gegen die weiße Liste lesen alle den Nachrichtentext, und alle wollen Klartext.
Die Platzierung ist auch eine Leistungsfrage. Die Stage deklariert Load::Full, weil sich den Umschlagspalten nicht ansehen lässt, ob eine Nachricht geschützt ist, und Load je Stage festliegt. Jede Nachricht, die durch sie hindurchgeht, lädt daher ihren gesamten Nachrichtentext aus der Datenbank, selbst eine, die sich als gewöhnliche unverschlüsselte Mail herausstellt. Auf einem eingehenden Pfad, der in lokaler Zustellung endet, ist das vertretbar; es ist keine Stage, die man vor Massen-Relay-Verkehr stellt.
85.1.7.1.6. Urteile¶
state.crypto.in.signature.status ist eines von:
noneDie Nachricht trägt keine Signatur.
validKryptographisch einwandfrei und der Schlüssel war verankert: eine X.509-Kette zu einem konfigurierten
ca_trust-Anker oder ein OpenPGP-Schlüssel aus einer eingestuften Entdeckungsquelle (DANE, WKD, ein Keyserver oder einer, den der Operator gepinnt hat).valid-untrustedKryptographisch einwandfrei, aber der Schlüssel ließ sich an nichts binden: ein erstmals gesehener Schlüssel, aus der Nachricht selbst oder aus einem
Autocrypt-Header gelernt, oder ein Zertifikat einer CA, für die diese Installation keinen Anker hält. Der größte Teil des signierten Mailverkehrs der Welt ist in diesem Zustand.Das wird nie als ``valid`` gemeldet. Es ist die Unterscheidung, für die diese Stage existiert, und ein Sicherheitsindikator, der die beiden vermengt, ist schlimmer als keiner.
invalidDie Signatur verifiziert nicht über die Bytes, die sie abdeckt, oder das Zertifikat des Signierenden ist abgelaufen, widerrufen oder an eine andere Adresse gebunden als das
From:der Nachricht.unverifiableFür den behaupteten Signierenden war kein Schlüssel oder Zertifikat verfügbar, sodass sich weder das eine noch das andere feststellen ließ. Dies ist das Urteil, das die Stage auf einen Schlüssel warten lässt (Schlüsselentdeckung).
Eine Nachricht mit mehreren Signaturschichten nimmt das schlechteste der Urteile jener Schichten, die für sie sprechen. Eine kaputte Signatur macht die Nachricht invalid, wie gut die anderen auch sind. Eine Schicht, die nur Chiffrat abdeckt, gehört nur dann dazu, wenn nichts den Klartext abdeckt (siehe unten): Eine solche Schicht kann die Nachricht nie valid machen, und sobald irgendeine Schicht den Klartext abdeckt, wird sie gänzlich außer Acht gelassen, wie schlecht sie auch sein mag.
Nur valid setzt state.signature_verified, das pepsi-stage-check-whitelist(1) als Schranke für einen Eintrag der weißen Liste verwendet.
85.1.7.1.6.1. Eine Signatur, die Chiffrat abdeckt¶
In signed(encrypted(body)) wird die Signatur über das Chiffrat berechnet, nicht über irgendetwas, das ein Leser je zu sehen bekommt. Das beweist, dass der Signierende den Blob übertragen hat; es beweist nicht, dass er ihn geschrieben hat, und es beweist nicht, dass er ihn lesen kann — jeder, der eine verschlüsselte Nachricht erlangt, kann sie in seine eigene Signatur wickeln und weiterleiten. Eine solche Schicht wird mit "covers_ciphertext": true in state.crypto.in.layers festgehalten und darf, was auch immer ihr eigenes Urteil ist, die Nachricht nie ``valid`` machen: Eine gute wird als valid-untrusted gemeldet, erhält also keine [verified]-Markierung und setzt state.signature_verified nicht. Eine schlechte wird als invalid gemeldet und unter ON_BAD_SIGNATURE geroutet — nur dann, wenn sie alles ist, was da ist, also wenn keine Schicht den Klartext abdeckt.
Sobald irgendeine Schicht den Klartext doch abdeckt, werden die chiffratabdeckenden vollständig beiseitegelegt, was auch immer ihr eigenes Urteil ist. Eine Schicht, die kein Urteil gewähren kann, darf keines zerstören können: Jeder, der den verschlüsselten Blob erlangt, kann ihn neu einwickeln, und wenn eine beschädigte Hülle invalid erzwänge, wäre es für einen Angreifer strikt nützlicher, die Hülle zu beschädigen, als sie zu entfernen (was ein gewöhnliches encrypted(signed(body)) zurücklässt, das weiterhin verifiziert). Die äußere Signatur eines Dreifachumschlags ist ohnehin ein Artefakt von Hop zu Hop — in §3.7 bringt ein Mailinglisten-Agent sie an —, ihr Fehlschlag sagt also nichts über den Autor. Die Manipulation geht nicht verloren: Sie bleibt in state.crypto.in.layers und in X-Pepsi-Crypto sichtbar, als Beobachtung und nicht als Routing-Eingabe. Dieselbe Überlegung deckt den häufigeren Fall einer äußeren Signatur ab, die bloß unverifiable ist (kein Schlüssel für den Weiterleiter), sodass der Dreifachumschlag unten nicht für einen Signierenden bestraft wird, den wir zufällig nicht kennen.
In signed(encrypted(signed(body))) — dem Dreifachumschlag, den RFC 8551 §3.7 empfiehlt — ist also die innere Signatur diejenige, die für den Inhalt spricht, und sie ist die, die diese Stage meldet. Diese Form wird daher als valid gemeldet, wo eine einzelne äußere Signatur es nicht wird.
Wann immer es ein Signatururteil gibt, hält state.crypto.in.signature auch covers_plaintext fest: true, wenn das Urteil von einer Signatur über den Klartext erteilt wurde, false, wenn es von einer um Chiffrat gelegten Schicht stammt. pepsi-stage-autocrypt-learn(1) akzeptiert nur die erste Art als Nachweis, dass ein Korrespondent einen unserer Schlüssel besitzt.
85.1.7.1.7. Fehlerbehandlung¶
Beide Fehlerpfade stellen standardmäßig zu, im Einklang mit Pepsis bewusster fail-open-Haltung bei eingehendem SPF, DKIM und DMARC:
ON_DECRYPT_FAILURE = passthroughDie weiterhin verschlüsselte Nachricht wird zugestellt. Der Benutzer hält den Schlüssel womöglich in seinem eigenen Client, und Mail zu bouncen, die wir bloß nicht öffnen konnten, hilft niemandem.
quarantineundbouncestehen zur Verfügung.ON_BAD_SIGNATURE = recordEine schlechte Signatur ist ein festgehaltenes Urteil, nie ein Zustellfehler. Mailinglisten, die Nachrichtentexte umschreiben, Weiterleiter und Clients mit kaputter Kanonisierung erzeugen alle schlechte Signaturen an völlig legitimer Mail; sie unter Quarantäne zu stellen kostete weit mehr, als es fängt.
quarantineundbouncestehen zur Verfügung.
Beachten Sie, dass für diesen Zweck nur invalid eine „schlechte Signatur“ ist. valid-untrusted und unverifiable sind der Normalzustand von Mail eines Korrespondenten, von dem hier niemand je gehört hat, und diese irgendwohin zu routen routete den größten Teil des Internets.
Die Entschlüsselungsrichtlinie wird zuerst herangezogen: Eine Nachricht, die nicht geöffnet werden konnte, hat kein Signatururteil, auf das zu reagieren sich lohnt.
Ein Empfängerschlüssel, den dieser Host besitzt, aber nicht öffnen kann — ein Schlüsselverschlüsselungsschlüssel, der nicht zum gespeicherten Blob passt, ein verschwundenes secrets.d-Fragment, eine entzogene Datenbankberechtigung —, endet ebenfalls als decrypt-failure=no-decryption-key und nimmt die ON_DECRYPT_FAILURE-Route, genau wie eine Nachricht, die an einen Schlüssel adressiert ist, den wir nie hatten. Das ist Absicht (eine kaputte Identität darf nicht verhindern, dass die anderen versucht werden), aber es ist eine kaputte Installation und nicht das Werk des Absenders, daher wird jede solche Identität auf Stufe error mit der Adresse und dem Grund protokolliert. Dasselbe gilt für Empfänger, die Entschlüsselungsidentitäten auf einem Host besitzen, auf dem überhaupt kein [pepsi-crypto] KEY_WRAP_SECRET konfiguriert ist.
85.1.7.1.8. Fehler dieses Hosts¶
Alles andere, was auf diesem Host schiefgeht, wird erneut versucht statt fehlschlagen gelassen (siehe pepsi-dispatch(1)): Eine Datenbank, die nicht antworten kann — einschließlich der Abfrage der eigenen MUA-Schlüssel der Empfänger, die nie als „kein solcher Schlüssel“ gelesen wird, da das Mail öffnen würde, die für den eigenen Client des Benutzers bestimmt ist —, wird pausiert und bis zur MAX_LIFETIME der Stage erneut versucht. Der Abschnitt der Stage, die [pepsi]-Krypto-Richtlinie, [pepsi-keydiscovery] und, wenn ein Schlüsselverschlüsselungsschlüssel konfiguriert ist, der daraus gebaute Schlüsselbund werden beim Start des Workers geprüft: Funktioniert einer davon nicht, verweigert der Worker den Start (Exit 78), sodass der Dispatcher die Warteschlange zurückhält, statt jede Nachricht am selben Fehler scheitern zu lassen. Eine Nachricht, die die Kryptografie zum Absturz bringt (eine Panic beim Parsen), wird sofort fehlschlagen gelassen: Sie ist das Werk der Nachricht und würde nur erneut abstürzen.
85.1.7.1.9. Mail für den eigenen Schlüssel des Benutzers¶
Ein Benutzer kann seinen eigenen Schlüssel registrieren, dessen privater Teil nur in seinem Mail-Client liegt (ein MUA-Schlüssel, crypto_identity.custody = client; siehe pepsi-stage-encrypt(1) und pepsi-keys(1)). Mail, die an einen solchen Schlüssel verschlüsselt ist, ist für den Mail-Client bestimmt, und die Stage erkennt sie, bevor sie versucht, irgendetwas zu öffnen: Sie liest die Empfängerkennungen des Chiffrats (OpenPGP-PKESK-Schlüssel-IDs, S/MIME-RecipientIdentifiers), ohne zu entschlüsseln, und gleicht sie mit den nicht widerrufenen Client-Schlüsseln der Empfänger ab. Eine Platzhalter-Schlüssel-ID („verborgener Empfänger“) passt auf nichts und nimmt den gewöhnlichen Pfad.
Bei einem Treffer wird die Nachricht ungeöffnet weitergereicht, selbst wenn auch einer unserer eigenen MTA-Schlüssel unter ihren Empfängern ist: Der Benutzer hat seinen eigenen Schlüssel registriert, um Ende-zu-Ende-Schutz zu erhalten, und eine Kopie auf dem Server zu öffnen und den Klartext im Postfach abzulegen, würde dies stillschweigend zunichtemachen. Die Stage hält state.crypto.in.decryption = for-client, for_client = true und client_fingerprint fest, setzt state.encrypted und fügt for-client=yes zu X-Pepsi-Crypto hinzu. Dies ist kein Entschlüsselungsfehler, daher wird ON_DECRYPT_FAILURE nicht herangezogen, und die Nachricht schaltet wie jede andere zu NEXT_STAGE weiter: Die Spam-Prüfungen und der Rest der Pipeline entscheiden weiterhin über ihr Schicksal. Eine Nachricht mit mehreren lokalen Empfängern wird zuerst auf einen Datensatz je Empfänger aufgeteilt, da der Client-Schlüssel eines Empfängers nichts über die Kopie eines anderen aussagt.
Die Folge ist, dass serverseitige Funktionen für solche Mail blind werden. Inhaltslesende Stages (etwa die Spracherkennung) sehen Chiffrat und fallen zurück, wie sie es bei jeder nicht entschlüsselbaren Nachricht tun, und es wurde nichts verifiziert, sodass state.signature_verified nie gesetzt wird und ein Whitelist-Eintrag mit signature_required nicht auf sie passt.
85.1.7.1.10. Fälschungsabwehr¶
Jedes X-Pepsi-*-Header-Feld wird aus jeder Nachricht entfernt, die diese Stage sieht — auch aus einer, die sie nicht anfassen wird, und auch aus einer, für die die Stage deaktiviert ist. Erst dann wird unser eigenes hinzugefügt.
X-Pepsi-Crypto ist ein privater Header, also definitionsgemäß fälschbar; die bedingungslose Entfernung ist die gesamte Grundlage dafür, dass ein Client ihm glauben darf. Der Pepsi-Origin-Herkunftsnachweis-Header liegt bewusst nicht im Namensraum und überlebt.
Dasselbe Argument gilt für das Subject. Mit STRIP_SUBJECT_TAGS = yes (dem Standardwert) wird das eigene Markierungsvokabular dieser Stage — TAG_DECRYPTED, TAG_VERIFIED, TAG_BAD_SIGNATURE, die eingebauten [decrypted] und [verified], wie auch immer die Markierungen konfiguriert sind, sowie alles in STRIP_SUBJECT_KEYWORDS — vom Anfang eines eingehenden Betreffs entfernt, bevor unseres vorangestellt wird. Andernfalls schreibt ein externer Absender [verified] einfach selbst. Markierungen werden nur vorn entfernt, und hinter einem Re:/Fwd:-Präfix, sodass ein Betreff, der eine mitten im Satz erwähnt, sie behält.
85.1.7.1.12. Der Ergebnis-Header¶
Mit ADD_RESULT_HEADER = yes (dem Standardwert) erhält eine Nachricht, die irgendeinen Schutz trug, ein Header-Feld, ganz oben vorangestellt, sodass es keine bestehende Signatur stört:
X-Pepsi-Crypto: encrypted=yes; decrypted=yes; protocol=openpgp;
signature=valid; signer=alice@example.net;
fingerprint=0123456789ABCDEF; key-source=wkd; trust=wkd-advanced;
layers="encrypted,signed"
Die Grammatik sind durch Semikola getrennte key=value-Paare in fester Reihenfolge. Ein Wert, der kein nacktes Token ist (A–Z, a–z, 0–9 und . _ @ : + / -), wird in doppelte Anführungszeichen gesetzt; ein eingebettetes " wird zu ', und Steuerzeichen werden durch Leerzeichen ersetzt, sodass kein Wert aus der Nachricht das Feld beenden oder ein anderes beginnen kann. Lange Werte werden an Leerraum gefaltet.
Die Schlüssel sind:
encryptedyes/no— die Nachricht kam mit Chiffrat an.decryptedyes/no— nur vorhanden, wennencrypted=yes.for-clientyes, wenn die Nachricht an den eigenen MUA-Schlüssel des Empfängers verschlüsselt ist und ungeöffnet durchgereicht wurde (Mail für den eigenen Schlüssel des Benutzers).protocolopenpgpodersmime.signatureEines der obigen Urteile.
signer,fingerprint,key-source,trust,algorithmDer Signierschlüssel, woher er kam und was er wert war. Nur vorhanden, wenn bekannt.
failureDer maschinenlesbare Grund, warum ein Signatururteil nicht gut ist.
decrypt-failureDer maschinenlesbare Grund, warum die Entschlüsselung fehlschlug.
layersDie Schutzschichten, von außen nach innen, kommagetrennt.
RFC 8601 registriert keine smime- oder pgp-Methode, sodass eine Authentication-Results-Erweiterung hieße, einen Methodennamen in einem Register zu erfinden, das uns nicht gehört — den andere Implementierungen ignorieren oder dem sie misstrauen dürfen. Ein privater Header mit dokumentierter Grammatik ist die ehrliche Wahl, und der Preis dafür ist das oben beschriebene bedingungslose Entfernen.
85.1.7.1.13. Schlüsselentdeckung¶
Die Stage betreibt überhaupt keine Netzwerk-E/A. Wenn der Schlüssel des Signierenden weder in der Nachricht noch im peer_key-Cache liegt, reiht sie eine Entdeckungsanfrage ein und parkt die Nachricht; ein pepsi-keydisc(1)-Dienst gibt sie frei, wenn sich die Anfrage erledigt, gefunden oder nicht, und die Stage läuft erneut. Eine erledigte Anfrage ohne Schlüssel gibt die Nachricht genauso frei, und sie verifiziert dann als unverifiable. Ein frischer Negativ-Cache-Eintrag kürzt das Warten ganz ab, was verhindert, dass ein Spammer, der mit einem unbekannten Schlüssel signiert, jede Nachricht warten lässt: Die erste parkt, der Rest nicht.
[pepsi-keydiscovery] INBOUND_TIMEOUT begrenzt die Wartezeit und ist getrennt vom ausgehenden TIMEOUT einstellbar; DISCOVERY_TIMEOUT im eigenen Abschnitt dieser Stage überschreibt es. DISCOVERY = no unterdrückt die Anfrage ganz und lässt die Stage auf dem Nur-Cache-Pfad.
Ob eine geparkte Nachricht entschlüsselt gespeichert wird, hängt von der Form der Nachricht ab, und der Unterschied zählt:
Eine S/MIME-Signatur, die in einem Umschlag verschachtelt ist, überlebt die Entschlüsselung als gewöhnliche MIME-Schicht, sodass die Nachricht mit festgeschriebenem Klartext geparkt und genau einmal entschlüsselt wird.
Eine OpenPGP-Signatur lebt nur innerhalb des Paketstroms und ist fort, sobald der Klartext heraus ist. Den Klartext zu committen zerstörte den Beleg, für dessen Prüfung der Schlüssel geholt wird, sodass eine solche Nachricht unverändert geparkt und beim Fortsetzen erneut entschlüsselt wird.
Eine mit committetem Klartext geparkte Nachricht liegt bis zur Entdeckungsfrist entschlüsselt in pepsi.workqueue. Das ist dieselbe Blöße, die die Zustellung einen Augenblick später ohnehin erzeugte; es ist ein längeres Fenster, kein neues.
85.1.7.1.14. Zertifikate, die die Nachricht mitführt¶
Die meiste signierte Mail führt das Zertifikat mit, das sie signiert hat, sodass die Stage, bevor sie etwas entscheidet, die S/MIME-Signiererzertifikate und application/pgp-keys-Teile aus der Nachricht liest und dem Verifizierer anbietet. Sie tut das erneut auf dem Klartext, sobald die Nachricht offen ist, denn ein innerhalb des Chiffrats angehängtes Zertifikat ist bis dahin unsichtbar, und bewertet einmal neu, falls das etwas ergab, was der erste Durchgang nicht hatte.
Diese Zertifikate werden benutzt und verworfen. Diese Stage speichert nichts: Aus eingehender Mail zu lernen — der Autocrypt:-Header, angehängte Schlüssel und Gossip — ist Sache von pepsi-stage-autocrypt-learn(1), das später in der Pipeline läuft, nach den Stages, die entscheiden, ob eine Nachricht Spam ist. Diese Trennung ist das, was die Spam-Regel von Autocrypt Level 1 §5.3 überhaupt einhaltbar macht: Diese Stage läuft konstruktionsbedingt zuerst auf dem eingehenden Pfad, bevor irgendein solches Urteil existiert. Es bedeutet auch, dass nichts von dem Prozess in den Schlüsselspeicher geschrieben wird, der die privaten Schlüssel hält.
Ein Zertifikat zu verwenden, das die Nachricht mitführte, kann das Ansehen eines Urteils immer nur senken, nie heben: Solches Material hat nicht vertrauenswürdige Herkunft, sodass eine dagegen geprüfte Signatur als valid-untrusted zurückkommt und state.signature_verified nicht setzt — den Schlüssel, den pepsi-stage-check-whitelist(1) als Schranke verwendet. Das ist dieselbe Sprosse, die ein gespeicherter geernteter Schlüssel hätte, sodass es nichts einbrächte, ihn durch die Datenbank zu leiten.
85.1.7.1.15. Zwei Tatsachen, die für die Lern-Stage festgehalten werden¶
Das Entschlüsseln committet den Klartext über die angekommenen Bytes, sodass zwei Dinge, die nur diese Stage sehen kann, für pepsi-stage-autocrypt-learn(1) in state.crypto.in geschrieben werden: encrypted, dass die Nachricht überhaupt Chiffrat trug, und outer_gossip, dass der ankommende Header-Block bereits ein Autocrypt-Gossip:-Feld hatte. Beides sind Voraussetzungen dafür, dem Gossip einer Nachricht zu glauben, und keines ist beantwortbar, sobald der Klartext im Datensatz steht.
85.1.7.1.16. Die Schlüssel unserer eigenen Benutzer werden nie überschrieben¶
Das Ernten schlüsselt auf den From:-Header, den der Absender schreibt, und die eingehende Authentifizierung ist bewusst fail-open. Eine Nachricht, die vorgibt, von einem der eigenen Benutzer dieser Installation zu kommen, säet daher für diesen Benutzer einen peer_key-Datensatz mit dem Schlüssel, den sie mitführte — und eine dagegen geprüfte Signatur würde sonst verifizieren und state.signature_verified setzen, das pepsi-stage-check-whitelist(1) als Schranke verwendet.
Bevor der Speicher herangezogen wird, fragt die Stage daher, ob der behauptete Absender jemand ist, für den sie eine Identität hält. Ist er es, ist der öffentliche Schlüssel dieser Identität der einzige Kandidat: Dem Verifizierer wird kein peer_key-Datensatz für die Adresse angeboten, gleich welchen Rangs und gleich wie er eintraf. Alles außer einer revoked-Identität zählt, abgelaufene eingeschlossen — eine letztes Jahr erstellte Signatur wurde mit dem letztjährigen Schlüssel erstellt, und sich zu weigern, sie anzusehen, meldete die Mail unserer eigenen Benutzer jedes Mal als unverifizierbar, wenn ein Schlüssel rotiert wurde.
Die Regel hängt daran, einen Schlüssel zu halten, nicht daran, die Adresse zu bedienen: Ein Benutzer, der seinen eigenen OpenPGP-Client betreibt und hier nie einen Schlüssel hochgeladen hat, hat keine Identität, sodass sein geernteter oder gegossipter Schlüssel genau so verwendet wird wie der jedes Korrespondenten. Der Preis ist das Spiegelbild — sobald für eine Adresse eine Identität gehalten wird, verifiziert eine mit dem separaten persönlichen Schlüssel dieses Benutzers erstellte Signatur nicht mehr. Siehe Die Schlüssel unserer eigenen Benutzer werden nicht entdeckt im Handbuch.
85.1.7.1.17. Vertrauensanker¶
X.509-Anker stammen aus der Tabelle pepsi.ca_trust (pepsi-keys(1) ca) und werden je Worker-Prozess für TRUST_ANCHOR_TTL (Standardwert fünf Minuten) zwischengespeichert. Ein hinzugefügter oder deaktivierter Anker wird daher innerhalb dieses Fensters wirksam; starten Sie die Worker neu, um ihn sofort anzuwenden. Sie werden träge geladen und nur für eine Nachricht, die tatsächlich eine S/MIME-Schicht trägt, sodass gewöhnlicher Verkehr keine Abfrage kostet.
Widerrufsdaten werden nicht abgerufen: Ein CRL-Abruf wäre Netzwerk-E/A in einer Stage, was der Entdeckungsentwurf gerade vermeiden soll. Eine Kette wird folglich mit dem Widerrufsstatus not-checked gemeldet, was ausgesprochen wird, statt es „nicht widerrufen“ nahelegen zu lassen.
85.1.7.1.18. Konfiguration¶
Die Stage liest ihren eigenen [stage-<name>]-Abschnitt (PROGRAM = pepsi-stage-decrypt, NEXT_STAGE (erforderlich), BOUNCE_STAGE, dazu ENABLED, LOCAL_DOMAINS, TARGETS, RECIPIENT_DELIMITER, REQUIRE_ACCOUNT, ON_DECRYPT_FAILURE, ON_BAD_SIGNATURE, QUARANTINE_STAGE, SUBJECT_TAGS, TAG_DECRYPTED, TAG_VERIFIED, TAG_BAD_SIGNATURE, STRIP_SUBJECT_TAGS, STRIP_SUBJECT_KEYWORDS, ADD_RESULT_HEADER, MAX_LAYERS, TRUST_ANCHOR_TTL, DISCOVERY, DISCOVERY_TIMEOUT), alle dokumentiert in pepsi.conf(5). pepsi-setup(1) verlangt ein BOUNCE_STAGE, sobald eine der beiden Fehlerrichtlinien bounce lautet, und ein QUARANTINE_STAGE, sobald eine von beiden quarantine lautet. Das sind Verhaltens-Optionen und je Adresse über die Tabelle pepsi.settings überschreibbar.
Die kryptographische Richtlinie — Algorithmenwahl, Akzeptanz schwacher Digests, Mindestschlüssellängen — liegt in den CRYPTO_*-Optionen von [pepsi] und in [pepsi-crypto]. Die sind ausschließlich Sache des Systemadministrators und aus pepsi.settings oder pepsi-stage-edit-settings(1) bewusst nicht erreichbar.
Eine davon gilt hier nicht. CRYPTO_ALLOW_DOWNGRADE regelt, was ausgegeben werden darf: OpenPGP-SEIPDv1+MDC und CMS-EnvelopedData sind stets lesbar, was auch immer es sagt, denn sie eingehend abzulehnen machte diesen Host unfähig, Mail aus dem größten Teil der Welt zu empfangen, ohne irgendjemanden zu schützen. Nur 3DES und die schwachen Signatur-Digests unterliegen eingehend einer Schranke, und jede Ablehnung erzeugt ihr eigenes Urteil statt eines generischen Fehlschlags. Die 3DES-Schranke ist auf beiden Seiten nicht dieselbe: Eine eingehende S/MIME-3DES-Nachricht wird nur unter yes angenommen, eine eingehende OpenPGP-Nachricht auch unter negotiate, denn ein OpenPGP-Zertifikat nennt seine eigenen Chiffrier-Fähigkeiten und ein X.509-Zertifikat nennt keine. Der tatsächlich verwendete Container wird je Schicht festgehalten, sodass eine Installation sehen kann, wie viel ihrer eingehenden Mail noch vor-AEAD ist.
85.1.7.1.19. Privilegien¶
Das Binärprogramm wird setuid pepsi-crypto installiert, Modus 4750 pepsi-crypto:pepsi, und ist daher nicht in das vereinheitlichte pepsi-Multi-Call-Binärprogramm eingefaltet.
Beide Hälften der Schlüsselverwahrungsgrenze richten sich nach dieser Identität. Die Datenbankrolle pepsi-crypto ist die einzige, der crypto_identity.private_wrapped gewährt ist, und die Peer-Authentifizierung von PostgreSQL richtet sich nach der effektiven uid; der Schlüsselverschlüsselungsschlüssel liegt in secrets.d/pepsi-crypto.secret, Modus 0640, im Besitz desselben Kontos. Ein setgid-Binärprogramm erlangte die Gruppe — genug, um das Fragment zu lesen — und authentifizierte sich gegenüber der Datenbank dennoch als pepsi, genau die Rolle, der die Spalte verwehrt ist.
Die Gruppe im Modus beschränkt die Ausführung auf das Konto des Dispatchers und root; das Programm verweigert zur Laufzeit außerdem den Dienst, sofern seine reale uid nicht root oder eines der Konten pepsi, pepsi-crypto und pepsi-owner ist. Diese Laufzeitprüfung greift nur, wenn das Binärprogramm das setuid-Bit tatsächlich trägt — ein ohne dieses Bit installierter Build (ein Entwicklerbaum, cargo test) lässt jeden es ausführen, mit der Begründung, dass ein solcher Aufrufer die Datenbank als er selbst erreicht und dann PostgreSQLs eigene Berechtigungen maßgeblich sind. -c wird von diesen Aufrufern angenommen (die dokumentierte Startform des Dispatchers ist PROGRAM -c cfg worker), und die Umgebung wird bereinigt, bevor die Konfiguration geladen wird, denn die Konfigurationsschicht ist über XDG_CONFIG_HOME, HOME, PATH und die PG*-Familie steuerbar.
Entschlüsselungsschlüssel werden nach Fähigkeit ausgewählt: jede nicht widerrufene Identität jedes lokalen Empfängers, deren purpose encrypt oder both ist, abgelaufene eingeschlossen, denn alte Mail muss lesbar bleiben.
85.1.7.1.20. Ressourcengrenzen¶
MAX_LAYERS (Standardwert 4) begrenzt, wie viele geschachtelte verschlüsselte Schichten ausgepackt werden; eine Nachricht mit mehr wird mit ungeöffnetem Rest zugestellt und decrypt-failure=unsupported festgehalten.
Eine OpenPGP-Nachricht ist routinemäßig komprimiert, und das Expansionsverhältnis ist die Wahl des Absenders, sodass pepsi-crypto einen Klartext über 64 MiB rundweg ablehnt, statt ihn abzuschneiden — ein Teilklartext darf nie als verifiziert gemeldet werden. Dieser Fall wird mit einem eigenen Fehlergrund, decrypt-failure=too-large, gemeldet und nicht als generischer Entschlüsselungsfehler: „diese Nachricht ist eine Bombe“ und „wir konnten diese nicht öffnen“ sind für einen Operator verschiedene Tatsachen.
85.1.7.1.21. State¶
Eingaben: state.dsn (beachtet und im Gleichschritt mit der Lokalitätsaufteilung zerteilt), state.crypto.in (bei einem fortgesetzten Datensatz das, was der entschlüsselnde Durchgang festgehalten hat).
Ausgaben: state.crypto.in — ob die Nachricht verschlüsselt war, was aus dem Chiffrat wurde (decryption: not-encrypted, decrypted, failed oder for-client), welche Identität sie geöffnet hat, das Signatururteil samt Detail (einschließlich covers_plaintext), die geordnete Schichtenliste und, bei Mail an den eigenen Schlüssel eines Benutzers, for_client und client_fingerprint. Außerdem state.encrypted = true, wenn die Nachricht verschlüsselt ankam, und state.signature_verified = true nur für das Urteil valid; pepsi-stage-check-whitelist(1) und pepsi-stage-auto-whitelist(1) lesen diese. Bei einem Bounce state.bounce. Das State-Layout wird in pepsi.state(7) beschrieben.
Übergänge: NEXT_STAGE für eine zugestellte Nachricht; QUARANTINE_STAGE oder BOUNCE_STAGE gemäß den Fehlerrichtlinien; paused während des Wartens auf die Schlüsselentdeckung; pending bei ebendieser Stage nach einer Lokalitätsaufteilung.
85.1.7.1.22. Befehle¶
- worker
Läuft als persistenter Dispatcher-Worker, liest Nachrichten-IDs von der Standardeingabe und schreibt eine Statuszeile je Nachricht. Das ist der einzige Modus; es gibt keine Einzelschussform. Um eine einzelne Nachricht von Hand auszuführen, pipen Sie ihre ID:
echo 1234 | pepsi-stage-decrypt -c /etc/pepsi/pepsi.conf worker
85.1.7.1.23. Exit-Status¶
- 0
Der Worker endete sauber (Standardeingabe geschlossen).
- 1
Ein Fehler ist aufgetreten (Fehlkonfiguration, ein nicht lesbarer Schlüsselspeicher oder ein Datenbankfehler). Der Grund wird in das Journal geschrieben.
- 78
Der Worker hat den Start verweigert: Seine Konfiguration oder sein Schlüsselbund funktioniert nicht (siehe Fehler dieses Hosts). Der Dispatcher reiht erneut ein, was er übergeben hatte, und versucht die Stage später wieder.
85.1.7.1.24. Siehe auch¶
pepsi-stage-encrypt(1), pepsi-stage-reencrypt(1), pepsi-stage-arc(1), pepsi-keys(1), pepsi-keydisc(1), pepsi-stage-check-whitelist(1), pepsi-stage-relay-to-maildir(1), pepsi-stage-relay-to-lmtp(1), pepsi-stage-bounce(1), pepsi-dispatch(1), pepsi-setup(1), pepsi.conf(5), pepsi.state(7)
85.1.7.1.25. Fehler¶
Melden Sie Fehler an den Pepsi-Issue-Tracker.