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 v4-17-test 1498b464 Lines: 0 327 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 18 0.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           0 : 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             :         struct ldb_message_element *el;
      41             :         unsigned int i;
      42             : 
      43           0 :         el = talloc_zero(mem_ctx, struct ldb_message_element);
      44           0 :         if (el == NULL) {
      45           0 :                 map_oom(module);
      46           0 :                 return NULL;
      47             :         }
      48             : 
      49           0 :         el->num_values = old->num_values;
      50           0 :         el->values = talloc_array(el, struct ldb_val, el->num_values);
      51           0 :         if (el->values == NULL) {
      52           0 :                 talloc_free(el);
      53           0 :                 map_oom(module);
      54           0 :                 return NULL;
      55             :         }
      56             : 
      57           0 :         el->name = map_attr_map_local(el, map, old->name);
      58             : 
      59           0 :         for (i = 0; i < el->num_values; i++) {
      60           0 :                 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           0 : 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           0 :         const struct ldb_map_context *data = map_get_context(module);
      71           0 :         const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
      72           0 :         struct ldb_message_element *el=NULL;
      73           0 :         struct ldb_context *ldb = ldb_module_get_ctx(module);
      74             : 
      75             :         /* Unknown attribute: ignore */
      76           0 :         if (map == NULL) {
      77           0 :                 ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
      78             :                           "Not mapping attribute '%s': no mapping found",
      79           0 :                           old->name);
      80           0 :                 goto local;
      81             :         }
      82             : 
      83           0 :         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             :                 FALL_THROUGH;
      92             :         case LDB_MAP_IGNORE:
      93           0 :                 goto local;
      94             : 
      95           0 :         case LDB_MAP_CONVERT:
      96           0 :                 if (map->u.convert.convert_local == NULL) {
      97           0 :                         ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
      98             :                                   "Not mapping attribute '%s': "
      99             :                                   "'convert_local' not set",
     100           0 :                                   map->local_name);
     101           0 :                         goto local;
     102             :                 }
     103             : 
     104             :                 FALL_THROUGH;
     105             :         case LDB_MAP_KEEP:
     106             :         case LDB_MAP_RENAME:
     107           0 :                 el = ldb_msg_el_map_local(module, remote, map, old);
     108           0 :                 break;
     109             : 
     110           0 :         case LDB_MAP_GENERATE:
     111           0 :                 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           0 :                 map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
     126           0 :                 return 0;
     127             :         }
     128             : 
     129           0 :         if (el == NULL) {
     130           0 :                 return -1;
     131             :         }
     132             : 
     133           0 :         return ldb_msg_add(remote, el, old->flags);
     134             : 
     135           0 : local:
     136           0 :         el = talloc(local, struct ldb_message_element);
     137           0 :         if (el == NULL) {
     138           0 :                 map_oom(module);
     139           0 :                 return -1;
     140             :         }
     141             : 
     142           0 :         *el = *old;                     /* copy the old element */
     143             : 
     144           0 :         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           0 : static bool ldb_msg_check_remote(struct ldb_module *module, const struct ldb_message *msg)
     152             : {
     153           0 :         const struct ldb_map_context *data = map_get_context(module);
     154             :         bool ret;
     155             :         unsigned int i;
     156             : 
     157           0 :         for (i = 0; i < msg->num_elements; i++) {
     158           0 :                 ret = map_attr_check_remote(data, msg->elements[i].name);
     159           0 :                 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           0 : 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             :         struct ldb_context *ldb;
     173             :         unsigned int i;
     174             :         int ret;
     175             : 
     176           0 :         ldb = ldb_module_get_ctx(module);
     177             : 
     178           0 :         for (i = 0; i < msg->num_elements; i++) {
     179             :                 /* Skip 'IS_MAPPED' */
     180           0 :                 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           0 :                 ret = ldb_msg_el_partition(module, optype, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
     188           0 :                 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           0 : static int map_search_self_callback(struct ldb_request *req, struct ldb_reply *ares)
     212             : {
     213             :         struct ldb_context *ldb;
     214             :         struct map_context *ac;
     215             :         int ret;
     216             : 
     217           0 :         ac = talloc_get_type(req->context, struct map_context);
     218           0 :         ldb = ldb_module_get_ctx(ac->module);
     219             : 
     220           0 :         if (!ares) {
     221           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     222             :                                         LDB_ERR_OPERATIONS_ERROR);
     223             :         }
     224           0 :         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           0 :         switch(ares->type) {
     231           0 :         case LDB_REPLY_ENTRY:
     232             :                 /* We have already found a remote DN */
     233           0 :                 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           0 :                 ac->local_dn = talloc_steal(ac, ares->message->dn);
     242           0 :                 break;
     243             : 
     244           0 :         case LDB_REPLY_DONE:
     245             : 
     246           0 :                 switch (ac->req->operation) {
     247           0 :                 case LDB_MODIFY:
     248           0 :                         ret = map_modify_do_local(ac);
     249           0 :                         break;
     250           0 :                 case LDB_DELETE:
     251           0 :                         ret = map_delete_do_local(ac);
     252           0 :                         break;
     253           0 :                 case LDB_RENAME:
     254           0 :                         ret = map_rename_do_local(ac);
     255           0 :                         break;
     256           0 :                 default:
     257             :                         /* if we get here we have definitely a problem */
     258           0 :                         ret = LDB_ERR_OPERATIONS_ERROR;
     259             :                 }
     260           0 :                 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           0 :         talloc_free(ares);
     272           0 :         return LDB_SUCCESS;
     273             : }
     274             : 
     275             : /* Build a request to search the local record by its DN. */
     276           0 : 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             :         static const char * const attrs[] = { IS_MAPPED, NULL };
     284             :         struct ldb_parse_tree *tree;
     285             : 
     286             :         /* Limit search to records with 'IS_MAPPED' present */
     287           0 :         tree = ldb_parse_tree(ac, "(" IS_MAPPED "=*)");
     288           0 :         if (tree == NULL) {
     289           0 :                 map_oom(ac->module);
     290           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     291             :         }
     292             : 
     293           0 :         *req = map_search_base_req(ac, dn, attrs, tree,
     294             :                                    ac, map_search_self_callback);
     295           0 :         if (*req == NULL) {
     296           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     297             :         }
     298             : 
     299           0 :         return LDB_SUCCESS;
     300             : }
     301             : 
     302           0 : static int map_op_local_callback(struct ldb_request *req,
     303             :                                  struct ldb_reply *ares)
     304             : {
     305             :         struct ldb_context *ldb;
     306             :         struct map_context *ac;
     307             :         int ret;
     308             : 
     309           0 :         ac = talloc_get_type(req->context, struct map_context);
     310           0 :         ldb = ldb_module_get_ctx(ac->module);
     311             : 
     312           0 :         if (!ares) {
     313           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     314             :                                         LDB_ERR_OPERATIONS_ERROR);
     315             :         }
     316           0 :         if (ares->error != LDB_SUCCESS) {
     317           0 :                 return ldb_module_done(ac->req, ares->controls,
     318             :                                         ares->response, ares->error);
     319             :         }
     320             : 
     321           0 :         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           0 :         ret = ldb_next_remote_request(ac->module, ac->remote_req);
     329           0 :         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           0 : static int map_op_remote_callback(struct ldb_request *req,
     338             :                                   struct ldb_reply *ares)
     339             : {
     340             :         struct ldb_context *ldb;
     341             :         struct map_context *ac;
     342             : 
     343           0 :         ac = talloc_get_type(req->context, struct map_context);
     344           0 :         ldb = ldb_module_get_ctx(ac->module);
     345             : 
     346           0 :         if (!ares) {
     347           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     348             :                                         LDB_ERR_OPERATIONS_ERROR);
     349             :         }
     350           0 :         if (ares->error != LDB_SUCCESS) {
     351           0 :                 return ldb_module_done(ac->req, ares->controls,
     352             :                                         ares->response, ares->error);
     353             :         }
     354             : 
     355           0 :         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           0 :         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           0 : int ldb_map_add(struct ldb_module *module, struct ldb_request *req)
     373             : {
     374           0 :         const struct ldb_message *msg = req->op.add.message;
     375             :         struct ldb_context *ldb;
     376             :         struct map_context *ac;
     377             :         struct ldb_message *remote_msg;
     378             :         int ret;
     379             : 
     380           0 :         ldb = ldb_module_get_ctx(module);
     381             : 
     382             :         /* Do not manipulate our control entries */
     383           0 :         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           0 :         if (!ldb_dn_check_local(module, msg->dn)) {
     389           0 :                 return ldb_next_request(module, req);
     390             :         }
     391             : 
     392             :         /* No mapping needed, fail */
     393           0 :         if (!ldb_msg_check_remote(module, msg)) {
     394           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     395             :         }
     396             : 
     397             :         /* Prepare context and handle */
     398           0 :         ac = map_init_context(module, req);
     399           0 :         if (ac == NULL) {
     400           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     401             :         }
     402             : 
     403             : 
     404             :         /* Prepare the local message */
     405           0 :         ac->local_msg = ldb_msg_new(ac);
     406           0 :         if (ac->local_msg == NULL) {
     407           0 :                 map_oom(module);
     408           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     409             :         }
     410           0 :         ac->local_msg->dn = msg->dn;
     411             : 
     412             :         /* Prepare the remote message */
     413           0 :         remote_msg = ldb_msg_new(ac);
     414           0 :         if (remote_msg == NULL) {
     415           0 :                 map_oom(module);
     416           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     417             :         }
     418           0 :         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
     419             : 
     420             :         /* Split local from remote message */
     421           0 :         ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);
     422             : 
     423             :         /* Prepare the remote operation */
     424           0 :         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           0 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     430           0 :         if (ret != LDB_SUCCESS) {
     431           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     432             :         }
     433             : 
     434           0 :         if ((ac->local_msg->num_elements == 0) ||
     435           0 :             ( ! 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           0 :         ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
     443             :                                         remote_msg->dn);
     444           0 :         if (ret != LDB_SUCCESS) {
     445           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     446             :         }
     447             : 
     448           0 :         return map_add_do_local(ac);
     449             : }
     450             : 
     451             : /* Add the local record. */
     452           0 : static int map_add_do_local(struct map_context *ac)
     453             : {
     454             :         struct ldb_request *local_req;
     455             :         struct ldb_context *ldb;
     456             :         int ret;
     457             : 
     458           0 :         ldb = ldb_module_get_ctx(ac->module);
     459             : 
     460             :         /* Prepare the local operation */
     461           0 :         ret = ldb_build_add_req(&local_req, ldb, ac,
     462           0 :                                 ac->local_msg,
     463           0 :                                 ac->req->controls,
     464             :                                 ac,
     465             :                                 map_op_local_callback,
     466             :                                 ac->req);
     467           0 :         LDB_REQ_SET_LOCATION(local_req);
     468           0 :         if (ret != LDB_SUCCESS) {
     469           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     470             :         }
     471           0 :         return ldb_next_request(ac->module, local_req);
     472             : }
     473             : 
     474             : /*****************************************************************************
     475             :  * MODIFY operations
     476             : *****************************************************************************/
     477             : 
     478             : /* Modify a record. */
     479           0 : int ldb_map_modify(struct ldb_module *module, struct ldb_request *req)
     480             : {
     481           0 :         const struct ldb_message *msg = req->op.mod.message;
     482           0 :         struct ldb_request *search_req = NULL;
     483             :         struct ldb_message *remote_msg;
     484             :         struct ldb_context *ldb;
     485             :         struct map_context *ac;
     486             :         int ret;
     487             : 
     488           0 :         ldb = ldb_module_get_ctx(module);
     489             : 
     490             :         /* Do not manipulate our control entries */
     491           0 :         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           0 :         if (!ldb_dn_check_local(module, msg->dn)) {
     497           0 :                 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           0 :         if (!ldb_msg_check_remote(module, msg)) {
     505           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     506             :         }
     507             : 
     508             :         /* Prepare context and handle */
     509           0 :         ac = map_init_context(module, req);
     510           0 :         if (ac == NULL) {
     511           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     512             :         }
     513             : 
     514             :         /* Prepare the local message */
     515           0 :         ac->local_msg = ldb_msg_new(ac);
     516           0 :         if (ac->local_msg == NULL) {
     517           0 :                 map_oom(module);
     518           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     519             :         }
     520           0 :         ac->local_msg->dn = msg->dn;
     521             : 
     522             :         /* Prepare the remote message */
     523           0 :         remote_msg = ldb_msg_new(ac->remote_req);
     524           0 :         if (remote_msg == NULL) {
     525           0 :                 map_oom(module);
     526           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     527             :         }
     528           0 :         remote_msg->dn = ldb_dn_map_local(ac->module, remote_msg, msg->dn);
     529             : 
     530             :         /* Split local from remote message */
     531           0 :         ldb_msg_partition(module, req->operation, ac->local_msg, remote_msg, msg);
     532             : 
     533             :         /* Prepare the remote operation */
     534           0 :         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           0 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     540           0 :         if (ret != LDB_SUCCESS) {
     541           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     542             :         }
     543             : 
     544           0 :         if ((ac->local_msg->num_elements == 0) ||
     545           0 :             ( ! map_check_local_db(ac->module))) {
     546             :                 /* No local data or db, just run the remote request */
     547           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     548             :         }
     549             : 
     550             :         /* prepare the search operation */
     551           0 :         ret = map_search_self_req(&search_req, ac, msg->dn);
     552           0 :         if (ret != LDB_SUCCESS) {
     553           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     554             :         }
     555             : 
     556           0 :         return ldb_next_request(module, search_req);
     557             : }
     558             : 
     559             : /* Modify the local record. */
     560           0 : static int map_modify_do_local(struct map_context *ac)
     561             : {
     562             :         struct ldb_request *local_req;
     563             :         struct ldb_context *ldb;
     564             :         int ret;
     565             : 
     566           0 :         ldb = ldb_module_get_ctx(ac->module);
     567             : 
     568           0 :         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           0 :                 ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED,
     573           0 :                                                    ac->remote_req->op.mod.message->dn,
     574             :                                                    LDB_FLAG_MOD_ADD);
     575           0 :                 if (ret != 0) {
     576           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     577             :                 }
     578             : 
     579             :                 /* Prepare the local operation */
     580           0 :                 ret = ldb_build_add_req(&local_req, ldb, ac,
     581           0 :                                         ac->local_msg,
     582           0 :                                         ac->req->controls,
     583             :                                         ac,
     584             :                                         map_op_local_callback,
     585             :                                         ac->req);
     586           0 :                 LDB_REQ_SET_LOCATION(local_req);
     587           0 :                 if (ret != LDB_SUCCESS) {
     588           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     589             :                 }
     590             :         } else {
     591             :                 /* Prepare the local operation */
     592           0 :                 ret = ldb_build_mod_req(&local_req, ldb, ac,
     593           0 :                                         ac->local_msg,
     594           0 :                                         ac->req->controls,
     595             :                                         ac,
     596             :                                         map_op_local_callback,
     597             :                                         ac->req);
     598           0 :                 LDB_REQ_SET_LOCATION(local_req);
     599           0 :                 if (ret != LDB_SUCCESS) {
     600           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     601             :                 }
     602             :         }
     603             : 
     604           0 :         return ldb_next_request(ac->module, local_req);
     605             : }
     606             : 
     607             : /*****************************************************************************
     608             :  * DELETE operations
     609             : *****************************************************************************/
     610             : 
     611             : /* Delete a record. */
     612           0 : int ldb_map_delete(struct ldb_module *module, struct ldb_request *req)
     613             : {
     614             :         struct ldb_request *search_req;
     615             :         struct ldb_context *ldb;
     616             :         struct map_context *ac;
     617             :         int ret;
     618             : 
     619           0 :         ldb = ldb_module_get_ctx(module);
     620             : 
     621             :         /* Do not manipulate our control entries */
     622           0 :         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           0 :         if (!ldb_dn_check_local(module, req->op.del.dn)) {
     629           0 :                 return ldb_next_request(module, req);
     630             :         }
     631             : 
     632             :         /* Prepare context and handle */
     633           0 :         ac = map_init_context(module, req);
     634           0 :         if (ac == NULL) {
     635           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     636             :         }
     637             : 
     638             :         /* Prepare the remote operation */
     639           0 :         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           0 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     646           0 :         if (ret != LDB_SUCCESS) {
     647           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     648             :         }
     649             : 
     650             :         /* No local db, just run the remote request */
     651           0 :         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           0 :         ret = map_search_self_req(&search_req, ac, req->op.del.dn);
     658           0 :         if (ret != LDB_SUCCESS) {
     659           0 :                 map_oom(module);
     660           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     661             :         }
     662             : 
     663           0 :         return ldb_next_request(module, search_req);
     664             : }
     665             : 
     666             : /* Delete the local record. */
     667           0 : static int map_delete_do_local(struct map_context *ac)
     668             : {
     669             :         struct ldb_request *local_req;
     670             :         struct ldb_context *ldb;
     671             :         int ret;
     672             : 
     673           0 :         ldb = ldb_module_get_ctx(ac->module);
     674             : 
     675             :         /* No local record, continue remotely */
     676           0 :         if (ac->local_dn == NULL) {
     677             :                 /* Do the remote request. */
     678           0 :                 return ldb_next_remote_request(ac->module, ac->remote_req);
     679             :         }
     680             : 
     681             :         /* Prepare the local operation */
     682           0 :         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           0 :         LDB_REQ_SET_LOCATION(local_req);
     689           0 :         if (ret != LDB_SUCCESS) {
     690           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     691             :         }
     692           0 :         return ldb_next_request(ac->module, local_req);
     693             : }
     694             : 
     695             : /*****************************************************************************
     696             :  * RENAME operations
     697             : *****************************************************************************/
     698             : 
     699             : /* Rename a record. */
     700           0 : int ldb_map_rename(struct ldb_module *module, struct ldb_request *req)
     701             : {
     702           0 :         struct ldb_request *search_req = NULL;
     703             :         struct ldb_context *ldb;
     704             :         struct map_context *ac;
     705             :         int ret;
     706             : 
     707           0 :         ldb = ldb_module_get_ctx(module);
     708             : 
     709             :         /* Do not manipulate our control entries */
     710           0 :         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           0 :         if ((!ldb_dn_check_local(module, req->op.rename.olddn)) &&
     717           0 :             (!ldb_dn_check_local(module, req->op.rename.newdn))) {
     718           0 :                 return ldb_next_request(module, req);
     719             :         }
     720             : 
     721             :         /* Rename into/out of the mapped partition requested, bail out */
     722           0 :         if (!ldb_dn_check_local(module, req->op.rename.olddn) ||
     723           0 :             !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           0 :         ac = map_init_context(module, req);
     729           0 :         if (ac == NULL) {
     730           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     731             :         }
     732             : 
     733             :         /* Prepare the remote operation */
     734           0 :         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           0 :         LDB_REQ_SET_LOCATION(ac->remote_req);
     741           0 :         if (ret != LDB_SUCCESS) {
     742           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     743             :         }
     744             : 
     745             :         /* No local db, just run the remote request */
     746           0 :         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           0 :         ret = map_search_self_req(&search_req, ac, req->op.rename.olddn);
     753           0 :         if (ret != LDB_SUCCESS) {
     754           0 :                 map_oom(module);
     755           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     756             :         }
     757             : 
     758           0 :         return ldb_next_request(module, search_req);
     759             : }
     760             : 
     761             : /* Rename the local record. */
     762           0 : static int map_rename_do_local(struct map_context *ac)
     763             : {
     764             :         struct ldb_request *local_req;
     765             :         struct ldb_context *ldb;
     766             :         int ret;
     767             : 
     768           0 :         ldb = ldb_module_get_ctx(ac->module);
     769             : 
     770             :         /* No local record, continue remotely */
     771           0 :         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           0 :         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           0 :         LDB_REQ_SET_LOCATION(local_req);
     785           0 :         if (ret != LDB_SUCCESS) {
     786           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     787             :         }
     788             : 
     789           0 :         return ldb_next_request(ac->module, local_req);
     790             : }
     791             : 
     792           0 : static int map_rename_local_callback(struct ldb_request *req,
     793             :                                      struct ldb_reply *ares)
     794             : {
     795             :         struct ldb_context *ldb;
     796             :         struct map_context *ac;
     797             :         int ret;
     798             : 
     799           0 :         ac = talloc_get_type(req->context, struct map_context);
     800           0 :         ldb = ldb_module_get_ctx(ac->module);
     801             : 
     802           0 :         if (!ares) {
     803           0 :                 return ldb_module_done(ac->req, NULL, NULL,
     804             :                                         LDB_ERR_OPERATIONS_ERROR);
     805             :         }
     806           0 :         if (ares->error != LDB_SUCCESS) {
     807           0 :                 return ldb_module_done(ac->req, ares->controls,
     808             :                                         ares->response, ares->error);
     809             :         }
     810             : 
     811           0 :         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           0 :         ret = map_rename_do_fixup(ac);
     819           0 :         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           0 : static int map_rename_do_fixup(struct map_context *ac)
     829             : {
     830             :         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           0 :         local_req = map_build_fixup_req(ac,
     835           0 :                                         ac->req->op.rename.newdn,
     836           0 :                                         ac->remote_req->op.rename.newdn,
     837             :                                         ac,
     838             :                                         map_op_local_callback);
     839           0 :         if (local_req == NULL) {
     840           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     841             :         }
     842             : 
     843           0 :         return ldb_next_request(ac->module, local_req);
     844             : }

Generated by: LCOV version 1.13