From 250b808c815c69a996d21131c7c52f7ea15a944d Mon Sep 17 00:00:00 2001 From: Hui Cao Date: Fri, 15 Nov 2019 11:49:34 -0800 Subject: [PATCH 1/4] Fix dkim verification issues and dmarc alignment default Change-Id: I0e023a602004bb18f573321c5811d1c876312663 --- dkim/canonical.go | 18 ++++-------------- dkim/query.go | 1 + dmarc/lookup.go | 2 ++ 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/dkim/canonical.go b/dkim/canonical.go index d25149d..ae1676a 100644 --- a/dkim/canonical.go +++ b/dkim/canonical.go @@ -2,6 +2,7 @@ package dkim import ( "io" + "regexp" "strings" ) @@ -104,21 +105,10 @@ func (c *relaxedCanonicalizer) CanonicalizeHeader(s string) string { var v string if len(kv) > 1 { - v = kv[1] - } - lines := strings.Split(v, crlf) - lines[0] = strings.TrimLeft(lines[0], " \t") + rxReduceWS := regexp.MustCompile(`[ \t\r\n]+`) + v = rxReduceWS.ReplaceAllString(kv[1], " ") + v = strings.TrimSpace(v) - v = "" - for _, l := range lines { - if len(l) == 0 { - break - } - - if l[0] == ' ' || l[0] == '\t' { - v += " " - } - v += strings.Trim(l, " \t") } return k + ":" + v + crlf diff --git a/dkim/query.go b/dkim/query.go index 9c09b10..b0fb0be 100644 --- a/dkim/query.go +++ b/dkim/query.go @@ -101,6 +101,7 @@ func parsePublicKey(s string) (*queryResult, error) { if p == "" { return nil, permFailError("key revoked") } + p = strings.ReplaceAll(p, " ", "") b, err := base64.StdEncoding.DecodeString(p) if err != nil { return nil, permFailError("key syntax error: " + err.Error()) diff --git a/dmarc/lookup.go b/dmarc/lookup.go index 4fa0896..2e9fa35 100644 --- a/dmarc/lookup.go +++ b/dmarc/lookup.go @@ -65,6 +65,7 @@ func Parse(txt string) (*Record, error) { return nil, err } + rec.DKIMAlignment = AlignmentRelaxed if adkim, ok := params["adkim"]; ok { rec.DKIMAlignment, err = parseAlignmentMode(adkim, "adkim") if err != nil { @@ -72,6 +73,7 @@ func Parse(txt string) (*Record, error) { } } + rec.SPFAlignment = AlignmentRelaxed if aspf, ok := params["aspf"]; ok { rec.SPFAlignment, err = parseAlignmentMode(aspf, "aspf") if err != nil { From 4126cd21093a96bd29b8daabf6cb6f6265e33e84 Mon Sep 17 00:00:00 2001 From: Hui Cao Date: Fri, 15 Nov 2019 13:01:55 -0800 Subject: [PATCH 2/4] Fix dkim verification issues and dmarc alignment default Change-Id: Id23c3a5f168214f441268e582d6448ab57defa12 --- dkim/canonical.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dkim/canonical.go b/dkim/canonical.go index ae1676a..440fe15 100644 --- a/dkim/canonical.go +++ b/dkim/canonical.go @@ -6,6 +6,8 @@ import ( "strings" ) +var rxReduceWS = regexp.MustCompile(`[ \t\r\n]+`) + // Canonicalization is a canonicalization algorithm. type Canonicalization string @@ -105,7 +107,6 @@ func (c *relaxedCanonicalizer) CanonicalizeHeader(s string) string { var v string if len(kv) > 1 { - rxReduceWS := regexp.MustCompile(`[ \t\r\n]+`) v = rxReduceWS.ReplaceAllString(kv[1], " ") v = strings.TrimSpace(v) From 5eaacad3557df258c035c8497b33e282bd999ee8 Mon Sep 17 00:00:00 2001 From: Hui Cao Date: Fri, 15 Nov 2019 13:33:51 -0800 Subject: [PATCH 3/4] Fix dkim verification issues and dmarc alignment default Change-Id: I299ac0c11aac1dda96c6637e2590413518972a1e --- dkim/canonical_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dkim/canonical_test.go b/dkim/canonical_test.go index 36cd9c7..e08a0c5 100644 --- a/dkim/canonical_test.go +++ b/dkim/canonical_test.go @@ -89,6 +89,10 @@ var relaxedCanonicalizerHeaderTests = []struct { "Subject \t:\t Kimi \t \r\n No \t\r\n Na Wa\r\n", "subject:Kimi No Na Wa\r\n", }, + { + "Subject \t:\t Ki \tmi \t \r\n No \t\r\n Na Wa\r\n", + "subject:Ki mi No Na Wa\r\n", + }, } func TestRelaxedCanonicalizer_CanonicalizeHeader(t *testing.T) { From 89e8201a6e5ac0e379ace8b8cd798f0a85aae212 Mon Sep 17 00:00:00 2001 From: Hui Cao Date: Sat, 11 Apr 2020 19:26:47 -0400 Subject: [PATCH 4/4] Allow setting lookup DNS/TXT function Change-Id: I5f77d2c52ace909fb18696492b9c4c6ce3ed5e57 --- dkim/query.go | 10 +++++++++- dmarc/lookup.go | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/dkim/query.go b/dkim/query.go index b0fb0be..d1e264f 100644 --- a/dkim/query.go +++ b/dkim/query.go @@ -68,8 +68,16 @@ var queryMethods = map[QueryMethod]queryFunc{ QueryMethodDNSTXT: queryDNSTXT, } +var lookupTXT = net.LookupTXT + +type lookupTXTFunc func(name string) ([]string, error) + +func SetLookupTXTFunc(lookup lookupTXTFunc) { + lookupTXT = lookup +} + func queryDNSTXT(domain, selector string) (*queryResult, error) { - txts, err := net.LookupTXT(selector + "._domainkey." + domain) + txts, err := lookupTXT(selector + "._domainkey." + domain) if netErr, ok := err.(net.Error); ok && netErr.Temporary() { return nil, tempFailError("key unavailable: " + err.Error()) } else if err != nil { diff --git a/dmarc/lookup.go b/dmarc/lookup.go index 2e9fa35..c4c1c4c 100644 --- a/dmarc/lookup.go +++ b/dmarc/lookup.go @@ -24,9 +24,17 @@ func IsTempFail(err error) bool { var ErrNoPolicy = errors.New("dmarc: no policy found for domain") +var lookupTXT = net.LookupTXT + +type lookupTXTFunc func(name string) ([]string, error) + +func SetLookupTXTFunc(lookup lookupTXTFunc) { + lookupTXT = lookup +} + // Lookup queries a DMARC record for a specified domain. func Lookup(domain string) (*Record, error) { - txts, err := net.LookupTXT("_dmarc." + domain) + txts, err := lookupTXT("_dmarc." + domain) if netErr, ok := err.(net.Error); ok && netErr.Temporary() { return nil, tempFailError("TXT record unavailable: " + err.Error()) } else if err != nil {