kerberos: Remove un-used event context argument from smb_krb5_init_context()
[Samba.git] / source4 / dsdb / samdb / ldb_modules / schema_data.c
blob996b1f2238618964f5449a02d8832cf635530051
1 /*
2 Unix SMB/CIFS mplementation.
4 The module that handles the Schema checkings and dynamic attributes
6 Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "ldb_module.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "librpc/gen_ndr/ndr_misc.h"
28 #include "librpc/gen_ndr/ndr_drsuapi.h"
29 #include "librpc/gen_ndr/ndr_drsblobs.h"
30 #include "param/param.h"
31 #include "dsdb/samdb/ldb_modules/util.h"
33 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
34 const struct dsdb_schema *schema);
35 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
36 const struct dsdb_schema *schema);
37 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
38 const struct dsdb_schema *schema);
39 static int generate_extendedAttributeInfo(struct ldb_context *ldb, struct ldb_message *msg,
40 const struct dsdb_schema *schema);
41 static int generate_extendedClassInfo(struct ldb_context *ldb, struct ldb_message *msg,
42 const struct dsdb_schema *schema);
43 static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
44 const struct dsdb_schema *schema);
46 static const struct {
47 const char *attr;
48 int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
49 bool aggregate;
50 } generated_attrs[] = {
52 .attr = "objectClasses",
53 .fn = generate_objectClasses,
54 .aggregate = true,
57 .attr = "attributeTypes",
58 .fn = generate_attributeTypes,
59 .aggregate = true,
62 .attr = "dITContentRules",
63 .fn = generate_dITContentRules,
64 .aggregate = true,
67 .attr = "extendedAttributeInfo",
68 .fn = generate_extendedAttributeInfo,
69 .aggregate = true,
72 .attr = "extendedClassInfo",
73 .fn = generate_extendedClassInfo,
74 .aggregate = true,
77 .attr = "possibleInferiors",
78 .fn = generate_possibleInferiors,
79 .aggregate = false,
83 struct schema_data_private_data {
84 struct ldb_dn *aggregate_dn;
85 struct ldb_dn *schema_dn;
88 struct schema_data_search_data {
89 struct ldb_module *module;
90 struct ldb_request *req;
92 const struct dsdb_schema *schema;
95 static int schema_data_init(struct ldb_module *module)
97 struct ldb_context *ldb;
98 struct ldb_dn *schema_dn;
99 int ret;
100 struct schema_data_private_data *data;
102 ret = ldb_next_init(module);
103 if (ret != LDB_SUCCESS) {
104 return ret;
107 ldb = ldb_module_get_ctx(module);
108 schema_dn = ldb_get_schema_basedn(ldb);
109 if (!schema_dn) {
110 ldb_reset_err_string(ldb);
111 ldb_debug(ldb, LDB_DEBUG_WARNING,
112 "schema_data_init: no schema dn present: (skip schema loading)\n");
113 return LDB_SUCCESS;
116 data = talloc(module, struct schema_data_private_data);
117 if (data == NULL) {
118 return ldb_oom(ldb);
121 data->schema_dn = schema_dn;
123 /* Used to check to see if this is a result on the CN=Aggregate schema */
124 data->aggregate_dn = samdb_aggregate_schema_dn(ldb, data);
125 if (!data->aggregate_dn) {
126 ldb_asprintf_errstring(ldb, "schema_data_init: Could not build aggregate schema DN for schema in %s", ldb_dn_get_linearized(schema_dn));
127 return LDB_ERR_OPERATIONS_ERROR;
130 ldb_module_set_private(module, data);
131 return LDB_SUCCESS;
134 static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
136 struct ldb_context *ldb;
137 struct dsdb_schema *schema;
138 const struct ldb_val *attributeID = NULL;
139 const struct ldb_val *governsID = NULL;
140 const char *oid_attr = NULL;
141 const char *oid = NULL;
142 struct ldb_dn *parent_dn = NULL;
143 int cmp;
144 WERROR status;
145 bool rodc = false;
146 int ret;
147 struct schema_data_private_data *mc;
148 mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
150 ldb = ldb_module_get_ctx(module);
152 /* special objects should always go through */
153 if (ldb_dn_is_special(req->op.add.message->dn)) {
154 return ldb_next_request(module, req);
157 /* replicated update should always go through */
158 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
159 return ldb_next_request(module, req);
162 schema = dsdb_get_schema(ldb, req);
163 if (!schema) {
164 return ldb_next_request(module, req);
167 ret = samdb_rodc(ldb, &rodc);
168 if (ret != LDB_SUCCESS) {
169 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
172 if (!schema->fsmo.we_are_master && !rodc) {
173 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
174 "schema_data_add: we are not master: reject request\n");
175 return LDB_ERR_UNWILLING_TO_PERFORM;
178 if (!schema->fsmo.update_allowed && !rodc) {
179 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
180 "schema_data_add: updates are not allowed: reject request\n");
181 return LDB_ERR_UNWILLING_TO_PERFORM;
184 if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
186 * the provision code needs to create
187 * the schema root object.
189 cmp = ldb_dn_compare(req->op.add.message->dn, mc->schema_dn);
190 if (cmp == 0) {
191 return ldb_next_request(module, req);
195 parent_dn = ldb_dn_get_parent(req, req->op.add.message->dn);
196 if (!parent_dn) {
197 return ldb_oom(ldb);
200 cmp = ldb_dn_compare(parent_dn, mc->schema_dn);
201 if (cmp != 0) {
202 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
203 "schema_data_add: no direct child :%s\n",
204 ldb_dn_get_linearized(req->op.add.message->dn));
205 return LDB_ERR_UNWILLING_TO_PERFORM;
208 attributeID = ldb_msg_find_ldb_val(req->op.add.message, "attributeID");
209 governsID = ldb_msg_find_ldb_val(req->op.add.message, "governsID");
211 if (attributeID) {
212 oid_attr = "attributeID";
213 oid = talloc_strndup(req, (const char *)attributeID->data, attributeID->length);
214 } else if (governsID) {
215 oid_attr = "governsID";
216 oid = talloc_strndup(req, (const char *)governsID->data, governsID->length);
217 } else {
218 return ldb_next_request(module, req);
221 if (!oid) {
222 return ldb_oom(ldb);
225 status = dsdb_schema_pfm_find_oid(schema->prefixmap, oid, NULL);
226 if (!W_ERROR_IS_OK(status)) {
227 /* check for internal errors */
228 if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
229 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
230 "schema_data_add: failed to map %s[%s]: %s\n",
231 oid_attr, oid, win_errstr(status));
232 return LDB_ERR_UNWILLING_TO_PERFORM;
235 /* Update prefixMap and save it */
236 status = dsdb_create_prefix_mapping(ldb, schema, oid);
237 if (!W_ERROR_IS_OK(status)) {
238 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
239 "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
240 oid_attr, oid, win_errstr(status));
241 return LDB_ERR_UNWILLING_TO_PERFORM;
245 return ldb_next_request(module, req);
248 static int schema_data_modify(struct ldb_module *module, struct ldb_request *req)
250 struct ldb_context *ldb;
251 struct dsdb_schema *schema;
252 int cmp;
253 bool rodc = false;
254 int ret;
255 struct ldb_control *sd_propagation_control;
256 struct schema_data_private_data *mc;
257 mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
259 ldb = ldb_module_get_ctx(module);
261 /* special objects should always go through */
262 if (ldb_dn_is_special(req->op.mod.message->dn)) {
263 return ldb_next_request(module, req);
266 /* replicated update should always go through */
267 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
268 return ldb_next_request(module, req);
271 /* dbcheck should be able to fix things */
272 if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
273 return ldb_next_request(module, req);
276 sd_propagation_control = ldb_request_get_control(req,
277 DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
278 if (sd_propagation_control != NULL) {
279 if (req->op.mod.message->num_elements != 1) {
280 return ldb_module_operr(module);
282 ret = strcmp(req->op.mod.message->elements[0].name,
283 "nTSecurityDescriptor");
284 if (ret != 0) {
285 return ldb_module_operr(module);
288 return ldb_next_request(module, req);
291 schema = dsdb_get_schema(ldb, req);
292 if (!schema) {
293 return ldb_next_request(module, req);
296 cmp = ldb_dn_compare(req->op.mod.message->dn, mc->schema_dn);
297 if (cmp == 0) {
298 static const char * const constrained_attrs[] = {
299 "schemaInfo",
300 "prefixMap",
301 "msDs-Schema-Extensions",
302 "msDS-IntId",
303 NULL
305 size_t i;
306 struct ldb_message_element *el;
308 if (ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID)) {
309 return ldb_next_request(module, req);
312 for (i=0; constrained_attrs[i]; i++) {
313 el = ldb_msg_find_element(req->op.mod.message,
314 constrained_attrs[i]);
315 if (el == NULL) {
316 continue;
319 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
320 "schema_data_modify: reject update "
321 "of attribute[%s]\n",
322 constrained_attrs[i]);
323 return LDB_ERR_CONSTRAINT_VIOLATION;
326 return ldb_next_request(module, req);
329 ret = samdb_rodc(ldb, &rodc);
330 if (ret != LDB_SUCCESS) {
331 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
334 if (!schema->fsmo.we_are_master && !rodc) {
335 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
336 "schema_data_modify: we are not master: reject request\n");
337 return LDB_ERR_UNWILLING_TO_PERFORM;
340 if (!schema->fsmo.update_allowed && !rodc) {
341 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
342 "schema_data_modify: updates are not allowed: reject request\n");
343 return LDB_ERR_UNWILLING_TO_PERFORM;
346 return ldb_next_request(module, req);
349 static int schema_data_del(struct ldb_module *module, struct ldb_request *req)
351 struct ldb_context *ldb;
352 struct dsdb_schema *schema;
353 bool rodc = false;
354 int ret;
356 ldb = ldb_module_get_ctx(module);
358 /* special objects should always go through */
359 if (ldb_dn_is_special(req->op.del.dn)) {
360 return ldb_next_request(module, req);
363 /* replicated update should always go through */
364 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
365 return ldb_next_request(module, req);
368 /* dbcheck should be able to fix things */
369 if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
370 return ldb_next_request(module, req);
373 schema = dsdb_get_schema(ldb, req);
374 if (!schema) {
375 return ldb_next_request(module, req);
378 ret = samdb_rodc(ldb, &rodc);
379 if (ret != LDB_SUCCESS) {
380 DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
383 if (!schema->fsmo.we_are_master && !rodc) {
384 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
385 "schema_data_modify: we are not master: reject request\n");
386 return LDB_ERR_UNWILLING_TO_PERFORM;
390 * normaly the DACL will prevent delete
391 * with LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
392 * above us.
394 ldb_debug_set(ldb, LDB_DEBUG_ERROR,
395 "schema_data_del: delete is not allowed in the schema\n");
396 return LDB_ERR_UNWILLING_TO_PERFORM;
399 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
400 const struct dsdb_schema *schema)
402 const struct dsdb_class *sclass;
403 int ret;
405 for (sclass = schema->classes; sclass; sclass = sclass->next) {
406 char *v = schema_class_to_description(msg, sclass);
407 if (v == NULL) {
408 return ldb_oom(ldb);
410 ret = ldb_msg_add_steal_string(msg, "objectClasses", v);
411 if (ret != LDB_SUCCESS) {
412 return ret;
415 return LDB_SUCCESS;
417 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
418 const struct dsdb_schema *schema)
420 const struct dsdb_attribute *attribute;
421 int ret;
423 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
424 char *v = schema_attribute_to_description(msg, attribute);
425 if (v == NULL) {
426 return ldb_oom(ldb);
428 ret = ldb_msg_add_steal_string(msg, "attributeTypes", v);
429 if (ret != LDB_SUCCESS) {
430 return ret;
433 return LDB_SUCCESS;
436 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
437 const struct dsdb_schema *schema)
439 const struct dsdb_class *sclass;
440 int ret;
442 for (sclass = schema->classes; sclass; sclass = sclass->next) {
443 if (sclass->auxiliaryClass || sclass->systemAuxiliaryClass) {
444 char *ditcontentrule = schema_class_to_dITContentRule(msg, sclass, schema);
445 if (!ditcontentrule) {
446 return ldb_oom(ldb);
448 ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
449 if (ret != LDB_SUCCESS) {
450 return ret;
454 return LDB_SUCCESS;
457 static int generate_extendedAttributeInfo(struct ldb_context *ldb,
458 struct ldb_message *msg,
459 const struct dsdb_schema *schema)
461 const struct dsdb_attribute *attribute;
462 int ret;
464 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
465 char *val = schema_attribute_to_extendedInfo(msg, attribute);
466 if (!val) {
467 return ldb_oom(ldb);
470 ret = ldb_msg_add_steal_string(msg, "extendedAttributeInfo", val);
471 if (ret != LDB_SUCCESS) {
472 return ret;
476 return LDB_SUCCESS;
479 static int generate_extendedClassInfo(struct ldb_context *ldb,
480 struct ldb_message *msg,
481 const struct dsdb_schema *schema)
483 const struct dsdb_class *sclass;
484 int ret;
486 for (sclass = schema->classes; sclass; sclass = sclass->next) {
487 char *val = schema_class_to_extendedInfo(msg, sclass);
488 if (!val) {
489 return ldb_oom(ldb);
492 ret = ldb_msg_add_steal_string(msg, "extendedClassInfo", val);
493 if (ret != LDB_SUCCESS) {
494 return ret;
498 return LDB_SUCCESS;
502 static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
503 const struct dsdb_schema *schema)
505 struct ldb_dn *dn = msg->dn;
506 unsigned int i;
507 int ret;
508 const char *first_component_name = ldb_dn_get_component_name(dn, 0);
509 const struct ldb_val *first_component_val;
510 const struct dsdb_class *schema_class;
511 const char **possibleInferiors;
513 if (strcasecmp(first_component_name, "cn") != 0) {
514 return LDB_SUCCESS;
517 first_component_val = ldb_dn_get_component_val(dn, 0);
519 schema_class = dsdb_class_by_cn_ldb_val(schema, first_component_val);
520 if (schema_class == NULL) {
521 return LDB_SUCCESS;
524 possibleInferiors = schema_class->possibleInferiors;
525 if (possibleInferiors == NULL) {
526 return LDB_SUCCESS;
529 for (i=0;possibleInferiors[i];i++) {
530 char *v = talloc_strdup(msg, possibleInferiors[i]);
531 if (v == NULL) {
532 return ldb_oom(ldb);
534 ret = ldb_msg_add_steal_string(msg, "possibleInferiors", v);
535 if (ret != LDB_SUCCESS) {
536 return ret;
540 return LDB_SUCCESS;
544 /* Add objectClasses, attributeTypes and dITContentRules from the
545 schema object (they are not stored in the database)
547 static int schema_data_search_callback(struct ldb_request *req, struct ldb_reply *ares)
549 struct ldb_context *ldb;
550 struct schema_data_search_data *ac;
551 struct schema_data_private_data *mc;
552 unsigned int i;
553 int ret;
555 ac = talloc_get_type(req->context, struct schema_data_search_data);
556 mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_data_private_data);
557 ldb = ldb_module_get_ctx(ac->module);
559 if (!ares) {
560 return ldb_module_done(ac->req, NULL, NULL,
561 LDB_ERR_OPERATIONS_ERROR);
563 if (ares->error != LDB_SUCCESS) {
564 return ldb_module_done(ac->req, ares->controls,
565 ares->response, ares->error);
567 /* Only entries are interesting, and we handle the case of the parent seperatly */
569 switch (ares->type) {
570 case LDB_REPLY_ENTRY:
572 if (ldb_dn_compare(ares->message->dn, mc->aggregate_dn) == 0) {
573 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
574 if (generated_attrs[i].aggregate &&
575 ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
576 ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
577 if (ret != LDB_SUCCESS) {
578 return ret;
582 } else if ((ldb_dn_compare_base(mc->schema_dn, ares->message->dn) == 0)
583 && (ldb_dn_compare(mc->schema_dn, ares->message->dn) != 0)) {
584 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
585 if (!generated_attrs[i].aggregate &&
586 ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
587 ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
588 if (ret != LDB_SUCCESS) {
589 return ret;
596 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
598 case LDB_REPLY_REFERRAL:
600 return ldb_module_send_referral(ac->req, ares->referral);
602 case LDB_REPLY_DONE:
604 return ldb_module_done(ac->req, ares->controls,
605 ares->response, ares->error);
608 return LDB_SUCCESS;
611 /* search */
612 static int schema_data_search(struct ldb_module *module, struct ldb_request *req)
614 struct ldb_context *ldb = ldb_module_get_ctx(module);
615 unsigned int i;
616 int ret;
617 struct schema_data_search_data *search_context;
618 struct ldb_request *down_req;
619 const struct dsdb_schema *schema;
620 if (!ldb_module_get_private(module)) {
621 /* If there is no module data, there is little we can do */
622 return ldb_next_request(module, req);
625 /* The schema manipulation does not apply to special DNs */
626 if (ldb_dn_is_special(req->op.search.base)) {
627 return ldb_next_request(module, req);
630 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
631 if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
632 break;
635 if (i == ARRAY_SIZE(generated_attrs)) {
636 /* No request for a generated attr found, nothing to
637 * see here, move along... */
638 return ldb_next_request(module, req);
641 schema = dsdb_get_schema(ldb, NULL);
642 if (!schema || !ldb_module_get_private(module)) {
643 /* If there is no schema, there is little we can do */
644 return ldb_next_request(module, req);
647 search_context = talloc(req, struct schema_data_search_data);
648 if (!search_context) {
649 return ldb_oom(ldb);
652 search_context->module = module;
653 search_context->req = req;
654 search_context->schema = talloc_reference(search_context, schema);
655 if (!search_context->schema) {
656 return ldb_oom(ldb);
659 ret = ldb_build_search_req_ex(&down_req, ldb, search_context,
660 req->op.search.base,
661 req->op.search.scope,
662 req->op.search.tree,
663 req->op.search.attrs,
664 req->controls,
665 search_context, schema_data_search_callback,
666 req);
667 LDB_REQ_SET_LOCATION(down_req);
668 if (ret != LDB_SUCCESS) {
669 return ldb_operr(ldb);
672 return ldb_next_request(module, down_req);
676 static const struct ldb_module_ops ldb_schema_data_module_ops = {
677 .name = "schema_data",
678 .init_context = schema_data_init,
679 .add = schema_data_add,
680 .modify = schema_data_modify,
681 .del = schema_data_del,
682 .search = schema_data_search
685 int ldb_schema_data_module_init(const char *version)
687 LDB_MODULE_CHECK_VERSION(version);
688 return ldb_register_module(&ldb_schema_data_module_ops);