s4:dsdb Search for the schema with dsdb_module_search(), in schema_fsmo
[Samba/ekacnet.git] / source4 / dsdb / samdb / ldb_modules / schema_fsmo.c
blob2b6606c147a58371e572cbc2111df2ed46ff0d15
1 /*
2 Unix SMB/CIFS mplementation.
4 The module that handles the Schema FSMO Role Owner
5 checkings, it also loads the dsdb_schema.
7 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
8 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "ldb_module.h"
27 #include "dsdb/samdb/samdb.h"
28 #include "librpc/gen_ndr/ndr_misc.h"
29 #include "librpc/gen_ndr/ndr_drsuapi.h"
30 #include "librpc/gen_ndr/ndr_drsblobs.h"
31 #include "param/param.h"
32 #include "dsdb/samdb/ldb_modules/util.h"
34 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
35 const struct dsdb_schema *schema);
36 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
37 const struct dsdb_schema *schema);
38 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
39 const struct dsdb_schema *schema);
40 static int generate_extendedAttributeInfo(struct ldb_context *ldb, struct ldb_message *msg,
41 const struct dsdb_schema *schema);
42 static int generate_extendedClassInfo(struct ldb_context *ldb, struct ldb_message *msg,
43 const struct dsdb_schema *schema);
44 static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
45 const struct dsdb_schema *schema);
47 static const struct {
48 const char *attr;
49 int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
50 bool aggregate;
51 } generated_attrs[] = {
53 .attr = "objectClasses",
54 .fn = generate_objectClasses,
55 .aggregate = true,
58 .attr = "attributeTypes",
59 .fn = generate_attributeTypes,
60 .aggregate = true,
63 .attr = "dITContentRules",
64 .fn = generate_dITContentRules,
65 .aggregate = true,
68 .attr = "extendedAttributeInfo",
69 .fn = generate_extendedAttributeInfo,
70 .aggregate = true,
73 .attr = "extendedClassInfo",
74 .fn = generate_extendedClassInfo,
75 .aggregate = true,
78 .attr = "possibleInferiors",
79 .fn = generate_possibleInferiors,
80 .aggregate = false,
84 struct schema_fsmo_private_data {
85 struct ldb_dn *aggregate_dn;
88 struct schema_fsmo_search_data {
89 struct ldb_module *module;
90 struct ldb_request *req;
92 const struct dsdb_schema *schema;
96 Given an LDB module (pointing at the schema DB), and the DN, set the populated schema
99 static int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_module *module,
100 struct smb_iconv_convenience *iconv_convenience,
101 struct ldb_dn *schema_dn,
102 struct dsdb_schema **schema)
104 TALLOC_CTX *tmp_ctx;
105 char *error_string;
106 int ret;
107 struct ldb_context *ldb = ldb_module_get_ctx(module);
108 struct ldb_result *schema_res;
109 struct ldb_result *a_res;
110 struct ldb_result *c_res;
111 static const char *schema_attrs[] = {
112 "prefixMap",
113 "schemaInfo",
114 "fSMORoleOwner",
115 NULL
117 unsigned flags;
119 tmp_ctx = talloc_new(mem_ctx);
120 if (!tmp_ctx) {
121 ldb_oom(ldb);
122 return LDB_ERR_OPERATIONS_ERROR;
125 /* we don't want to trace the schema load */
126 flags = ldb_get_flags(ldb);
127 ldb_set_flags(ldb, flags & ~LDB_FLG_ENABLE_TRACING);
130 * setup the prefix mappings and schema info
132 ret = dsdb_module_search_dn(module, tmp_ctx, &schema_res,
133 schema_dn, schema_attrs);
134 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
135 goto failed;
136 } else if (ret != LDB_SUCCESS) {
137 ldb_asprintf_errstring(ldb,
138 "dsdb_schema: failed to search the schema head: %s",
139 ldb_errstring(ldb));
140 goto failed;
144 * load the attribute definitions
146 ret = dsdb_module_search(module, tmp_ctx, &a_res,
147 schema_dn, LDB_SCOPE_ONELEVEL, NULL,
148 "(objectClass=attributeSchema)");
149 if (ret != LDB_SUCCESS) {
150 ldb_asprintf_errstring(ldb,
151 "dsdb_schema: failed to search attributeSchema objects: %s",
152 ldb_errstring(ldb));
153 goto failed;
157 * load the objectClass definitions
159 ret = dsdb_module_search(module, tmp_ctx, &c_res,
160 schema_dn, LDB_SCOPE_ONELEVEL, NULL,
161 "(objectClass=classSchema)");
162 if (ret != LDB_SUCCESS) {
163 ldb_asprintf_errstring(ldb,
164 "dsdb_schema: failed to search attributeSchema objects: %s",
165 ldb_errstring(ldb));
166 goto failed;
169 ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb,
170 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
171 schema_res, a_res, c_res, schema, &error_string);
172 if (ret != LDB_SUCCESS) {
173 ldb_asprintf_errstring(ldb,
174 "dsdb_schema load failed: %s",
175 error_string);
176 goto failed;
178 talloc_steal(mem_ctx, *schema);
180 failed:
181 if (flags & LDB_FLG_ENABLE_TRACING) {
182 flags = ldb_get_flags(ldb);
183 ldb_set_flags(ldb, flags | LDB_FLG_ENABLE_TRACING);
185 talloc_free(tmp_ctx);
186 return ret;
190 static int schema_fsmo_init(struct ldb_module *module)
192 struct ldb_context *ldb;
193 TALLOC_CTX *mem_ctx;
194 struct ldb_dn *schema_dn;
195 struct dsdb_schema *schema;
196 int ret;
197 struct schema_fsmo_private_data *data;
199 ldb = ldb_module_get_ctx(module);
200 schema_dn = samdb_schema_dn(ldb);
201 if (!schema_dn) {
202 ldb_reset_err_string(ldb);
203 ldb_debug(ldb, LDB_DEBUG_WARNING,
204 "schema_fsmo_init: no schema dn present: (skip schema loading)\n");
205 return ldb_next_init(module);
208 data = talloc(module, struct schema_fsmo_private_data);
209 if (data == NULL) {
210 ldb_oom(ldb);
211 return LDB_ERR_OPERATIONS_ERROR;
214 /* Check to see if this is a result on the CN=Aggregate schema */
215 data->aggregate_dn = ldb_dn_copy(data, schema_dn);
216 if (!ldb_dn_add_child_fmt(data->aggregate_dn, "CN=Aggregate")) {
217 ldb_oom(ldb);
218 return LDB_ERR_OPERATIONS_ERROR;
221 ldb_module_set_private(module, data);
223 if (dsdb_get_schema(ldb)) {
224 return ldb_next_init(module);
227 mem_ctx = talloc_new(module);
228 if (!mem_ctx) {
229 ldb_oom(ldb);
230 return LDB_ERR_OPERATIONS_ERROR;
233 ret = dsdb_schema_from_schema_dn(mem_ctx, module,
234 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
235 schema_dn, &schema);
237 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
238 ldb_reset_err_string(ldb);
239 ldb_debug(ldb, LDB_DEBUG_WARNING,
240 "schema_fsmo_init: no schema head present: (skip schema loading)\n");
241 talloc_free(mem_ctx);
242 return ldb_next_init(module);
245 if (ret != LDB_SUCCESS) {
246 talloc_free(mem_ctx);
247 return ret;
250 /* dsdb_set_schema() steal schema into the ldb_context */
251 ret = dsdb_set_schema(ldb, schema);
252 if (ret != LDB_SUCCESS) {
253 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
254 "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
255 ret, ldb_strerror(ret));
256 talloc_free(mem_ctx);
257 return ret;
260 talloc_free(mem_ctx);
261 return ldb_next_init(module);
264 static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
266 struct ldb_context *ldb;
267 struct dsdb_schema *schema;
268 const struct ldb_val *attributeID = NULL;
269 const struct ldb_val *governsID = NULL;
270 const char *oid_attr = NULL;
271 const char *oid = NULL;
272 uint32_t id32;
273 WERROR status;
275 ldb = ldb_module_get_ctx(module);
277 /* special objects should always go through */
278 if (ldb_dn_is_special(req->op.add.message->dn)) {
279 return ldb_next_request(module, req);
282 /* replicated update should always go through */
283 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
284 return ldb_next_request(module, req);
287 schema = dsdb_get_schema(ldb);
288 if (!schema) {
289 return ldb_next_request(module, req);
292 if (!schema->fsmo.we_are_master) {
293 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
294 "schema_fsmo_add: we are not master: reject request\n");
295 return LDB_ERR_UNWILLING_TO_PERFORM;
298 attributeID = ldb_msg_find_ldb_val(req->op.add.message, "attributeID");
299 governsID = ldb_msg_find_ldb_val(req->op.add.message, "governsID");
301 if (attributeID) {
302 oid_attr = "attributeID";
303 oid = talloc_strndup(req, (const char *)attributeID->data, attributeID->length);
304 } else if (governsID) {
305 oid_attr = "governsID";
306 oid = talloc_strndup(req, (const char *)governsID->data, governsID->length);
307 } else {
308 return ldb_next_request(module, req);
311 if (!oid) {
312 ldb_oom(ldb);
313 return LDB_ERR_OPERATIONS_ERROR;
316 status = dsdb_map_oid2int(schema, oid, &id32);
317 if (W_ERROR_IS_OK(status)) {
318 return ldb_next_request(module, req);
319 } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
320 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
321 "schema_fsmo_add: failed to map %s[%s]: %s\n",
322 oid_attr, oid, win_errstr(status));
323 return LDB_ERR_UNWILLING_TO_PERFORM;
326 status = dsdb_create_prefix_mapping(ldb, schema, oid);
327 if (!W_ERROR_IS_OK(status)) {
328 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
329 "schema_fsmo_add: failed to create prefix mapping for %s[%s]: %s\n",
330 oid_attr, oid, win_errstr(status));
331 return LDB_ERR_UNWILLING_TO_PERFORM;
334 return ldb_next_request(module, req);
337 static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
339 struct ldb_context *ldb;
340 struct ldb_dn *schema_dn;
341 struct dsdb_schema *schema;
342 int ret;
343 TALLOC_CTX *mem_ctx;
345 ldb = ldb_module_get_ctx(module);
347 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
348 return ldb_next_request(module, req);
351 schema_dn = samdb_schema_dn(ldb);
352 if (!schema_dn) {
353 ldb_reset_err_string(ldb);
354 ldb_debug(ldb, LDB_DEBUG_WARNING,
355 "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
356 return ldb_next_request(module, req);
359 mem_ctx = talloc_new(module);
360 if (!mem_ctx) {
361 ldb_oom(ldb);
362 return LDB_ERR_OPERATIONS_ERROR;
365 ret = dsdb_schema_from_schema_dn(mem_ctx, module,
366 lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
367 schema_dn, &schema);
369 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
370 ldb_reset_err_string(ldb);
371 ldb_debug(ldb, LDB_DEBUG_WARNING,
372 "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
373 talloc_free(mem_ctx);
374 return ldb_next_request(module, req);
377 if (ret != LDB_SUCCESS) {
378 talloc_free(mem_ctx);
379 return ldb_next_request(module, req);
382 /* Replace the old schema*/
383 ret = dsdb_set_schema(ldb, schema);
384 if (ret != LDB_SUCCESS) {
385 ldb_debug_set(ldb, LDB_DEBUG_FATAL,
386 "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
387 ret, ldb_strerror(ret));
388 talloc_free(mem_ctx);
389 return ret;
392 dsdb_make_schema_global(ldb);
394 talloc_free(mem_ctx);
395 return LDB_SUCCESS;
398 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
399 const struct dsdb_schema *schema)
401 const struct dsdb_class *sclass;
402 int ret;
404 for (sclass = schema->classes; sclass; sclass = sclass->next) {
405 ret = ldb_msg_add_string(msg, "objectClasses", schema_class_to_description(msg, sclass));
406 if (ret != LDB_SUCCESS) {
407 return ret;
410 return LDB_SUCCESS;
412 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
413 const struct dsdb_schema *schema)
415 const struct dsdb_attribute *attribute;
416 int ret;
418 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
419 ret = ldb_msg_add_string(msg, "attributeTypes", schema_attribute_to_description(msg, attribute));
420 if (ret != LDB_SUCCESS) {
421 return ret;
424 return LDB_SUCCESS;
427 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
428 const struct dsdb_schema *schema)
430 const struct dsdb_class *sclass;
431 int ret;
433 for (sclass = schema->classes; sclass; sclass = sclass->next) {
434 if (sclass->auxiliaryClass || sclass->systemAuxiliaryClass) {
435 char *ditcontentrule = schema_class_to_dITContentRule(msg, sclass, schema);
436 if (!ditcontentrule) {
437 ldb_oom(ldb);
438 return LDB_ERR_OPERATIONS_ERROR;
440 ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
441 if (ret != LDB_SUCCESS) {
442 return ret;
446 return LDB_SUCCESS;
449 static int generate_extendedAttributeInfo(struct ldb_context *ldb,
450 struct ldb_message *msg,
451 const struct dsdb_schema *schema)
453 const struct dsdb_attribute *attribute;
454 int ret;
456 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
457 char *val = schema_attribute_to_extendedInfo(msg, attribute);
458 if (!val) {
459 ldb_oom(ldb);
460 return LDB_ERR_OPERATIONS_ERROR;
463 ret = ldb_msg_add_string(msg, "extendedAttributeInfo", val);
464 if (ret != LDB_SUCCESS) {
465 return ret;
469 return LDB_SUCCESS;
472 static int generate_extendedClassInfo(struct ldb_context *ldb,
473 struct ldb_message *msg,
474 const struct dsdb_schema *schema)
476 const struct dsdb_class *sclass;
477 int ret;
479 for (sclass = schema->classes; sclass; sclass = sclass->next) {
480 char *val = schema_class_to_extendedInfo(msg, sclass);
481 if (!val) {
482 ldb_oom(ldb);
483 return LDB_ERR_OPERATIONS_ERROR;
486 ret = ldb_msg_add_string(msg, "extendedClassInfo", val);
487 if (ret != LDB_SUCCESS) {
488 return ret;
492 return LDB_SUCCESS;
496 static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
497 const struct dsdb_schema *schema)
499 struct ldb_dn *dn = msg->dn;
500 int ret, i;
501 const char *first_component_name = ldb_dn_get_component_name(dn, 0);
502 const struct ldb_val *first_component_val;
503 const struct dsdb_class *schema_class;
504 const char **possibleInferiors;
506 if (strcasecmp(first_component_name, "cn") != 0) {
507 return LDB_SUCCESS;
510 first_component_val = ldb_dn_get_component_val(dn, 0);
512 schema_class = dsdb_class_by_cn_ldb_val(schema, first_component_val);
513 if (schema_class == NULL) {
514 return LDB_SUCCESS;
517 possibleInferiors = schema_class->possibleInferiors;
518 if (possibleInferiors == NULL) {
519 return LDB_SUCCESS;
522 for (i=0;possibleInferiors[i];i++) {
523 ret = ldb_msg_add_string(msg, "possibleInferiors", possibleInferiors[i]);
524 if (ret != LDB_SUCCESS) {
525 return ret;
529 return LDB_SUCCESS;
533 /* Add objectClasses, attributeTypes and dITContentRules from the
534 schema object (they are not stored in the database)
536 static int schema_fsmo_search_callback(struct ldb_request *req, struct ldb_reply *ares)
538 struct ldb_context *ldb;
539 struct schema_fsmo_search_data *ac;
540 struct schema_fsmo_private_data *mc;
541 int i, ret;
543 ac = talloc_get_type(req->context, struct schema_fsmo_search_data);
544 mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_fsmo_private_data);
545 ldb = ldb_module_get_ctx(ac->module);
547 if (!ares) {
548 return ldb_module_done(ac->req, NULL, NULL,
549 LDB_ERR_OPERATIONS_ERROR);
551 if (ares->error != LDB_SUCCESS) {
552 return ldb_module_done(ac->req, ares->controls,
553 ares->response, ares->error);
555 /* Only entries are interesting, and we handle the case of the parent seperatly */
557 switch (ares->type) {
558 case LDB_REPLY_ENTRY:
560 if (ldb_dn_compare(ares->message->dn, mc->aggregate_dn) == 0) {
561 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
562 if (generated_attrs[i].aggregate &&
563 ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
564 ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
565 if (ret != LDB_SUCCESS) {
566 return ret;
570 } else {
571 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
572 if (!generated_attrs[i].aggregate &&
573 ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
574 ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
575 if (ret != LDB_SUCCESS) {
576 return ret;
583 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
585 case LDB_REPLY_REFERRAL:
587 return ldb_module_send_referral(ac->req, ares->referral);
589 case LDB_REPLY_DONE:
591 return ldb_module_done(ac->req, ares->controls,
592 ares->response, ares->error);
595 return LDB_SUCCESS;
598 /* search */
599 static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req)
601 struct ldb_context *ldb = ldb_module_get_ctx(module);
602 int i, ret;
603 struct schema_fsmo_search_data *search_context;
604 struct ldb_request *down_req;
605 struct dsdb_schema *schema = dsdb_get_schema(ldb);
607 if (!schema || !ldb_module_get_private(module)) {
608 /* If there is no schema, there is little we can do */
609 return ldb_next_request(module, req);
611 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
612 if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
613 break;
616 if (i == ARRAY_SIZE(generated_attrs)) {
617 /* No request for a generated attr found, nothing to
618 * see here, move along... */
619 return ldb_next_request(module, req);
622 search_context = talloc(req, struct schema_fsmo_search_data);
623 if (!search_context) {
624 ldb_oom(ldb);
625 return LDB_ERR_OPERATIONS_ERROR;
628 search_context->module = module;
629 search_context->req = req;
630 search_context->schema = schema;
632 ret = ldb_build_search_req_ex(&down_req, ldb, search_context,
633 req->op.search.base,
634 req->op.search.scope,
635 req->op.search.tree,
636 req->op.search.attrs,
637 req->controls,
638 search_context, schema_fsmo_search_callback,
639 req);
640 if (ret != LDB_SUCCESS) {
641 return LDB_ERR_OPERATIONS_ERROR;
644 return ldb_next_request(module, down_req);
648 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
649 .name = "schema_fsmo",
650 .init_context = schema_fsmo_init,
651 .add = schema_fsmo_add,
652 .extended = schema_fsmo_extended,
653 .search = schema_fsmo_search