public static void main(String[] args) throws Exception { try (DatagramSocket socket = new DatagramSocket()) { Message message = new Message(); Header header = message.getHeader(); header.setOpcode(Opcode.QUERY); header.setID(1); header.setRcode(Rcode.NOERROR); header.setFlag(Flags.RD); message.addRecord(Record.newRecord(new Name("www.xqbase.com."), Type.A, DClass.IN), Section.QUESTION); byte[] data = message.toWire(); DatagramPacket packet = new DatagramPacket(data, data.length, new InetSocketAddress("localhost", 53)); socket.send(packet); data = new byte[65536]; packet = new DatagramPacket(data, data.length); socket.setSoTimeout(2000); socket.receive(packet); Message response = new Message(Bytes.left(data, packet.getLength())); System.out.println(response); } }
@Test public void testDNameWithNoCnameIsValid() throws IOException { Message m = resolver.send(createMessage("www.isc.ingotronic.ch./A")); Message message = messageFromString(m.toString().replaceAll("(.*CNAME.*)", "").replaceAll("\n\n", "\n")); add("www.isc.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.isc.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); Lookup l = new Lookup("www.isc.ingotronic.ch"); l.setResolver(resolver); Record[] results = l.run(); assertTrue(results != null); assertTrue(results.length >= 1); }
@Test public void testValidAnswerToDifferentQueryTypeIsBogus() throws IOException { Message m = resolver.send(createMessage("www.ingotronic.ch./A")); Message message = createMessage("www.ingotronic.ch./MX"); for (int i = 1; i < Section.ADDITIONAL; i++) { for (Record r: m.getSectionArray(i)) { message.addRecord(r, i); } } add("www.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("validate.response.unknown:UNKNOWN", getReason(response)); }
@Test public void testUnsignedThatMustBeSigned() throws IOException { Name query = Name.fromString("www.ingotronic.ch."); // prepare a faked, unsigned response message that must have a signature // to be valid Message message = new Message(); message.addRecord(Record.newRecord(query, Type.A, DClass.IN), Section.QUESTION); message.addRecord(new ARecord(query, Type.A, DClass.IN, InetAddress.getByName(localhost)), Section.ANSWER); add("www.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("validate.bogus.missingsig", getReason(response)); }
@Test public void testModifiedSignature() throws IOException { Name query = Name.fromString("www.ingotronic.ch."); // prepare a faked, unsigned response message that must have a signature // to be valid Message message = new Message(); message.addRecord(Record.newRecord(query, Type.A, DClass.IN), Section.QUESTION); message.addRecord(new ARecord(query, Type.A, DClass.IN, InetAddress.getByName(localhost)), Section.ANSWER); message.addRecord(new RRSIGRecord(query, DClass.IN, 0, Type.A, Algorithm.RSASHA256, 5, new Date(System.currentTimeMillis() + 5000), new Date(System.currentTimeMillis() - 5000), 1234, Name.fromString("ingotronic.ch."), new byte[] { 1, 2, 3 }), Section.ANSWER); add("www.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertTrue(getReason(response).startsWith("failed.answer.positive:{ www.ingotronic.ch.")); }
private void setAnswerFlagsToState(Header header, AnswerScreenState state){ state.flag_AA = header.getFlag(Flags.AA); state.flag_AD = header.getFlag(Flags.AD); state.flag_TC = header.getFlag(Flags.TC); state.flag_RD = header.getFlag(Flags.RD); state.flag_RA = header.getFlag(Flags.RA); state.flag_CD = header.getFlag(Flags.CD); }
/** * A packet is available. Decode it and act accordingly. If the packet is * truncated over UDP, and ignoreTruncation is false, then a tcp query is * run to return the whole response. * * @param data * @param ignoreMe */ @Override public void dataAvailable(byte[] data, Connection ignoreMe) { // Now get the data, and send it back to the listener. try { disconnect(ignoreMe); Message message = NonblockingResolver.parseMessage(data); if (message != null && LOG.isTraceEnabled()) { LOG.trace("dataAvailable(" + data.length + " bytes)"); LOG.trace(message); } NonblockingResolver.verifyTSIG(query, message, data, tsig); // Now check that we got the whole message, if we're asked to do so if (!tcp && !ignoreTruncation && message.getHeader().getFlag(Flags.TC)) { // Redo the query, but use tcp this time. tcp = true; // Now start again with a TCP connection startConnect(); return; } if (query.getHeader().getID() != message.getHeader().getID()) { // System.out.println("Query wrong id! Expected " + query.getHeader().getID() + " but got " + message.getHeader().getID()); return; } returnResponse(message); } catch (IOException e) { returnException(e, null); } }
private Message messageWithResponseCode(int responseCode) { Message message = new Message(); message.getHeader().setOpcode(Opcode.UPDATE); message.getHeader().setFlag(Flags.QR); message.getHeader().setRcode(responseCode); return message; }
private Message responseMessageWithCode(Message query, int responseCode) { Message message = new Message(query.getHeader().getID()); message.getHeader().setOpcode(query.getHeader().getOpcode()); message.getHeader().setFlag(Flags.QR); message.getHeader().setRcode(responseCode); return message; }
/** * Apply any final massaging to a response before returning up the pipeline. * Primarily this means setting the AD bit or not and possibly stripping * DNSSEC data. */ private SMessage processFinishedState(Message request, SMessage response) { // If the response message validated, set the AD bit. SecurityStatus status = response.getStatus(); String reason = response.getBogusReason(); switch (status) { case BOGUS: // For now, in the absence of any other API information, we // return SERVFAIL. int code = response.getHeader().getRcode(); if (code == Rcode.NOERROR || code == Rcode.NXDOMAIN || code == Rcode.YXDOMAIN) { code = Rcode.SERVFAIL; } response = ValidatingResolver.errorMessage(request, code); break; case SECURE: response.getHeader().setFlag(Flags.AD); break; case UNCHECKED: case INSECURE: break; default: throw new RuntimeException("unexpected security status"); } response.setStatus(status, reason); return response; }
/** * Creates a response message with the given return code. * * @param request The request for which the response belongs. * @param rcode The response code, @see Rcode * @return The response message for <code>request</code>. */ private static SMessage errorMessage(Message request, int rcode) { SMessage m = new SMessage(request.getHeader().getID(), request.getQuestion()); Header h = m.getHeader(); h.setRcode(rcode); h.setFlag(Flags.QR); return m; }
@Test public void testInvalidIterationCountMarksInsecure() throws IOException { Properties config = new Properties(); config.put("org.jitsi.dnssec.nsec3.iterations.1024", 0); config.put("org.jitsi.dnssec.nsec3.iterations.2048", 0); config.put("org.jitsi.dnssec.nsec3.iterations.4096", 0); resolver.init(config); Message response = resolver.send(createMessage("www.wc.nsec3.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals("failed.nsec3_ignored", getReason(response)); }
@Test public void testNsec3WithoutClosestEncloser() throws IOException { Message m = resolver.send(createMessage("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A")); Message message = messageFromString(m.toString().replaceAll("((UDUMPS9J6F8348HFHH2FAED6I9DDE0U6)|(NTV3QJT4VQDVBPB6BNOVM40NMKJ3H29P))\\.nsec3.*", "")); add("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A", message); Message response = resolver.send(createMessage("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.nxdomain.nsec3_bogus", getReason(response)); }
@Test public void testNsec3NodataChangedToNxdomainIsBogus() throws IOException { Message m = resolver.send(createMessage("a.b.nsec3.ingotronic.ch./MX")); Message message = messageFromString(m.toString().replaceAll("status: NOERROR", "status: NXDOMAIN")); add("a.b.nsec3.ingotronic.ch./A", message); Message response = resolver.send(createMessage("a.b.nsec3.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.nxdomain.nsec3_bogus", getReason(response)); }
@Test public void testEccgostAlgIsUnknown() throws IOException { Message response = resolver.send(createMessage("eccgost.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals("insecure.ds.noalgorithms:eccgost.ingotronic.ch.", getReason(response)); }
@Test public void testDoubleLabelMXBelowSignedForExistingA() throws IOException { // a.b.ingotronic.ch./A exists Message response = resolver.send(createMessage("a.b.ingotronic.ch./MX")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(0, response.getSectionRRsets(Section.ANSWER).length); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testNsecEcdsa256() throws IOException { Provider[] providers = Security.getProviders("KeyFactory.EC"); Assume.assumeTrue(providers != null && providers.length > 0); Message response = resolver.send(createMessage("www.wc.nsec3-ecdsa256.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); }
@Test public void testNsecEcdsa384() throws IOException { Provider[] providers = Security.getProviders("KeyFactory.EC"); Assume.assumeTrue(providers != null && providers.length > 0); Message response = resolver.send(createMessage("www.wc.nsec3-ecdsa384.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); }
@Test public void testSingleLabelMXBelowSignedForExistingANsec3() throws IOException { Message response = resolver.send(createMessage("www.nsec3.ingotronic.ch./MX")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(0, response.getSectionRRsets(Section.ANSWER).length); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testNoDataWhenDSResultIsFromChild() throws IOException { Message m = resolver.send(createMessage("samekey.ingotronic.ch./MX")); // this test needs to have the key in the cache add("samekey.ingotronic.ch./DS", m, false); Message response = resolver.send(createMessage("samekey.ingotronic.ch./DS")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.nodata", getReason(response)); }
@Test public void testNoDataOfDSForRoot() throws IOException { Message response = resolver.send(createMessage("./DS")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testValidExising() throws IOException { Message response = resolver.send(createMessage("www.partial.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals(localhost, firstA(response)); assertNull(getReason(response)); }
@Test public void testDoubleLabelMXBelowSignedForExistingWildcardANsec3() throws IOException { // *.d.nsec3.ingotronic.ch./A exists Message response = resolver.send(createMessage("b.d.nsec3.ingotronic.ch./MX")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(0, response.getSectionRRsets(Section.ANSWER).length); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testValidNonExising() throws IOException { Message response = resolver.send(createMessage("www.gibtsnicht.partial.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NXDOMAIN, response.getRcode()); assertNull(getReason(response)); }
@Test public void testDoubleLabelABelowSignedNsec3MissingNsec3() throws IOException { Message m = resolver.send(createMessage("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A")); Message message = messageFromString(m.toString().replaceAll("L40.+nsec3\\.ingotronic\\.ch\\.\\s+300.*", "")); add("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A", message); Message response = resolver.send(createMessage("gibtsnicht.gibtsnicht.nsec3.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.nxdomain.nsec3_bogus", getReason(response)); }
@Test public void testFakedNoDataNsec3WithNsecs() throws IOException { Message m = resolver.send(createMessage("www.nsec3.ingotronic.ch./MX")); Message message = messageFromString(m.toString().replaceAll("type = MX", "type = A")); add("www.nsec3.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.nsec3.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertTrue(getReason(response).startsWith("failed.nodata")); }
@Test public void testUnsigned() throws IOException { Message response = resolver.send(createMessage("www.unsigned.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals(localhost, firstA(response)); assertEquals("insecure.ds.nsec", getReason(response)); // send the query a second time to ensure the cache doesn't create a wrong behavior response = resolver.send(createMessage("www.unsigned.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals(localhost, firstA(response)); assertEquals("insecure.ds.nsec", getReason(response)); }
@Test public void testDNameToNoDataIsValid() throws IOException { Message response = resolver.send(createMessage("www.alias.ingotronic.ch./MX")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testDNameToNxDomainIsValid() throws IOException { Message response = resolver.send(createMessage("x.alias.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NXDOMAIN, response.getRcode()); assertNull(getReason(response)); }
@Test public void testDNameDirectQueryIsValid() throws IOException { Message response = resolver.send(createMessage("alias.ingotronic.ch./DNAME")); assertTrue("AD flag must not set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); for (RRset set : response.getSectionRRsets(Section.ANSWER)) { if (set.getType() == Type.DNAME) { DNAMERecord r = (DNAMERecord)set.first(); assertEquals(Name.fromString("ingotronic.ch."), r.getTarget()); } } }
@Test public void testDNameWithFakedCnameIsInvalid() throws IOException { Message m = resolver.send(createMessage("www.alias.ingotronic.ch./A")); Message message = messageFromString(m.toString().replaceAll("(.*CNAME\\s+)(.*)", "$1 www.isc.org.")); add("www.alias.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.alias.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.synthesize.nomatch:www.isc.org.:www.ingotronic.ch.", getReason(response)); }
@Test public void testDNameWithMultipleCnamesIsInvalid() throws IOException { Message m = resolver.send(createMessage("www.alias.ingotronic.ch./A")); Message message = messageFromString(m.toString().replaceAll("(.*CNAME.*)", "$1\n$1example.com.")); add("www.alias.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.alias.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.synthesize.multiple", getReason(response)); }
@Test public void testValidExising() throws IOException { Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals(localhost, firstA(response)); assertNull(getReason(response)); }
@SuppressWarnings("unchecked") @Test public void testDNameInNsecIsUnderstood_Rfc6672_5_3_4_1() throws IOException { Message nsecs = resolver.send(createMessage("alias.ingotronic.ch./NS")); RRset nsecSet = null; for (RRset set : nsecs.getSectionRRsets(Section.AUTHORITY)) { if (set.getName().equals(Name.fromString("alias.ingotronic.ch."))) { nsecSet = set; break; } } Message message = new Message(); message.getHeader().setRcode(Rcode.NXDOMAIN); message.addRecord(Record.newRecord(Name.fromString("www.alias.ingotronic.ch."), Type.A, DClass.IN), Section.QUESTION); Iterator<Record> rrs = nsecSet.rrs(); while (rrs.hasNext()) { message.addRecord(rrs.next(), Section.AUTHORITY); } Iterator<Record> sigs = nsecSet.sigs(); while (sigs.hasNext()) { message.addRecord(sigs.next(), Section.AUTHORITY); } add("www.alias.ingotronic.ch./A", message); Message response = resolver.send(createMessage("www.alias.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("failed.nxdomain.exists:www.alias.ingotronic.ch.", getReason(response)); }
@Test public void testDNameToExternal() throws IOException { Message response = resolver.send(createMessage("www.isc.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testDNameChain() throws IOException { Message response = resolver.send(createMessage("www.alias.nsec3.ingotronic.ch./A")); assertTrue("AD flag must be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertNull(getReason(response)); }
@Test public void testDnskeyPrimeResponseWithEmptyAnswerIsBad() throws IOException { Message message = new Message(); message.addRecord(Record.newRecord(Name.root, Type.DNSKEY, DClass.IN), Section.QUESTION); add("./DNSKEY", message); Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("validate.bogus.badkey:.:dnskey.no_rrset:.", getReason(response)); }
@Test public void testMd5AlgRfc6944() throws IOException { Message response = resolver.send(createMessage("rsamd5.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.NOERROR, response.getRcode()); assertEquals("insecure.ds.noalgorithms:rsamd5.ingotronic.ch.", getReason(response)); }
@Test public void testDnskeyPrimeResponseWithInvalidSignatureIsBad() throws IOException, NumberFormatException, DNSSECException { Message m = resolver.send(createMessage("./DNSKEY")); Message message = messageFromString(m.toString().replaceAll("(.*\\sRRSIG\\sDNSKEY\\s(\\d+\\s+){6}.*\\.)(.*)", "$1 YXNkZg==")); add("./DNSKEY", message); Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("validate.bogus.badkey:.:dnskey.no_ds_match", getReason(response)); }
@Test @PrepareMocks("prepareTestDnskeyPrimeResponseWithMismatchedFootprintIsBad") public void testDnskeyPrimeResponseWithMismatchedFootprintIsBad() throws Exception { Message response = resolver.send(createMessage("www.ingotronic.ch./A")); assertFalse("AD flag must not be set", response.getHeader().getFlag(Flags.AD)); assertEquals(Rcode.SERVFAIL, response.getRcode()); assertEquals("validate.bogus.badkey:.:dnskey.no_ds_match", getReason(response)); }