root/source4/lib/ldb/common/ldb_dn.c

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

DEFINITIONS

This source file includes following definitions.
  1. ldb_dn_from_ldb_val
  2. ldb_dn_new
  3. ldb_dn_new_fmt
  4. ldb_dn_escape_internal
  5. ldb_dn_escape_value
  6. ldb_dn_explode
  7. ldb_dn_validate
  8. ldb_dn_get_linearized
  9. ldb_dn_get_extended_linearized
  10. ldb_dn_alloc_linearized
  11. ldb_dn_casefold_internal
  12. ldb_dn_get_casefold
  13. ldb_dn_alloc_casefold
  14. ldb_dn_compare_base
  15. ldb_dn_compare
  16. ldb_dn_copy_component
  17. ldb_dn_extended_copy_component
  18. ldb_dn_copy
  19. ldb_dn_add_base
  20. ldb_dn_add_base_fmt
  21. ldb_dn_add_child
  22. ldb_dn_add_child_fmt
  23. ldb_dn_remove_base_components
  24. ldb_dn_remove_child_components
  25. ldb_dn_get_parent
  26. ldb_dn_canonical
  27. ldb_dn_canonical_string
  28. ldb_dn_canonical_ex_string
  29. ldb_dn_get_comp_num
  30. ldb_dn_get_component_name
  31. ldb_dn_get_component_val
  32. ldb_dn_get_rdn_name
  33. ldb_dn_get_rdn_val
  34. ldb_dn_set_component
  35. ldb_dn_get_extended_component
  36. ldb_dn_set_extended_component
  37. ldb_dn_remove_extended_components
  38. ldb_dn_is_valid
  39. ldb_dn_is_special
  40. ldb_dn_has_extended
  41. ldb_dn_check_special
  42. ldb_dn_is_null

   1 /* 
   2    ldb database library
   3 
   4    Copyright (C) Simo Sorce 2005
   5 
   6      ** NOTE! The following LGPL license applies to the ldb
   7      ** library. This does NOT imply that all of Samba is released
   8      ** under the LGPL
   9    
  10    This library is free software; you can redistribute it and/or
  11    modify it under the terms of the GNU Lesser General Public
  12    License as published by the Free Software Foundation; either
  13    version 3 of the License, or (at your option) any later version.
  14 
  15    This library is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18    Lesser General Public License for more details.
  19 
  20    You should have received a copy of the GNU Lesser General Public
  21    License along with this library; if not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 /*
  25  *  Name: ldb
  26  *
  27  *  Component: ldb dn creation and manipulation utility functions
  28  *
  29  *  Description: - explode a dn into it's own basic elements
  30  *                 and put them in a structure (only if necessary)
  31  *               - manipulate ldb_dn structures
  32  *
  33  *  Author: Simo Sorce
  34  */
  35 
  36 #include "ldb_private.h"
  37 #include <ctype.h>
  38 
  39 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
  40 
  41 #define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
  42 
  43 /**
  44    internal ldb exploded dn structures
  45 */
  46 struct ldb_dn_component {
  47 
  48         char *name;
  49         struct ldb_val value;
  50 
  51         char *cf_name;
  52         struct ldb_val cf_value;
  53 };
  54 
  55 struct ldb_dn_extended_component {
  56 
  57         char *name;
  58         struct ldb_val value;
  59 };
  60 
  61 struct ldb_dn {
  62 
  63         struct ldb_context *ldb;
  64 
  65         /* Special DNs are always linearized */
  66         bool special;
  67         bool invalid;
  68 
  69         bool valid_case;
  70 
  71         char *linearized;
  72         char *extended_linearized;
  73         char *casefold;
  74 
  75         unsigned int comp_num;
  76         struct ldb_dn_component *components;
  77 
  78         unsigned int extended_comp_num;
  79         struct ldb_dn_extended_component *extended_components;
  80 };
  81 
  82 /* strdn may be NULL */
  83 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
     /* [<][>][^][v][top][bottom][index][help] */
  84 {
  85         struct ldb_dn *dn;
  86 
  87         if (! ldb) return NULL;
  88 
  89         dn = talloc_zero(mem_ctx, struct ldb_dn);
  90         LDB_DN_NULL_FAILED(dn);
  91 
  92         dn->ldb = ldb;
  93 
  94         if (strdn->data && strdn->length) {
  95                 if (strdn->data[0] == '@') {
  96                         dn->special = true;
  97                 } 
  98                 dn->extended_linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
  99                 LDB_DN_NULL_FAILED(dn->extended_linearized);
 100         
 101                 if (strdn->data[0] == '<') {
 102                         const char *p_save, *p = dn->extended_linearized;
 103                         do {
 104                                 p_save = p;
 105                                 p = strstr(p, ">;");
 106                                 if (p) {
 107                                         p = p + 2;
 108                                 }
 109                         } while (p);
 110                         
 111                         if (p_save == dn->extended_linearized) {
 112                                 dn->linearized = talloc_strdup(dn, "");
 113                         } else {
 114                                 dn->linearized = talloc_strdup(dn, p_save);
 115                         }
 116                         LDB_DN_NULL_FAILED(dn->linearized);
 117                 } else {
 118                         dn->linearized = dn->extended_linearized;
 119                         dn->extended_linearized = NULL;
 120                 }
 121         } else {
 122                 dn->linearized = talloc_strdup(dn, "");
 123                 LDB_DN_NULL_FAILED(dn->linearized);
 124         }
 125 
 126         return dn;
 127 
 128 failed:
 129         talloc_free(dn);
 130         return NULL;
 131 }
 132 
 133 /* strdn may be NULL */
 134 struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
     /* [<][>][^][v][top][bottom][index][help] */
 135 {
 136         struct ldb_val blob;
 137         blob.data = strdn;
 138         blob.length = strdn ? strlen(strdn) : 0;
 139         return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
 140 }
 141 
 142 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 143 {
 144         char *strdn;
 145         va_list ap;
 146 
 147         if ( (! mem_ctx) || (! ldb)) return NULL;
 148 
 149         va_start(ap, new_fmt);
 150         strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
 151         va_end(ap);
 152 
 153         if (strdn) {
 154                 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
 155                 talloc_free(strdn);
 156                 return dn;
 157         }
 158         
 159         return NULL;
 160 }
 161 
 162 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
     /* [<][>][^][v][top][bottom][index][help] */
 163 {
 164         const char *p, *s;
 165         char *d;
 166         int l;
 167 
 168         p = s = src;
 169         d = dst;
 170 
 171         while (p - src < len) {
 172 
 173                 p += strcspn(p, ",=\n+<>#;\\\"");
 174 
 175                 if (p - src == len) /* found no escapable chars */
 176                         break;
 177 
 178                 memcpy(d, s, p - s); /* copy the part of the string before the stop */
 179                 d += (p - s); /* move to current position */
 180 
 181                 if (*p) { /* it is a normal escapable character */
 182                         *d++ = '\\';
 183                         *d++ = *p++;
 184                 } else { /* we have a zero byte in the string */
 185                         strncpy(d, "\00", 3); /* escape the zero */
 186                         d += 3;
 187                         p++; /* skip the zero */
 188                 }
 189                 s = p; /* move forward */
 190         }
 191 
 192         /* copy the last part (with zero) and return */
 193         l = len - (s - src);
 194         memcpy(d, s, l + 1);
 195 
 196         /* return the length of the resulting string */
 197         return (l + (d - dst));
 198 } 
 199 
 200 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
     /* [<][>][^][v][top][bottom][index][help] */
 201 {
 202         char *dst;
 203 
 204         if (!value.length)
 205                 return NULL;
 206 
 207         /* allocate destination string, it will be at most 3 times the source */
 208         dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
 209         if ( ! dst) {
 210                 talloc_free(dst);
 211                 return NULL;
 212         }
 213 
 214         ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
 215 
 216         dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
 217 
 218         return dst;
 219 }
 220 
 221 /*
 222   explode a DN string into a ldb_dn structure
 223   based on RFC4514 except that we don't support multiple valued RDNs
 224 */
 225 static bool ldb_dn_explode(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 226 {
 227         char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
 228         bool trim = false;
 229         bool in_extended = false;
 230         bool in_ex_name = false;
 231         bool in_ex_value = false;
 232         bool in_attr = false;
 233         bool in_value = false;
 234         bool in_quote = false;
 235         bool is_oid = false;
 236         bool escape = false;
 237         unsigned x;
 238         int l, ret;
 239         char *parse_dn;
 240 
 241         if ( ! dn || dn->invalid) return false;
 242 
 243         if (dn->components) {
 244                 return true;
 245         }
 246 
 247         if (dn->extended_linearized) {
 248                 parse_dn = dn->extended_linearized;
 249         } else {
 250                 parse_dn = dn->linearized;
 251         }
 252 
 253         if ( ! parse_dn ) {
 254                 return false;
 255         }
 256 
 257         /* Empty DNs */
 258         if (parse_dn[0] == '\0') {
 259                 return true;
 260         }
 261 
 262         /* Special DNs case */
 263         if (dn->special) {
 264                 return true;
 265         }
 266 
 267         /* make sure we free this if alloced previously before replacing */
 268         talloc_free(dn->components);
 269 
 270         talloc_free(dn->extended_components);
 271         dn->extended_components = NULL;
 272 
 273         /* in the common case we have 3 or more components */
 274         /* make sure all components are zeroed, other functions depend on this */
 275         dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
 276         if ( ! dn->components) {
 277                 return false;
 278         }
 279         dn->comp_num = 0;
 280 
 281         /* Components data space is allocated here once */
 282         data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
 283         if (!data) {
 284                 return false;
 285         }
 286 
 287         p = parse_dn;
 288         in_extended = true;
 289         in_ex_name = false;
 290         in_ex_value = false;
 291         trim = true;
 292         t = NULL;
 293         d = dt = data;
 294 
 295         while (*p) {
 296                 if (in_extended) {
 297 
 298                         if (!in_ex_name && !in_ex_value) {
 299 
 300                                 if (p[0] == '<') {
 301                                         p++;
 302                                         ex_name = d;
 303                                         in_ex_name = true;
 304                                         continue;
 305                                 } else if (p[0] == '\0') {
 306                                         p++;
 307                                         continue;
 308                                 } else {
 309                                         in_extended = false;
 310                                         in_attr = true;
 311                                         dt = d;
 312 
 313                                         continue;
 314                                 }
 315                         }
 316                         
 317                         if (in_ex_name && *p == '=') {
 318                                 *d++ = '\0';
 319                                 p++;
 320                                 ex_value = d;
 321                                 in_ex_name = false;
 322                                 in_ex_value = true;
 323                                 continue;
 324                         }
 325 
 326                         if (in_ex_value && *p == '>') {
 327                                 const struct ldb_dn_extended_syntax *extended_syntax;
 328                                 struct ldb_val ex_val = {
 329                                         .data = ex_value,
 330                                         .length = d - ex_value
 331                                 };
 332                                         
 333                                 *d++ = '\0';
 334                                 p++;
 335                                 in_ex_value = false;
 336 
 337                                 /* Process name and ex_value */
 338 
 339                                 dn->extended_components = talloc_realloc(dn,
 340                                                                          dn->extended_components,
 341                                                                          struct ldb_dn_extended_component,
 342                                                                          dn->extended_comp_num + 1);
 343                                 if ( ! dn->extended_components) {
 344                                         /* ouch ! */
 345                                         goto failed;
 346                                 }
 347 
 348                                 extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
 349                                 if (!extended_syntax) {
 350                                         /* We don't know about this type of extended DN */
 351                                         goto failed;
 352                                 }
 353 
 354                                 dn->extended_components[dn->extended_comp_num].name = talloc_strdup(dn->extended_components, ex_name);
 355                                 if (!dn->extended_components[dn->extended_comp_num].name) {
 356                                         /* ouch */
 357                                         goto failed;
 358                                 }
 359                                 ret = extended_syntax->read_fn(dn->ldb, dn->extended_components,
 360                                                                &ex_val, &dn->extended_components[dn->extended_comp_num].value);
 361                                 if (ret != LDB_SUCCESS) {
 362                                         dn->invalid = true;
 363                                         goto failed;
 364                                 }
 365 
 366                                 dn->extended_comp_num++;
 367 
 368                                 if (*p == '\0') {
 369                                         /* We have reached the end (extended component only)! */
 370                                         talloc_free(data);
 371                                         return true;
 372 
 373                                 } else if (*p == ';') {
 374                                         p++;
 375                                         continue;
 376                                 } else {
 377                                         dn->invalid = true;
 378                                         goto failed;
 379                                 }
 380                         }
 381 
 382                         *d++ = *p++;
 383                         continue;
 384                 }
 385                 if (in_attr) {
 386                         if (trim) {
 387                                 if (*p == ' ') {
 388                                         p++;
 389                                         continue;
 390                                 }
 391 
 392                                 /* first char */
 393                                 trim = false;
 394 
 395                                 if (!isascii(*p)) {
 396                                         /* attr names must be ascii only */
 397                                         dn->invalid = true;
 398                                         goto failed;
 399                                 }
 400 
 401                                 if (isdigit(*p)) {
 402                                         is_oid = true;
 403                                 } else
 404                                 if ( ! isalpha(*p)) {
 405                                         /* not a digit nor an alpha, invalid attribute name */
 406                                         dn->invalid = true;
 407                                         goto failed;
 408                                 }
 409                                 
 410                                 /* Copy this character across from parse_dn, now we have trimmed out spaces */
 411                                 *d++ = *p++;
 412                                 continue;
 413                         }
 414 
 415                         if (*p == ' ') {
 416                                 p++;
 417                                 /* valid only if we are at the end */
 418                                 trim = true;
 419                                 continue;
 420                         }
 421 
 422                         if (trim && (*p != '=')) {
 423                                 /* spaces/tabs are not allowed in attribute names */
 424                                 dn->invalid = true;
 425                                 goto failed;
 426                         }
 427 
 428                         if (*p == '=') {
 429                                 /* attribute terminated */
 430                                 in_attr = false;
 431                                 in_value = true;
 432                                 trim = true;
 433                                 l = 0;
 434 
 435                                 /* Terminate this string in d (which is a copy of parse_dn with spaces trimmed) */
 436                                 *d++ = '\0';
 437                                 dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
 438                                 if ( ! dn->components[dn->comp_num].name) {
 439                                         /* ouch */
 440                                         goto failed;
 441                                 }
 442 
 443                                 dt = d;
 444 
 445                                 p++;
 446                                 continue;
 447                         }
 448 
 449                         if (!isascii(*p)) {
 450                                 /* attr names must be ascii only */
 451                                 dn->invalid = true;
 452                                 goto failed;
 453                         }
 454 
 455                         if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
 456                                 /* not a digit nor a dot, invalid attribute oid */
 457                                 dn->invalid = true;
 458                                 goto failed;
 459                         } else
 460                         if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
 461                                 /* not ALPHA, DIGIT or HYPHEN */
 462                                 dn->invalid = true;
 463                                 goto failed;
 464                         }
 465 
 466                         *d++ = *p++;
 467                         continue;
 468                 }
 469 
 470                 if (in_value) {
 471                         if (in_quote) {
 472                                 if (*p == '\"') {
 473                                         if (p[-1] != '\\') {
 474                                                 p++;
 475                                                 in_quote = false;
 476                                                 continue;
 477                                         }
 478                                 }
 479                                 *d++ = *p++;
 480                                 l++;
 481                                 continue;
 482                         }
 483 
 484                         if (trim) {
 485                                 if (*p == ' ') {
 486                                         p++;
 487                                         continue;
 488                                 }
 489 
 490                                 /* first char */
 491                                 trim = false;
 492 
 493                                 if (*p == '\"') {
 494                                         in_quote = true;
 495                                         p++;
 496                                         continue;
 497                                 }
 498                         }
 499 
 500                         switch (*p) {
 501 
 502                         /* TODO: support ber encoded values
 503                         case '#':
 504                         */
 505 
 506                         case ',':
 507                                 if (escape) {
 508                                         *d++ = *p++;
 509                                         l++;
 510                                         escape = false;
 511                                         continue;
 512                                 }
 513                                 /* ok found value terminator */
 514 
 515                                 if ( t ) {
 516                                         /* trim back */
 517                                         d -= (p - t);
 518                                         l -= (p - t);
 519                                 }
 520 
 521                                 in_attr = true;
 522                                 in_value = false;
 523                                 trim = true;
 524 
 525                                 p++;
 526                                 *d++ = '\0';
 527                                 dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
 528                                 dn->components[dn->comp_num].value.length = l;
 529                                 if ( ! dn->components[dn->comp_num].value.data) {
 530                                         /* ouch ! */
 531                                         goto failed;
 532                                 }
 533 
 534                                 dt = d;
 535 
 536                                 dn->comp_num++;
 537                                 if (dn->comp_num > 2) {
 538                                         dn->components = talloc_realloc(dn,
 539                                                                         dn->components,
 540                                                                         struct ldb_dn_component,
 541                                                                         dn->comp_num + 1);
 542                                         if ( ! dn->components) {
 543                                                 /* ouch ! */
 544                                                 goto failed;
 545                                         }
 546                                         /* make sure all components are zeroed, other functions depend on this */
 547                                         memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
 548                                 }
 549 
 550                                 continue;
 551 
 552                         case '=':
 553                         case '\n':
 554                         case '+':
 555                         case '<':
 556                         case '>':
 557                         case '#':
 558                         case ';':
 559                         case '\"':
 560                                 /* a string with not escaped specials is invalid (tested) */
 561                                 if ( ! escape) {
 562                                         dn->invalid = true;
 563                                         goto failed;
 564                                 }
 565                                 escape = false;
 566 
 567                                 *d++ = *p++;
 568                                 l++;
 569 
 570                                 if ( t ) t = NULL;
 571                                 break;
 572 
 573                         case '\\':
 574                                 if ( ! escape) {
 575                                         escape = true;
 576                                         p++;
 577                                         continue;
 578                                 }
 579                                 escape = false;
 580 
 581                                 *d++ = *p++;
 582                                 l++;
 583 
 584                                 if ( t ) t = NULL;
 585                                 break;
 586 
 587                         default:
 588                                 if (escape) {
 589                                         if (sscanf(p, "%02x", &x) != 1) {
 590                                                 /* invalid escaping sequence */
 591                                                 dn->invalid = true;
 592                                                 goto failed;
 593                                         }
 594                                         escape = false;
 595 
 596                                         p += 2;
 597                                         *d++ = (unsigned char)x;
 598                                         l++;
 599 
 600                                         if ( t ) t = NULL;
 601                                         break;
 602                                 }
 603 
 604                                 if (*p == ' ') { 
 605                                         if ( ! t) t = p;
 606                                 } else {
 607                                         if ( t ) t = NULL;
 608                                 }
 609 
 610                                 *d++ = *p++;
 611                                 l++;
 612                                 
 613                                 break;
 614                         }
 615 
 616                 }
 617         }
 618 
 619         if (in_attr || in_quote) {
 620                 /* invalid dn */
 621                 dn->invalid = true;
 622                 goto failed;
 623         }
 624 
 625         /* save last element */
 626         if ( t ) {
 627                 /* trim back */
 628                 d -= (p - t);
 629                 l -= (p - t);
 630         }
 631 
 632         *d++ = '\0';
 633         dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
 634         dn->components[dn->comp_num].value.length = l;
 635 
 636         if ( ! dn->components[dn->comp_num].value.data) {
 637                 /* ouch */
 638                 goto failed;
 639         }
 640 
 641         dn->comp_num++;
 642 
 643         talloc_free(data);
 644         return true;
 645 
 646 failed:
 647         dn->comp_num = 0;
 648         talloc_free(dn->components);
 649         return false;
 650 }
 651 
 652 bool ldb_dn_validate(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 653 {
 654         return ldb_dn_explode(dn);
 655 }
 656 
 657 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 658 {
 659         int i, len;
 660         char *d, *n;
 661 
 662         if ( ! dn || ( dn->invalid)) return NULL;
 663 
 664         if (dn->linearized) return dn->linearized;
 665 
 666         if ( ! dn->components) {
 667                 dn->invalid = true;
 668                 return NULL;
 669         }
 670 
 671         if (dn->comp_num == 0) {
 672                 dn->linearized = talloc_strdup(dn, "");
 673                 if ( ! dn->linearized) return NULL;
 674                 return dn->linearized;
 675         }
 676 
 677         /* calculate maximum possible length of DN */
 678         for (len = 0, i = 0; i < dn->comp_num; i++) {
 679                 len += strlen(dn->components[i].name); /* name len */
 680                 len += (dn->components[i].value.length * 3); /* max escaped data len */
 681                 len += 2; /* '=' and ',' */
 682         }
 683         dn->linearized = talloc_array(dn, char, len);
 684         if ( ! dn->linearized) return NULL;
 685 
 686         d = dn->linearized;
 687 
 688         for (i = 0; i < dn->comp_num; i++) {
 689 
 690                 /* copy the name */
 691                 n = dn->components[i].name;
 692                 while (*n) *d++ = *n++;
 693 
 694                 *d++ = '=';
 695 
 696                 /* and the value */
 697                 d += ldb_dn_escape_internal( d,
 698                                 (char *)dn->components[i].value.data,
 699                                 dn->components[i].value.length);
 700                 *d++ = ',';
 701         }
 702 
 703         *(--d) = '\0';
 704 
 705         /* don't waste more memory than necessary */
 706         dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));
 707 
 708         return dn->linearized;
 709 }
 710 
 711 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
     /* [<][>][^][v][top][bottom][index][help] */
 712 {
 713         const char *linearized = ldb_dn_get_linearized(dn);
 714         char *p;
 715         int i;
 716 
 717         if (!linearized) {
 718                 return NULL;
 719         }
 720 
 721         if (!ldb_dn_has_extended(dn)) {
 722                 return talloc_strdup(mem_ctx, linearized);
 723         }
 724         
 725         if (!ldb_dn_validate(dn)) {
 726                 return NULL;
 727         }
 728 
 729         for (i=0; i < dn->extended_comp_num; i++) {
 730                 struct ldb_val val;
 731                 int ret;
 732                 const struct ldb_dn_extended_syntax *extended_syntax;
 733                 const char *name = dn->extended_components[i].name;
 734                 
 735                 extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
 736 
 737                 if (mode == 1) {
 738                         ret = extended_syntax->write_clear_fn(dn->ldb, mem_ctx,
 739                                                               &dn->extended_components[i].value,
 740                                                               &val);
 741                 } else if (mode == 0) {
 742                         ret = extended_syntax->write_hex_fn(dn->ldb, mem_ctx,
 743                                                               &dn->extended_components[i].value,
 744                                                               &val);
 745                 } else {
 746                         ret = -1;
 747                 }
 748 
 749                 if (ret != LDB_SUCCESS) {
 750                         return NULL;
 751                 }
 752 
 753                 if (i == 0) {
 754                         p = talloc_asprintf(mem_ctx, "<%s=%s>", dn->extended_components[i].name, val.data);
 755                 } else {
 756                         p = talloc_asprintf_append(p, ";<%s=%s>",  dn->extended_components[i].name, val.data);
 757                 }
 758 
 759                 talloc_free(val.data);
 760 
 761                 if (!p) {
 762                         return NULL;
 763                 }
 764         }
 765 
 766         if (dn->extended_comp_num && *linearized) {
 767                 p = talloc_asprintf_append(p, ";%s", linearized);
 768         }
 769 
 770         if (!p) {
 771                 return NULL;
 772         }
 773 
 774         return p;
 775 }
 776 
 777 
 778 
 779 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 780 {
 781         return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
 782 }
 783 
 784 /*
 785   casefold a dn. We need to casefold the attribute names, and canonicalize 
 786   attribute values of case insensitive attributes.
 787 */
 788 
 789 static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 790 {
 791         int i, ret;
 792 
 793         if ( ! dn || dn->invalid) return false;
 794 
 795         if (dn->valid_case) return true;
 796 
 797         if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
 798                 return false;
 799         }
 800 
 801         for (i = 0; i < dn->comp_num; i++) {
 802                 const struct ldb_schema_attribute *a;
 803 
 804                 dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
 805                 if (!dn->components[i].cf_name) {
 806                         goto failed;
 807                 }
 808 
 809                 a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);
 810                 ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
 811                                                  &(dn->components[i].value),
 812                                                  &(dn->components[i].cf_value));
 813                 if (ret != 0) {
 814                         goto failed;
 815                 }
 816         }
 817 
 818         dn->valid_case = true;
 819 
 820         return true;
 821 
 822 failed:
 823         for (i = 0; i < dn->comp_num; i++) {
 824                 LDB_FREE(dn->components[i].cf_name);
 825                 LDB_FREE(dn->components[i].cf_value.data);
 826         }
 827         return false;
 828 }
 829 
 830 const char *ldb_dn_get_casefold(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 831 {
 832         int i, len;
 833         char *d, *n;
 834 
 835         if (dn->casefold) return dn->casefold;
 836 
 837         if (dn->special) { 
 838                 dn->casefold = talloc_strdup(dn, dn->linearized);
 839                 if (!dn->casefold) return NULL;
 840                 dn->valid_case = true;
 841                 return dn->casefold;
 842         }
 843 
 844         if ( ! ldb_dn_casefold_internal(dn)) {
 845                 return NULL;
 846         }
 847 
 848         if (dn->comp_num == 0) {
 849                 if (dn->linearized && dn->linearized[0] == '\0') {
 850                         /* hmm a NULL dn, should we faild casefolding ? */
 851                         dn->casefold = talloc_strdup(dn, "");
 852                         return dn->casefold;
 853                 }
 854                 /* A DN must be NULL, special, or have components */
 855                 dn->invalid = true;
 856                 return NULL;
 857         }
 858 
 859         /* calculate maximum possible length of DN */
 860         for (len = 0, i = 0; i < dn->comp_num; i++) {
 861                 len += strlen(dn->components[i].cf_name); /* name len */
 862                 len += (dn->components[i].cf_value.length * 3); /* max escaped data len */
 863                 len += 2; /* '=' and ',' */
 864         }
 865         dn->casefold = talloc_array(dn, char, len);
 866         if ( ! dn->casefold) return NULL;
 867 
 868         d = dn->casefold;
 869 
 870         for (i = 0; i < dn->comp_num; i++) {
 871 
 872                 /* copy the name */
 873                 n = dn->components[i].cf_name;
 874                 while (*n) *d++ = *n++;
 875 
 876                 *d++ = '=';
 877 
 878                 /* and the value */
 879                 d += ldb_dn_escape_internal( d,
 880                                 (char *)dn->components[i].cf_value.data,
 881                                 dn->components[i].cf_value.length);
 882                 *d++ = ',';
 883         }
 884         *(--d) = '\0';
 885 
 886         /* don't waste more memory than necessary */
 887         dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);
 888 
 889         return dn->casefold;
 890 }
 891 
 892 char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 893 {
 894         return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
 895 }
 896 
 897 /* Determine if dn is below base, in the ldap tree.  Used for
 898  * evaluating a subtree search.
 899  * 0 if they match, otherwise non-zero
 900  */
 901 
 902 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 903 {
 904         int ret;
 905         int n_base, n_dn;
 906 
 907         if ( ! base || base->invalid) return 1;
 908         if ( ! dn || dn->invalid) return -1;
 909 
 910         if (( ! base->valid_case) || ( ! dn->valid_case)) {
 911                 if (base->linearized && dn->linearized) {
 912                         /* try with a normal compare first, if we are lucky
 913                          * we will avoid exploding and casfolding */
 914                         int dif;
 915                         dif = strlen(dn->linearized) - strlen(base->linearized);
 916                         if (dif < 0) return dif;
 917                         if (strcmp(base->linearized, &dn->linearized[dif]) == 0) return 0;
 918                 }
 919 
 920                 if ( ! ldb_dn_casefold_internal(base)) {
 921                         return 1;
 922                 }
 923 
 924                 if ( ! ldb_dn_casefold_internal(dn)) {
 925                         return -1;
 926                 }
 927 
 928         }
 929 
 930         /* if base has more components,
 931          * they don't have the same base */
 932         if (base->comp_num > dn->comp_num) {
 933                 return (dn->comp_num - base->comp_num);
 934         }
 935 
 936         if (dn->comp_num == 0) {
 937                 if (dn->special && base->special) {
 938                         return strcmp(base->linearized, dn->linearized);
 939                 } else if (dn->special) {
 940                         return -1;
 941                 } else if (base->special) {
 942                         return 1;
 943                 } else {
 944                         return 0;
 945                 }
 946         }
 947 
 948         n_base = base->comp_num - 1;
 949         n_dn = dn->comp_num - 1;
 950 
 951         while (n_base >= 0) {
 952                 /* compare attr names */
 953                 ret = strcmp(base->components[n_base].cf_name, dn->components[n_dn].cf_name);
 954                 if (ret != 0) return ret;
 955 
 956                 /* compare attr.cf_value. */ 
 957                 if (base->components[n_base].cf_value.length != dn->components[n_dn].cf_value.length) {
 958                         return base->components[n_base].cf_value.length - dn->components[n_dn].cf_value.length;
 959                 }
 960                 ret = strcmp((char *)base->components[n_base].cf_value.data, (char *)dn->components[n_dn].cf_value.data);
 961                 if (ret != 0) return ret;
 962 
 963                 n_base--;
 964                 n_dn--;
 965         }
 966 
 967         return 0;
 968 }
 969 
 970 /* compare DNs using casefolding compare functions.  
 971 
 972    If they match, then return 0
 973  */
 974 
 975 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
     /* [<][>][^][v][top][bottom][index][help] */
 976 {
 977         int i, ret;
 978 
 979         if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) return -1;
 980 
 981         if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
 982                 if (dn0->linearized && dn1->linearized) {
 983                         /* try with a normal compare first, if we are lucky
 984                          * we will avoid exploding and casfolding */
 985                         if (strcmp(dn0->linearized, dn1->linearized) == 0) return 0;
 986                 }
 987 
 988                 if ( ! ldb_dn_casefold_internal(dn0)) {
 989                         return 1;
 990                 }
 991 
 992                 if ( ! ldb_dn_casefold_internal(dn1)) {
 993                         return -1;
 994                 }
 995 
 996         }
 997 
 998         if (dn0->comp_num != dn1->comp_num) {
 999                 return (dn1->comp_num - dn0->comp_num);
1000         }
1001 
1002         if (dn0->comp_num == 0) {
1003                 if (dn0->special && dn1->special) {
1004                         return strcmp(dn0->linearized, dn1->linearized);
1005                 } else if (dn0->special) {
1006                         return 1;
1007                 } else if (dn1->special) {
1008                         return -1;
1009                 } else {
1010                         return 0;
1011                 }
1012         }
1013 
1014         for (i = 0; i < dn0->comp_num; i++) {
1015                 /* compare attr names */
1016                 ret = strcmp(dn0->components[i].cf_name, dn1->components[i].cf_name);
1017                 if (ret != 0) return ret;
1018 
1019                 /* compare attr.cf_value. */ 
1020                 if (dn0->components[i].cf_value.length != dn1->components[i].cf_value.length) {
1021                         return dn0->components[i].cf_value.length - dn1->components[i].cf_value.length;
1022                 }
1023                 ret = strcmp((char *)dn0->components[i].cf_value.data, (char *)dn1->components[i].cf_value.data);
1024                 if (ret != 0) return ret;
1025         }
1026 
1027         return 0;
1028 }
1029 
1030 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
     /* [<][>][^][v][top][bottom][index][help] */
