private static List<Name> subdomainsForName(Name name) {
   final List<Name> names = Lists.newArrayList(name);
   final String sub = parentDomainForName(name);
   if (sub.equals("") || sub.equals(".")) {
     names.add(Name.fromConstantString("."));
   } else {
     names.addAll(subdomainsForName(Name.fromConstantString(sub)));
   }
   return names;
 }
예제 #2
0
  public static DnsRecord createNSRecord(String name, String target) throws Exception {

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

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

    NSRecord rec = new NSRecord(Name.fromString(name), DClass.IN, 86400L, Name.fromString(target));

    return toDnsRecord(DNSRecord.fromWire(rec.toWireCanonical()));
  }
예제 #3
0
 public static Zone getPtrZone(Name queryName) {
   try {
     String nameString = queryName.toString();
     Name name;
     int index = nameString.indexOf(".in-addr.arpa.");
     if (index > 0) {
       String ipString = nameString.substring(0, index);
       String[] parts = ipString.split("\\.");
       // fix this for v6
       if (parts.length == 4) {
         nameString = nameString.substring(parts[0].length() + 1);
         name = new Name(nameString);
       } else {
         return null;
       }
     } else {
       return null;
     }
     long serial = 1;
     long refresh = 86400;
     long retry = ttl;
     long expires = 2419200;
     // This is the negative cache TTL
     long minimum = 600;
     Record soarec =
         new SOARecord(
             name,
             DClass.IN,
             ttl,
             name,
             Name.fromString("root." + name.toString()),
             serial,
             refresh,
             retry,
             expires,
             minimum);
     long nsTTL = 604800;
     Record nsrec =
         new NSRecord(
             name,
             DClass.IN,
             nsTTL,
             Name.fromString(Internets.localHostInetAddress().getCanonicalHostName() + "."));
     return new TransientZone(name, new Record[] {soarec, nsrec});
   } catch (Exception e) {
     LOG.error(e, e);
     return null;
   }
 }
예제 #4
0
  private Message makeQuery(DNSRequest request, int id) throws TextParseException {
    Name name = Name.fromString(request.getHostname(), Name.root);

    int type;
    switch (request.getRecordType()) {
      case DNSRequest.A:
        type = Type.A;
        break;
      case DNSRequest.AAAA:
        type = Type.AAAA;
        break;
      case DNSRequest.MX:
        type = Type.MX;
        break;
      case DNSRequest.PTR:
        type = Type.PTR;
        break;
      case DNSRequest.SPF:
        type = Type.SPF;
        break;
      case DNSRequest.TXT:
        type = Type.TXT;
        break;
      default:
        throw new UnsupportedOperationException("Unknown query type: " + request.getRecordType());
    }

    Record question = Record.newRecord(name, type, DClass.ANY);
    Message query = Message.newQuery(question);
    query.getHeader().setID(id);
    return query;
  }
  @Test
  public void itLogsServerErrors() throws Exception {
    header.setRcode(Rcode.REFUSED);

    Name name = Name.fromString("John Wayne.");
    Record question = Record.newRecord(name, 65530, 43210);

    Message query = Message.newQuery(question);

    Message response = mock(Message.class);
    when(response.getHeader()).thenReturn(header);
    when(response.getSectionArray(Section.ANSWER)).thenReturn(null);
    when(response.getQuestion()).thenReturn(question);

    when(nameServer.query(
            any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class)))
        .thenThrow(new RuntimeException("Aw snap!"));

    FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, query.toWire());
    abstractProtocol.setNameServer(nameServer);
    abstractProtocol.run();

    verify(accessLogger)
        .info(
            "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=John\\032Wayne. type=TYPE65530 class=CLASS43210 rcode=SERVFAIL rtype=- rloc=\"-\" rdtl=- rerr=\"Server Error:RuntimeException:Aw snap!\" ttl=\"-\" ans=\"-\"");
  }
예제 #6
0
 public static Name getInternalName() throws TextParseException {
   String internalNameString = VmInstances.INSTANCE_SUBDOMAIN + ".internal.";
   internalNameString =
       internalNameString.startsWith(".")
           ? internalNameString.replaceFirst("\\.", "")
           : internalNameString;
   Name internalName = Name.fromString(internalNameString);
   return internalName;
 }
예제 #7
0
  /*
   * converts a String to a DNS name
   */
  private Name nameFromString(String str) {
    if (!str.endsWith(".")) str += ".";

    try {
      return Name.fromString(str);
    } catch (Exception e) {
      throw new IllegalArgumentException("Invalid DNS name");
    }
  }
