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

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

DEFINITIONS

This source file includes following definitions.
  1. extended_final_callback
  2. extended_base_callback
  3. extended_dn_in_fix
  4. extended_dn_in_search
  5. extended_dn_in_modify
  6. extended_dn_in_del
  7. extended_dn_in_rename

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Simo Sorce 2005-2008
   5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007-2008
   6 
   7    This program is free software; you can redistribute it and/or modify
   8    it under the terms of the GNU General Public License as published by
   9    the Free Software Foundation; either version 3 of the License, or
  10    (at your option) any later version.
  11    
  12    This program is distributed in the hope that it will be useful,
  13    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15    GNU General Public License for more details.
  16    
  17    You should have received a copy of the GNU General Public License
  18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  19 */
  20 
  21 /*
  22  *  Name: ldb
  23  *
  24  *  Component: ldb extended dn control module
  25  *
  26  *  Description: this module interprets DNs of the form <SID=S-1-2-4456> into normal DNs.
  27  *
  28  *  Authors: Simo Sorce
  29  *           Andrew Bartlett
  30  */
  31 
  32 #include "includes.h"
  33 #include "ldb/include/ldb.h"
  34 #include "ldb/include/ldb_errors.h"
  35 #include "ldb/include/ldb_private.h"
  36 
  37 /* search */
  38 struct extended_search_context {
  39         struct ldb_module *module;
  40         struct ldb_request *req;
  41         struct ldb_dn *basedn;
  42         char *wellknown_object;
  43         int extended_type;
  44 };
  45 
  46 /* An extra layer of indirection because LDB does not allow the original request to be altered */
  47 
  48 static int extended_final_callback(struct ldb_request *req, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
  49 {
  50         int ret = LDB_ERR_OPERATIONS_ERROR;
  51         struct extended_search_context *ac;
  52         ac = talloc_get_type(req->context, struct extended_search_context);
  53 
  54         if (ares->error != LDB_SUCCESS) {
  55                 ret = ldb_module_done(ac->req, ares->controls,
  56                                       ares->response, ares->error);
  57         } else {
  58                 switch (ares->type) {
  59                 case LDB_REPLY_ENTRY:
  60                         
  61                         ret = ldb_module_send_entry(ac->req, ares->message, ares->controls);
  62                         break;
  63                 case LDB_REPLY_REFERRAL:
  64                         
  65                         ret = ldb_module_send_referral(ac->req, ares->referral);
  66                         break;
  67                 case LDB_REPLY_DONE:
  68                         
  69                         ret = ldb_module_done(ac->req, ares->controls,
  70                                               ares->response, ares->error);
  71                         break;
  72                 }
  73         }
  74         return ret;
  75 }
  76 
  77 static int extended_base_callback(struct ldb_request *req, struct ldb_reply *ares)
     /* [<][>][^][v][top][bottom][index][help] */
  78 {
  79         struct extended_search_context *ac;
  80         struct ldb_request *down_req;
  81         struct ldb_message_element *el;
  82         int ret;
  83         size_t i;
  84         size_t wkn_len = 0;
  85         char *valstr = NULL;
  86         const char *found = NULL;
  87 
  88         ac = talloc_get_type(req->context, struct extended_search_context);
  89 
  90         if (!ares) {
  91                 return ldb_module_done(ac->req, NULL, NULL,
  92                                         LDB_ERR_OPERATIONS_ERROR);
  93         }
  94         if (ares->error != LDB_SUCCESS) {
  95                 return ldb_module_done(ac->req, ares->controls,
  96                                         ares->response, ares->error);
  97         }
  98 
  99         switch (ares->type) {
 100         case LDB_REPLY_ENTRY:
 101                 if (!ac->wellknown_object) {
 102                         ac->basedn = talloc_steal(ac, ares->message->dn);
 103                         break;
 104                 }
 105 
 106                 wkn_len = strlen(ac->wellknown_object);
 107 
 108                 el = ldb_msg_find_element(ares->message, "wellKnownObjects");
 109                 if (!el) {
 110                         ac->basedn = NULL;
 111                         break;
 112                 }
 113 
 114                 for (i=0; i < el->num_values; i++) {
 115                         valstr = talloc_strndup(ac,
 116                                                 (const char *)el->values[i].data,
 117                                                 el->values[i].length);
 118                         if (!valstr) {
 119                                 ldb_oom(ac->module->ldb);
 120                                 return ldb_module_done(ac->req, NULL, NULL,
 121                                                        LDB_ERR_OPERATIONS_ERROR);
 122                         }
 123 
 124                         if (strncasecmp(valstr, ac->wellknown_object, wkn_len) != 0) {
 125                                 talloc_free(valstr);
 126                                 continue;
 127                         }
 128 
 129                         found = &valstr[wkn_len];
 130                         break;
 131                 }
 132 
 133                 if (!found) {
 134                         break;
 135                 }
 136 
 137                 ac->basedn = ldb_dn_new(ac, ac->module->ldb, found);
 138                 talloc_free(valstr);
 139                 if (!ac->basedn) {
 140                         ldb_oom(ac->module->ldb);
 141                         return ldb_module_done(ac->req, NULL, NULL,
 142                                                LDB_ERR_OPERATIONS_ERROR);
 143                 }
 144 
 145                 break;
 146 
 147         case LDB_REPLY_REFERRAL:
 148                 break;
 149 
 150         case LDB_REPLY_DONE:
 151 
 152                 if (!ac->basedn) {
 153                         const char *str = talloc_asprintf(req, "Base-DN '%s' not found",
 154                                                           ldb_dn_get_linearized(ac->req->op.search.base));
 155                         ldb_set_errstring(ac->module->ldb, str);
 156                         return ldb_module_done(ac->req, NULL, NULL,
 157                                                LDB_ERR_NO_SUCH_OBJECT);
 158                 }
 159 
 160                 switch (ac->req->operation) {
 161                 case LDB_SEARCH:
 162                         ret = ldb_build_search_req_ex(&down_req,
 163                                                       ac->module->ldb, ac->req,
 164                                                       ac->basedn,
 165                                                       ac->req->op.search.scope,
 166                                                       ac->req->op.search.tree,
 167                                                       ac->req->op.search.attrs,
 168                                                       ac->req->controls,
 169                                                       ac, extended_final_callback, 
 170                                                       ac->req);
 171                         break;
 172                 case LDB_ADD:
 173                 {
 174                         struct ldb_message *add_msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
 175                         if (!add_msg) {
 176                                 ldb_oom(ac->module->ldb);
 177                                 return ldb_module_done(ac->req, NULL, NULL,
 178                                                        LDB_ERR_OPERATIONS_ERROR);
 179                         }
 180                         
 181                         add_msg->dn = ac->basedn;
 182 
 183                         ret = ldb_build_add_req(&down_req,
 184                                                 ac->module->ldb, ac->req,
 185                                                 add_msg, 
 186                                                 ac->req->controls,
 187                                                 ac, extended_final_callback, 
 188                                                 ac->req);
 189                         break;
 190                 }
 191                 case LDB_MODIFY:
 192                 {
 193                         struct ldb_message *mod_msg = ldb_msg_copy_shallow(ac, ac->req->op.mod.message);
 194                         if (!mod_msg) {
 195                                 ldb_oom(ac->module->ldb);
 196                                 return ldb_module_done(ac->req, NULL, NULL,
 197                                                        LDB_ERR_OPERATIONS_ERROR);
 198                         }
 199                         
 200                         mod_msg->dn = ac->basedn;
 201 
 202                         ret = ldb_build_mod_req(&down_req,
 203                                                 ac->module->ldb, ac->req,
 204                                                 mod_msg, 
 205                                                 ac->req->controls,
 206                                                 ac, extended_final_callback, 
 207                                                 ac->req);
 208                         break;
 209                 }
 210                 case LDB_DELETE:
 211                         ret = ldb_build_del_req(&down_req,
 212                                                 ac->module->ldb, ac->req,
 213                                                 ac->basedn, 
 214                                                 ac->req->controls,
 215                                                 ac, extended_final_callback, 
 216                                                 ac->req);
 217                         break;
 218                 case LDB_RENAME:
 219                         ret = ldb_build_rename_req(&down_req,
 220                                                    ac->module->ldb, ac->req,
 221                                                    ac->basedn, 
 222                                                    ac->req->op.rename.newdn,
 223                                                    ac->req->controls,
 224                                                    ac, extended_final_callback, 
 225                                                    ac->req);
 226                         break;
 227                 default:
 228                         return ldb_module_done(ac->req, NULL, NULL, LDB_ERR_OPERATIONS_ERROR);
 229                 }
 230                 
 231                 if (ret != LDB_SUCCESS) {
 232                         return ldb_module_done(ac->req, NULL, NULL, ret);
 233                 }
 234 
 235                 return ldb_next_request(ac->module, down_req);
 236         }
 237         talloc_free(ares);
 238         return LDB_SUCCESS;
 239 }
 240 
 241 static int extended_dn_in_fix(struct ldb_module *module, struct ldb_request *req, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 242 {
 243         struct extended_search_context *ac;
 244         struct ldb_request *down_req;
 245         int ret;
 246         struct ldb_dn *base_dn = NULL;
 247         enum ldb_scope base_dn_scope = LDB_SCOPE_BASE;
 248         const char *base_dn_filter = NULL;
 249         const char * const *base_dn_attrs = NULL;
 250         char *wellknown_object = NULL;
 251         static const char *no_attr[] = {
 252                 NULL
 253         };
 254         static const char *wkattr[] = {
 255                 "wellKnownObjects",
 256                 NULL
 257         };
 258 
 259         if (!ldb_dn_has_extended(dn)) {
 260                 /* Move along there isn't anything to see here */
 261                 return ldb_next_request(module, req);
 262         } else {
 263                 /* It looks like we need to map the DN */
 264                 const struct ldb_val *sid_val, *guid_val, *wkguid_val;
 265 
 266                 sid_val = ldb_dn_get_extended_component(dn, "SID");
 267                 guid_val = ldb_dn_get_extended_component(dn, "GUID");
 268                 wkguid_val = ldb_dn_get_extended_component(dn, "WKGUID");
 269 
 270                 if (sid_val) {
 271                         /* TODO: do a search over all partitions */
 272                         base_dn = ldb_get_default_basedn(module->ldb);
 273                         base_dn_filter = talloc_asprintf(req, "(objectSid=%s)", 
 274                                                          ldb_binary_encode(req, *sid_val));
 275                         if (!base_dn_filter) {
 276                                 ldb_oom(module->ldb);
 277                                 return LDB_ERR_OPERATIONS_ERROR;
 278                         }
 279                         base_dn_scope = LDB_SCOPE_SUBTREE;
 280                         base_dn_attrs = no_attr;
 281 
 282                 } else if (guid_val) {
 283 
 284                         /* TODO: do a search over all partitions */
 285                         base_dn = ldb_get_default_basedn(module->ldb);
 286                         base_dn_filter = talloc_asprintf(req, "(objectGUID=%s)", 
 287                                                          ldb_binary_encode(req, *guid_val));
 288                         if (!base_dn_filter) {
 289                                 ldb_oom(module->ldb);
 290                                 return LDB_ERR_OPERATIONS_ERROR;
 291                         }
 292                         base_dn_scope = LDB_SCOPE_SUBTREE;
 293                         base_dn_attrs = no_attr;
 294 
 295 
 296                 } else if (wkguid_val) {
 297                         char *wkguid_dup;
 298                         char *tail_str;
 299                         char *p;
 300 
 301                         wkguid_dup = talloc_strndup(req, (char *)wkguid_val->data, wkguid_val->length);
 302 
 303                         p = strchr(wkguid_dup, ',');
 304                         if (!p) {
 305                                 return LDB_ERR_INVALID_DN_SYNTAX;
 306                         }
 307 
 308                         p[0] = '\0';
 309                         p++;
 310 
 311                         wellknown_object = talloc_asprintf(req, "B:32:%s:", wkguid_dup);
 312                         if (!wellknown_object) {
 313                                 ldb_oom(module->ldb);
 314                                 return LDB_ERR_OPERATIONS_ERROR;
 315                         }
 316 
 317                         tail_str = p;
 318 
 319                         base_dn = ldb_dn_new(req, module->ldb, tail_str);
 320                         talloc_free(wkguid_dup);
 321                         if (!base_dn) {
 322                                 ldb_oom(module->ldb);
 323                                 return LDB_ERR_OPERATIONS_ERROR;
 324                         }
 325                         base_dn_filter = talloc_strdup(req, "(objectClass=*)");
 326                         if (!base_dn_filter) {
 327                                 ldb_oom(module->ldb);
 328                                 return LDB_ERR_OPERATIONS_ERROR;
 329                         }
 330                         base_dn_scope = LDB_SCOPE_BASE;
 331                         base_dn_attrs = wkattr;
 332                 } else {
 333                         return LDB_ERR_INVALID_DN_SYNTAX;
 334                 }
 335 
 336                 ac = talloc_zero(req, struct extended_search_context);
 337                 if (ac == NULL) {
 338                         ldb_oom(module->ldb);
 339                         return LDB_ERR_OPERATIONS_ERROR;
 340                 }
 341                 
 342                 ac->module = module;
 343                 ac->req = req;
 344                 ac->basedn = NULL;  /* Filled in if the search finds the DN by SID/GUID etc */
 345                 ac->wellknown_object = wellknown_object;
 346                 
 347                 /* If the base DN was an extended DN (perhaps a well known
 348                  * GUID) then search for that, so we can proceed with the original operation */
 349 
 350                 ret = ldb_build_search_req(&down_req,
 351                                            module->ldb, ac,
 352                                            base_dn,
 353                                            base_dn_scope,
 354                                            base_dn_filter,
 355                                            base_dn_attrs,
 356                                            NULL,
 357                                            ac, extended_base_callback,
 358                                            req);
 359                 if (ret != LDB_SUCCESS) {
 360                         return LDB_ERR_OPERATIONS_ERROR;
 361                 }
 362 
 363                 /* perform the search */
 364                 return ldb_next_request(module, down_req);
 365         }
 366 }
 367 
 368 static int extended_dn_in_search(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 369 {
 370         return extended_dn_in_fix(module, req, req->op.search.base);
 371 }
 372 
 373 static int extended_dn_in_modify(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 374 {
 375         return extended_dn_in_fix(module, req, req->op.mod.message->dn);
 376 }
 377 
 378 static int extended_dn_in_del(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 379 {
 380         return extended_dn_in_fix(module, req, req->op.del.dn);
 381 }
 382 
 383 static int extended_dn_in_rename(struct ldb_module *module, struct ldb_request *req)
     /* [<][>][^][v][top][bottom][index][help] */
 384 {
 385         return extended_dn_in_fix(module, req, req->op.rename.olddn);
 386 }
 387 
 388 _PUBLIC_ const struct ldb_module_ops ldb_extended_dn_in_module_ops = {
 389         .name              = "extended_dn_in",
 390         .search            = extended_dn_in_search,
 391         .modify            = extended_dn_in_modify,
 392         .del               = extended_dn_in_del,
 393         .rename            = extended_dn_in_rename,
 394 };

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