1/*2Maddy Mail Server - Composable all-in-one email server.3Copyright © 2019-2020 Max Mazurov <fox.cpp@disroot.org>, Maddy Mail Server contributors45This program is free software: you can redistribute it and/or modify6it under the terms of the GNU General Public License as published by7the Free Software Foundation, either version 3 of the License, or8(at your option) any later version.910This program is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13GNU General Public License for more details.1415You should have received a copy of the GNU General Public License16along with this program. If not, see <https://www.gnu.org/licenses/>.17*/1819package dns2021import (22 "net"23 "testing"2425 "github.com/foxcpp/go-mockdns"26 "github.com/foxcpp/maddy/framework/future"27 "github.com/foxcpp/maddy/framework/module"28 "github.com/foxcpp/maddy/internal/check"29 "github.com/foxcpp/maddy/internal/testutils"30)3132func TestRequireMatchingRDNS(t *testing.T) {33 test := func(rdns, srcHost string, fail bool) {34 rdnsFut := future.New()35 var ptr []string36 if rdns != "" {37 rdnsFut.Set(rdns, nil)38 ptr = []string{rdns}39 } else {40 rdnsFut.Set(nil, nil)41 }4243 res := requireMatchingRDNS(check.StatelessCheckContext{44 Resolver: &mockdns.Resolver{45 Zones: map[string]mockdns.Zone{46 "4.3.2.1.in-addr.arpa.": {47 PTR: ptr,48 },49 },50 },51 MsgMeta: &module.MsgMetadata{52 Conn: &module.ConnState{53 RemoteAddr: &net.TCPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 55555},54 Hostname: srcHost,55 RDNSName: rdnsFut,56 },57 },58 Logger: testutils.Logger(t, "require_matching_rdns"),59 })6061 actualFail := res.Reason != nil62 if fail && !actualFail {63 t.Errorf("%v, %s: expected failure but check succeeded", rdns, srcHost)64 }65 if !fail && actualFail {66 t.Errorf("%v, %s: unexpected failure", rdns, srcHost)67 }68 }6970 test("", "example.org", true)71 test("example.org", "[1.2.3.4]", true)72 test("example.org", "[IPv6:beef::1]", true)73 test("example.org", "example.org", false)74 test("example.org.", "example.org", false)75 test("example.org", "example.org.", false)76 test("example.org.", "example.org.", false)77 test("example.com.", "example.org.", true)78}7980func TestRequireMXRecord(t *testing.T) {81 test := func(mailFrom, mxDomain string, mx []net.MX, fail bool) {82 res := requireMXRecord(check.StatelessCheckContext{83 Resolver: &mockdns.Resolver{84 Zones: map[string]mockdns.Zone{85 mxDomain + ".": {86 MX: mx,87 },88 },89 },90 MsgMeta: &module.MsgMetadata{91 Conn: &module.ConnState{92 RemoteAddr: &net.TCPAddr{IP: net.IPv4(1, 2, 3, 4), Port: 55555},93 },94 },95 Logger: testutils.Logger(t, "require_mx_record"),96 }, mailFrom)9798 actualFail := res.Reason != nil99 if fail && !actualFail {100 t.Errorf("%v, %v: expected failure but check succeeded", mailFrom, mx)101 }102 if !fail && actualFail {103 t.Errorf("%v, %v: unexpected failure", mailFrom, mx)104 }105 }106107 test("foo@example.org", "example.org", nil, true)108 test("foo@example.com", "", nil, true) // NXDOMAIN109 test("foo@[1.2.3.4]", "", nil, true)110 test("[IPv6:beef::1]", "", nil, true)111 test("[IPv6:beef::1]", "", nil, true)112 test("foo@example.org", "example.org", []net.MX{{Host: "a.com"}}, false)113 test("foo@", "", nil, true)114 test("", "", nil, false) // Permit <> for bounces.115 test("foo@example.org", "example.org", []net.MX{{Host: "."}}, true)116}