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 <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abart...@samba.org>
    Autobuild-Date(master): Wed May 22 04:07:02 UTC 2024 on atb-devel-224

commit b4be5718d3de3bc90d142cb53f79fe067d0a3e0a
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 2793ef3e1632c735f9caac015503aab06f53d543
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit e2a5fbf5cf2b65db77e7c5a859c896acca69f432
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 7f1e89488a7212832819380a93fe137a6fa28c37
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 37292f8a60f8fa82faa7bde4314919dcae6fb7ab
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 6ecc607edeeeb1877b5ecf02ba60d6c8799f583a
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit f5c8c212dcba48167d8ae8c555a5c4750cb763fd
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit f48699641cf95f1e2d197e0f8ea1ed4ce2c4fb41
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit d1efc396de4855a90c7dfd3d935028a21d780272
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 8cfebc36edcf5a4ba259d11c6e319aba303ea8ff
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 83f03513fd5221cb3bf914bd996c86f0840f34dd
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 888a785f476c64cd34a67149f69bd20f9b7749d8
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 2b2cc544725368e1922c3c71541c2b478a47586b
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit feff15fc88b548f9b59aef1427dd1fb5d72ef2a1
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@samba.org>

commit 52df4063871bb6b18e84e559a94fd05ebf33b012
Author: Stefan Metzmacher <me...@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 <me...@samba.org>
    Reviewed-by: Andrew Bartlett <abart...@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

Reply via email to