[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Wed May 22 04:08:02 UTC 2024


The branch, master has been updated
       via  bdfbf25255e test_kinit_export_keytab: reset pw of the test account and test --only-current-keys
       via  b4be5718d3d samba-tool: let 'samba-tool domain exportkeytab' take an --only-current-keys option
       via  2793ef3e163 samba.tests.dckeytab: add test_export_keytab_change3_update_only_current_keep()
       via  e2a5fbf5cf2 s4:libnet_export_keytab: add only_current_keys option
       via  7f1e89488a7 s4:kdc: also provide cross-realm keys via samba_kdc_seq()
       via  37292f8a60f s4:kdc: let samba_kdc_trust_message2entry() return all keys with SDB_F_ADMIN_DATA
       via  6ecc607edee s4:kdc: split out samba_kdc_fill_trust_keys() helper
       via  f5c8c212dcb s4:kdc: add available_enctypes to supported_session_etypes in samba_kdc_trust_message2entry()
       via  f48699641cf s4:kdc: add a returned_kvno helper variable in samba_kdc_trust_message2entry()
       via  d1efc396de4 s4:kdc: let samba_kdc_trust_message2entry() ignore KRB5_PROG_ETYPE_NOSUPP
       via  8cfebc36edc s4:kdc: split out samba_kdc_fill_trust_keys() helper
       via  83f03513fd5 s3:libnet: add a debug message to libnet_keytab_add_to_keytab_entries()
       via  888a785f476 s3:libnet: add support for trusted domains in libnet_dssync_keytab.c
       via  2b2cc544725 s3:libnet: split out store_or_fetch_attribute() from parse_user() in libnet_dssync_keytab.c
       via  feff15fc88b s3:libnet: split out parse_user() in libnet_dssync_keytab.c
       via  52df4063871 s3:libnet: let parse_user() in libnet_dssync_keytab.c work without nt hash
      from  01849ab1bca s4:kdc: Implement KDC plugin hardware authentication policy

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


- Log -----------------------------------------------------------------
commit bdfbf25255e457c3e5d5d75ee09fca3af461c5a7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 17 16:15:17 2024 +0200

    test_kinit_export_keytab: reset pw of the test account and test --only-current-keys
    
    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): Wed May 22 04:07:02 UTC 2024 on atb-devel-224

