During signed dyn. DNS updates with the internal DNS server a TSIG error is flagged
Günter Kukkukk
linux at kukkukk.com
Sat Feb 9 23:10:01 MST 2013
Hi all,
in the following i'll describe my findings about the dyn. DNS update
failure message, seen when the internal DNS is used.
Be warned - it will be a longer story, cause when i started the investigation
i had only very few background knowledge about dns and crypto at all.
Again - all this is only related to the internal DNS server!
-------
In our wiki in the samba-4.x.x howto, section "Testing/Debugging Dynamic DNS Updates"
we offer a test to check dyn. DNS updates:
/usr/local/samba/sbin/samba_dnsupdate --verbose --all-names
Lots of users ran that command and were/are complaining (mostly on IRC),
that they get more than 20 "error messages".
Atm samba uses the ISC supplied "nsupdate" tool, which can also be listed
as the internal default with:
samba-tool testparm --suppress-prompt -v | grep "nsupdate command"
nsupdate command = /usr/bin/nsupdate -g
Nsupdate is run with the "-g" options, which results in "...GSS-TSIG uses
Kerberos credentials...". One can also run that tool interactive:
nsupdate -g
> update add huhu1.intranet01.hom 86400 A 192.168.200.182
> send
; TSIG error with server: tsig verify failure
>
So the TSIG error is also seen here. Btw - the requested update _is_ done
on the dns server, but then something goes wrong .....
I now did the following:
- downloaded the recent ISC bind source package (i do that for years)
- installed all krb5 related debug packages
- built and installed the bind package to be able to run
nsupdate inside gdb with all sources available
- added DEBUG (); and some dump-hex-and ascii stuff at some places
in some samba sources (mainly dsn_crypto.c and gensec_gssapi.c, ...)
During my first gdb sessions (btw - i used DDD as the gui-frontend), i
realized that "this crypto stuff can easily drive you crazy :-) cause
gdb got deeper and deeper .... and deeper into krb5 libraries.
A big THANKS here to abartlet, who noticed on IRC "...Guenter, look at the
"plain" data ... on both the samba and the ISC nsupdate side...".
The following was one of the first stuff i put into my internal docu:
GKKKK: gensec_gssapi_check_packet: sig
data: 0x85ffce0 len: 28
[0000] 04 04 04 FF FF FF FF FF 00 00 00 00 07 8F B9 C0 ........ ........
[0010] 68 B6 A0 E6 1A 9F B6 32 58 C1 C9 19 h......2 X...
CCC2: input_message: value: 0x8aa1f90 len: 123
CCC3: input_token: value: 0x85ffce0 len: 28
CCC4: input_message: value: 0x8aa1f90 len: 123
CCC5: input_token: value: 0x85ffce0 len: 28 (REQUEST FROM CLIENT checked here)
GKKKK: gensec_gssapi_check_packet: MESSAGE
data: 0x8aa1f90 len: 123
[0000] F1 42 28 00 00 01 00 00 00 01 00 00 0A 69 6E 74 .B(..... .....int
[0010] 72 61 6E 65 74 30 31 03 68 6F 6D 00 00 06 00 01 ranet01. hom.....
[0020] 06 68 75 68 75 38 38 C0 0C 00 01 00 01 00 01 51 .huhu88. .......Q
[0030] 80 00 04 C0 A8 C8 BC 0A 33 39 31 38 30 39 31 39 ........ 39180919
[0040] 37 38 0C 73 69 67 2D 6C 69 6E 75 78 33 30 30 0A 78.sig-l inux300.
[0050] 69 6E 74 72 61 6E 65 74 30 31 03 68 6F 6D 00 00 intranet 01.hom..
[0060] FF 00 00 00 00 08 67 73 73 2D 74 73 69 67 00 00 ......gs s-tsig..
[0070] 00 50 FB 61 73 01 2C 00 00 00 00 .P.ar.,. ...
(gdb) x/169xb plain.data
0x81492d8: 0x00 0x1c
0x04 0x04 0x04 0xff 0xff 0xff
0x81492e0: 0xff 0xff 0x00 0x00 0x00 0x00 0x07 0x8f
0x81492e8: 0xb9 0xc0 0x68 0xb6 0xa0 0xe6 0x1a 0x9f
0x81492f0: 0xb6 0x32 0x58 0xc1 0xc9 0x19
0xf1 0x42
0x81492f8: 0xa8 0x80 0x00 0x01 0x00 0x00 0x00 0x01
^^^^^ ^^^^^
0x8149300: 0x00 0x00 0x0a 0x69 0x6e 0x74 0x72 0x61
0x8149308: 0x6e 0x65 0x74 0x30 0x31 0x03 0x68 0x6f
0x8149310: 0x6d 0x00 0x00 0x06 0x00 0x01 0x06 0x68
0x8149318: 0x75 0x68 0x75 0x38 0x38 0xc0 0x0c 0x00
0x8149320: 0x01 0x00 0x01 0x00 0x01 0x51 0x80 0x00
0x8149328: 0x04 0xc0 0xa8 0xc8 0xbc 0x0a 0x33 0x39
0x8149330: 0x31 0x38 0x30 0x39 0x31 0x39 0x37 0x38
0x8149338: 0x0c 0x73 0x69 0x67 0x2d 0x6c 0x69 0x6e
0x8149340: 0x75 0x78 0x33 0x30 0x30 0x0a 0x69 0x6e
0x8149348: 0x74 0x72 0x61 0x6e 0x65 0x74 0x30 0x31
0x8149350: 0x03 0x68 0x6f 0x6d 0x00 0x00 0xff 0x00
0x8149358: 0x00 0x00 0x00 0x08 0x67 0x73 0x73 0x2d
0x8149360: 0x74 0x73 0x69 0x67 0x00 0x00 0x00 0x50
0x8149368: 0xfb 0x61 0x73 0x01 0x2c 0x00 0x00 0x00
0x8149370: 0x00
0x04 0x04 0x05 0xff 0xff 0xff 0xff
0x8149378: 0xff 0x00 0x00 0x00 0x00 0x0f 0xb9 0xb6
0x8149380: 0xd9
(gdb)
-
BBB2: input: value: 0x847a420 len: 125
BBB3: input; value: 0x847a420 len: 125
BBB4: output; value: 0x8728fc8 len: 28
GKKKK: gensec_gssapi_sign_packet: INPUT (SIGNED RESPONSE)
data: 0x847a420 len: 125
[0000] F1 42 A8 80 00 01 00 00 00 01 00 00 0A 69 6E 74 .B...... .....int
[0010] 72 61 6E 65 74 30 31 03 68 6F 6D 00 00 06 00 01 ranet01. hom.....
[0020] 06 68 75 68 75 38 38 C0 0C 00 01 00 01 00 01 51 .huhu88. .......Q
[0030] 80 00 04 C0 A8 C8 BC 0A 33 39 31 38 30 39 31 39 ........ 39180919
[0040] 37 38 0C 73 69 67 2D 6C 69 6E 75 78 33 30 30 0A 78.sig-l inux300.
[0050] 69 6E 74 72 61 6E 65 74 30 31 03 68 6F 6D 00 00 intranet 01.hom..
[0060] FF 00 00 00 00 08 67 73 73 2D 74 73 69 67 00 00 ......gs s-tsig..
[0070] 00 50 FB 61 73 01 2C 00 00 00 00 00 00 .P.as.,. .....
GKKKK: gensec_gssapi_sign_packet: sig
data: 0x8ee6770 len: 28
[0000] 04 04 05 FF FF FF FF FF 00 00 00 00 0F B9 B6 D9 ........ ........
======================= seqnum
[0010] DF 71 D4 93 3A AB D6 0F E8 E8 33 FD .q..:... ..3. <==checksum
--------------------
The difference between both sides was obvious:
- there were 2 + 28 = 30 additional bytes at the beginning
(later i realized that "0x00 0x1c" is 28 in big-endian ..)
I also realized that the 28 bytes were the MIC from the _former_ request!
- 16 additonal bytes at the end
Fortunately http://tools.ietf.org/html/rfc4121 describes in section
4.2.4. Encryption and Checksum Operations
that the first 16 bytes of the new signed MIC are added at the end of "plain" data.
Btw - the remaining 12 MIC bytes are the checksum itself.
Puuuh, so the trailing 16 bytes were explained now! :-)
But WHY was the former request MIC (and the big-endian length) placed
in front of the plain data? &%(&/@%&( - grumble.
I started hours of reading RFCs and other docus ......
This one caught me attention:
http://docs.oracle.com/cd/E19253-01/816-4863/overview-49/index.html
At the bottom in "Confirming Message Transmission in GSS-API" both
sign and seal cases are described. In the signed MIC only case in step 4:
4. The acceptor sends the MIC back to the initiator.
Okay, but HOW is that done in the DNS case?
I also remembered that i did not understand, which info was used
to create the struct dns_fake_tsig_rec inside samba ... ?
Again hours of searching for RFCs to explain that.....
I knew that the smb/cifs protocol was not really well documented
over years - but i couldn't believe that the same could be true
for the DNS (crypto) protocol.
In my head thoughts like "you are just to stupid to find the right
RFCs" were rotating.
Aaah, why not looking more carefully at the sources from ISC?
They had crafted the plain buffer, which was then send deep
down to the krb5 checksum verify function gss_verify_mic().
When not me, then the devs at ISC had surely a RFC which they
used during coding:
In tsig.c ---> dns_tsig_verify()
.....
if (tsig.siglen > 0) {
sig_r.base = tsig.signature;
sig_r.length = tsig.siglen;
ret = dst_context_create(key, mctx, &ctx);
if (ret != ISC_R_SUCCESS)
return (ret);
if (response) {
isc_buffer_init(&databuf, data, sizeof(data));
isc_buffer_putuint16(&databuf, querytsig.siglen); !!!!!!
isc_buffer_usedregion(&databuf, &r);
ret = dst_context_adddata(ctx, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
if (querytsig.siglen > 0) {
r.length = querytsig.siglen; !!!!!!
r.base = querytsig.signature; !!!!!!
ret = dst_context_adddata(ctx, &r);
if (ret != ISC_R_SUCCESS)
goto cleanup_context;
}
}
..........
Oh well, as the very first bytes they put the former query (!) MIC data
into the plain buffer (was expected, cause my "gdb nsupdate"
sessions were showing that always).
That was the time when i added my first UGLY test code to samba:
- when the update request was seen, i just copied THAT MIC
into a static buffer (Oh well...) Ugly as ugly can be ...
- later when samba was crafting the to be signed buffer response
buffer, i just copied the formerly saved MIC back in front of it.
WOW - that infamous
; TSIG error with server: tsig verify failure
WAS GONE!
I wrote a 2nd UGLY test .... posted it somewhere to a pastebin....
http://pastie.org/6100631
to let Andrew and Kai have a look.
This code was _never_ meant as a patch to the samba source!
But the best news FOR ME is, that i think that today (!!!) i found the RFC
where all that is written down:
http://www.ietf.org/rfc/rfc2845.txt
Could have saved me hours - but i don't count them .... :-)
I hope, that these findings can help to improve the samba code.
Cheers, Günter
Remember - you have been warned, that this story would possibly
never end ....
More information about the samba-technical
mailing list