[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Jun 6 03:19:02 UTC 2024


The branch, master has been updated
       via  ed61c57e023 s4:dns_server: no-op dns updates with ACCESS_DENIED should be ignored
       via  76fec2668e7 s4:dns_server: correctly sign dns update responses with gss-tsig like Windows
       via  db350bc573b s4:dns_server: dns_verify_tsig should return REFUSED on error
       via  5906ed94f2c s4:dns_server: also search DNS_QTYPE_TKEY in the answers section if it's the last section
       via  ae7538af044 s4:dns_server: use tkey->algorithm if available in dns_sign_tsig()
       via  bd0235cd515 s4:dns_server: use the client provided algorithm for the fake TSIG structure
       via  3467d149149 s4:dns_server: only allow gss-tsig and gss.microsoft.com for TSIG
       via  fa0f23e69ea s4:dns_server: only allow gss-tsig and gss.microsoft.com for TKEY
       via  a56627b0d12 s4:dns_server: failed dns updates should result in REFUSED for ACCESS_DENIED
       via  708a6fae697 python:tests/dns_tkey: add test_update_tsig_record_access_denied()
       via  753428a3b6c s4:selftest/tests: pass USERNAME_UNPRIV=$DOMAIN_USER to samba.tests.dns_tkey
       via  88457da00d4 python:tests/dns_base: add get_unpriv_creds() helper
       via  848318338b2 python:tests/dns_tkey: let test_update_tsig_windows() actually pass against windows 2022
       via  8324d0739df python:tests/dns_base: let verify_packet() work against Windows
       via  de4ed363d37 python:tests/dns_tkey: test bad and changing tsig algorithms
       via  b9b03ca503c python:tests/dns_tkey: add gss.microsoft.com tsig updates
       via  3c7cb85eaf8 python:tests/dns_tkey: let us have test_update_gss_tsig_tkey_req_{additional,answers}()
       via  740bda87a80 python:tests/dns_tkey: test TKEY with gss-tsig, gss.microsoft.com and invalid algorithms
       via  b0af60e7850 python:tests/dns_base: maintain a dict with tkey related state
       via  1b1e7e06cf6 python:tests/dns_base: let dns_transaction_udp() take allow_{remaining,truncated}=True
       via  27d92fa808c python:tests/dns_base: pass tkey_trans(expected_rcode)
       via  cd747307d84 python:tests/dns_base: let tkey_trans() take tkey_req_in_answers
       via  f8dfa9b33bd python:tests/dns_base: let tkey_trans() and sign_packet() take algorithm_name as argument
       via  6e997f93d53 python:tests/dns_tkey: make use of self.assert_echoed_dns_error()
       via  ce591464cb1 python:tests/dns_base: add self.assert_echoed_dns_error()
       via  c741d0f3969 python:tests/dns_base: let dns_transaction_tcp() handle short receives
       via  c594cbad4af python:tests/dns_base: use ndr_deepcopy() and ndr_pack() in verify_packet()
       via  ae23d512a72 python:tests/dns_base: generate a real signature in bad_sign_packet()
       via  319836ce9e6 lib/addns: remove unused kerberos/gssapi includes in dns.h
      from  096d3807b05 build: Make "samba4" public libraries provided (mostly) for OpenChange private

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit ed61c57e02309b738e73fb12877a0a565b627724
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu May 30 14:52:22 2024 +0200

    s4:dns_server: no-op dns updates with ACCESS_DENIED should be ignored
    
    If the client does not have permissions to update the record,
    but the record already has the data the update tries to apply,
    it's a no-op that should result in success instead of failing.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Jun  6 03:18:16 UTC 2024 on atb-devel-224

commit 76fec2668e73b9d15447abee551d5c04148aaf27
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu May 30 14:39:28 2024 +0200

    s4:dns_server: correctly sign dns update responses with gss-tsig like Windows
    
    This means we no longer generate strange errors/warnings
    in the Windows event log nor in the nsupdate -g output.
    
    Note: this is a only difference between gss-tsig and
    the legacy gss.microsoft.com algorithms.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit db350bc573b378fb0615bdd8592cc9c62f6db146
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu May 30 14:42:53 2024 +0200

    s4:dns_server: dns_verify_tsig should return REFUSED on error
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 5906ed94f2c5c68e83c63e7c201534eeb323cfe7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu May 30 14:41:21 2024 +0200

    s4:dns_server: also search DNS_QTYPE_TKEY in the answers section if it's the last section
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ae7538af04435658d2ba6dcab109beecb6c5f13e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:38:24 2024 +0200

    s4:dns_server: use tkey->algorithm if available in dns_sign_tsig()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit bd0235cd515d5602ed9501bfc810a2487364ea10
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:38:24 2024 +0200

    s4:dns_server: use the client provided algorithm for the fake TSIG structure
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3467d1491490830d61d16cb6278051daf48466fc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:38:24 2024 +0200

    s4:dns_server: only allow gss-tsig and gss.microsoft.com for TSIG
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit fa0f23e69eaf4f475bc9dc9aa0e23c7bd5208250
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:38:24 2024 +0200

    s4:dns_server: only allow gss-tsig and gss.microsoft.com for TKEY
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a56627b0d125ef7b456bebe307087f324f1f0422
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:36:40 2024 +0200

    s4:dns_server: failed dns updates should result in REFUSED for ACCESS_DENIED
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 708a6fae6978e1462e1a53f4ee08f11b51a5637a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 11:40:51 2024 +0200

    python:tests/dns_tkey: add test_update_tsig_record_access_denied()
    
    This demonstrates that access_denied is only generated if the client
    really generates a change in the database.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 753428a3b6c488c4aacea04d2ddb9ea73244695a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 11:39:56 2024 +0200

    s4:selftest/tests: pass USERNAME_UNPRIV=$DOMAIN_USER to samba.tests.dns_tkey
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 88457da00d4110b419f7a7ccabcd542fa77e463f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 11:39:56 2024 +0200

    python:tests/dns_base: add get_unpriv_creds() helper
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 848318338b2972f331e067bf1c8d6c7dac0748c8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:17:54 2024 +0200

    python:tests/dns_tkey: let test_update_tsig_windows() actually pass against windows 2022
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8324d0739dfdd0a081c403e298a9038ee7df681f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:17:54 2024 +0200

    python:tests/dns_base: let verify_packet() work against Windows
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit de4ed363d378f2065a4634f94af80ea0e3965c96
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 17:26:39 2024 +0200

    python:tests/dns_tkey: test bad and changing tsig algorithms
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit b9b03ca503c43c7ee06df6c331839bd47f9eac8c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 17:18:34 2024 +0200

    python:tests/dns_tkey: add gss.microsoft.com tsig updates
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 3c7cb85eaf8371be55a371601cc354440dab7a94
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 14:15:45 2024 +0200

    python:tests/dns_tkey: let us have test_update_gss_tsig_tkey_req_{additional,answers}()
    
    Also test using the additional record in the answers section.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 740bda87a80b97816d892e8f7aae28759f6916ec
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 16:41:12 2024 +0200

    python:tests/dns_tkey: test TKEY with gss-tsig, gss.microsoft.com and invalid algorithms
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit b0af60e7850e656ef98edeac657c66b853080dab
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 14:10:52 2024 +0200

    python:tests/dns_base: maintain a dict with tkey related state
    
    This will allow tests to backup the whole state
    and mix them.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 1b1e7e06cf6ebd283de73c351267d53b42663d2f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 14:14:11 2024 +0200

    python:tests/dns_base: let dns_transaction_udp() take allow_{remaining,truncated}=True
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 27d92fa808c6617353c36fdb230504e880f4925b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 16:07:53 2024 +0200

    python:tests/dns_base: pass tkey_trans(expected_rcode)
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit cd747307d845f3cff723a7916aeeb31458f19202
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 14:08:13 2024 +0200

    python:tests/dns_base: let tkey_trans() take tkey_req_in_answers
    
    It's possible to put the additional into the answers section,
    so we should be able to test that.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f8dfa9b33bdedffbe2e3b6e229ffae4beb3c712e
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:17:54 2024 +0200

    python:tests/dns_base: let tkey_trans() and sign_packet() take algorithm_name as argument
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6e997f93d53ac45af79aec030bad73f51bdc5629
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:35:58 2024 +0200

    python:tests/dns_tkey: make use of self.assert_echoed_dns_error()
    
    Failed DNS updates just echo the request flaged as response,
    all other elements are unchanged.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ce591464cb12ab00a5d5752a7cea5f909c3c3f1b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:35:58 2024 +0200

    python:tests/dns_base: add self.assert_echoed_dns_error()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c741d0f3969abe821e8ee2a10f848159eb2749fe
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 31 08:07:24 2024 +0200

    python:tests/dns_base: let dns_transaction_tcp() handle short receives
    
    With socket_wrapper we only get 1500 byte chunks...
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit c594cbad4af97031bb7b5b0eb2fb228b00acf646
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:16:40 2024 +0200

    python:tests/dns_base: use ndr_deepcopy() and ndr_pack() in verify_packet()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ae23d512a724650ae2de1178ac43deff8266aa56
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed May 29 13:11:24 2024 +0200

    python:tests/dns_base: generate a real signature in bad_sign_packet()
    
    We just destroy the signature bytes but keep the header unchanged.
    
    This makes it easier to look at it in wireshark.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13019
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 319836ce9e65d68aa98696f387c0d3e6d99e57b8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 5 17:46:53 2024 +0200

    lib/addns: remove unused kerberos/gssapi includes in dns.h
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/addns/dns.h                       |   2 -
 python/samba/tests/dns_base.py        | 213 +++++++++++++++-------
 python/samba/tests/dns_tkey.py        | 325 ++++++++++++++++++++++++++++++----
 python/samba/tests/join.py            |   2 +-
 source4/dns_server/dns_crypto.c       |  49 ++++-
 source4/dns_server/dns_query.c        |  27 ++-
 source4/dns_server/dns_update.c       |  11 ++
 source4/dns_server/dnsserver_common.c |   2 +
 source4/selftest/tests.py             |   6 +-
 9 files changed, 526 insertions(+), 111 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/addns/dns.h b/lib/addns/dns.h
index abf0906fdab..6e605cbec2e 100644
--- a/lib/addns/dns.h
+++ b/lib/addns/dns.h
@@ -27,8 +27,6 @@
 
 #include "../replace/replace.h"
 #include "system/network.h"
-#include "system/kerberos.h"
-#include "system/gssapi.h"
 
 /* make sure we have included the correct config.h */
 #ifndef NO_CONFIG_H /* for some tests */
diff --git a/python/samba/tests/dns_base.py b/python/samba/tests/dns_base.py
index d320a0e9183..43a62b1ac57 100644
--- a/python/samba/tests/dns_base.py
+++ b/python/samba/tests/dns_base.py
@@ -20,6 +20,7 @@ from samba.tests import TestCaseInTempDir
 from samba.dcerpc import dns, dnsp
 from samba import gensec, tests
 from samba import credentials
+from samba import NTSTATUSError
 import struct
 import samba.ndr as ndr
 import random
@@ -76,6 +77,24 @@ class DNSTest(TestCaseInTempDir):
         self.assertEqual(p_opcode, opcode, "Expected OPCODE %s, got %s" %
                           (opcode, p_opcode))
 
+    def assert_dns_flags_equals(self, packet, flags):
+        "Helper function to check opcode"
+        p_flags = packet.operation & (~(dns.DNS_OPCODE|dns.DNS_RCODE))
+        self.assertEqual(p_flags, flags, "Expected FLAGS %02x, got %02x" %
+                          (flags, p_flags))
+
+    def assert_echoed_dns_error(self, request, response, response_p, rcode):
+
+        request_p = ndr.ndr_pack(request)
+
+        self.assertEqual(response.id, request.id)
+        self.assert_dns_rcode_equals(response, rcode)
+        self.assert_dns_opcode_equals(response, request.operation & dns.DNS_OPCODE)
+        self.assert_dns_flags_equals(response,
+            (request.operation | dns.DNS_FLAG_REPLY) & (~(dns.DNS_OPCODE|dns.DNS_RCODE)))
+        self.assertEqual(len(response_p), len(request_p))
+        self.assertEqual(response_p[4:], request_p[4:])
+
     def make_name_packet(self, opcode, qid=None):
         "Helper creating a dns.name_packet"
         p = dns.name_packet()
@@ -112,6 +131,8 @@ class DNSTest(TestCaseInTempDir):
         return self.creds.get_realm().lower()
 
     def dns_transaction_udp(self, packet, host,
+                            allow_remaining=False,
+                            allow_truncated=False,
                             dump=False, timeout=None):
         "send a DNS query and read the reply"
         s = None
@@ -128,8 +149,22 @@ class DNSTest(TestCaseInTempDir):
             recv_packet = s.recv(2048, 0)
             if dump:
                 print(self.hexdump(recv_packet))
-            response = ndr.ndr_unpack(dns.name_packet, recv_packet)
+            if allow_truncated:
+                # with allow_remaining
+                # we add some zero bytes
+                # in order to also parse truncated
+                # responses
+                recv_packet_p = recv_packet + 32*b"\x00"
+                allow_remaining = True
+            else:
+                recv_packet_p = recv_packet
+            response = ndr.ndr_unpack(dns.name_packet, recv_packet_p,
+                                      allow_remaining=allow_remaining)
             return (response, recv_packet)
+        except RuntimeError as re:
+            if s is not None:
+                s.close()
+            raise AssertionError(re)
         finally:
             if s is not None:
                 s.close()
@@ -151,11 +186,26 @@ class DNSTest(TestCaseInTempDir):
             tcp_packet += send_packet
             s.sendall(tcp_packet)
 
-            recv_packet = s.recv(0xffff + 2, 0)
+            recv_packet = b''
+            length = None
+            for i in range(0, 2 + 0xffff):
+                if len(recv_packet) >= 2:
+                    length, = struct.unpack('!H', recv_packet[0:2])
+                    remaining = 2 + length
+                else:
+                    remaining = 2 + 12
+                remaining -= len(recv_packet)
+                if remaining == 0:
+                    break
+                recv_packet += s.recv(remaining, 0)
             if dump:
                 print(self.hexdump(recv_packet))
             response = ndr.ndr_unpack(dns.name_packet, recv_packet[2:])
 
+        except RuntimeError as re:
+            if s is not None:
+                s.close()
+            raise AssertionError(re)
         finally:
             if s is not None:
                 s.close()
@@ -217,18 +267,41 @@ class DNSTKeyTest(DNSTest):
         self.creds.set_username(tests.env_get_var_value('USERNAME'))
         self.creds.set_password(tests.env_get_var_value('PASSWORD'))
         self.creds.set_kerberos_state(credentials.MUST_USE_KERBEROS)
+
+        self.unpriv_creds = None
+
         self.newrecname = "tkeytsig.%s" % self.get_dns_domain()
 
-    def tkey_trans(self, creds=None):
+    def get_unpriv_creds(self):
+        if self.unpriv_creds is not None:
+            return self.unpriv_creds
+
+        self.unpriv_creds = credentials.Credentials()
+        self.unpriv_creds.guess(self.lp_ctx)
+        self.unpriv_creds.set_username(tests.env_get_var_value('USERNAME_UNPRIV'))
+        self.unpriv_creds.set_password(tests.env_get_var_value('PASSWORD_UNPRIV'))
+        self.unpriv_creds.set_kerberos_state(credentials.MUST_USE_KERBEROS)
+
+        return self.unpriv_creds
+
+    def tkey_trans(self, creds=None, algorithm_name="gss-tsig",
+                   tkey_req_in_answers=False,
+                   expected_rcode=dns.DNS_RCODE_OK):
         "Do a TKEY transaction and establish a gensec context"
 
         if creds is None:
             creds = self.creds
 
-        self.key_name = "%s.%s" % (uuid.uuid4(), self.get_dns_domain())
+        mech = 'spnego'
+
+        tkey = {}
+        tkey['name'] = "%s.%s" % (uuid.uuid4(), self.get_dns_domain())
+        tkey['creds'] = creds
+        tkey['mech'] = mech
+        tkey['algorithm'] = algorithm_name
 
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
-        q = self.make_name_question(self.key_name,
+        q = self.make_name_question(tkey['name'],
                                     dns.DNS_QTYPE_TKEY,
                                     dns.DNS_QCLASS_IN)
         questions = []
@@ -236,30 +309,30 @@ class DNSTKeyTest(DNSTest):
         self.finish_name_packet(p, questions)
 
         r = dns.res_rec()
-        r.name = self.key_name
+        r.name = tkey['name']
         r.rr_type = dns.DNS_QTYPE_TKEY
         r.rr_class = dns.DNS_QCLASS_IN
         r.ttl = 0
         r.length = 0xffff
         rdata = dns.tkey_record()
-        rdata.algorithm = "gss-tsig"
+        rdata.algorithm = algorithm_name
         rdata.inception = int(time.time())
         rdata.expiration = int(time.time()) + 60 * 60
         rdata.mode = dns.DNS_TKEY_MODE_GSSAPI
         rdata.error = 0
         rdata.other_size = 0
 
-        self.g = gensec.Security.start_client(self.settings)
-        self.g.set_credentials(creds)
-        self.g.set_target_service("dns")
-        self.g.set_target_hostname(self.server)
-        self.g.want_feature(gensec.FEATURE_SIGN)
-        self.g.start_mech_by_name("spnego")
+        tkey['gensec'] = gensec.Security.start_client(self.settings)
+        tkey['gensec'].set_credentials(creds)
+        tkey['gensec'].set_target_service("dns")
+        tkey['gensec'].set_target_hostname(self.server)
+        tkey['gensec'].want_feature(gensec.FEATURE_SIGN)
+        tkey['gensec'].start_mech_by_name(tkey['mech'])
 
         finished = False
         client_to_server = b""
 
-        (finished, server_to_client) = self.g.update(client_to_server)
+        (finished, server_to_client) = tkey['gensec'].update(client_to_server)
         self.assertFalse(finished)
 
         data = [x if isinstance(x, int) else ord(x) for x in list(server_to_client)]
@@ -268,56 +341,76 @@ class DNSTKeyTest(DNSTest):
         r.rdata = rdata
 
         additional = [r]
-        p.arcount = 1
-        p.additional = additional
+        if tkey_req_in_answers:
+            p.ancount = 1
+            p.answers = additional
+        else:
+            p.arcount = 1
+            p.additional = additional
 
         (response, response_packet) =\
             self.dns_transaction_tcp(p, self.server_ip)
+        if expected_rcode != dns.DNS_RCODE_OK:
+            self.assert_echoed_dns_error(p, response, response_packet, expected_rcode)
+            return
         self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
 
         tkey_record = response.answers[0].rdata
         server_to_client = bytes(tkey_record.key_data)
-        (finished, client_to_server) = self.g.update(server_to_client)
+        (finished, client_to_server) = tkey['gensec'].update(server_to_client)
         self.assertTrue(finished)
 
+        self.tkey = tkey
+
         self.verify_packet(response, response_packet)
 
     def verify_packet(self, response, response_packet, request_mac=b""):
+        self.assertEqual(response.arcount, 1)
         self.assertEqual(response.additional[0].rr_type, dns.DNS_QTYPE_TSIG)
 
+        if self.tkey['algorithm'] == "gss-tsig":
+            gss_tsig = True
+        else:
+            gss_tsig = False
+
+        request_mac_len = b""
+        if len(request_mac) > 0 and gss_tsig:
+            request_mac_len = struct.pack('!H', len(request_mac))
+
         tsig_record = response.additional[0].rdata
         mac = bytes(tsig_record.mac)
 
+        self.assertEqual(tsig_record.original_id, response.id)
+        self.assertEqual(tsig_record.mac_size, len(mac))
+
         # Cut off tsig record from dns response packet for MAC verification
         # and reset additional record count.
-        key_name_len = len(self.key_name) + 2
-        tsig_record_len = len(ndr.ndr_pack(tsig_record)) + key_name_len + 10
-
-        # convert str/bytes to a list (of string char or int)
-        # so it can be modified
-        response_packet_list = [x if isinstance(x, int) else ord(x) for x in response_packet]
-        del response_packet_list[-tsig_record_len:]
-        response_packet_list[11] = 0
-
-        # convert modified list (of string char or int) to str/bytes
-        response_packet_wo_tsig = bytes(response_packet_list)
+        response_copy = ndr.ndr_deepcopy(response)
+        response_copy.arcount = 0
+        response_packet_wo_tsig = ndr.ndr_pack(response_copy)
 
         fake_tsig = dns.fake_tsig_rec()
-        fake_tsig.name = self.key_name
+        fake_tsig.name = self.tkey['name']
         fake_tsig.rr_class = dns.DNS_QCLASS_ANY
         fake_tsig.ttl = 0
         fake_tsig.time_prefix = tsig_record.time_prefix
         fake_tsig.time = tsig_record.time
         fake_tsig.algorithm_name = tsig_record.algorithm_name
         fake_tsig.fudge = tsig_record.fudge
-        fake_tsig.error = 0
-        fake_tsig.other_size = 0
+        fake_tsig.error = tsig_record.error
+        fake_tsig.other_size = tsig_record.other_size
+        fake_tsig.other_data = tsig_record.other_data
         fake_tsig_packet = ndr.ndr_pack(fake_tsig)
 
-        data = request_mac + response_packet_wo_tsig + fake_tsig_packet
-        self.g.check_packet(data, data, mac)
+        data = request_mac_len + request_mac + response_packet_wo_tsig + fake_tsig_packet
+        try:
+            self.tkey['gensec'].check_packet(data, data, mac)
+        except NTSTATUSError as nt:
+            raise AssertionError(nt)
 
-    def sign_packet(self, packet, key_name):
+    def sign_packet(self, packet, key_name,
+                    algorithm_name="gss-tsig",
+                    bad_sig=False):
         "Sign a packet, calculate a MAC and add TSIG record"
         packet_data = ndr.ndr_pack(packet)
 
@@ -327,18 +420,35 @@ class DNSTKeyTest(DNSTest):
         fake_tsig.ttl = 0
         fake_tsig.time_prefix = 0
         fake_tsig.time = int(time.time())
-        fake_tsig.algorithm_name = "gss-tsig"
+        fake_tsig.algorithm_name = algorithm_name
         fake_tsig.fudge = 300
         fake_tsig.error = 0
         fake_tsig.other_size = 0
         fake_tsig_packet = ndr.ndr_pack(fake_tsig)
 
         data = packet_data + fake_tsig_packet
-        mac = self.g.sign_packet(data, data)
+        mac = self.tkey['gensec'].sign_packet(data, data)
         mac_list = [x if isinstance(x, int) else ord(x) for x in list(mac)]
+        if bad_sig:
+            if len(mac) > 8:
+                mac_list[-8] = mac_list[-8] ^ 0xff
+            if len(mac) > 7:
+                mac_list[-7] = ord('b')
+            if len(mac) > 6:
+                mac_list[-6] = ord('a')
+            if len(mac) > 5:
+                mac_list[-5] = ord('d')
+            if len(mac) > 4:
+                mac_list[-4] = ord('m')
+            if len(mac) > 3:
+                mac_list[-3] = ord('a')
+            if len(mac) > 2:
+                mac_list[-2] = ord('c')
+            if len(mac) > 1:
+                mac_list[-1] = mac_list[-1] ^ 0xff
 
         rdata = dns.tsig_record()
-        rdata.algorithm_name = "gss-tsig"
+        rdata.algorithm_name = algorithm_name
         rdata.time_prefix = 0
         rdata.time = fake_tsig.time
         rdata.fudge = 300
@@ -363,33 +473,10 @@ class DNSTKeyTest(DNSTest):
         return mac
 
     def bad_sign_packet(self, packet, key_name):
-        """Add bad signature for a packet by bitflipping
-        the final byte in the MAC"""
-
-        mac_list = [x if isinstance(x, int) else ord(x) for x in list("badmac")]
-
-        rdata = dns.tsig_record()
-        rdata.algorithm_name = "gss-tsig"
-        rdata.time_prefix = 0
-        rdata.time = int(time.time())
-        rdata.fudge = 300
-        rdata.original_id = packet.id
-        rdata.error = 0
-        rdata.other_size = 0
-        rdata.mac = mac_list
-        rdata.mac_size = len(mac_list)
+        """Add bad signature for a packet by
+        bitflipping and hardcoding bytes at the end of the MAC"""
 
-        r = dns.res_rec()
-        r.name = key_name
-        r.rr_type = dns.DNS_QTYPE_TSIG
-        r.rr_class = dns.DNS_QCLASS_ANY
-        r.ttl = 0
-        r.length = 0xffff
-        r.rdata = rdata
-
-        additional = [r]
-        packet.additional = additional
-        packet.arcount = 1
+        return self.sign_packet(packet, key_name, bad_sig=True)
 
     def search_record(self, name):
         p = self.make_name_packet(dns.DNS_OPCODE_QUERY)
diff --git a/python/samba/tests/dns_tkey.py b/python/samba/tests/dns_tkey.py
index 69af14d6f10..f8417ea119d 100644
--- a/python/samba/tests/dns_tkey.py
+++ b/python/samba/tests/dns_tkey.py
@@ -19,6 +19,7 @@
 import sys
 import optparse
 import samba.getopt as options
+import samba.ndr as ndr
 from samba.dcerpc import dns
 from samba.tests.subunitrun import SubunitOptions, TestProgram
 from samba.tests.dns_base import DNSTKeyTest
@@ -55,17 +56,34 @@ class TestDNSUpdates(DNSTKeyTest):
         self.server_ip = server_ip
         super().setUp()
 
-    def test_tkey(self):
-        "test DNS TKEY handshake"
+    def test_tkey_gss_tsig(self):
+        "test DNS TKEY handshake with gss-tsig"
 
         self.tkey_trans()
 
+    def test_tkey_gss_microsoft_com(self):
+        "test DNS TKEY handshake with gss.microsoft.com"
+
+        self.tkey_trans(algorithm_name="gss.microsoft.com")
+
+    def test_tkey_invalid_gss_TSIG(self):
+        "test DNS TKEY handshake with invalid gss-TSIG"
+
+        self.tkey_trans(algorithm_name="gss-TSIG",
+                        expected_rcode=dns.DNS_RCODE_REFUSED)
+
+    def test_tkey_invalid_gss_MICROSOFT_com(self):
+        "test DNS TKEY handshake with invalid gss.MICROSOFT.com"
+
+        self.tkey_trans(algorithm_name="gss.MICROSOFT.com",
+                        expected_rcode=dns.DNS_RCODE_REFUSED)
+
     def test_update_wo_tsig(self):
         "test DNS update without TSIG record"
 
         p = self.make_update_request()
         (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_REFUSED)
+        self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
 
         rcode = self.search_record(self.newrecname)
         self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
@@ -78,10 +96,7 @@ class TestDNSUpdates(DNSTKeyTest):
         p = self.make_update_request()
         self.sign_packet(p, "badkey")
         (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH)
-        tsig_record = response.additional[0].rdata
-        self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADKEY)
-        self.assertEqual(tsig_record.mac_size, 0)
+        self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
 
         rcode = self.search_record(self.newrecname)
         self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
@@ -92,23 +107,149 @@ class TestDNSUpdates(DNSTKeyTest):
         self.tkey_trans()
 
         p = self.make_update_request()
-        self.bad_sign_packet(p, self.key_name)
+        self.bad_sign_packet(p, self.tkey['name'])
         (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
-        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_NOTAUTH)
-        tsig_record = response.additional[0].rdata
-        self.assertEqual(tsig_record.error, dns.DNS_RCODE_BADSIG)
-        self.assertEqual(tsig_record.mac_size, 0)
+        self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
 
         rcode = self.search_record(self.newrecname)
         self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
 
-    def test_update_tsig(self):
-        "test DNS update with correct TSIG record"
+    def test_update_tsig_bad_algorithm(self):
+        "test DNS update with a TSIG record with a bad algorithm"
 
         self.tkey_trans()
 
+        algorithm_name = "gss-TSIG"
         p = self.make_update_request()
-        mac = self.sign_packet(p, self.key_name)
+        mac = self.sign_packet(p, self.tkey['name'],
+                               algorithm_name=algorithm_name)
+        (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+        self.assert_echoed_dns_error(p, response, response_p, dns.DNS_RCODE_REFUSED)
+
+        rcode = self.search_record(self.newrecname)
+        self.assert_rcode_equals(rcode, dns.DNS_RCODE_NXDOMAIN)
+
+    def test_update_tsig_changed_algorithm1(self):
+        "test DNS update with a TSIG record with a changed algorithm"
+
+        algorithm_name = "gss-tsig"
+        self.tkey_trans(algorithm_name=algorithm_name)
+
+        # Now delete the record, it's most likely
+        # a no-op as it should not be there if the test
+        # runs the first time
+        p = self.make_update_request(delete=True)
+        mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)
+        (response, response_p) = self.dns_transaction_udp(p, self.server_ip)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.verify_packet(response, response_p, mac)
+
+        # Now do an update with the algorithm_name
+        # changed in the requests TSIG message.
+        p = self.make_update_request()
+        algorithm_name = "gss.microsoft.com"
+        mac = self.sign_packet(p, self.tkey['name'],
+                               algorithm_name=algorithm_name)
+        algorithm_name = "gss-tsig"
+        (response, response_p) = self.dns_transaction_udp(p, self.server_ip,
+                                                          allow_remaining=True)
+        self.assert_dns_rcode_equals(response, dns.DNS_RCODE_OK)
+        self.verify_packet(response, response_p, mac)
+
+        # Check the record is around
+        rcode = self.search_record(self.newrecname)
+        self.assert_rcode_equals(rcode, dns.DNS_RCODE_OK)
+
+        # Now delete the record, with the original
+        # algorithm_name used in the tkey exchange
+        p = self.make_update_request(delete=True)
+        mac = self.sign_packet(p, self.tkey['name'], algorithm_name=algorithm_name)


-- 
Samba Shared Repository



More information about the samba-cvs mailing list