85.1.13. pepsi-stage-dot-forward¶
process per-user ~/.forward files
- Handbuchabschnitt:
1
85.1.13.1.1. Name¶
pepsi-stage-dot-forward - die ~/.forward-Verarbeitungs-Stage der Pepsi-Pipeline.
85.1.13.1.2. Übersicht¶
pepsi-stage-dot-forward [GLOBAL-OPTIONS] worker
85.1.13.1.3. Beschreibung¶
pepsi-stage-dot-forward ist ein Stage-Programm, das von pepsi-dispatch(1) ausgeführt wird. Für jeden Umschlagempfänger, der auf ein lokales Konto auflöst, führt es die ~/.forward-Datei dieses Benutzers aus — der klassische sendmail/Postfix-Mechanismus, mit dem ein Kontoinhaber seine eigene Mail umleitet. Die Lokalität wird genau wie in pepsi-stage-relay-to-maildir(1) entschieden: Die Domain des Empfängers muss in LOCAL_DOMAINS stehen, sein Postfachname (Local-Part, Subadresse nach RECIPIENT_DELIMITER entfernt, kleingeschrieben) muss auf einen passwd-Eintrag auflösen, und diese uid muss durch TARGETS erlaubt sein. Ein Empfänger, der nicht lokal ist, bleibt unberührt und schaltet zu NEXT_STAGE weiter. Eine passwd-Abfrage, die fehlschlägt (ein LDAP- oder sssd-Backend, das nicht läuft), wird nicht als „nicht lokal“ gewertet: Die Nachricht wird erneut versucht, statt am ~/.forward des Benutzers vorbei zugestellt zu werden.
Das ~/.forward selbst wird von dem privilegierten Helper pepsi-helper-dot-forward(1) gelesen und ausgeführt, der zuvor seine Privilegien auf den Zielbenutzer absenkt. Der Exit-Status des Helpers teilt der Stage mit, was aus diesem Empfänger wurde:
kein ~/.forward — der Empfänger ist eine Durchleitung: Er bleibt auf der Nachricht, die zu NEXT_STAGE weiterschaltet (typischerweise lokale Zustellung, dann ein Smarthost). Ein Empfänger, der durch seinen eigenen
\name-Eintrag behalten wird, schaltet ebenfalls zu NEXT_STAGE weiter, aber, wann immer die Nachricht aufgeteilt wird, auf einem eigenen Geschwisterdatensatz, sodass keine Wiederholung dieser Stage sein~/.forwardein zweites Mal ausführt.weitergeleitet — der Empfänger wird durch die vom
~/.forwardbenannten Adressen ersetzt. Diese starten die Pipeline bei RESTART_STAGE (Standardwertinit) auf einem neuenpending-Geschwister-Datensatz neu, sodass die umgeschriebenen Empfänger wie frische Mail neu authentifiziert und neu geroutet werden. Eine leere Adressliste (die Nachricht wurde vollständig von|pipe//file-Direktiven verbraucht) lässt den Empfänger einfach fallen.fehlgeschlagen — der Helper hat sich für diesen Empfänger verweigert oder ist gescheitert (Exit
2): Ein Pipe-Befehl beendete sich mit einem Wert ungleich null, eine Datei konnte nicht geschrieben werden, oder eine deaktivierte Direktive wurde angefordert. Der Empfänger wird zu BOUNCE_STAGE geroutet, sodass eine Failure-DSN erzeugt wird (unter Beachtung desNOTIFYdes Absenders). Für eine Nachricht, die selbst ein Bounce ist (Null-Absender), wird nie erneut ein Bounce erzeugt.Host-Problem — der Helper meldete einen betrieblichen Fehler (Exit
3: Er ist nicht setuid-root installiert, die passwd-Abfrage schlug fehl, das Konto wird abgelehnt, oder das Heimatverzeichnis bzw. das~/.forwardgehört nicht ausschließlich dem Benutzer — es gehört ihm nicht oder ist für die Gruppe bzw. für alle schreibbar; der Helper prüft das Heimatverzeichnis, bevor er nach einem~/.forwardsucht, sodass dies auch Konten abweist, die keines haben), ein|commandbat darum, erneut versucht zu werden (es endete mit75,EX_TEMPFAIL, oder überschritt seine Zeit), oder der Helper konnte gar nicht ausgeführt werden, wurde durch ein Signal beendet oder endete mit einem Status, den er nicht dokumentiert. Nichts davon ist ein Urteil über den Empfänger, also wird nichts gebounct: Die Nachricht wird erneut versucht (eine Minute, verdoppelt bis zu einer Stunde, bis MAX_LIFETIME; siehe pepsi-dispatch(1)).Die früher im selben Durchlauf verarbeiteten Empfänger sind erledigt — ihre Pipes sind gelaufen, ihre Dateien geschrieben —, daher werden sie vor der Wiederholung mit ihrem Ergebnis (weitergeleitet, behalten, gebounct) committet, und die Nachricht wird auf die Empfänger reduziert, die der Helper nicht erreicht hat. Eine Wiederholung führt das
~/.forwardeines Empfängers daher nie zweimal aus. Die einzige Ausnahme ist der Empfänger, dessen eigenes~/.forwardmittendrin aufgeschoben hat: Direktiven oberhalb derjenigen, die aufgeschoben hat, haben gewirkt und wirken erneut.
Eine einzelne Nachricht kann eine Mischung dieser Ergebnisse über ihre Empfänger hinweg haben; die weitergeleiteten Adressen, die Bounces je Empfänger und die behaltenen (durchgeleiteten) Empfänger werden in einer einzigen Aufteilung der Nachricht abgeglichen, gefolgt von ihrem Terminal (in derselben Anweisung, wenn kein Empfänger auf der Nachricht verbleibt). Das Token jedes Geschwisterdatensatzes wird aus dem Empfänger oder dem weiterleitenden Login abgeleitet, den er trägt, sodass ein wiederholter Durchlauf nie mit einem kollidieren kann, den ein früherer Durchlauf erzeugt hat.
85.1.13.1.4. Weiterleitungsschleifen¶
Weil eine weitergeleitete Nachricht die gesamte Pipeline neu startet, würden zwei Benutzer, die einander weiterleiten (~bob → alice, ~alice → bob), in eine Schleife geraten. Um dies zu verhindern, trägt jeder weitergeleitete Datensatz seine Weiterleitungskette in state["dot-forwarders"] (siehe pepsi.state(7)): die Kette des Datensatzes, von dem er weitergeleitet wurde, plus das Login, dessen ~/.forward ihn weitergeleitet hat. Ein Empfänger, dessen Benutzer bereits in der Kette seines Datensatzes steht, wird nicht zugestellt, und der Helper wird nicht aufgerufen (eine Warnung wird protokolliert), sodass die Kette terminiert. Der Empfänger wird wie bei jedem anderen ~/.forward-Fehler zu BOUNCE_STAGE geroutet, sodass der Absender es erfährt (RFC 5321 §6.1 verlangt eine Benachrichtigung, sobald die Nachricht angenommen wurde); eine Nachricht, die selbst ein Bounce ist, oder eine Stage ohne BOUNCE_STAGE lässt ihn stattdessen fallen.
Die Kette gehört zu einem Weiterleitungspfad, nicht zur Nachricht: Wenn mehrere Empfänger einer Nachricht weiterleiten, gehen die Adressen jedes einzelnen auf einem eigenen Geschwister-Datensatz hinaus, der nur die Kette dieses Empfängers trägt, sodass die ~/.forward eines Empfängers einen späteren Hop über die eines anderen nie wie eine Schleife aussehen lässt. Eine Adresse, an die mehrere von ihnen weiterleiten, wird einmal zugestellt, auf dem Datensatz des ersten Empfängers, der sie genannt hat.
85.1.13.1.5. Argumente und Unterbefehle¶
- worker
Läuft als persistenter pepsi-dispatch(1)-Worker, der Nachrichten-IDs von der Standardeingabe liest und je eine Statuszeile schreibt. So führt der Dispatcher die Stage im Produktivbetrieb aus.
85.1.13.1.6. Konfiguration¶
Aus dem [stage-<stage>]-Abschnitt der Nachricht gelesen:
- PROGRAM
Muss
pepsi-stage-dot-forwardsein.- RESTART_STAGE
Die Stage, bei der eine erfolgreich weitergeleitete Nachricht neu startet. Standardwert ist
init(führt die gesamte eingehende Pipeline erneut aus, einschließlich Authentifizierung). Setzen Sie sie auf eine spätere Stage (z. B.srs), um die erneute Authentifizierung einer intern weitergeleiteten Nachricht zu überspringen. Muss eine existierende Stage benennen.- ALLOW_PIPE
Ob
|command-Direktiven in einem~/.forwardbeachtet werden (die Nachricht wird an den Befehl geleitet, der als der Benutzer ausgeführt wird). Standardwert istyes.- ALLOW_FILE
Ob
/path-Direktiven (die Nachricht an eine Datei anhängen) beachtet werden. Standardwert istyes. Sind sowohl ALLOW_PIPE als auch ALLOW_FILEno, leitet die Stage den Nachrichtentext überhaupt nicht an den Helper weiter (der Helper muss nur Weiterleitungsadressen lesen).- TARGETS, LOCAL_DOMAINS, RECIPIENT_DELIMITER
Die Auswahl lokaler Konten, in der Bedeutung identisch mit pepsi-stage-relay-to-maildir(1). Standardwert von TARGETS ist der reguläre (Nicht-System-)uid-Bereich aus
/etc/login.defs, und pepsi-helper-dot-forward(1) lehnt jede uid unterUID_MINab, was auch immer dort steht (pepsi-setup(1) warnt vor einem Token, das darunter reicht); Standardwert von LOCAL_DOMAINS ist[pepsi-ingress] ACCEPTED_DOMAINS; Standardwert von RECIPIENT_DELIMITER ist[pepsi] RECIPIENT_DELIMITERund, falls dieses fehlt,+(noneschaltet das Entfernen der Subadresse ab).- HELPER
Der auszuführende privilegierte
~/.forward-Helper. Standardwert istpepsi-helper-dot-forward(auf$PATHaufgelöst); setzen Sie einen absoluten Pfad, um ihn zu überschreiben.- NEXT_STAGE
Wohin durchgeleitete Empfänger (kein
~/.forward) weiterschalten. Erforderlich, da die meisten Empfänger kein~/.forwardhaben. Die Stage wird normalerweise direkt vor der lokalen Zustellung platziert, sodass NEXT_STAGE die Lokale-Zustellung-Stage ist.- BOUNCE_STAGE
Die DSN-Erzeugungs-Stage, zu der ein Empfänger geroutet wird, wenn die Ausführung seines
~/.forwardfehlschlägt.
85.1.13.1.7. Eine ~/.forward-Datei¶
Der Helper deutet jede nicht leere Zeile des ~/.forward des Benutzers, die kein Kommentar (#) ist, als eines von:
eine E-Mail-Adresse — gesammelt und als neuer Empfänger verwendet;
\name— sendmails Markierung „an name zustellen und nicht weiter expandieren“. Die Adresse wird nicht bei RESTART_STAGE neu gestartet: Benennt sie das eigene Konto des Empfängers (das kanonische\bobin~bob/.forward, womit ein Benutzer eine lokale Kopie behält und zugleich weiterleitet), bleibt dieser Empfänger einfach auf der Nachricht und schaltet zu NEXT_STAGE weiter; jedes andere\name— ein bloßer Name wird mit der Domain des Empfängers qualifiziert — wird zu einem Geschwister-Datensatz bei NEXT_STAGE. Weil ein solcher Empfänger diese Stage nie erneut betritt, kann die Markierung keine unbegrenzte Schleife erzeugen. Beachten Sie, dass sie auch das eigene~/.forwardjenes Benutzers umgeht, was „nicht weiter expandieren“ bedeutet;|command— ist ALLOW_PIPE eingeschaltet, wird die Nachricht an/bin/sh -c commandgeleitet, das als der Benutzer ausgeführt wird;/absolute/path— ist ALLOW_FILE eingeschaltet, wird die Nachricht als der Benutzer an diese Datei angehängt (im mbox-Stil).
Weiterleitungsadressen sollten vollqualifiziert sein (user@domain); ein bloßer lokaler Name wird wörtlich zurückgegeben und löst möglicherweise nicht erneut als lokal auf.
Ein |command bekommt 300 Sekunden, um fertig zu werden; danach wird seine gesamte Prozessgruppe abgeschossen und der Empfänger wie bei einem Befehl, der mit 75 endete, erneut versucht (ein langsamer Zustellagent sagt nichts über den Empfänger aus; ihn zu bouncen verwarf Mail, die eine Minute später angenommen worden wäre). Die Stage ihrerseits gibt einen Helper auf und schießt ihn ab, wenn er nach 330 Sekunden nicht fertig ist, was sie als wiederholbaren Fehler statt als Bounce meldet. Beide Grenzen sind fest einkompilierte Konstanten, keine Konfiguration: Sie sorgen dafür, dass das |sleep infinity eines einzigen Kontos — oder eine Datei-Direktive, die ein FIFO benennt — keinen Dispatcher-Worker dauerhaft belegen kann und PARALLELISM solcher Fälle die Stage nicht zum Stillstand bringen. Eine Datei-Direktive muss eine reguläre Datei benennen; ein FIFO, ein Gerät oder ein Symlink wird abgelehnt.
85.1.13.1.8. Installation und Privilegien¶
Um den setuid-root-Helper zu erreichen, muss pepsi-stage-dot-forward selbst set-group-id auf die Gruppe pepsi-forward installiert sein (Modus 2550, Eigentümer pepsi:pepsi-forward — ausführbar für den Eigentümer und nicht für alle, denn das setgid-Bit ist die Schranke vor dem setuid-root-Helper; das Ausführungsrecht kann auch nicht aus den Gruppenbits kommen, da pepsi bewusst kein Mitglied der Gruppe ist, also kommt es vom Eigentümer). pepsi-dispatch(1) führt die Stage als unprivilegierten Dienstbenutzer pepsi aus; das setgid-Bit gibt dem Worker eine effektive gid von pepsi-forward, was genau das ist, was ihm erlaubt, den gruppenbeschränkten pepsi-helper-dot-forward(1) auszuführen — und nichts anderes auf dem Host erlangt diese Fähigkeit. make install richtet dies ein (mit seinem Schritt install-forward-stage), sofern es als root ausgeführt wird und die Gruppe pepsi-forward existiert; andernfalls gibt es die genauen, von Hand auszuführenden Befehle aus.
Da das setgid-Bit diese Schranke ist, stellt das Programm dieselbe Regel selbst auf: Sofern der reale Benutzer nicht root oder das Dienstkonto pepsi ist, beendet es sich mit einem Fehler, bevor irgendeine Konfiguration gelesen wird, und — wie die setuid-Krypto-Stages — entfernt es die Umgebungsvariablen, die das Laden der Konfiguration steuern (HOME, XDG_CONFIG_HOME, PG*, TALER_*, PEPSI_*), und legt PATH auf einen sicheren Standardwert fest. Ein Dateimodus ist eine Tatsache der Installation und dies eine Tatsache des Programms; keines von beiden soll für sich allein stehen.
85.1.13.1.9. Siehe auch¶
pepsi-helper-dot-forward(1), pepsi-stage-relay-to-maildir(1), pepsi-stage-aliases(1), pepsi-stage-bounce(1), pepsi-dispatch(1), pepsi.conf(5), pepsi.state(7)
85.1.13.1.10. Fehler¶
Melden Sie Fehler an den Pepsi-Issue-Tracker.