r19430: merge recent ldb changes from Samba4. This includes memory leak fixes
[Samba/bb.git] / source / lib / ldb / common / ldb_dn.c
blobe937a2b7fc40cbe10f8c4cfccc800e3203a025a7
1 /*
2 ldb database library
4 Copyright (C) Simo Sorce 2005
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
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 2 of the License, or (at your option) any later version.
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.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * Name: ldb
28 * Component: ldb dn explode and utility functions
30 * Description: - explode a dn into it's own basic elements
31 * and put them in a structure
32 * - manipulate ldb_dn structures
34 * Author: Simo Sorce
37 #include "includes.h"
38 #include "ldb/include/includes.h"
40 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
42 #define LDB_SPECIAL "@SPECIAL"
44 int ldb_dn_is_special(const struct ldb_dn *dn)
46 if (dn == NULL || dn->comp_num != 1) return 0;
48 return ! strcmp(dn->components[0].name, LDB_SPECIAL);
51 int ldb_dn_check_special(const struct ldb_dn *dn, const char *check)
53 if (dn == NULL || dn->comp_num != 1) return 0;
55 return ! strcmp((char *)dn->components[0].value.data, check);
58 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
60 const char *p, *s, *src;
61 char *d, *dst;
62 int len;
64 if (!value.length)
65 return NULL;
67 p = s = src = (const char *)value.data;
68 len = value.length;
70 /* allocate destination string, it will be at most 3 times the source */
71 dst = d = talloc_array(mem_ctx, char, len * 3 + 1);
72 LDB_DN_NULL_FAILED(dst);
74 while (p - src < len) {
76 p += strcspn(p, ",=\n+<>#;\\\"");
78 if (p - src == len) /* found no escapable chars */
79 break;
81 memcpy(d, s, p - s); /* copy the part of the string before the stop */
82 d += (p - s); /* move to current position */
84 if (*p) { /* it is a normal escapable character */
85 *d++ = '\\';
86 *d++ = *p++;
87 } else { /* we have a zero byte in the string */
88 strncpy(d, "\00", 3); /* escape the zero */
89 d = d + 3;
90 p++; /* skip the zero */
92 s = p; /* move forward */
95 /* copy the last part (with zero) and return */
96 memcpy(d, s, &src[len] - s + 1);
98 return dst;
100 failed:
101 talloc_free(dst);
102 return NULL;
105 static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src)
107 struct ldb_val value;
108 unsigned x;
109 char *p, *dst = NULL, *end;
111 memset(&value, 0, sizeof(value));
113 LDB_DN_NULL_FAILED(src);
115 dst = p = (char *)talloc_memdup(mem_ctx, src, strlen(src) + 1);
116 LDB_DN_NULL_FAILED(dst);
118 end = &dst[strlen(dst)];
120 while (*p) {
121 p += strcspn(p, ",=\n+<>#;\\\"");
123 if (*p == '\\') {
124 if (strchr(",=\n+<>#;\\\"", p[1])) {
125 memmove(p, p + 1, end - (p + 1) + 1);
126 end--;
127 p++;
128 continue;
131 if (sscanf(p + 1, "%02x", &x) == 1) {
132 *p = (unsigned char)x;
133 memmove(p + 1, p + 3, end - (p + 3) + 1);
134 end -= 2;
135 p++;
136 continue;
140 /* a string with not escaped specials is invalid (tested) */
141 if (*p != '\0') {
142 goto failed;
146 value.length = end - dst;
147 value.data = (uint8_t *)dst;
148 return value;
150 failed:
151 talloc_free(dst);
152 return value;
155 /* check if the string contains quotes
156 * skips leading and trailing spaces
157 * - returns 0 if no quotes found
158 * - returns 1 if quotes are found and put their position
159 * in *quote_start and *quote_end parameters
160 * - return -1 if there are open quotes
163 static int get_quotes_position(const char *source, int *quote_start, int *quote_end)
165 const char *p;
167 if (source == NULL || quote_start == NULL || quote_end == NULL) return -1;
169 p = source;
171 /* check if there are quotes surrounding the value */
172 p += strspn(p, " \n"); /* skip white spaces */
174 if (*p == '\"') {
175 *quote_start = p - source;
177 p++;
178 while (*p != '\"') {
179 p = strchr(p, '\"');
180 LDB_DN_NULL_FAILED(p);
182 if (*(p - 1) == '\\')
183 p++;
186 *quote_end = p - source;
187 return 1;
190 return 0;
192 failed:
193 return -1;
196 static char *seek_to_separator(char *string, const char *separators)
198 char *p, *q;
199 int ret, qs, qe, escaped;
201 if (string == NULL || separators == NULL) return NULL;
203 p = strchr(string, '=');
204 LDB_DN_NULL_FAILED(p);
206 p++;
208 /* check if there are quotes surrounding the value */
210 ret = get_quotes_position(p, &qs, &qe);
211 if (ret == -1)
212 return NULL;
214 if (ret == 1) { /* quotes found */
216 p += qe; /* positioning after quotes */
217 p += strspn(p, " \n"); /* skip white spaces after the quote */
219 if (strcspn(p, separators) != 0) /* if there are characters between quotes */
220 return NULL; /* and separators, the dn is invalid */
222 return p; /* return on the separator */
225 /* no quotes found seek to separators */
226 q = p;
227 do {
228 escaped = 0;
229 ret = strcspn(q, separators);
231 if (q[ret - 1] == '\\') {
232 escaped = 1;
233 q = q + ret + 1;
235 } while (escaped);
237 if (ret == 0 && p == q) /* no separators ?! bail out */
238 return NULL;
240 return q + ret;
242 failed:
243 return NULL;
246 static char *ldb_dn_trim_string(char *string, const char *edge)
248 char *s, *p;
250 /* seek out edge from start of string */
251 s = string + strspn(string, edge);
253 /* backwards skip from end of string */
254 p = &s[strlen(s) - 1];
255 while (p > s && strchr(edge, *p)) {
256 *p = '\0';
257 p--;
260 return s;
263 /* we choosed to not support multpile valued components */
264 static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component)
266 struct ldb_dn_component dc;
267 char *p;
268 int ret, qs, qe;
270 memset(&dc, 0, sizeof(dc));
272 if (raw_component == NULL) {
273 return dc;
276 /* find attribute type/value separator */
277 p = strchr(raw_component, '=');
278 LDB_DN_NULL_FAILED(p);
280 *p++ = '\0'; /* terminate name and point to value */
282 /* copy and trim name in the component */
283 dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n"));
284 if (!dc.name)
285 return dc;
287 if (! ldb_valid_attr_name(dc.name)) {
288 goto failed;
291 ret = get_quotes_position(p, &qs, &qe);
293 switch (ret) {
294 case 0: /* no quotes trim the string */
295 p = ldb_dn_trim_string(p, " \n");
296 dc.value = ldb_dn_unescape_value(mem_ctx, p);
297 break;
299 case 1: /* quotes found get the unquoted string */
300 p[qe] = '\0';
301 p = p + qs + 1;
302 dc.value.length = strlen(p);
303 dc.value.data = (uint8_t *)talloc_memdup(mem_ctx, p,
304 dc.value.length + 1);
305 break;
307 default: /* mismatched quotes ot other error, bail out */
308 goto failed;
311 if (dc.value.length == 0) {
312 goto failed;
315 return dc;
317 failed:
318 talloc_free(dc.name);
319 dc.name = NULL;
320 return dc;
323 struct ldb_dn *ldb_dn_new(void *mem_ctx)
325 struct ldb_dn *edn;
327 edn = talloc(mem_ctx, struct ldb_dn);
328 LDB_DN_NULL_FAILED(edn);
330 /* Initially there are no components */
331 edn->comp_num = 0;
332 edn->components = NULL;
334 return edn;
336 failed:
337 return NULL;
341 explode a DN string into a ldb_dn structure
343 struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
345 struct ldb_dn *edn; /* the exploded dn */
346 char *pdn, *p;
348 if (dn == NULL) return NULL;
350 /* Allocate a structure to hold the exploded DN */
351 edn = ldb_dn_new(mem_ctx);
352 if (edn == NULL) {
353 return NULL;
356 pdn = NULL;
358 /* Empty DNs */
359 if (dn[0] == '\0') {
360 return edn;
363 /* Special DNs case */
364 if (dn[0] == '@') {
365 edn->comp_num = 1;
366 edn->components = talloc(edn, struct ldb_dn_component);
367 if (edn->components == NULL) goto failed;
368 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
369 if (edn->components[0].name == NULL) goto failed;
370 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
371 if (edn->components[0].value.data== NULL) goto failed;
372 edn->components[0].value.length = strlen(dn);
373 return edn;
376 pdn = p = talloc_strdup(edn, dn);
377 LDB_DN_NULL_FAILED(pdn);
379 /* get the components */
380 do {
381 char *t;
383 /* terminate the current component and return pointer to the next one */
384 t = seek_to_separator(p, ",;");
385 LDB_DN_NULL_FAILED(t);
387 if (*t) { /* here there is a separator */
388 *t = '\0'; /*terminate */
389 t++; /* a separtor means another component follows */
392 /* allocate space to hold the dn component */
393 edn->components = talloc_realloc(edn, edn->components,
394 struct ldb_dn_component,
395 edn->comp_num + 1);
396 if (edn->components == NULL)
397 goto failed;
399 /* store the exploded component in the main structure */
400 edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p);
401 LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name);
403 edn->comp_num++;
405 /* jump to the next component if any */
406 p = t;
408 } while(*p);
410 talloc_free(pdn);
411 return edn;
413 failed:
414 talloc_free(pdn);
415 talloc_free(edn);
416 return NULL;
419 struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn)
421 struct ldb_dn *edn; /* the exploded dn */
423 if (dn == NULL) return NULL;
425 if (strncasecmp(dn, "<GUID=", 6) == 0) {
426 /* this is special DN returned when the
427 * exploded_dn control is used
430 /* Allocate a structure to hold the exploded DN */
431 edn = ldb_dn_new(mem_ctx);
433 edn->comp_num = 1;
434 edn->components = talloc(edn, struct ldb_dn_component);
435 if (edn->components == NULL) goto failed;
436 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
437 if (edn->components[0].name == NULL) goto failed;
438 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
439 if (edn->components[0].value.data== NULL) goto failed;
440 edn->components[0].value.length = strlen(dn);
441 return edn;
445 return ldb_dn_explode(mem_ctx, dn);
447 failed:
448 talloc_free(edn);
449 return NULL;
452 char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn)
454 char *dn, *value;
455 int i;
457 if (edn == NULL) return NULL;
459 /* Special DNs */
460 if (ldb_dn_is_special(edn)) {
461 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
462 return dn;
465 dn = talloc_strdup(mem_ctx, "");
466 LDB_DN_NULL_FAILED(dn);
468 for (i = 0; i < edn->comp_num; i++) {
469 value = ldb_dn_escape_value(dn, edn->components[i].value);
470 LDB_DN_NULL_FAILED(value);
472 if (i == 0) {
473 dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value);
474 } else {
475 dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value);
477 LDB_DN_NULL_FAILED(dn);
479 talloc_free(value);
482 return dn;
484 failed:
485 talloc_free(dn);
486 return NULL;
489 /* Determine if dn is below base, in the ldap tree. Used for
490 * evaluating a subtree search.
491 * 0 if they match, otherwise non-zero
494 int ldb_dn_compare_base(struct ldb_context *ldb,
495 const struct ldb_dn *base,
496 const struct ldb_dn *dn)
498 int ret;
499 int n0, n1;
501 if (base == NULL || base->comp_num == 0) return 0;
502 if (dn == NULL || dn->comp_num == 0) return -1;
504 /* if the base has more componts than the dn, then they differ */
505 if (base->comp_num > dn->comp_num) {
506 return (dn->comp_num - base->comp_num);
509 n0 = base->comp_num - 1;
510 n1 = dn->comp_num - 1;
511 while (n0 >= 0 && n1 >= 0) {
512 const struct ldb_attrib_handler *h;
514 /* compare names (attribute names are guaranteed to be ASCII only) */
515 ret = ldb_attr_cmp(base->components[n0].name,
516 dn->components[n1].name);
517 if (ret) {
518 return ret;
521 /* names match, compare values */
522 h = ldb_attrib_handler(ldb, base->components[n0].name);
523 ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value),
524 &(dn->components[n1].value));
525 if (ret) {
526 return ret;
528 n1--;
529 n0--;
532 return 0;
535 /* compare DNs using casefolding compare functions.
537 If they match, then return 0
540 int ldb_dn_compare(struct ldb_context *ldb,
541 const struct ldb_dn *edn0,
542 const struct ldb_dn *edn1)
544 if (edn0 == NULL || edn1 == NULL) return edn1 - edn0;
546 if (edn0->comp_num != edn1->comp_num)
547 return (edn1->comp_num - edn0->comp_num);
549 return ldb_dn_compare_base(ldb, edn0, edn1);
552 int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1)
554 struct ldb_dn *edn0;
555 struct ldb_dn *edn1;
556 int ret;
558 if (dn0 == NULL || dn1 == NULL) return dn1 - dn0;
560 edn0 = ldb_dn_explode_casefold(ldb, ldb, dn0);
561 if (edn0 == NULL) return 1;
563 edn1 = ldb_dn_explode_casefold(ldb, ldb, dn1);
564 if (edn1 == NULL) {
565 talloc_free(edn0);
566 return -1;
569 ret = ldb_dn_compare(ldb, edn0, edn1);
571 talloc_free(edn0);
572 talloc_free(edn1);
574 return ret;
578 casefold a dn. We need to casefold the attribute names, and canonicalize
579 attribute values of case insensitive attributes.
581 struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
583 struct ldb_dn *cedn;
584 int i, ret;
586 if (edn == NULL) return NULL;
588 cedn = ldb_dn_new(mem_ctx);
589 if (!cedn) {
590 return NULL;
593 cedn->comp_num = edn->comp_num;
594 cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num);
595 if (!cedn->components) {
596 talloc_free(cedn);
597 return NULL;
600 for (i = 0; i < edn->comp_num; i++) {
601 struct ldb_dn_component dc;
602 const struct ldb_attrib_handler *h;
604 memset(&dc, 0, sizeof(dc));
605 dc.name = ldb_attr_casefold(cedn->components, edn->components[i].name);
606 if (!dc.name) {
607 talloc_free(cedn);
608 return NULL;
611 h = ldb_attrib_handler(ldb, dc.name);
612 ret = h->canonicalise_fn(ldb, cedn->components,
613 &(edn->components[i].value),
614 &(dc.value));
615 if (ret != 0) {
616 talloc_free(cedn);
617 return NULL;
620 cedn->components[i] = dc;
623 return cedn;
626 struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, void *mem_ctx, const char *dn)
628 struct ldb_dn *edn, *cdn;
630 if (dn == NULL) return NULL;
632 edn = ldb_dn_explode(ldb, dn);
633 if (edn == NULL) return NULL;
635 cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
637 talloc_free(edn);
638 return cdn;
641 char *ldb_dn_linearize_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
643 struct ldb_dn *cdn;
644 char *dn;
646 if (edn == NULL) return NULL;
648 /* Special DNs */
649 if (ldb_dn_is_special(edn)) {
650 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
651 return dn;
654 cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
655 if (cdn == NULL) return NULL;
657 dn = ldb_dn_linearize(ldb, cdn);
658 if (dn == NULL) {
659 talloc_free(cdn);
660 return NULL;
663 talloc_free(cdn);
664 return dn;
667 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
669 struct ldb_dn_component dst;
671 memset(&dst, 0, sizeof(dst));
673 if (src == NULL) {
674 return dst;
677 dst.value = ldb_val_dup(mem_ctx, &(src->value));
678 if (dst.value.data == NULL) {
679 return dst;
682 dst.name = talloc_strdup(mem_ctx, src->name);
683 if (dst.name == NULL) {
684 talloc_free(dst.value.data);
685 dst.value.data = NULL;
688 return dst;
691 /* copy specified number of elements of a dn into a new one
692 element are copied from top level up to the unique rdn
693 num_el may be greater than dn->comp_num (see ldb_dn_make_child)
695 struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el)
697 struct ldb_dn *newdn;
698 int i, n, e;
700 if (dn == NULL) return NULL;
701 if (num_el <= 0) return NULL;
703 newdn = ldb_dn_new(mem_ctx);
704 LDB_DN_NULL_FAILED(newdn);
706 newdn->comp_num = num_el;
707 n = newdn->comp_num - 1;
708 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
709 if (newdn->components == NULL) goto failed;
711 if (dn->comp_num == 0) return newdn;
712 e = dn->comp_num - 1;
714 for (i = 0; i < newdn->comp_num; i++) {
715 newdn->components[n - i] = ldb_dn_copy_component(newdn->components,
716 &(dn->components[e - i]));
717 if ((e - i) == 0) {
718 return newdn;
722 return newdn;
724 failed:
725 talloc_free(newdn);
726 return NULL;
729 struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn)
731 if (dn == NULL) return NULL;
732 return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num);
735 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn)
737 if (dn == NULL) return NULL;
738 return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1);
741 struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
742 const char *val)
744 struct ldb_dn_component *dc;
746 if (attr == NULL || val == NULL) return NULL;
748 dc = talloc(mem_ctx, struct ldb_dn_component);
749 if (dc == NULL) return NULL;
751 dc->name = talloc_strdup(dc, attr);
752 if (dc->name == NULL) {
753 talloc_free(dc);
754 return NULL;
757 dc->value.data = (uint8_t *)talloc_strdup(dc, val);
758 if (dc->value.data == NULL) {
759 talloc_free(dc);
760 return NULL;
763 dc->value.length = strlen(val);
765 return dc;
768 struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
769 const char * value,
770 const struct ldb_dn *base)
772 struct ldb_dn *newdn;
773 if (! ldb_valid_attr_name(attr)) return NULL;
774 if (value == NULL || value == '\0') return NULL;
776 if (base != NULL) {
777 newdn = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1);
778 LDB_DN_NULL_FAILED(newdn);
779 } else {
780 newdn = ldb_dn_new(mem_ctx);
781 LDB_DN_NULL_FAILED(newdn);
783 newdn->comp_num = 1;
784 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
787 newdn->components[0].name = talloc_strdup(newdn->components, attr);
788 LDB_DN_NULL_FAILED(newdn->components[0].name);
790 newdn->components[0].value.data = (uint8_t *)talloc_strdup(newdn->components, value);
791 LDB_DN_NULL_FAILED(newdn->components[0].value.data);
792 newdn->components[0].value.length = strlen((char *)newdn->components[0].value.data);
794 return newdn;
796 failed:
797 talloc_free(newdn);
798 return NULL;
802 struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component,
803 const struct ldb_dn *base)
805 if (component == NULL) return NULL;
807 return ldb_dn_build_child(mem_ctx, component->name,
808 (char *)component->value.data, base);
811 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2)
813 int i;
814 struct ldb_dn *newdn;
816 if (dn2 == NULL && dn1 == NULL) {
817 return NULL;
820 if (dn2 == NULL) {
821 newdn = ldb_dn_new(mem_ctx);
822 LDB_DN_NULL_FAILED(newdn);
824 newdn->comp_num = dn1->comp_num;
825 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
826 } else {
827 int comp_num = dn2->comp_num;
828 if (dn1 != NULL) comp_num += dn1->comp_num;
829 newdn = ldb_dn_copy_partial(mem_ctx, dn2, comp_num);
830 LDB_DN_NULL_FAILED(newdn);
833 if (dn1 == NULL) {
834 return newdn;
837 for (i = 0; i < dn1->comp_num; i++) {
838 newdn->components[i] = ldb_dn_copy_component(newdn->components,
839 &(dn1->components[i]));
840 if (newdn->components[i].value.data == NULL) {
841 goto failed;
845 return newdn;
847 failed:
848 talloc_free(newdn);
849 return NULL;
852 struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...)
854 struct ldb_dn *dn, *dn1;
855 char *child_str;
856 va_list ap;
858 if (child_fmt == NULL) return NULL;
860 va_start(ap, child_fmt);
861 child_str = talloc_vasprintf(mem_ctx, child_fmt, ap);
862 va_end(ap);
864 if (child_str == NULL) return NULL;
866 dn1 = ldb_dn_explode(mem_ctx, child_str);
867 dn = ldb_dn_compose(mem_ctx, dn1, base);
869 talloc_free(child_str);
870 talloc_free(dn1);
872 return dn;
875 struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn)
877 struct ldb_dn_component *rdn;
879 if (dn == NULL) return NULL;
881 if (dn->comp_num < 1) {
882 return NULL;
885 rdn = talloc(mem_ctx, struct ldb_dn_component);
886 if (rdn == NULL) return NULL;
888 *rdn = ldb_dn_copy_component(mem_ctx, &dn->components[0]);
889 if (rdn->name == NULL) {
890 talloc_free(rdn);
891 return NULL;
894 return rdn;
897 /* Create a 'canonical name' string from a DN:
899 ie dc=samba,dc=org -> samba.org/
900 uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
902 There are two formats, the EX format has the last / replaced with a newline (\n).
905 static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) {
906 int i;
907 char *cracked = NULL;
909 /* Walk backwards down the DN, grabbing 'dc' components at first */
910 for (i = dn->comp_num - 1 ; i >= 0; i--) {
911 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
912 break;
914 if (cracked) {
915 cracked = talloc_asprintf(mem_ctx, "%s.%s",
916 ldb_dn_escape_value(mem_ctx, dn->components[i].value),
917 cracked);
918 } else {
919 cracked = ldb_dn_escape_value(mem_ctx, dn->components[i].value);
921 if (!cracked) {
922 return NULL;
926 /* Only domain components? Finish here */
927 if (i < 0) {
928 if (ex_format) {
929 cracked = talloc_asprintf(mem_ctx, "%s\n", cracked);
930 } else {
931 cracked = talloc_asprintf(mem_ctx, "%s/", cracked);
933 return cracked;
936 /* Now walk backwards appending remaining components */
937 for (; i > 0; i--) {
938 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked,
939 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
940 if (!cracked) {
941 return NULL;
945 /* Last one, possibly a newline for the 'ex' format */
946 if (ex_format) {
947 cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked,
948 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
949 } else {
950 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked,
951 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
953 return cracked;
956 /* Wrapper functions for the above, for the two different string formats */
957 char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
958 return ldb_dn_canonical(mem_ctx, dn, 0);
962 char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
963 return ldb_dn_canonical(mem_ctx, dn, 1);