
=pod

=head1 NAME

I<val_create_context()>
I<val_free_context()> - manage validator context

I<val_context_setqflags()> - manage validator context flags

I<val_resolve_and_check()>, I<val_free_result_chain()> - query and validate
answers from a DNS name server

I<val_istrusted()> - check if status value corresponds to that of a
trustworthy answer

I<val_isvalidated()> - check if status value represents an
answer that cryptographically chains down from a configured
trust anchor

I<val_does_not_exist()> - check if status value represents
one of the non-existence types

I<p_val_status()>, I<p_ac_status()>, I<p_val_error()> - display validation status,
authentication chain status and error information

I<val_log_add_optarg> - control log message verbosity and output location

=head1 SYNOPSIS

  #include <validator.h>

  int val_create_context(const char *label, val_context_t **newcontext);

  int val_create_context_ex(char *label, 
                            val_context_opt_t *opt, 
                            val_context_t ** newcontext);

  int val_context_setqflags(val_context_t *context, 
                            unsigned char action, 
                            unsigned int flags);

  int val_context_store_ns_for_zone(val_context_t *context, 
                                    char * zone, 
                                    char *resp_server,
                                    int recursive)

  int val_resolve_and_check(val_context_t *context,
                         const char *domain_name,
                         int class,
                         int type,
                         unsigned int  flags,
                         struct val_result_chain  **results);

  char *p_val_status(val_status_t valerrno);

  char *p_ac_status(val_astatus_t auth_chain_status);

  char *p_val_error(int err);

  int val_istrusted(val_status_t val_status);

  int val_isvalidated(val_status_t val_status);

  int val_does_not_exist(val_status_t status);

  val_log_t *val_log_add_optarg(const char *args, int use_stderr);

  void val_free_result_chain(struct val_result_chain *results);

  void val_free_context(val_context_t *context);


=head1 DESCRIPTION

The I<val_resolve_and_check()> function queries a set of name servers for
the I<<domain_name, type, class>> tuple and verifies and validates the
response.  Verification involves checking the RRSIGs, and validation is
verification of an authentication chain from a configured trust anchor.

The I<flags> parameter can be used to control the results of validation.
The following values, which may be ORed together, are currently defined 
for this field: 

=over 4

=item B<VAL_QUERY_DONT_VALIDATE> 

This flag causes the validator to disable validation for this query.  

=item B<VAL_QUERY_IGNORE_SKEW> 

This flag causes the validator to disable checking signature inception and
expiration times on RRSIGs.  

=item B<VAL_QUERY_AC_DETAIL> 

This flag causes the validator to copy the authentication chain details into
the I<val_rc_answer> member within the returned I<val_result_chain> structure.

=item B<VAL_QUERY_ASYNC> 

This flag enables asynchronous query resolution for that lookup. 

=item B<VAL_QUERY_NO_DLV> 

This flag causes the validator to disable DLV processing for this query.  
This is only available if the B<libval(3)> library has
been compiled with DLV support.

=item B<VAL_QUERY_NO_EDNS0_FALLBACK>

In querying various name servers, B<libsres(3)> will also attempt multiple
EDNS0 sizes, ending with a query that has EDNS0 disabled (i.e. no CD bit set).
This flag causes B<libval> to disable EDNS0 fallback for the query.

=item B<VAL_QUERY_ITERATE>

This flag forces B<libval> to iteratively lookup the query by querying
various name servers in the delegation hierarchy, instead of
requesting this information from
any caching name server that may be configured in B<dnsval.conf>.

=item B<VAL_QUERY_SKIP_RESOLVER>

This flag forces B<libval> to only look at its cache while trying to resolve a
name.

=item B<VAL_QUERY_SKIP_CACHE>

There are two levels of caching that happen within libval: at the
assertion level and at the answer level. This flag forces B<libval> to
ignore data in both caches while trying to resolve a name.

=item B<VAL_QUERY_SKIP_ANS_CACHE>

There are two levels of caching that happen within libval: at the
assertion level and at the answer level. This flag forces B<libval> to
ignore data in the answer cache while trying to resolve a name.
If an assertion already exists for the given name,class and type that
assertion is re-used till it expires. Once it expires the name is looked
up via a query even if an newer record (fetched by another assertion in
the same or different context) is available in its answer cache.