commit b4be5718d3de3bc90d142cb53f79fe067d0a3e0a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 16:14:18 2024 +0100

    samba-tool: let 'samba-tool domain exportkeytab' take an --only-current-keys option
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2793ef3e1632c735f9caac015503aab06f53d543
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 16:31:22 2024 +0100

    samba.tests.dckeytab: add test_export_keytab_change3_update_only_current_keep()
    
    This tests that only_current_keys=True works.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit e2a5fbf5cf2b65db77e7c5a859c896acca69f432
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 16:11:10 2024 +0100

    s4:libnet_export_keytab: add only_current_keys option
    
    By default we also export on the old and older passwords...
    
    In order to do a kinit with a keytab it might we useful to
    include only the current keys.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 7f1e89488a7212832819380a93fe137a6fa28c37
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 14:14:06 2022 +0100

    s4:kdc: also provide cross-realm keys via samba_kdc_seq()
    
    This means that 'samba-tool domain exportkeytab' is able to
    export them.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 37292f8a60f8fa82faa7bde4314919dcae6fb7ab
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:23:46 2024 +0100

    s4:kdc: let samba_kdc_trust_message2entry() return all keys with SDB_F_ADMIN_DATA
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 6ecc607edeeeb1877b5ecf02ba60d6c8799f583a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:19:20 2024 +0100

    s4:kdc: split out samba_kdc_fill_trust_keys() helper
    
    This simplifies the logic in samba_kdc_trust_message2entry(),
    is very similar to our samba_kdc_fill_user_keys() helper
    and will make it trivial to provide the previous keys
    in entry->old_keys in the next commit.
    
    Review with: git show -p --patience
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f5c8c212dcba48167d8ae8c555a5c4750cb763fd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:19:20 2024 +0100

    s4:kdc: add available_enctypes to supported_session_etypes in samba_kdc_trust_message2entry()
    
    This aligns the logic of samba_kdc_trust_message2entry() with
    samba_kdc_message2entry_keys().
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit f48699641cf95f1e2d197e0f8ea1ed4ce2c4fb41
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:19:20 2024 +0100

    s4:kdc: add a returned_kvno helper variable in samba_kdc_trust_message2entry()
    
    This will simplifiy further changes.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d1efc396de4855a90c7dfd3d935028a21d780272
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:19:20 2024 +0100

    s4:kdc: let samba_kdc_trust_message2entry() ignore KRB5_PROG_ETYPE_NOSUPP
    
    We already handle it in samba_kdc_fill_user_keys() mostly for DES keys,
    but other encryption types might be from kerberos libraries in future.
    And things like FIPS mode may also alter the runtime behaviour.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 8cfebc36edcf5a4ba259d11c6e319aba303ea8ff
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 15 19:19:20 2024 +0100

    s4:kdc: split out samba_kdc_fill_trust_keys() helper
    
    Let samba_kdc_trust_message2entry() also fill in the salt used
    by the key. This is not strictly needed, but it's better to
    be consistent.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 83f03513fd5221cb3bf914bd996c86f0840f34dd
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 18:27:19 2022 +0100

    s3:libnet: add a debug message to libnet_keytab_add_to_keytab_entries()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 888a785f476c64cd34a67149f69bd20f9b7749d8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 18:27:19 2022 +0100

    s3:libnet: add support for trusted domains in libnet_dssync_keytab.c
    
    It means that keytabs generated via 'net rpc vampire keytab' are
    able to decrypt cross-realm tickets in wireshark.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 2b2cc544725368e1922c3c71541c2b478a47586b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 14:48:03 2022 +0100

    s3:libnet: split out store_or_fetch_attribute() from parse_user() in libnet_dssync_keytab.c
    
    This way we can easily re-use the logic in the next commits...
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit feff15fc88b548f9b59aef1427dd1fb5d72ef2a1
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 14:48:03 2022 +0100

    s3:libnet: split out parse_user() in libnet_dssync_keytab.c
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 52df4063871bb6b18e84e559a94fd05ebf33b012
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Feb 3 14:48:03 2022 +0100

    s3:libnet: let parse_user() in libnet_dssync_keytab.c work without nt hash
    
    It happens in setups with 'nt hash store = never'.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 python/samba/netcmd/domain/keytab.py           |   9 +-
 python/samba/tests/dckeytab.py                 |  53 ++-
 selftest/knownfail.d/export-keytab             |   1 -
 source3/libnet/libnet_dssync_keytab.c          | 595 ++++++++++++++++++++++---
 source3/libnet/libnet_keytab.c                 |   2 +
 source4/auth/kerberos/srv_keytab.c             |   3 +-
 source4/kdc/db-glue.c                          | 556 +++++++++++++++++------
 source4/libnet/libnet_export_keytab.c          |  87 ++++
 source4/libnet/libnet_export_keytab.h          |   1 +
 source4/libnet/py_net_dckeytab.c               |  12 +-
 testprogs/blackbox/test_kinit_export_keytab.sh |  22 +-
 11 files changed, 1110 insertions(+), 231 deletions(-)
 delete mode 100644 selftest/knownfail.d/export-keytab


Changeset truncated at 500 lines:

diff --git a/python/samba/netcmd/domain/keytab.py b/python/samba/netcmd/domain/keytab.py
index 0136a11436f..a6d5291ae1a 100644
--- a/python/samba/netcmd/domain/keytab.py
+++ b/python/samba/netcmd/domain/keytab.py
@@ -47,6 +47,9 @@ else:
         takes_options = [
             Option("--principal", help="extract only this principal", type=str),
             Option("--keep-stale-entries", help="keep stale keys in keytab (useful for collecting keys for Wireshark)", action="store_true"),
+            Option("--only-current-keys",
+                   help="This avoids exporting old and older keys (useful for keytabs used by kinit)",
+                   action="store_true"),
         ]
 
         takes_args = ["keytab"]
@@ -58,7 +61,8 @@ else:
                 versionopts=None,
                 hostopts=None,
                 principal=None,
-                keep_stale_entries=None):
+                keep_stale_entries=None,
+                only_current_keys=None):
             lp = sambaopts.get_loadparm()
             net = Net(None, lp)
             samdb = self.ldb_connect(hostopts, sambaopts, credopts)
