This is an automated email from the ASF dual-hosted git repository.

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

commit c7da02b3cc1917cafa7e18c5adc669e119a84549
Author: Quan Tran <[email protected]>
AuthorDate: Thu Nov 5 10:13:22 2026 +0700

    [FIX] DNSTestingServer: no extended rcode in the OPT record of an answer
    
    DNSTestingServer, derived from dnsjava's jnamed, gave the rcode of an
    answer to the OPT record it adds for a query with EDNS, as its
    extended rcode: the upper 8 bits of a 12-bit rcode (RFC 6891 6.1.3).
    Its answers of no data and NXDOMAIN, whose rcode is 3 for both inside
    the server, then read as rcode 48 and 51, errors. dnsjava's Lookup
    reads only the 4 bits of the header, so the YAML suites run over this
    server never noticed.
    
    Leave the extended bits 0: the rcode, NOERROR or NXDOMAIN, is in the
    header.
    A package-private constructor builds the server without its network
    listeners, for its test.
---
 .../james/jspf/tester/DNSTestingServerTest.java    | 66 ++++++++++++++++++++++
 .../apache/james/jspf/tester/DNSTestingServer.java | 10 +++-
 2 files changed, 75 insertions(+), 1 deletion(-)

diff --git 
a/resolver/src/test/java/org/apache/james/jspf/tester/DNSTestingServerTest.java 
b/resolver/src/test/java/org/apache/james/jspf/tester/DNSTestingServerTest.java
new file mode 100644
index 0000000..36b51b3
--- /dev/null
+++ 
b/resolver/src/test/java/org/apache/james/jspf/tester/DNSTestingServerTest.java
@@ -0,0 +1,66 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jspf.tester;
+
+import org.junit.Test;
+import org.xbill.DNS.DClass;
+import org.xbill.DNS.Message;
+import org.xbill.DNS.Name;
+import org.xbill.DNS.OPTRecord;
+import org.xbill.DNS.Rcode;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.Section;
+import org.xbill.DNS.Type;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+public class DNSTestingServerTest {
+    /**
+     * @return the answer of a server holding a TXT record of example.com to 
an EDNS query
+     */
+    private static Message answerOf(String name, int type) throws IOException {
+        DNSTestingServer server = new DNSTestingServer();
+        server.setData(Collections.singletonMap("example.com",
+            Collections.singletonList(Collections.singletonMap("TXT", "v=spf1 
-all"))));
+        Message query = 
Message.newQuery(Record.newRecord(Name.fromString(name), type, DClass.IN));
+        query.addRecord(new OPTRecord(1232, 0, 0), Section.ADDITIONAL);
+        byte[] wire = query.toWire();
+
+        return new Message(server.generateReply(wire, wire.length));
+    }
+
+    @Test(timeout = 10000)
+    public void shouldAnswerNxdomainToAnEdnsQueryOfANameThatDoesNotExist() 
throws Exception {
+        Message answer = answerOf("other.example.com.", Type.TXT);
+
+        // the rcode is in the header, the OPT record holds no extended bits 
(RFC 6891 6.1.3)
+        assertEquals(Rcode.NXDOMAIN, answer.getRcode());
+    }
+
+    @Test(timeout = 10000)
+    public void shouldAnswerNoErrorToAnEdnsQueryOfATypeTheNameHasNot() throws 
Exception {
+        Message answer = answerOf("example.com.", Type.A);
+
+        assertEquals(Rcode.NOERROR, answer.getRcode());
+    }
+}
diff --git 
a/tester/src/main/java/org/apache/james/jspf/tester/DNSTestingServer.java 
b/tester/src/main/java/org/apache/james/jspf/tester/DNSTestingServer.java
index 60a1125..c1ebb85 100644
--- a/tester/src/main/java/org/apache/james/jspf/tester/DNSTestingServer.java
+++ b/tester/src/main/java/org/apache/james/jspf/tester/DNSTestingServer.java
@@ -128,6 +128,13 @@ public class DNSTestingServer implements ResponseGenerator 
{
         zone = null;
     }
 
+    /**
+     * A server that only generates replies, without listening on the network: 
for tests
+     */
+    DNSTestingServer() {
+        zone = null;
+    }
+
     @SuppressWarnings("unchecked")
     public synchronized void setData(Map<String, List<?>> map) {
         try {
@@ -462,7 +469,8 @@ public class DNSTestingServer implements ResponseGenerator {
 
         if (queryOPT != null) {
             int optflags = (flags == FLAG_DNSSECOK) ? ExtendedFlags.DO : 0;
-            OPTRecord opt = new OPTRecord((short) 4096, rcode, (byte) 0,
+            // the rcode, NOERROR or NXDOMAIN, is in the header: no extended 
bits (RFC 6891 6.1.3)
+            OPTRecord opt = new OPTRecord((short) 4096, 0, (byte) 0,
                     optflags);
             response.addRecord(opt, Section.ADDITIONAL);
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to