예제 #8
0
 public static Zone getInstanceExternalZone() {
   try {
     Name name = getExternalName();
     Name host = Name.fromString("root." + name.toString());
     Name admin =
         Name.fromString(
             Internets.localHostInetAddress().getCanonicalHostName() + "." + name.toString());
     Name target = Name.fromString(Internets.localHostInetAddress().getCanonicalHostName() + ".");
     long serial = 1;
     long refresh = 86400;
     long retry = ttl;
     long expires = 2419200;
     // This is the negative cache TTL
     long minimum = 600;
     Record soarec =
         new SOARecord(
             name, DClass.IN, ttl, host, admin, serial, refresh, retry, expires, minimum);
     long nsTTL = 604800;
     Record nsrec = new NSRecord(name, DClass.IN, nsTTL, target);
     return new TransientZone(name, new Record[] {soarec, nsrec});
   } catch (Exception e) {
     LOG.error(e, e);
     return null;
   }
 }
예제 #9
0
 public static Name getExternalName() throws TextParseException {
   String externalNameString =
       VmInstances.INSTANCE_SUBDOMAIN
           + "."
           + SystemConfiguration.getSystemConfiguration().getDnsDomain()
           + ".";
   externalNameString =
       externalNameString.startsWith(".")
           ? externalNameString.replaceFirst("\\.", "")
           : externalNameString;
   Name externalName = Name.fromString(externalNameString);
   return externalName;
 }
예제 #10
0
  /*
   * 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;
  }
  @Test
  public void itLogsARecordQueries() throws Exception {
    header.setRcode(Rcode.NOERROR);

    Name name = Name.fromString("www.example.com.");
    Record question = Record.newRecord(name, Type.A, DClass.IN, 0L);
    Message query = Message.newQuery(question);

    query.getHeader().getRcode();

    byte[] queryBytes = query.toWire();

    whenNew(Message.class).withArguments(queryBytes).thenReturn(query);

    InetAddress resolvedAddress = Inet4Address.getByName("192.168.8.9");

    Record answer = new ARecord(name, DClass.IN, 3600L, resolvedAddress);
    Record[] answers = new Record[] {answer};

    Message response = mock(Message.class);
    when(response.getHeader()).thenReturn(header);
    when(response.getSectionArray(Section.ANSWER)).thenReturn(answers);
    when(response.getQuestion()).thenReturn(question);

    InetAddress client = Inet4Address.getByName("192.168.23.45");
    when(nameServer.query(
            any(Message.class), any(InetAddress.class), any(DNSAccessRecord.Builder.class)))
        .thenReturn(response);

    FakeAbstractProtocol abstractProtocol = new FakeAbstractProtocol(client, queryBytes);
    abstractProtocol.setNameServer(nameServer);

    abstractProtocol.run();

    verify(accessLogger)
        .info(
            "144140678.000 qtype=DNS chi=192.168.23.45 ttms=345.123 xn=65535 fqdn=www.example.com. type=A class=IN rcode=NOERROR rtype=- rloc=\"-\" rdtl=- rerr=\"-\" ttl=\"3600\" ans=\"192.168.8.9\"");
  }
예제 #12
0
  protected Collection<Record> processGenericANYRecordRequest(String name) throws DNSException {
    DnsRecord records[];

    try {
      records = proxy.getDNSByNameAndType(name, Type.ANY);
    } 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;

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

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

    return retVal;
  }
예제 #13
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;
  }
 private static String parentDomainForName(Name name) {
   return name.toString().replaceAll("\\A[^\\.]+\\.", "");
 }
예제 #15
0
  /* (non-Javadoc)
   * @see com.eucalyptus.dns.Zone#findRecords(org.xbill.DNS.Name, int)
   */
  @Override
  public SetResponse findRecords(Name name, int type) {
    if (type == Type.AAAA) return (SetResponse.ofType(SetResponse.SUCCESSFUL));

    if (StackConfiguration.USE_INSTANCE_DNS
        && name.toString().matches("euca-.+{3}-.+{3}-.+{3}-.+{3}\\..*")) {
      try {
        String[] tryIp =
            name.toString()
                .replaceAll("euca-", "")
                .replaceAll(VmInstances.INSTANCE_SUBDOMAIN + ".*", "")
                .split("-");
        if (tryIp.length < 4) return super.findRecords(name, type);
        String ipCandidate =
            new StringBuffer()
                .append(tryIp[0])
                .append(".")
                .append(tryIp[1])
                .append(".")
                .append(tryIp[2])
                .append(".")
                .append(tryIp[3])
                .toString();
        try {
          VmInstances.lookupByPublicIp(ipCandidate);
        } catch (Exception e) {
          try {
            VmInstances.lookupByPrivateIp(ipCandidate);
          } catch (Exception e1) {
            return super.findRecords(name, type);
          }
        }
        InetAddress ip = InetAddress.getByName(ipCandidate);
        SetResponse resp = new SetResponse(SetResponse.SUCCESSFUL);
        resp.addRRset(new RRset(new ARecord(name, 1, ttl, ip)));
        return resp;
      } catch (Exception e) {
        return super.findRecords(name, type);
      }
    } else if (StackConfiguration.USE_INSTANCE_DNS && name.toString().endsWith(".in-addr.arpa.")) {
      int index = name.toString().indexOf(".in-addr.arpa.");
      Name target;
      if (index > 0) {
        String ipString = name.toString().substring(0, index);
        String[] parts = ipString.split("\\.");
        String ipCandidate;
        if (parts.length == 4) {
          ipCandidate =
              new StringBuffer()
                  .append(parts[3])
                  .append(".")
                  .append(parts[2])
                  .append(".")
                  .append(parts[1])
                  .append(".")
                  .append(parts[0])
                  .toString();
        } else {
          return super.findRecords(name, type);
        }
        try {
          VmInstance instance = VmInstances.lookupByPublicIp(ipCandidate);
          target = new Name(instance.getPublicDnsName() + ".");
        } catch (Exception e) {
          try {
            VmInstance instance = VmInstances.lookupByPrivateIp(ipCandidate);
            target = new Name(instance.getPrivateDnsName() + ".");
          } catch (Exception e1) {
            return super.findRecords(name, type);
          }
        }
        SetResponse resp = new SetResponse(SetResponse.SUCCESSFUL);
        resp.addRRset(new RRset(new PTRRecord(name, DClass.IN, ttl, target)));
        return resp;
      } else {
        return super.findRecords(name, type);
      }
    } else {
      return super.findRecords(name, type);
    }
  }
