[Freeipa-devel] Generic support for unknown DNS RR types (RFC 3597)

Petr Spacek pspacek at redhat.com
Tue Mar 10 18:24:40 UTC 2015


On 10.3.2015 18:36, Simo Sorce wrote:
> On Tue, 2015-03-10 at 18:26 +0100, Petr Spacek wrote:
>> On 10.3.2015 17:35, Simo Sorce wrote:
>>> On Tue, 2015-03-10 at 16:19 +0100, Petr Spacek wrote:
>>>> On 10.3.2015 15:53, Simo Sorce wrote:
>>>>> On Tue, 2015-03-10 at 15:32 +0100, Petr Spacek wrote:
>>>>>> Hello,
>>>>>>
>>>>>> I would like to discuss Generic support for unknown DNS RR types (RFC 3597
>>>>>> [0]). Here is the proposal:
>>>>>>
>>>>>> LDAP schema
>>>>>> ===========
>>>>>> - 1 new attribute:
>>>>>> ( <OID> NAME 'GenericRecord' DESC 'unknown DNS record, RFC 3597' EQUALITY
>>>>>> caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
>>>>>>
>>>>>> The attribute should be added to existing idnsRecord object class as MAY.
>>>>>>
>>>>>> This new attribute should contain data encoded according to ​RFC 3597 section
>>>>>> 5 [5]:
>>>>>>
>>>>>> The RDATA section of an RR of unknown type is represented as a
>>>>>>    sequence of white space separated words as follows:
>>>>>>
>>>>>>       The special token \# (a backslash immediately followed by a hash
>>>>>>       sign), which identifies the RDATA as having the generic encoding
>>>>>>       defined herein rather than a traditional type-specific encoding.
>>>>>>
>>>>>>       An unsigned decimal integer specifying the RDATA length in octets.
>>>>>>
>>>>>>       Zero or more words of hexadecimal data encoding the actual RDATA
>>>>>>       field, each containing an even number of hexadecimal digits.
>>>>>>
>>>>>>    If the RDATA is of zero length, the text representation contains only
>>>>>>    the \# token and the single zero representing the length.
>>>>>>
>>>>>> Examples from RFC:
>>>>>>       a.example.   CLASS32     TYPE731         \# 6 abcd (
>>>>>>                                                ef 01 23 45 )
>>>>>>       b.example.   HS          TYPE62347       \# 0
>>>>>>       e.example.   IN          A               \# 4 0A000001
>>>>>>       e.example.   CLASS1      TYPE1           10.0.0.2
>>>>>>
>>>>>>
>>>>>> Open questions about LDAP format
>>>>>> ================================
>>>>>> Should we include "\#" constant? We know that the attribute contains record in
>>>>>> RFC 3597 syntax so it is not strictly necessary.
>>>>>>
>>>>>> I think it would be better to follow RFC 3597 format. It allows blind
>>>>>> copy&pasting from other tools, including direct calls to python-dns.
>>>>>>
>>>>>> It also eases writing conversion tools between DNS and LDAP format because
>>>>>> they do not need to change record values.
>>>>>>
>>>>>>
>>>>>> Another question is if we should explicitly include length of data represented
>>>>>> in hexadecimal notation as a decimal number. I'm very strongly inclined to let
>>>>>> it there because it is very good sanity check and again, it allows us to
>>>>>> re-use existing tools including parsers.
>>>>>>
>>>>>> I will ask Uninett.no for standardization after we sort this out (they own the
>>>>>> OID arc we use for DNS records).
>>>>>>
>>>>>>
>>>>>> Attribute usage
>>>>>> ===============
>>>>>> Every DNS RR type has assigned a number [1] which is used on wire. RR types
>>>>>> which are unknown to the server cannot be named by their mnemonic/type name
>>>>>> because server would not be able to do name->number conversion and to generate
>>>>>> DNS wire format.
>>>>>>
>>>>>> As a result, we have to encode the RR type number somehow. Let's use attribute
>>>>>> sub-types.
>>>>>>
>>>>>> E.g. a record with type 65280 and hex value 0A000001 will be represented as:
>>>>>> GenericRecord;TYPE65280: \# 4 0A000001
>>>>>>
>>>>>>
>>>>>> CLI
>>>>>> ===
>>>>>> $ ipa dnsrecord-add zone.example owner \
>>>>>>   --generic-type=65280 --generic-data='\# 4 0A000001'
>>>>>>
>>>>>> $ ipa dnsrecord-show zone.example owner
>>>>>> Record name: owner
>>>>>> TYPE65280 Record: \# 4 0A000001
>>>>>>
>>>>>>
>>>>>> ACK? :-)
>>>>>
>>>>> Almost.
>>>>> We should refrain from using subtypes when not necessary, and in this
>>>>> case it is not necessary.
>>>>>
>>>>> Use:
>>>>> GenericRecord: 65280 \# 4 0A000001
>>>>
>>>> I was considering that too but I can see two main drawbacks:
>>>>
>>>> 1) It does not work very well with DS ACI (targetattrfilter, anyone?). Adding
>>>> generic write access to GenericRecord == ability to add TLSA records too,
>>>> which you may not want. IMHO it is perfectly reasonable to limit write access
>>>> to certain types (e.g. to one from private range).
>>>>
>>>> 2) We would need a separate substring index for emulating filters like
>>>> (type==65280). AFAIK GenericRecord;TYPE65280 should work with presence index
>>>> which will be handy one day when we decide to handle upgrades like
>>>> GenericRecord;TYPE256->UriRecord.
>>>>
>>>> Another (less important) annoyance is that conversion tools would have to
>>>> mangle record data instead of just converting attribute name->record type.
>>>>
>>>>
>>>> I can be convinced that subtypes are not necessary but I do not see clear
>>>> advantage of avoiding them. What is the problem with subtypes?
>>>
>>> Poor support by most clients, so it is generally discouraged.
>> Hmm, it does not sound like a thing we should care in this case. DNS tree is
>> not meant for direct consumption by LDAP clients (compare with cn=compat).
>>
>> IMHO the only two clients we should care are FreeIPA framework and
>> bind-dyndb-ldap so I do not see this as a problem, really. If someone wants to
>> access DNS tree by hand - sure, use a standard compliant client!
>>
>> Working ACI and LDAP filters sounds like good price for supporting only
>> standards compliant clients.
>>
>> AFAIK OpenLDAP works well and I suspect that ApacheDS will work too because
>> Eclipse has nice support for sub-types built-in. If I can draw some
>> conclusions from that, sub-types are not a thing aliens forgot here when
>> leaving Earth one million years ago :-)
>>
>>> The problem with subtypes and ACIs though is that I think ACIs do not
>>> care about the subtype unless you explicit mention them.
>> IMHO that is exactly what I would like to see for GenericRecord. It allows us
>> to write ACI which allows admins to add any GenericRecord and at the same time
>> allows us to craft ACI which allows access only to GenericRecord;TYPE65280 for
>> specific group/user.
>>
>>> So perhaps bind_dyndb_ldap should refuse to use a generic type that
>>> shadows DNSSEC relevant records ?
>> Sorry, this cannot possibly work because it depends on up-to-date blacklist.
>>
>> How would the plugin released in 2015 know that highly sensitive OPENPGPKEY
>> type will be standardized in 2016 and assigned number XYZ?
> 
> Ok, show me an example ACI that works and you get my ack :)