1031 {
1032         struct ldb_dn_component dst;
1033 
1034         memset(&dst, 0, sizeof(dst));
1035 
1036         if (src == NULL) {
1037                 return dst;
1038         }
1039 
1040         dst.value = ldb_val_dup(mem_ctx, &(src->value));
1041         if (dst.value.data == NULL) {
1042                 return dst;
1043         }
1044 
1045         dst.name = talloc_strdup(mem_ctx, src->name);
1046         if (dst.name == NULL) {
1047                 LDB_FREE(dst.value.data);
1048                 return dst;
1049         }
1050 
1051         if (src->cf_value.data) {
1052                 dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
1053                 if (dst.cf_value.data == NULL) {
1054                         LDB_FREE(dst.value.data);
1055                         LDB_FREE(dst.name);
1056                         return dst;
1057                 }
1058 
1059                 dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
1060                 if (dst.cf_name == NULL) {
1061                         LDB_FREE(dst.cf_name);
1062                         LDB_FREE(dst.value.data);
1063                         LDB_FREE(dst.name);
1064                         return dst;
1065                 }
1066         } else {
1067                 dst.cf_value.data = NULL;
1068                 dst.cf_name = NULL;
1069         }
1070 
1071         return dst;
1072 }
1073 
1074 static struct ldb_dn_extended_component ldb_dn_extended_copy_component(void *mem_ctx, struct ldb_dn_extended_component *src)
     /* [<][>][^][v][top][bottom][index][help] */
