Line data Source code
1 : /*
2 : Unix SMB/CIFS Implementation.
3 :
4 : The module that handles the Schema checkings and dynamic attributes
5 :
6 : Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
7 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
8 :
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.
13 :
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.
18 :
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/>.
21 :
22 : */
23 :
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"
32 :
33 : #undef strcasecmp
34 :
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);
45 : static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
46 : const struct dsdb_schema *schema);
47 :
48 : static const struct {
49 : const char *attr;
50 : int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *);
51 : bool aggregate;
52 : } generated_attrs[] = {
53 : {
54 : .attr = "objectClasses",
55 : .fn = generate_objectClasses,
56 : .aggregate = true,
57 : },
58 : {
59 : .attr = "attributeTypes",
60 : .fn = generate_attributeTypes,
61 : .aggregate = true,
62 : },
63 : {
64 : .attr = "dITContentRules",
65 : .fn = generate_dITContentRules,
66 : .aggregate = true,
67 : },
68 : {
69 : .attr = "extendedAttributeInfo",
70 : .fn = generate_extendedAttributeInfo,
71 : .aggregate = true,
72 : },
73 : {
74 : .attr = "extendedClassInfo",
75 : .fn = generate_extendedClassInfo,
76 : .aggregate = true,
77 : },
78 : {
79 : .attr = "possibleInferiors",
80 : .fn = generate_possibleInferiors,
81 : .aggregate = false,
82 : }
83 : };
84 :
85 : struct schema_data_private_data {
86 : struct ldb_dn *aggregate_dn;
87 : struct ldb_dn *schema_dn;
88 : };
89 :
90 : struct schema_data_search_data {
91 : struct ldb_module *module;
92 : struct ldb_request *req;
93 :
94 : const struct dsdb_schema *schema;
95 : };
96 :
97 182002 : static int schema_data_init(struct ldb_module *module)
98 : {
99 6015 : struct ldb_context *ldb;
100 6015 : struct ldb_dn *schema_dn;
101 6015 : int ret;
102 6015 : struct schema_data_private_data *data;
103 :
104 182002 : ret = ldb_next_init(module);
105 182002 : if (ret != LDB_SUCCESS) {
106 0 : return ret;
107 : }
108 :
109 182002 : ldb = ldb_module_get_ctx(module);
110 182002 : schema_dn = ldb_get_schema_basedn(ldb);
111 182002 : if (!schema_dn) {
112 0 : ldb_reset_err_string(ldb);
113 0 : ldb_debug(ldb, LDB_DEBUG_WARNING,
114 : "schema_data_init: no schema dn present: (skip schema loading)\n");
115 0 : return LDB_SUCCESS;
116 : }
117 :
118 182002 : data = talloc(module, struct schema_data_private_data);
119 182002 : if (data == NULL) {
120 0 : return ldb_oom(ldb);
121 : }
122 :
123 182002 : data->schema_dn = schema_dn;
124 :
125 : /* Used to check to see if this is a result on the CN=Aggregate schema */
126 182002 : data->aggregate_dn = samdb_aggregate_schema_dn(ldb, data);
127 182002 : if (!data->aggregate_dn) {
128 0 : ldb_asprintf_errstring(ldb, "schema_data_init: Could not build aggregate schema DN for schema in %s", ldb_dn_get_linearized(schema_dn));
129 0 : return LDB_ERR_OPERATIONS_ERROR;
130 : }
131 :
132 182002 : ldb_module_set_private(module, data);
133 182002 : return LDB_SUCCESS;
134 : }
135 :
136 350703 : static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
137 : {
138 39060 : struct ldb_context *ldb;
139 39060 : struct dsdb_schema *schema;
140 350703 : const struct ldb_val *attributeID = NULL;
141 350703 : const struct ldb_val *governsID = NULL;
142 350703 : const char *oid_attr = NULL;
143 350703 : const char *oid = NULL;
144 350703 : struct ldb_dn *parent_dn = NULL;
145 39060 : int cmp;
146 39060 : WERROR status;
147 350703 : bool rodc = false;
148 39060 : int ret;
149 39060 : struct schema_data_private_data *mc;
150 350703 : mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
151 :
152 350703 : ldb = ldb_module_get_ctx(module);
153 :
154 : /* special objects should always go through */
155 350703 : if (ldb_dn_is_special(req->op.add.message->dn)) {
156 1084 : return ldb_next_request(module, req);
157 : }
158 :
159 : /* replicated update should always go through */
160 349619 : if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
161 131383 : return ldb_next_request(module, req);
162 : }
163 :
164 218236 : schema = dsdb_get_schema(ldb, req);
165 218236 : if (!schema) {
166 0 : return ldb_next_request(module, req);
167 : }
168 :
169 218236 : ret = samdb_rodc(ldb, &rodc);
170 218236 : if (ret != LDB_SUCCESS) {
171 0 : DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
172 : }
173 :
174 218236 : if (!schema->fsmo.we_are_master && !rodc) {
175 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
176 : "schema_data_add: we are not master: reject add request\n");
177 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
178 : }
179 :
180 218236 : if (!schema->fsmo.update_allowed && !rodc) {
181 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
182 : "schema_data_add: updates are not allowed: reject add request\n");
183 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
184 : }
185 :
186 218236 : if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
187 : /*
188 : * the provision code needs to create
189 : * the schema root object.
190 : */
191 217291 : cmp = ldb_dn_compare(req->op.add.message->dn, mc->schema_dn);
192 217291 : if (cmp == 0) {
193 127 : return ldb_next_request(module, req);
194 : }
195 : }
196 :
197 218109 : parent_dn = ldb_dn_get_parent(req, req->op.add.message->dn);
198 218109 : if (!parent_dn) {
199 0 : return ldb_oom(ldb);
200 : }
201 :
202 218109 : cmp = ldb_dn_compare(parent_dn, mc->schema_dn);
203 218109 : if (cmp != 0) {
204 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
205 : "schema_data_add: no direct child :%s\n",
206 0 : ldb_dn_get_linearized(req->op.add.message->dn));
207 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
208 : }
209 :
210 218109 : attributeID = ldb_msg_find_ldb_val(req->op.add.message, "attributeID");
211 218109 : governsID = ldb_msg_find_ldb_val(req->op.add.message, "governsID");
212 :
213 218109 : if (attributeID) {
214 184310 : oid_attr = "attributeID";
215 184310 : oid = talloc_strndup(req, (const char *)attributeID->data, attributeID->length);
216 33799 : } else if (governsID) {
217 33672 : oid_attr = "governsID";
218 33672 : oid = talloc_strndup(req, (const char *)governsID->data, governsID->length);
219 : } else {
220 127 : return ldb_next_request(module, req);
221 : }
222 :
223 217982 : if (!oid) {
224 0 : return ldb_oom(ldb);
225 : }
226 :
227 217982 : status = dsdb_schema_pfm_find_oid(schema->prefixmap, oid, NULL);
228 217982 : if (!W_ERROR_IS_OK(status)) {
229 : /* check for internal errors */
230 686 : if (!W_ERROR_EQUAL(status, WERR_NOT_FOUND)) {
231 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
232 : "schema_data_add: failed to map %s[%s]: %s\n",
233 : oid_attr, oid, win_errstr(status));
234 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
235 : }
236 :
237 : /* Update prefixMap and save it */
238 686 : status = dsdb_create_prefix_mapping(ldb, schema, oid);
239 686 : if (!W_ERROR_IS_OK(status)) {
240 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
241 : "schema_data_add: failed to create prefix mapping for %s[%s]: %s\n",
242 : oid_attr, oid, win_errstr(status));
243 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
244 : }
245 : }
246 :
247 217982 : return ldb_next_request(module, req);
248 : }
249 :
250 333948 : static int schema_data_modify(struct ldb_module *module, struct ldb_request *req)
251 : {
252 12558 : struct ldb_context *ldb;
253 12558 : struct dsdb_schema *schema;
254 12558 : int cmp;
255 333948 : bool rodc = false;
256 12558 : int ret;
257 12558 : struct ldb_control *sd_propagation_control;
258 12558 : struct schema_data_private_data *mc;
259 333948 : mc = talloc_get_type(ldb_module_get_private(module), struct schema_data_private_data);
260 :
261 333948 : ldb = ldb_module_get_ctx(module);
262 :
263 : /* special objects should always go through */
264 333948 : if (ldb_dn_is_special(req->op.mod.message->dn)) {
265 2256 : return ldb_next_request(module, req);
266 : }
267 :
268 : /* replicated update should always go through */
269 331692 : if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
270 275 : return ldb_next_request(module, req);
271 : }
272 :
273 : /* dbcheck should be able to fix things */
274 331417 : if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
275 48382 : return ldb_next_request(module, req);
276 : }
277 :
278 283035 : sd_propagation_control = ldb_request_get_control(req,
279 : DSDB_CONTROL_SEC_DESC_PROPAGATION_OID);
280 283035 : if (sd_propagation_control != NULL) {
281 241922 : if (req->op.mod.message->num_elements != 1) {
282 0 : return ldb_module_operr(module);
283 : }
284 241922 : ret = strcmp(req->op.mod.message->elements[0].name,
285 : "nTSecurityDescriptor");
286 241922 : if (ret != 0) {
287 0 : return ldb_module_operr(module);
288 : }
289 :
290 241922 : return ldb_next_request(module, req);
291 : }
292 :
293 41113 : schema = dsdb_get_schema(ldb, req);
294 41113 : if (!schema) {
295 0 : return ldb_next_request(module, req);
296 : }
297 :
298 41113 : cmp = ldb_dn_compare(req->op.mod.message->dn, mc->schema_dn);
299 41113 : if (cmp == 0) {
300 127 : static const char * const constrained_attrs[] = {
301 : "schemaInfo",
302 : "prefixMap",
303 : "msDs-Schema-Extensions",
304 : "msDS-IntId",
305 : NULL
306 : };
307 127 : size_t i;
308 127 : struct ldb_message_element *el;
309 :
310 6729 : if (ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID)) {
311 2762 : return ldb_next_request(module, req);
312 : }
313 :
314 19835 : for (i=0; constrained_attrs[i]; i++) {
315 15868 : el = ldb_msg_find_element(req->op.mod.message,
316 15448 : constrained_attrs[i]);
317 15868 : if (el == NULL) {
318 15868 : continue;
319 : }
320 :
321 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
322 : "schema_data_modify: reject update "
323 : "of attribute[%s]\n",
324 0 : constrained_attrs[i]);
325 0 : return LDB_ERR_CONSTRAINT_VIOLATION;
326 : }
327 :
328 3967 : return ldb_next_request(module, req);
329 : }
330 :
331 34384 : ret = samdb_rodc(ldb, &rodc);
332 34384 : if (ret != LDB_SUCCESS) {
333 0 : DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
334 : }
335 :
336 34384 : if (!schema->fsmo.we_are_master && !rodc) {
337 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
338 : "schema_data_modify: we are not master: reject modify request\n");
339 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
340 : }
341 :
342 34384 : if (!schema->fsmo.update_allowed && !rodc) {
343 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
344 : "schema_data_modify: updates are not allowed: reject modify request\n");
345 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
346 : }
347 :
348 34384 : return ldb_next_request(module, req);
349 : }
350 :
351 0 : static int schema_data_del(struct ldb_module *module, struct ldb_request *req)
352 : {
353 0 : struct ldb_context *ldb;
354 0 : struct dsdb_schema *schema;
355 0 : bool rodc = false;
356 0 : int ret;
357 :
358 0 : ldb = ldb_module_get_ctx(module);
359 :
360 : /* special objects should always go through */
361 0 : if (ldb_dn_is_special(req->op.del.dn)) {
362 0 : return ldb_next_request(module, req);
363 : }
364 :
365 : /* replicated update should always go through */
366 0 : if (ldb_request_get_control(req, DSDB_CONTROL_REPLICATED_UPDATE_OID)) {
367 0 : return ldb_next_request(module, req);
368 : }
369 :
370 : /* dbcheck should be able to fix things */
371 0 : if (ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
372 0 : return ldb_next_request(module, req);
373 : }
374 :
375 0 : schema = dsdb_get_schema(ldb, req);
376 0 : if (!schema) {
377 0 : return ldb_next_request(module, req);
378 : }
379 :
380 0 : ret = samdb_rodc(ldb, &rodc);
381 0 : if (ret != LDB_SUCCESS) {
382 0 : DEBUG(4, (__location__ ": unable to tell if we are an RODC \n"));
383 : }
384 :
385 0 : if (!schema->fsmo.we_are_master && !rodc) {
386 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
387 : "schema_data_modify: we are not master: reject request\n");
388 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
389 : }
390 :
391 : /*
392 : * normally the DACL will prevent delete
393 : * with LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
394 : * above us.
395 : */
396 0 : ldb_debug_set(ldb, LDB_DEBUG_ERROR,
397 : "schema_data_del: delete is not allowed in the schema\n");
398 0 : return LDB_ERR_UNWILLING_TO_PERFORM;
399 : }
400 :
401 9 : static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg,
402 : const struct dsdb_schema *schema)
403 : {
404 0 : const struct dsdb_class *sclass;
405 0 : int ret;
406 :
407 2170 : for (sclass = schema->classes; sclass; sclass = sclass->next) {
408 2161 : char *v = schema_class_to_description(msg, sclass);
409 2161 : if (v == NULL) {
410 0 : return ldb_oom(ldb);
411 : }
412 2161 : ret = ldb_msg_add_steal_string(msg, "objectClasses", v);
413 2161 : if (ret != LDB_SUCCESS) {
414 0 : return ret;
415 : }
416 : }
417 9 : return LDB_SUCCESS;
418 : }
419 9 : static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg,
420 : const struct dsdb_schema *schema)
421 : {
422 0 : const struct dsdb_attribute *attribute;
423 0 : int ret;
424 :
425 12178 : for (attribute = schema->attributes; attribute; attribute = attribute->next) {
426 12169 : char *v = schema_attribute_to_description(msg, attribute);
427 12169 : if (v == NULL) {
428 0 : return ldb_oom(ldb);
429 : }
430 12169 : ret = ldb_msg_add_steal_string(msg, "attributeTypes", v);
431 12169 : if (ret != LDB_SUCCESS) {
432 0 : return ret;
433 : }
434 : }
435 9 : return LDB_SUCCESS;
436 : }
437 :
438 9 : static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg,
439 : const struct dsdb_schema *schema)
440 : {
441 0 : const struct dsdb_class *sclass;
442 0 : int ret;
443 :
444 2170 : for (sclass = schema->classes; sclass; sclass = sclass->next) {
445 2161 : if (sclass->auxiliaryClass || sclass->systemAuxiliaryClass) {
446 81 : char *ditcontentrule = schema_class_to_dITContentRule(msg, sclass, schema);
447 81 : if (!ditcontentrule) {
448 0 : return ldb_oom(ldb);
449 : }
450 81 : ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule);
451 81 : if (ret != LDB_SUCCESS) {
452 0 : return ret;
453 : }
454 : }
455 : }
456 9 : return LDB_SUCCESS;
457 : }
458 :
459 0 : static int generate_extendedAttributeInfo(struct ldb_context *ldb,
460 : struct ldb_message *msg,
461 : const struct dsdb_schema *schema)
462 : {
463 0 : const struct dsdb_attribute *attribute;
464 0 : int ret;
465 :
466 0 : for (attribute = schema->attributes; attribute; attribute = attribute->next) {
467 0 : char *val = schema_attribute_to_extendedInfo(msg, attribute);
468 0 : if (!val) {
469 0 : return ldb_oom(ldb);
470 : }
471 :
472 0 : ret = ldb_msg_add_steal_string(msg, "extendedAttributeInfo", val);
473 0 : if (ret != LDB_SUCCESS) {
474 0 : return ret;
475 : }
476 : }
477 :
478 0 : return LDB_SUCCESS;
479 : }
480 :
481 0 : static int generate_extendedClassInfo(struct ldb_context *ldb,
482 : struct ldb_message *msg,
483 : const struct dsdb_schema *schema)
484 : {
485 0 : const struct dsdb_class *sclass;
486 0 : int ret;
487 :
488 0 : for (sclass = schema->classes; sclass; sclass = sclass->next) {
489 0 : char *val = schema_class_to_extendedInfo(msg, sclass);
490 0 : if (!val) {
491 0 : return ldb_oom(ldb);
492 : }
493 :
494 0 : ret = ldb_msg_add_steal_string(msg, "extendedClassInfo", val);
495 0 : if (ret != LDB_SUCCESS) {
496 0 : return ret;
497 : }
498 : }
499 :
500 0 : return LDB_SUCCESS;
501 : }
502 :
503 :
504 2215 : static int generate_possibleInferiors(struct ldb_context *ldb, struct ldb_message *msg,
505 : const struct dsdb_schema *schema)
506 : {
507 2215 : struct ldb_dn *dn = msg->dn;
508 0 : unsigned int i;
509 0 : int ret;
510 2215 : const char *first_component_name = ldb_dn_get_component_name(dn, 0);
511 0 : const struct ldb_val *first_component_val;
512 0 : const struct dsdb_class *schema_class;
513 0 : const char **possibleInferiors;
514 :
515 2215 : if (strcasecmp(first_component_name, "cn") != 0) {
516 0 : return LDB_SUCCESS;
517 : }
518 :
519 2215 : first_component_val = ldb_dn_get_component_val(dn, 0);
520 :
521 2215 : schema_class = dsdb_class_by_cn_ldb_val(schema, first_component_val);
522 2215 : if (schema_class == NULL) {
523 0 : return LDB_SUCCESS;
524 : }
525 :
526 2215 : possibleInferiors = schema_class->possibleInferiors;
527 2215 : if (possibleInferiors == NULL) {
528 1361 : return LDB_SUCCESS;
529 : }
530 :
531 13528 : for (i=0;possibleInferiors[i];i++) {
532 12674 : char *v = talloc_strdup(msg, possibleInferiors[i]);
533 12674 : if (v == NULL) {
534 0 : return ldb_oom(ldb);
535 : }
536 12674 : ret = ldb_msg_add_steal_string(msg, "possibleInferiors", v);
537 12674 : if (ret != LDB_SUCCESS) {
538 0 : return ret;
539 : }
540 : }
541 :
542 854 : return LDB_SUCCESS;
543 : }
544 :
545 :
546 : /* Add objectClasses, attributeTypes and dITContentRules from the
547 : schema object (they are not stored in the database)
548 : */
549 4448 : static int schema_data_search_callback(struct ldb_request *req, struct ldb_reply *ares)
550 : {
551 0 : struct ldb_context *ldb;
552 0 : struct schema_data_search_data *ac;
553 0 : struct schema_data_private_data *mc;
554 0 : unsigned int i;
555 0 : int ret;
556 :
557 4448 : ac = talloc_get_type(req->context, struct schema_data_search_data);
558 4448 : mc = talloc_get_type(ldb_module_get_private(ac->module), struct schema_data_private_data);
559 4448 : ldb = ldb_module_get_ctx(ac->module);
560 :
561 4448 : if (!ares) {
562 0 : return ldb_module_done(ac->req, NULL, NULL,
563 : LDB_ERR_OPERATIONS_ERROR);
564 : }
565 4448 : if (ares->error != LDB_SUCCESS) {
566 0 : return ldb_module_done(ac->req, ares->controls,
567 : ares->response, ares->error);
568 : }
569 : /* Only entries are interesting, and we handle the case of the parent separately */
570 :
571 4448 : switch (ares->type) {
572 2224 : case LDB_REPLY_ENTRY:
573 :
574 2224 : if (ldb_dn_compare(ares->message->dn, mc->aggregate_dn) == 0) {
575 63 : for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
576 99 : if (generated_attrs[i].aggregate &&
577 45 : ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
578 27 : ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
579 27 : if (ret != LDB_SUCCESS) {
580 0 : return ret;
581 : }
582 : }
583 : }
584 2215 : } else if ((ldb_dn_compare_base(mc->schema_dn, ares->message->dn) == 0)
585 2215 : && (ldb_dn_compare(mc->schema_dn, ares->message->dn) != 0)) {
586 15505 : for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
587 15505 : if (!generated_attrs[i].aggregate &&
588 2215 : ldb_attr_in_list(ac->req->op.search.attrs, generated_attrs[i].attr)) {
589 2215 : ret = generated_attrs[i].fn(ldb, ares->message, ac->schema);
590 2215 : if (ret != LDB_SUCCESS) {
591 0 : return ret;
592 : }
593 : }
594 : }
595 : }
596 :
597 :
598 2224 : return ldb_module_send_entry(ac->req, ares->message, ares->controls);
599 :
600 0 : case LDB_REPLY_REFERRAL:
601 :
602 0 : return ldb_module_send_referral(ac->req, ares->referral);
603 :
604 2224 : case LDB_REPLY_DONE:
605 :
606 2224 : return ldb_module_done(ac->req, ares->controls,
607 : ares->response, ares->error);
608 : }
609 :
610 0 : return LDB_SUCCESS;
611 : }
612 :
613 : /* search */
614 27658683 : static int schema_data_search(struct ldb_module *module, struct ldb_request *req)
615 : {
616 27658683 : struct ldb_context *ldb = ldb_module_get_ctx(module);
617 1203884 : unsigned int i;
618 1203884 : int ret;
619 1203884 : struct schema_data_search_data *search_context;
620 1203884 : struct ldb_request *down_req;
621 1203884 : const struct dsdb_schema *schema;
622 27658683 : if (!ldb_module_get_private(module)) {
623 : /* If there is no module data, there is little we can do */
624 0 : return ldb_next_request(module, req);
625 : }
626 :
627 : /* The schema manipulation does not apply to special DNs */
628 27658683 : if (ldb_dn_is_special(req->op.search.base)) {
629 10551 : return ldb_next_request(module, req);
630 : }
631 :
632 193534655 : for (i=0; i < ARRAY_SIZE(generated_attrs); i++) {
633 165888747 : if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) {
634 2224 : break;
635 : }
636 : }
637 27648132 : if (i == ARRAY_SIZE(generated_attrs)) {
638 : /* No request for a generated attr found, nothing to
639 : * see here, move along... */
640 27645908 : return ldb_next_request(module, req);
641 : }
642 :
643 2224 : schema = dsdb_get_schema(ldb, NULL);
644 2224 : if (!schema || !ldb_module_get_private(module)) {
645 : /* If there is no schema, there is little we can do */
646 0 : return ldb_next_request(module, req);
647 : }
648 :
649 2224 : search_context = talloc(req, struct schema_data_search_data);
650 2224 : if (!search_context) {
651 0 : return ldb_oom(ldb);
652 : }
653 :
654 2224 : search_context->module = module;
655 2224 : search_context->req = req;
656 2224 : search_context->schema = talloc_reference(search_context, schema);
657 2224 : if (!search_context->schema) {
658 0 : return ldb_oom(ldb);
659 : }
660 :
661 2224 : ret = ldb_build_search_req_ex(&down_req, ldb, search_context,
662 : req->op.search.base,
663 : req->op.search.scope,
664 : req->op.search.tree,
665 : req->op.search.attrs,
666 : req->controls,
667 : search_context, schema_data_search_callback,
668 : req);
669 2224 : LDB_REQ_SET_LOCATION(down_req);
670 2224 : if (ret != LDB_SUCCESS) {
671 0 : return ldb_operr(ldb);
672 : }
673 :
674 2224 : return ldb_next_request(module, down_req);
675 : }
676 :
677 :
678 : static const struct ldb_module_ops ldb_schema_data_module_ops = {
679 : .name = "schema_data",
680 : .init_context = schema_data_init,
681 : .add = schema_data_add,
682 : .modify = schema_data_modify,
683 : .del = schema_data_del,
684 : .search = schema_data_search
685 : };
686 :
687 6040 : int ldb_schema_data_module_init(const char *version)
688 : {
689 6040 : LDB_MODULE_CHECK_VERSION(version);
690 6040 : return ldb_register_module(&ldb_schema_data_module_ops);
691 : }
|