diff mbox

Building consensus over DNSSEC enhancements to glibc.

Message ID 564D69F2.7080904@redhat.com
State Dropped
Headers show

Commit Message

Carlos O'Donell Nov. 19, 2015, 6:19 a.m. UTC
On 11/17/2015 09:54 AM, Simo Sorce wrote:
> I would prefer if glibc (and all other libraries) gave this
> information to applications themselves, as it would be more
> efficient. The "out of libc" method causes resolv.conf to be re-read
> 3 times which is a burden for short lived processes but is better
> than not trusting glibc and having applications implement their own
> crypto or have a dozen different methods to "configure" DNSSEC.

I believe the following answers all of the questions in your email,
and resolves the use cases you brought forward. If I missed one, please
provide it again and I'll see what I can do.

I think that defaulting to stripping the AD-bit *and* providing a way
for an application to know which resolv.conf option was set at
startup would allow the application to know the following:

* Assume DNSSEC AD-bit untrusted by default in glibc.

  - Modern glibc will strip AD-bit by default without `options: dnssec-enforced`
    specified in /etc/resolv.conf

  - Old glibc will not strip AD-bit.

  - Applications that want to read /etc/resolv.conf as a heuristic
    can look for `dnssec-enforced` option. Not the recommended way.

* Is the system enforcing DNSSEC (to use an SELinux term)?

  - Use up a res._options bit for RES_DNSSEC_ENFORCED, meaning the
    admin has secured the system and DNS results follow DNSSEC rules.

e.g.
  - res._options has RES_DNSSEC_ENFORCED set (indicates /etc/resolv.conf
    had the `options: dnssec-enforced`. So yes we are enforcing
    DNSSEC and AD-bit is not stripped, and all listed servers are trusted.

    - Use all the normal APIs knowing the results are secure or indeterminate.

    - Connected validating resolvers are trusted and drop insecure
      and bogus results.

  - res._options does not have RES_DNSSEC_ENFORCED set. So no.

    - Only APIs that have explicity trust information can be used.

    - Use getdns API.

    - Use new glibc APIs with DNSSEC flags per Petr's suggestions.

Regardless of the mode the application can use the extended APIs with
DNSSEC flags to receive perhaps all the results of a query along with
trust information so it can decide which results to use and which to
discard. Likewise the extended APIs with flags that request only secure
results are also a valid option.

You must still lock down /etc/resolv.conf to prevent someone from marking
the system as secure when it is not.

Higher level policy frameworks have to decide what to do about multiple
connected interfaces, mixtures of trusted and untrusted networks, etc.
etc. and route that information to the validating resolver whose results
go to the stub resolver which is part of the running application process.

How does that sound?

Cheers,
Carlos.

Comments

Petr Spacek Nov. 19, 2015, 2:03 p.m. UTC | #1
On 19.11.2015 07:19, Carlos O'Donell wrote:
> On 11/17/2015 09:54 AM, Simo Sorce wrote:
>> I would prefer if glibc (and all other libraries) gave this
>> information to applications themselves, as it would be more
>> efficient. The "out of libc" method causes resolv.conf to be re-read
>> 3 times which is a burden for short lived processes but is better
>> than not trusting glibc and having applications implement their own
>> crypto or have a dozen different methods to "configure" DNSSEC.
> 
> I believe the following answers all of the questions in your email,
> and resolves the use cases you brought forward. If I missed one, please
> provide it again and I'll see what I can do.

This sounds very good as far as I understood it :-) I will try to clarify few
things just to be sure we understand each other.