@@ -66,6 +70,7 @@ else:
                 net.export_keytab(samdb=samdb,
                                   keytab=keytab,
                                   principal=principal,
-                                  keep_stale_entries=keep_stale_entries)
+                                  keep_stale_entries=keep_stale_entries,
+                                  only_current_keys=only_current_keys)
             except NTSTATUSError as error:
                 raise CommandError(f"Failed to export domain keys into keytab {keytab}: {error.args[1]}")
diff --git a/python/samba/tests/dckeytab.py b/python/samba/tests/dckeytab.py
index 31139c0360f..9424c8e50ff 100644
--- a/python/samba/tests/dckeytab.py
+++ b/python/samba/tests/dckeytab.py
@@ -259,7 +259,7 @@ class DCKeytabTests(TestCaseInTempDir):
         # keytab
         self.samdb.setpassword(f"(userPrincipalName={new_principal})", "5rfvBGT%")
         self.samdb.setpassword(f"(userPrincipalName={new_principal})", "6rfvBGT%")
-        self.samdb.setpassword(f"(userPrincipalName={new_principal})", "6rfvBGT%")
+        self.samdb.setpassword(f"(userPrincipalName={new_principal})", "7rfvBGT%")
 
         net.export_keytab(keytab=self.ktfile, principal=new_principal, keep_stale_entries=True)
 
@@ -279,13 +279,62 @@ class DCKeytabTests(TestCaseInTempDir):
             if principal == new_principal and enctype == credentials.ENCTYPE_AES128_CTS_HMAC_SHA1_96:
                 found += 1
 
-        # Samba currently does not export the previous keys into the keytab, but could.
+        # We exported the previous keys into the keytab...
         self.assertEqual(found, 4)
 
         # confirm at least 12 keys (4 changes, 1 in orig export and 3
         # history in 2nd export, 3 enctypes) were exported
         self.assertGreaterEqual(len(keytab_as_set), 12)
 
+    def test_export_keytab_change3_update_only_current_keep(self):
+        new_principal=f"keytab_testuser@{self.creds.get_realm()}"
+        self.samdb.newuser("keytab_testuser", "4rfvBGT%")
+        self.addCleanup(self.samdb.deleteuser, "keytab_testuser")
+        net = Net(None, self.lp)
+        self.addCleanup(self.rm_files, self.ktfile)
+        net.export_keytab(keytab=self.ktfile, principal=new_principal)
+        self.assertTrue(os.path.exists(self.ktfile), 'keytab was not created')
+
+        # Parse the first entry in the keytab
+        with open(self.ktfile, 'rb') as bytes_kt:
+            keytab_orig_bytes = bytes_kt.read()
+
+        # By changing the password three times, we allow Samba to fill
+        # out current, old, older from supplementalCredentials and
+        # still have one password that must still be from the original
+        # keytab
+        self.samdb.setpassword(f"(userPrincipalName={new_principal})", "5rfvBGT%")
+        self.samdb.setpassword(f"(userPrincipalName={new_principal})", "6rfvBGT%")
+        self.samdb.setpassword(f"(userPrincipalName={new_principal})", "7rfvBGT%")
+
+        net.export_keytab(keytab=self.ktfile,
+                          principal=new_principal,
+                          keep_stale_entries=True,
+                          only_current_keys=True)
+
+        with open(self.ktfile, 'rb') as bytes_kt:
+            keytab_change_bytes = bytes_kt.read()
+
+        self.assertNotEqual(keytab_orig_bytes, keytab_change_bytes)
+
+        # self.keytab_as_set() will also check we got each entry
+        # exactly once
+        keytab_as_set = self.keytab_as_set(keytab_change_bytes)
+
+        # Look for the new principal, showing this was updated but the old kept
+        found = 0
+        for entry in keytab_as_set:
+            (principal, enctype, kvno, key) = entry
+            if principal == new_principal and enctype == credentials.ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+                found += 1
+
+        # By default previous keys are not exported into the keytab.
+        self.assertEqual(found, 2)
+
+        # confirm at least 6 keys (1 change, 1 in orig export
+        # both with 3 enctypes) were exported
+        self.assertGreaterEqual(len(keytab_as_set), 6)
+
     def test_export_keytab_change2_export2_update_keep(self):
         new_principal=f"keytab_testuser@{self.creds.get_realm()}"
         self.samdb.newuser("keytab_testuser", "4rfvBGT%")
