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
);
44 int (*fn
)(struct ldb_context
*, struct ldb_message
*, const struct dsdb_schema
*);
45 } generated_attrs
[] = {
47 .attr
= "objectClasses",
48 .fn
= generate_objectClasses
51 .attr
= "attributeTypes",
52 .fn
= generate_attributeTypes
55 .attr
= "dITContentRules",
56 .fn
= generate_dITContentRules
60 struct schema_fsmo_private_data
{
61 struct ldb_dn
*aggregate_dn
;
64 struct schema_fsmo_search_data
{
65 struct ldb_module
*module
;
66 struct ldb_request
*req
;
68 const struct dsdb_schema
*schema
;
71 static int schema_fsmo_init(struct ldb_module
*module
)
74 struct ldb_dn
*schema_dn
;
75 struct dsdb_schema
*schema
;
76 char *error_string
= NULL
;
78 struct schema_fsmo_private_data
*data
;
80 schema_dn
= samdb_schema_dn(module
->ldb
);
82 ldb_reset_err_string(module
->ldb
);
83 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
,
84 "schema_fsmo_init: no schema dn present: (skip schema loading)\n");
85 return ldb_next_init(module
);
88 data
= talloc(module
, struct schema_fsmo_private_data
);
91 return LDB_ERR_OPERATIONS_ERROR
;
94 /* Check to see if this is a result on the CN=Aggregate schema */
95 data
->aggregate_dn
= ldb_dn_copy(data
, schema_dn
);
96 if (!ldb_dn_add_child_fmt(data
->aggregate_dn
, "CN=Aggregate")) {
98 return LDB_ERR_OPERATIONS_ERROR
;
101 module
->private_data
= data
;
103 if (dsdb_get_schema(module
->ldb
)) {
104 return ldb_next_init(module
);
107 mem_ctx
= talloc_new(module
);
109 ldb_oom(module
->ldb
);
110 return LDB_ERR_OPERATIONS_ERROR
;
113 ret
= dsdb_schema_from_schema_dn(mem_ctx
, module
->ldb
,
114 lp_iconv_convenience(ldb_get_opaque(module
->ldb
, "loadparm")),
115 schema_dn
, &schema
, &error_string
);
117 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
118 ldb_reset_err_string(module
->ldb
);
119 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
,
120 "schema_fsmo_init: no schema head present: (skip schema loading)\n");
121 talloc_free(mem_ctx
);
122 return ldb_next_init(module
);
125 if (ret
!= LDB_SUCCESS
) {
126 ldb_asprintf_errstring(module
->ldb
,
127 "schema_fsmo_init: dsdb_schema load failed: %s",
129 talloc_free(mem_ctx
);
133 /* dsdb_set_schema() steal schema into the ldb_context */
134 ret
= dsdb_set_schema(module
->ldb
, schema
);
135 if (ret
!= LDB_SUCCESS
) {
136 ldb_debug_set(module
->ldb
, LDB_DEBUG_FATAL
,
137 "schema_fsmo_init: dsdb_set_schema() failed: %d:%s",
138 ret
, ldb_strerror(ret
));
139 talloc_free(mem_ctx
);
143 talloc_free(mem_ctx
);
144 return ldb_next_init(module
);
147 static int schema_fsmo_add(struct ldb_module
*module
, struct ldb_request
*req
)
149 struct dsdb_schema
*schema
;
150 const char *attributeID
= NULL
;
151 const char *governsID
= NULL
;
152 const char *oid_attr
= NULL
;
153 const char *oid
= NULL
;
157 /* special objects should always go through */
158 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
159 return ldb_next_request(module
, req
);
162 /* replicated update should always go through */
163 if (ldb_request_get_control(req
, DSDB_CONTROL_REPLICATED_UPDATE_OID
)) {
164 return ldb_next_request(module
, req
);
167 schema
= dsdb_get_schema(module
->ldb
);
169 return ldb_next_request(module
, req
);
172 if (!schema
->fsmo
.we_are_master
) {
173 ldb_debug_set(module
->ldb
, LDB_DEBUG_ERROR
,
174 "schema_fsmo_add: we are not master: reject request\n");
175 return LDB_ERR_UNWILLING_TO_PERFORM
;
178 attributeID
= samdb_result_string(req
->op
.add
.message
, "attributeID", NULL
);
179 governsID
= samdb_result_string(req
->op
.add
.message
, "governsID", NULL
);
182 oid_attr
= "attributeID";
184 } else if (governsID
) {
185 oid_attr
= "governsID";
190 return ldb_next_request(module
, req
);
193 status
= dsdb_map_oid2int(schema
, oid
, &id32
);
194 if (W_ERROR_IS_OK(status
)) {
195 return ldb_next_request(module
, req
);
196 } else if (!W_ERROR_EQUAL(WERR_DS_NO_MSDS_INTID
, status
)) {
197 ldb_debug_set(module
->ldb
, LDB_DEBUG_ERROR
,
198 "schema_fsmo_add: failed to map %s[%s]: %s\n",
199 oid_attr
, oid
, win_errstr(status
));
200 return LDB_ERR_UNWILLING_TO_PERFORM
;
203 status
= dsdb_create_prefix_mapping(module
->ldb
, schema
, oid
);
204 if (!W_ERROR_IS_OK(status
)) {
205 ldb_debug_set(module
->ldb
, LDB_DEBUG_ERROR
,
206 "schema_fsmo_add: failed to create prefix mapping for %s[%s]: %s\n",
207 oid_attr
, oid
, win_errstr(status
));
208 return LDB_ERR_UNWILLING_TO_PERFORM
;
211 return ldb_next_request(module
, req
);
214 static int schema_fsmo_extended(struct ldb_module
*module
, struct ldb_request
*req
)
216 struct ldb_dn
*schema_dn
;
217 struct dsdb_schema
*schema
;
218 char *error_string
= NULL
;
222 if (strcmp(req
->op
.extended
.oid
, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID
) != 0) {
223 return ldb_next_request(module
, req
);
226 schema_dn
= samdb_schema_dn(module
->ldb
);
228 ldb_reset_err_string(module
->ldb
);
229 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
,
230 "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
231 return ldb_next_request(module
, req
);
234 mem_ctx
= talloc_new(module
);
236 ldb_oom(module
->ldb
);
237 return LDB_ERR_OPERATIONS_ERROR
;
240 ret
= dsdb_schema_from_schema_dn(mem_ctx
, module
->ldb
,
241 lp_iconv_convenience(ldb_get_opaque(module
->ldb
, "loadparm")),
242 schema_dn
, &schema
, &error_string
);
244 if (ret
== LDB_ERR_NO_SUCH_OBJECT
) {
245 ldb_reset_err_string(module
->ldb
);
246 ldb_debug(module
->ldb
, LDB_DEBUG_WARNING
,
247 "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
248 talloc_free(mem_ctx
);
249 return ldb_next_request(module
, req
);
252 if (ret
!= LDB_SUCCESS
) {
253 ldb_asprintf_errstring(module
->ldb
,
254 "schema_fsmo_extended: dsdb_schema load failed: %s",
256 talloc_free(mem_ctx
);
257 return ldb_next_request(module
, req
);
260 /* Replace the old schema*/
261 ret
= dsdb_set_schema(module
->ldb
, schema
);
262 if (ret
!= LDB_SUCCESS
) {
263 ldb_debug_set(module
->ldb
, LDB_DEBUG_FATAL
,
264 "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
265 ret
, ldb_strerror(ret
));
266 talloc_free(mem_ctx
);
270 talloc_free(mem_ctx
);
274 static int generate_objectClasses(struct ldb_context
*ldb
, struct ldb_message
*msg
,
275 const struct dsdb_schema
*schema
)
277 const struct dsdb_class
*class;
280 for (class = schema
->classes
; class; class = class->next
) {
281 ret
= ldb_msg_add_string(msg
, "objectClasses", schema_class_to_description(msg
, class));
282 if (ret
!= LDB_SUCCESS
) {
288 static int generate_attributeTypes(struct ldb_context
*ldb
, struct ldb_message
*msg
,
289 const struct dsdb_schema
*schema
)
291 const struct dsdb_attribute
*attribute
;
294 for (attribute
= schema
->attributes
; attribute
; attribute
= attribute
->next
) {
295 ret
= ldb_msg_add_string(msg
, "attributeTypes", schema_attribute_to_description(msg
, attribute
));
296 if (ret
!= LDB_SUCCESS
) {
303 static int generate_dITContentRules(struct ldb_context
*ldb
, struct ldb_message
*msg
,
304 const struct dsdb_schema
*schema
)
306 const struct dsdb_class
*class;
309 for (class = schema
->classes
; class; class = class->next
) {
310 if (class->auxiliaryClass
|| class->systemAuxiliaryClass
) {
311 char *ditcontentrule
= schema_class_to_dITContentRule(msg
, class, schema
);
312 if (!ditcontentrule
) {
314 return LDB_ERR_OPERATIONS_ERROR
;
316 ret
= ldb_msg_add_steal_string(msg
, "dITContentRules", ditcontentrule
);
317 if (ret
!= LDB_SUCCESS
) {
327 /* Add objectClasses, attributeTypes and dITContentRules from the
328 schema object (they are not stored in the database)
330 static int schema_fsmo_search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
332 struct schema_fsmo_search_data
*ac
;
333 struct schema_fsmo_private_data
*mc
;
336 ac
= talloc_get_type(req
->context
, struct schema_fsmo_search_data
);
337 mc
= talloc_get_type(ac
->module
->private_data
, struct schema_fsmo_private_data
);
340 return ldb_module_done(ac
->req
, NULL
, NULL
,
341 LDB_ERR_OPERATIONS_ERROR
);
343 if (ares
->error
!= LDB_SUCCESS
) {
344 return ldb_module_done(ac
->req
, ares
->controls
,
345 ares
->response
, ares
->error
);
347 /* Only entries are interesting, and we handle the case of the parent seperatly */
349 switch (ares
->type
) {
350 case LDB_REPLY_ENTRY
:
352 if (ldb_dn_compare(ares
->message
->dn
, mc
->aggregate_dn
) != 0) {
353 return ldb_module_send_entry(ac
->req
, ares
->message
);
356 for (i
=0; i
< ARRAY_SIZE(generated_attrs
); i
++) {
357 if (ldb_attr_in_list(ac
->req
->op
.search
.attrs
, generated_attrs
[i
].attr
)) {
358 ret
= generated_attrs
[i
].fn(ac
->module
->ldb
, ares
->message
, ac
->schema
);
359 if (ret
!= LDB_SUCCESS
) {
365 return ldb_module_send_entry(ac
->req
, ares
->message
);
367 case LDB_REPLY_REFERRAL
:
369 return ldb_module_send_referral(ac
->req
, ares
->referral
);
373 return ldb_module_done(ac
->req
, ares
->controls
,
374 ares
->response
, ares
->error
);
381 static int schema_fsmo_search(struct ldb_module
*module
, struct ldb_request
*req
)
384 struct schema_fsmo_search_data
*search_context
;
385 struct ldb_request
*down_req
;
386 struct dsdb_schema
*schema
= dsdb_get_schema(module
->ldb
);
388 if (!schema
|| !module
->private_data
) {
389 /* If there is no schema, there is little we can do */
390 return ldb_next_request(module
, req
);
392 for (i
=0; i
< ARRAY_SIZE(generated_attrs
); i
++) {
393 if (ldb_attr_in_list(req
->op
.search
.attrs
, generated_attrs
[i
].attr
)) {
397 if (i
== ARRAY_SIZE(generated_attrs
)) {
398 /* No request for a generated attr found, nothing to
399 * see here, move along... */
400 return ldb_next_request(module
, req
);
403 search_context
= talloc(req
, struct schema_fsmo_search_data
);
404 if (!search_context
) {
405 ldb_oom(module
->ldb
);
406 return LDB_ERR_OPERATIONS_ERROR
;
409 search_context
->module
= module
;
410 search_context
->req
= req
;
411 search_context
->schema
= schema
;
413 ret
= ldb_build_search_req_ex(&down_req
, module
->ldb
, search_context
,
415 req
->op
.search
.scope
,
417 req
->op
.search
.attrs
,
419 search_context
, schema_fsmo_search_callback
,
421 if (ret
!= LDB_SUCCESS
) {
422 return LDB_ERR_OPERATIONS_ERROR
;
425 return ldb_next_request(module
, down_req
);
429 _PUBLIC_
const struct ldb_module_ops ldb_schema_fsmo_module_ops
= {
430 .name
= "schema_fsmo",
431 .init_context
= schema_fsmo_init
,
432 .add
= schema_fsmo_add
,
433 .extended
= schema_fsmo_extended
,
434 .search
= schema_fsmo_search