예제 #16
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;
  }
예제 #17
0
  public static void main(String[] args) throws Exception {
    ZoneTransferIn xfrin;
    TSIG key = null;
    int ixfr_serial = -1;
    String server = null;
    int port = SimpleResolver.DEFAULT_PORT;
    boolean fallback = false;
    Name zname;

    int arg = 0;
    while (arg < args.length) {
      if (args[arg].equals("-i")) {
        ixfr_serial = Integer.parseInt(args[++arg]);
        if (ixfr_serial < 0) usage("invalid serial number");
      } else if (args[arg].equals("-k")) {
        String s = args[++arg];
        int index = s.indexOf('/');
        if (index < 0) usage("invalid key");
        key = new TSIG(s.substring(0, index), s.substring(index + 1));
      } else if (args[arg].equals("-s")) {
        server = args[++arg];
      } else if (args[arg].equals("-p")) {
        port = Integer.parseInt(args[++arg]);
        if (port < 0 || port > 0xFFFF) usage("invalid port");
      } else if (args[arg].equals("-f")) {
        fallback = true;
      } else if (args[arg].startsWith("-")) {
        usage("invalid option");
      } else {
        break;
      }
      arg++;
    }
    if (arg >= args.length) usage("no zone name specified");
    zname = Name.fromString(args[arg]);

    if (server == null) {
      Lookup l = new Lookup(zname, Type.NS);
      Record[] ns = l.run();
      if (ns == null) {
        System.out.println("failed to look up NS record: " + l.getErrorString());
        System.exit(1);
      }
      server = ns[0].rdataToString();
      System.out.println("sending to server '" + server + "'");
    }

    if (ixfr_serial >= 0)
      xfrin = ZoneTransferIn.newIXFR(zname, ixfr_serial, fallback, server, port, key);
    else xfrin = ZoneTransferIn.newAXFR(zname, server, port, key);

    List response = xfrin.run();
    if (xfrin.isAXFR()) {
      if (ixfr_serial >= 0) System.out.println("AXFR-like IXFR response");
      else System.out.println("AXFR response");
      Iterator it = response.iterator();
      while (it.hasNext()) System.out.println(it.next());
    } else if (xfrin.isIXFR()) {
      System.out.println("IXFR response");
      Iterator it = response.iterator();
      while (it.hasNext()) {
        ZoneTransferIn.Delta delta;
        delta = (ZoneTransferIn.Delta) it.next();
        System.out.println("delta from " + delta.start + " to " + delta.end);
        System.out.println("deletes");
        Iterator it2 = delta.deletes.iterator();
        while (it2.hasNext()) System.out.println(it2.next());
        System.out.println("adds");
        it2 = delta.adds.iterator();
        while (it2.hasNext()) System.out.println(it2.next());
      }
    } else if (xfrin.isCurrent()) {
      System.out.println("up to date");
    }
  }