/** * This resolver works when it is: 1. Enabled 2. The query is absolute 3. The name/address is not * in a Eucalyptus controlled subdomain * * @see com.eucalyptus.util.dns.DnsResolvers.DnsResolver#checkAccepts(Record, org.xbill.DNS.Name, * InetAddress) */ @Override public boolean checkAccepts(Record query, InetAddress source) { if (!Bootstrap.isOperational() || !enabled) { return false; } else if ((RequestType.A.apply(query) || RequestType.AAAA.apply(query)) && query.getName().isAbsolute() && !DomainNames.isSystemSubdomain(query.getName())) { return true; } else if (RequestType.PTR.apply(query) && !Subnets.isSystemManagedAddress( DomainNameRecords.inAddrArpaToInetAddress(query.getName()))) { return true; } return false; }
private static String createQuery(final Record query) { if (query != null && query.getName() != null) { final String qname = query.getName().toString(); final String qtype = Type.string(query.getType()); final String qclass = DClass.string(query.getDClass()); return new StringBuilder() .append("fqdn=") .append(qname) .append(" type=") .append(qtype) .append(" class=") .append(qclass) .toString(); } return ""; }
/* * Look for SOA records corresponding to the request * TODO: Add cache coherency to SOA records? */ protected synchronized Record checkForSoaRecord(String questionName) { if (!questionName.endsWith(".")) questionName += "."; if (soaRecords == null) { DnsRecord[] getRecs = null; // load all SOA records... try { getRecs = proxy.getDNSByType(Type.SOA); if (getRecs == null || getRecs.length == 0) soaRecords = Collections.emptyMap(); else { soaRecords = new HashMap<String, Record>(); for (DnsRecord rec : getRecs) { Record newRec = Record.newRecord( Name.fromString(rec.getName()), Type.SOA, rec.getDclass(), rec.getTtl(), rec.getData()); soaRecords.put(newRec.getName().toString(), newRec); } } } catch (Exception e) { LOGGER.error("Failed to load SOA records from config service."); } } Record retVal = null; if (soaRecords.size() > 0) { // look for the record by question name retVal = soaRecords.get(questionName); if (retVal == null) { // start taking apart the question name . by . int index = -1; while ((index = questionName.indexOf(".")) > 0 && index < (questionName.length() - 1)) { questionName = questionName.substring(index + 1); retVal = soaRecords.get(questionName); if (retVal != null) break; } } } return retVal; }
public static SetResponse findRecords( final Message response, final Record queryRecord, final InetAddress source) { final Name name = queryRecord.getName(); final int type = queryRecord.getType(); try { if (!enabled || !Bootstrap.isOperational()) { return SetResponse.ofType(SetResponse.UNKNOWN); } else { final Iterable<DnsResolver> resolverList = DnsResolvers.resolversFor(queryRecord, source); LOG.debug("DnsResolvers.findRecords(): resolvers for " + name + " are: " + resolverList); if (Iterables.isEmpty(resolverList)) { return SetResponse.ofType(SetResponse.UNKNOWN); } else { return DnsResolvers.lookupRecords(response, queryRecord, source); } } } catch (final Exception ex) { LOG.error(ex); LOG.trace(ex, ex); } return SetResponse.ofType(SetResponse.UNKNOWN); }
private static SetResponse lookupRecords( final Message response, final Record query, final InetAddress source) { final Name name = query.getName(); final int type = query.getType(); response.getHeader().setFlag(Flags.RA); // always mark the response w/ the recursion available // bit LOG.debug("DnsResolver: " + RequestType.typeOf(type) + " " + name); for (final DnsResolver r : DnsResolvers.resolversFor(query, source)) { try { final DnsResponse reply = r.lookupRecords(query); if (reply == null) { LOG.debug("DnsResolver: returned null " + name + " using " + r); continue; } if (reply.isAuthoritative()) { // mark response.getHeader().setFlag(Flags.AA); } if (reply.isNxdomain()) { addRRset(name, response, new Record[] {DomainNameRecords.sourceOfAuthority(name)}, type); response.getHeader().setRcode(Rcode.NXDOMAIN); return SetResponse.ofType(SetResponse.NXDOMAIN); } else if (reply.hasAnswer()) { for (ResponseSection s : ResponseSection.values()) { Record[] records = reply.section(s); if (records != null) { addRRset(name, response, records, s.section()); } } return SetResponse.ofType(SetResponse.SUCCESSFUL); } } catch (final Exception ex) { LOG.debug( "DnsResolver: failed for " + name + " using " + r + " because of: " + ex.getMessage(), ex); } } return SetResponse.ofType(SetResponse.UNKNOWN); // no dice, return unknown }
@SuppressWarnings("unchecked") public void execute() throws Exception { // Read in the zone List<Record> records = ZoneUtils.readZoneFile(state.inputfile, null); if (records == null || records.size() == 0) { System.err.println("error: empty RRset file"); state.usage(); } // Construct the RRset. Complain if the records in the input file // consist of more than one RRset. RRset rrset = null; for (Record r : records) { // skip RRSIGs if (r.getType() == Type.RRSIG || r.getType() == Type.SIG) { continue; } // Handle the first record. if (rrset == null) { rrset = new RRset(); rrset.addRR(r); continue; } // Ensure that the remaining records all belong to the same rrset. if (rrset.getName().equals(r.getName()) && rrset.getType() == r.getType() && rrset.getDClass() == r.getDClass()) { rrset.addRR(r); } else { System.err.println("Records do not all belong to the same RRset."); state.usage(); } } if (rrset.size() == 0) { System.err.println("No records found in inputfile."); state.usage(); } // Load the key pairs. if (state.keyFiles.length == 0) { System.err.println("error: at least one keyfile must be specified"); state.usage(); } List<DnsKeyPair> keypairs = getKeys(state.keyFiles, 0, state.keyDirectory); // Make sure that all the keypairs have the same name. // This will be used as the zone name, too. Name keysetName = null; for (DnsKeyPair pair : keypairs) { if (keysetName == null) { keysetName = pair.getDNSKEYName(); continue; } if (!pair.getDNSKEYName().equals(keysetName)) { System.err.println("Keys do not all have the same name."); state.usage(); } } // default the output file, if not set. if (state.outputfile == null && !state.inputfile.equals("-")) { state.outputfile = state.inputfile + ".signed"; } JCEDnsSecSigner signer = new JCEDnsSecSigner(); List<RRSIGRecord> sigs = signer.signRRset(rrset, keypairs, state.start, state.expire); for (RRSIGRecord s : sigs) { rrset.addRR(s); } // write out the signed RRset List<Record> signed_records = new ArrayList<Record>(); for (Iterator<Record> i = rrset.rrs(); i.hasNext(); ) { signed_records.add(i.next()); } for (Iterator<Record> i = rrset.sigs(); i.hasNext(); ) { signed_records.add(i.next()); } // write out the signed zone ZoneUtils.writeZoneFile(signed_records, state.outputfile); if (state.verifySigs) { log.fine("verifying generated signatures"); boolean res = verifySigs(keysetName, signed_records, keypairs); if (res) { System.out.println("Generated signatures verified"); // log.info("Generated signatures verified"); } else { System.out.println("Generated signatures did not verify."); // log.warn("Generated signatures did not verify."); } } }
/** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Message get(Message request) throws DNSException { LOGGER.trace("get(Message) Entered"); /* for testing time out cases try { Thread.sleep(1000000); } catch (Exception e) { } */ if (request == null) throw new DNSException(DNSError.newError(Rcode.FORMERR)); Header header = request.getHeader(); if (header.getFlag(Flags.QR) || header.getRcode() != Rcode.NOERROR) throw new DNSException(DNSError.newError(Rcode.FORMERR)); if (header.getOpcode() != Opcode.QUERY) throw new DNSException(DNSError.newError(Rcode.NOTIMP)); Record question = request.getQuestion(); if (question == null || question.getDClass() != DClass.IN) { throw new DNSException(DNSError.newError(Rcode.NOTIMP)); } Record queryRecord = request.getQuestion(); Name name = queryRecord.getName(); int type = queryRecord.getType(); if (LOGGER.isDebugEnabled()) { StringBuilder builder = new StringBuilder("Recieved Query Request:"); builder.append("\r\n\tName: " + name.toString()); builder.append("\r\n\tType: " + type); builder.append("\r\n\tDClass: " + queryRecord.getDClass()); LOGGER.debug(builder.toString()); } Collection<Record> lookupRecords = null; switch (question.getType()) { case Type.A: case Type.MX: case Type.SOA: case Type.SRV: case Type.NS: case Type.CNAME: { try { final RRset set = processGenericRecordRequest(name.toString(), type); if (set != null) { lookupRecords = new ArrayList<Record>(); Iterator<Record> iter = set.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } } catch (Exception e) { throw new DNSException( DNSError.newError(Rcode.SERVFAIL), "DNS service proxy call failed: " + e.getMessage(), e); } break; } case Type.CERT: { final RRset set = processCERTRecordRequest(name.toString()); if (set != null) { lookupRecords = new ArrayList<Record>(); Iterator<Record> iter = set.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } break; } case Type.ANY: { Collection<Record> genRecs = processGenericANYRecordRequest(name.toString()); RRset certRecs = processCERTRecordRequest(name.toString()); if (genRecs != null || certRecs != null) { lookupRecords = new ArrayList<Record>(); if (genRecs != null) lookupRecords.addAll(genRecs); if (certRecs != null) { Iterator<Record> iter = certRecs.rrs(); while (iter.hasNext()) lookupRecords.add(iter.next()); } } break; } default: { LOGGER.debug("Query Type " + type + " not implemented"); throw new DNSException( DNSError.newError(Rcode.NOTIMP), "Query Type " + type + " not implemented"); } } if (lookupRecords == null || lookupRecords.size() == 0) { LOGGER.debug("No records found."); return null; } final Message response = new Message(request.getHeader().getID()); response.getHeader().setFlag(Flags.QR); if (request.getHeader().getFlag(Flags.RD)) response.getHeader().setFlag(Flags.RD); response.addRecord(queryRecord, Section.QUESTION); final Iterator<Record> iter = lookupRecords.iterator(); while (iter.hasNext()) response.addRecord(iter.next(), Section.ANSWER); // we are authoritative only response.getHeader().setFlag(Flags.AA); // look for an SOA record final Record soaRecord = checkForSoaRecord(name.toString()); if (soaRecord != null) response.addRecord(soaRecord, Section.AUTHORITY); LOGGER.trace("get(Message) Exit"); return response; }
@Override public DnsResponse lookupRecords(final Record query) { final Name name = query.getName(); final int type = query.getType(); final Cache cache = new Cache(); Lookup aLookup = new Lookup(name, type); aLookup.setCache(cache); Record[] found = aLookup.run(); List<Record> queriedrrs = Arrays.asList(found != null ? found : new Record[] {}); List<Name> cnames = (List<Name>) (aLookup.getAliases().length > 0 ? Arrays.asList(aLookup.getAliases()) : Lists.newArrayList()); List<Record> answer = Lists.newArrayList(); List<Record> authority = Lists.newArrayList(); List<Record> additional = Lists.newArrayList(); for (Name cnameRec : cnames) { SetResponse sr = cache.lookupRecords(cnameRec, Type.CNAME, Credibility.ANY); if (sr != null && sr.isSuccessful() && sr.answers() != null) { for (RRset result : sr.answers()) { Iterator rrs = result.rrs(false); if (rrs != null) { for (Object record : ImmutableSet.copyOf(rrs)) { answer.add((Record) record); } } } } } for (Record queriedRec : queriedrrs) { SetResponse sr = cache.lookupRecords(queriedRec.getName(), queriedRec.getType(), Credibility.ANY); if (sr != null && sr.isSuccessful() && sr.answers() != null) { for (RRset result : sr.answers()) { Iterator rrs = result.rrs(false); if (rrs != null) { for (Object record : ImmutableSet.copyOf(rrs)) { answer.add((Record) record); } } } } } for (Record aRec : queriedrrs) { List<Record> nsRecs = lookupNSRecords(aRec.getName(), cache); for (Record nsRec : nsRecs) { authority.add(nsRec); Lookup nsLookup = new Lookup(((NSRecord) nsRec).getTarget(), Type.A); nsLookup.setCache(cache); Record[] nsAnswers = nsLookup.run(); if (nsAnswers != null) { additional.addAll(Arrays.asList(nsAnswers)); } } } return DnsResponse.forName(query.getName()) .recursive() .withAuthority(authority) .withAdditional(additional) .answer(answer); }