Commit
Author: mdecimus [mauro@stalw.art]
Hash: e77138ea4a9f5c6274b4c85b42dae7a7a5e92b23
Timestamp: Wed, 19 Jun 2024 17:16:20 +0000 (4 months ago)

+29 -16 +/-2 browse
Merge branch 'main' of github.com:stalwartlabs/mail-auth
1diff --git a/resources/spf/basic.yml b/resources/spf/basic.yml
2index a00787c..ff26b09 100644
3--- a/resources/spf/basic.yml
4+++ b/resources/spf/basic.yml
5 @@ -1,17 +1,22 @@
6- # If the <domain> is malformed (e.g., label longer than 63 characters,
7- # zero-length label not at the end, etc.) or is not a multi-label
8- # domain name, or if the DNS lookup returns "Name Error" (RCODE 3, also
9- # known as "NXDOMAIN" [RFC2308]), check_host() immediately returns the
10- # result "none".
11+ # If the <domain> is malformed (e.g., label longer than 63 characters, total
12+ # length longer than 255 characters, zero-length label not at the end, etc.) or
13+ # is not a multi-label domain name, or if the DNS lookup returns "Name Error"
14+ # (RCODE 3, also known as "NXDOMAIN" [RFC2308]), check_host() immediately
15+ # returns the result "none".
16
17 name: Malformed Domains
18 records:
19- spf: extremely.ridiculously.long.domain.name.that.should.fail.immediately.com v=spf1 +all
20+ spf: this.domain.name.is.extremely.long.because.we.want.to.explicitly.show.that.the.maximum.length.of.a.domain.name.is.255.characters.so.this.one.will.definitely.fail.immediately.due.to.its.excessive.length.and.ridiculously.large.number.of.characters.which.makes.it.invalid.com v=spf1 +all
21+ spf: thislabelisjustoverthesixtythreecharacterlimitandshouldbeanerror.com v=spf1 +all
22 spf: nolabels v=spf1 +all
23 spf: none.test.org v=something-else not=spf for=sure
24 tests:
25- - domain: extremely.ridiculously.long.domain.name.that.should.fail.immediately.com
26- sender: sender@extremely.ridiculously.long.domain.name.that.should.fail.immediately.com
27+ - domain: this.domain.name.is.extremely.long.because.we.want.to.explicitly.show.that.the.maximum.length.of.a.domain.name.is.255.characters.so.this.one.will.definitely.fail.immediately.due.to.its.excessive.length.and.ridiculously.large.number.of.characters.which.makes.it.invalid.com
28+ sender: sender@this.domain.name.is.extremely.long.because.we.want.to.explicitly.show.that.the.maximum.length.of.a.domain.name.is.255.characters.so.this.one.will.definitely.fail.immediately.due.to.its.excessive.length.and.ridiculously.large.number.of.characters.which.makes.it.invalid.com
29+ ip: 172.168.0.1
30+ expect: none
31+ - domain: thislabelisjustoverthesixtythreecharacterlimitandshouldbeanerror.com
32+ sender: sender@thislabelisjustoverthesixtythreecharacterlimitandshouldbeanerror.com
33 ip: 172.168.0.1
34 expect: none
35 - domain: nolabels
36 diff --git a/src/spf/verify.rs b/src/spf/verify.rs
37index 63152d3..0d1d7ec 100644
38--- a/src/spf/verify.rs
39+++ b/src/spf/verify.rs
40 @@ -26,7 +26,7 @@ impl Resolver {
41 helo_domain: &str,
42 host_domain: &str,
43 ) -> SpfOutput {
44- if helo_domain.has_labels() {
45+ if helo_domain.has_valid_labels() {
46 self.check_host(
47 ip,
48 helo_domain,
49 @@ -88,7 +88,7 @@ impl Resolver {
50 sender: &str,
51 ) -> SpfOutput {
52 let output = SpfOutput::new(domain.to_string());
53- if domain.is_empty() || domain.len() > 63 || !domain.has_labels() {
54+ if domain.is_empty() || domain.len() > 255 || !domain.has_valid_labels() {
55 return output.with_result(SpfResult::None);
56 }
57 let mut vars = Variables::new();
58 @@ -499,24 +499,32 @@ impl LookupLimit {
59 }
60 }
61
62- pub trait HasLabels {
63- fn has_labels(&self) -> bool;
64+ pub trait HasValidLabels {
65+ fn has_valid_labels(&self) -> bool;
66 }
67
68- impl HasLabels for &str {
69- fn has_labels(&self) -> bool {
70+ impl HasValidLabels for &str {
71+ fn has_valid_labels(&self) -> bool {
72 let mut has_dots = false;
73 let mut has_chars = false;
74+ let mut label_len = 0;
75 for ch in self.chars() {
76+ label_len += 1;
77+
78 if ch.is_alphanumeric() {
79 has_chars = true;
80 } else if ch == '.' {
81 has_dots = true;
82+ label_len = 0;
83 }
84- if has_chars && has_dots {
85- return true;
86+
87+ if label_len > 63 {
88+ return false;
89 }
90 }
91+ if has_chars && has_dots {
92+ return true;
93+ }
94 false
95 }
96 }