TSIG in libcli/dns

David Disseldorp ddiss at samba.org
Mon Jul 3 23:52:08 UTC 2017


[cc'ing samba-technical list]

Hi Dimitris,

On Mon, 3 Jul 2017 21:20:33 +0300, Dimitris Gravanis wrote:

> Hi,
> 
> I've been studying the RFC 2845 <https://tools.ietf.org/html/rfc2845> on 
> TSIG, as well as the relative existing code, and I'm writing some code 
> to add TSIG RR in DNS calls.
> 
> I need to define a data type for octet stream, to use for some 
> variables. Also, stdint.h does not define uint48 data type, so I guess I 
> have to define that as well (but to which header!?).

48 bytes, sheesh, looks as though the protocol designers wanted to cause
headaches for implementers ;). I'd suggest just breaking it up into
something manageable, e.g.
	uint8_t time_signed[6]
or
	uint16_t time_signed_upper
	uint32_t time_signed_lower
...and then (un)marshall it to/from a time_t manually, taking care that
it's endian safe.

> This is the code I'm referring to:
> 
> /*
>   * TSIG RDATA according to RFC 2845 (2000)
>   *
>   * alg_name:    algorithm name in domain name syntax
>   *
>   * t_sig:        time signed in seconds since 1-Jan-70 UTC
>   *
>   * t_fud:        t_sig error margin permitted in seconds
>   *
>   * mac_size:    number of octets in MAC
>   *
>   * mac:            defined by algorithm name
>   *
>   * orig_id:        original message ID
>   *
>   * err:            expanded RCODE covering TSIG processing
>   *                 NOERROR:       0
>   *                 BADSIG:        16
>   *                 BADKEY:        17
>   *                 BADTIME:       18
>   *
>   * other_len:    length of other data (in octets)
>   *
>   * other_data:    NULL (BADTIME if Error == BADTIME)
>   *
>   */
> 
> struct *tsig_rdata {
>      const char[] *alg_name;
>      // uint48_t type not defined
>      uint48_t t_sig;
>      uint16_t t_fud;
>      uint16_t mac_size;
>      // MAC datatype in RFC 2845 is defined as octet stream
>      const char[] *mac;
>      uint16_t orig_id;
>      uint16_t err;
>      uint8_t other_len;
>      const char[] *other_data;
> };
> 
> /* TSIG RR Format
>   *
>   * type:    250
>   *
>   * ttl:     0
>   *
> */
> struct tsig_rr {
>      const char *hostname;
>      uint16_t type;
>      uint16_t in_class;
>      uint32_t ttl;
>      uint16_t tsig_rdatalen;
>      uint8_t *tsig_rdata;
> };
> 
> How do you suggest that I handle the data types and the const char[] 
> pointers? I'm not sure those variables have to be pointers, it just made 
> sense to me. I'm also not sure about the size, that's why I left the [] 
> blank.

You'll have to match the wire format in the protocol definitions, to
ensure that Samba remains compatible with other implementations. For
this I'd suggest digging deeper into the corresponding specs. E.g.

The RDATA algorithm_name field has a Data Type of "domain-name", which
is defined in rfc1035 3.1. Name space definitions:
  Domain names in messages are expressed in terms of a sequence of
  labels.
  Each label is represented as a one octet length field followed by that
  number of octets.  Since every domain name ends with the null label of
  the root, a domain name is terminated by a length byte of zero.  The
  high order two bits of every length octet must be zero, and the
  remaining six bits of the length field limit the label to 63 octets or
  less.

At this point it's probably worth getting acquainted with PIDL[1], which
is used within Samba for simplified data structure marshalling and
unmarshalling. PIDL allows a developer to define a wire format (e.g.
struct srv_copychunk_copy in librpc/idl/ioctl.idl) and have it generate
code for marshalling (e.g. ndr_push_srv_copychunk_copy()), unmarshalling
(e.g. ndr_pull_srv_copychunk_copy()) and debugging (e.g.
ndr_print_srv_copychunk_copy()).

Cheers, David

1. PIDL: The Perl Interface description language (IDL) compiler
   https://wiki.samba.org/index.php/Pidl



More information about the samba-technical mailing list