LCOV - code coverage report
Current view: top level - lib/ldb/ldb_map - ldb_map_inbound.c (source / functions) Hit Total Coverage
Test: coverage report for master 469b22b8 Lines: 276 377 73.2 %
Date: 2024-06-10 12:05:21 Functions: 18 18 100.0 %

          Line data    Source code
       1             : /*
       2             :    ldb database mapping module
       3             : 
       4             :    Copyright (C) Jelmer Vernooij 2005
       5             :    Copyright (C) Martin Kuehl <mkhl@samba.org> 2006
       6             :    Copyright (C) Simo Sorce <idra@samba.org> 2008
       7             : 
       8             :      ** NOTE! The following LGPL license applies to the ldb
       9             :      ** library. This does NOT imply that all of Samba is released
      10             :      ** under the LGPL
      11             :    
      12             :    This library is free software; you can redistribute it and/or
      13             :    modify it under the terms of the GNU Lesser General Public
      14             :    License as published by the Free Software Foundation; either
      15             :    version 3 of the License, or (at your option) any later version.
      16             : 
      17             :    This library is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      20             :    Lesser General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU Lesser General Public
      23             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      24             : 
      25             : */
      26             : 
      27             : #include "replace.h"
      28             : #include "system/filesys.h"
      29             : #include "system/time.h"
      30             : #include "ldb_map.h"
      31             : #include "ldb_map_private.h"
      32             : 
      33             : 
      34             : /* Mapping message elements
      35             :  * ======================== */
      36             : 
      37             : /* Map a message element into the remote partition. */
      38          58 : static struct ldb_message_element *ldb_msg_el_map_local(struct ldb_module *module, void *mem_ctx, const struct ldb_map_attribute *map, const struct ldb_message_element *old)
      39             : {
      40          58 :         struct ldb_message_element *el;
      41          58 :         unsigned int i;
      42             : 
      43          58 :         el = talloc_zero(mem_ctx, struct ldb_message_element);
      44          58 :         if (el == NULL) {
      45           0 :                 map_oom(module);
      46           0 :                 return NULL;
      47             :         }
      48             : 
      49          58 :         el->num_values = old->num_values;
      50          58 :         el->values = talloc_array(el, struct ldb_val, el->num_values);
      51          58 :         if (el->values == NULL) {
      52           0 :                 talloc_free(el);
      53           0 :                 map_oom(module);
      54           0 :                 return NULL;
      55             :         }
      56             : 
      57          58 :         el->name = map_attr_map_local(el, map, old->name);
      58             : 
      59         113 :         for (i = 0; i < el->num_values; i++) {
      60          55 :                 el->values[i] = ldb_val_map_local(module, el->values, map, &old->values[i]);
      61             :         }
      62             : 
      63           0 :         return el;
      64             : }
      65             : 
      66             : /* Add a message element either to a local or to a remote message,
      67             :  * depending on whether it goes into the local or remote partition. */
      68         138 : static int ldb_msg_el_partition(struct ldb_module *module, enum ldb_request_type optype, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg, const char *attr_name, /* const char * const names[], */ const struct ldb_message_element *old)
      69             : {
      70         138 :         const struct ldb_map_context *data = map_get_context(module);
      71         138 :         const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
      72         138 :         struct ldb_message_element *el=NULL;
      73         138 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
      74             : 
      75             :         /* Unknown attribute: ignore */
      76         138 :         if (map == NULL) {
      77           9 :                 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
      78             :                           "Not mapping attribute '%s': no mapping found",
      79           9 :                           old->name);
      80           9 :                 goto local;
      81             :         }
      82             : 
      83         129 :         switch (map->type) {
      84           0 :         case LDB_MAP_RENDROP:
      85           0 :                 if (optype != LDB_ADD) {
      86             :                         /* do the same as LDB_MAP_RENAME */
      87           0 :                         el = ldb_msg_el_map_local(module, remote, map, old);
      88           0 :                         break;
      89             :                 }
      90             : 
      91          66 :                 FALL_THROUGH;
      92             :         case LDB_MAP_IGNORE:
      93          66 :                 goto local;
      94             : 
      95          12 :         case LDB_MAP_CONVERT:
      96          12 :                 if (map->u.convert.convert_local == NULL) {
      97           3 :                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
      98             :                                   "Not mapping attribute '%s': "
      99             :                                   "'convert_local' not set",
     100           3 :                                   map->local_name);
     101           3 :                         goto local;
     102             :                 }
     103             : 
     104          58 :                 FALL_THROUGH;
     105             :         case LDB_MAP_KEEP:
     106             :         case LDB_MAP_RENAME:
     107          58 :                 el = ldb_msg_el_map_local(module, remote, map, old);
     108          58 :                 break;
     109             : 
     110           2 :         case LDB_MAP_GENERATE:
     111           2 :                 if (map->u.generate.generate_remote == NULL) {
     112           0 :                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
     113             :                                   "Not mapping attribute '%s': "
     114             :                                   "'generate_remote' not set",
     115           0 :                                   map->local_name);
     116           0 :                         goto local;
     117             :                 }
     118             : 
     119             :                 /* TODO: if this attr requires context:
     120             :                  *       make sure all context attrs are mappable (in 'names')
     121             :                  *       make sure all context attrs have already been mapped?
     122             :                  *       maybe postpone generation until they have been mapped?
     123             :                  */
     124             : 
     125           2 :                 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
     126           2 :                 return 0;
     127             :         }
     128             : 
     129          58 :         if (el == NULL) {
     130           0 :                 return -1;
     131             :         }
     132             : 
     133          58 :         return ldb_msg_add(remote, el, old->flags);
     134             : 
     135          78 : local:
     136          78 :         el = talloc(local, struct ldb_message_element);
     137          78 :         if (el == NULL) {
     138           0 :                 map_oom(module);
     139           0 :                 return -1;
     140             :         }
     141             : 
     142          78 :         *el = *old;                     /* copy the old element */
     143             : 
     144          78 :         return ldb_msg_add(local, el, old->flags);
     145             : }
     146             : 
     147             : /* Mapping messages
     148             :  * ================ */
     149             : 
     150             : /* Check whether a message will be (partially) mapped into the remote partition. */
     151          15 : static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
     152             : {
     153          15 :         const struct ldb_map_context *data = map_get_context(module);
     154          15 :         bool ret;
     155          15 :         unsigned int i;
     156             : 
     157          31 :         for (i = 0; i < msg->num_elements; i++) {
     158          16 :                 ret = map_attr_check_remote(data, msg->elements[i].name);
     159          16 :                 if (ret) {
     160           0 :                         return ret;
     161             :                 }
     162             :         }
     163             : 
     164           0 :         return false;
     165             : }
     166             : 
     167             : /* Split message elements that stay in the local partition from those
     168             :  * that are mapped into the remote partition. */
     169          15 : static int ldb_msg_partition(struct ldb_module *module, enum ldb_request_type optype, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
     170             : {
     171             :         /* const char * const names[]; */
     172          15 :         struct ldb_context *ldb;
     173          15 :         unsigned int i;
     174          15 :         int ret;
     175             : 
     176          15 :         ldb = ldb_module_get_ctx(module);
     177             : 
     178         168 :         for (i = 0; i < msg->num_elements; i++) {
     179             :                 /* Skip 'IS_MAPPED' */
     180         138 :                 if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
     181           0 :                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
     182             :                                   "Skipping attribute '%s'",
     183           0 :                                   msg->elements[i].name);
     184           0 :                         continue;
     185             :                 }
     186             : 
     187         138 :                 ret = ldb_msg_el_partition(module, optype, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
     188         138 :                 if (ret) {
     189           0 :                         return ret;
     190             :                 }
     191             :         }
     192             : 
     193           0 :         return 0;
     194             : }
     195             : 
     196             : 
     197             : static int map_add_do_local(struct map_context *ac);
     198             : static int map_modify_do_local(struct map_context *ac);
     199             : static int map_delete_do_local(struct map_context *ac);
     200             : static int map_rename_do_local(struct map_context *ac);
     201             : static int map_rename_do_fixup(struct map_context *ac);
     202             : static int map_rename_local_callback(struct ldb_request *req,
     203             :                                      struct ldb_reply *ares);
     204             : 
     205             : 
     206             : /*****************************************************************************
     207             :  * COMMON INBOUND functions
     208             : *****************************************************************************/
     209             : 
     210             : /* Store the DN of a single search result in context. */
     211          33 : static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares)
     212             : {
     213          33 :         struct ldb_context *ldb;
     214          33 :         struct map_context *ac;
     215          33 :         int ret;
     216             : 
     217          33 :         ac = talloc_get_type(req->context, struct map_context);
     218          33 :         ldb = ldb_module_get_ctx(ac->module);
     219             : 
     220          33 :         if (!ares) {
     221           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     222             :                                         LDB_ERR_OPERATIONS_ERROR);
     223             :         }
     224          33 :         if (ares->error != LDB_SUCCESS) {
     225           0 :                 return ldb_module_done(ac->req, ares->controls,
     226             :                                         ares->response, ares->error);
     227             :         }
     228             : 
     229             :         /* We are interested only in the single reply */
     230          33 :         switch(ares->type) {
     231          14 :         case LDB_REPLY_ENTRY:
     232             :                 /* We have already found a remote DN */
     233          14 :                 if (ac->local_dn) {
     234           0 :                         ldb_set_errstring(ldb,
     235             :                                           "Too many results!");
     236           0 :                         return ldb_module_done(ac->req, NULL, NULL,
     237             :                                                 LDB_ERR_OPERATIONS_ERROR);
     238             :                 }
     239             : 
     240             :                 /* Store local DN */
     241          14 :                 ac->local_dn = talloc_steal(ac, ares->message->dn);
     242          14 :                 break;
     243             : 
     244          19 :         case LDB_REPLY_DONE:
     245             : 
     246          19 :                 switch (ac->req->operation) {
     247           6 :                 case LDB_MODIFY:
     248           6 :                         ret = map_modify_do_local(ac);
     249           6 :                         break;
     250          10 :                 case LDB_DELETE:
     251          10 :                         ret = map_delete_do_local(ac);
     252          10 :                         break;
     253           3 :                 case LDB_RENAME:
     254           3 :                         ret = map_rename_do_local(ac);
     255           3 :                         break;
     256           0 :                 default:
     257             :                         /* if we get here we have definitely a problem */
     258           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     259             :                 }
     260          19 :                 if (ret != LDB_SUCCESS) {
     261           0 :                         return ldb_module_done(ac->req, NULL, NULL,
     262             :                                                 LDB_ERR_OPERATIONS_ERROR);
     263             :                 }
     264             : 
     265           0 :                 break;
     266           0 :         default:
     267             :                 /* ignore referrals */
     268           0 :                 break;
     269             :         }
     270             : 
     271          33 :         talloc_free(ares);
     272          33 :         return LDB_SUCCESS;
     273             : }
     274             : 
     275             : /* Build a request to search the local record by its DN. */
     276          19 : static int map_search_self_req(struct ldb_request **req,
     277             :                                 struct map_context *ac,
     278             :                                 struct ldb_dn *dn)
     279             : {
     280             :         /* attrs[] is returned from this function in
     281             :          * ac->search_req->op.search.attrs, so it must be static, as
     282             :          * otherwise the compiler can put it on the stack */
     283          19 :         static const char * const attrs[] = { IS_MAPPED, NULL };
     284          19 :         struct ldb_parse_tree *tree;
     285             : 
     286             :         /* Limit search to records with 'IS_MAPPED' present */
     287          19 :         tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
     288          19 :         if (tree == NULL) {
     289           0 :                 map_oom(ac->module);
     290           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     291             :         }
     292             : 
     293          19 :         *req = map_search_base_req(ac, dn, attrs, tree,
     294             :                                    ac, map_search_self_callback);
     295          19 :         if (*req == NULL) {
     296           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     297             :         }
     298             : 
     299           0 :         return LDB_SUCCESS;
     300             : }
     301             : 
     302          22 : static int map_op_local_callback(struct ldb_request *req,
     303             :                                  struct ldb_reply *ares)
     304             : {
     305          22 :         struct ldb_context *ldb;
     306          22 :         struct map_context *ac;
     307          22 :         int ret;
     308             : 
     309          22 :         ac = talloc_get_type(req->context, struct map_context);
     310          22 :         ldb = ldb_module_get_ctx(ac->module);
     311             : 
     312          22 :         if (!ares) {
     313           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     314             :                                         LDB_ERR_OPERATIONS_ERROR);
     315             :         }
     316          22 :         if (ares->error != LDB_SUCCESS) {
     317           0 :                 return ldb_module_done(ac->req, ares->controls,
     318             :                                         ares->response, ares->error);
     319             :         }
     320             : 
     321          22 :         if (ares->type != LDB_REPLY_DONE) {
     322           0 :                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
     323           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     324             :                                         LDB_ERR_OPERATIONS_ERROR);
     325             :         }
     326             : 
     327             :         /* Do the remote request. */
     328          22 :         ret = ldb_next_remote_request(ac->module, ac->remote_req);
     329          22 :         if (ret != LDB_SUCCESS) {
     330           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     331             :                                         LDB_ERR_OPERATIONS_ERROR);
     332             :         }
     333             : 
     334           0 :         return LDB_SUCCESS;
     335             : }
     336             : 
     337          28 : static int map_op_remote_callback(struct ldb_request *req,
     338             :                                   struct ldb_reply *ares)
     339             : {
     340          28 :         struct ldb_context *ldb;
     341          28 :         struct map_context *ac;
     342             : 
     343          28 :         ac = talloc_get_type(req->context, struct map_context);
     344          28 :         ldb = ldb_module_get_ctx(ac->module);
     345             : 
     346          28 :         if (!ares) {
     347           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     348             :                                         LDB_ERR_OPERATIONS_ERROR);
     349             :         }
     350          28 :         if (ares->error != LDB_SUCCESS) {
     351           0 :                 return ldb_module_done(ac->req, ares->controls,
     352             :                                         ares->response, ares->error);
     353             :         }
     354             : 
     355          28 :         if (ares->type != LDB_REPLY_DONE) {
     356           0 :                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
     357           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     358             :                                         LDB_ERR_OPERATIONS_ERROR);
     359             :         }
     360             : 
     361          28 :         return ldb_module_done(ac->req, ares->controls,
     362             :                                         ares->response, ares->error);
     363             : }
     364             : 
     365             : 
     366             : /*****************************************************************************
     367             :  * ADD operations
     368             : *****************************************************************************/
     369             : 
     370             : 
     371             : /* Add a record. */
     372           8 : int ldb_map_add(struct ldb_module *module, struct ldb_request *req)
     373             : {
     374           8 :         const struct ldb_message *msg = req->op.add.message;
     375           8 :         struct ldb_context *ldb;
     376           8 :         struct map_context *ac;
     377           8 :         struct ldb_message *remote_msg;
     378           8 :         int ret;
     379             : 
     380           8 :         ldb = ldb_module_get_ctx(module);
     381             : 
     382             :         /* Do not manipulate our control entries */
     383           8 :         if (ldb_dn_is_special(msg->dn)) {
     384           0 :                 return ldb_next_request(module, req);
     385             :         }
     386             : 
     387             :         /* No mapping requested (perhaps no DN mapping specified), skip to next module */
     388           8 :         if (!ldb_dn_check_local(module, msg->dn)) {
     389           2 :                 return ldb_next_request(module, req);
     390             :         }
     391             : 
     392             :         /* No mapping needed, fail */
     393           6 :         if (!ldb_msg_check_remote(module, msg)) {
     394           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     395             :         }
     396             : 
     397             :         /* Prepare context and handle */
     398           6 :         ac = map_init_context(module, req);
     399           6 :         if (ac == NULL) {
     400           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     401             :         }
     402             : 
     403             : 
     404             :         /* Prepare the local message */
     405           6 :         ac->local_msg = ldb_msg_new(ac);
     406           6 :         if (ac->local_msg == NULL) {
     407           0 :                 map_oom(module);
     408           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     409             :         }
     410           6 :         ac->local_msg->dn = msg->dn;
     411             : 
     412             :         /* Prepare the remote message */
     413           6 :         remote_msg = ldb_msg_new(ac);
     414           6 :         if (remote_msg == NULL) {
     415           0 :                 map_oom(module);
     416           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     417             :         }
     418           6 :         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
     419             : 
     420             :         /* Split local from remote message */
     421           6 :         ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);
     422             : 
     423             :         /* Prepare the remote operation */
     424           6 :         ret = ldb_build_add_req(&ac->remote_req, ldb,
     425             :                                 ac, remote_msg,
     426             :                                 req->controls,
     427             :                                 ac, map_op_remote_callback,
     428             :                                 req);
     429           6 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     430           6 :         if (ret != LDB_SUCCESS) {
     431           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     432             :         }
     433             : 
     434          12 :         if ((ac->local_msg->num_elements == 0) ||
     435           6 :             ( ! map_check_local_db(ac->module))) {
     436             :                 /* No local data or db, just run the remote request */
     437           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     438             :         }
     439             : 
     440             :         /* Store remote DN in 'IS_MAPPED' */
     441             :         /* TODO: use GUIDs here instead */
     442           6 :         ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
     443             :                                         remote_msg->dn);
     444           6 :         if (ret != LDB_SUCCESS) {
     445           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     446             :         }
     447             : 
     448           6 :         return map_add_do_local(ac);
     449             : }
     450             : 
     451             : /* Add the local record. */
     452           6 : static int map_add_do_local(struct map_context *ac)
     453             : {
     454           6 :         struct ldb_request *local_req;
     455           6 :         struct ldb_context *ldb;
     456           6 :         int ret;
     457             : 
     458           6 :         ldb = ldb_module_get_ctx(ac->module);
     459             : 
     460             :         /* Prepare the local operation */
     461          12 :         ret = ldb_build_add_req(&local_req, ldb, ac,
     462           6 :                                 ac->local_msg,
     463           0 :                                 ac->req->controls,
     464             :                                 ac,
     465             :                                 map_op_local_callback,
     466             :                                 ac->req);
     467           6 :         LDB_REQ_SET_LOCATION(local_req);
     468           6 :         if (ret != LDB_SUCCESS) {
     469           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     470             :         }
     471           6 :         return ldb_next_request(ac->module, local_req);
     472             : }
     473             : 
     474             : /*****************************************************************************
     475             :  * MODIFY operations
     476             : *****************************************************************************/
     477             : 
     478             : /* Modify a record. */
     479          11 : int ldb_map_modify(struct ldb_module *module, struct ldb_request *req)
     480             : {
     481          11 :         const struct ldb_message *msg = req->op.mod.message;
     482          11 :         struct ldb_request *search_req = NULL;
     483          11 :         struct ldb_message *remote_msg;
     484          11 :         struct ldb_context *ldb;
     485          11 :         struct map_context *ac;
     486          11 :         int ret;
     487             : 
     488          11 :         ldb = ldb_module_get_ctx(module);
     489             : 
     490             :         /* Do not manipulate our control entries */
     491          11 :         if (ldb_dn_is_special(msg->dn)) {
     492           0 :                 return ldb_next_request(module, req);
     493             :         }
     494             : 
     495             :         /* No mapping requested (perhaps no DN mapping specified), skip to next module */
     496          11 :         if (!ldb_dn_check_local(module, msg->dn)) {
     497           2 :                 return ldb_next_request(module, req);
     498             :         }
     499             : 
     500             :         /* No mapping needed, skip to next module */
     501             :         /* TODO: What if the remote part exists, the local doesn't,
     502             :          *       and this request wants to modify local data and thus
     503             :          *       add the local record? */
     504           9 :         if (!ldb_msg_check_remote(module, msg)) {
     505           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     506             :         }
     507             : 
     508             :         /* Prepare context and handle */
     509           9 :         ac = map_init_context(module, req);
     510           9 :         if (ac == NULL) {
     511           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     512             :         }
     513             : 
     514             :         /* Prepare the local message */
     515           9 :         ac->local_msg = ldb_msg_new(ac);
     516           9 :         if (ac->local_msg == NULL) {
     517           0 :                 map_oom(module);
     518           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     519             :         }
     520           9 :         ac->local_msg->dn = msg->dn;
     521             : 
     522             :         /* Prepare the remote message */
     523           9 :         remote_msg = ldb_msg_new(ac->remote_req);
     524           9 :         if (remote_msg == NULL) {
     525           0 :                 map_oom(module);
     526           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     527             :         }
     528           9 :         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
     529             : 
     530             :         /* Split local from remote message */
     531           9 :         ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);
     532             : 
     533             :         /* Prepare the remote operation */
     534           9 :         ret = ldb_build_mod_req(&ac->remote_req, ldb,
     535             :                                 ac, remote_msg,
     536             :                                 req->controls,
     537             :                                 ac, map_op_remote_callback,
     538             :                                 req);
     539           9 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     540           9 :         if (ret != LDB_SUCCESS) {
     541           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     542             :         }
     543             : 
     544          15 :         if ((ac->local_msg->num_elements == 0) ||
     545           6 :             ( ! map_check_local_db(ac->module))) {
     546             :                 /* No local data or db, just run the remote request */
     547           3 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     548             :         }
     549             : 
     550             :         /* prepare the search operation */
     551           6 :         ret = map_search_self_req(&search_req, ac, msg->dn);
     552           6 :         if (ret != LDB_SUCCESS) {
     553           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     554             :         }
     555             : 
     556           6 :         return ldb_next_request(module, search_req);
     557             : }
     558             : 
     559             : /* Modify the local record. */
     560           6 : static int map_modify_do_local(struct map_context *ac)
     561             : {
     562           6 :         struct ldb_request *local_req;
     563           6 :         struct ldb_context *ldb;
     564           6 :         int ret;
     565             : 
     566           6 :         ldb = ldb_module_get_ctx(ac->module);
     567             : 
     568           6 :         if (ac->local_dn == NULL) {
     569             :                 /* No local record present, add it instead */
     570             :                 /* Add local 'IS_MAPPED' */
     571             :                 /* TODO: use GUIDs here instead */
     572           4 :                 ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED,
     573           2 :                                                    ac->remote_req->op.mod.message->dn,
     574             :                                                    LDB_FLAG_MOD_ADD);
     575           2 :                 if (ret != 0) {
     576           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     577             :                 }
     578             : 
     579             :                 /* Prepare the local operation */
     580           4 :                 ret = ldb_build_add_req(&local_req, ldb, ac,
     581           2 :                                         ac->local_msg,
     582           0 :                                         ac->req->controls,
     583             :                                         ac,
     584             :                                         map_op_local_callback,
     585             :                                         ac->req);
     586           2 :                 LDB_REQ_SET_LOCATION(local_req);
     587           2 :                 if (ret != LDB_SUCCESS) {
     588           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     589             :                 }
     590             :         } else {
     591             :                 /* Prepare the local operation */
     592           8 :                 ret = ldb_build_mod_req(&local_req, ldb, ac,
     593           4 :                                         ac->local_msg,
     594           0 :                                         ac->req->controls,
     595             :                                         ac,
     596             :                                         map_op_local_callback,
     597             :                                         ac->req);
     598           4 :                 LDB_REQ_SET_LOCATION(local_req);
     599           4 :                 if (ret != LDB_SUCCESS) {
     600           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     601             :                 }
     602             :         }
     603             : 
     604           6 :         return ldb_next_request(ac->module, local_req);
     605             : }
     606             : 
     607             : /*****************************************************************************
     608             :  * DELETE operations
     609             : *****************************************************************************/
     610             : 
     611             : /* Delete a record. */
     612          11 : int ldb_map_delete(struct ldb_module *module, struct ldb_request *req)
     613             : {
     614          11 :         struct ldb_request *search_req;
     615          11 :         struct ldb_context *ldb;
     616          11 :         struct map_context *ac;
     617          11 :         int ret;
     618             : 
     619          11 :         ldb = ldb_module_get_ctx(module);
     620             : 
     621             :         /* Do not manipulate our control entries */
     622          11 :         if (ldb_dn_is_special(req->op.del.dn)) {
     623           0 :                 return ldb_next_request(module, req);
     624             :         }
     625             : 
     626             :         /* No mapping requested (perhaps no DN mapping specified).
     627             :          * Skip to next module */
     628          11 :         if (!ldb_dn_check_local(module, req->op.del.dn)) {
     629           1 :                 return ldb_next_request(module, req);
     630             :         }
     631             : 
     632             :         /* Prepare context and handle */
     633          10 :         ac = map_init_context(module, req);
     634          10 :         if (ac == NULL) {
     635           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     636             :         }
     637             : 
     638             :         /* Prepare the remote operation */
     639          10 :         ret = ldb_build_del_req(&ac->remote_req, ldb, ac,
     640             :                                    ldb_dn_map_local(module, ac, req->op.del.dn),
     641             :                                    req->controls,
     642             :                                    ac,
     643             :                                    map_op_remote_callback,
     644             :                                    req);
     645          10 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     646          10 :         if (ret != LDB_SUCCESS) {
     647           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     648             :         }
     649             : 
     650             :         /* No local db, just run the remote request */
     651          10 :         if (!map_check_local_db(ac->module)) {
     652             :                 /* Do the remote request. */
     653           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     654             :         }
     655             : 
     656             :         /* Prepare the search operation */
     657          10 :         ret = map_search_self_req(&search_req, ac, req->op.del.dn);
     658          10 :         if (ret != LDB_SUCCESS) {
     659           0 :                 map_oom(module);
     660           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     661             :         }
     662             : 
     663          10 :         return ldb_next_request(module, search_req);
     664             : }
     665             : 
     666             : /* Delete the local record. */
     667          10 : static int map_delete_do_local(struct map_context *ac)
     668             : {
     669          10 :         struct ldb_request *local_req;
     670          10 :         struct ldb_context *ldb;
     671          10 :         int ret;
     672             : 
     673          10 :         ldb = ldb_module_get_ctx(ac->module);
     674             : 
     675             :         /* No local record, continue remotely */
     676          10 :         if (ac->local_dn == NULL) {
     677             :                 /* Do the remote request. */
     678           3 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     679             :         }
     680             : 
     681             :         /* Prepare the local operation */
     682           7 :         ret = ldb_build_del_req(&local_req, ldb, ac,
     683           0 :                                    ac->req->op.del.dn,
     684           0 :                                    ac->req->controls,
     685             :                                    ac,
     686             :                                    map_op_local_callback,
     687             :                                    ac->req);
     688           7 :         LDB_REQ_SET_LOCATION(local_req);
     689           7 :         if (ret != LDB_SUCCESS) {
     690           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     691             :         }
     692           7 :         return ldb_next_request(ac->module, local_req);
     693             : }
     694             : 
     695             : /*****************************************************************************
     696             :  * RENAME operations
     697             : *****************************************************************************/
     698             : 
     699             : /* Rename a record. */
     700           4 : int ldb_map_rename(struct ldb_module *module, struct ldb_request *req)
     701             : {
     702           4 :         struct ldb_request *search_req = NULL;
     703           4 :         struct ldb_context *ldb;
     704           4 :         struct map_context *ac;
     705           4 :         int ret;
     706             : 
     707           4 :         ldb = ldb_module_get_ctx(module);
     708             : 
     709             :         /* Do not manipulate our control entries */
     710           4 :         if (ldb_dn_is_special(req->op.rename.olddn)) {
     711           0 :                 return ldb_next_request(module, req);
     712             :         }
     713             : 
     714             :         /* No mapping requested (perhaps no DN mapping specified).
     715             :          * Skip to next module */
     716           5 :         if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
     717           1 :             (!ldb_dn_check_local(module, req->op.rename.newdn))) {
     718           1 :                 return ldb_next_request(module, req);
     719             :         }
     720             : 
     721             :         /* Rename into/out of the mapped partition requested, bail out */
     722           6 :         if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
     723           3 :             !ldb_dn_check_local(module, req->op.rename.newdn)) {
     724           0 :                 return LDB_ERR_AFFECTS_MULTIPLE_DSAS;
     725             :         }
     726             : 
     727             :         /* Prepare context and handle */
     728           3 :         ac = map_init_context(module, req);
     729           3 :         if (ac == NULL) {
     730           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     731             :         }
     732             : 
     733             :         /* Prepare the remote operation */
     734           3 :         ret = ldb_build_rename_req(&ac->remote_req, ldb, ac,
     735             :                                    ldb_dn_map_local(module, ac, req->op.rename.olddn),
     736             :                                    ldb_dn_map_local(module, ac, req->op.rename.newdn),
     737             :                                    req->controls,
     738             :                                    ac, map_op_remote_callback,
     739             :                                    req);
     740           3 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     741           3 :         if (ret != LDB_SUCCESS) {
     742           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     743             :         }
     744             : 
     745             :         /* No local db, just run the remote request */
     746           3 :         if (!map_check_local_db(ac->module)) {
     747             :                 /* Do the remote request. */
     748           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     749             :         }
     750             : 
     751             :         /* Prepare the search operation */
     752           3 :         ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
     753           3 :         if (ret != LDB_SUCCESS) {
     754           0 :                 map_oom(module);
     755           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     756             :         }
     757             : 
     758           3 :         return ldb_next_request(module, search_req);
     759             : }
     760             : 
     761             : /* Rename the local record. */
     762           3 : static int map_rename_do_local(struct map_context *ac)
     763             : {
     764           3 :         struct ldb_request *local_req;
     765           3 :         struct ldb_context *ldb;
     766           3 :         int ret;
     767             : 
     768           3 :         ldb = ldb_module_get_ctx(ac->module);
     769             : 
     770             :         /* No local record, continue remotely */
     771           3 :         if (ac->local_dn == NULL) {
     772             :                 /* Do the remote request. */
     773           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     774             :         }
     775             : 
     776             :         /* Prepare the local operation */
     777           3 :         ret = ldb_build_rename_req(&local_req, ldb, ac,
     778           0 :                                    ac->req->op.rename.olddn,
     779           0 :                                    ac->req->op.rename.newdn,
     780           0 :                                    ac->req->controls,
     781             :                                    ac,
     782             :                                    map_rename_local_callback,
     783             :                                    ac->req);
     784           3 :         LDB_REQ_SET_LOCATION(local_req);
     785           3 :         if (ret != LDB_SUCCESS) {
     786           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     787             :         }
     788             : 
     789           3 :         return ldb_next_request(ac->module, local_req);
     790             : }
     791             : 
     792           3 : static int map_rename_local_callback(struct ldb_request *req,
     793             :                                      struct ldb_reply *ares)
     794             : {
     795           3 :         struct ldb_context *ldb;
     796           3 :         struct map_context *ac;
     797           3 :         int ret;
     798             : 
     799           3 :         ac = talloc_get_type(req->context, struct map_context);
     800           3 :         ldb = ldb_module_get_ctx(ac->module);
     801             : 
     802           3 :         if (!ares) {
     803           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     804             :                                         LDB_ERR_OPERATIONS_ERROR);
     805             :         }
     806           3 :         if (ares->error != LDB_SUCCESS) {
     807           0 :                 return ldb_module_done(ac->req, ares->controls,
     808             :                                         ares->response, ares->error);
     809             :         }
     810             : 
     811           3 :         if (ares->type != LDB_REPLY_DONE) {
     812           0 :                 ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
     813           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     814             :                                         LDB_ERR_OPERATIONS_ERROR);
     815             :         }
     816             : 
     817             :         /* proceed with next step */
     818           3 :         ret = map_rename_do_fixup(ac);
     819           3 :         if (ret != LDB_SUCCESS) {
     820           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     821             :                                         LDB_ERR_OPERATIONS_ERROR);
     822             :         }
     823             : 
     824           0 :         return LDB_SUCCESS;
     825             : }
     826             : 
     827             : /* Update the local 'IS_MAPPED' attribute. */
     828           3 : static int map_rename_do_fixup(struct map_context *ac)
     829             : {
     830           3 :         struct ldb_request *local_req;
     831             : 
     832             :         /* Prepare the fixup operation */
     833             :         /* TODO: use GUIDs here instead -- or skip it when GUIDs are used. */
     834           6 :         local_req = map_build_fixup_req(ac,
     835           3 :                                         ac->req->op.rename.newdn,
     836           3 :                                         ac->remote_req->op.rename.newdn,
     837             :                                         ac,
     838             :                                         map_op_local_callback);
     839           3 :         if (local_req == NULL) {
     840           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     841             :         }
     842             : 
     843           3 :         return ldb_next_request(ac->module, local_req);
     844             : }

Generated by: LCOV version 1.14