DNSSEC Application Development

From DNSSEC-Tools
Jump to: navigation, search

This is a short introduction to dnssec-tools for those that want to write applications that support DNSSEC.


Contents

libval

The base DNSSEC-Tools tool to use for development is the validation library, libval. In order to support DNS calls, libval provides a set of API's similar to the standard set of resolver API's. Although the function headers should be checked to make sure, the following are generally true for similar function calls in the standard library and in libval:

  • common API function calls have similar names except that libval calls have a val_ prefix.
  • usually two additional parameters are added:
    • val_status_t parameter used to store success/failure of validation
    • val_context_t parameter used to store context for validation (allowed to be 'null' which uses a default context)

Example

Below is some pseudo code as an example of a simple conversion from using the standard 'res_query' call to using libval's 'val_res_query'.

Standard call:

        
  #include <resolv.h>

  length = res_search((char *) dname, 
                      (int) class, (int) type, 
                      (unsigned char *) reply->buf, (int) sizeof(reply->buf));

  if (length < 0) {
  /* process errors */
  } 

Using libval's call: [libval included during linking]

  #include <validator.h>

  val_status_t val_status;
  len = val_res_query((val_context_t *) NULL,
                      (char *) dname, 
                      (int) class, (int) type, 
                      (unsigned char *) reply->buf, (int) sizeof(reply->buf),
                       &val_status);

  if ((length < 0) || (!val_istrusted(val_status))) {
  /* process errors */
  }

If desired, more information about the validation status of a query can be pulled from libval. Using additional libval API's and data structures a program can delve into the validation chain to find exactly where and how a query failed validation. But often, the only information needed is whether or not the query can be trusted.

Trust

Libval's trust is configurable. The file dnsval.conf, usually in /usr/local/etc/dnssec-tools/, holds the configuration information for validation. That is, it contains the list of trust anchors to use, the list of domains that require DNSSEC validation, and the list of domains that do not require DNSSEC validation. Domains in dnsval.conf that require validation are only considered trusted if the queries for those domain can be successfully validated. Domains in dnsval.conf that do not require validation are considered implicitly trusted. That is, standard DNS responses from those domains are trusted.

libval_shim

The libval_shim library is designed to be dynamically loaded by applications using the 'LD_PRELOAD' mechanism supported on linux and various other unix-like platforms. If used in this manner the functions exported by libval_shim are used ahead of the functions normally exported by system resolver libraries. As long as the application uses one of the legacy resolver API calls [gethostbyname(), gethostbyaddr(), getaddrinfo(), getnameinfo(), res_query(), res_search(), getipnodebyname() and getipnodebyaddr()] libval_shim automatically interleaves DNSSEC processing for the given function call and only returns a result if DNSSEC processing succeeds.

Users need to ensure that the libval_shim library is loaded prior to the target application's execution. A typical way of achieving this is to set the LD_PRELOAD variable within the environment of the the target application prior to execution.

Since libval_shim internally makes use of libval, the mechanism for configuring trust and policy settings for libval_shim is almost identical to that of libval. The only difference is that since the applications that make use of libval_shim are expected to be DNSSEC-unaware, there is no way for the application itself to specify a validation policy to use. libval provides two ways for libval_shim to select a specific validation policy for a given application (see the man page for dnsval.conf for additional details). If neither of these options are enabled, libval_shim uses the default validator context for its validation policy.

  • env-policy

If the env-policy global option is not disabled, libval looks at the VAL_CONTEXT_LABEL environmental variable in order to determine the validator policy label.

  • app-policy

If the app-policy global option is not disabled, libval automatically looks for a policy in dnsval.conf with a label value constructed from the name of the application. For example, dnsval.conf may be defined with validator policies for the foo label. The foo application, when run, will use the policy defined against the foo label during its validation operation.

Maketestzone

The maketestzone script generates a test dnssec zone that can be used to test DNSSEC validator behavior. In normal scenarios, the test zone at test.dnssec-tools.org, which was constructed using this script, may be used directly for testing validator behavior. In other cases where a specific set of tests needs to be run, a validator operator may choose to create a new test zone using the maketestzone script. The man page for this script outlines the different command line options and discusses how to extend the maketestzone tool with new output modifications.