diff --git a/selftest/knownfail.d/export-keytab b/selftest/knownfail.d/export-keytab
deleted file mode 100644
index 34c16072f5a..00000000000
--- a/selftest/knownfail.d/export-keytab
+++ /dev/null
@@ -1 +0,0 @@
-^samba.tests.dckeytab.samba.tests.dckeytab.DCKeytabTests.test_export_keytab_change3_update_keep
diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c
index 41893b4f7fd..a4fc4e98b0c 100644
--- a/source3/libnet/libnet_dssync_keytab.c
+++ b/source3/libnet/libnet_dssync_keytab.c
@@ -23,6 +23,7 @@
 #include "libnet/libnet_dssync.h"
 #include "libnet/libnet_keytab.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "lib/crypto/md4.h"
 
 #if defined(HAVE_ADS)
 
@@ -233,9 +234,76 @@ done:
 	return status;
 }
 
-static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
-			     struct libnet_keytab_context *ctx,
-			     struct drsuapi_DsReplicaObjectListItemEx *cur)
+static NTSTATUS store_or_fetch_attribute(TALLOC_CTX *mem_ctx,
+					 struct libnet_keytab_context *ctx,
+					 const char *object_dn,
+					 const char *attr,
+					 char **value)
+{
+	DATA_BLOB blob = { .length = 0, };
+	NTSTATUS status;
+
+	if (*value == NULL) {
+		/* look into keytab ... */
+		struct libnet_keytab_entry *entry = NULL;
+		char *principal = NULL;
+
+		D_DEBUG("looking for %s/%s@%s in keytayb...\n",
+			attr, object_dn, ctx->dns_domain_name);
+
+		principal = talloc_asprintf(mem_ctx,
+					    "%s/%s@%s",
+					    attr,
+					    object_dn,
+					    ctx->dns_domain_name);
+		if (principal == NULL) {
+			return NT_STATUS_NO_MEMORY;
+		}
+		entry = libnet_keytab_search(ctx,
+					     principal,
+					     0,
+					     ENCTYPE_NULL,
+					     mem_ctx);
+		if (entry != NULL) {
+			*value = talloc_strndup(mem_ctx,
+						(char *)entry->password.data,
+						entry->password.length);
+			if (*value == NULL) {
+				return NT_STATUS_NO_MEMORY;
+			}
+			D_DEBUG("found %s: %s\n", attr, *value);
+			TALLOC_FREE(entry);
+		} else {
+			*value = NULL;
+			D_DEBUG("entry not found\n");
+		}
+		TALLOC_FREE(principal);
+		return NT_STATUS_OK;
+	}
+
+	blob = data_blob_string_const_null(*value);
+	blob = data_blob_dup_talloc(mem_ctx, blob);
+	if (blob.data == NULL) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	status = libnet_keytab_add_to_keytab_entries(mem_ctx,
+						     ctx,
+						     0,
+						     object_dn,
+						     attr,
+						     ENCTYPE_NULL,
+						     blob);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
+static NTSTATUS parse_user(TALLOC_CTX *mem_ctx,
+			   struct libnet_keytab_context *ctx,
+			   struct drsuapi_DsReplicaObjectListItemEx *cur)
 {
 	NTSTATUS status = NT_STATUS_OK;
 	uchar nt_passwd[16];
@@ -266,7 +334,7 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 		return NT_STATUS_NO_MEMORY;
 	}
 
-	DEBUG(3, ("parsing object '%s'\n", object_dn));
+	DEBUG(3, ("parsing user '%s'\n", object_dn));
 
 	for (i=0; i < cur->object.attribute_ctr.num_attributes; i++) {
 
@@ -278,6 +346,9 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 			spn = talloc_array(mem_ctx, char *, num_spns);
 			for (count = 0; count < num_spns; count++) {
 				blob = attr->value_ctr.values[count].blob;
+				if (blob == NULL) {
+					continue;
+				}
 				pull_string_talloc(spn, NULL, 0,
 						   &spn[count],
 						   blob->data, blob->length,
@@ -285,6 +356,18 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 			}
 		}
 
+		if (attr->attid == DRSUAPI_ATTID_unicodePwd &&
+		    cur->meta_data_ctr != NULL &&
+		    cur->meta_data_ctr->count ==
+		    cur->object.attribute_ctr.num_attributes)
+		{
+			/*
+			 * pick the kvno from the unicodePwd
+			 * meta data, even without a unicodePwd blob
+			 */
+			kvno = cur->meta_data_ctr->meta_data[i].version;
+		}
+
 		if (attr->value_ctr.num_values != 1) {
 			continue;
 		}
@@ -304,18 +387,6 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 
 				memcpy(&nt_passwd, blob->data, 16);
 				got_pwd = true;
-
-				/* pick the kvno from the meta_data version,
-				 * thanks, metze, for explaining this */
-
-				if (!cur->meta_data_ctr) {
-					break;
-				}
-				if (cur->meta_data_ctr->count !=
-				    cur->object.attribute_ctr.num_attributes) {
-					break;
-				}
-				kvno = cur->meta_data_ctr->meta_data[i].version;
 				break;
 			case DRSUAPI_ATTID_ntPwdHistory:
 				pwd_history_len = blob->length / 16;
@@ -353,53 +424,16 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 		}
 	}
 
