client-side DNS TCP
Stefan Metzmacher
metze at samba.org
Fri Jul 7 05:03:43 UTC 2017
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: OpenPGP digital signature
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20170707/e6e38afb/signature.sig>
More information about the samba-technical
mailing list