(james-jspf) 04/07: Add more tests

[email protected]
Newsgroups gmane.comp.jakarta.james.devel
Message-ID <[email protected]>
This is an automated email from the ASF dual-hosted git repository.

btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-jspf.git

commit 530227acacd5018a752f7aad887793309768cfa2
Author: Emerson Pinter <[email protected]>
AuthorDate: Fri Jan 24 15:53:53 2025 -0300

    Add more tests
---
 .../org/apache/james/jspf/SPFExecutorBaseTest.java | 193 +++++++++++++++++++++
 .../dnszones/SPFExecutorIntegrationTest-1.zone     |  12 ++
 2 files changed, 205 insertions(+)

diff --git a/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java b/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
index ae1c296..acdc376 100644
--- a/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
+++ b/resolver/src/test/java/org/apache/james/jspf/SPFExecutorBaseTest.java
@@ -1,22 +1,33 @@
 package org.apache.james.jspf;
 
 import org.apache.james.jspf.core.DNSService;
+import org.apache.james.jspf.core.exceptions.SPFErrorConstants;
 import org.apache.james.jspf.executor.SPFResult;
+import org.apache.james.jspf.helpers.FakeResolver;
 import org.apache.james.jspf.impl.DNSServiceXBillImpl;
 import org.apache.james.jspf.impl.SPF;
 import org.junit.Before;
 import org.junit.Test;
 import org.xbill.DNS.DClass;
 import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Name;
 import org.xbill.DNS.Resolver;
+import org.xbill.DNS.SPFRecord;
 import org.xbill.DNS.SimpleResolver;
+import org.xbill.DNS.TXTRecord;
+import org.xbill.DNS.TextParseException;
 
+import java.io.IOException;
 import java.net.UnknownHostException;