1075 {
1076         struct ldb_dn_extended_component dst;
1077 
1078         memset(&dst, 0, sizeof(dst));
1079 
1080         if (src == NULL) {
1081                 return dst;
1082         }
1083 
1084         dst.value = ldb_val_dup(mem_ctx, &(src->value));
1085         if (dst.value.data == NULL) {
1086                 return dst;
1087         }
1088 
1089         dst.name = talloc_strdup(mem_ctx, src->name);
1090         if (dst.name == NULL) {
1091                 LDB_FREE(dst.value.data);
1092                 return dst;
1093         }
1094 
1095         return dst;
1096 }
1097 
1098 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1099 {
1100         struct ldb_dn *new_dn;
1101 
1102         if (!dn || dn->invalid) {
1103                 return NULL;
1104         }
1105 
1106         new_dn = talloc_zero(mem_ctx, struct ldb_dn);
1107         if ( !new_dn) {
1108                 return NULL;
1109         }
1110 
1111         *new_dn = *dn;
1112 
1113         if (dn->components) {
1114                 int i;
1115 
1116                 new_dn->components = talloc_zero_array(new_dn, struct ldb_dn_component, dn->comp_num);
1117                 if ( ! new_dn->components) {
1118                         talloc_free(new_dn);
1119                         return NULL;
1120                 }
1121 
1122                 for (i = 0; i < dn->comp_num; i++) {
1123                         new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &dn->components[i]);
1124                         if ( ! new_dn->components[i].value.data) {
1125                                 talloc_free(new_dn);
1126                                 return NULL;
1127                         }
1128                 }
1129         }
1130 
1131         if (dn->extended_components) {
1132                 int i;
1133 
1134                 new_dn->extended_components = talloc_zero_array(new_dn, struct ldb_dn_extended_component, dn->extended_comp_num);
1135                 if ( ! new_dn->extended_components) {
1136                         talloc_free(new_dn);
1137                         return NULL;
1138                 }
1139 
1140                 for (i = 0; i < dn->extended_comp_num; i++) {
1141                         new_dn->extended_components[i] = ldb_dn_extended_copy_component(new_dn->extended_components, &dn->extended_components[i]);
1142                         if ( ! new_dn->extended_components[i].value.data) {
1143                                 talloc_free(new_dn);
1144                                 return NULL;
1145                         }
1146                 }
1147         }
1148 
1149         if (dn->casefold) {
1150                 new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
1151                 if ( ! new_dn->casefold) {
1152                         talloc_free(new_dn);
1153                         return NULL;
1154                 }
1155         }
1156 
1157         if (dn->linearized) {
1158                 new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
1159                 if ( ! new_dn->linearized) {
1160                         talloc_free(new_dn);
1161                         return NULL;
1162                 }
1163         }
1164 
1165         if (dn->extended_linearized) {
1166                 new_dn->extended_linearized = talloc_strdup(new_dn, dn->extended_linearized);
1167                 if ( ! new_dn->extended_linearized) {
1168                         talloc_free(new_dn);
1169                         return NULL;
1170                 }
1171         }
1172 
1173         return new_dn;
1174 }
1175 
1176 /* modify the given dn by adding a base.
1177  *
1178  * return true if successful and false if not
1179  * if false is returned the dn may be marked invalid
1180  */
1181 bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
     /* [<][>][^][v][top][bottom][index][help] */
