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
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/>.
25 #include "lib/ldb/include/ldb.h"
26 #include "lib/ldb/include/ldb_errors.h"
27 #include "lib/ldb/include/ldb_private.h"
28 #include "dsdb/samdb/samdb.h"
29 #include "librpc/gen_ndr/ndr_misc.h"
30 #include "librpc/gen_ndr/ndr_drsuapi.h"
31 #include "librpc/gen_ndr/ndr_drsblobs.h"
32 #include "../lib/util/dlinklist.h"
33 #include "param/param.h"
35 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
36 const struct dsdb_schema *schema);
37 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
38 const struct dsdb_schema *schema);
39 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
40 const struct dsdb_schema *schema);
41 static int generate_extendedAttributeInfo(struct ldb_context *ldb, struct ldb_message *msg,
42 const struct dsdb_schema *schema);
43 static int generate_extendedClassInfo(struct ldb_context *ldb, struct ldb_message *msg,
44 const struct dsdb_schema *schema);
48 int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
49 } generated_attrs[] = {
51 .attr = "objectClasses",
52 .fn = generate_objectClasses
55 .attr = "attributeTypes",
56 .fn = generate_attributeTypes
59 .attr = "dITContentRules",
60 .fn = generate_dITContentRules
63 .attr = "extendedAttributeInfo",
64 .fn = generate_extendedAttributeInfo
67 .attr = "extendedClassInfo",
68 .fn = generate_extendedClassInfo
72 struct schema_fsmo_private_data {
73 struct ldb_dn *aggregate_dn;
76 struct schema_fsmo_search_data {
77 struct ldb_module *module;
78 struct ldb_request *req;
80 const struct dsdb_schema *schema;
83 static int schema_fsmo_init(struct ldb_module *module)
86 struct ldb_dn *schema_dn;
87 struct dsdb_schema *schema;
88 char *error_string = NULL;
90 struct schema_fsmo_private_data *data;
92 schema_dn = samdb_schema_dn(module->ldb);
94 ldb_reset_err_string(module->ldb);
95 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
96 "schema_fsmo_init: no schema dn present: (skip schema loading)\n");
97 return ldb_next_init(module);
100 data = talloc(module, struct schema_fsmo_private_data);
102 ldb_oom(module->ldb);
103 return LDB_ERR_OPERATIONS_ERROR;
106 /* Check to see if this is a result on the CN=Aggregate schema */
107 data->aggregate_dn = ldb_dn_copy(data, schema_dn);
108 if (!ldb_dn_add_child_fmt(data->aggregate_dn, "CN=Aggregate")) {
109 ldb_oom(module->ldb);
110 return LDB_ERR_OPERATIONS_ERROR;
113 module->private_data = data;
115 if (dsdb_get_schema(module->ldb)) {
116 return ldb_next_init(module);
119 mem_ctx = talloc_new(module);
121 ldb_oom(module->ldb);
122 return LDB_ERR_OPERATIONS_ERROR;
125 ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
126 lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
127 schema_dn, &schema, &error_string);
129 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
130 ldb_reset_err_string(module->ldb);
131 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
132 "schema_fsmo_init: no schema head present: (skip schema loading)\n");
133 talloc_free(mem_ctx);
134 return ldb_next_init(module);
137 if (ret != LDB_SUCCESS) {
138 ldb_asprintf_errstring(module->ldb,
139 "schema_fsmo_init: dsdb_schema load failed: %s",
141 talloc_free(mem_ctx);
145 /* dsdb_set_schema() steal schema into the ldb_context */
146 ret = dsdb_set_schema(module->ldb, schema);
147 if (ret != LDB_SUCCESS) {
148 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
149 "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
150 ret, ldb_strerror(ret));
151 talloc_free(mem_ctx);
155 talloc_free(mem_ctx);
156 return ldb_next_init(module);
159 static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
161 struct dsdb_schema *schema;
162 const char *attributeID = NULL;
163 const char *governsID = NULL;
164 const char *oid_attr = NULL;
165 const char *oid = NULL;
169 /* special objects should always go through */
170 if (ldb_dn_is_special(req->op.add.message->dn)) {
171 return ldb_next_request(module, req);
174 /* replicated update should always go through */
175 if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
176 return ldb_next_request(module, req);
179 schema = dsdb_get_schema(module->ldb);
181 return ldb_next_request(module, req);
184 if (!schema->fsmo.we_are_master) {
185 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
186 "schema_fsmo_add: we are not master: reject request\n");
187 return LDB_ERR_UNWILLING_TO_PERFORM;
190 attributeID = samdb_result_string(req->op.add.message, "attributeID", NULL);
191 governsID = samdb_result_string(req->op.add.message, "governsID", NULL);
194 oid_attr = "attributeID";
196 } else if (governsID) {
197 oid_attr = "governsID";
202 return ldb_next_request(module, req);
205 status = dsdb_map_oid2int(schema, oid, &id32);
206 if (W_ERROR_IS_OK(status)) {
207 return ldb_next_request(module, req);
208 } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID, status)) {
209 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
210 "schema_fsmo_add: failed to map %s[%s]: %s\n",
211 oid_attr, oid, win_errstr(status));
212 return LDB_ERR_UNWILLING_TO_PERFORM;
215 status = dsdb_create_prefix_mapping(module->ldb, schema, oid);
216 if (!W_ERROR_IS_OK(status)) {
217 ldb_debug_set(module->ldb, LDB_DEBUG_ERROR,
218 "schema_fsmo_add: failed to create prefix mapping for %s[%s]: %s\n",
219 oid_attr, oid, win_errstr(status));
220 return LDB_ERR_UNWILLING_TO_PERFORM;
223 return ldb_next_request(module, req);
226 static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
228 struct ldb_dn *schema_dn;
229 struct dsdb_schema *schema;
230 char *error_string = NULL;
234 if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
235 return ldb_next_request(module, req);
238 schema_dn = samdb_schema_dn(module->ldb);
240 ldb_reset_err_string(module->ldb);
241 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
242 "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
243 return ldb_next_request(module, req);
246 mem_ctx = talloc_new(module);
248 ldb_oom(module->ldb);
249 return LDB_ERR_OPERATIONS_ERROR;
252 ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
253 lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
254 schema_dn, &schema, &error_string);
256 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
257 ldb_reset_err_string(module->ldb);
258 ldb_debug(module->ldb, LDB_DEBUG_WARNING,
259 "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
260 talloc_free(mem_ctx);
261 return ldb_next_request(module, req);
264 if (ret != LDB_SUCCESS) {
265 ldb_asprintf_errstring(module->ldb,
266 "schema_fsmo_extended: dsdb_schema load failed: %s",
268 talloc_free(mem_ctx);
269 return ldb_next_request(module, req);
272 /* Replace the old schema*/
273 ret = dsdb_set_schema(module->ldb, schema);
274 if (ret != LDB_SUCCESS) {
275 ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
276 "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
277 ret, ldb_strerror(ret));
278 talloc_free(mem_ctx);
282 talloc_free(mem_ctx);
286 static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
287 const struct dsdb_schema *schema)
289 const struct dsdb_class *class;
292 for (class = schema->classes; class; class = class->next) {
293 ret = ldb_msg_add_string(msg, "objectClasses", schema_class_to_description(msg, class));
294 if (ret != LDB_SUCCESS) {
300 static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
301 const struct dsdb_schema *schema)
303 const struct dsdb_attribute *attribute;
306 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
307 ret = ldb_msg_add_string(msg, "attributeTypes", schema_attribute_to_description(msg, attribute));
308 if (ret != LDB_SUCCESS) {
315 static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
316 const struct dsdb_schema *schema)
318 const struct dsdb_class *class;
321 for (class = schema->classes; class; class = class->next) {
322 if (class->auxiliaryClass || class->systemAuxiliaryClass) {
323 char *ditcontentrule = schema_class_to_dITContentRule(msg, class, schema);
324 if (!ditcontentrule) {
326 return LDB_ERR_OPERATIONS_ERROR;
328 ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
329 if (ret != LDB_SUCCESS) {
337 static int generate_extendedAttributeInfo(struct ldb_context *ldb,
338 struct ldb_message *msg,
339 const struct dsdb_schema *schema)
341 const struct dsdb_attribute *attribute;
344 for (attribute = schema->attributes; attribute; attribute = attribute->next) {
345 char *val = schema_attribute_to_extendedInfo(msg, attribute);
348 return LDB_ERR_OPERATIONS_ERROR;
351 ret = ldb_msg_add_string(msg, "extendedAttributeInfo", val);
352 if (ret != LDB_SUCCESS) {
360 static int generate_extendedClassInfo(struct ldb_context *ldb,
361 struct ldb_message *msg,
362 const struct dsdb_schema *schema)
364 const struct dsdb_class *sclass;
367 for (sclass = schema->classes; sclass; sclass = sclass->next) {
368 char *val = schema_class_to_extendedInfo(msg, sclass);
371 return LDB_ERR_OPERATIONS_ERROR;
374 ret = ldb_msg_add_string(msg, "extendedClassInfo", val);
375 if (ret != LDB_SUCCESS) {
383 /* Add objectClasses, attributeTypes and dITContentRules from the
384 schema object (they are not stored in the database)
386 static int schema_fsmo_search_callback(struct ldb_request *req, struct ldb_reply *ares)
388 struct schema_fsmo_search_data *ac;
389 struct schema_fsmo_private_data *mc;
392 ac = talloc_get_type(req->context, struct schema_fsmo_search_data);
393 mc = talloc_get_type(ac->module->private_data, struct schema_fsmo_private_data);
396 return ldb_module_done(ac->req, NULL, NULL,
397 LDB_ERR_OPERATIONS_ERROR);
399 if (ares->error != LDB_SUCCESS) {
400 return ldb_module_done(ac->req, ares->controls,
401 ares->response, ares->error);
403 /* Only entries are interesting, and we handle the case of the parent seperatly */
405 switch (ares->type) {
406 case LDB_REPLY_ENTRY:
408 if (ldb_dn_compare(ares->message->dn, mc->aggregate_dn) != 0) {
409 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
412 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
413 if (ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
414 ret = generated_attrs[i].fn(ac->module->ldb, ares->message, ac->schema);
415 if (ret != LDB_SUCCESS) {
421 return ldb_module_send_entry(ac->req, ares->message, ares->controls);
423 case LDB_REPLY_REFERRAL:
425 return ldb_module_send_referral(ac->req, ares->referral);
429 return ldb_module_done(ac->req, ares->controls,
430 ares->response, ares->error);
437 static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req)
440 struct schema_fsmo_search_data *search_context;
441 struct ldb_request *down_req;
442 struct dsdb_schema *schema = dsdb_get_schema(module->ldb);
444 if (!schema || !module->private_data) {
445 /* If there is no schema, there is little we can do */
446 return ldb_next_request(module, req);
448 for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
449 if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
453 if (i == ARRAY_SIZE(generated_attrs)) {
454 /* No request for a generated attr found, nothing to
455 * see here, move along... */
456 return ldb_next_request(module, req);
459 search_context = talloc(req, struct schema_fsmo_search_data);
460 if (!search_context) {
461 ldb_oom(module->ldb);
462 return LDB_ERR_OPERATIONS_ERROR;
465 search_context->module = module;
466 search_context->req = req;
467 search_context->schema = schema;
469 ret = ldb_build_search_req_ex(&down_req, module->ldb, search_context,
471 req->op.search.scope,
473 req->op.search.attrs,
475 search_context, schema_fsmo_search_callback,
477 if (ret != LDB_SUCCESS) {
478 return LDB_ERR_OPERATIONS_ERROR;
481 return ldb_next_request(module, down_req);
485 _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
486 .name = "schema_fsmo",
487 .init_context = schema_fsmo_init,
488 .add = schema_fsmo_add,
489 .extended = schema_fsmo_extended,
490 .search = schema_fsmo_search