=back

The first parameter to I<val_resolve_and_check()> is the validator context.
Applications can create a new validator context using the
I<val_create_context()> function.  This function parses the resolver and
validator configuration files and creates the I<newcontext> handle for this
parsed information.  Information stored as part of the validator context
includes the validation policy the and resolver policy.

Validator and resolver policies are read from the B</etc/dnsval.conf> and
B</etc/resolv.conf> files by default.  B</etc/root.hints> provides
bootstrapping information for the validator when it functions as a full
resolver (see B<dnsval.conf(3)>). These defaults may be different if 
any other value was specified at library configure time.  If the default 
resolver configuration file is not found at the specified location, B<libval>
will also try to fall back to B</etc/resolv.conf> as a last resort. 

Applications may also create a validator context with a custom policy 
using the I<val_create_context_ex()> function. 

The I<opt> argument in I<val_create_context_ex()> points to the
following structure:

    typedef struct val_context_opt {
        unsigned int vc_qflags;
        unsigned int vc_polflags;
        char *vc_valpol;
        char *vc_nslist;
        char *vc_val_conf;
        char *vc_res_conf;
        char *vc_root_conf;
        val_global_opt_t *gopt, 
    } val_context_opt_t;


I<vc_qflags> specify the default query flags for queries associated with
the context. This field is identical to the I<flags> argument in the
I<val_resolve_and_check()> function.

The I<vc_val_conf>, I<vc_res_conf>, and I<vc_root_conf> fields can be used to
specify alternative configuration files in place of the default files used for
the validator, resolver, and root hints configuration information.

The I<vc_valpol> field can be used to supply a custom validator
configuration "snippet" to the validator. The validator parses this
information and applies it to the default validator configuration either
as an extension or as an override, as specified by the I<vc_polflags>
field. The I<vc_nslist> field, similarly, can be used to supply a custom
list of recursive name servers to send queries to, in addition (or in
place of) the list of name servers specified in the B<resolv.conf> file.
The list of name servers in I<vc_res_conf> must be specified as a
white-space delimited list of IP or IPv6 addresses.

A custom mapping between a zone and a name server may be created
using the B<val_context_store_ns_for_zone()> function.

I<vc_polflags> can be configured with the following values:

=over 4

=item B<CTX_DYN_POL_VAL_OVR> 

When this flag is set only the validator configuration specified in the
I<vc_valpol> field is used for the validator configuration.  Options
specified in the B<dnsval.conf> file are ignored. 

=item B<CTX_DYN_POL_RES_OVR> 

When this flag is set only the name servers specified in the
I<vc_nslist> field is used for the resolver configuration.  Options
specified in the B<resolv.conf> file are ignored. 

=item B<CTX_DYN_POL_GLO_OVR> 

When this flag is set only the global options set in I<gopt> field are
used.  Global options specified in the B<dnsval.conf> file are ignored.

=item B<CTX_DYN_POL_RES_NRD> 

When this flag is set outgoing queries have the Recursion Desired (RD)
bit set to 0.  This is useful if queries need to be sent to an
authoritative-only name server.

=back

The I<gopt> field points to the following structure:

    typedef struct val_global_opt {
        int local_is_trusted;
        long edns0_size;
        int env_policy;
        int app_policy;
        char *log_target;
        int closest_ta_only;
        int rec_fallback;
        long max_refresh;
        int proto;
    } val_global_opt_t;

Setting a value of 1 for I<local_is_trusted> is equivalent to specifying the
I<trust-oob-answers> option in the B<dnsval.conf> file to B<yes>. 
Similarly, setting the I<closest_ta_only> and I<rec_fallback>
members to 1 is equivalent to setting the I<closest-ta-only>
and I<rec-fallback> options to B<yes> in the B<dnsval.conf> file. 
A value of 0 is equivalent to the B<no> setting for these option.

Setting the I<edns0_size> member to a particular value has the same effect 
setting the I<edns0-size> option in the B<dnsval.conf> file.