1182 {
1183         const char *s;
1184         char *t;
1185 
1186         if ( !base || base->invalid || !dn || dn->invalid) {
1187                 return false;
1188         }
1189 
1190         if (dn->components) {
1191                 int i;
1192 
1193                 if ( ! ldb_dn_validate(base)) {
1194                         return false;
1195                 }
1196 
1197                 s = NULL;
1198                 if (dn->valid_case) {
1199                         if ( ! (s = ldb_dn_get_casefold(base))) {
1200                                 return false;
1201                         }
1202                 }
1203 
1204                 dn->components = talloc_realloc(dn,
1205                                                 dn->components,
1206                                                 struct ldb_dn_component,
1207                                                 dn->comp_num + base->comp_num);
1208                 if ( ! dn->components) {
1209                         dn->invalid = true;
1210                         return false;
1211                 }
1212 
1213                 for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
1214                         dn->components[dn->comp_num] = ldb_dn_copy_component(dn->components, &base->components[i]);
1215                         if (dn->components[dn->comp_num].value.data == NULL) {
1216                                 dn->invalid = true;
1217                                 return false;
1218                         }
1219                 }
1220 
1221                 if (dn->casefold && s) {
1222                         if (*dn->casefold) {
1223                                 t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
1224                         } else {
1225                                 t = talloc_strdup(dn, s);
1226                         }
1227                         LDB_FREE(dn->casefold);
1228                         dn->casefold = t;
1229                 }
1230         }
1231 
1232         if (dn->linearized) {
1233 
1234                 s = ldb_dn_get_linearized(base);
1235                 if ( ! s) {
1236                         return false;
1237                 }
1238                 
1239                 if (*dn->linearized) {
1240                         t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
1241                 } else {
1242                         t = talloc_strdup(dn, s);
1243                 }
1244                 if ( ! t) {
1245                         dn->invalid = true;
1246                         return false;
1247                 }
1248                 LDB_FREE(dn->linearized);
1249                 dn->linearized = t;
1250         }
1251 
1252         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1253         if (dn->extended_linearized) {
1254                 LDB_FREE(dn->extended_linearized);
1255         }
1256 
1257         LDB_FREE(dn->extended_components);
1258         dn->extended_comp_num = 0;
1259         return true;
1260 }
1261 
1262 /* modify the given dn by adding a base.
1263  *
1264  * return true if successful and false if not
1265  * if false is returned the dn may be marked invalid
1266  */
1267 bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
1268 {
1269         struct ldb_dn *base;
1270         char *base_str;
1271         va_list ap;
1272         bool ret;
1273 
1274         if ( !dn || dn->invalid) {
1275                 return false;
1276         }
1277 
1278         va_start(ap, base_fmt);
1279         base_str = talloc_vasprintf(dn, base_fmt, ap);
1280         va_end(ap);
1281 
1282         if (base_str == NULL) {
1283                 return false;
1284         }
1285 
1286         base = ldb_dn_new(base_str, dn->ldb, base_str);
1287 
1288         ret = ldb_dn_add_base(dn, base);
1289 
1290         talloc_free(base_str);
1291 
1292         return ret;
1293 }       
1294 
1295 /* modify the given dn by adding children elements.
1296  *
1297  * return true if successful and false if not
1298  * if false is returned the dn may be marked invalid
1299  */
1300 bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
     /* [<][>][^][v][top][bottom][index][help] */
