root/source4/dsdb/samdb/ldb_modules/subtree_delete.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. subdel_ctx_init
  2. subtree_delete_search_callback
  3. subtree_delete

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
   5    Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
   6    Copyright (C) Simo Sorce <idra@samba.org> 2008
   7 
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 /*
  23  *  Name: ldb
  24  *
  25  *  Component: ldb subtree delete (prevention) module
  26  *
  27  *  Description: Prevent deletion of a subtree in LDB
  28  *
  29  *  Author: Andrew Bartlett
  30  */
  31 
  32 #include "ldb_module.h"
  33 
  34 struct subtree_delete_context {
  35         struct ldb_module *module;
  36         struct ldb_request *req;
  37 
  38         int num_children;
  39 };
  40 
  41 static struct subtree_delete_context *subdel_ctx_init(struct ldb_module *module,
     /* [<][>][^][v][top][bottom][index][help] */
  42                                                       struct ldb_request *req)
  43 {
  44         struct ldb_context *ldb;
  45         struct subtree_delete_context *ac;
  46 
  47         ldb = ldb_module_get_ctx(module);
  48 
  49         ac = talloc_zero(req, struct subtree_delete_context);
  50         if (ac == NULL) {
  51                 ldb_oom(ldb);
  52                 return NULL;
  53         }
  54 
  55         ac->module = module;
  56         ac->req = req;
  57 
  58         return ac;
  59 }
  60 
  61 static int subtree_delete_search_callback(struct ldb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
  62                                           struct ldb_reply *ares)
  63 {
  64         struct ldb_context *ldb;
  65         struct subtree_delete_context *ac;
  66         int ret;
  67 
  68         ac = talloc_get_type(req->context, struct subtree_delete_context);
  69         ldb = ldb_module_get_ctx(ac->module);
  70 
  71         if (!ares) {
  72                 return ldb_module_done(ac->req, NULL, NULL,
  73                                         LDB_ERR_OPERATIONS_ERROR);
  74         }
  75         if (ares->error != LDB_SUCCESS) {
  76                 return ldb_module_done(ac->req, ares->controls,
  77                                         ares->response, ares->error);
  78         }
  79 
  80         switch (ares->type) {
  81         case LDB_REPLY_ENTRY:
  82 
  83                 talloc_free(ares);
  84                 ac->num_children++;
  85                 break;
  86 
  87         case LDB_REPLY_REFERRAL:
  88 
  89                 /* ignore */
  90                 talloc_free(ares);
  91                 break;
  92 
  93         case LDB_REPLY_DONE:
  94 
  95                 if (ac->num_children > 0) {
  96                         talloc_free(ares);
  97                         ldb_asprintf_errstring(ldb,
  98                                 "Cannot delete %s, not a leaf node "
  99                                 "(has %d children)\n",
 100                                 ldb_dn_get_linearized(ac->req->op.del.dn),
 101                                 ac->num_children);
 102                         return ldb_module_done(ac->req, NULL, NULL,
 103                                                LDB_ERR_NOT_ALLOWED_ON_NON_LEAF);
 104                 }
 105 
 106                 /* ok no children, let the original request through */
 107                 ret = ldb_next_request(ac->module, ac->req);
 108                 if (ret != LDB_SUCCESS) {
 109                         return ldb_module_done(ac->req, NULL, NULL, ret);
 110                 }
 111 
 112                 /* free our own context we are not going to be called back */
 113                 talloc_free(ac);
 114         }
 115         return LDB_SUCCESS;
 116 }
 117 
 118 static int subtree_delete(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 119 {
 120         struct ldb_context *ldb;
 121         static const char * const attrs[2] = { "distinguishedName", NULL };
 122         struct ldb_request *search_req;
 123         struct subtree_delete_context *ac;
 124         int ret;
 125         if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
 126                 return ldb_next_request(module, req);
 127         }
 128 
 129         ldb = ldb_module_get_ctx(module);
 130 
 131         /* This gets complex:  We need to:
 132            - Do a search for all entires under this entry 
 133            - Wait for these results to appear
 134            - In the callback for each result, count the children (if any)
 135            - return an error if there are any
 136         */
 137 
 138         ac = subdel_ctx_init(module, req);
 139         if (!ac) {
 140                 return LDB_ERR_OPERATIONS_ERROR;
 141         }
 142 
 143         /* we do not really need to find all descendents,
 144          * if there is even one single direct child, that's
 145          * enough to bail out */
 146         ret = ldb_build_search_req(&search_req, ldb, ac,
 147                                    req->op.del.dn, LDB_SCOPE_ONELEVEL,
 148                                    "(objectClass=*)", attrs,
 149                                    req->controls,
 150                                    ac, subtree_delete_search_callback,
 151                                    req);
 152         if (ret != LDB_SUCCESS) {
 153                 return ret;
 154         }
 155 
 156         return ldb_next_request(module, search_req);
 157 }
 158 
 159 const struct ldb_module_ops ldb_subtree_delete_module_ops = {
 160         .name              = "subtree_delete",
 161         .del               = subtree_delete,
 162 };

/* [<][>][^][v][top][bottom][index][help] */