> I think that defaulting to stripping the AD-bit *and* providing a way
> for an application to know which resolv.conf option was set at
> startup would allow the application to know the following:
> 
> * Assume DNSSEC AD-bit untrusted by default in glibc.
> 
>   - Modern glibc will strip AD-bit by default without `options: dnssec-enforced`
>     specified in /etc/resolv.conf
> 
>   - Old glibc will not strip AD-bit.
> 
>   - Applications that want to read /etc/resolv.conf as a heuristic
>     can look for `dnssec-enforced` option. Not the recommended way.
> 
> * Is the system enforcing DNSSEC (to use an SELinux term)?
> 
>   - Use up a res._options bit for RES_DNSSEC_ENFORCED, meaning the
>     admin has secured the system and DNS results follow DNSSEC rules.
> 
> e.g.
> diff --git a/resolv/resolv.h b/resolv/resolv.h
> index 53c3bba..e886610 100644
> --- a/resolv/resolv.h
> +++ b/resolv/resolv.h
> @@ -221,6 +221,7 @@ struct res_sym {
>  #define RES_USE_DNSSEC 0x00800000      /* use DNSSEC using OK bit in OPT */
>  #define RES_NOTLDQUERY 0x01000000      /* Do not look up unqualified name
>                                            as a TLD.  */
> +#define RES_DNSSEC_ENFORCED    0x02000000      /* System is enforcing DNSSEC.  */
>  
>  #define RES_DEFAULT    (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
> ---
> 
>   - res._options has RES_DNSSEC_ENFORCED set (indicates /etc/resolv.conf
>     had the `options: dnssec-enforced`. So yes we are enforcing
>     DNSSEC and AD-bit is not stripped, and all listed servers are trusted.
> 
>     - Use all the normal APIs knowing the results are secure or indeterminate.
> 
>     - Connected validating resolvers are trusted and drop insecure
>       and bogus results.

Detail:
Neither DNS-wire format nor applications distinguish between "indeterminate"
and "insecure". This is expected and follows RFC 4033 section 5. In both cases
AD bit = 0 so consumers will know that particular RR set was not authenticated
and cannot be used for security decisions.

Validating resolvers will drop bogus answers (this includes case where
attacker stripped DNSSEC metadata from answers!).

The logic in consumer should be the results can be trusted if and only ...
if (res._options & RES_DNSSEC_ENFORCED & response->header.ad == 1)
 // data can be trusted
else
 // data cannot be trusted

Applications might potentially skip some DNS queries
if (res._options & RES_DNSSEC_ENFORCED == 0)
because they now beforehand that it does not make sense to even try it.


>   - res._options does not have RES_DNSSEC_ENFORCED set. So no.
> 
>     - Only APIs that have explicity trust information can be used.

Carlos, could you be more specific? I'm not sure what exactly you mean.

I would expect that 'old' functions which do not know anything about DNSSEC
will work as before, e.g. getaddrinfo() will do what it does today, except the
fact that arrays returned by res_query() will have AD bit zeroed out.

Looking from upgrade perspective, anything more restrictive may break the
system when glibc is upgraded but `options: dnssec-enforced` is not added to
/etc/resolv.conf. This may easily happen when glibc is upgraded but validator
needs manual configuration.

This should not be a problem because any application doing
if (res._options & RES_DNSSEC_ENFORCED & response->header.ad == 1)
will not use not-trustworthy-data.

>     - Use getdns API.
> 
>     - Use new glibc APIs with DNSSEC flags per Petr's suggestions.

I guess that you meant new flag for getaddrinfo() etc. to get only secure
results. Yes, that is an option, but I certainly do not insist on that.
Highest impact is on res_*() functions because these are used to obtain
TLSA/SSHFP records etc.


> Regardless of the mode the application can use the extended APIs with
> DNSSEC flags to receive perhaps all the results of a query along with
> trust information so it can decide which results to use and which to
> discard. Likewise the extended APIs with flags that request only secure
> results are also a valid option.

> You must still lock down /etc/resolv.conf to prevent someone from marking
> the system as secure when it is not.
> 
> Higher level policy frameworks have to decide what to do about multiple
> connected interfaces, mixtures of trusted and untrusted networks, etc.
> etc. and route that information to the validating resolver whose results
> go to the stub resolver which is part of the running application process.

Yes, this is what dnssec-trigger is going to do in Fedora.


> How does that sound?

Good, thank you very much!
diff mbox

Patch

diff --git a/resolv/resolv.h b/resolv/resolv.h
index 53c3bba..e886610 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -221,6 +221,7 @@  struct res_sym {
 #define RES_USE_DNSSEC 0x00800000      /* use DNSSEC using OK bit in OPT */
 #define RES_NOTLDQUERY 0x01000000      /* Do not look up unqualified name
                                           as a TLD.  */
+#define RES_DNSSEC_ENFORCED    0x02000000      /* System is enforcing DNSSEC.  */
 
 #define RES_DEFAULT    (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
---