Am I being punished for something? :-)

Anyway, this monstrosity:

(targetattr = "objectclass || txtRecord;test")(target =
"ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl
"permission:luser: Read DNS Entries";allow (compare,read,search) userdn =
"ldap:///uid=luser,cn=users,cn=accounts,dc=ipa,dc=example";)

Gives 'luser' read access only to txtRecord;test and *not* to the whole
txtRecord in general.

$ kinit luser
$ ldapsearch -Y GSSAPI -s base -b
'idnsname=txt,idnsname=ipa.example.,cn=dns,dc=ipa,dc=example'
SASL username: luser at IPA.EXAMPLE

# txt, ipa.example., dns, ipa.example
dn: idnsname=txt,idnsname=ipa.example.,cn=dns,dc=ipa,dc=example
objectClass: top
objectClass: idnsrecord
tXTRecord;test: Guess what is new here!

Filter '(tXTRecord;test=*)' works as expected and returns only objects with
subtype ;test.

The only weird thing I noticed is that search filter '(tXTRecord=*)' does not
return the object if you have access only to an subtype with existing value
but not to the 'vanilla' attribute.

Maybe it is a bug? I will think about it for a while and possibly open a
ticket. Anyway, this is not something we need for implementation.


For completeness:

$ kinit admin
$ ldapsearch -Y GSSAPI -s base -b
'idnsname=txt,idnsname=ipa.example.,cn=dns,dc=ipa,dc=example'
SASL username: admin at IPA.EXAMPLE

# txt, ipa.example., dns, ipa.example
dn: idnsname=txt,idnsname=ipa.example.,cn=dns,dc=ipa,dc=example
objectClass: top
objectClass: idnsrecord
tXTRecord: nothing
tXTRecord: something
idnsName: txt
tXTRecord;test: Guess what is new here!


And yes, you assume correctly that (targetattr = "txtRecord") gives access to
whole txtRecord including all its subtypes.

ACK? :-)

-- 
Petr^2 Spacek




More information about the Freeipa-devel mailing list