-	if (!got_pwd) {
-		DEBUG(10, ("no password (unicodePwd) found - skipping.\n"));
-		return NT_STATUS_OK;
-	}
-
-	if (name) {
-		status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, 0, object_dn,
-							     "SAMACCOUNTNAME",
-							     ENCTYPE_NULL,
-							     data_blob_talloc(mem_ctx, name,
-							     strlen(name) + 1));
-		if (!NT_STATUS_IS_OK(status)) {
-			return status;
-		}
-	} else {
-		/* look into keytab ... */
-		struct libnet_keytab_entry *entry = NULL;
-		char *principal = NULL;
-
-		DEBUG(10, ("looking for SAMACCOUNTNAME/%s@%s in keytayb...\n",
-			   object_dn, ctx->dns_domain_name));
-
-		principal = talloc_asprintf(mem_ctx, "%s/%s@%s",
-					    "SAMACCOUNTNAME",
-					    object_dn,
-					    ctx->dns_domain_name);
-		if (!principal) {
-			DEBUG(1, ("talloc failed\n"));
-			return NT_STATUS_NO_MEMORY;
-		}
-		entry = libnet_keytab_search(ctx, principal, 0, ENCTYPE_NULL,
-					     mem_ctx);
-		if (entry) {
-			name = (char *)talloc_memdup(mem_ctx,
-						     entry->password.data,
-						     entry->password.length);
-			if (!name) {
-				DEBUG(1, ("talloc failed!\n"));
-				return NT_STATUS_NO_MEMORY;
-			} else {
-				DEBUG(10, ("found name %s\n", name));
-			}
-			TALLOC_FREE(entry);
-		} else {
-			DEBUG(10, ("entry not found\n"));
-		}
-		TALLOC_FREE(principal);
+	status = store_or_fetch_attribute(mem_ctx,
+					  ctx,
+					  object_dn,
+					  "SAMACCOUNTNAME",
+					  &name);
+	if (!NT_STATUS_IS_OK(status)) {
+		DBG_ERR("store_or_fetch_attribute(%s, %s, %s): %s\n",
+			object_dn, "SAMACCOUNTNAME", name,
+			nt_errstr(status));
+		return status;
 	}
 
 	if (!name) {
@@ -422,12 +456,14 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 	}
 	DEBUGADD(1,("\n"));
 
-	status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL,
-						     ENCTYPE_ARCFOUR_HMAC,
-						     data_blob_talloc(mem_ctx, nt_passwd, 16));
+	if (got_pwd) {
+		status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx, kvno, name, NULL,
+							     ENCTYPE_ARCFOUR_HMAC,
+							     data_blob_talloc(mem_ctx, nt_passwd, 16));
 
-	if (!NT_STATUS_IS_OK(status)) {
-		return status;
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
 	}
 
 	/* add kerberos keys (if any) */
@@ -528,6 +564,429 @@ static NTSTATUS parse_object(TALLOC_CTX *mem_ctx,
 	return status;
 }
 