Perl Modules

Net::DNS::Zonefile::Fast

The Net::DNS::ZoneFile::Fast module provides an ability to parse zone files that BIND8 and BIND9 use, fast. Currently it provides a single function, parse(), which returns a reference to an array of traditional Net::DNS::RR objects, so that no new API has to be learned in order to manipulate zone records. A typical invocation is as follows:

       use Net::DNS::ZoneFile::Fast;
       my $rr = Net::DNS::ZoneFile::Fast::parse($zone_text);

Net::DNS::SEC::Validator

This Perl module is designed to implement and export functionality provided by the validating DNS resolver library, libval(3). The functions are provided through an easy-to-use object oriented interface. The interface is designed for the higher level user, hiding some of the complexity of validating resolvers. Nevertheless, application interface behavior can be customized through configuration files provided by libval(3) and extensive error codes returned.

A description of the API is provided in the Net:DNS::SEC::Validator man page. An example usage is provided below:

        use Net::DNS::SEC::Validator;
        use Net::DNS::Packet;
        use Net::hostent;
        use Net::addrinfo;
        use Socket qw(:all);
        # construct object
        my $validator = new Net::DNS::SEC::Validator(policy => ":");
        # change validation policy
        $validator->policy("validate_tools:");
        # fetch array of Net::addrinfo objects
        my (@r) = $validator->getaddrinfo("good-A.test.dnssec-tools.org");
        foreach $a (@r) {
           print $a->stringify, " is trusted\n"
              if $validator->istrusted($a->val_status));
        }
        # query an MX record
        my $r = $validator->res_query("marzot.net", "IN", "MX");
        my ($pkt, $err) = new Net::DNS::Packet(\$r);
        print ($validator->istrusted ?
              "result is trusted\n" :
              "result is NOT trusted\n");
        my $h = $validator->gethostbyname("good-A.test.dnssec-tools.org");
        if ( @{$h->addr_list}) {
        my $i;
          for $addr ( @{$h->addr_list} ) {
              printf "\taddr #%d is [%s]\n", $i++, inet_ntoa($addr);
          }
       }


Net::Addrinfo

This Perl module is designed to implement and export functionality related to the POSIX getaddrinfo(3) system call. The Net::addrinfo data object is provided with field name accsessor functions, similarly named to the the C data structure definition in netdb.h. The getaddrinfo(3), gai_strerror(3) calls, and related constants are exported.

Additional details are provided in the Net::addrinfo man page. An example usage is provided below:

       use Net::addrinfo;
       use Socket qw(:all);
       my $hint = new Net::addrinfo(flags => AI_CANONNAME,
                                    family => AF_INET,
                                    socktype => SOCK_DGRAM);
       my (@ainfo) = getaddrinfo("www.marzot.net", "http", $hint);
       foreach $ainfo (@ainfo) {
          if (ref $ainfo eq 'Net::addrinfo') {
             print $ainfo->stringify(), "\n";
             print "addr = ", inet_ntoa($ainfo->addr), "\n";
             ...
             connect(SH, $ainfo->addr);
           } else {
              print "Error($ainfo):", gai_strerror($ainfo), "\n";
           }
       }


Software Summary

Application/Script Writers
libval
libsres
Manual
Manual
C libraries that implement DNSSEC aware DNS resolution APIs.
libval_shim Manual Preload shim library - maps DNS calls in legacy apps to equivalent DNSSEC functions.
Maketestzone Manual Generate a test dnssec zone that can be used to test DNSSEC validators.
Perl Modules:
Net::DNS::ZoneFile::Fast Manual Quickly read and parse a zone file into Net::DNS object records.
Net::DNS::SEC::Validator Manual Perl bindings to the libval and libsres libraries.
Net::addrinfo Manual interface to POSIX getaddrinfo and related constants, structures and functions
Personal tools