From: Stefan Metzmacher Date: Fri, 15 Mar 2024 15:11:10 +0000 (+0100) Subject: s4:libnet_export_keytab: add only_current_keys option X-Git-Tag: tdb-1.4.11~632 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e2a5fbf5cf2b65db77e7c5a859c896acca69f432;p=thirdparty%2Fsamba.git 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 Reviewed-by: Andrew Bartlett --- diff --git a/python/samba/tests/dckeytab.py b/python/samba/tests/dckeytab.py index 31139c0360f..7e47ab48898 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,7 +279,7 @@ 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 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/source4/auth/kerberos/srv_keytab.c b/source4/auth/kerberos/srv_keytab.c index a2f0d172e02..875d06971cc 100644 --- a/source4/auth/kerberos/srv_keytab.c +++ b/source4/auth/kerberos/srv_keytab.c @@ -231,6 +231,7 @@ NTSTATUS smb_krb5_fill_keytab_gmsa_keys(TALLOC_CTX *mem_ctx, krb5_principal principal, struct ldb_context *samdb, struct ldb_dn *dn, + bool include_historic_keys, const char **error_string) { const char *gmsa_attrs[] = { @@ -402,7 +403,7 @@ NTSTATUS smb_krb5_fill_keytab_gmsa_keys(TALLOC_CTX *mem_ctx, &principal, context, keytab, - true, + include_historic_keys, error_string); if (ret) { *error_string = talloc_asprintf(mem_ctx, diff --git a/source4/libnet/libnet_export_keytab.c b/source4/libnet/libnet_export_keytab.c index 69b47c8834f..68912285e3b 100644 --- a/source4/libnet/libnet_export_keytab.c +++ b/source4/libnet/libnet_export_keytab.c @@ -36,6 +36,7 @@ static NTSTATUS sdb_kt_copy(TALLOC_CTX *mem_ctx, const char *keytab_name, const char *principal, bool keep_stale_entries, + bool include_historic_keys, const char **error_string) { struct sdb_entry sentry = {}; @@ -148,6 +149,7 @@ static NTSTATUS sdb_kt_copy(TALLOC_CTX *mem_ctx, sentry.principal, db_ctx->samdb, dn, + include_historic_keys, error_string); if (NT_STATUS_IS_OK(status)) { keys_exported = true; @@ -199,6 +201,90 @@ static NTSTATUS sdb_kt_copy(TALLOC_CTX *mem_ctx, continue; } + code = krb5_kt_add_entry(context, keytab, &kt_entry); + if (code != 0) { + status = NT_STATUS_UNSUCCESSFUL; + *error_string = smb_get_krb5_error_message(context, + code, + mem_ctx); + DEBUG(0, ("smb_krb5_kt_add_entry failed code=%d, error = %s\n", + code, *error_string)); + goto done; + } + keys_exported = true; + } + kt_entry.vno -= 1; + for (i = 0; include_historic_keys && i < sentry.old_keys.len; i++) { + struct sdb_key *s = &(sentry.old_keys.val[i]); + krb5_keyblock *keyp; + bool found; + + keyp = KRB5_KT_KEY(&kt_entry); + + *keyp = s->key; + + code = smb_krb5_is_exact_entry_in_keytab(mem_ctx, + context, + keytab, + &kt_entry, + &found, + error_string); + if (code != 0) { + status = NT_STATUS_UNSUCCESSFUL; + *error_string = smb_get_krb5_error_message(context, + code, + mem_ctx); + DEBUG(0, ("smb_krb5_is_exact_entry_in_keytab failed code=%d, error = %s\n", + code, *error_string)); + goto done; + } + + if (found) { + continue; + } + + code = krb5_kt_add_entry(context, keytab, &kt_entry); + if (code != 0) { + status = NT_STATUS_UNSUCCESSFUL; + *error_string = smb_get_krb5_error_message(context, + code, + mem_ctx); + DEBUG(0, ("smb_krb5_kt_add_entry failed code=%d, error = %s\n", + code, *error_string)); + goto done; + } + keys_exported = true; + } + kt_entry.vno -= 1; + for (i = 0; include_historic_keys && i < sentry.older_keys.len; i++) { + struct sdb_key *s = &(sentry.older_keys.val[i]); + krb5_keyblock *keyp; + bool found; + + keyp = KRB5_KT_KEY(&kt_entry); + + *keyp = s->key; + + code = smb_krb5_is_exact_entry_in_keytab(mem_ctx, + context, + keytab, + &kt_entry, + &found, + error_string); + if (code != 0) { + status = NT_STATUS_UNSUCCESSFUL; + *error_string = smb_get_krb5_error_message(context, + code, + mem_ctx); + DEBUG(0, ("smb_krb5_is_exact_entry_in_keytab failed code=%d, error = %s\n", + code, *error_string)); + goto done; + } + + if (found) { + continue; + } + code = krb5_kt_add_entry(context, keytab, &kt_entry); if (code != 0) { status = NT_STATUS_UNSUCCESSFUL; @@ -329,6 +415,7 @@ NTSTATUS libnet_export_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, s r->in.keytab_name, r->in.principal, keep_stale_entries, + !r->in.only_current_keys, &error_string); talloc_free(db_ctx); diff --git a/source4/libnet/libnet_export_keytab.h b/source4/libnet/libnet_export_keytab.h index 117d2121806..706e88c2e20 100644 --- a/source4/libnet/libnet_export_keytab.h +++ b/source4/libnet/libnet_export_keytab.h @@ -25,6 +25,7 @@ struct libnet_export_keytab { const char *principal; struct ldb_context *samdb; bool keep_stale_entries; + bool only_current_keys; } in; struct { const char *error_string; diff --git a/source4/libnet/py_net_dckeytab.c b/source4/libnet/py_net_dckeytab.c index 39deb5d3601..efdecf68be4 100644 --- a/source4/libnet/py_net_dckeytab.c +++ b/source4/libnet/py_net_dckeytab.c @@ -31,13 +31,14 @@ static PyObject *py_net_export_keytab(py_net_Object *self, PyObject *args, PyObject *kwargs) { - struct libnet_export_keytab r; + struct libnet_export_keytab r = { .in = { .principal = NULL, }}; PyObject *py_samdb = NULL; TALLOC_CTX *mem_ctx; const char *kwnames[] = { "keytab", "samdb", "principal", "keep_stale_entries", + "only_current_keys", NULL }; NTSTATUS status; /* @@ -45,18 +46,19 @@ static PyObject *py_net_export_keytab(py_net_Object *self, PyObject *args, PyObj * PyArg_ParseTupleAndKeywords() */ int keep_stale_entries = false; + int only_current_keys = false; - r.in.principal = NULL; - - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Ozp:export_keytab", discard_const_p(char *, kwnames), + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Ozpp:export_keytab", discard_const_p(char *, kwnames), &r.in.keytab_name, &py_samdb, &r.in.principal, - &keep_stale_entries)) { + &keep_stale_entries, + &only_current_keys)) { return NULL; } r.in.keep_stale_entries = keep_stale_entries; + r.in.only_current_keys = only_current_keys; if (py_samdb == NULL) { r.in.samdb = NULL;