2 Samba4 module loading module
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 * Component: Samba4 module loading module
25 * Description: Implement a single 'module' in the ldb database,
26 * which loads the remaining modules based on 'choice of configuration' attributes
28 * This is to avoid forcing a reprovision of the ldb databases when we change the internal structure of the code
30 * Author: Andrew Bartlett
35 #include <ldb_errors.h>
36 #include <ldb_module.h>
37 #include "dsdb/samdb/ldb_modules/util.h"
38 #include "dsdb/samdb/samdb.h"
39 #include "librpc/ndr/libndr.h"
40 #include "auth/credentials/credentials.h"
41 #include "param/secrets.h"
42 #include "lib/ldb-samba/ldb_wrap.h"
44 static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx,
45 struct ldb_message **msg, struct ldb_request *parent)
48 static const char *rootdse_attrs[] = { "defaultNamingContext", "configurationNamingContext", "schemaNamingContext", NULL };
49 struct ldb_result *rootdse_res;
50 struct ldb_dn *rootdse_dn;
51 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
56 rootdse_dn = ldb_dn_new(tmp_ctx, ldb, "@ROOTDSE");
62 ret = dsdb_module_search_dn(module, tmp_ctx, &rootdse_res, rootdse_dn,
63 rootdse_attrs, DSDB_FLAG_NEXT_MODULE, parent);
64 if (ret != LDB_SUCCESS) {
69 talloc_steal(mem_ctx, rootdse_res->msgs);
70 *msg = rootdse_res->msgs[0];
77 static int prepare_modules_line(struct ldb_context *ldb,
79 const struct ldb_message *rootdse_msg,
80 struct ldb_message *msg, const char *backend_attr,
81 const char *backend_mod, const char **backend_mod_list)
84 const char **backend_full_list;
85 const char *backend_dn;
86 char *mod_list_string;
88 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
94 backend_dn = ldb_msg_find_attr_as_string(rootdse_msg, backend_attr, NULL);
96 ldb_asprintf_errstring(ldb,
98 "unable to read %s from %s:%s",
99 backend_attr, ldb_dn_get_linearized(rootdse_msg->dn),
101 return LDB_ERR_CONSTRAINT_VIOLATION;
108 char **b = str_list_make_single(tmp_ctx, backend_mod);
109 backend_full_list = discard_const_p(const char *, b);
111 char **b = str_list_make_empty(tmp_ctx);
112 backend_full_list = discard_const_p(const char *, b);
114 if (!backend_full_list) {
115 talloc_free(tmp_ctx);
119 backend_full_list = str_list_append_const(backend_full_list, backend_mod_list);
120 if (!backend_full_list) {
121 talloc_free(tmp_ctx);
125 mod_list_string = str_list_join(tmp_ctx, backend_full_list, ',');
127 /* str_list_append allocates on NULL */
128 talloc_free(backend_full_list);
130 if (!mod_list_string) {
131 talloc_free(tmp_ctx);
135 full_string = talloc_asprintf(tmp_ctx, "%s:%s", backend_dn, mod_list_string);
136 ret = ldb_msg_add_steal_string(msg, "modules", full_string);
137 talloc_free(tmp_ctx);
141 static bool check_required_features(struct ldb_message_element *el)
145 DATA_BLOB esf = data_blob_string_const(
146 SAMBA_ENCRYPTED_SECRETS_FEATURE);
147 DATA_BLOB lmdbl1 = data_blob_string_const(
148 SAMBA_LMDB_LEVEL_ONE_FEATURE);
149 for (k = 0; k < el->num_values; k++) {
150 if ((data_blob_cmp(&esf, &el->values[k]) != 0) &&
151 (data_blob_cmp(&lmdbl1, &el->values[k]) != 0)) {
159 static int samba_dsdb_init(struct ldb_module *module)
161 struct ldb_context *ldb = ldb_module_get_ctx(module);
162 int ret, lock_ret, len, i, j;
163 TALLOC_CTX *tmp_ctx = talloc_new(module);
164 struct ldb_result *res;
165 struct ldb_message *rootdse_msg = NULL, *partition_msg;
166 struct ldb_dn *samba_dsdb_dn, *partition_dn, *indexlist_dn;
167 struct ldb_module *backend_module, *module_chain;
168 const char **final_module_list, **reverse_module_list;
170 Add modules to the list to activate them by default
171 beware often order is important
173 Some Known ordering constraints:
174 - rootdse must be first, as it makes redirects from "" -> cn=rootdse
175 - extended_dn_in must be before objectclass.c, as it resolves the DN
176 - objectclass must be before password_hash and samldb since these LDB
177 modules require the expanded "objectClass" list
178 - objectclass must be before descriptor and acl, as both assume that
179 objectClass values are sorted
180 - objectclass_attrs must be behind operational in order to see all
181 attributes (the operational module protects and therefore
182 suppresses per default some important ones)
183 - partition must be last
184 - each partition has its own module list then
186 The list is presented here as a set of declarations to show the
187 stack visually - the code below then handles the creation of the list
188 based on the parameters loaded from the database.
190 static const char *modules_list1[] = {"resolve_oids",
196 "dsdb_paged_results",
204 /* extended_dn_in or extended_dn_in_openldap goes here */
205 static const char *modules_list1a[] = {"audit_log",
207 "tombstone_reanimate",
217 const char **link_modules;
218 static const char *tdb_modules_list[] = {
225 "unique_object_sids",
230 const char *extended_dn_module;
231 const char *extended_dn_module_ldb = "extended_dn_out_ldb";
232 const char *extended_dn_in_module = "extended_dn_in";
234 static const char *modules_list2[] = {"dns_notify",
240 const char **backend_modules;
241 static const char *samba_dsdb_attrs[] = { SAMBA_COMPATIBLE_FEATURES_ATTR,
242 SAMBA_REQUIRED_FEATURES_ATTR, NULL };
243 static const char *indexlist_attrs[] = { SAMBA_FEATURES_SUPPORTED_FLAG, NULL };
245 const char *current_supportedFeatures[] = {SAMBA_SORTED_LINKS_FEATURE};
251 ret = ldb_register_samba_handlers(ldb);
252 if (ret != LDB_SUCCESS) {
253 talloc_free(tmp_ctx);
257 samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
258 if (!samba_dsdb_dn) {
259 talloc_free(tmp_ctx);
263 indexlist_dn = ldb_dn_new(tmp_ctx, ldb, "@INDEXLIST");
264 if (!samba_dsdb_dn) {
265 talloc_free(tmp_ctx);
269 partition_dn = ldb_dn_new(tmp_ctx, ldb, DSDB_PARTITION_DN);
271 talloc_free(tmp_ctx);
275 #define CHECK_LDB_RET(check_ret) \
277 if (check_ret != LDB_SUCCESS) { \
278 talloc_free(tmp_ctx); \
283 ret = dsdb_module_search_dn(module, tmp_ctx, &res, samba_dsdb_dn,
284 samba_dsdb_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
285 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
286 /* do nothing, a very old db being upgraded */
287 } else if (ret == LDB_SUCCESS) {
288 struct ldb_message_element *requiredFeatures;
289 struct ldb_message_element *old_compatibleFeatures;
291 requiredFeatures = ldb_msg_find_element(res->msgs[0], SAMBA_REQUIRED_FEATURES_ATTR);
292 if (!check_required_features(requiredFeatures)) {
295 "This Samba database was created with "
296 "a newer Samba version and is marked "
297 "with extra requiredFeatures in "
298 "@SAMBA_DSDB. This database can not "
299 "safely be read by this Samba version");
300 return LDB_ERR_OPERATIONS_ERROR;
303 old_compatibleFeatures = ldb_msg_find_element(res->msgs[0],
304 SAMBA_COMPATIBLE_FEATURES_ATTR);
306 if (old_compatibleFeatures) {
307 struct ldb_message *features_msg;
308 struct ldb_message_element *features_el;
309 int samba_options_supported = 0;
310 ret = dsdb_module_search_dn(module, tmp_ctx, &res,
313 DSDB_FLAG_NEXT_MODULE, NULL);
314 if (ret == LDB_SUCCESS) {
315 samba_options_supported
316 = ldb_msg_find_attr_as_int(res->msgs[0],
317 SAMBA_FEATURES_SUPPORTED_FLAG,
320 } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
322 * If we don't have @INDEXLIST yet, then we
323 * are so early in set-up that we know this is
324 * a blank DB, so no need to wripe out old
327 samba_options_supported = 1;
330 features_msg = ldb_msg_new(res);
331 if (features_msg == NULL) {
332 return ldb_module_operr(module);
334 features_msg->dn = samba_dsdb_dn;
336 ret = ldb_msg_add_empty(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
337 LDB_FLAG_MOD_DELETE, &features_el);
338 if (ret != LDB_SUCCESS) {
342 if (samba_options_supported == 1) {
344 old_compatibleFeatures && i < old_compatibleFeatures->num_values;
347 j < ARRAY_SIZE(current_supportedFeatures); j++) {
348 if (strcmp((char *)old_compatibleFeatures->values[i].data,
349 current_supportedFeatures[j]) == 0) {
353 if (j == ARRAY_SIZE(current_supportedFeatures)) {
355 * Add to list of features to remove
356 * (rather than all features)
358 ret = ldb_msg_add_value(features_msg, SAMBA_COMPATIBLE_FEATURES_ATTR,
359 &old_compatibleFeatures->values[i],
361 if (ret != LDB_SUCCESS) {
367 if (features_el->num_values > 0) {
369 ret = ldb_next_start_trans(module);
370 if (ret != LDB_SUCCESS) {
373 ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
374 if (ret != LDB_SUCCESS) {
375 ldb_next_del_trans(module);
378 ret = ldb_next_end_trans(module);
379 if (ret != LDB_SUCCESS) {
385 ret = ldb_next_start_trans(module);
386 if (ret != LDB_SUCCESS) {
389 ret = dsdb_module_modify(module, features_msg, DSDB_FLAG_NEXT_MODULE, NULL);
390 if (ret != LDB_SUCCESS) {
391 ldb_next_del_trans(module);
394 ret = ldb_next_end_trans(module);
395 if (ret != LDB_SUCCESS) {
402 talloc_free(tmp_ctx);
406 backend_modules = NULL;
407 extended_dn_module = extended_dn_module_ldb;
408 link_modules = tdb_modules_list;
410 #define CHECK_MODULE_LIST \
412 if (!final_module_list) { \
413 talloc_free(tmp_ctx); \
414 return ldb_oom(ldb); \
418 final_module_list = str_list_copy_const(tmp_ctx, modules_list1);
421 final_module_list = str_list_add_const(final_module_list, extended_dn_in_module);
424 final_module_list = str_list_append_const(final_module_list, modules_list1a);
427 final_module_list = str_list_append_const(final_module_list, link_modules);
430 final_module_list = str_list_add_const(final_module_list, extended_dn_module);
433 final_module_list = str_list_append_const(final_module_list, modules_list2);
437 ret = read_at_rootdse_record(ldb, module, tmp_ctx, &rootdse_msg, NULL);
440 partition_msg = ldb_msg_new(tmp_ctx);
441 partition_msg->dn = ldb_dn_new(partition_msg, ldb, "@" DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME);
443 ret = prepare_modules_line(ldb, tmp_ctx,
445 partition_msg, "schemaNamingContext",
446 "schema_data", backend_modules);
449 ret = prepare_modules_line(ldb, tmp_ctx,
452 NULL, backend_modules);
455 /* This opaque is also used by the gMSA code to confirm that it has local DB access */
456 ret = ldb_set_opaque(ldb, DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME, partition_msg);
459 talloc_steal(ldb, partition_msg);
461 /* Now prepare the module chain. Oddly, we must give it to
462 * ldb_module_load_list in REVERSE */
463 for (len = 0; final_module_list[len]; len++) { /* noop */};
465 reverse_module_list = talloc_array(tmp_ctx, const char *, len+1);
466 if (!reverse_module_list) {
467 talloc_free(tmp_ctx);
470 for (i=0; i < len; i++) {
471 reverse_module_list[i] = final_module_list[(len - 1) - i];
473 reverse_module_list[i] = NULL;
475 /* The backend (at least until the partitions module
476 * reconfigures things) is the next module in the currently
478 backend_module = ldb_module_next(module);
479 ret = ldb_module_load_list(ldb, reverse_module_list, backend_module, &module_chain);
482 talloc_free(tmp_ctx);
483 /* Set this as the 'next' module, so that we effectively append it to
485 ldb_module_set_next(module, module_chain);
487 ret = ldb_next_read_lock(module);
488 if (ret != LDB_SUCCESS) {
492 ret = ldb_next_init(module);
494 lock_ret = ldb_next_read_unlock(module);
496 if (lock_ret != LDB_SUCCESS) {
503 static const struct ldb_module_ops ldb_samba_dsdb_module_ops = {
504 .name = "samba_dsdb",
505 .init_context = samba_dsdb_init,
508 static struct ldb_message *dsdb_flags_ignore_fixup(TALLOC_CTX *mem_ctx,
509 const struct ldb_message *_msg)
511 struct ldb_message *msg = NULL;
514 /* we have to copy the message as the caller might have it as a const */
515 msg = ldb_msg_copy_shallow(mem_ctx, _msg);
520 for (i=0; i < msg->num_elements;) {
521 struct ldb_message_element *e = &msg->elements[i];
523 if (!(e->flags & DSDB_FLAG_INTERNAL_FORCE_META_DATA)) {
528 e->flags &= ~DSDB_FLAG_INTERNAL_FORCE_META_DATA;
530 if (e->num_values != 0) {
535 ldb_msg_remove_element(msg, e);
541 static int dsdb_flags_ignore_add(struct ldb_module *module, struct ldb_request *req)
543 struct ldb_context *ldb = ldb_module_get_ctx(module);
544 struct ldb_request *down_req = NULL;
545 struct ldb_message *msg = NULL;
548 msg = dsdb_flags_ignore_fixup(req, req->op.add.message);
550 return ldb_module_oom(module);
553 ret = ldb_build_add_req(&down_req, ldb, req,
556 req, dsdb_next_callback,
558 LDB_REQ_SET_LOCATION(down_req);
559 if (ret != LDB_SUCCESS) {
563 /* go on with the call chain */
564 return ldb_next_request(module, down_req);
567 static int dsdb_flags_ignore_modify(struct ldb_module *module, struct ldb_request *req)
569 struct ldb_context *ldb = ldb_module_get_ctx(module);
570 struct ldb_request *down_req = NULL;
571 struct ldb_message *msg = NULL;
574 msg = dsdb_flags_ignore_fixup(req, req->op.mod.message);
576 return ldb_module_oom(module);
579 ret = ldb_build_mod_req(&down_req, ldb, req,
582 req, dsdb_next_callback,
584 LDB_REQ_SET_LOCATION(down_req);
585 if (ret != LDB_SUCCESS) {
589 /* go on with the call chain */
590 return ldb_next_request(module, down_req);
593 static const struct ldb_module_ops ldb_dsdb_flags_ignore_module_ops = {
594 .name = "dsdb_flags_ignore",
595 .add = dsdb_flags_ignore_add,
596 .modify = dsdb_flags_ignore_modify,
599 int ldb_samba_dsdb_module_init(const char *version)
602 LDB_MODULE_CHECK_VERSION(version);
603 ret = ldb_register_module(&ldb_samba_dsdb_module_ops);
604 if (ret != LDB_SUCCESS) {
607 ret = ldb_register_module(&ldb_dsdb_flags_ignore_module_ops);
608 if (ret != LDB_SUCCESS) {