4. The check_host() Function (Die check_host()-Funktion)
4. The check_host() Function (Die check_host()-Funktion)
Diese Beschreibung ist keine Anwendungsprogrammierschnittstellen-Definition, sondern eine Funktionsbeschreibung zur Erläuterung des Algorithmus. Konforme SPF-Implementierungen müssen Ergebnisse liefern, die dieser Beschreibung semantisch äquivalent sind.
Die check_host()-Funktion ruft SPF-Einträge ab, analysiert sie und wertet sie aus, um festzustellen, ob ein bestimmter Host berechtigt ist oder nicht berechtigt ist, E-Mails mit einer bestimmten Identität zu senden. Das empfangende ADMD, das diese Überprüfung durchführt, muss die check_host()-Funktion korrekt bewerten, wie hier beschrieben.
Implementierungen können einen anderen Algorithmus als den hier definierten kanonischen Algorithmus verwenden, solange die Ergebnisse in allen Fällen identisch sind.
4.1 Arguments (Argumente)
Die check_host()-Funktion nimmt die folgenden Argumente:
<ip> - Die IP-Adresse des SMTP-Clients, der die E-Mail sendet, entweder IPv4 oder IPv6.
<domain> - Die Domain, die die gesuchten Autorisierungsinformationen bereitstellt; anfänglich der Domain-Teil der "MAIL FROM"- oder "HELO"-Identität.
<sender> - Die "MAIL FROM"- oder "HELO"-Identität.
Für rekursive Auswertungen kann sich der Domain-Teil von <sender> vom <domain>-Argument bei der ersten Auswertung von check_host() unterscheiden. In den meisten anderen Fällen wird es dasselbe sein (siehe Abschnitt 5.2 unten). Die Gesamt-DNS-Abfragebeschränkung für SPF-Terme, die in Abschnitt 4.6.4 beschrieben wird, muss als einzelnes globales Limit über alle Auswertungen hinweg verfolgt werden, nicht nur für eine einzelne rekursive Auswertungsinstanz.
Beachten Sie, dass das <domain>-Argument möglicherweise kein wohlgeformter Domain-Name ist. Wenn beispielsweise der Reverse-Path leer ist, wird die EHLO/HELO-Domain mit den damit verbundenen Problemen verwendet (siehe Abschnitt 2.3). In diesen Fällen ist check_host() in Abschnitt 4.3 so definiert, dass es ein "none"-Ergebnis zurückgibt.
4.2 Results (Ergebnisse)
Die check_host()-Funktion kann eines von mehreren Ergebnissen zurückgeben, die in Abschnitt 2.6 beschrieben sind. Die zu ergreifende Aktion basierend auf dem Ergebnis wird durch die lokale Richtlinie des Empfängers bestimmt. Dies wird in Abschnitt 8 diskutiert.
4.3 Initial Processing (Anfangsverarbeitung)
Wenn <domain> fehlerhaft formatiert ist (z.B. Label-Länge über 63 Zeichen, nicht-endende Null-Längen-Labels usw.) oder kein Multi-Label-Domain-Name ist, oder wenn die DNS-Abfrage "Name Error" (RCODE 3, auch bekannt als "NXDOMAIN" [RFC2308]) zurückgibt, gibt check_host() sofort das Ergebnis "none" zurück. DNS RCODEs sind in [RFC1035] definiert. Ein wohlgeformter Domain ist ein vollqualifizierter Domain-Name, wie in [RFC1983] definiert. Das heißt, im DNS sind sie implizit relativ zur Root qualifiziert (siehe Abschnitt 3.1 von [RFC1034]). Internationalisierte Domain-Namen müssen als A-Label kodiert werden, wie in Abschnitt 2.3 von [RFC5890] beschrieben.
Wenn <sender> keinen local-part hat, ersetzen Sie den local-part durch die Zeichenkette "postmaster".
4.4 Record Lookup (Eintragsabfrage)
Abhängig davon, wie der Eintrag veröffentlicht wird (siehe Abschnitt 3 oben), ist eine DNS-Abfrage für den <domain>-Namen erforderlich, nur für Typ TXT.
Wenn die DNS-Abfrage einen Server-Fehler (RCODE 2) oder einen anderen Fehler (RCODE nicht 0 oder 3) zurückgibt, oder wenn die Abfrage eine Zeitüberschreitung hat, terminiert check_host() sofort mit dem Ergebnis "temperror".
4.5 Selecting Records (Auswahl von Einträgen)
Einträge beginnen mit einem Versionsteil:
record = version terms *SP
version = "v=spf1"
Beginnend mit der aus der Abfrage zurückgegebenen Eintrags-Menge, verwerfen Sie Einträge, die nicht mit einem Versionsteil von genau "v=spf1" beginnen. Beachten Sie, dass der Versionsteil durch ein SP-Zeichen oder das Ende des Eintrags terminiert wird. Zum Beispiel passt ein Eintrag mit einem Versionsteil "v=spf10" nicht und wird verworfen.
Wenn die resultierende Eintrags-Menge keine Einträge enthält, liefert check_host() ein "none"-Ergebnis. Wenn die resultierende Eintrags-Menge mehrere Einträge enthält, liefert check_host() ein "permerror"-Ergebnis.
4.6 Record Evaluation (Eintragsbewertung)
Die check_host()-Funktion analysiert und interpretiert den SPF-Eintrag, um ein Ergebnis für den aktuellen Test zu finden. Zunächst wird die Syntax des Eintrags validiert, und wenn irgendwo im Eintrag Syntaxfehler vorliegen, gibt check_host() sofort das Ergebnis "permerror" zurück, ohne weitere Interpretation oder Bewertung.
4.6.1 Term Evaluation (Term-Bewertung)
Es gibt zwei Arten von Termen: Mechanismen (definiert in Abschnitt 5) und Modifikatoren (definiert in Abschnitt 6). Einträge enthalten eine geordnete Liste dieser, wie in der folgenden erweiterten Backus-Naur-Form (ABNF) angegeben.
terms = *( 1*SP ( directive / modifier ) )
directive = [ qualifier ] mechanism
qualifier = "+" / "-" / "?" / "~"
mechanism = ( all / include
/ a / mx / ptr / ip4 / ip6 / exists )
modifier = redirect / explanation / unknown-modifier
unknown-modifier = name "=" macro-string
; where name is not any known modifier
name = ALPHA *( ALPHA / DIGIT / "-" / "_" / "." )
Die meisten Mechanismen erlauben ein ":" oder "/" Zeichen nach dem Namen.
Modifikatoren enthalten immer ein Gleichheitszeichen ('=') unmittelbar nach dem Namen und vor jedem ":" oder "/" Zeichen, das Teil eines macro-string sein könnte.
Ein Term, der keines der Zeichen "=", ":" oder "/" enthält, ist ein Mechanismus, wie in Abschnitt 5 definiert.
Nach der ABNF-Notation, wie in [RFC5234] definiert, sind Mechanismus- und Modifikatornamen nicht case-sensitiv.
4.6.2 Mechanisms (Mechanismen)
Jeder Mechanismus wird der Reihe nach von links nach rechts betrachtet. Wenn es keine weiteren Mechanismen gibt, ist das Ergebnis das in Abschnitt 4.7 beschriebene Standardergebnis.
Wenn ein Mechanismus bewertet wird, können drei Dinge geschehen: Es kann übereinstimmen, nicht übereinstimmen oder eine Ausnahme zurückgeben.
Wenn es übereinstimmt, endet die Verarbeitung und der Qualifier-Wert wird als Ergebnis für diesen Eintrag zurückgegeben. Wenn es nicht übereinstimmt, wird mit dem nächsten Mechanismus fortgefahren. Wenn es eine Ausnahme zurückgibt, endet die Mechanismusverarbeitung und der Ausnahmewert wird zurückgegeben.
Die möglichen Qualifier und die Ergebnisse, die sie dazu veranlassen, dass check_host() zurückgibt, sind wie folgt:
"+" pass
"-" fail
"~" softfail
"?" neutral
Der Qualifier ist optional und standardmäßig "+".
Wenn der Mechanismus übereinstimmt und der Qualifier "-" ist, wird ein "fail"-Ergebnis zurückgegeben und die Erklärungszeichenkette wird berechnet, wie in Abschnitt 6.2 beschrieben.
Abschnitt 5 beschreibt die spezifischen Mechanismen.
4.6.3 Modifiers (Modifikatoren)
Modifikatoren sind keine Mechanismen. Sie geben keine Übereinstimmung oder Nicht-Übereinstimmung zurück. Stattdessen liefern sie zusätzliche Informationen. Obwohl Modifikatoren die Bewertung des Eintrags nicht direkt beeinflussen, hat der "redirect"-Modifikator nach der Bewertung aller Mechanismen eine Auswirkung.
4.6.4 DNS Lookup Limits (DNS-Abfragebeschränkungen)
Einige Mechanismen und Modifikatoren (zusammen als "Terme" bezeichnet) verursachen bei der Bewertung DNS-Abfragen, während andere dies nicht tun. Die folgenden Terme verursachen DNS-Abfragen: die Mechanismen "include", "a", "mx", "ptr" und "exists" sowie der "redirect"-Modifikator. SPF-Implementierungen müssen die Gesamtzahl dieser Terme während einer SPF-Auswertung auf 10 begrenzen, um eine unangemessene Last auf DNS zu vermeiden. Wenn dieses Limit überschritten wird, muss die Implementierung "permerror" zurückgeben. Andere Terme -- die Mechanismen "all", "ip4" und "ip6" sowie der "exp"-Modifikator -- verursachen keine DNS-Abfragen bei der SPF-Auswertung (der "exp"-Modifikator verursacht nur zu einem späteren Zeitpunkt eine Abfrage), und ihre Verwendung unterliegt nicht diesem Limit.
Bei der Bewertung des "mx"-Mechanismus ist die Anzahl der abgefragten "MX"-Ressourceneinträge in der oben genannten Gesamtbeschränkung von 10 Mechanismen/Modifikatoren enthalten, die DNS-Abfragen verursachen. Zusätzlich zu dieser Beschränkung darf die Bewertung jedes "MX"-Eintrags absolut nicht dazu führen, dass mehr als 10 Adresseinträge abgefragt werden -- "A"- oder "AAAA"-Ressourceneinträge. Wenn dieses Limit überschritten wird, muss der "mx"-Mechanismus ein "permerror"-Ergebnis liefern.
Bei der Bewertung des "ptr"-Mechanismus oder des %\{p}-Makros ist die Anzahl der abgefragten "PTR"-Ressourceneinträge in der oben genannten Gesamtbeschränkung von 10 Mechanismen/Modifikatoren enthalten, die DNS-Abfragen verursachen. Zusätzlich zu dieser Beschränkung darf die Bewertung jedes "PTR"-Eintrags absolut nicht dazu führen, dass mehr als 10 Adresseinträge abgefragt werden -- "A"- oder "AAAA"-Ressourceneinträge. Wenn dieses Limit überschritten wird, müssen alle Einträge außer den ersten 10 ignoriert werden.
Der Grund für den Unterschied ist, dass der Satz und Inhalt von MX-Einträgen unter der Kontrolle des veröffentlichenden ADMD steht, während der Satz und Inhalt von PTR-Einträgen unter der Kontrolle des Besitzers der IP-Adresse steht, die tatsächlich die Verbindung herstellt.
Diese Beschränkungen gelten pro Mechanismus oder Makro in einem Eintrag und sind zusätzlich zu den oben angegebenen Abfragebeschränkungen.
Ein MTA oder anderer Prozessor sollte eine Beschränkung der maximalen verstrichenen Zeit auferlegen, die für die Bewertung von check_host() verwendet wird. Eine solche Beschränkung sollte mindestens 20 Sekunden zulassen. Wenn eine solche Beschränkung überschritten wird, sollte das Autorisierungsergebnis "temperror" sein.
Wie am Ende von Abschnitt 11.1 erwähnt, kann es in einigen Fällen nützlich sein, die Anzahl der "Terme" zu begrenzen, die DNS-Abfragen zurückgeben, die eine positive Antwort (RCODE 0) mit einer Antwortanzahl von 0 oder eine "Name Error"-Antwort (RCODE 3) zurückgeben. Diese werden manchmal zusammen als "void lookups" bezeichnet. SPF-Implementierungen sollten "void lookups" auf zwei begrenzen. Implementierungen können wählen, ein solches Limit konfigurierbar zu machen. In diesem Fall wird empfohlen, dass der Standardwert zwei beträgt. Das Überschreiten des Limits führt zu einem "permerror"-Ergebnis.
4.7 Default Result (Standardergebnis)
Wenn keiner der Mechanismen übereinstimmt und es keinen "redirect"-Modifikator gibt, gibt check_host() das Ergebnis "neutral" zurück, so als ob "?all" als letztes Direktiv angegeben wäre. Wenn ein "redirect"-Modifikator vorhanden ist, fährt check_host() fort, wie in Abschnitt 6.1 definiert.
Es wird bevorzugt, einen "redirect"-Modifikator oder einen "all"-Mechanismus zu verwenden, um die Verarbeitung explizit zu beenden. Obwohl es ein implizites "?all" am Ende jedes Eintrags gibt, der nicht explizit terminiert, hilft es bei Debugging-Bemühungen, wenn es explizit bereitgestellt wird.
Beispiel:
v=spf1 +mx -all
Oder
v=spf1 +mx redirect=_spf.example.com
4.8 Domain Specification (Domain-Spezifikation)
Mehrere dieser Mechanismen und Modifikatoren haben einen <domain-spec>-Teil. Die Zeichenkette wird der Makroerweiterung unterzogen (siehe Abschnitt 7). Die resultierende Zeichenkette ist die übliche Darstellung eines vollqualifizierten DNS-Namens: eine Folge von Labels, die durch Punkte getrennt sind. Diese Domain wird im Rest dieses Dokuments als <target-name> bezeichnet.
Hinweis: Das Ergebnis der Makroerweiterung unterliegt keinem weiteren Escaping. Daher kann dieses Tool nicht alle Zeichen erzeugen, die in DNS-Labels legal sind (z.B. Steuerzeichen). Dieses Tool ist jedoch leistungsfähig genug, um legale Hostnamen und übliche Utility-Labels auszudrücken, die im DNS verwendet werden (z.B. "_spf").
Für mehrere Mechanismen ist <domain-spec> optional. Wenn es nicht bereitgestellt wird, wird das <domain> aus den check_host()-Argumenten (siehe Abschnitt 4.1) als <target-name> verwendet. "domain" und <target-name> sind nach der Makroerweiterung syntaktisch identisch. "domain" ist der Eingabewert für check_host(), während <target-name> von check_host() berechnet wird.
Die Bewertung von check_host() mit einer syntaktisch ungültigen Domain ist undefiniert.
Hinweis: Dieses Dokument und sein Vorgänger enthalten keine Bestimmung für die korrekte Behandlung von syntaktisch ungültigen <domain-spec> (möglicherweise das Ergebnis einer Makroerweiterung) gemäß [RFC1035]. Beispiele sind Namen mit leeren Labels wie "foo..example.com" und Labels mit einer Länge von mehr als 63 Zeichen. Einige Implementierungen wählen, solche Fehler als Nicht-Übereinstimmung zu behandeln und solche Namen daher zu ignorieren, während andere Implementierungen eine "permerror"-Ausnahme zurückgeben.