root/source4/lib/ldb/modules/rdn_name.c

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

DEFINITIONS

This source file includes following definitions.
  1. rdn_name_find_attribute
  2. rdn_name_add_callback
  3. rdn_name_add
  4. rdn_modify_callback
  5. rdn_rename_callback
  6. rdn_name_rename

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Andrew Bartlet 2005
   5    Copyright (C) Simo Sorce     2006-2008
   6 
   7      ** NOTE! The following LGPL license applies to the ldb
   8      ** library. This does NOT imply that all of Samba is released
   9      ** under the LGPL
  10    
  11    This library is free software; you can redistribute it and/or
  12    modify it under the terms of the GNU Lesser General Public
  13    License as published by the Free Software Foundation; either
  14    version 3 of the License, or (at your option) any later version.
  15 
  16    This library is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  19    Lesser General Public License for more details.
  20 
  21    You should have received a copy of the GNU Lesser General Public
  22    License along with this library; if not, see <http://www.gnu.org/licenses/>.
  23 */
  24 
  25 /*
  26  *  Name: rdb_name
  27  *
  28  *  Component: ldb rdn name module
  29  *
  30  *  Description: keep a consistent name attribute on objects manpulations
  31  *
  32  *  Author: Andrew Bartlet
  33  *
  34  *  Modifications:
  35  *    - made the module async
  36  *      Simo Sorce Mar 2006
  37  */
  38 
  39 #include "ldb_includes.h"
  40 #include "ldb_module.h"
  41 
  42 struct rename_context {
  43 
  44         struct ldb_module *module;
  45         struct ldb_request *req;
  46 
  47         struct ldb_reply *ares;
  48 };
  49 
  50 static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  51 {
  52         int i;
  53 
  54         for (i = 0; i < msg->num_elements; i++) {
  55                 if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
  56                         return &msg->elements[i];
  57                 }
  58         }
  59 
  60         return NULL;
  61 }
  62 
  63 static int rdn_name_add_callback(struct ldb_request *req,
     /* [<][>][^][v][top][bottom][index][help] */
  64                                  struct ldb_reply *ares)
  65 {
  66         struct rename_context *ac;
  67 
  68         ac = talloc_get_type(req->context, struct rename_context);
  69 
  70         if (!ares) {
  71                 return ldb_module_done(ac->req, NULL, NULL,
  72                                         LDB_ERR_OPERATIONS_ERROR);
  73         }
  74         if (ares->error != LDB_SUCCESS) {
  75                 return ldb_module_done(ac->req, ares->controls,
  76                                         ares->response, ares->error);
  77         }
  78 
  79         if (ares->type != LDB_REPLY_DONE) {
  80                 return ldb_module_done(ac->req, NULL, NULL,
  81                                         LDB_ERR_OPERATIONS_ERROR);
  82         }
  83 
  84         return ldb_module_done(ac->req, ares->controls,
  85                                         ares->response, LDB_SUCCESS);
  86 }
  87 
  88 static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
  89 {
  90         struct ldb_context *ldb;
  91         struct ldb_request *down_req;
  92         struct rename_context *ac;
  93         struct ldb_message *msg;
  94         struct ldb_message_element *attribute;
  95         const struct ldb_schema_attribute *a;
  96         const char *rdn_name;
  97         struct ldb_val rdn_val;
  98         int i, ret;
  99 
 100         ldb = ldb_module_get_ctx(module);
 101         ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
 102 
 103         /* do not manipulate our control entries */
 104         if (ldb_dn_is_special(req->op.add.message->dn)) {
 105                 return ldb_next_request(module, req);
 106         }
 107 
 108         ac = talloc_zero(req, struct rename_context);
 109         if (ac == NULL) {
 110                 return LDB_ERR_OPERATIONS_ERROR;
 111         }
 112 
 113         ac->module = module;
 114         ac->req = req;
 115 
 116         msg = ldb_msg_copy_shallow(req, req->op.add.message);
 117         if (msg == NULL) {
 118                 return LDB_ERR_OPERATIONS_ERROR;
 119         }
 120 
 121         rdn_name = ldb_dn_get_rdn_name(msg->dn);
 122         if (rdn_name == NULL) {
 123                 talloc_free(ac);
 124                 return LDB_ERR_OPERATIONS_ERROR;
 125         }
 126         
 127         rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(msg->dn));
 128         
 129         /* Perhaps someone above us tried to set this? */
 130         if ((attribute = rdn_name_find_attribute(msg, "name")) != NULL ) {
 131                 attribute->num_values = 0;
 132         }
 133 
 134         if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
 135                 talloc_free(ac);
 136                 return LDB_ERR_OPERATIONS_ERROR;
 137         }
 138 
 139         attribute = rdn_name_find_attribute(msg, rdn_name);
 140 
 141         if (!attribute) {
 142                 if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
 143                         talloc_free(ac);
 144                         return LDB_ERR_OPERATIONS_ERROR;
 145                 }
 146         } else {
 147                 a = ldb_schema_attribute_by_name(ldb, rdn_name);
 148 
 149                 for (i = 0; i < attribute->num_values; i++) {
 150                         ret = a->syntax->comparison_fn(ldb, msg,
 151                                         &rdn_val, &attribute->values[i]);
 152                         if (ret == 0) {
 153                                 /* overwrite so it matches in case */
 154                                 attribute->values[i] = rdn_val;
 155                                 break;
 156                         }
 157                 }
 158                 if (i == attribute->num_values) {
 159                         ldb_debug_set(ldb, LDB_DEBUG_FATAL, 
 160                                       "RDN mismatch on %s: %s (%s)", 
 161                                       ldb_dn_get_linearized(msg->dn), rdn_name, rdn_val.data);
 162                         talloc_free(ac);
 163                         /* Match AD's error here */
 164                         return LDB_ERR_INVALID_DN_SYNTAX;
 165                 }
 166         }
 167 
 168         ret = ldb_build_add_req(&down_req, ldb, req,
 169                                 msg,
 170                                 req->controls,
 171                                 ac, rdn_name_add_callback,
 172                                 req);
 173         if (ret != LDB_SUCCESS) {
 174                 return ret;
 175         }
 176 
 177         talloc_steal(down_req, msg);
 178 
 179         /* go on with the call chain */
 180         return ldb_next_request(module, down_req);
 181 }
 182 
 183 static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
 184 {
 185         struct rename_context *ac;
 186 
 187         ac = talloc_get_type(req->context, struct rename_context);
 188 
 189         if (!ares) {
 190                 return ldb_module_done(ac->req, NULL, NULL,
 191                                         LDB_ERR_OPERATIONS_ERROR);
 192         }
 193         if (ares->error != LDB_SUCCESS) {
 194                 return ldb_module_done(ac->req, ares->controls,
 195                                         ares->response, ares->error);
 196         }
 197 
 198         /* the only supported reply right now is a LDB_REPLY_DONE */
 199         if (ares->type != LDB_REPLY_DONE) {
 200                 return ldb_module_done(ac->req, NULL, NULL,
 201                                         LDB_ERR_OPERATIONS_ERROR);
 202         }
 203 
 204         /* send saved controls eventually */
 205         return ldb_module_done(ac->req, ac->ares->controls,
 206                                 ac->ares->response, LDB_SUCCESS);
 207 }
 208 
 209 static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
 210 {
 211         struct ldb_context *ldb;
 212         struct rename_context *ac;
 213         struct ldb_request *mod_req;
 214         const char *rdn_name;
 215         struct ldb_val rdn_val;
 216         struct ldb_message *msg;
 217         int ret;
 218 
 219         ac = talloc_get_type(req->context, struct rename_context);
 220         ldb = ldb_module_get_ctx(ac->module);
 221 
 222         if (!ares) {
 223                 goto error;
 224         }
 225         if (ares->error != LDB_SUCCESS) {
 226                 return ldb_module_done(ac->req, ares->controls,
 227                                         ares->response, ares->error);
 228         }
 229 
 230         /* the only supported reply right now is a LDB_REPLY_DONE */
 231         if (ares->type != LDB_REPLY_DONE) {
 232                 goto error;
 233         }
 234 
 235         /* save reply for caller */
 236         ac->ares = talloc_steal(ac, ares);
 237 
 238         msg = ldb_msg_new(ac);
 239         if (msg == NULL) {
 240                 goto error;
 241         }
 242         msg->dn = ldb_dn_copy(msg, ac->req->op.rename.newdn);
 243         if (msg->dn == NULL) {
 244                 goto error;
 245         }
 246         rdn_name = ldb_dn_get_rdn_name(ac->req->op.rename.newdn);
 247         if (rdn_name == NULL) {
 248                 goto error;
 249         }
 250         
 251         rdn_val = ldb_val_dup(msg, ldb_dn_get_rdn_val(ac->req->op.rename.newdn));
 252         
 253         if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
 254                 goto error;
 255         }
 256         if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
 257                 goto error;
 258         }
 259         if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
 260                 goto error;
 261         }
 262         if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
 263                 goto error;
 264         }
 265 
 266         ret = ldb_build_mod_req(&mod_req, ldb,
 267                                 ac, msg, NULL,
 268                                 ac, rdn_modify_callback,
 269                                 req);
 270         if (ret != LDB_SUCCESS) {
 271                 return ldb_module_done(ac->req, NULL, NULL, ret);
 272         }
 273         talloc_steal(mod_req, msg);
 274 
 275         /* do the mod call */
 276         return ldb_request(ldb, mod_req);
 277 
 278 error:
 279         return ldb_module_done(ac->req, NULL, NULL,
 280                                                 LDB_ERR_OPERATIONS_ERROR);
 281 }
 282 
 283 static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 284 {
 285         struct ldb_context *ldb;
 286         struct rename_context *ac;
 287         struct ldb_request *down_req;
 288         int ret;
 289 
 290         ldb = ldb_module_get_ctx(module);
 291         ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_rename\n");
 292 
 293         /* do not manipulate our control entries */
 294         if (ldb_dn_is_special(req->op.rename.newdn)) {
 295                 return ldb_next_request(module, req);
 296         }
 297 
 298         ac = talloc_zero(req, struct rename_context);
 299         if (ac == NULL) {
 300                 return LDB_ERR_OPERATIONS_ERROR;
 301         }
 302 
 303         ac->module = module;
 304         ac->req = req;
 305 
 306         ret = ldb_build_rename_req(&down_req,
 307                                    ldb,
 308                                    ac,
 309                                    req->op.rename.olddn,
 310                                    req->op.rename.newdn,
 311                                    req->controls,
 312                                    ac,
 313                                    rdn_rename_callback,
 314                                    req);
 315 
 316         if (ret != LDB_SUCCESS) {
 317                 return LDB_ERR_OPERATIONS_ERROR;
 318         }
 319 
 320         /* rename first, modify "name" if rename is ok */
 321         return ldb_next_request(module, down_req);
 322 }
 323 
 324 const struct ldb_module_ops ldb_rdn_name_module_ops = {
 325         .name              = "rdn_name",
 326         .add               = rdn_name_add,
 327         .rename            = rdn_name_rename,
 328 };

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