1301 {
1302         const char *s;
1303         char *t;
1304 
1305         if ( !child || child->invalid || !dn || dn->invalid) {
1306                 return false;
1307         }
1308 
1309         if (dn->components) {
1310                 int n, i, j;
1311 
1312                 if ( ! ldb_dn_validate(child)) {
1313                         return false;
1314                 }
1315 
1316                 s = NULL;
1317                 if (dn->valid_case) {
1318                         if ( ! (s = ldb_dn_get_casefold(child))) {
1319                                 return false;
1320                         }
1321                 }
1322 
1323                 n = dn->comp_num + child->comp_num;
1324 
1325                 dn->components = talloc_realloc(dn,
1326                                                 dn->components,
1327                                                 struct ldb_dn_component,
1328                                                 n);
1329                 if ( ! dn->components) {
1330                         dn->invalid = true;
1331                         return false;
1332                 }
1333 
1334                 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
1335                         dn->components[j] = dn->components[i];
1336                 }
1337 
1338                 for (i = 0; i < child->comp_num; i++) { 
1339                         dn->components[i] = ldb_dn_copy_component(dn->components, &child->components[i]);
1340                         if (dn->components[i].value.data == NULL) {
1341                                 dn->invalid = true;
1342                                 return false;
1343                         }
1344                 }
1345 
1346                 dn->comp_num = n;
1347 
1348                 if (dn->casefold && s) {
1349                         t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
1350                         LDB_FREE(dn->casefold);
1351                         dn->casefold = t;
1352                 }
1353         }
1354 
1355         if (dn->linearized) {
1356 
1357                 s = ldb_dn_get_linearized(child);
1358                 if ( ! s) {
1359                         return false;
1360                 }
1361                 
1362                 t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
1363                 if ( ! t) {
1364                         dn->invalid = true;
1365                         return false;
1366                 }
1367                 LDB_FREE(dn->linearized);
1368                 dn->linearized = t;
1369         }
1370 
1371         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1372         LDB_FREE(dn->extended_linearized);
1373 
1374         LDB_FREE(dn->extended_components);
1375         dn->extended_comp_num = 0;
1376 
1377         return true;
1378 }
1379 
1380 /* modify the given dn by adding children elements.
1381  *
1382  * return true if successful and false if not
1383  * if false is returned the dn may be marked invalid
1384  */
1385 bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
1386 {
1387         struct ldb_dn *child;
1388         char *child_str;
1389         va_list ap;
1390         bool ret;
1391 
1392         if ( !dn || dn->invalid) {
1393                 return false;
1394         }
1395 
1396         va_start(ap, child_fmt);
1397         child_str = talloc_vasprintf(dn, child_fmt, ap);
1398         va_end(ap);
1399 
1400         if (child_str == NULL) {
1401                 return false;
1402         }
1403 
1404         child = ldb_dn_new(child_str, dn->ldb, child_str);
1405 
1406         ret = ldb_dn_add_child(dn, child);
1407 
1408         talloc_free(child_str);
1409 
1410         return ret;
1411 }
1412 
1413 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
1414 {
1415         int i;
1416 
1417         if ( ! ldb_dn_validate(dn)) {
1418                 return false;
1419         }
1420 
1421         if (dn->comp_num < num) {
1422                 return false;
1423         }
1424 
1425         /* free components */
1426         for (i = num; i > 0; i--) {
1427                 LDB_FREE(dn->components[dn->comp_num - i].name);
1428                 LDB_FREE(dn->components[dn->comp_num - i].value.data);
1429                 LDB_FREE(dn->components[dn->comp_num - i].cf_name);
1430                 LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
1431         }
1432         
1433         dn->comp_num -= num;
1434 
1435         if (dn->valid_case) {
1436                 for (i = 0; i < dn->comp_num; i++) {
1437                         LDB_FREE(dn->components[i].cf_name);
1438                         LDB_FREE(dn->components[i].cf_value.data);
1439                 }
1440                 dn->valid_case = false;
1441         }
1442 
1443         LDB_FREE(dn->casefold);
1444         LDB_FREE(dn->linearized);
1445 
1446         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1447         LDB_FREE(dn->extended_linearized);
1448 
1449         LDB_FREE(dn->extended_components);
1450         dn->extended_comp_num = 0;
1451 
1452         return true;
1453 }
1454 
1455 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
1456 {
1457         int i, j;
1458 
1459         if ( ! ldb_dn_validate(dn)) {
1460                 return false;
1461         }
1462 
1463         if (dn->comp_num < num) {
1464                 return false;
1465         }
1466 
1467         for (i = 0, j = num; j < dn->comp_num; i++, j++) {
1468                 if (i < num) {
1469                         LDB_FREE(dn->components[i].name);
1470                         LDB_FREE(dn->components[i].value.data);
1471                         LDB_FREE(dn->components[i].cf_name);
1472                         LDB_FREE(dn->components[i].cf_value.data);
1473                 }
1474                 dn->components[i] = dn->components[j];
1475         }
1476 
1477         dn->comp_num -= num;
1478 
1479         if (dn->valid_case) {
1480                 for (i = 0; i < dn->comp_num; i++) {
1481                         LDB_FREE(dn->components[i].cf_name);
1482                         LDB_FREE(dn->components[i].cf_value.data);
1483                 }
1484                 dn->valid_case = false;
1485         }
1486 
1487         LDB_FREE(dn->casefold);
1488         LDB_FREE(dn->linearized);
1489 
1490         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1491         LDB_FREE(dn->extended_linearized);
1492 
1493         LDB_FREE(dn->extended_components);
1494         dn->extended_comp_num = 0;
1495         return true;
1496 }
1497 
1498 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1499 {
1500         struct ldb_dn *new_dn;
1501 
1502         new_dn = ldb_dn_copy(mem_ctx, dn);
1503         if ( !new_dn ) {
1504                 return NULL;
1505         }
1506 
1507         if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
1508                 talloc_free(new_dn);
1509                 return NULL;
1510         }
1511 
1512         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1513         LDB_FREE(dn->extended_linearized);
1514 
1515         LDB_FREE(dn->extended_components);
1516         dn->extended_comp_num = 0;
1517         return new_dn;
1518 }
1519 
1520 /* Create a 'canonical name' string from a DN:
1521 
1522    ie dc=samba,dc=org -> samba.org/
1523       uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
1524 
1525    There are two formats, the EX format has the last / replaced with a newline (\n).
1526 
1527 */
1528 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
     /* [<][>][^][v][top][bottom][index][help] */