Setting the I<max_refresh> member to a particular value has the same effect 
setting the I<max-refresh> option in the B<dnsval.conf> file.

Setting the I<proto> member to a particular value has the same effect 
setting the I<proto> option in the B<dnsval.conf> file.

I<env_policy> and I<app_policy> can be set to one of B<VAL_POL_GOPT_DISABLE>,
B<VAL_POL_GOPT_ENABLE>, or B<VAL_POL_GOPT_OVERRIDE>.  These values correspond
directly to the I<disable>, I<enable> and I<override> options for the
I<env-policy> and I<app-policy> settings in the B<dnsval.conf> file.

Values of -1 for the above fields are treated as "ignore" conditions
in that the validator will not include dynamically supplied global
options with a value of -1 when creating its context.  This allows an
application to overriding a subset of global options while using the
global options supplied in the B<dnsval.conf> file by default.

The log_target field enables the application to supply log targets 
I<in addition> to the ones configured in the configuration file.

See B<dnsval.conf(3)> for more details on specifying validator policy.

Default query flags can be set and unset for a given context using 
I<val_context_setqflags()>.  This allows an application to alter the 
DNSSEC validator processing, while still having most of the more 
granular default configuration specified in its configuration file.  
The I<action> parameter can be set to one of the following.

=over 4

=item B<VAL_CTX_FLAG_SET> 

This option causes the validator to set the given flag as one of the default 
query flags. 

=item B<VAL_CTX_FLAG_RESET> 

This option causes the validator to reset the given flag if it was set as one 
of the default query flags for the context.

=back

Answers returned by I<val_resolve_and_check()> are made available in the
I<*results> linked list.  Each answer corresponds to a distinct RRset;
multiple RRs within the RRset are part of the same answer.  Multiple answers
are possible when I<type> is I<ns_t_any> or I<ns_t_rrsig>.

Individual elements in I<*results> point to I<val_authentication_chain> linked
lists.  The authentication chain elements in I<val_authentication_chain>
contain the actual RRsets returned by the name server in response to the query.

Validation result values returned in I<val_result_chain> can be can be
converted into ASCII format using the I<p_val_status()>.  Authentication chain
status values returned in each element of the I<val_authentication_chain>
linked list can be can be converted into ASCII format using the
I<p_ac_status()> functions.

While some applications such as DNSSEC troubleshooting utilities and packet
inspection tools may look at individual authentication chain elements to
identify the actual reasons for validation error, most applications will only
be interested in a single error code for determining the authenticity of data.

I<val_isvalidated()> identifies if a given validation result status value
corresponds to an answer that was cryptographically verified and validated
using a locally configured trust anchor.

I<val_istrusted()> identifies if a given validator status value is trusted.
An answer may be locally trusted without being validated.

I<val_does_not_exist()> identifies if a given validator status value
corresponds to one of the non-existence types.

The I<libval> library internally allocates memory for I<*results> and this
must be freed by the invoking application using the I<free_result_chain()>
interface.

=head1 DATA STRUCTURES

=over 4

=item I<struct val_result_chain>

  struct val_result_chain
  {
      val_status_t                     val_rc_status;
      char                            *val_rc_alias;
      struct val_rrset_rec            *val_rc_rrset;
      struct val_authentication_chain *val_rc_answer;
      int                              val_rc_proof_count;
      struct val_authentication_chain *val_rc_proofs[MAX_PROOFS];
      struct val_result_chain         *val_rc_next;
  };

=over 4

=item I<val_rc_answer>

Authentication chain for a given RRset.

=item I<val_rc_next>

Pointer to the next RRset in the set of answers returned for a query.

=item I<val_rc_proofs>

Pointer to authentication chains for any proof of non-existence that were
returned for the query.

=item I<val_rc_proof_count>

Number of proof elements stored in I<val_rc_proofs>.  The number cannot exceed
B<MAX_PROOFS>.

=item I<val_rc_alias>

For an val_result_chain element that points to a name alias, this field
contains the target value.

=item I<val_rc_rrset>

For a I<val_result_chain> element that contains a valid (not NULL)
I<val_rc_answer> field, the I<val_rc_rrset> field points to the top-most
I<val_rrset_rec> element in the I<val_rc_answer> authentication chain.