+import java.nio.file.Paths;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import static org.junit.Assert.assertEquals;
 
 public abstract class SPFExecutorBaseTest {
+    protected final String zonesDir = "src/test/resources/dnszones";
 
     protected abstract SPF createSPF();
 
@@ -27,6 +38,10 @@ public abstract class SPFExecutorBaseTest {
         Lookup.getDefaultCache(DClass.IN).clearCache();
     }
 
+    public String getZonePath(String zoneFile) {
+        return Paths.get(zonesDir, zoneFile).toAbsolutePath().toString();
+    }
+
     @Test
     public void test() {
         SPF spf = createSPF();
@@ -68,4 +83,182 @@ public abstract class SPFExecutorBaseTest {
         assertEquals("Received-SPF: temperror (spfCheck: Error in retrieving data from DNS) client-ip=207.54.72.202; envelope-from=do_not_reply@reyifglerifwukfvbdjhrkbvebvekvfulervkerkeruerbeb.de; helo=reyifglerifwukfvbdjhrkbvebvekvfulervkerkeruerbeb.de;",
                 result.getHeader());
     }
+
+    @Test
+    public void shouldReturnPassIfJustOneTxtSpf1Record() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnPassIfJustOneTxtSpf1Record." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.fromZoneFile(testDomain, getZonePath("SPFExecutorIntegrationTest-1.zone"));
+        fakeResolver.addRecords(FakeResolver.genNRandomTXTRecords(hostname + ".", 300));
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: domain of %2$s designates %1$s as permitted sender) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PASS_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PASS_CONV, result.getResult());
+    }
+
+    @Test
+    public void shouldReturnErrorIfMoreThanOneTxtSpf1Record() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnErrorIfMoreThanOneTxtSpf1Record." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.fromZoneFile(testDomain, getZonePath("SPFExecutorIntegrationTest-1.zone"));
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: Error in processing SPF Record) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PERM_ERROR_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
+
+    @Test
+    public void shouldReturnErrorIfMoreThanOneSpfRecord() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnErrorIfMoreThanOneSpfRecord." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.setRecords(FakeResolver.genNRandomTXTRecords(hostname + ".", 300));
+        fakeResolver.addRecord(new SPFRecord(
+                Name.fromString(hostname + "."), DClass.IN, 30L, String.format("v=spf1 ip4:%s ip4:1.1.1.1 -all", ip)));
+        fakeResolver.addRecord(new SPFRecord(
+                Name.fromString(hostname + "."), DClass.IN, 30L, String.format("v=spf1 ip4:%s -all", ip)));
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: Error in processing SPF Record) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PERM_ERROR_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
+
+    /*
+     * Test the limit described in RFC7208 section "4.6.4.  DNS Lookup Limits"
+     */
+    @Test
+    public void shouldReturnErrorIfDepthMoreThan10() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnErrorIfDepthMoreThan10." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.addRecord(new TXTRecord(Name.fromString(hostname + "."),
+                DClass.IN, 30L, String.format("v=spf1 ip4:4.3.2.1 include:depth0.%s -all", hostname)));
+
+        fakeResolver.addRecords(IntStream.range(0, 10).mapToObj(
+                i -> {
+                    try {
+                        String txt = String.format("v=spf1 ip4:4.3.2.2 include:depth%s.%s -all", i + 1, hostname);
+                        return new TXTRecord(
+                                Name.fromString(String.format("depth%s.%s.", i, hostname), Name.fromString(testDomain)),
+                                DClass.IN, 30L, txt);
+                    } catch (TextParseException e) {
+                        throw new RuntimeException(e);
+                    }
+                }).collect(Collectors.toList()));
+
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: Error in processing SPF Record) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PERM_ERROR_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
+
+    /*
+     * Test the limit described in RFC7208 section "4.6.4.  DNS Lookup Limits"
+     */
+    @Test
+    public void shouldReturnPassIfDepth10orLess() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnPassIfDepth10OrLess." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.addRecord(new TXTRecord(Name.fromString(hostname + "."),
+                DClass.IN, 30L, String.format("v=spf1 ip4:4.3.2.1 include:depth0.%s -all", hostname)));
+
+        int count = 10;
+        fakeResolver.addRecords(IntStream.range(0, count).mapToObj(
+                i -> {
+                    try {
+                        String txt;
+                        if (i == count - 1) {
+                            txt = String.format("v=spf1 ip4:4.3.2.2 ip4:%s -all", ip);
+                        } else {
+                            txt = String.format("v=spf1 ip4:4.3.2.2 include:depth%s.%s -all", i + 1, hostname);
+                        }
+                        return new TXTRecord(
+                                Name.fromString(String.format("depth%s.%s.", i, hostname), Name.fromString(testDomain)),
+                                DClass.IN, 30L, txt);
+                    } catch (TextParseException e) {
+                        throw new RuntimeException(e);
+                    }
+                }).collect(Collectors.toList()));
+
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: domain of %2$s designates %1$s as permitted sender) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PASS_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PASS_CONV, result.getResult());
+    }
+
+    @Test
+    public void shouldReturnPermErrorIfIncludeDomainNotFound() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnPermErrorIfIncludeDomainNotFound." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.fromZoneFile(testDomain, getZonePath("SPFExecutorIntegrationTest-1.zone"));
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: Error in processing SPF Record) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PERM_ERROR_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PERM_ERROR_CONV, result.getResult());
+    }
+
+    @Test
+    public void shouldHandleMultipleStrings() throws IOException {
+        String testDomain = "spfexecutor.fake";
+        String hostname = "shouldReturnPassIfMultipleStrings." + testDomain;
+        String ip = "192.0.2.127";
+
+        //setup resolver
+        FakeResolver fakeResolver = new FakeResolver();
+        fakeResolver.fromZoneFile(testDomain, getZonePath("SPFExecutorIntegrationTest-1.zone"));
+
+        SPF spf = createCustomSPF(new DNSServiceXBillImpl(fakeResolver));
+        SPFResult result = spf.checkSPF(ip, "a_user@" + hostname, hostname);
+        assertEquals(String.format(
+                        "Received-SPF: %3$s (spfCheck: domain of %2$s designates %1$s as permitted sender) client-ip=%1$s; envelope-from=a_user@%2$s; helo=%2$s;",
+                        ip, hostname, SPFErrorConstants.PASS_CONV),
+                result.getHeader());
+        assertEquals(SPFErrorConstants.PASS_CONV, result.getResult());
+    }
 }
diff --git a/resolver/src/test/resources/dnszones/SPFExecutorIntegrationTest-1.zone b/resolver/src/test/resources/dnszones/SPFExecutorIntegrationTest-1.zone
new file mode 100644
index 0000000..8898bee
--- /dev/null
+++ b/resolver/src/test/resources/dnszones/SPFExecutorIntegrationTest-1.zone
@@ -0,0 +1,12 @@
+$TTL 30
+@   30    IN    SOA    ns1.fakeresolver.apache. hostmaster.fakeresolver.apache. 1 30 30 30 30
+@   30    IN    NS     ns1
+
+shouldReturnErrorIfMoreThanOneTxtSpf1Record         IN    TXT   "v=spf1 ip4:192.0.2.162 -all"
+shouldReturnErrorIfMoreThanOneTxtSpf1Record         IN    TXT   "v=spf1 ip4:192.0.2.127 ip4:1.1.1.1 -all"
+
+shouldReturnPassIfJustOneTxtSpf1Record              IN    TXT   "v=spf1 include:_spf.google.com include:spf.protection.outlook.com ip4:2.3.4.5 ip4:192.0.2.127 -all"
+
+shouldReturnPermErrorIfIncludeDomainNotFound        IN    TXT   "v=spf1 ip4:4.3.2.1 include:unknownDomain.fake -all"
+
+shouldReturnPassIfMultipleStrings                 IN    TXT   "v=spf1 mx a ip4:192.0.2.127 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1 ip4:4.3.2.1" " ip4:4.3.2.1 -all"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.