1529         int i;
1530         TALLOC_CTX *tmpctx;
1531         char *cracked = NULL;
1532         const char *format = (ex_format ? "\n" : "/" );
1533  
1534         if ( ! ldb_dn_validate(dn)) {
1535                 return NULL;
1536         }
1537 
1538         tmpctx = talloc_new(mem_ctx);
1539 
1540         /* Walk backwards down the DN, grabbing 'dc' components at first */
1541         for (i = dn->comp_num - 1 ; i >= 0; i--) {
1542                 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
1543                         break;
1544                 }
1545                 if (cracked) {
1546                         cracked = talloc_asprintf(tmpctx, "%s.%s",
1547                                                   ldb_dn_escape_value(tmpctx, dn->components[i].value),
1548                                                   cracked);
1549                 } else {
1550                         cracked = ldb_dn_escape_value(tmpctx, dn->components[i].value);
1551                 }
1552                 if (!cracked) {
1553                         goto done;
1554                 }
1555         }
1556 
1557         /* Only domain components?  Finish here */
1558         if (i < 0) {
1559                 cracked = talloc_strdup_append_buffer(cracked, format);
1560                 talloc_steal(mem_ctx, cracked);
1561                 goto done;
1562         }
1563 
1564         /* Now walk backwards appending remaining components */
1565         for (; i > 0; i--) {
1566                 cracked = talloc_asprintf_append_buffer(cracked, "/%s", 
1567                                                         ldb_dn_escape_value(tmpctx, dn->components[i].value));
1568                 if (!cracked) {
1569                         goto done;
1570                 }
1571         }
1572 
1573         /* Last one, possibly a newline for the 'ex' format */
1574         cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
1575                                                 ldb_dn_escape_value(tmpctx, dn->components[i].value));
1576 
1577         talloc_steal(mem_ctx, cracked);
1578 done:
1579         talloc_free(tmpctx);
1580         return cracked;
1581 }
1582 
1583 /* Wrapper functions for the above, for the two different string formats */
1584 char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
1585         return ldb_dn_canonical(mem_ctx, dn, 0);
1586 
1587 }
1588 
1589 char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
1590         return ldb_dn_canonical(mem_ctx, dn, 1);
1591 }
1592 
1593 int ldb_dn_get_comp_num(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1594 {
1595         if ( ! ldb_dn_validate(dn)) {
1596                 return -1;
1597         }
1598         return dn->comp_num;
1599 }
1600 
1601 const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
1602 {
1603         if ( ! ldb_dn_validate(dn)) {
1604                 return NULL;
1605         }
1606         if (num >= dn->comp_num) return NULL;
1607         return dn->components[num].name;
1608 }
1609 
1610 const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
1611 {
1612         if ( ! ldb_dn_validate(dn)) {
1613                 return NULL;
1614         }
1615         if (num >= dn->comp_num) return NULL;
1616         return &dn->components[num].value;
1617 }
1618 
1619 const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1620 {
1621         if ( ! ldb_dn_validate(dn)) {
1622                 return NULL;
1623         }
1624         if (dn->comp_num == 0) return NULL;
1625         return dn->components[0].name;
1626 }
1627 
1628 const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1629 {
1630         if ( ! ldb_dn_validate(dn)) {
1631                 return NULL;
1632         }
1633         if (dn->comp_num == 0) return NULL;
1634         return &dn->components[0].value;
1635 }
1636 
1637 int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
     /* [<][>][^][v][top][bottom][index][help] */
1638 {
1639         char *n;
1640         struct ldb_val v;
1641 
1642         if ( ! ldb_dn_validate(dn)) {
1643                 return LDB_ERR_OTHER;
1644         }
1645 
1646         if (num >= dn->comp_num) {
1647                 return LDB_ERR_OTHER;
1648         }
1649 
1650         n = talloc_strdup(dn, name);
1651         if ( ! n) {
1652                 return LDB_ERR_OTHER;
1653         }
1654 
1655         v.length = val.length;
1656         v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1657         if ( ! v.data) {
1658                 talloc_free(n);
1659                 return LDB_ERR_OTHER;
1660         }
1661 
1662         talloc_free(dn->components[num].name);
1663         talloc_free(dn->components[num].value.data);
1664         dn->components[num].name = n;
1665         dn->components[num].value = v;
1666 
1667         if (dn->valid_case) {
1668                 int i;
1669                 for (i = 0; i < dn->comp_num; i++) {
1670                         LDB_FREE(dn->components[i].cf_name);
1671                         LDB_FREE(dn->components[i].cf_value.data);
1672                 }
1673                 dn->valid_case = false;
1674         }
1675         LDB_FREE(dn->casefold);
1676         LDB_FREE(dn->linearized);
1677 
1678         /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
1679         LDB_FREE(dn->extended_linearized);
1680 
1681         dn->extended_comp_num = 0;
1682         LDB_FREE(dn->extended_components);
1683         return LDB_SUCCESS;
1684 }
1685 
1686 const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1687 {
1688         int i;
1689         if ( ! ldb_dn_validate(dn)) {
1690                 return NULL;
1691         }
1692         for (i=0; i < dn->extended_comp_num; i++) {
1693                 if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
1694                         return &dn->extended_components[i].value;
1695                 }
1696         }
1697         return NULL;
1698 }
1699 
1700 int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val)
     /* [<][>][^][v][top][bottom][index][help] */