=item I<val_rc_status>

Validation status for a given RRset.  This can be one of the following:

=over 4

=item B<VAL_SUCCESS>

Answer received and validated successfully.

=item B<VAL_NONEXISTENT_NAME>

No name was present and a valid proof of non-existence confirming the missing
name (NSEC or NSEC3 span) was returned.  The components of the proof were also
individually validated.

=item B<VAL_NONEXISTENT_TYPE>

No type exists for the name and a valid proof of non-existence confirming the
missing name was returned.  The components of the proof were also individually
validated.

=item B<VAL_NONEXISTENT_NAME_NOCHAIN>

No name was present and a valid proof of non-existence confirming the missing
name was returned.  The components of the proof were also identified to be
trustworthy, but they were not individually validated.

=item B<VAL_NONEXISTENT_TYPE_NOCHAIN>

No type exists for the name and a valid proof of non-existence confirming the
missing name (NSEC or NSEC3 span) was returned.  The components of the proof
were also identified to be trustworthy, but they were not individually
validated.

=item B<VAL_PINSECURE>

The record or some ancestor of the record in the authentication chain towards
the trust anchor was known to be provably insecure.

=item B<VAL_PINSECURE_UNTRUSTED>

The record or some ancestor of the record in the authentication chain towards
the trust anchor was known to be provably insecure. But the provably insecure
condition was configured as untrustworthy.

=item B<VAL_BARE_RRSIG>

No DNSSEC validation possible, query was for an RRSIG.

=item B<VAL_IGNORE_VALIDATION>

Local policy was configured to ignore validation for the zone from which this
data was received.

=item B<VAL_UNTRUSTED_ZONE>

Local policy was configured to reject any data received from the given zone.

=item B<VAL_OOB_ANSWER>

Answer was obtained using some Out Of Band method, such as a local
configuration file.

=item B<VAL_BOGUS>

Response could not be validated due to signature verification failures or the
inability to verify proofs in the authentication chain.

=item B<VAL_DNS_ERROR>

Some error was encountered during DNS processing.

=item B<VAL_INDETERMINATE>

Response could not be validated due to missing DNSSEC meta-data. 

=item B<VAL_NOTRUST>

All available components in the authentication chain verified properly, but
there was no trust anchor available.

=back

Status values in I<val_status_t> returned by the validator can be displayed
in ASCII format using I<p_val_status()>.

=back

=back

=over 4

=item I<struct val_authentication_chain>

  struct val_authentication_chain
  {
      val_astatus_t                    val_ac_status;
      struct val_rrset_rec                *val_ac_rrset;
      struct val_authentication_chain *val_ac_trust;
  };

=over 4

=item I<val_ac_status>

Validation state of the authentication chain element.  This field will contain
the status code for the given component in the authentication chain.  This
field may contain one of the following values:

=over 4

=item B<VAL_AC_UNSET>

The status could not be determined.

=item B<VAL_AC_IGNORE_VALIDATION>

Validation for the given resource record was ignored, either because of some
local policy directive or because of some protocol-specific behavior.

=item B<VAL_AC_UNTRUSTED_ZONE>

Local policy defined a given zone as untrusted, with no further validation
being deemed necessary.

=item B<VAL_AC_PINSECURE>

The authentication chain from a trust anchor to a given zone could not be
constructed due to the provable absence of a DS record for this zone in the
parent.

=item B<VAL_AC_BARE_RRSIG>

The response was for a query of type RRSIG.  RRSIGs contain the cryptographic
signatures for other DNS data and cannot themselves be validated.

=item B<VAL_AC_NO_LINK>

There was no trust anchor configured for a given authentication chain or the
chain didn't link up.

=item B<VAL_AC_TRUST>

At least one of the signatures covering the given DNSKEY RRset was directly
verified using a key that was configured as a DNSSEC trust anchor.

=item B<VAL_AC_RRSIG_MISSING>

RRSIG data could not be retrieved for a resource record.

=item B<VAL_AC_DNSKEY_MISSING>

The DNSKEY for an RRSIG covering a resource record could not be retrieved.

=item B<VAL_AC_DS_MISSING>

