From: Joseph Sutton Date: Fri, 8 Dec 2023 00:00:34 +0000 (+1300) Subject: tests/ndr: Add tests for Group Key Distribution Service blobs X-Git-Tag: talloc-2.4.2~423 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=60e9e3e01cd48c66dba9417783568895be67fc94;p=thirdparty%2Fsamba.git tests/ndr: Add tests for Group Key Distribution Service blobs Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/ndr/gkdi.py b/python/samba/tests/ndr/gkdi.py new file mode 100755 index 00000000000..58e3ce8c376 --- /dev/null +++ b/python/samba/tests/ndr/gkdi.py @@ -0,0 +1,392 @@ +#!/usr/bin/env python3 +# Unix SMB/CIFS implementation. +# Copyright (C) Catalyst.Net Ltd 2023 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import sys +import os + +sys.path.insert(0, "bin/python") +os.environ["PYTHONUNBUFFERED"] = "1" + +from samba.dcerpc import gkdi, misc +from samba.ndr import ndr_pack, ndr_unpack +import samba.tests + + +def utf16_encoded_len(s: str) -> int: + """Return the number of bytes required to encode a string as null‐terminated + UTF‐16.""" + return len(s.encode("utf-16-le")) + 2 + + +class KeyEnvelopeTests(samba.tests.TestCase): + key_envelope_blob = ( + b"\x01\x00\x00\x00KDSK\x02\x00\x00\x00j\x01\x00\x00\x01\x00\x00\x00" + b"\x0e\x00\x00\x001\"\x92\x9d'\xaf;\xb7\x10V\xae\xb1\x8e\xec\xa7\x1a" + b"\x00\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00e\x00x\x00a\x00m\x00" + b"p\x00l\x00e\x00.\x00c\x00o\x00m\x00\x00\x00e\x00x\x00a\x00m\x00p\x00l\x00" + b"e\x00.\x00c\x00o\x00m\x00\x00\x00" + ) + + root_key_id = misc.GUID("9d922231-af27-b73b-1056-aeb18eeca71a") + + domain_name = "example.com" + forest_name = "example.com" + + def test_unpack(self): + """Unpack a GKDI Key Envelope blob and check its fields.""" + + envelope = ndr_unpack(gkdi.KeyEnvelope, self.key_envelope_blob) + + self.assertEqual(1, envelope.version) + self.assertEqual(int.from_bytes(b"KDSK", byteorder="little"), envelope.magic) + self.assertEqual(gkdi.ENVELOPE_FLAG_KEY_MAY_ENCRYPT_NEW_DATA, envelope.flags) + + self.assertEqual(362, envelope.l0_index) + self.assertEqual(1, envelope.l1_index) + self.assertEqual(14, envelope.l2_index) + + self.assertEqual(self.root_key_id, envelope.root_key_id) + + self.assertEqual(0, envelope.unknown) + + self.assertEqual(self.domain_name, envelope.domain_name) + self.assertEqual(utf16_encoded_len(self.domain_name), envelope.domain_name_len) + self.assertEqual(self.forest_name, envelope.forest_name) + self.assertEqual(utf16_encoded_len(self.forest_name), envelope.forest_name_len) + + def test_pack(self): + """Create a GKDI Key Envelope object and test that it packs to the + blob we expect.""" + + envelope = gkdi.KeyEnvelope() + + envelope.version = 1 + envelope.flags = gkdi.ENVELOPE_FLAG_KEY_MAY_ENCRYPT_NEW_DATA + + envelope.l0_index = 362 + envelope.l1_index = 1 + envelope.l2_index = 14 + + envelope.root_key_id = self.root_key_id + + envelope.unknown = 0 + + envelope.domain_name = self.domain_name + envelope.forest_name = self.forest_name + + self.assertEqual(self.key_envelope_blob, ndr_pack(envelope)) + + +class GroupKeyEnvelopeTests(samba.tests.TestCase): + group_key_envelope_blob = ( + b"\x01\x00\x00\x00KDSK\x00\x00\x00\x00j\x01\x00\x00\x01\x00\x00\x00" + b"\x0e\x00\x00\x00\x8c\xc4\x8c\xdevp\x94\x97\x05m\x897{Z\x80R&\x00\x00\x00" + b"\x1e\x00\x00\x00\x06\x00\x00\x00\x0c\x02\x00\x00\x00\x02\x00\x00" + b"\x00\x08\x00\x00@\x00\x00\x00@\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00" + b"S\x00P\x008\x000\x000\x00_\x001\x000\x008\x00_\x00C\x00T\x00R\x00_\x00" + b"H\x00M\x00A\x00C\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0e\x00" + b"\x00\x00\x00\x00\x00\x00S\x00H\x00A\x005\x001\x002\x00\x00\x00D\x00H\x00" + b"\x00\x00\x0c\x02\x00\x00DHPM\x00\x01\x00\x00\x87\xa8\xe6\x1d\xb4\xb6" + b"f<\xff\xbb\xd1\x9ce\x19Y\x99\x8c\xee\xf6\x08f\r\xd0\xf2],\xee\xd4C^" + b";\x00\xe0\r\xf8\xf1\xd6\x19W\xd4\xfa\xf7\xdfEa\xb2\xaa0\x16\xc3\xd9\x114\t" + b"o\xaa;\xf4)m\x83\x0e\x9a| \x9e\x0cd\x97Qz\xbdZ\x8a\x9d0k\xcfg\xed\x91\xf9" + b'\xe6r[GX\xc0"\xe0\xb1\xefBu\xbf{l[\xfc\x11\xd4_\x90\x88\xb9A\xf5N\xb1\xe5' + b"\x9b\xb8\xbc9\xa0\xbf\x120\x7f\\O\xdbp\xc5\x81\xb2?v\xb6:\xca\xe1\xca\xa6" + b"\xb7\x90-RRg5H\x8a\x0e\xf1