client-side DNS TCP

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

client-side DNS TCP

Samba - samba-technical mailing list
Hi,

I'm trying to put together the standard for the client-side DNS TCP
calls in libcli/dns/dns.c, libdns.h and dns.h, so that I can then work
on switching from UDP for packages larger than 512 bytes. I'm using
source4/dns_server/dns_server.c and dns_server for cross-referencing and
to figure out how exactly should I make the client implementation.

I've gone through RFC 1035/768/793/2548/7766, but I'm still getting a
bit overwhelmed from the custom headers and APIs that are used in Samba.
To my understanding, dns_server.c/.h cover the stream, socket and
binding over TCP and most functions from dns_server.c that handle the
above, could be directly implemented to libcli/dns.c, am I correct? Do I
use the same memory and tevent context that is used for UDP requests?

Both talloc and tevent have given me a bit of a hard time, information
overload!

I've also looked into PIDL and found the definition for TSIG records,
along with a "fake" TSIG definition, could you tell me what exactly this
is, since I didn't come across it in RFC 2845?

I checked this
<http://www.csd.uoc.gr/%7Ehy556/material/tutorials/cs556-3rd-tutorial.pdf>
tutorial as well (it's from a Greek University), though it uses Sockets,
it helped me put all those RFCs in perspective.

I'd greatly appreciate your help,

Dimitris

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: client-side DNS TCP

Samba - samba-technical mailing list
Hi Dimitris,

> I'm trying to put together the standard for the client-side DNS TCP
> calls in libcli/dns/dns.c, libdns.h and dns.h, so that I can then work
> on switching from UDP for packages larger than 512 bytes. I'm using
> source4/dns_server/dns_server.c and dns_server for cross-referencing and
> to figure out how exactly should I make the client implementation.

I'd say for dns updates we should only use tcp.

Do you have some work in progress branch somewhere?

> I've gone through RFC 1035/768/793/2548/7766, but I'm still getting a
> bit overwhelmed from the custom headers and APIs that are used in Samba.
> To my understanding, dns_server.c/.h cover the stream, socket and
> binding over TCP and most functions from dns_server.c that handle the
> above, could be directly implemented to libcli/dns.c, am I correct? Do I
> use the same memory and tevent context that is used for UDP requests?
>
> Both talloc and tevent have given me a bit of a hard time, information
> overload!

But once you get around it you'll never want to use something else:-)

> I've also looked into PIDL and found the definition for TSIG records,
> along with a "fake" TSIG definition, could you tell me what exactly this
> is, since I didn't come across it in RFC 284
dns_fake_tsig_rec is what RFC 2845 3.4.2. "TSIG Variables" is about:
Source       Field Name       Notes
-----------------------------------------------------------------------
TSIG RR      NAME             Key name, in canonical wire format
TSIG RR      CLASS            (Always ANY in the current specification)
TSIG RR      TTL              (Always 0 in the current specification)
TSIG RDATA   Algorithm Name   in canonical wire format
TSIG RDATA   Time Signed      in network byte order
TSIG RDATA   Fudge            in network byte order
TSIG RDATA   Error            in network byte order
TSIG RDATA   Other Len        in network byte order
TSIG RDATA   Other Data       exactly as transmitted

While dns_tsig_record is "RDATA" from RFC 2845 2.3. Record Format:
      Field Name       Data Type      Notes
      --------------------------------------------------------------
      Algorithm Name   domain-name    Name of the algorithm
                                      in domain name syntax.
      Time Signed      u_int48_t      seconds since 1-Jan-70 UTC.
      Fudge            u_int16_t      seconds of error permitted
                                      in Time Signed.
      MAC Size         u_int16_t      number of octets in MAC.
      MAC              octet stream   defined by Algorithm Name.
      Original ID      u_int16_t      original message ID
      Error            u_int16_t      expanded RCODE covering
                                      TSIG processing.
      Other Len        u_int16_t      length, in octets, of
                                      Other Data.
      Other Data       octet stream   empty unless Error == BADTIME

Basically the signature generation needs to use the original
dns packet and:
- remove the bytes from dns_tsig_record
- count down the arcount field in the buffer
- construct a blob using dns_fake_tsig_rec and append that
- pass the constructed buffer to gensec_sign_packet()
- rebuild the dns packet buffer with the signature (MAC) field of
  dns_tsig_record filled with the signature from gensec_sign_packet().

See dns_verify_tsig() in source4/dns_server/dns_crypto.c
for the checking function that verifies the client request
and dns_sign_tsig() and dns_tsig_compute_mac() for the
MAC generated in the server response, which should be validated
by the client.

> I checked this
> <http://www.csd.uoc.gr/%7Ehy556/material/tutorials/cs556-3rd-tutorial.pdf>
> tutorial as well (it's from a Greek University), though it uses Sockets,
> it helped me put all those RFCs in perspective.

It's good have some low level understanding, but our high level code
should deal with all these nasty details.

That's why we have the tdgram (for udp) and tstream (for tcp) abstractions.

I guess for one DNS "transaction/call" (request and response) you'll
need to have a call chain like:

1. prepare the request buffer:
2. submit the buffer with tstream_writev_send() or tdgram_sendto_send()
3. register a callback, which uses tstream_writev_recv() or
  tdgram_sendto_recv() to get the result.
4. use tstream_read_pdu_blob_send() (similar to dns_tcp_call_loop())
  or tdgram_recvfrom_send() (similar to dns_udp_call_loop()) to
  wait for the servers response.
5. register a callback, which uses tstream_read_pdu_blob_recv() or
  tdgram_recvfrom_recv() to get the response buffer.
6. parse the response buffer.

I guess you want to implement a low level
dns_client_call_send/recv() which takes the
request buffer and returns the response buffer,
it will basically cover steps 2-5.
And then you have multiple wrapper on top
of it, e.g. dns_client_update_send/recv()
or dns_client_query_send/recv(), which hide
the preparation of the request buffer (including a
signature generation).

metze


signature.asc (853 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: client-side DNS TCP

Samba - samba-technical mailing list
Hi Stefan,

Thank you very much for your detailed input, it helped me significantly.

My main obstacle right now is to determine how are TCP/UDP headers
implemented in Samba. I've figured out UDP, it's pretty straightforward
for the client, but TCP is a bit more complicated and the libraries that
include TCP definitions are a lot. I'm using source4/dns_server as my
main guide, putting it together with talloc, tevent and tsocket. It's a
bit of a maze :).

Regarding branches, is it ok, in terms of permissions/licensing, if I
use a repo at my GitHub and move at git.Samba.org at a later point?

Thanks again and enjoy your weekend,

Dimitris


On 07/07/2017 08:03 πμ, Stefan Metzmacher wrote:

> Hi Dimitris,
>
>> I'm trying to put together the standard for the client-side DNS TCP
>> calls in libcli/dns/dns.c, libdns.h and dns.h, so that I can then work
>> on switching from UDP for packages larger than 512 bytes. I'm using
>> source4/dns_server/dns_server.c and dns_server for cross-referencing and
>> to figure out how exactly should I make the client implementation.
> I'd say for dns updates we should only use tcp.
>
> Do you have some work in progress branch somewhere?
>
>> I've gone through RFC 1035/768/793/2548/7766, but I'm still getting a
>> bit overwhelmed from the custom headers and APIs that are used in Samba.
>> To my understanding, dns_server.c/.h cover the stream, socket and
>> binding over TCP and most functions from dns_server.c that handle the
>> above, could be directly implemented to libcli/dns.c, am I correct? Do I
>> use the same memory and tevent context that is used for UDP requests?
>>
>> Both talloc and tevent have given me a bit of a hard time, information
>> overload!
> But once you get around it you'll never want to use something else:-)
>
>> I've also looked into PIDL and found the definition for TSIG records,
>> along with a "fake" TSIG definition, could you tell me what exactly this
>> is, since I didn't come across it in RFC 284
> dns_fake_tsig_rec is what RFC 2845 3.4.2. "TSIG Variables" is about:
> Source       Field Name       Notes
> -----------------------------------------------------------------------
> TSIG RR      NAME             Key name, in canonical wire format
> TSIG RR      CLASS            (Always ANY in the current specification)
> TSIG RR      TTL              (Always 0 in the current specification)
> TSIG RDATA   Algorithm Name   in canonical wire format
> TSIG RDATA   Time Signed      in network byte order
> TSIG RDATA   Fudge            in network byte order
> TSIG RDATA   Error            in network byte order
> TSIG RDATA   Other Len        in network byte order
> TSIG RDATA   Other Data       exactly as transmitted
>
> While dns_tsig_record is "RDATA" from RFC 2845 2.3. Record Format:
>        Field Name       Data Type      Notes
>        --------------------------------------------------------------
>        Algorithm Name   domain-name    Name of the algorithm
>                                        in domain name syntax.
>        Time Signed      u_int48_t      seconds since 1-Jan-70 UTC.
>        Fudge            u_int16_t      seconds of error permitted
>                                        in Time Signed.
>        MAC Size         u_int16_t      number of octets in MAC.
>        MAC              octet stream   defined by Algorithm Name.
>        Original ID      u_int16_t      original message ID
>        Error            u_int16_t      expanded RCODE covering
>                                        TSIG processing.
>        Other Len        u_int16_t      length, in octets, of
>                                        Other Data.
>        Other Data       octet stream   empty unless Error == BADTIME
>
> Basically the signature generation needs to use the original
> dns packet and:
> - remove the bytes from dns_tsig_record
> - count down the arcount field in the buffer
> - construct a blob using dns_fake_tsig_rec and append that
> - pass the constructed buffer to gensec_sign_packet()
> - rebuild the dns packet buffer with the signature (MAC) field of
>    dns_tsig_record filled with the signature from gensec_sign_packet().
>
> See dns_verify_tsig() in source4/dns_server/dns_crypto.c
> for the checking function that verifies the client request
> and dns_sign_tsig() and dns_tsig_compute_mac() for the
> MAC generated in the server response, which should be validated
> by the client.
>
>> I checked this
>> <http://www.csd.uoc.gr/%7Ehy556/material/tutorials/cs556-3rd-tutorial.pdf>
>> tutorial as well (it's from a Greek University), though it uses Sockets,
>> it helped me put all those RFCs in perspective.
> It's good have some low level understanding, but our high level code
> should deal with all these nasty details.
>
> That's why we have the tdgram (for udp) and tstream (for tcp) abstractions.
>
> I guess for one DNS "transaction/call" (request and response) you'll
> need to have a call chain like:
>
> 1. prepare the request buffer:
> 2. submit the buffer with tstream_writev_send() or tdgram_sendto_send()
> 3. register a callback, which uses tstream_writev_recv() or
>    tdgram_sendto_recv() to get the result.
> 4. use tstream_read_pdu_blob_send() (similar to dns_tcp_call_loop())
>    or tdgram_recvfrom_send() (similar to dns_udp_call_loop()) to
>    wait for the servers response.
> 5. register a callback, which uses tstream_read_pdu_blob_recv() or
>    tdgram_recvfrom_recv() to get the response buffer.
> 6. parse the response buffer.
>
> I guess you want to implement a low level
> dns_client_call_send/recv() which takes the
> request buffer and returns the response buffer,
> it will basically cover steps 2-5.
> And then you have multiple wrapper on top
> of it, e.g. dns_client_update_send/recv()
> or dns_client_query_send/recv(), which hide
> the preparation of the request buffer (including a
> signature generation).
>
> metze
>


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: client-side DNS TCP

Samba - samba-technical mailing list
On Saturday, 8 July 2017 17:21:35 CEST Dimitris Gravanis via samba-technical
wrote:

> Hi Stefan,
>
> Thank you very much for your detailed input, it helped me significantly.
>
> My main obstacle right now is to determine how are TCP/UDP headers
> implemented in Samba. I've figured out UDP, it's pretty straightforward
> for the client, but TCP is a bit more complicated and the libraries that
> include TCP definitions are a lot. I'm using source4/dns_server as my
> main guide, putting it together with talloc, tevent and tsocket. It's a
> bit of a maze :).
>
> Regarding branches, is it ok, in terms of permissions/licensing, if I
> use a repo at my GitHub and move at git.Samba.org at a later point?

Yes, that's fine.

--
Andreas Schneider                   GPG-ID: CC014E3D
Samba Team                             [hidden email]
www.samba.org

Loading...