The DS record covering a DNSKEY record was not available.

=item B<VAL_AC_DATA_MISSING>

No data were returned for a query and the DNS did not indicate an error.

=item B<VAL_AC_DNS_ERROR>

Some error was encountered during DNS processing.

=item B<VAL_AC_NOT_VERIFIED>

All RRSIGs covering the RRset could not be verified.

=item B<VAL_AC_VERIFIED>

At least one RRSIG covering a resource record had a status of
B<VAL_AC_RRSIG_VERIFIED>.

=back

=item I<val_ac_rrset>

Pointer to an RRset of type I<struct val_rrset_rec> obtained from the DNS
response.

=item I<val_ac_trust>

Pointer to an authentication chain element that either contains a DNSKEY RRset
that can be used to verify RRSIGs over the current record, or contains a DS
RRset that can be used to build the chain-of-trust towards a trust anchor.

=back

=back

=over 4

=item I<struct val_rrset_rec>

  struct val_rrset_rec
  {
      int    val_rrset_rcode;
      char   *val_rrset_name;
      int    val_rrset_class;
      int    val_rrset_type;
      long   val_rrset_ttl;
      int    val_rrset_section;
      struct sockaddr *val_rrset_server;
      struct val_rr_rec *val_rrset_data;
      struct val_rr_rec *val_rrset_sig;
  };

=over 4

=item I<val_rrset_rcode>

The rcode on the response header for this rrset.

=item I<val_rrset_name>

Owner name of the RRset. 

=item I<val_rrset_class>

Class of the RRset.

=item I<val_val_rrset_type>

Type of the RRset.

=item I<val_rrset_ttl>

TTL of the RRset.

=item I<val_rrset_section>

Section in which the RRset was received.  This value may be
B<VAL_FROM_ANSWER>, B<VAL_FROM_AUTHORITY>, or B<VAL_FROM_ADDITIONAL>.

=item I<val_rrset_server>

The name server that returned this reponse.

=item I<val_rrset_data>

Response RDATA.

=item I<val_rrset_sig>

Any associated RRSIGs for the RDATA returned in I<val_rrset_data>.

=back

=back

=over 4

=item I<struct val_rr_rec>

  struct val_rr_rec
  {
      size_t            rr_rdata_length;
      unsigned char     *rr_rdata;
      struct val_rr_rec *rr_next;
      val_astatus_t     rr_status;
  };

=over 4

=item I<rr_rdata_length_h>

Length of data stored in I<rr_rdata>.

=item I<rr_rdata>

RDATA bytes.

=item I<rr_status>

For each signature I<val_rr_rec> member within the authentication chain
I<val_ac_rrset>, the validation status stored in the variable
I<rr_status> can return one of the following values:

    VAL_AC_RRSIG_VERIFIED
	The RRSIG verified successfully.

    VAL_AC_WCARD_VERIFIED
	A given RRSIG covering a resource record shows
	that the record was wildcard expanded.

    VAL_AC_RRSIG_VERIFIED_SKEW
	The RRSIG verified successfully after clock
	skew was taken into account.

    VAL_AC_WCARD_VERIFIED_SKEW
	A given RRSIG covering a resource record shows that
	the record was wildcard expanded, but it was verified
	only after clock skew was taken into account.

    VAL_AC_WRONG_LABEL_COUNT
	The number of labels on the signature was greater
	than the count given in the RRSIG RDATA.

    VAL_AC_INVALID_RRSIG
	The RRSIG could not be parsed.

    VAL_AC_RRSIG_NOTYETACTIVE
	The RRSIG's inception time is in the future.

    VAL_AC_RRSIG_EXPIRED
	The RRSIG had expired.

    VAL_AC_ALGORITHM_NOT_SUPPORTED
	The RRSIG algorithm was not supported.

    VAL_AC_RRSIG_VERIFY_FAILED
	A given RRSIG covering an RRset was bogus.

    VAL_AC_RRSIG_ALGORITHM_MISMATCH
	The keytag referenced in the RRSIG matched a
	DNSKEY but the algorithms were different.

    VAL_AC_DNSKEY_NOMATCH
	An RRSIG was created by a DNSKEY that did not
	exist in the apex keyset.

