]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
python: Implement CreateTrustedDomainFallback()
authorAndreas Schneider <asn@samba.org>
Wed, 3 Apr 2024 09:16:19 +0000 (11:16 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Tue, 9 Apr 2024 22:52:37 +0000 (22:52 +0000)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/lsa_utils.py
python/samba/tests/dcerpc/lsa_utils.py

index f2ac8931c2b35098aa538bab630fbb39afe53e54..a56675d6b63dfd3d9a491e26c1f15d53505f7239 100644 (file)
 
 from samba.dcerpc import lsa, drsblobs, misc
 from samba.ndr import ndr_pack
-from samba import NTSTATUSError, arcfour_encrypt, string_to_byte_array
+from samba import (
+    NTSTATUSError,
+    aead_aes_256_cbc_hmac_sha512,
+    arcfour_encrypt,
+    string_to_byte_array
+)
 from samba.ntstatus import (
     NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE
 )
@@ -109,3 +114,80 @@ def CreateTrustedDomainRelax(
         crypto.set_strict_mode()
 
     return lsaconn.CreateTrustedDomainEx2(policy, trust_info, auth_info, mask)
+
+
+def CreateTrustedDomainFallback(
+    conn: lsa.lsarpc,
+    policy_handle: misc.policy_handle,
+    trust_info: lsa.TrustDomainInfoInfoEx,
+    access_mask: int,
+    srv_version: int,
+    srv_revision_info1: lsa.revision_info1,
+    in_blob: drsblobs.trustAuthInOutBlob,
+    out_blob: drsblobs.trustAuthInOutBlob
+):
+    def generate_AuthInfoInternalAES(
+        session_key,
+        incoming=None,
+        outgoing=None
+    ):
+        trustpass = drsblobs.trustDomainPasswords()
+
+        trustpass.outgoing = outgoing
+        trustpass.incoming = incoming
+
+        trustpass_blob = ndr_pack(trustpass)
+
+        lsa_aes256_enc_key = (
+            "Microsoft LSAD encryption key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
+            + b'\x00'
+        )
+        lsa_aes256_mac_key = (
+            "Microsoft LSAD MAC key AEAD-AES-256-CBC-HMAC-SHA512 16".encode()
+            + b'\x00'
+        )
+
+        iv = token_bytes(16)
+        ciphertext, auth_data = aead_aes_256_cbc_hmac_sha512(
+            trustpass_blob,
+            session_key,
+            lsa_aes256_enc_key,
+            lsa_aes256_mac_key,
+            iv,
+        )
+
+        return ciphertext, iv, auth_data
+
+    if (srv_version == 1
+        and srv_revision_info1.revision == 1
+        and (srv_revision_info1.supported_features
+             & lsa.LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER)):
+
+        ciphertext, iv, auth_data = generate_AuthInfoInternalAES(
+            conn.session_key, in_blob, out_blob
+        )
+
+        auth_blob = lsa.DATA_BUF2()
+        auth_blob.size = len(ciphertext)
+        auth_blob.data = string_to_byte_array(ciphertext)
+
+        auth_info = lsa.TrustDomainInfoAuthInfoInternalAES()
+        auth_info.cipher = auth_blob
+        auth_info.salt = string_to_byte_array(iv)
+        auth_info.auth_data = string_to_byte_array(auth_data)
+
+        return conn.CreateTrustedDomainEx3(
+            policy_handle,
+            trust_info,
+            auth_info,
+            access_mask
+        )
+
+    return CreateTrustedDomainRelax(
+        conn,
+        policy_handle,
+        trust_info,
+        access_mask,
+        in_blob,
+        out_blob
+    )
index 648f8ace48157572f69c1d6dac7398e0ad18a794..d6da5eb60bdfbf0791fdf1ac6e53d1bedc78c74c 100644 (file)
@@ -27,7 +27,11 @@ from samba.credentials import (
     SMB_ENCRYPTION_REQUIRED,
     SMB_ENCRYPTION_OFF
 )
-from samba.lsa_utils import OpenPolicyFallback, CreateTrustedDomainRelax
+from samba.lsa_utils import (
+    OpenPolicyFallback,
+    CreateTrustedDomainRelax,
+    CreateTrustedDomainFallback,
+)
 
 
 class CreateTrustedDomain(TestCase):
@@ -144,8 +148,100 @@ class CreateTrustedDomain(TestCase):
         else:
             self.assertIsNone(trustdom_handle)
 
+    def _create_trust_fallback(self):
+        creds = self.get_user_creds()
+
+        lp = self.get_loadparm()
+
+        binding_string = (
+            "ncacn_np:%s" % (samba.tests.env_get_var_value('SERVER'))
+        )
+        lsa_conn = lsa.lsarpc(binding_string, lp, creds)
+
+        in_version = 1
+        in_revision_info1 = lsa.revision_info1()
+        in_revision_info1.revision = 1
+        in_revision_info1.supported_features = (
+            lsa.LSA_FEATURE_TDO_AUTH_INFO_AES_CIPHER
+        )
+
+        out_version, out_revision_info1, pol_handle = OpenPolicyFallback(
+            lsa_conn,
+            '',
+            in_version,
+            in_revision_info1,
+            access_mask=security.SEC_FLAG_MAXIMUM_ALLOWED
+        )
+        self.assertIsNotNone(pol_handle)
+
+        name = lsa.String()
+        name.string = "tests.samba.example.com"
+        try:
+            info = lsa_conn.QueryTrustedDomainInfoByName(
+                pol_handle,
+                name,
+                lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO
+            )
+
+            lsa_conn.DeleteTrustedDomain(pol_handle, info.info_ex.sid)
+        except RuntimeError:
+            pass
+
+        info = lsa.TrustDomainInfoInfoEx()
+        info.domain_name.string = name.string
+        info.netbios_name.string = "createtrustrelax"
+        info.sid = security.dom_sid("S-1-5-21-538490383-3740119673-95748416")
+        info.trust_direction = (
+            lsa.LSA_TRUST_DIRECTION_INBOUND
+            | lsa.LSA_TRUST_DIRECTION_OUTBOUND
+        )
+        info.trust_type = lsa.LSA_TRUST_TYPE_UPLEVEL
+        info.trust_attributes = lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
+
+        password_blob = samba.string_to_byte_array(
+            "password".encode('utf-16-le')
+        )
+
+        clear_value = drsblobs.AuthInfoClear()
+        clear_value.size = len(password_blob)
+        clear_value.password = password_blob
+
+        clear_authentication_information = drsblobs.AuthenticationInformation()
+        clear_authentication_information.LastUpdateTime = 0
+        clear_authentication_information.AuthType = lsa.TRUST_AUTH_TYPE_CLEAR
+        clear_authentication_information.AuthInfo = clear_value
+
+        auth_info_array = drsblobs.AuthenticationInformationArray()
+        auth_info_array.count = 1
+        auth_info_array.array = [clear_authentication_information]
+
+        outgoing = drsblobs.trustAuthInOutBlob()
+        outgoing.count = 1
+        outgoing.current = auth_info_array
+
+        trustdom_handle = None
+        try:
+            trustdom_handle = CreateTrustedDomainFallback(
+                lsa_conn,
+                pol_handle,
+                info,
+                security.SEC_STD_DELETE,
+                out_version,
+                out_revision_info1,
+                outgoing,
+                outgoing
+            )
+        except samba.NTSTATUSError as nt:
+            raise AssertionError(nt)
+
+        self.assertIsNotNone(trustdom_handle)
+        lsa_conn.DeleteTrustedDomain(pol_handle, info.sid)
+
     def test_create_trust_relax_encrypt(self):
         self._create_trust_relax(True)
 
     def test_create_trust_relax_no_enc(self):
         self._create_trust_relax(False)
+
+    def test_create_trust_fallback(self):
+        self._create_trust_fallback()