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

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

DEFINITIONS

This source file includes following definitions.
  1. ldb_dn_is_special
  2. ldb_dn_check_special
  3. ldb_dn_escape_value
  4. ldb_dn_unescape_value
  5. get_quotes_position
  6. seek_to_separator
  7. ldb_dn_trim_string
  8. ldb_dn_explode_component
  9. ldb_dn_new
  10. ldb_dn_explode
  11. ldb_dn_explode_or_special
  12. ldb_dn_linearize
  13. ldb_dn_compare_base
  14. ldb_dn_compare
  15. ldb_dn_cmp
  16. ldb_dn_casefold
  17. ldb_dn_explode_casefold
  18. ldb_dn_linearize_casefold
  19. ldb_dn_copy_component
  20. ldb_dn_copy_rebase
  21. ldb_dn_copy_partial
  22. ldb_dn_copy
  23. ldb_dn_get_parent
  24. ldb_dn_build_component
  25. ldb_dn_build_child
  26. ldb_dn_compose
  27. ldb_dn_string_compose
  28. ldb_dn_canonical
  29. ldb_dn_canonical_string
  30. ldb_dn_canonical_ex_string
  31. ldb_dn_get_comp_num
  32. ldb_dn_get_component_name
  33. ldb_dn_get_component_val
  34. ldb_dn_get_rdn_name
  35. ldb_dn_get_rdn_val
  36. ldb_dn_set_component

   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 explode and utility functions
  28  *
  29  *  Description: - explode a dn into its own basic elements
  30  *                 and put them in a structure
  31  *               - manipulate ldb_dn structures
  32  *
  33  *  Author: Simo Sorce
  34  */
  35 
  36 #include "includes.h"
  37 #include "ldb/include/includes.h"
  38 
  39 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
  40 
  41 #define LDB_SPECIAL "@SPECIAL"
  42 
  43 /**
  44    internal ldb exploded dn structures
  45 */
  46 struct ldb_dn_component {
  47         char *name;  
  48         struct ldb_val value;
  49 };
  50 
  51 struct ldb_dn {
  52         int comp_num;
  53         struct ldb_dn_component *components;
  54 };
  55 
  56 int ldb_dn_is_special(const struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
  57 {
  58         if (dn == NULL || dn->comp_num != 1) return 0;
  59 
  60         return ! strcmp(dn->components[0].name, LDB_SPECIAL);
  61 }
  62 
  63 int ldb_dn_check_special(const struct ldb_dn *dn, const char *check)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         if (dn == NULL || dn->comp_num != 1) return 0;
  66 
  67         return ! strcmp((char *)dn->components[0].value.data, check);
  68 }
  69 
  70 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
     /* [<][>][^][v][top][bottom][index][help] */
  71 {
  72         const char *p, *s, *src;
  73         char *d, *dst;
  74         int len;
  75 
  76         if (!value.length)
  77                 return NULL;
  78 
  79         p = s = src = (const char *)value.data;
  80         len = value.length;
  81 
  82         /* allocate destination string, it will be at most 3 times the source */
  83         dst = d = talloc_array(mem_ctx, char, len * 3 + 1);
  84         LDB_DN_NULL_FAILED(dst);
  85 
  86         while (p - src < len) {
  87 
  88                 p += strcspn(p, ",=\n+<>#;\\\"");
  89 
  90                 if (p - src == len) /* found no escapable chars */
  91                         break;
  92 
  93                 memcpy(d, s, p - s); /* copy the part of the string before the stop */
  94                 d += (p - s); /* move to current position */
  95 
  96                 if (*p) { /* it is a normal escapable character */
  97                         *d++ = '\\';
  98                         *d++ = *p++;
  99                 } else { /* we have a zero byte in the string */
 100                         strncpy(d, "\00", 3); /* escape the zero */
 101                         d = d + 3;
 102                         p++; /* skip the zero */
 103                 }
 104                 s = p; /* move forward */
 105         }
 106 
 107         /* copy the last part (with zero) and return */
 108         memcpy(d, s, &src[len] - s + 1);
 109 
 110         return dst;
 111 
 112 failed:
 113         talloc_free(dst);
 114         return NULL;
 115 }
 116 
 117 static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src)
     /* [<][>][^][v][top][bottom][index][help] */
 118 {
 119         struct ldb_val value;
 120         unsigned x;
 121         char *p, *dst = NULL, *end;
 122 
 123         memset(&value, 0, sizeof(value));
 124 
 125         LDB_DN_NULL_FAILED(src);
 126 
 127         dst = p = (char *)talloc_memdup(mem_ctx, src, strlen(src) + 1);
 128         LDB_DN_NULL_FAILED(dst);
 129 
 130         end = &dst[strlen(dst)];
 131 
 132         while (*p) {
 133                 p += strcspn(p, ",=\n+<>#;\\\"");
 134 
 135                 if (*p == '\\') {
 136                         if (strchr(",=\n+<>#;\\\"", p[1])) {
 137                                 memmove(p, p + 1, end - (p + 1) + 1);
 138                                 end--;
 139                                 p++;
 140                                 continue;
 141                         }
 142 
 143                         if (sscanf(p + 1, "%02x", &x) == 1) {
 144                                 *p = (unsigned char)x;
 145                                 memmove(p + 1, p + 3, end - (p + 3) + 1);
 146                                 end -= 2;
 147                                 p++;
 148                                 continue;
 149                         }
 150                 }
 151 
 152                 /* a string with not escaped specials is invalid (tested) */
 153                 if (*p != '\0') {
 154                         goto failed;
 155                 }
 156         }
 157 
 158         value.length = end - dst;
 159         value.data = (uint8_t *)dst;
 160         return value;
 161 
 162 failed:
 163         talloc_free(dst);
 164         return value;
 165 }
 166 
 167 /* check if the string contains quotes
 168  * skips leading and trailing spaces
 169  * - returns 0 if no quotes found
 170  * - returns 1 if quotes are found and put their position
 171  *   in *quote_start and *quote_end parameters
 172  * - return -1 if there are open quotes
 173  */
 174 
 175 static int get_quotes_position(const char *source, int *quote_start, int *quote_end)
     /* [<][>][^][v][top][bottom][index][help] */
 176 {
 177         const char *p;
 178 
 179         if (source == NULL || quote_start == NULL || quote_end == NULL) return -1;
 180 
 181         p = source;
 182 
 183         /* check if there are quotes surrounding the value */
 184         p += strspn(p, " \n"); /* skip white spaces */
 185 
 186         if (*p == '\"') {
 187                 *quote_start = p - source;
 188 
 189                 p++;
 190                 while (*p != '\"') {
 191                         p = strchr(p, '\"');
 192                         LDB_DN_NULL_FAILED(p);
 193 
 194                         if (*(p - 1) == '\\')
 195                                 p++;
 196                 }
 197 
 198                 *quote_end = p - source;
 199                 return 1;
 200         }
 201 
 202         return 0;
 203 
 204 failed:
 205         return -1;
 206 }
 207 
 208 static char *seek_to_separator(char *string, const char *separators)
     /* [<][>][^][v][top][bottom][index][help] */
 209 {
 210         char *p, *q;
 211         int ret, qs, qe, escaped;
 212 
 213         if (string == NULL || separators == NULL) return NULL;
 214 
 215         p = strchr(string, '=');
 216         LDB_DN_NULL_FAILED(p);
 217 
 218         p++;
 219 
 220         /* check if there are quotes surrounding the value */
 221 
 222         ret = get_quotes_position(p, &qs, &qe);
 223         if (ret == -1)
 224                 return NULL;
 225 
 226         if (ret == 1) { /* quotes found */
 227 
 228                 p += qe; /* positioning after quotes */
 229                 p += strspn(p, " \n"); /* skip white spaces after the quote */
 230 
 231                 if (strcspn(p, separators) != 0) /* if there are characters between quotes */
 232                         return NULL;        /* and separators, the dn is invalid */
 233 
 234                 return p; /* return on the separator */
 235         }
 236 
 237         /* no quotes found seek to separators */
 238         q = p;
 239         do {
 240                 escaped = 0;
 241                 ret = strcspn(q, separators);
 242                 
 243                 if (q[ret - 1] == '\\') {
 244                         escaped = 1;
 245                         q = q + ret + 1;
 246                 }
 247         } while (escaped);
 248 
 249         if (ret == 0 && p == q) /* no separators ?! bail out */
 250                 return NULL;
 251 
 252         return q + ret;
 253 
 254 failed:
 255         return NULL;
 256 }
 257 
 258 static char *ldb_dn_trim_string(char *string, const char *edge)
     /* [<][>][^][v][top][bottom][index][help] */
 259 {
 260         char *s, *p;
 261 
 262         /* seek out edge from start of string */
 263         s = string + strspn(string, edge);
 264 
 265         /* backwards skip from end of string */
 266         p = &s[strlen(s) - 1];
 267         while (p > s && strchr(edge, *p)) {
 268                 *p = '\0';
 269                 p--;
 270         }
 271 
 272         return s;
 273 }
 274 
 275 /* we choosed to not support multpile valued components */
 276 static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component)
     /* [<][>][^][v][top][bottom][index][help] */
 277 {
 278         struct ldb_dn_component dc;
 279         char *p;
 280         int ret, qs, qe;
 281 
 282         memset(&dc, 0, sizeof(dc));
 283 
 284         if (raw_component == NULL) {
 285                 return dc;
 286         }
 287 
 288         /* find attribute type/value separator */
 289         p = strchr(raw_component, '=');
 290         LDB_DN_NULL_FAILED(p);
 291 
 292         *p++ = '\0'; /* terminate name and point to value */
 293 
 294         /* copy and trim name in the component */
 295         dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n"));
 296         if (!dc.name)
 297                 return dc;
 298 
 299         if (! ldb_valid_attr_name(dc.name)) {
 300                 goto failed;
 301         }
 302 
 303         ret = get_quotes_position(p, &qs, &qe);
 304 
 305         switch (ret) {
 306         case 0: /* no quotes trim the string */
 307                 p = ldb_dn_trim_string(p, " \n");
 308                 dc.value = ldb_dn_unescape_value(mem_ctx, p);
 309                 break;
 310 
 311         case 1: /* quotes found get the unquoted string */
 312                 p[qe] = '\0';
 313                 p = p + qs + 1;
 314                 dc.value.length = strlen(p);
 315                 dc.value.data = (uint8_t *)talloc_memdup(mem_ctx, p,
 316                                                          dc.value.length + 1);
 317                 break;
 318 
 319         default: /* mismatched quotes ot other error, bail out */
 320                 goto failed;
 321         }
 322 
 323         if (dc.value.length == 0) {
 324                 goto failed;
 325         }
 326 
 327         return dc;
 328 
 329 failed:
 330         talloc_free(dc.name);
 331         dc.name = NULL;
 332         return dc;
 333 }
 334 
 335 struct ldb_dn *ldb_dn_new(void *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 336 {
 337         struct ldb_dn *edn;
 338 
 339         edn = talloc(mem_ctx, struct ldb_dn);
 340         LDB_DN_NULL_FAILED(edn);
 341 
 342         /* Initially there are no components */
 343         edn->comp_num = 0;
 344         edn->components = NULL;
 345 
 346         return edn;
 347 
 348 failed:
 349         return NULL;
 350 }
 351 
 352 /*
 353   explode a DN string into a ldb_dn structure
 354 */
 355 struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 356 {
 357         struct ldb_dn *edn; /* the exploded dn */
 358         char *pdn, *p;
 359 
 360         if (dn == NULL) return NULL;
 361 
 362         /* Allocate a structure to hold the exploded DN */
 363         edn = ldb_dn_new(mem_ctx);
 364         if (edn == NULL) {
 365                 return NULL;
 366         }
 367 
 368         pdn = NULL;
 369 
 370         /* Empty DNs */
 371         if (dn[0] == '\0') {
 372                 return edn;
 373         }
 374 
 375         /* Special DNs case */
 376         if (dn[0] == '@') {
 377                 edn->comp_num = 1;
 378                 edn->components = talloc(edn, struct ldb_dn_component);
 379                 if (edn->components == NULL) goto failed;
 380                 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
 381                 if (edn->components[0].name == NULL) goto failed;
 382                 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
 383                 if (edn->components[0].value.data== NULL) goto failed;
 384                 edn->components[0].value.length = strlen(dn);
 385                 return edn;
 386         }
 387 
 388         pdn = p = talloc_strdup(edn, dn);
 389         LDB_DN_NULL_FAILED(pdn);
 390 
 391         /* get the components */
 392         do {
 393                 char *t;
 394 
 395                 /* terminate the current component and return pointer to the next one */
 396                 t = seek_to_separator(p, ",;");
 397                 LDB_DN_NULL_FAILED(t);
 398 
 399                 if (*t) { /* here there is a separator */
 400                         *t = '\0'; /*terminate */
 401                         t++; /* a separtor means another component follows */
 402                 }
 403 
 404                 /* allocate space to hold the dn component */
 405                 edn->components = talloc_realloc(edn, edn->components,
 406                                                  struct ldb_dn_component,
 407                                                  edn->comp_num + 1);
 408                 if (edn->components == NULL)
 409                         goto failed;
 410 
 411                 /* store the exploded component in the main structure */
 412                 edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p);
 413                 LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name);
 414 
 415                 edn->comp_num++;
 416 
 417                 /* jump to the next component if any */
 418                 p = t;
 419 
 420         } while(*p);
 421 
 422         talloc_free(pdn);
 423         return edn;
 424 
 425 failed:
 426         talloc_free(pdn);
 427         talloc_free(edn);
 428         return NULL;
 429 }
 430 
 431 struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 432 {
 433         struct ldb_dn *edn; /* the exploded dn */
 434 
 435         if (dn == NULL) return NULL;
 436 
 437         if (strncasecmp(dn, "<GUID=", 6) == 0) {
 438                 /* this is special DN returned when the
 439                  * exploded_dn control is used
 440                  */
 441 
 442                 /* Allocate a structure to hold the exploded DN */
 443                 if (!(edn = ldb_dn_new(mem_ctx))) {
 444                         return NULL;
 445                 }
 446 
 447                 edn->comp_num = 1;
 448                 edn->components = talloc(edn, struct ldb_dn_component);
 449                 if (edn->components == NULL) goto failed;
 450                 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
 451                 if (edn->components[0].name == NULL) goto failed;
 452                 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
 453                 if (edn->components[0].value.data== NULL) goto failed;
 454                 edn->components[0].value.length = strlen(dn);
 455                 return edn;
 456 
 457         }
 458         
 459         return ldb_dn_explode(mem_ctx, dn);
 460 
 461 failed:
 462         talloc_free(edn);
 463         return NULL;
 464 }
 465 
 466 char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn)
     /* [<][>][^][v][top][bottom][index][help] */
 467 {
 468         char *dn, *value;
 469         int i;
 470 
 471         if (edn == NULL) return NULL;
 472 
 473         /* Special DNs */
 474         if (ldb_dn_is_special(edn)) {
 475                 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
 476                 return dn;
 477         }
 478 
 479         dn = talloc_strdup(mem_ctx, "");
 480         LDB_DN_NULL_FAILED(dn);
 481 
 482         for (i = 0; i < edn->comp_num; i++) {
 483                 value = ldb_dn_escape_value(dn, edn->components[i].value);
 484                 LDB_DN_NULL_FAILED(value);
 485 
 486                 if (i == 0) {
 487                         dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value);
 488                 } else {
 489                         dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value);
 490                 }
 491                 LDB_DN_NULL_FAILED(dn);
 492 
 493                 talloc_free(value);
 494         }
 495 
 496         return dn;
 497 
 498 failed:
 499         talloc_free(dn);
 500         return NULL;
 501 }
 502 
 503 /* Determine if dn is below base, in the ldap tree.  Used for
 504  * evaluating a subtree search.
 505  * 0 if they match, otherwise non-zero
 506  */
 507 
 508 int ldb_dn_compare_base(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 509                         const struct ldb_dn *base,
 510                         const struct ldb_dn *dn)
 511 {
 512         int ret;
 513         int n0, n1;
 514 
 515         if (base == NULL || base->comp_num == 0) return 0;
 516         if (dn == NULL || dn->comp_num == 0) return -1;
 517 
 518         /* if the base has more componts than the dn, then they differ */
 519         if (base->comp_num > dn->comp_num) {
 520                 return (dn->comp_num - base->comp_num);
 521         }
 522 
 523         n0 = base->comp_num - 1;
 524         n1 = dn->comp_num - 1;
 525         while (n0 >= 0 && n1 >= 0) {
 526                 const struct ldb_attrib_handler *h;
 527 
 528                 /* compare names (attribute names are guaranteed to be ASCII only) */
 529                 ret = ldb_attr_cmp(base->components[n0].name,
 530                                    dn->components[n1].name);
 531                 if (ret) {
 532                         return ret;
 533                 }
 534 
 535                 /* names match, compare values */
 536                 h = ldb_attrib_handler(ldb, base->components[n0].name);
 537                 ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value),
 538                                                   &(dn->components[n1].value));
 539                 if (ret) {
 540                         return ret;
 541                 }
 542                 n1--;
 543                 n0--;
 544         }
 545 
 546         return 0;
 547 }
 548 
 549 /* compare DNs using casefolding compare functions.  
 550 
 551    If they match, then return 0
 552  */
 553 
 554 int ldb_dn_compare(struct ldb_context *ldb,
     /* [<][>][^][v][top][bottom][index][help] */
 555                    const struct ldb_dn *edn0,
 556                    const struct ldb_dn *edn1)
 557 {
 558         if (edn0 == NULL || edn1 == NULL) return edn1 - edn0;
 559 
 560         if (edn0->comp_num != edn1->comp_num)
 561                 return (edn1->comp_num - edn0->comp_num);
 562 
 563         return ldb_dn_compare_base(ldb, edn0, edn1);
 564 }
 565 
 566 int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1)
     /* [<][>][^][v][top][bottom][index][help] */
 567 {
 568         struct ldb_dn *edn0;
 569         struct ldb_dn *edn1;
 570         int ret;
 571 
 572         if (dn0 == NULL || dn1 == NULL) return dn1 - dn0;
 573 
 574         edn0 = ldb_dn_explode_casefold(ldb, ldb, dn0);
 575         if (edn0 == NULL) return 1;
 576 
 577         edn1 = ldb_dn_explode_casefold(ldb, ldb, dn1);
 578         if (edn1 == NULL) {
 579                 talloc_free(edn0);
 580                 return -1;
 581         }
 582 
 583         ret = ldb_dn_compare(ldb, edn0, edn1);
 584 
 585         talloc_free(edn0);
 586         talloc_free(edn1);
 587 
 588         return ret;
 589 }
 590 
 591 /*
 592   casefold a dn. We need to casefold the attribute names, and canonicalize 
 593   attribute values of case insensitive attributes.
 594 */
 595 struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
     /* [<][>][^][v][top][bottom][index][help] */
 596 {
 597         struct ldb_dn *cedn;
 598         int i, ret;
 599 
 600         if (edn == NULL) return NULL;
 601 
 602         cedn = ldb_dn_new(mem_ctx);
 603         if (!cedn) {
 604                 return NULL;
 605         }
 606 
 607         cedn->comp_num = edn->comp_num;
 608         cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num);
 609         if (!cedn->components) {
 610                 talloc_free(cedn);
 611                 return NULL;
 612         }
 613 
 614         for (i = 0; i < edn->comp_num; i++) {
 615                 struct ldb_dn_component dc;
 616                 const struct ldb_attrib_handler *h;
 617 
 618                 memset(&dc, 0, sizeof(dc));
 619                 dc.name = ldb_attr_casefold(cedn->components, edn->components[i].name);
 620                 if (!dc.name) {
 621                         talloc_free(cedn);
 622                         return NULL;
 623                 }
 624 
 625                 h = ldb_attrib_handler(ldb, dc.name);
 626                 ret = h->canonicalise_fn(ldb, cedn->components,
 627                                          &(edn->components[i].value),
 628                                          &(dc.value));
 629                 if (ret != 0) {
 630                         talloc_free(cedn);
 631                         return NULL;
 632                 }
 633 
 634                 cedn->components[i] = dc;
 635         }
 636 
 637         return cedn;
 638 }
 639 
 640 struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, void *mem_ctx, const char *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 641 {
 642         struct ldb_dn *edn, *cdn;
 643 
 644         if (dn == NULL) return NULL;
 645 
 646         edn = ldb_dn_explode(ldb, dn);
 647         if (edn == NULL) return NULL;
 648 
 649         cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
 650         
 651         talloc_free(edn);
 652         return cdn;
 653 }
 654 
 655 char *ldb_dn_linearize_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
     /* [<][>][^][v][top][bottom][index][help] */
 656 {
 657         struct ldb_dn *cdn;
 658         char *dn;
 659 
 660         if (edn == NULL) return NULL;
 661 
 662         /* Special DNs */
 663         if (ldb_dn_is_special(edn)) {
 664                 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
 665                 return dn;
 666         }
 667 
 668         cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
 669         if (cdn == NULL) return NULL;
 670 
 671         dn = ldb_dn_linearize(ldb, cdn);
 672         if (dn == NULL) {
 673                 talloc_free(cdn);
 674                 return NULL;
 675         }
 676 
 677         talloc_free(cdn);
 678         return dn;
 679 }
 680 
 681 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
     /* [<][>][^][v][top][bottom][index][help] */
 682 {
 683         struct ldb_dn_component dst;
 684 
 685         memset(&dst, 0, sizeof(dst));
 686 
 687         if (src == NULL) {
 688                 return dst;
 689         }
 690 
 691         dst.value = ldb_val_dup(mem_ctx, &(src->value));
 692         if (dst.value.data == NULL) {
 693                 return dst;
 694         }
 695 
 696         dst.name = talloc_strdup(mem_ctx, src->name);
 697         if (dst.name == NULL) {
 698                 talloc_free(dst.value.data);
 699                 dst.value.data = NULL;
 700         }
 701 
 702         return dst;
 703 }
 704 
 705 /* Copy a DN but replace the old with the new base DN. */
 706 struct ldb_dn *ldb_dn_copy_rebase(void *mem_ctx, const struct ldb_dn *old, const struct ldb_dn *old_base, const struct ldb_dn *new_base)
     /* [<][>][^][v][top][bottom][index][help] */
 707 {
 708         struct ldb_dn *new_dn;
 709         int i, offset;
 710 
 711         /* Perhaps we don't need to rebase at all? */
 712         if (!old_base || !new_base) {
 713                 return ldb_dn_copy(mem_ctx, old);
 714         }
 715 
 716         offset = old->comp_num - old_base->comp_num;
 717         if (!(new_dn = ldb_dn_copy_partial(mem_ctx, new_base,
 718                                            offset + new_base->comp_num))) {
 719                 return NULL;
 720         }
 721         for (i = 0; i < offset; i++) {
 722                 new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &(old->components[i]));
 723         }
 724 
 725         return new_dn;
 726 }
 727 
 728 /* copy specified number of elements of a dn into a new one
 729    element are copied from top level up to the unique rdn
 730    num_el may be greater than dn->comp_num (see ldb_dn_make_child)
 731 */
 732 struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el)
     /* [<][>][^][v][top][bottom][index][help] */
 733 {
 734         struct ldb_dn *newdn;
 735         int i, n, e;
 736 
 737         if (dn == NULL) return NULL;
 738         if (num_el <= 0) return NULL;
 739 
 740         newdn = ldb_dn_new(mem_ctx);
 741         LDB_DN_NULL_FAILED(newdn);
 742 
 743         newdn->comp_num = num_el;
 744         n = newdn->comp_num - 1;
 745         newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
 746         if (newdn->components == NULL) goto failed;
 747 
 748         if (dn->comp_num == 0) return newdn;
 749         e = dn->comp_num - 1;
 750 
 751         for (i = 0; i < newdn->comp_num; i++) {
 752                 newdn->components[n - i] = ldb_dn_copy_component(newdn->components,
 753                                                                 &(dn->components[e - i]));
 754                 if ((e - i) == 0) {
 755                         return newdn;
 756                 }
 757         }
 758 
 759         return newdn;
 760 
 761 failed:
 762         talloc_free(newdn);
 763         return NULL;
 764 }
 765 
 766 struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 767 {
 768         if (dn == NULL) return NULL;
 769         return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num);
 770 }
 771 
 772 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 773 {
 774         if (dn == NULL) return NULL;
 775         return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1);
 776 }
 777 
 778 struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
     /* [<][>][^][v][top][bottom][index][help] */
 779                                                 const char *val)
 780 {
 781         struct ldb_dn_component *dc;
 782 
 783         if (attr == NULL || val == NULL) return NULL;
 784 
 785         dc = talloc(mem_ctx, struct ldb_dn_component);
 786         if (dc == NULL) return NULL;
 787 
 788         dc->name = talloc_strdup(dc, attr);
 789         if (dc->name ==  NULL) {
 790                 talloc_free(dc);
 791                 return NULL;
 792         }
 793 
 794         dc->value.data = (uint8_t *)talloc_strdup(dc, val);
 795         if (dc->value.data ==  NULL) {
 796                 talloc_free(dc);
 797                 return NULL;
 798         }
 799 
 800         dc->value.length = strlen(val);
 801 
 802         return dc;
 803 }
 804 
 805 struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
     /* [<][>][^][v][top][bottom][index][help] */
 806                                                  const char * value,
 807                                                  const struct ldb_dn *base)
 808 {
 809         struct ldb_dn *newdn;
 810         if (! ldb_valid_attr_name(attr)) return NULL;
 811         if (value == NULL || value == '\0') return NULL; 
 812 
 813         if (base != NULL) {
 814                 newdn = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1);
 815                 LDB_DN_NULL_FAILED(newdn);
 816         } else {
 817                 newdn = ldb_dn_new(mem_ctx);
 818                 LDB_DN_NULL_FAILED(newdn);
 819 
 820                 newdn->comp_num = 1;
 821                 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
 822                 LDB_DN_NULL_FAILED(newdn->components);
 823         }
 824 
 825         newdn->components[0].name = talloc_strdup(newdn->components, attr);
 826         LDB_DN_NULL_FAILED(newdn->components[0].name);
 827 
 828         newdn->components[0].value.data = (uint8_t *)talloc_strdup(newdn->components, value);
 829         LDB_DN_NULL_FAILED(newdn->components[0].value.data);
 830         newdn->components[0].value.length = strlen((char *)newdn->components[0].value.data);
 831 
 832         return newdn;
 833 
 834 failed:
 835         talloc_free(newdn);
 836         return NULL;
 837 
 838 }
 839 
 840 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2)
     /* [<][>][^][v][top][bottom][index][help] */
 841 {
 842         int i;
 843         struct ldb_dn *newdn;
 844 
 845         if (dn2 == NULL && dn1 == NULL) {
 846                 return NULL;
 847         }
 848 
 849         if (dn2 == NULL) {
 850                 newdn = ldb_dn_new(mem_ctx);
 851                 LDB_DN_NULL_FAILED(newdn);
 852 
 853                 newdn->comp_num = dn1->comp_num;
 854                 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
 855                 LDB_DN_NULL_FAILED(newdn->components);
 856         } else {
 857                 int comp_num = dn2->comp_num;
 858                 if (dn1 != NULL) comp_num += dn1->comp_num;
 859                 newdn = ldb_dn_copy_partial(mem_ctx, dn2, comp_num);
 860                 LDB_DN_NULL_FAILED(newdn);
 861         }
 862 
 863         if (dn1 == NULL) {
 864                 return newdn;
 865         }
 866 
 867         for (i = 0; i < dn1->comp_num; i++) {
 868                 newdn->components[i] = ldb_dn_copy_component(newdn->components,
 869                                                            &(dn1->components[i]));
 870                 if (newdn->components[i].value.data == NULL) {
 871                         goto failed;
 872                 }
 873         }
 874 
 875         return newdn;
 876 
 877 failed:
 878         talloc_free(newdn);
 879         return NULL;
 880 }
 881 
 882 struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 883 {
 884         struct ldb_dn *dn, *dn1;
 885         char *child_str;
 886         va_list ap;
 887         
 888         if (child_fmt == NULL) return NULL;
 889 
 890         va_start(ap, child_fmt);
 891         child_str = talloc_vasprintf(mem_ctx, child_fmt, ap);
 892         va_end(ap);
 893 
 894         if (child_str == NULL) return NULL;
 895 
 896         dn1 = ldb_dn_explode(mem_ctx, child_str);
 897         dn = ldb_dn_compose(mem_ctx, dn1, base);
 898 
 899         talloc_free(child_str);
 900         talloc_free(dn1);
 901 
 902         return dn;
 903 }
 904 
 905 /* Create a 'canonical name' string from a DN:
 906 
 907    ie dc=samba,dc=org -> samba.org/
 908       uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
 909 
 910    There are two formats, the EX format has the last / replaced with a newline (\n).
 911 
 912 */
 913 static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) {
     /* [<][>][^][v][top][bottom][index][help] */
 914         int i;
 915         char *cracked = NULL;
 916 
 917         /* Walk backwards down the DN, grabbing 'dc' components at first */
 918         for (i = dn->comp_num - 1 ; i >= 0; i--) {
 919                 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
 920                         break;
 921                 }
 922                 if (cracked) {
 923                         cracked = talloc_asprintf(mem_ctx, "%s.%s",
 924                                                   ldb_dn_escape_value(mem_ctx, dn->components[i].value),
 925                                                   cracked);
 926                 } else {
 927                         cracked = ldb_dn_escape_value(mem_ctx, dn->components[i].value);
 928                 }
 929                 if (!cracked) {
 930                         return NULL;
 931                 }
 932         }
 933 
 934         /* Only domain components?  Finish here */
 935         if (i < 0) {
 936                 if (ex_format) {
 937                         cracked = talloc_asprintf(mem_ctx, "%s\n", cracked);
 938                 } else {
 939                         cracked = talloc_asprintf(mem_ctx, "%s/", cracked);
 940                 }
 941                 return cracked;
 942         }
 943 
 944         /* Now walk backwards appending remaining components */
 945         for (; i > 0; i--) {
 946                 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
 947                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
 948                 if (!cracked) {
 949                         return NULL;
 950                 }
 951         }
 952 
 953         /* Last one, possibly a newline for the 'ex' format */
 954         if (ex_format) {
 955                 cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked, 
 956                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
 957         } else {
 958                 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
 959                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
 960         }
 961         return cracked;
 962 }
 963 
 964 /* Wrapper functions for the above, for the two different string formats */
 965 char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
 966         return ldb_dn_canonical(mem_ctx, dn, 0);
 967 
 968 }
 969 
 970 char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
 971         return ldb_dn_canonical(mem_ctx, dn, 1);
 972 }
 973 
 974 int ldb_dn_get_comp_num(const struct ldb_dn *dn)
     /* [<][>][^][v][top][bottom][index][help] */
 975 {
 976         return dn->comp_num;
 977 }
 978 
 979 const char *ldb_dn_get_component_name(const struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
 980 {
 981         if (num >= dn->comp_num) return NULL;
 982         return dn->components[num].name;
 983 }
 984 
 985 const struct ldb_val *ldb_dn_get_component_val(const struct ldb_dn *dn, unsigned int num)
     /* [<][>][^][v][top][bottom][index][help] */
 986 {
 987         if (num >= dn->comp_num) return NULL;
 988         return &dn->components[num].value;
 989 }
 990 
 991 const char *ldb_dn_get_rdn_name(const struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
 992         if (dn->comp_num == 0) return NULL;
 993         return dn->components[0].name;
 994 }
 995 
 996 const struct ldb_val *ldb_dn_get_rdn_val(const struct ldb_dn *dn) {
     /* [<][>][^][v][top][bottom][index][help] */
 997         if (dn->comp_num == 0) return NULL;
 998         return &dn->components[0].value;
 999 }
1000 
1001 int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
     /* [<][>][^][v][top][bottom][index][help] */
1002 {
1003         char *n;
1004         struct ldb_val v;
1005 
1006         if (num >= dn->comp_num) {
1007                 return LDB_ERR_OTHER;
1008         }
1009 
1010         n = talloc_strdup(dn, name);
1011         if ( ! n) {
1012                 return LDB_ERR_OTHER;
1013         }
1014 
1015         v.length = val.length;
1016         v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1017         if ( ! v.data) {
1018                 return LDB_ERR_OTHER;
1019         }
1020 
1021         talloc_free(dn->components[num].name);
1022         talloc_free(dn->components[num].value.data);
1023         dn->components[num].name = n;
1024         dn->components[num].value = v;
1025 
1026         return LDB_SUCCESS;
1027 }

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