Пример #1
0
  RRsetIterator(Zone zone, DomainFactory factory) {

    this.zone = zone;
    this.factory = factory;
    this.domainIter = zone.iterator();
    if (domainIter == null) {
      throw new RuntimeException("Null Domain iterator");
    }

    String rootString = zone.getRootDomain();
    this.originNode = getDomainResource(rootString);

    if (originNode.getRRset(Type.SOA) == null) {
      throw new RuntimeException("Zone " + rootString + " missing SOA record");
    }
    if (originNode.getRRset(Type.NS) == null) {
      throw new RuntimeException("Zone " + rootString + " missing NS rrset");
    }

    List<RRset> sets = originNode.getAllRRsets();
    this.current = new RRset[sets.size()];
    for (int j = 2, k = 0; k < sets.size(); k++) {
      RRset rrset = sets.get(k);
      int type = rrset.getType();

      if (type == Type.SOA) {
        current[0] = rrset;
      } else if (type == Type.NS) {
        current[1] = rrset;
      } else {
        current[j++] = rrset;
      }
    }
  }
Пример #2
0
  /**
   * Verify the generated signatures.
   *
   * @param zonename the origin name of the zone.
   * @param records a list of {@link org.xbill.DNS.Record}s.
   * @param keypairs a list of keypairs used the sign the zone.
   * @return true if all of the signatures validated.
   */
  private static boolean verifySigs(
      Name zonename, List<Record> records, List<DnsKeyPair> keypairs) {
    boolean secure = true;

    DnsSecVerifier verifier = new DnsSecVerifier();

    for (DnsKeyPair pair : keypairs) {
      verifier.addTrustedKey(pair);
    }

    verifier.setVerifyAllSigs(true);

    List<RRset> rrsets = SignUtils.assembleIntoRRsets(records);

    for (RRset rrset : rrsets) {
      // skip unsigned rrsets.
      if (!rrset.sigs().hasNext()) continue;

      int result = verifier.verify(rrset, null);

      if (result != DNSSEC.Secure) {
        log.fine("Signatures did not verify for RRset: (" + result + "): " + rrset);
        secure = false;
      }
    }

    return secure;
  }
Пример #3
0
 private static RRset createRRset(Record... records) {
   RRset rrset = new RRset();
   for (Record r : records) {
     rrset.addRR(r);
   }
   return rrset;
 }
Пример #4
0
  /**
   * Processes all DNS requests except CERT records.
   *
   * @param name The record name.
   * @param type The record type.
   * @return Returns a set of record responses to the request.
   * @throws DNSException
   */
  protected RRset processGenericRecordRequest(String name, int type) throws DNSException {
    DnsRecord records[];

    try {
      records = proxy.getDNSByNameAndType(name, type);
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "DNS service proxy call for DNS records failed: " + e.getMessage(),
          e);
    }

    if (records == null || records.length == 0) return null;

    RRset retVal = new RRset();
    try {
      for (DnsRecord record : records) {
        Record rec =
            Record.newRecord(
                Name.fromString(record.getName()),
                record.getType(),
                record.getDclass(),
                record.getTtl(),
                record.getData());

        retVal.addRR(rec);
      }
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "Failure while parsing generic record data: " + e.getMessage(),
          e);
    }

    return retVal;
  }
Пример #5
0
  @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.");
      }
    }
  }
Пример #6
0
  /**
   * Processes all DNS CERT requests.
   *
   * @param name The record name. In many cases this a email address.
   * @return Returns a set of record responses to the request.
   * @throws DNSException
   */
  @SuppressWarnings("unused")
  protected RRset processCERTRecordRequest(String name) throws DNSException {
    if (name.endsWith(".")) name = name.substring(0, name.length() - 1);

    Certificate[] certs;

    // use the certificate configuration service
    try {
      certs = proxy.getCertificatesForOwner(name, null);
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "DNS service proxy call for certificates failed: " + e.getMessage(),
          e);
    }

    if (certs == null || certs.length == 0) {
      // unless the call above was for an org level cert, it will probably always fail because the
      // "name" parameter has had all instances of "@" replaced with ".".  The certificate service
      // stores owners using "@".
      // This is horrible, but try hitting the cert service replacing each "." with "@" one by one.
      // Start at the beginning of the address because this is more than likely where the "@"
      // character
      // will be.
      int previousIndex = 0;
      int replaceIndex = 0;
      while ((replaceIndex = name.indexOf(".", previousIndex)) > -1) {
        char[] chars = name.toCharArray();
        chars[replaceIndex] = '@';
        try {
          certs = proxy.getCertificatesForOwner(String.copyValueOf(chars), null);
        } catch (Exception e) {
          throw new DNSException(
              DNSError.newError(Rcode.SERVFAIL),
              "DNS service proxy call for certificates failed: " + e.getMessage(),
              e);
        }
        if (certs != null && certs.length > 0) break;

        if (replaceIndex >= (name.length() - 1)) break;

        previousIndex = replaceIndex + 1;
      }
    }

    if (certs == null || certs.length == 0) return null;

    if (!name.endsWith(".")) name += ".";

    RRset retVal = new RRset();
    try {
      for (Certificate cert : certs) {
        int certRecordType = CERTRecord.PKIX;
        byte[] retData = null;

        X509Certificate xCert = null;
        try {
          // need to convert to cert container because this might be
          // a certificate with wrapped private key data
          final CertUtils.CertContainer cont = CertUtils.toCertContainer(cert.getData());
          xCert = cont.getCert();
          // check if this is a compliant certificate with the configured policy... if not, move on
          if (!isCertCompliantWithPolicy(xCert)) continue;

          retData = xCert.getEncoded();
        } catch (CertificateConversionException e) {
          // probably not a Certificate... might be a URL
        }

        if (xCert == null) {
          // see if it's a URL
          try {
            retData = cert.getData();
            URL url = new URL(new String(retData));
            certRecordType = CERTRecord.URI;
          } catch (Exception e) {
            throw new DNSException(
                DNSError.newError(Rcode.SERVFAIL),
                "Failure while parsing CERT record data: " + e.getMessage(),
                e);
          }
        }

        int keyTag = 0;
        int alg = 0;
        if (xCert != null && xCert.getPublicKey() instanceof RSAKey) {
          RSAKey key = (RSAKey) xCert.getPublicKey();
          byte[] modulus = key.getModulus().toByteArray();

          keyTag = (modulus[modulus.length - 2] << 8) & 0xFF00;

          keyTag |= modulus[modulus.length - 1] & 0xFF;
          alg = 5;
        }

        CERTRecord rec =
            new CERTRecord(
                Name.fromString(name),
                DClass.IN,
                86400L,
                certRecordType,
                keyTag,
                alg /*public key alg, RFC 4034*/,
                retData);

        retVal.addRR(rec);
      }
    } catch (Exception e) {
      throw new DNSException(
          DNSError.newError(Rcode.SERVFAIL),
          "Failure while parsing CERT record data: " + e.getMessage(),
          e);
    }

    // because of policy filtering, it's possible that we could have filtered out every cert
    // resulting in an empty RR set
    return (retVal.size() == 0) ? null : retVal;
  }
Пример #7
0
  /** {@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);
 }