+static NTSTATUS parse_AuthenticationInformation(TALLOC_CTX *mem_ctx,
+						struct libnet_keytab_context *ctx,
+						const char *dn,
+						const char *trust_name,
+						const char *attr_name,
+						const char *salt_principal,
+						const char *type,
+						uint32_t *kvno,
+						const struct AuthenticationInformationArray *ia)
+{
+	uint32_t i;
+	struct samr_Password _nthash = {{ 0, }};
+	const struct samr_Password *nthash = NULL;
+	const struct AuthInfoClear *clear = NULL;
+	DATA_BLOB password_utf8 = data_blob_null;
+
+	for (i = 0; i < ia->count; i++) {
+		const struct AuthenticationInformation *a = &ia->array[i];
+
+		switch (a->AuthType) {
+		case TRUST_AUTH_TYPE_VERSION:
+			*kvno = a->AuthInfo.version.version;
+			break;
+		case TRUST_AUTH_TYPE_NT4OWF:
+			nthash = &a->AuthInfo.nt4owf.password;
+			break;
+		case TRUST_AUTH_TYPE_CLEAR:
+			clear = &a->AuthInfo.clear;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (clear != NULL && clear->size != 0) {
+		DATA_BLOB password_utf16 = data_blob_null;
+		bool ok;
+
+		password_utf16 = data_blob_const(clear->password,
+						 clear->size);
+
+		if (nthash == NULL) {
+			mdfour(_nthash.hash,
+			       password_utf16.data,
+			       password_utf16.length);
+			nthash = &_nthash;
+		}
+
+		ok = convert_string_talloc(mem_ctx,
+					   CH_UTF16MUNGED, CH_UTF8,
+					   password_utf16.data,
+					   password_utf16.length,
+					   (void *)&password_utf8.data,
+					   &password_utf8.length);
+		if (!ok) {
+			return NT_STATUS_NO_MEMORY;
+		}
+	}
+
+	if (password_utf8.length != 0) {
+		krb5_principal salt_princ = NULL;
+		krb5_data salt = { 0, };
+		krb5_data cleartext_data = { 0, };
+		krb5_enctype enctypes[] = {
+			ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+			ENCTYPE_AES128_CTS_HMAC_SHA1_96,
+		};
+		size_t ei;
+		krb5_error_code kret;
+		NTSTATUS status;
+
+		kret = smb_krb5_parse_name(ctx->context,
+					   salt_principal,
+					   &salt_princ);
+		if (kret != 0) {
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		cleartext_data.data = discard_const_p(char, password_utf8.data);
+		cleartext_data.length = password_utf8.length;
+
+		kret = smb_krb5_get_pw_salt(ctx->context,
+					    salt_princ,
+					    &salt);
+		if (kret != 0) {
+			krb5_free_principal(ctx->context, salt_princ);
+			return NT_STATUS_NO_MEMORY;
+		}
+
+		for (ei = 0; ei < ARRAY_SIZE(enctypes); ei++) {
+			krb5_keyblock keyb = { 0, };
+			DATA_BLOB blob = data_blob_null;
+
+			kret = smb_krb5_create_key_from_string(ctx->context,
+							       salt_princ,
+							       &salt,
+							       &cleartext_data,
+							       enctypes[ei],
+							       &keyb);
+			if (kret != 0) {
+				smb_krb5_free_data_contents(ctx->context, &salt);
+				krb5_free_principal(ctx->context, salt_princ);
+				return NT_STATUS_NO_MEMORY;
+			}
+
+			blob = data_blob_talloc(mem_ctx,
+						KRB5_KEY_DATA(&keyb),
+						KRB5_KEY_LENGTH(&keyb));
+			krb5_free_keyblock_contents(ctx->context, &keyb);
+
+			status = libnet_keytab_add_to_keytab_entries(mem_ctx,
+								     ctx,
+								     *kvno,
+								     trust_name,
+								     attr_name,
+								     enctypes[ei],
+								     blob);
+			if (!NT_STATUS_IS_OK(status)) {
+				smb_krb5_free_data_contents(ctx->context, &salt);
+				krb5_free_principal(ctx->context, salt_princ);
+				return status;
+			}
+		}
+
+		smb_krb5_free_data_contents(ctx->context, &salt);
+		krb5_free_principal(ctx->context, salt_princ);
+	}
+
+	if (nthash != NULL) {
+		DATA_BLOB blob = data_blob_null;
+		NTSTATUS status;
+
+		blob = data_blob_talloc(mem_ctx, nthash->hash, sizeof(nthash->hash));
+
+		status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx,
+							     *kvno,
+							     trust_name,
+							     attr_name,
+							     ENCTYPE_ARCFOUR_HMAC,
+							     blob);
+		if (!NT_STATUS_IS_OK(status)) {
+			return status;
+		}
+	}
+
+	return NT_STATUS_OK;


-- 
Samba Shared Repository



More information about the samba-cvs mailing list