The branch, master has been updated via da7f056fb5d lib/ldb-samba: Remove unused ldb.set_opaque_integer() via d73c92a35dd dsdb: Remove calls to ldb.set_opaque_integer() via 416b6c5a03d lib/ldb-samba: Align py_ldb_set_opaque_integer() with pyldb_set_opaque() and use "unsigned long long" via 195c0e0d491 lib/ldb: Allocate opaque on ldb_ctx via b42043897a6 python/samba/provision: Ensure KDS root key is usable as soon as provision is complete via fb219d545bb selftest: Assert that the provision KDS root key is already valid for use from 9b0330ea3f5 pytest:samba-tool domain kds root-key: test with normal user
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit da7f056fb5d932ad4a302f1fab0ef886183f3b8f Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 4 14:45:42 2024 +1300 lib/ldb-samba: Remove unused ldb.set_opaque_integer() Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Tue Mar 5 03:55:33 UTC 2024 on atb-devel-224 commit d73c92a35dda1e20cd75b7061fc151234996d9b4 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 4 14:44:53 2024 +1300 dsdb: Remove calls to ldb.set_opaque_integer() This routine will shortly be removed, it is now replaced by an improved ldb.set_opaque() Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit 416b6c5a03d4fa9d55decc1de6a9ab409fa045f0 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 4 14:27:19 2024 +1300 lib/ldb-samba: Align py_ldb_set_opaque_integer() with pyldb_set_opaque() and use "unsigned long long" We need to change the internal types assumed in Samba for the opaque integers to "unsigned long long" as this is what ldb.set_opaque() will create, and we want to move to this interface rather than have a duplicate. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit 195c0e0d4912d37a8404e83e0e3357bb47b61e0d Author: Andrew Bartlett <abart...@samba.org> Date: Mon Mar 4 13:02:54 2024 +1300 lib/ldb: Allocate opaque on ldb_ctx Just in case this LDB is given away into the C code, that opaque must live as long as the LDB itself, not the python wrapper object. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit b42043897a6ebf52f70c5bdcdcfe6a18f8ad6fd8 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Mar 5 11:49:49 2024 +1300 python/samba/provision: Ensure KDS root key is usable as soon as provision is complete We do this by setting the start time to being 10 hours 5min earlier than now. Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> commit fb219d545bb3bd328200a3097b52594617fc246a Author: Andrew Bartlett <abart...@samba.org> Date: Tue Mar 5 12:38:06 2024 +1300 selftest: Assert that the provision KDS root key is already valid for use Signed-off-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Jo Sutton <josut...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: lib/ldb-samba/pyldb.c | 67 ------------------------ lib/ldb/pyldb.c | 6 +-- python/samba/join.py | 12 ++--- python/samba/provision/__init__.py | 20 +++++-- python/samba/tests/dsdb_quiet_provision_tests.py | 14 ++++- source4/dsdb/common/util.c | 14 ++--- source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 4 +- source4/dsdb/samdb/ldb_modules/rootdse.c | 13 +++-- source4/torture/drs/python/ridalloc_exop.py | 4 +- 9 files changed, 55 insertions(+), 99 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/ldb-samba/pyldb.c b/lib/ldb-samba/pyldb.c index 2241abc01df..8154679146b 100644 --- a/lib/ldb-samba/pyldb.c +++ b/lib/ldb-samba/pyldb.c @@ -91,71 +91,6 @@ static PyObject *py_ldb_set_credentials(PyObject *self, PyObject *args) Py_RETURN_NONE; } -/* XXX: This function really should be in libldb's pyldb.c */ -static PyObject *py_ldb_set_opaque_integer(PyObject *self, PyObject *args) -{ - int value; - int *old_val, *new_val; - char *py_opaque_name, *opaque_name_talloc; - struct ldb_context *ldb; - int ret; - TALLOC_CTX *tmp_ctx; - - if (!PyArg_ParseTuple(args, "si", &py_opaque_name, &value)) - return NULL; - - ldb = pyldb_Ldb_AS_LDBCONTEXT(self); - - /* see if we have a cached copy */ - old_val = (int *)ldb_get_opaque(ldb, py_opaque_name); - /* XXX: We shouldn't just blindly assume that the value that is - * already present has the size of an int and is not shared - * with other code that may rely on it not changing. - * JRV 20100403 */ - - if (old_val) { - *old_val = value; - Py_RETURN_NONE; - } - - tmp_ctx = talloc_new(ldb); - if (tmp_ctx == NULL) { - PyErr_NoMemory(); - return NULL; - } - - new_val = talloc(tmp_ctx, int); - if (new_val == NULL) { - talloc_free(tmp_ctx); - PyErr_NoMemory(); - return NULL; - } - - opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name); - if (opaque_name_talloc == NULL) { - talloc_free(tmp_ctx); - PyErr_NoMemory(); - return NULL; - } - - *new_val = value; - - /* cache the domain_sid in the ldb */ - ret = ldb_set_opaque(ldb, opaque_name_talloc, new_val); - - if (ret != LDB_SUCCESS) { - talloc_free(tmp_ctx); - PyErr_SetLdbError(py_ldb_error, ret, ldb); - return NULL; - } - - talloc_steal(ldb, new_val); - talloc_steal(ldb, opaque_name_talloc); - talloc_free(tmp_ctx); - - Py_RETURN_NONE; -} - static PyObject *py_ldb_set_utf8_casefold(PyObject *self, PyObject *Py_UNUSED(ignored)) { @@ -250,8 +185,6 @@ static PyMethodDef py_samba_ldb_methods[] = { { "set_credentials", (PyCFunction)py_ldb_set_credentials, METH_VARARGS, "set_credentials(credentials)\n" "Set credentials to use when connecting." }, - { "set_opaque_integer", (PyCFunction)py_ldb_set_opaque_integer, - METH_VARARGS, NULL }, { "set_utf8_casefold", (PyCFunction)py_ldb_set_utf8_casefold, METH_NOARGS, "set_utf8_casefold()\n" diff --git a/lib/ldb/pyldb.c b/lib/ldb/pyldb.c index 435f2477672..5d995243d44 100644 --- a/lib/ldb/pyldb.c +++ b/lib/ldb/pyldb.c @@ -2475,7 +2475,7 @@ static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args) b = is_true; } - opaque = talloc(self->mem_ctx, bool); + opaque = talloc(self->ldb_ctx, bool); if (opaque == NULL) { return PyErr_NoMemory(); } @@ -2488,7 +2488,7 @@ static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args) return NULL; } - opaque = talloc(self->mem_ctx, unsigned long long); + opaque = talloc(self->ldb_ctx, unsigned long long); if (opaque == NULL) { return PyErr_NoMemory(); } @@ -2501,7 +2501,7 @@ static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args) return NULL; } - opaque = talloc_strdup(self->mem_ctx, s); + opaque = talloc_strdup(self->ldb_ctx, s); if (opaque == NULL) { return PyErr_NoMemory(); } diff --git a/python/samba/join.py b/python/samba/join.py index 8b7e882a236..724dd6e258e 100644 --- a/python/samba/join.py +++ b/python/samba/join.py @@ -1096,11 +1096,11 @@ class DCJoinContext(object): # was sent, as we are processing all links in the # transaction_commit(). if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY: - ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, - 1) + ctx.local_samdb.set_opaque(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 1) ctx.local_samdb.transaction_commit() - ctx.local_samdb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, - 0) + ctx.local_samdb.set_opaque(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 0) ctx.logger.info("Committed SAM database") # A large replication may have caused our LDB connection to the @@ -1320,8 +1320,8 @@ class DCJoinContext(object): if ctx.RODC: print("Setting RODC invocationId") ctx.local_samdb.set_invocation_id(str(ctx.invocation_id)) - ctx.local_samdb.set_opaque_integer("domainFunctionality", - ctx.behavior_version) + ctx.local_samdb.set_opaque("domainFunctionality", + ctx.behavior_version) m = ldb.Message() m.dn = ldb.Dn(ctx.local_samdb, "%s" % ctx.ntds_dn) m["invocationId"] = ldb.MessageElement(ndr_pack(ctx.invocation_id), diff --git a/python/samba/provision/__init__.py b/python/samba/provision/__init__.py index c8731c4962f..80684c47522 100644 --- a/python/samba/provision/__init__.py +++ b/python/samba/provision/__init__.py @@ -73,9 +73,14 @@ from samba.dsdb import ( DS_DOMAIN_FUNCTION_2016, ENC_ALL_TYPES, ) +from samba.gkdi import ( + KEY_CYCLE_DURATION, + MAX_CLOCK_SKEW +) from samba.idmap import IDmapDB from samba.ms_display_specifiers import read_ms_ldif from samba.ntacls import setntacl, getntacl, dsacl2fsacl +from samba.nt_time import nt_now from samba.ndr import ndr_pack, ndr_unpack from samba.provision.backend import ( LDBBackend, @@ -1376,10 +1381,10 @@ def fill_samdb(samdb, lp, names, logger, policyguid, # These will be fixed into the database via the database # modifictions below, but we need them set from the start. - samdb.set_opaque_integer("domainFunctionality", domainFunctionality) - samdb.set_opaque_integer("forestFunctionality", forestFunctionality) - samdb.set_opaque_integer("domainControllerFunctionality", - domainControllerFunctionality) + samdb.set_opaque("domainFunctionality", domainFunctionality) + samdb.set_opaque("forestFunctionality", forestFunctionality) + samdb.set_opaque("domainControllerFunctionality", + domainControllerFunctionality) samdb.set_domain_sid(str(names.domainsid)) samdb.set_invocation_id(invocationid) @@ -2401,7 +2406,12 @@ def provision(logger, session_info, smbconf=None, if updates_allowed_overridden: lp.set("dsdb:schema update allowed", "no") - gkdi_root_key_dn = samdb.new_gkdi_root_key() + current_time = nt_now() + # We want the GKDI key to be instantly available for use + use_start_time = current_time \ + - KEY_CYCLE_DURATION - MAX_CLOCK_SKEW + gkdi_root_key_dn = samdb.new_gkdi_root_key(current_time=current_time, + use_start_time=use_start_time) logger.info("gkdi/gmsa root key added with guid " f"{gkdi_root_key_dn.get_rdn_value()}") diff --git a/python/samba/tests/dsdb_quiet_provision_tests.py b/python/samba/tests/dsdb_quiet_provision_tests.py index da642a7a94d..81ef3ceb74f 100644 --- a/python/samba/tests/dsdb_quiet_provision_tests.py +++ b/python/samba/tests/dsdb_quiet_provision_tests.py @@ -28,6 +28,11 @@ from samba.credentials import Credentials from samba.samdb import SamDB from samba.auth import system_session from samba.tests import TestCase +from samba.gkdi import ( + KEY_CYCLE_DURATION, + MAX_CLOCK_SKEW +) +from samba.nt_time import nt_now import ldb import samba @@ -48,12 +53,17 @@ class DsdbQuietProvisionTests(TestCase): def test_dsdb_dn_gkdi_gmsa_root_keys_exist(self): """In provision we set up a GKDI root key. - There should always be at least one. + There should always be at least one that is already valid """ + current_time = nt_now() + # We need the GKDI key to be already available for use + min_use_start_time = current_time \ + - KEY_CYCLE_DURATION - MAX_CLOCK_SKEW + dn = self.samdb.get_config_basedn() dn.add_child("CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services") res = self.samdb.search(dn, scope=ldb.SCOPE_SUBTREE, - expression="(objectClass = msKds-ProvRootKey)") + expression=f"(&(objectClass = msKds-ProvRootKey)(msKds-UseStartTime<={min_use_start_time}))") self.assertGreater(len(res), 0) diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index fff0abaedaa..d31d7d94f2d 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -4122,8 +4122,8 @@ const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn) */ int dsdb_functional_level(struct ldb_context *ldb) { - int *domainFunctionality = - talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int); + unsigned long long *domainFunctionality = + talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), unsigned long long); if (!domainFunctionality) { /* this is expected during initial provision */ DEBUG(4,(__location__ ": WARNING: domainFunctionality not setup\n")); @@ -4137,8 +4137,8 @@ int dsdb_functional_level(struct ldb_context *ldb) */ int dsdb_forest_functional_level(struct ldb_context *ldb) { - int *forestFunctionality = - talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), int); + unsigned long long *forestFunctionality = + talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), unsigned long long); if (!forestFunctionality) { DEBUG(0,(__location__ ": WARNING: forestFunctionality not setup\n")); return DS_DOMAIN_FUNCTION_2000; @@ -4151,8 +4151,8 @@ int dsdb_forest_functional_level(struct ldb_context *ldb) */ int dsdb_dc_functional_level(struct ldb_context *ldb) { - int *dcFunctionality = - talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), int); + unsigned long long *dcFunctionality = + talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), unsigned long long); if (!dcFunctionality) { /* this is expected during initial provision */ DEBUG(4,(__location__ ": WARNING: domainControllerFunctionality not setup\n")); @@ -4296,7 +4296,7 @@ int dsdb_check_and_update_fl(struct ldb_context *ldb_ctx, struct loadparm_contex * will not re-read the DB */ { - int *val = talloc(ldb_ctx, int); + unsigned long long *val = talloc(ldb_ctx, unsigned long long); if (!val) { TALLOC_FREE(frame); return LDB_ERR_OPERATIONS_ERROR; diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c index 7aec0063c96..57098f0a8b7 100644 --- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c +++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c @@ -7644,10 +7644,10 @@ static int replmd_allow_missing_target(struct ldb_module *module, * replication is completed, so failing now would just * trigger errors, rather than trigger a GET_TGT */ - int *finished_full_join_ptr = + unsigned long long *finished_full_join_ptr = talloc_get_type(ldb_get_opaque(ldb, DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME), - int); + unsigned long long); bool finished_full_join = finished_full_join_ptr && *finished_full_join_ptr; /* diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index d80d2af485c..7541a2cf376 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -234,7 +234,7 @@ static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *m const char * const *attrs = ac->req->op.search.attrs; const char **server_sasl = NULL; const struct dsdb_schema *schema; - int *val; + unsigned long long *val; struct ldb_control *edn_control; const char *dn_attrs[] = { "configurationNamingContext", @@ -452,7 +452,7 @@ static int rootdse_add_dynamic(struct rootdse_context *ac, struct ldb_message *m } if (do_attribute(attrs, "domainControllerFunctionality") - && (val = talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), int))) { + && (val = talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), unsigned long long))) { if (samdb_msg_add_int(ldb, msg, msg, "domainControllerFunctionality", *val) != LDB_SUCCESS) { @@ -1039,7 +1039,8 @@ static int rootdse_init(struct ldb_module *module) = ldb_msg_find_attr_as_int(res->msgs[0], "msDS-Behavior-Version", -1); if (domain_behaviour_version != -1) { - int *val = talloc(ldb, int); + unsigned long long *val + = talloc(ldb, unsigned long long); if (!val) { talloc_free(mem_ctx); return ldb_oom(ldb); @@ -1064,7 +1065,8 @@ static int rootdse_init(struct ldb_module *module) = ldb_msg_find_attr_as_int(res->msgs[0], "msDS-Behavior-Version", -1); if (forest_behaviour_version != -1) { - int *val = talloc(ldb, int); + unsigned long long *val + = talloc(ldb, unsigned long long); if (!val) { talloc_free(mem_ctx); return ldb_oom(ldb); @@ -1107,7 +1109,8 @@ static int rootdse_init(struct ldb_module *module) = ldb_msg_find_attr_as_int(res->msgs[0], "msDS-Behavior-Version", -1); if (domain_controller_behaviour_version != -1) { - int *val = talloc(ldb, int); + unsigned long long *val + = talloc(ldb, unsigned long long); if (!val) { talloc_free(mem_ctx); return ldb_oom(ldb); diff --git a/source4/torture/drs/python/ridalloc_exop.py b/source4/torture/drs/python/ridalloc_exop.py index ecd5cec6f4e..2ac64c05d3b 100644 --- a/source4/torture/drs/python/ridalloc_exop.py +++ b/source4/torture/drs/python/ridalloc_exop.py @@ -736,8 +736,8 @@ class DrsReplicaSyncTestCase(drs_base.DrsBaseTestCase): # simulates getting the delete in the replciation stream. new_ldb.deleteuser(test_user4) - new_ldb.set_opaque_integer(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, - 1) + new_ldb.set_opaque(dsdb.DSDB_FULL_JOIN_REPLICATION_COMPLETED_OPAQUE_NAME, + 1) # This should now work try: -- Samba Shared Repository