Line data Source code
1 : /*
2 : Partitions ldb module
3 :
4 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
5 : Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : /*
22 : * Name: ldb
23 : *
24 : * Component: ldb partitions module
25 : *
26 : * Description: Implement LDAP partitions
27 : *
28 : * Author: Andrew Bartlett
29 : * Author: Stefan Metzmacher
30 : */
31 :
32 : #include "dsdb/samdb/ldb_modules/partition.h"
33 :
34 : struct part_request {
35 : struct ldb_module *module;
36 : struct ldb_request *req;
37 : };
38 :
39 : struct partition_context {
40 : struct ldb_module *module;
41 : struct ldb_request *req;
42 :
43 : struct part_request *part_req;
44 : unsigned int num_requests;
45 : unsigned int finished_requests;
46 :
47 : const char **referrals;
48 : };
49 :
50 55736059 : static struct partition_context *partition_init_ctx(struct ldb_module *module, struct ldb_request *req)
51 : {
52 2454981 : struct partition_context *ac;
53 :
54 55736059 : ac = talloc_zero(req, struct partition_context);
55 55736059 : if (ac == NULL) {
56 0 : ldb_set_errstring(ldb_module_get_ctx(module), "Out of Memory");
57 0 : return NULL;
58 : }
59 :
60 55736059 : ac->module = module;
61 55736059 : ac->req = req;
62 :
63 55736059 : return ac;
64 : }
65 :
66 : /*
67 : * helper functions to call the next module in chain
68 : */
69 127237071 : int partition_request(struct ldb_module *module, struct ldb_request *request)
70 : {
71 127237071 : if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) { \
72 0 : const struct dsdb_control_current_partition *partition = NULL;
73 0 : struct ldb_control *partition_ctrl = ldb_request_get_control(request, DSDB_CONTROL_CURRENT_PARTITION_OID);
74 0 : if (partition_ctrl) {
75 0 : partition = talloc_get_type(partition_ctrl->data,
76 : struct dsdb_control_current_partition);
77 : }
78 :
79 0 : if (partition != NULL) {
80 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_request() -> %s",
81 0 : ldb_dn_get_linearized(partition->dn));
82 : } else {
83 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_request() -> (metadata partition)");
84 : }
85 : }
86 :
87 127237071 : return ldb_next_request(module, request);
88 : }
89 :
90 57776017 : static struct dsdb_partition *find_partition(struct partition_private_data *data,
91 : struct ldb_dn *dn,
92 : struct ldb_request *req)
93 : {
94 2504508 : unsigned int i;
95 2504508 : struct ldb_control *partition_ctrl;
96 :
97 : /* see if the request has the partition DN specified in a
98 : * control. The repl_meta_data module can specify this to
99 : * ensure that replication happens to the right partition
100 : */
101 57776017 : partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
102 57776017 : if (partition_ctrl) {
103 621419 : const struct dsdb_control_current_partition *partition;
104 7583398 : partition = talloc_get_type(partition_ctrl->data,
105 : struct dsdb_control_current_partition);
106 7583398 : if (partition != NULL) {
107 285413 : dn = partition->dn;
108 : }
109 : }
110 :
111 57776017 : if (dn == NULL) {
112 52881872 : return NULL;
113 : }
114 :
115 : /* Look at base DN */
116 : /* Figure out which partition it is under */
117 : /* Skip the lot if 'data' isn't here yet (initialisation) */
118 7501225 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
119 7500467 : if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, dn) == 0) {
120 2504139 : return data->partitions[i];
121 : }
122 : }
123 :
124 702 : return NULL;
125 : }
126 :
127 : /**
128 : * fire the caller's callback for every entry, but only send 'done' once.
129 : */
130 226500776 : static int partition_req_callback(struct ldb_request *req,
131 : struct ldb_reply *ares)
132 : {
133 6790384 : struct partition_context *ac;
134 6790384 : struct ldb_module *module;
135 6790384 : struct ldb_request *nreq;
136 6790384 : int ret;
137 6790384 : struct ldb_control *partition_ctrl;
138 :
139 226500776 : ac = talloc_get_type(req->context, struct partition_context);
140 :
141 226500776 : if (!ares) {
142 0 : return ldb_module_done(ac->req, NULL, NULL,
143 : LDB_ERR_OPERATIONS_ERROR);
144 : }
145 :
146 226500776 : partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID);
147 226500776 : if (partition_ctrl && (ac->num_requests == 1 || ares->type == LDB_REPLY_ENTRY)) {
148 : /* If we didn't fan this request out to multiple partitions,
149 : * or this is an individual search result, we can
150 : * deterministically tell the caller what partition this was
151 : * written to (repl_meta_data likes to know) */
152 11660691 : ret = ldb_reply_add_control(ares,
153 : DSDB_CONTROL_CURRENT_PARTITION_OID,
154 : false, partition_ctrl->data);
155 11660691 : if (ret != LDB_SUCCESS) {
156 0 : return ldb_module_done(ac->req, NULL, NULL,
157 : ret);
158 : }
159 : }
160 :
161 226500776 : if (ares->error != LDB_SUCCESS) {
162 2173823 : return ldb_module_done(ac->req, ares->controls,
163 : ares->response, ares->error);
164 : }
165 :
166 224326953 : switch (ares->type) {
167 0 : case LDB_REPLY_REFERRAL:
168 0 : return ldb_module_send_referral(ac->req, ares->referral);
169 :
170 99317516 : case LDB_REPLY_ENTRY:
171 99317516 : if (ac->req->operation != LDB_SEARCH) {
172 0 : ldb_set_errstring(ldb_module_get_ctx(ac->module),
173 : "partition_req_callback:"
174 : " Unsupported reply type for this request");
175 0 : return ldb_module_done(ac->req, NULL, NULL,
176 : LDB_ERR_OPERATIONS_ERROR);
177 : }
178 :
179 99317516 : return ldb_module_send_entry(ac->req, ares->message, ares->controls);
180 :
181 125009437 : case LDB_REPLY_DONE:
182 125009437 : if (ac->req->operation == LDB_EXTENDED) {
183 : /* FIXME: check for ares->response, replmd does not fill it ! */
184 0 : if (ares->response) {
185 0 : if (strcmp(ares->response->oid, LDB_EXTENDED_START_TLS_OID) != 0) {
186 0 : ldb_set_errstring(ldb_module_get_ctx(ac->module),
187 : "partition_req_callback:"
188 : " Unknown extended reply, "
189 : "only supports START_TLS");
190 0 : talloc_free(ares);
191 0 : return ldb_module_done(ac->req, NULL, NULL,
192 : LDB_ERR_OPERATIONS_ERROR);
193 : }
194 : }
195 : }
196 :
197 125009437 : ac->finished_requests++;
198 125009437 : if (ac->finished_requests == ac->num_requests) {
199 : /* Send back referrals if they do exist (search ops) */
200 53507644 : if (ac->referrals != NULL) {
201 : const char **ref;
202 6135418 : for (ref = ac->referrals; *ref != NULL; ++ref) {
203 4190615 : ret = ldb_module_send_referral(ac->req,
204 4190615 : talloc_strdup(ac->req, *ref));
205 4190615 : if (ret != LDB_SUCCESS) {
206 0 : return ldb_module_done(ac->req, NULL, NULL,
207 : ret);
208 : }
209 : }
210 : }
211 :
212 : /* this was the last one, call callback */
213 53507644 : return ldb_module_done(ac->req, ares->controls,
214 : ares->response,
215 : ares->error);
216 : }
217 :
218 : /* not the last, now call the next one */
219 71501793 : module = ac->part_req[ac->finished_requests].module;
220 71501793 : nreq = ac->part_req[ac->finished_requests].req;
221 :
222 71501793 : ret = partition_request(module, nreq);
223 71501793 : if (ret != LDB_SUCCESS) {
224 0 : talloc_free(ares);
225 0 : return ldb_module_done(ac->req, NULL, NULL, ret);
226 : }
227 :
228 69820228 : break;
229 : }
230 :
231 71501793 : talloc_free(ares);
232 71501793 : return LDB_SUCCESS;
233 : }
234 :
235 127237047 : static int partition_prep_request(struct partition_context *ac,
236 : struct dsdb_partition *partition)
237 : {
238 4136485 : int ret;
239 4136485 : struct ldb_request *req;
240 127237047 : struct ldb_control *partition_ctrl = NULL;
241 127237047 : void *part_data = NULL;
242 :
243 127237047 : ac->part_req = talloc_realloc(ac, ac->part_req,
244 : struct part_request,
245 : ac->num_requests + 1);
246 127237047 : if (ac->part_req == NULL) {
247 0 : return ldb_oom(ldb_module_get_ctx(ac->module));
248 : }
249 :
250 127237047 : switch (ac->req->operation) {
251 124951595 : case LDB_SEARCH:
252 124951595 : ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(ac->module),
253 120929560 : ac->part_req,
254 120929560 : ac->req->op.search.base,
255 120929560 : ac->req->op.search.scope,
256 120929560 : ac->req->op.search.tree,
257 120929560 : ac->req->op.search.attrs,
258 120929560 : ac->req->controls,
259 : ac, partition_req_callback,
260 : ac->req);
261 124951595 : LDB_REQ_SET_LOCATION(req);
262 124951595 : break;
263 923595 : case LDB_ADD:
264 923595 : ret = ldb_build_add_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
265 839862 : ac->req->op.add.message,
266 839862 : ac->req->controls,
267 : ac, partition_req_callback,
268 : ac->req);
269 923595 : LDB_REQ_SET_LOCATION(req);
270 923595 : break;
271 1281027 : case LDB_MODIFY:
272 1281027 : ret = ldb_build_mod_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
273 1250493 : ac->req->op.mod.message,
274 1250493 : ac->req->controls,
275 : ac, partition_req_callback,
276 : ac->req);
277 1281027 : LDB_REQ_SET_LOCATION(req);
278 1281027 : break;
279 33 : case LDB_DELETE:
280 33 : ret = ldb_build_del_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
281 7 : ac->req->op.del.dn,
282 7 : ac->req->controls,
283 : ac, partition_req_callback,
284 : ac->req);
285 33 : LDB_REQ_SET_LOCATION(req);
286 33 : break;
287 80797 : case LDB_RENAME:
288 80797 : ret = ldb_build_rename_req(&req, ldb_module_get_ctx(ac->module), ac->part_req,
289 80640 : ac->req->op.rename.olddn,
290 80640 : ac->req->op.rename.newdn,
291 80640 : ac->req->controls,
292 : ac, partition_req_callback,
293 : ac->req);
294 80797 : LDB_REQ_SET_LOCATION(req);
295 80797 : break;
296 0 : case LDB_EXTENDED:
297 0 : ret = ldb_build_extended_req(&req, ldb_module_get_ctx(ac->module),
298 0 : ac->part_req,
299 0 : ac->req->op.extended.oid,
300 0 : ac->req->op.extended.data,
301 0 : ac->req->controls,
302 : ac, partition_req_callback,
303 : ac->req);
304 0 : LDB_REQ_SET_LOCATION(req);
305 0 : break;
306 0 : default:
307 0 : ldb_set_errstring(ldb_module_get_ctx(ac->module),
308 : "Unsupported request type!");
309 0 : ret = LDB_ERR_UNWILLING_TO_PERFORM;
310 : }
311 :
312 127237047 : if (ret != LDB_SUCCESS) {
313 0 : return ret;
314 : }
315 :
316 127237047 : ac->part_req[ac->num_requests].req = req;
317 :
318 127237047 : if (ac->req->controls) {
319 : /* Duplicate everything beside the current partition control */
320 120823186 : partition_ctrl = ldb_request_get_control(ac->req,
321 : DSDB_CONTROL_CURRENT_PARTITION_OID);
322 120823186 : if (!ldb_save_controls(partition_ctrl, req, NULL)) {
323 0 : return ldb_module_oom(ac->module);
324 : }
325 : }
326 :
327 127237047 : part_data = partition->ctrl;
328 :
329 127237047 : ac->part_req[ac->num_requests].module = partition->module;
330 :
331 127237047 : if (partition_ctrl != NULL) {
332 7525472 : if (partition_ctrl->data != NULL) {
333 228096 : part_data = partition_ctrl->data;
334 : }
335 :
336 : /*
337 : * If the provided current partition control is without
338 : * data then use the calculated one.
339 : */
340 7525472 : ret = ldb_request_add_control(req,
341 : DSDB_CONTROL_CURRENT_PARTITION_OID,
342 : false, part_data);
343 7525472 : if (ret != LDB_SUCCESS) {
344 0 : return ret;
345 : }
346 : }
347 :
348 127237047 : if (req->operation == LDB_SEARCH) {
349 : /*
350 : * If the search is for 'more' than this partition,
351 : * then change the basedn, so the check of the BASE DN
352 : * still passes in the ldb_key_value layer
353 : */
354 124951595 : if (ldb_dn_compare_base(partition->ctrl->dn,
355 120929560 : req->op.search.base) != 0) {
356 91094050 : req->op.search.base = partition->ctrl->dn;
357 : }
358 : }
359 :
360 127237047 : ac->num_requests++;
361 :
362 127237047 : return LDB_SUCCESS;
363 : }
364 :
365 55735254 : static int partition_call_first(struct partition_context *ac)
366 : {
367 55735254 : return partition_request(ac->part_req[0].module, ac->part_req[0].req);
368 : }
369 :
370 : /**
371 : * Send a request down to all the partitions (but not the sam.ldb file)
372 : */
373 19592257 : static int partition_send_all(struct ldb_module *module,
374 : struct partition_context *ac,
375 : struct ldb_request *req)
376 : {
377 466066 : unsigned int i;
378 19592257 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
379 : struct partition_private_data);
380 466066 : int ret;
381 :
382 111061632 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
383 91003309 : ret = partition_prep_request(ac, data->partitions[i]);
384 91003309 : if (ret != LDB_SUCCESS) {
385 0 : return ret;
386 : }
387 : }
388 :
389 : /* fire the first one */
390 19592257 : return partition_call_first(ac);
391 : }
392 :
393 : struct partition_copy_context {
394 : struct ldb_module *module;
395 : struct partition_context *partition_context;
396 : struct ldb_request *request;
397 : struct ldb_dn *dn;
398 : };
399 :
400 : /*
401 : * A special DN has been updated in the primary partition. Now propagate those
402 : * changes to the remaining partitions.
403 : *
404 : * Note: that the operations are asynchronous and this function is called
405 : * from partition_copy_all_callback_handler in response to an async
406 : * callback.
407 : */
408 272 : static int partition_copy_all_callback_action(
409 : struct ldb_module *module,
410 : struct partition_context *ac,
411 : struct ldb_request *req,
412 : struct ldb_dn *dn)
413 :
414 : {
415 :
416 32 : unsigned int i;
417 32 : struct partition_private_data *data =
418 272 : talloc_get_type(
419 : ldb_module_get_private(module),
420 : struct partition_private_data);
421 32 : int search_ret;
422 32 : struct ldb_result *res;
423 : /* now fetch the resulting object, and then copy it to all the
424 : * other partitions. We need this approach to cope with the
425 : * partitions getting out of sync. If for example the
426 : * @ATTRIBUTES object exists on one partition but not the
427 : * others then just doing each of the partitions in turn will
428 : * lead to an error
429 : */
430 272 : search_ret = dsdb_module_search_dn(module, ac, &res, dn, NULL, DSDB_FLAG_NEXT_MODULE, req);
431 272 : if (search_ret != LDB_SUCCESS && search_ret != LDB_ERR_NO_SUCH_OBJECT) {
432 0 : return search_ret;
433 : }
434 :
435 : /* now delete the object in the other partitions, if required
436 : */
437 272 : if (search_ret == LDB_ERR_NO_SUCH_OBJECT) {
438 0 : for (i=0; data->partitions && data->partitions[i]; i++) {
439 0 : int pret;
440 0 : pret = dsdb_module_del(data->partitions[i]->module,
441 : dn,
442 : DSDB_FLAG_NEXT_MODULE,
443 : req);
444 0 : if (pret != LDB_SUCCESS && pret != LDB_ERR_NO_SUCH_OBJECT) {
445 : /* we should only get success or no
446 : such object from the other partitions */
447 0 : return pret;
448 : }
449 : }
450 :
451 0 : return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
452 : }
453 :
454 : /* now add/modify in the other partitions */
455 1566 : for (i=0; data->partitions && data->partitions[i]; i++) {
456 1294 : struct ldb_message *modify_msg = NULL;
457 152 : int pret;
458 152 : unsigned int el_idx;
459 :
460 1446 : pret = dsdb_module_add(data->partitions[i]->module,
461 1294 : res->msgs[0],
462 : DSDB_FLAG_NEXT_MODULE,
463 : req);
464 1294 : if (pret == LDB_SUCCESS) {
465 0 : continue;
466 : }
467 :
468 1294 : if (pret != LDB_ERR_ENTRY_ALREADY_EXISTS) {
469 0 : return pret;
470 : }
471 :
472 1294 : modify_msg = ldb_msg_copy(req, res->msgs[0]);
473 1294 : if (modify_msg == NULL) {
474 0 : return ldb_module_oom(module);
475 : }
476 :
477 : /*
478 : * mark all the message elements as
479 : * LDB_FLAG_MOD_REPLACE
480 : */
481 1142 : for (el_idx=0;
482 548377 : el_idx < modify_msg->num_elements;
483 547083 : el_idx++) {
484 547083 : modify_msg->elements[el_idx].flags
485 547083 : = LDB_FLAG_MOD_REPLACE;
486 : }
487 :
488 1294 : if (req->operation == LDB_MODIFY) {
489 1294 : const struct ldb_message *req_msg = req->op.mod.message;
490 : /*
491 : * mark elements to be removed, if these were
492 : * deleted entirely above we need to delete
493 : * them here too
494 : */
495 15331 : for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) {
496 14037 : if (LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_DELETE
497 12971 : || ((LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_REPLACE) &&
498 9168 : req_msg->elements[el_idx].num_values == 0)) {
499 1066 : if (ldb_msg_find_element(modify_msg,
500 962 : req_msg->elements[el_idx].name) != NULL) {
501 0 : continue;
502 : }
503 1170 : pret = ldb_msg_add_empty(
504 : modify_msg,
505 1066 : req_msg->elements[el_idx].name,
506 : LDB_FLAG_MOD_REPLACE,
507 : NULL);
508 1066 : if (pret != LDB_SUCCESS) {
509 0 : return pret;
510 : }
511 : }
512 : }
513 : }
514 :
515 1294 : pret = dsdb_module_modify(data->partitions[i]->module,
516 : modify_msg,
517 : DSDB_FLAG_NEXT_MODULE,
518 : req);
519 :
520 1294 : if (pret != LDB_SUCCESS) {
521 0 : return pret;
522 : }
523 : }
524 :
525 272 : return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
526 : }
527 :
528 :
529 : /*
530 : * @brief call back function for the ldb operations on special DN's.
531 : *
532 : * As the LDB operations are async, and we wish to use the result
533 : * the operations, a callback needs to be registered to process the results
534 : * of the LDB operations.
535 : *
536 : * @param req the ldb request
537 : * @param res the result of the operation
538 : *
539 : * @return the LDB_STATUS
540 : */
541 274 : static int partition_copy_all_callback_handler(
542 : struct ldb_request *req,
543 : struct ldb_reply *ares)
544 : {
545 274 : struct partition_copy_context *ac = NULL;
546 :
547 274 : ac = talloc_get_type(
548 : req->context,
549 : struct partition_copy_context);
550 :
551 274 : if (!ares) {
552 0 : return ldb_module_done(
553 : ac->request,
554 : NULL,
555 : NULL,
556 : LDB_ERR_OPERATIONS_ERROR);
557 : }
558 :
559 : /* pass on to the callback */
560 274 : switch (ares->type) {
561 0 : case LDB_REPLY_ENTRY:
562 0 : return ldb_module_send_entry(
563 : ac->request,
564 : ares->message,
565 : ares->controls);
566 :
567 0 : case LDB_REPLY_REFERRAL:
568 0 : return ldb_module_send_referral(
569 : ac->request,
570 : ares->referral);
571 :
572 274 : case LDB_REPLY_DONE: {
573 274 : int error = ares->error;
574 274 : if (error == LDB_SUCCESS) {
575 272 : error = partition_copy_all_callback_action(
576 : ac->module,
577 : ac->partition_context,
578 : ac->request,
579 : ac->dn);
580 : }
581 274 : return ldb_module_done(
582 : ac->request,
583 : ares->controls,
584 : ares->response,
585 : error);
586 : }
587 :
588 0 : default:
589 : /* Can't happen */
590 0 : return LDB_ERR_OPERATIONS_ERROR;
591 : }
592 : }
593 :
594 : /**
595 : * send an operation to the top partition, then copy the resulting
596 : * object to all other partitions.
597 : */
598 274 : static int partition_copy_all(
599 : struct ldb_module *module,
600 : struct partition_context *partition_context,
601 : struct ldb_request *req,
602 : struct ldb_dn *dn)
603 : {
604 274 : struct ldb_request *new_req = NULL;
605 274 : struct ldb_context *ldb = NULL;
606 274 : struct partition_copy_context *context = NULL;
607 :
608 32 : int ret;
609 :
610 274 : ldb = ldb_module_get_ctx(module);
611 :
612 274 : context = talloc_zero(req, struct partition_copy_context);
613 274 : if (context == NULL) {
614 0 : return ldb_oom(ldb);
615 : }
616 274 : context->module = module;
617 274 : context->request = req;
618 274 : context->dn = dn;
619 274 : context->partition_context = partition_context;
620 :
621 274 : switch (req->operation) {
622 0 : case LDB_ADD:
623 0 : ret = ldb_build_add_req(
624 : &new_req,
625 : ldb,
626 : req,
627 : req->op.add.message,
628 : req->controls,
629 : context,
630 : partition_copy_all_callback_handler,
631 : req);
632 0 : break;
633 274 : case LDB_MODIFY:
634 274 : ret = ldb_build_mod_req(
635 : &new_req,
636 : ldb,
637 : req,
638 : req->op.mod.message,
639 : req->controls,
640 : context,
641 : partition_copy_all_callback_handler,
642 : req);
643 274 : break;
644 0 : case LDB_DELETE:
645 0 : ret = ldb_build_del_req(
646 : &new_req,
647 : ldb,
648 : req,
649 : req->op.del.dn,
650 : req->controls,
651 : context,
652 : partition_copy_all_callback_handler,
653 : req);
654 0 : break;
655 0 : case LDB_RENAME:
656 0 : ret = ldb_build_rename_req(
657 : &new_req,
658 : ldb,
659 : req,
660 : req->op.rename.olddn,
661 : req->op.rename.newdn,
662 : req->controls,
663 : context,
664 : partition_copy_all_callback_handler,
665 : req);
666 0 : break;
667 0 : default:
668 : /*
669 : * Shouldn't happen.
670 : */
671 0 : ldb_debug(
672 : ldb,
673 : LDB_DEBUG_ERROR,
674 0 : "Unexpected operation type (%d)\n", req->operation);
675 0 : ret = LDB_ERR_OPERATIONS_ERROR;
676 0 : break;
677 : }
678 274 : if (ret != LDB_SUCCESS) {
679 0 : return ret;
680 : }
681 274 : return ldb_next_request(module, new_req);
682 : }
683 : /**
684 : * Figure out which backend a request needs to be aimed at. Some
685 : * requests must be replicated to all backends
686 : */
687 2286712 : static int partition_replicate(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn)
688 : {
689 114582 : struct partition_context *ac;
690 114582 : unsigned int i;
691 114582 : int ret;
692 114582 : struct dsdb_partition *partition;
693 2286712 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
694 : struct partition_private_data);
695 :
696 : /* if we aren't initialised yet go further */
697 2286712 : if (!data || !data->partitions) {
698 458 : return ldb_next_request(module, req);
699 : }
700 :
701 2286254 : if (ldb_dn_is_special(dn)) {
702 : /* Is this a special DN, we need to replicate to every backend? */
703 914830 : for (i=0; data->replicate && data->replicate[i]; i++) {
704 686212 : if (ldb_dn_compare(data->replicate[i],
705 : dn) == 0) {
706 :
707 274 : ac = partition_init_ctx(module, req);
708 274 : if (!ac) {
709 0 : return ldb_operr(ldb_module_get_ctx(module));
710 : }
711 :
712 274 : return partition_copy_all(module, ac, req, dn);
713 : }
714 : }
715 : }
716 :
717 : /* Otherwise, we need to find the partition to fire it to */
718 :
719 : /* Find partition */
720 2285980 : partition = find_partition(data, dn, req);
721 2285980 : if (!partition) {
722 : /*
723 : * if we haven't found a matching partition
724 : * pass the request to the main ldb
725 : *
726 : * TODO: we should maybe return an error here
727 : * if it's not a special dn
728 : */
729 :
730 528 : return ldb_next_request(module, req);
731 : }
732 :
733 2285452 : ac = partition_init_ctx(module, req);
734 2285452 : if (!ac) {
735 0 : return ldb_operr(ldb_module_get_ctx(module));
736 : }
737 :
738 : /* we need to add a control but we never touch the original request */
739 2285452 : ret = partition_prep_request(ac, partition);
740 2285452 : if (ret != LDB_SUCCESS) {
741 0 : return ret;
742 : }
743 :
744 : /* fire the first one */
745 2285452 : return partition_call_first(ac);
746 : }
747 :
748 : /* search */
749 55328437 : static int partition_search(struct ldb_module *module, struct ldb_request *req)
750 : {
751 : /* Find backend */
752 55328437 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
753 : struct partition_private_data);
754 2389688 : struct partition_context *ac;
755 2389688 : struct ldb_context *ldb;
756 2389688 : struct loadparm_context *lp_ctx;
757 :
758 55328437 : struct ldb_control *search_control = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
759 55328437 : struct ldb_control *domain_scope_control = ldb_request_get_control(req, LDB_CONTROL_DOMAIN_SCOPE_OID);
760 55328437 : struct ldb_control *no_gc_control = ldb_request_get_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG);
761 :
762 55328437 : struct ldb_search_options_control *search_options = NULL;
763 2389688 : struct dsdb_partition *p;
764 2389688 : unsigned int i, j;
765 2389688 : int ret;
766 55328437 : bool domain_scope = false, phantom_root = false;
767 :
768 55328437 : p = find_partition(data, NULL, req);
769 55328437 : if (p != NULL) {
770 : /* the caller specified what partition they want the
771 : * search - just pass it on
772 : */
773 57089 : return ldb_next_request(p->module, req);
774 : }
775 :
776 : /* Get back the search options from the search control, and mark it as
777 : * non-critical (to make backends and also dcpromo happy).
778 : */
779 55271348 : if (search_control) {
780 19620337 : search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
781 19620337 : search_control->critical = 0;
782 :
783 : }
784 :
785 : /* if we aren't initialised yet go further */
786 55271348 : if (!data || !data->partitions) {
787 187176 : return ldb_next_request(module, req);
788 : }
789 :
790 : /* Special DNs without specified partition should go further */
791 55084172 : if (ldb_dn_is_special(req->op.search.base)) {
792 1633839 : return ldb_next_request(module, req);
793 : }
794 :
795 : /* Locate the options */
796 55790832 : domain_scope = (search_options
797 19620337 : && (search_options->search_options & LDB_SEARCH_OPTION_DOMAIN_SCOPE))
798 73070670 : || domain_scope_control;
799 55790832 : phantom_root = search_options
800 53450333 : && (search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT);
801 :
802 : /* Remove handled options from the search control flag */
803 53450333 : if (search_options) {
804 19620337 : search_options->search_options = search_options->search_options
805 : & ~LDB_SEARCH_OPTION_DOMAIN_SCOPE
806 19620337 : & ~LDB_SEARCH_OPTION_PHANTOM_ROOT;
807 : }
808 :
809 53450333 : ac = partition_init_ctx(module, req);
810 53450333 : if (!ac) {
811 0 : return ldb_operr(ldb_module_get_ctx(module));
812 : }
813 :
814 53450333 : ldb = ldb_module_get_ctx(ac->module);
815 53450333 : lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
816 : struct loadparm_context);
817 :
818 : /* Search from the base DN */
819 53450333 : if (ldb_dn_is_null(req->op.search.base)) {
820 19592257 : if (!phantom_root) {
821 0 : return ldb_error(ldb, LDB_ERR_NO_SUCH_OBJECT, "empty base DN");
822 : }
823 19592257 : return partition_send_all(module, ac, req);
824 : }
825 :
826 103949168 : for (i=0; data->partitions[i]; i++) {
827 103948637 : bool match = false, stop = false;
828 :
829 103948637 : if (data->partitions[i]->partial_replica && no_gc_control != NULL) {
830 0 : if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn,
831 : req->op.search.base) == 0) {
832 : /* base DN is in a partial replica
833 : with the NO_GLOBAL_CATALOG
834 : control. This partition is invisible */
835 : /* DEBUG(0,("DENYING NON-GC OP: %s\n", ldb_module_call_chain(req, req))); */
836 0 : continue;
837 : }
838 : }
839 :
840 103948637 : if (phantom_root) {
841 : /* Phantom root: Find all partitions under the
842 : * search base. We match if:
843 : *
844 : * 1) the DN we are looking for exactly matches a
845 : * certain partition and always stop
846 : * 2) the DN we are looking for is a parent of certain
847 : * partitions and it isn't a scope base search
848 : * 3) the DN we are looking for is a child of a certain
849 : * partition and always stop
850 : * - we don't need to go any further up in the
851 : * hierarchy!
852 : */
853 118571 : if (ldb_dn_compare(data->partitions[i]->ctrl->dn,
854 : req->op.search.base) == 0) {
855 27780 : match = true;
856 27780 : stop = true;
857 : }
858 209362 : if (!match &&
859 90791 : (ldb_dn_compare_base(req->op.search.base,
860 90791 : data->partitions[i]->ctrl->dn) == 0 &&
861 90741 : req->op.search.scope != LDB_SCOPE_BASE)) {
862 90543 : match = true;
863 : }
864 118423 : if (!match &&
865 50 : ldb_dn_compare_base(data->partitions[i]->ctrl->dn,
866 : req->op.search.base) == 0) {
867 16 : match = true;
868 16 : stop = true; /* note that this relies on partition ordering */
869 : }
870 : } else {
871 : /* Domain scope: Find all partitions under the search
872 : * base.
873 : *
874 : * We generate referral candidates if we haven't
875 : * specified the domain scope control, haven't a base
876 : * search* scope and the DN we are looking for is a real
877 : * predecessor of certain partitions. When a new
878 : * referral candidate is nearer to the DN than an
879 : * existing one delete the latter (we want to have only
880 : * the closest ones). When we checked this for all
881 : * candidates we have the final referrals.
882 : *
883 : * We match if the DN we are looking for is a child of
884 : * a certain partition or the partition
885 : * DN itself - we don't need to go any further
886 : * up in the hierarchy!
887 : */
888 103830066 : if ((!domain_scope) &&
889 117420626 : (req->op.search.scope != LDB_SCOPE_BASE) &&
890 13594151 : (ldb_dn_compare_base(req->op.search.base,
891 21824889 : data->partitions[i]->ctrl->dn) == 0) &&
892 8230738 : (ldb_dn_compare(req->op.search.base,
893 8230738 : data->partitions[i]->ctrl->dn) != 0)) {
894 5615833 : const char *scheme = ldb_get_opaque(
895 : ldb, LDAP_REFERRAL_SCHEME_OPAQUE);
896 11200406 : char *ref = talloc_asprintf(
897 : ac,
898 : "%s://%s/%s%s",
899 : scheme == NULL ? "ldap" : scheme,
900 : lpcfg_dnsdomain(lp_ctx),
901 : ldb_dn_get_linearized(
902 5615833 : data->partitions[i]->ctrl->dn),
903 5615833 : req->op.search.scope ==
904 : LDB_SCOPE_ONELEVEL ? "??base" : "");
905 :
906 5615833 : if (ref == NULL) {
907 0 : return ldb_oom(ldb);
908 : }
909 :
910 : /* Initialise the referrals list */
911 5615833 : if (ac->referrals == NULL) {
912 1944978 : char **l = str_list_make_empty(ac);
913 1944978 : ac->referrals = discard_const_p(const char *, l);
914 1944978 : if (ac->referrals == NULL) {
915 0 : return ldb_oom(ldb);
916 : }
917 : }
918 :
919 : /* Check if the new referral candidate is
920 : * closer to the base DN than already
921 : * saved ones and delete the latters */
922 5487203 : j = 0;
923 10409617 : while (ac->referrals[j] != NULL) {
924 4793784 : if (strstr(ac->referrals[j],
925 4793784 : ldb_dn_get_linearized(data->partitions[i]->ctrl->dn)) != NULL) {
926 1424997 : str_list_remove(ac->referrals,
927 1389146 : ac->referrals[j]);
928 : } else {
929 3368787 : ++j;
930 : }
931 : }
932 :
933 : /* Add our new candidate */
934 5615833 : ac->referrals = str_list_add(ac->referrals, ref);
935 :
936 5615833 : talloc_free(ref);
937 :
938 5615833 : if (ac->referrals == NULL) {
939 0 : return ldb_oom(ldb);
940 : }
941 : }
942 103830066 : if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
943 31955397 : match = true;
944 31955397 : stop = true; /* note that this relies on partition ordering */
945 : }
946 : }
947 :
948 99987872 : if (match) {
949 33948286 : ret = partition_prep_request(ac, data->partitions[i]);
950 33948286 : if (ret != LDB_SUCCESS) {
951 0 : return ret;
952 : }
953 : }
954 :
955 103948637 : if (stop) break;
956 : }
957 :
958 : /* Perhaps we didn't match any partitions. Try the main partition */
959 33858076 : if (ac->num_requests == 0) {
960 531 : talloc_free(ac);
961 531 : return ldb_next_request(module, req);
962 : }
963 :
964 : /* fire the first one */
965 33857545 : return partition_call_first(ac);
966 : }
967 :
968 : /* add */
969 924135 : static int partition_add(struct ldb_module *module, struct ldb_request *req)
970 : {
971 924135 : return partition_replicate(module, req, req->op.add.message->dn);
972 : }
973 :
974 : /* modify */
975 1281744 : static int partition_modify(struct ldb_module *module, struct ldb_request *req)
976 : {
977 1281744 : return partition_replicate(module, req, req->op.mod.message->dn);
978 : }
979 :
980 : /* delete */
981 35 : static int partition_delete(struct ldb_module *module, struct ldb_request *req)
982 : {
983 35 : return partition_replicate(module, req, req->op.del.dn);
984 : }
985 :
986 : /* rename */
987 80800 : static int partition_rename(struct ldb_module *module, struct ldb_request *req)
988 : {
989 : /* Find backend */
990 158 : struct dsdb_partition *backend, *backend2;
991 :
992 80800 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
993 : struct partition_private_data);
994 :
995 : /* Skip the lot if 'data' isn't here yet (initialisation) */
996 80800 : if (!data) {
997 0 : return ldb_operr(ldb_module_get_ctx(module));
998 : }
999 :
1000 80800 : backend = find_partition(data, req->op.rename.olddn, req);
1001 80800 : backend2 = find_partition(data, req->op.rename.newdn, req);
1002 :
1003 80800 : if ((backend && !backend2) || (!backend && backend2)) {
1004 0 : return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
1005 : }
1006 :
1007 80800 : if (backend != backend2) {
1008 6 : ldb_asprintf_errstring(ldb_module_get_ctx(module),
1009 : "Cannot rename from %s in %s to %s in %s: %s",
1010 : ldb_dn_get_linearized(req->op.rename.olddn),
1011 2 : ldb_dn_get_linearized(backend->ctrl->dn),
1012 : ldb_dn_get_linearized(req->op.rename.newdn),
1013 2 : ldb_dn_get_linearized(backend2->ctrl->dn),
1014 : ldb_strerror(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
1015 2 : return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
1016 : }
1017 :
1018 80798 : return partition_replicate(module, req, req->op.rename.olddn);
1019 : }
1020 :
1021 : /* start a transaction */
1022 349765 : int partition_start_trans(struct ldb_module *module)
1023 : {
1024 349765 : int i = 0;
1025 349765 : int ret = 0;
1026 349765 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1027 : struct partition_private_data);
1028 : /* Look at base DN */
1029 : /* Figure out which partition it is under */
1030 : /* Skip the lot if 'data' isn't here yet (initialization) */
1031 349765 : if (ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING) {
1032 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> (metadata partition)");
1033 : }
1034 :
1035 : /*
1036 : * We start a transaction on metadata.tdb first and end it last in
1037 : * end_trans. This makes locking semantics follow TDB rather than MDB,
1038 : * and effectively locks all partitions at once.
1039 : * Detail:
1040 : * Samba AD is special in that the partitions module (this file)
1041 : * combines multiple independently locked databases into one overall
1042 : * transaction. Changes across multiple partition DBs in a single
1043 : * transaction must ALL be either visible or invisible.
1044 : * The way this is achieved is by taking out a write lock on
1045 : * metadata.tdb at the start of prepare_commit, while unlocking it at
1046 : * the end of end_trans. This is matched by read_lock, ensuring it
1047 : * can't progress until that write lock is released.
1048 : *
1049 : * metadata.tdb needs to be a TDB file because MDB uses independent
1050 : * locks, which means a read lock and a write lock can be held at the
1051 : * same time, whereas in TDB, the two locks block each other. The TDB
1052 : * behaviour is required to implement the functionality described
1053 : * above.
1054 : *
1055 : * An important additional detail here is that if prepare_commit is
1056 : * called on a TDB without any changes being made, no write lock is
1057 : * taken. We address this by storing a sequence number in metadata.tdb
1058 : * which is updated every time a replicated attribute is modified.
1059 : * The possibility of a few unreplicated attributes being out of date
1060 : * turns out not to be a problem.
1061 : * For this reason, a lock on sam.ldb (which is a TDB) won't achieve
1062 : * the same end as locking metadata.tdb, unless we made a modification
1063 : * to the @ records found there before every prepare_commit.
1064 : */
1065 349765 : ret = partition_metadata_start_trans(module);
1066 349765 : if (ret != LDB_SUCCESS) {
1067 0 : return ret;
1068 : }
1069 :
1070 349765 : ret = ldb_next_start_trans(module);
1071 349765 : if (ret != LDB_SUCCESS) {
1072 0 : partition_metadata_del_trans(module);
1073 0 : return ret;
1074 : }
1075 :
1076 349765 : ret = partition_reload_if_required(module, data, NULL);
1077 349765 : if (ret != LDB_SUCCESS) {
1078 0 : ldb_next_del_trans(module);
1079 0 : partition_metadata_del_trans(module);
1080 0 : return ret;
1081 : }
1082 :
1083 : /*
1084 : * The following per partition locks are required mostly because TDB
1085 : * and MDB require locks before read and write ops are permitted.
1086 : */
1087 2021630 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
1088 1671865 : if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1089 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_start_trans() -> %s",
1090 0 : ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1091 : }
1092 1671865 : ret = ldb_next_start_trans(data->partitions[i]->module);
1093 1671865 : if (ret != LDB_SUCCESS) {
1094 : /* Back it out, if it fails on one */
1095 0 : for (i--; i >= 0; i--) {
1096 0 : ldb_next_del_trans(data->partitions[i]->module);
1097 : }
1098 0 : ldb_next_del_trans(module);
1099 0 : partition_metadata_del_trans(module);
1100 0 : return ret;
1101 : }
1102 : }
1103 :
1104 349765 : data->in_transaction++;
1105 :
1106 349765 : return LDB_SUCCESS;
1107 : }
1108 :
1109 : /* prepare for a commit */
1110 303837 : int partition_prepare_commit(struct ldb_module *module)
1111 : {
1112 2204 : unsigned int i;
1113 303837 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1114 : struct partition_private_data);
1115 2204 : int ret;
1116 :
1117 : /*
1118 : * Order of prepare_commit calls must match that in
1119 : * partition_start_trans. See comment in that function for detail.
1120 : */
1121 303837 : ret = partition_metadata_prepare_commit(module);
1122 303837 : if (ret != LDB_SUCCESS) {
1123 0 : return ret;
1124 : }
1125 :
1126 303837 : ret = ldb_next_prepare_commit(module);
1127 303837 : if (ret != LDB_SUCCESS) {
1128 0 : return ret;
1129 : }
1130 :
1131 1762317 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
1132 1458480 : if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1133 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> %s",
1134 0 : ldb_dn_get_linearized(data->partitions[i]->ctrl->dn));
1135 : }
1136 1458480 : ret = ldb_next_prepare_commit(data->partitions[i]->module);
1137 1458480 : if (ret != LDB_SUCCESS) {
1138 0 : ldb_asprintf_errstring(ldb_module_get_ctx(module), "prepare_commit error on %s: %s",
1139 0 : ldb_dn_get_linearized(data->partitions[i]->ctrl->dn),
1140 : ldb_errstring(ldb_module_get_ctx(module)));
1141 0 : return ret;
1142 : }
1143 : }
1144 :
1145 303837 : if ((module && ldb_module_flags(ldb_module_get_ctx(module)) & LDB_FLG_ENABLE_TRACING)) {
1146 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_prepare_commit() -> (metadata partition)");
1147 : }
1148 :
1149 301633 : return LDB_SUCCESS;
1150 : }
1151 :
1152 :
1153 : /* end a transaction */
1154 304270 : int partition_end_trans(struct ldb_module *module)
1155 : {
1156 2204 : int ret, ret2;
1157 2204 : int i;
1158 304270 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1159 304270 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1160 : struct partition_private_data);
1161 304270 : bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING;
1162 :
1163 304270 : ret = LDB_SUCCESS;
1164 :
1165 304270 : if (data->in_transaction == 0) {
1166 0 : DEBUG(0,("partition end transaction mismatch\n"));
1167 0 : ret = LDB_ERR_OPERATIONS_ERROR;
1168 : } else {
1169 304270 : data->in_transaction--;
1170 : }
1171 :
1172 : /*
1173 : * Order of end_trans calls must be the reverse of that in
1174 : * partition_start_trans. See comment in that function for detail.
1175 : */
1176 304270 : if (data && data->partitions) {
1177 : /* Just counting the partitions */
1178 1764505 : for (i=0; data->partitions[i]; i++) {}
1179 :
1180 : /* now walk them backwards */
1181 1764505 : for (i--; i>=0; i--) {
1182 1460645 : struct dsdb_partition *p = data->partitions[i];
1183 1460645 : if (trace) {
1184 0 : ldb_debug(ldb,
1185 : LDB_DEBUG_TRACE,
1186 : "partition_end_trans() -> %s",
1187 0 : ldb_dn_get_linearized(p->ctrl->dn));
1188 : }
1189 1460645 : ret2 = ldb_next_end_trans(p->module);
1190 1460645 : if (ret2 != LDB_SUCCESS) {
1191 0 : ldb_asprintf_errstring(ldb,
1192 : "end_trans error on %s: %s",
1193 0 : ldb_dn_get_linearized(p->ctrl->dn),
1194 : ldb_errstring(ldb));
1195 0 : ret = ret2;
1196 : }
1197 : }
1198 : }
1199 :
1200 304270 : if (trace) {
1201 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_end_trans() -> (metadata partition)");
1202 : }
1203 304270 : ret2 = ldb_next_end_trans(module);
1204 304270 : if (ret2 != LDB_SUCCESS) {
1205 0 : ret = ret2;
1206 : }
1207 :
1208 304270 : ret2 = partition_metadata_end_trans(module);
1209 304270 : if (ret2 != LDB_SUCCESS) {
1210 0 : ret = ret2;
1211 : }
1212 :
1213 304270 : return ret;
1214 : }
1215 :
1216 : /* delete a transaction */
1217 45493 : int partition_del_trans(struct ldb_module *module)
1218 : {
1219 45493 : int ret, final_ret = LDB_SUCCESS;
1220 4 : int i;
1221 45493 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1222 45493 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1223 : struct partition_private_data);
1224 45493 : bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING;
1225 :
1226 45493 : if (data == NULL) {
1227 0 : DEBUG(0,("partition delete transaction with no private data\n"));
1228 0 : return ldb_operr(ldb);
1229 : }
1230 :
1231 : /*
1232 : * Order of del_trans calls must be the reverse of that in
1233 : * partition_start_trans. See comment in that function for detail.
1234 : */
1235 45493 : if (data->partitions) {
1236 : /* Just counting the partitions */
1237 257682 : for (i=0; data->partitions[i]; i++) {}
1238 :
1239 : /* now walk them backwards */
1240 257682 : for (i--; i>=0; i--) {
1241 212189 : struct dsdb_partition *p = data->partitions[i];
1242 212189 : if (trace) {
1243 0 : ldb_debug(ldb,
1244 : LDB_DEBUG_TRACE,
1245 : "partition_del_trans() -> %s",
1246 0 : ldb_dn_get_linearized(p->ctrl->dn));
1247 : }
1248 212189 : ret = ldb_next_del_trans(p->module);
1249 212189 : if (ret != LDB_SUCCESS) {
1250 0 : ldb_asprintf_errstring(ldb,
1251 : "del_trans error on %s: %s",
1252 0 : ldb_dn_get_linearized(p->ctrl->dn),
1253 : ldb_errstring(ldb));
1254 0 : final_ret = ret;
1255 : }
1256 : }
1257 : }
1258 :
1259 45493 : if (trace) {
1260 0 : ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_TRACE, "partition_del_trans() -> (metadata partition)");
1261 : }
1262 45493 : ret = ldb_next_del_trans(module);
1263 45493 : if (ret != LDB_SUCCESS) {
1264 0 : final_ret = ret;
1265 : }
1266 :
1267 45493 : ret = partition_metadata_del_trans(module);
1268 45493 : if (ret != LDB_SUCCESS) {
1269 0 : final_ret = ret;
1270 : }
1271 :
1272 45493 : if (data->in_transaction == 0) {
1273 0 : DEBUG(0,("partition del transaction mismatch\n"));
1274 0 : return ldb_operr(ldb_module_get_ctx(module));
1275 : }
1276 45493 : data->in_transaction--;
1277 :
1278 45493 : return final_ret;
1279 : }
1280 :
1281 19379278 : int partition_primary_sequence_number(struct ldb_module *module, TALLOC_CTX *mem_ctx,
1282 : uint64_t *seq_number,
1283 : struct ldb_request *parent)
1284 : {
1285 1123789 : int ret;
1286 1123789 : struct ldb_result *res;
1287 1123789 : struct ldb_seqnum_request *tseq;
1288 1123789 : struct ldb_seqnum_result *seqr;
1289 :
1290 19379278 : tseq = talloc_zero(mem_ctx, struct ldb_seqnum_request);
1291 19379278 : if (tseq == NULL) {
1292 0 : return ldb_oom(ldb_module_get_ctx(module));
1293 : }
1294 19379278 : tseq->type = LDB_SEQ_HIGHEST_SEQ;
1295 :
1296 19379278 : ret = dsdb_module_extended(module, tseq, &res,
1297 : LDB_EXTENDED_SEQUENCE_NUMBER,
1298 : tseq,
1299 : DSDB_FLAG_NEXT_MODULE,
1300 : parent);
1301 19379278 : if (ret != LDB_SUCCESS) {
1302 0 : talloc_free(tseq);
1303 0 : return ret;
1304 : }
1305 :
1306 19379278 : seqr = talloc_get_type_abort(res->extended->data,
1307 : struct ldb_seqnum_result);
1308 19379278 : if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
1309 0 : talloc_free(res);
1310 0 : return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
1311 : "Primary backend in partition module returned a timestamp based seq");
1312 : }
1313 :
1314 19379278 : *seq_number = seqr->seq_num;
1315 19379278 : talloc_free(tseq);
1316 19379278 : return LDB_SUCCESS;
1317 : }
1318 :
1319 :
1320 : /*
1321 : * Older version of sequence number as sum of sequence numbers for each partition
1322 : */
1323 213 : int partition_sequence_number_from_partitions(struct ldb_module *module,
1324 : uint64_t *seqr)
1325 : {
1326 29 : int ret;
1327 29 : unsigned int i;
1328 213 : uint64_t seq_number = 0;
1329 213 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1330 : struct partition_private_data);
1331 :
1332 213 : ret = partition_primary_sequence_number(module, data, &seq_number, NULL);
1333 213 : if (ret != LDB_SUCCESS) {
1334 0 : return ret;
1335 : }
1336 :
1337 : /* Skip the lot if 'data' isn't here yet (initialisation) */
1338 237 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
1339 15 : struct ldb_seqnum_request *tseq;
1340 15 : struct ldb_seqnum_result *tseqr;
1341 15 : struct ldb_request *treq;
1342 24 : struct ldb_result *res = talloc_zero(data, struct ldb_result);
1343 24 : if (res == NULL) {
1344 0 : return ldb_oom(ldb_module_get_ctx(module));
1345 : }
1346 24 : tseq = talloc_zero(res, struct ldb_seqnum_request);
1347 24 : if (tseq == NULL) {
1348 0 : talloc_free(res);
1349 0 : return ldb_oom(ldb_module_get_ctx(module));
1350 : }
1351 24 : tseq->type = LDB_SEQ_HIGHEST_SEQ;
1352 :
1353 24 : ret = ldb_build_extended_req(&treq, ldb_module_get_ctx(module), res,
1354 : LDB_EXTENDED_SEQUENCE_NUMBER,
1355 : tseq,
1356 : NULL,
1357 : res,
1358 : ldb_extended_default_callback,
1359 : NULL);
1360 24 : LDB_REQ_SET_LOCATION(treq);
1361 24 : if (ret != LDB_SUCCESS) {
1362 0 : talloc_free(res);
1363 0 : return ret;
1364 : }
1365 :
1366 24 : ret = partition_request(data->partitions[i]->module, treq);
1367 24 : if (ret != LDB_SUCCESS) {
1368 0 : talloc_free(res);
1369 0 : return ret;
1370 : }
1371 24 : ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
1372 24 : if (ret != LDB_SUCCESS) {
1373 0 : talloc_free(res);
1374 0 : return ret;
1375 : }
1376 24 : tseqr = talloc_get_type(res->extended->data,
1377 : struct ldb_seqnum_result);
1378 24 : seq_number += tseqr->seq_num;
1379 24 : talloc_free(res);
1380 : }
1381 :
1382 213 : *seqr = seq_number;
1383 213 : return LDB_SUCCESS;
1384 : }
1385 :
1386 :
1387 : /*
1388 : * Newer version of sequence number using metadata tdb
1389 : */
1390 1276083 : static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
1391 : {
1392 95491 : struct ldb_extended *ext;
1393 95491 : struct ldb_seqnum_request *seq;
1394 95491 : struct ldb_seqnum_result *seqr;
1395 95491 : uint64_t seq_number;
1396 95491 : int ret;
1397 :
1398 1276083 : seq = talloc_get_type_abort(req->op.extended.data, struct ldb_seqnum_request);
1399 1276083 : switch (seq->type) {
1400 1253269 : case LDB_SEQ_NEXT:
1401 1253269 : ret = partition_metadata_sequence_number_increment(module, &seq_number);
1402 1253269 : if (ret != LDB_SUCCESS) {
1403 0 : return ret;
1404 : }
1405 1157804 : break;
1406 :
1407 22814 : case LDB_SEQ_HIGHEST_SEQ:
1408 22814 : ret = partition_metadata_sequence_number(module, &seq_number);
1409 22814 : if (ret != LDB_SUCCESS) {
1410 0 : return ret;
1411 : }
1412 22788 : break;
1413 :
1414 0 : case LDB_SEQ_HIGHEST_TIMESTAMP:
1415 0 : return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
1416 : "LDB_SEQ_HIGHEST_TIMESTAMP not supported");
1417 : }
1418 :
1419 1276083 : ext = talloc_zero(req, struct ldb_extended);
1420 1276083 : if (!ext) {
1421 0 : return ldb_module_oom(module);
1422 : }
1423 1276083 : seqr = talloc_zero(ext, struct ldb_seqnum_result);
1424 1276083 : if (seqr == NULL) {
1425 0 : talloc_free(ext);
1426 0 : return ldb_module_oom(module);
1427 : }
1428 1276083 : ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
1429 1276083 : ext->data = seqr;
1430 :
1431 1276083 : seqr->seq_num = seq_number;
1432 1276083 : seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
1433 :
1434 : /* send request done */
1435 1276083 : return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
1436 : }
1437 :
1438 : /* lock all the backends */
1439 18846306 : int partition_read_lock(struct ldb_module *module)
1440 : {
1441 18846306 : int i = 0;
1442 18846306 : int ret = 0;
1443 18846306 : int ret2 = 0;
1444 18846306 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1445 1115416 : struct partition_private_data *data = \
1446 18846306 : talloc_get_type(ldb_module_get_private(module),
1447 : struct partition_private_data);
1448 :
1449 18846306 : if (ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING) {
1450 0 : ldb_debug(ldb, LDB_DEBUG_TRACE,
1451 : "partition_read_lock() -> (metadata partition)");
1452 : }
1453 :
1454 : /*
1455 : * It is important to only do this for LOCK because:
1456 : * - we don't want to unlock what we did not lock
1457 : *
1458 : * - we don't want to make a new lock on the sam.ldb
1459 : * (triggered inside this routine due to the seq num check)
1460 : * during an unlock phase as that will violate the lock
1461 : * ordering
1462 : */
1463 :
1464 18846306 : if (data == NULL) {
1465 182015 : TALLOC_CTX *mem_ctx = talloc_new(module);
1466 :
1467 182015 : data = talloc_zero(mem_ctx, struct partition_private_data);
1468 182015 : if (data == NULL) {
1469 0 : talloc_free(mem_ctx);
1470 0 : return ldb_operr(ldb);
1471 : }
1472 :
1473 : /*
1474 : * When used from Samba4, this message is set by the
1475 : * samba4 module, as a fixed value not read from the
1476 : * DB. This avoids listing modules in the DB
1477 : */
1478 182015 : data->forced_module_msg = talloc_get_type(
1479 : ldb_get_opaque(ldb,
1480 : DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME),
1481 : struct ldb_message);
1482 :
1483 182015 : ldb_module_set_private(module, talloc_steal(module,
1484 : data));
1485 182015 : talloc_free(mem_ctx);
1486 : }
1487 :
1488 : /*
1489 : * This will lock sam.ldb and will also call event loops,
1490 : * so we do it before we get the whole db lock.
1491 : */
1492 18846306 : ret = partition_reload_if_required(module, data, NULL);
1493 18846306 : if (ret != LDB_SUCCESS) {
1494 0 : return ret;
1495 : }
1496 :
1497 : /*
1498 : * Order of read_lock calls must match that in partition_start_trans.
1499 : * See comment in that function for detail.
1500 : */
1501 18846306 : ret = partition_metadata_read_lock(module);
1502 18846306 : if (ret != LDB_SUCCESS) {
1503 0 : goto failed;
1504 : }
1505 :
1506 : /*
1507 : * The top level DB (sam.ldb) lock is not enough to block another
1508 : * process in prepare_commit(), because if nothing was changed in the
1509 : * specific backend, then prepare_commit() is a no-op. Therefore the
1510 : * metadata.tdb lock is taken out above, as it is the best we can do
1511 : * right now.
1512 : */
1513 18846306 : ret = ldb_next_read_lock(module);
1514 18846306 : if (ret != LDB_SUCCESS) {
1515 0 : ldb_debug_set(ldb,
1516 : LDB_DEBUG_FATAL,
1517 : "Failed to lock db: %s / %s for metadata partition",
1518 : ldb_errstring(ldb),
1519 : ldb_strerror(ret));
1520 :
1521 0 : return ret;
1522 : }
1523 :
1524 : /*
1525 : * The following per partition locks are required mostly because TDB
1526 : * and MDB require locks before reads are permitted.
1527 : */
1528 105848941 : for (i=0; data && data->partitions && data->partitions[i]; i++) {
1529 87002635 : if ((module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING)) {
1530 0 : ldb_debug(ldb, LDB_DEBUG_TRACE,
1531 : "partition_read_lock() -> %s",
1532 : ldb_dn_get_linearized(
1533 0 : data->partitions[i]->ctrl->dn));
1534 : }
1535 87002635 : ret = ldb_next_read_lock(data->partitions[i]->module);
1536 87002635 : if (ret == LDB_SUCCESS) {
1537 87002635 : continue;
1538 : }
1539 :
1540 0 : ldb_debug_set(ldb,
1541 : LDB_DEBUG_FATAL,
1542 : "Failed to lock db: %s / %s for %s",
1543 : ldb_errstring(ldb),
1544 : ldb_strerror(ret),
1545 : ldb_dn_get_linearized(
1546 0 : data->partitions[i]->ctrl->dn));
1547 :
1548 0 : goto failed;
1549 : }
1550 :
1551 17730890 : return LDB_SUCCESS;
1552 :
1553 0 : failed:
1554 : /* Back it out, if it fails on one */
1555 0 : for (i--; i >= 0; i--) {
1556 0 : ret2 = ldb_next_read_unlock(data->partitions[i]->module);
1557 0 : if (ret2 != LDB_SUCCESS) {
1558 0 : ldb_debug(ldb,
1559 : LDB_DEBUG_FATAL,
1560 : "Failed to unlock db: %s / %s",
1561 : ldb_errstring(ldb),
1562 : ldb_strerror(ret2));
1563 : }
1564 : }
1565 0 : ret2 = ldb_next_read_unlock(module);
1566 0 : if (ret2 != LDB_SUCCESS) {
1567 0 : ldb_debug(ldb,
1568 : LDB_DEBUG_FATAL,
1569 : "Failed to unlock db: %s / %s",
1570 : ldb_errstring(ldb),
1571 : ldb_strerror(ret2));
1572 : }
1573 0 : return ret;
1574 : }
1575 :
1576 : /* unlock all the backends */
1577 18846306 : int partition_read_unlock(struct ldb_module *module)
1578 : {
1579 1115416 : int i;
1580 18846306 : int ret = LDB_SUCCESS;
1581 1115416 : int ret2;
1582 18846306 : struct ldb_context *ldb = ldb_module_get_ctx(module);
1583 1115416 : struct partition_private_data *data = \
1584 18846306 : talloc_get_type(ldb_module_get_private(module),
1585 : struct partition_private_data);
1586 18846306 : bool trace = module && ldb_module_flags(ldb) & LDB_FLG_ENABLE_TRACING;
1587 :
1588 : /*
1589 : * Order of read_unlock calls must be the reverse of that in
1590 : * partition_start_trans. See comment in that function for detail.
1591 : */
1592 18846306 : if (data && data->partitions) {
1593 : /* Just counting the partitions */
1594 105665176 : for (i=0; data->partitions[i]; i++) {}
1595 :
1596 : /* now walk them backwards */
1597 105665176 : for (i--; i>=0; i--) {
1598 87002635 : struct dsdb_partition *p = data->partitions[i];
1599 87002635 : if (trace) {
1600 0 : ldb_debug(ldb, LDB_DEBUG_TRACE,
1601 : "partition_read_unlock() -> %s",
1602 0 : ldb_dn_get_linearized(p->ctrl->dn));
1603 : }
1604 87002635 : ret2 = ldb_next_read_unlock(p->module);
1605 87002635 : if (ret2 != LDB_SUCCESS) {
1606 0 : ldb_debug_set(ldb,
1607 : LDB_DEBUG_FATAL,
1608 : "Failed to lock db: %s / %s for %s",
1609 : ldb_errstring(ldb),
1610 : ldb_strerror(ret2),
1611 0 : ldb_dn_get_linearized(p->ctrl->dn));
1612 :
1613 : /*
1614 : * Don't overwrite the original failure code
1615 : * if there was one
1616 : */
1617 0 : if (ret == LDB_SUCCESS) {
1618 0 : ret = ret2;
1619 : }
1620 : }
1621 : }
1622 : }
1623 :
1624 18846306 : if (trace) {
1625 0 : ldb_debug(ldb, LDB_DEBUG_TRACE,
1626 : "partition_read_unlock() -> (metadata partition)");
1627 : }
1628 :
1629 18846306 : ret2 = ldb_next_read_unlock(module);
1630 18846306 : if (ret2 != LDB_SUCCESS) {
1631 0 : ldb_debug_set(ldb,
1632 : LDB_DEBUG_FATAL,
1633 : "Failed to unlock db: %s / %s for metadata partition",
1634 : ldb_errstring(ldb),
1635 : ldb_strerror(ret2));
1636 :
1637 : /*
1638 : * Don't overwrite the original failure code
1639 : * if there was one
1640 : */
1641 0 : if (ret == LDB_SUCCESS) {
1642 0 : ret = ret2;
1643 : }
1644 : }
1645 :
1646 18846306 : ret2 = partition_metadata_read_unlock(module);
1647 :
1648 : /*
1649 : * Don't overwrite the original failure code
1650 : * if there was one
1651 : */
1652 18846306 : if (ret == LDB_SUCCESS) {
1653 18846306 : ret = ret2;
1654 : }
1655 :
1656 18846306 : return ret;
1657 : }
1658 :
1659 : /* extended */
1660 1279807 : static int partition_extended(struct ldb_module *module, struct ldb_request *req)
1661 : {
1662 1279807 : struct partition_private_data *data = talloc_get_type(ldb_module_get_private(module),
1663 : struct partition_private_data);
1664 95646 : struct partition_context *ac;
1665 95646 : int ret;
1666 :
1667 : /* if we aren't initialised yet go further */
1668 1279807 : if (!data) {
1669 0 : return ldb_next_request(module, req);
1670 : }
1671 :
1672 1279807 : if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
1673 : /* Update the metadata.tdb to increment the schema version if needed*/
1674 2745 : DEBUG(10, ("Incrementing the sequence_number after schema_update_now\n"));
1675 2745 : ret = partition_metadata_inc_schema_sequence(module);
1676 2745 : return ldb_module_done(req, NULL, NULL, ret);
1677 : }
1678 :
1679 1277062 : if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
1680 1276083 : return partition_sequence_number(module, req);
1681 : }
1682 :
1683 979 : if (strcmp(req->op.extended.oid, DSDB_EXTENDED_CREATE_PARTITION_OID) == 0) {
1684 979 : return partition_create(module, req);
1685 : }
1686 :
1687 : /*
1688 : * as the extended operation has no dn
1689 : * we need to send it to all partitions
1690 : */
1691 :
1692 0 : ac = partition_init_ctx(module, req);
1693 0 : if (!ac) {
1694 0 : return ldb_operr(ldb_module_get_ctx(module));
1695 : }
1696 :
1697 0 : return partition_send_all(module, ac, req);
1698 : }
1699 :
1700 : static const struct ldb_module_ops ldb_partition_module_ops = {
1701 : .name = "partition",
1702 : .init_context = partition_init,
1703 : .search = partition_search,
1704 : .add = partition_add,
1705 : .modify = partition_modify,
1706 : .del = partition_delete,
1707 : .rename = partition_rename,
1708 : .extended = partition_extended,
1709 : .start_transaction = partition_start_trans,
1710 : .prepare_commit = partition_prepare_commit,
1711 : .end_transaction = partition_end_trans,
1712 : .del_transaction = partition_del_trans,
1713 : .read_lock = partition_read_lock,
1714 : .read_unlock = partition_read_unlock
1715 : };
1716 :
1717 6040 : int ldb_partition_module_init(const char *version)
1718 : {
1719 6040 : LDB_MODULE_CHECK_VERSION(version);
1720 6040 : return ldb_register_module(&ldb_partition_module_ops);
1721 : }
|