For each I<val_rr_rec> member of type DNSKEY (or DS, where relevant) within the
authentication chain I<val_ac_rrset>, the validation status is stored in the
variable I<rr_status> and can return one of the following values:

    VAL_AC_TRUST_POINT
        The given DNSKEY or a DS record was configured 
        as a DNSSEC trust anchor.

    VAL_AC_SIGNING_KEY
	This DNSKEY was used to create an RRSIG for
	the resource record set.

    VAL_AC_VERIFIED_LINK
	This DNSKEY provided the link in the authentication
	chain from the trust anchor to the signed record.

    VAL_AC_UNKNOWN_ALGORITHM_LINK
	This DNSKEY provided the link in the authentication
	chain from the trust anchor to the signed record,
	but the DNSKEY algorithm was unknown.

    VAL_AC_UNKNOWN_DNSKEY_PROTOCOL
	The DNSKEY protocol number was unrecognized.

    VAL_AC_ALGORITHM_NOT_SUPPORTED
	The DNSKEY or DS algorithm was not supported.
    
    VAL_AC_DS_NOMATCH
	An RRSIG was created with a key that did not
	exist in the parent DS record set.

    VAL_AC_INVALID_KEY
	The key used to verify the RRSIG was not a valid DNSKEY.

    VAL_AC_INVALID_DS
	The DS used to validate the DNSKEY could not be parsed.

=back

=item I<rr_next>

Points to the next resource record in the RRset.

=back

=head1 LOGGING 

B<libval> provides the I<val_log_add_optarg()> function for controlling the 
verbosity and location of log message output.

The I<val_log_add_optarg()> function takes two arguments: the first argument
I<args> is a character-string value that specifies the location and verbosity.
The second argument, I<use_stderr>, if set to a value greater than 0 allows 
B<libval> to send log messages to stderr.

The character string that specifies log target location and verbosity has 
a specific format:

    <debug-level>:<dest-type>[:<dest-options>]

where 
    <debug-level> is 1-7, for increasing levels of verbosity
    <dest-type> is one of file, net, syslog, stderr, stdout
    <dest-options> depends on <dest-type>
        file:<file-name>   (opened in append mode)
        net[:<host-name>:<host-port>] (127.0.0.1:1053)
        syslog[:facility] (0-23 (default 1 USER))

The log levels can be roughly translated into different types of log messages 
as follows (the messages returned for each level in this list subsumes the 
messages returned for the level above it):

    3 : Error   : error encountered
    4 : Warning : recovering from error
    5 : Notice  : gives final validation results for a query 
                  and details on policy files and labels used 
    6 : Info    : gives details on authentication chains 
    7 : Debug   : gives debug level information
    
=head1 RETURN VALUES

Return values for various functions are given below. These values can be
displayed in ASCII format using the I<p_val_error()> function.

=over 4

=item VAL_NO_ERROR

No error was encountered.

=item VAL_NOT_IMPLEMENTED

Functionality not yet implemented.

=item VAL_RESOURCE_UNAVAILABLE

Some resource (crypto possibly) was unavailable.  Currently not implemented.

=item VAL_BAD_ARGUMENT

Bad arguments passed as parameters.

=item VAL_INTERNAL_ERROR

Encountered some internal error.

=item VAL_NO_PERMISSION

No permission to perform operation.  Currently not implemented.

=item VAL_CONF_PARSE_ERROR

Error in parsing some configuration file.

=item VAL_CONF_NOT_FOUND

A configuration file was not available.

=item VAL_NO_POLICY

The policy identifier being referenced was invalid.

=back

=head1 FILES

The validator library reads configuration information from two files,
B<resolv.conf> and B<dnsval.conf>.

See B<dnsval.conf(5)> for a description of the syntax for these files.

=head1 COPYRIGHT

Copyright 2004-2013 SPARTA, Inc.  All rights reserved.
See the COPYING file included with the dnssec-tools package for details.

=head1 AUTHORS

Suresh Krishnaswamy, Robert Story

=head1 SEE ALSO

B<libsres(3)>

B<dnsval.conf(5)>

http://www.dnssec-tools.org

=cut	
