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/>.
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
);
49 int (*fn
)(struct ldb_context
*, struct ldb_message
*, const struct dsdb_schema
*);
51 } generated_attrs
[] = {
53 .attr
= "objectClasses",
54 .fn
= generate_objectClasses
,
58 .attr
= "attributeTypes",
59 .fn
= generate_attributeTypes
,
63 .attr
= "dITContentRules",
64 .fn
= generate_dITContentRules
,
68 .attr
= "extendedAttributeInfo",
69 .fn
= generate_extendedAttributeInfo
,
73 .attr
= "extendedClassInfo",
74 .fn
= generate_extendedClassInfo
,
78 .attr
= "possibleInferiors",
79 .fn
= generate_possibleInferiors
,
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
)
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
[] = {
119 tmp_ctx
= talloc_new(mem_ctx
);
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
) {
136 } else if (ret
!= LDB_SUCCESS
) {
137 ldb_asprintf_errstring(ldb
,
138 "dsdb_schema: failed to search the schema head: %s",
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",
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",
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",
178 talloc_steal(mem_ctx
, *schema
);
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
);
190 static int schema_fsmo_init(struct ldb_module
*module
)
192 struct ldb_context
*ldb
;
194 struct ldb_dn
*schema_dn
;
195 struct dsdb_schema
*schema
;
197 struct schema_fsmo_private_data
*data
;
199 ldb
= ldb_module_get_ctx(module
);
200 schema_dn
= samdb_schema_dn(ldb
);
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
);
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")) {
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
);
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")),
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
);
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
);
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
;
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
);
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");
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
);
308 return ldb_next_request(module
, req
);
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
;
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
);
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
);
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")),
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
);
392 dsdb_make_schema_global(ldb
);
394 talloc_free(mem_ctx
);
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
;
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
) {
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
;
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
) {
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
;
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
) {
438 return LDB_ERR_OPERATIONS_ERROR
;
440 ret
= ldb_msg_add_steal_string(msg
, "dITContentRules", ditcontentrule
);
441 if (ret
!= 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
;
456 for (attribute
= schema
->attributes
; attribute
; attribute
= attribute
->next
) {
457 char *val
= schema_attribute_to_extendedInfo(msg
, attribute
);
460 return LDB_ERR_OPERATIONS_ERROR
;
463 ret
= ldb_msg_add_string(msg
, "extendedAttributeInfo", val
);
464 if (ret
!= 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
;
479 for (sclass
= schema
->classes
; sclass
; sclass
= sclass
->next
) {
480 char *val
= schema_class_to_extendedInfo(msg
, sclass
);
483 return LDB_ERR_OPERATIONS_ERROR
;
486 ret
= ldb_msg_add_string(msg
, "extendedClassInfo", val
);
487 if (ret
!= 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
;
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) {
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
) {
517 possibleInferiors
= schema_class
->possibleInferiors
;
518 if (possibleInferiors
== NULL
) {
522 for (i
=0;possibleInferiors
[i
];i
++) {
523 ret
= ldb_msg_add_string(msg
, "possibleInferiors", possibleInferiors
[i
]);
524 if (ret
!= 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
;
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
);
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
) {
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
) {
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
);
591 return ldb_module_done(ac
->req
, ares
->controls
,
592 ares
->response
, ares
->error
);
599 static int schema_fsmo_search(struct ldb_module
*module
, struct ldb_request
*req
)
601 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
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
)) {
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
) {
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
,
634 req
->op
.search
.scope
,
636 req
->op
.search
.attrs
,
638 search_context
, schema_fsmo_search_callback
,
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