1701 {
1702         struct ldb_dn_extended_component *p;
1703         int i;
1704                                 
1705         if ( ! ldb_dn_validate(dn)) {
1706                 return LDB_ERR_OTHER;
1707         }
1708 
1709         for (i=0; i < dn->extended_comp_num; i++) {
1710                 if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
1711                         if (val) {
1712                                 dn->extended_components[i].value = ldb_val_dup(dn->extended_components, val);
1713 
1714                                 dn->extended_components[i].name = talloc_strdup(dn->extended_components, name);
1715                                 if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
1716                                         dn->invalid = true;
1717                                         return LDB_ERR_OPERATIONS_ERROR;
1718                                 }
1719         
1720                         } else {
1721                                 if (i != (dn->extended_comp_num - 1)) {
1722                                         memmove(&dn->extended_components[i], &dn->extended_components[i+1],
1723                                                 ((dn->extended_comp_num-1) - i)*sizeof(*dn->extended_components));
1724                                 }
1725                                 dn->extended_comp_num--;
1726                                 
1727                                 dn->extended_components = talloc_realloc(dn,
1728                                                    dn->extended_components,
1729                                                    struct ldb_dn_extended_component,
1730                                                    dn->extended_comp_num);
1731                                 if (!dn->extended_components) {
1732                                         dn->invalid = true;
1733                                         return LDB_ERR_OPERATIONS_ERROR;
1734                                 }
1735                                 return LDB_SUCCESS;
1736                         }
1737                 }
1738         }
1739 
1740         p = dn->extended_components
1741                 = talloc_realloc(dn,
1742                                  dn->extended_components,
1743                                  struct ldb_dn_extended_component,
1744                                  dn->extended_comp_num + 1);
1745         if (!dn->extended_components) {
1746                 dn->invalid = true;
1747                 return LDB_ERR_OPERATIONS_ERROR;
1748         }
1749         
1750         p[dn->extended_comp_num].value = ldb_val_dup(dn->extended_components, val);
1751         p[dn->extended_comp_num].name = talloc_strdup(p, name);
1752         
1753         if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
1754                 dn->invalid = true;
1755                 return LDB_ERR_OPERATIONS_ERROR;
1756         }
1757         dn->extended_components = p;
1758         dn->extended_comp_num++;
1759         
1760         return LDB_SUCCESS;
1761 }
1762 
1763 void ldb_dn_remove_extended_components(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1764 {
1765         dn->extended_comp_num = 0;
1766         LDB_FREE(dn->extended_components);      
1767 }
1768 
1769 bool ldb_dn_is_valid(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1770 {
1771         if ( ! dn) return false;
1772         return ! dn->invalid;
1773 }
1774 
1775 bool ldb_dn_is_special(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1776 {
1777         if ( ! dn || dn->invalid) return false;
1778         return dn->special;
1779 }
1780 
1781 bool ldb_dn_has_extended(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1782 {
1783         if ( ! dn || dn->invalid) return false;
1784         if (dn->extended_linearized && (dn->extended_linearized[0] == '<')) return true;
1785         return dn->extended_comp_num != 0;
1786 }
1787 
1788 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
     /* [<][>][^][v][top][bottom][index][help] */
1789 {
1790         if ( ! dn || dn->invalid) return false;
1791         return ! strcmp(dn->linearized, check);
1792 }
1793 
1794 bool ldb_dn_is_null(struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
1795 {
1796         if ( ! dn || dn->invalid) return false;
1797         if (ldb_dn_has_extended(dn)) return false;
1798         if (dn->linearized && (dn->linearized[0] == '\0')) return true;
1799         return false;
1800 }

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