r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / lib / ldb / common / ldb_dn.c
blob7a1d8a910b2b1429135bfec5ae64379b8d4c82a2
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 /**
45 internal ldb exploded dn structures
47 struct ldb_dn_component {
48 char *name;
49 struct ldb_val value;
52 struct ldb_dn {
53 int comp_num;
54 struct ldb_dn_component *components;
57 int ldb_dn_is_special(const struct ldb_dn *dn)
59 if (dn == NULL || dn->comp_num != 1) return 0;
61 return ! strcmp(dn->components[0].name, LDB_SPECIAL);
64 int ldb_dn_check_special(const struct ldb_dn *dn, const char *check)
66 if (dn == NULL || dn->comp_num != 1) return 0;
68 return ! strcmp((char *)dn->components[0].value.data, check);
71 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
73 const char *p, *s, *src;
74 char *d, *dst;
75 int len;
77 if (!value.length)
78 return NULL;
80 p = s = src = (const char *)value.data;
81 len = value.length;
83 /* allocate destination string, it will be at most 3 times the source */
84 dst = d = talloc_array(mem_ctx, char, len * 3 + 1);
85 LDB_DN_NULL_FAILED(dst);
87 while (p - src < len) {
89 p += strcspn(p, ",=\n+<>#;\\\"");
91 if (p - src == len) /* found no escapable chars */
92 break;
94 memcpy(d, s, p - s); /* copy the part of the string before the stop */
95 d += (p - s); /* move to current position */
97 if (*p) { /* it is a normal escapable character */
98 *d++ = '\\';
99 *d++ = *p++;
100 } else { /* we have a zero byte in the string */
101 strncpy(d, "\00", 3); /* escape the zero */
102 d = d + 3;
103 p++; /* skip the zero */
105 s = p; /* move forward */
108 /* copy the last part (with zero) and return */
109 memcpy(d, s, &src[len] - s + 1);
111 return dst;
113 failed:
114 talloc_free(dst);
115 return NULL;
118 static struct ldb_val ldb_dn_unescape_value(void *mem_ctx, const char *src)
120 struct ldb_val value;
121 unsigned x;
122 char *p, *dst = NULL, *end;
124 memset(&value, 0, sizeof(value));
126 LDB_DN_NULL_FAILED(src);
128 dst = p = (char *)talloc_memdup(mem_ctx, src, strlen(src) + 1);
129 LDB_DN_NULL_FAILED(dst);
131 end = &dst[strlen(dst)];
133 while (*p) {
134 p += strcspn(p, ",=\n+<>#;\\\"");
136 if (*p == '\\') {
137 if (strchr(",=\n+<>#;\\\"", p[1])) {
138 memmove(p, p + 1, end - (p + 1) + 1);
139 end--;
140 p++;
141 continue;
144 if (sscanf(p + 1, "%02x", &x) == 1) {
145 *p = (unsigned char)x;
146 memmove(p + 1, p + 3, end - (p + 3) + 1);
147 end -= 2;
148 p++;
149 continue;
153 /* a string with not escaped specials is invalid (tested) */
154 if (*p != '\0') {
155 goto failed;
159 value.length = end - dst;
160 value.data = (uint8_t *)dst;
161 return value;
163 failed:
164 talloc_free(dst);
165 return value;
168 /* check if the string contains quotes
169 * skips leading and trailing spaces
170 * - returns 0 if no quotes found
171 * - returns 1 if quotes are found and put their position
172 * in *quote_start and *quote_end parameters
173 * - return -1 if there are open quotes
176 static int get_quotes_position(const char *source, int *quote_start, int *quote_end)
178 const char *p;
180 if (source == NULL || quote_start == NULL || quote_end == NULL) return -1;
182 p = source;
184 /* check if there are quotes surrounding the value */
185 p += strspn(p, " \n"); /* skip white spaces */
187 if (*p == '\"') {
188 *quote_start = p - source;
190 p++;
191 while (*p != '\"') {
192 p = strchr(p, '\"');
193 LDB_DN_NULL_FAILED(p);
195 if (*(p - 1) == '\\')
196 p++;
199 *quote_end = p - source;
200 return 1;
203 return 0;
205 failed:
206 return -1;
209 static char *seek_to_separator(char *string, const char *separators)
211 char *p, *q;
212 int ret, qs, qe, escaped;
214 if (string == NULL || separators == NULL) return NULL;
216 p = strchr(string, '=');
217 LDB_DN_NULL_FAILED(p);
219 p++;
221 /* check if there are quotes surrounding the value */
223 ret = get_quotes_position(p, &qs, &qe);
224 if (ret == -1)
225 return NULL;
227 if (ret == 1) { /* quotes found */
229 p += qe; /* positioning after quotes */
230 p += strspn(p, " \n"); /* skip white spaces after the quote */
232 if (strcspn(p, separators) != 0) /* if there are characters between quotes */
233 return NULL; /* and separators, the dn is invalid */
235 return p; /* return on the separator */
238 /* no quotes found seek to separators */
239 q = p;
240 do {
241 escaped = 0;
242 ret = strcspn(q, separators);
244 if (q[ret - 1] == '\\') {
245 escaped = 1;
246 q = q + ret + 1;
248 } while (escaped);
250 if (ret == 0 && p == q) /* no separators ?! bail out */
251 return NULL;
253 return q + ret;
255 failed:
256 return NULL;
259 static char *ldb_dn_trim_string(char *string, const char *edge)
261 char *s, *p;
263 /* seek out edge from start of string */
264 s = string + strspn(string, edge);
266 /* backwards skip from end of string */
267 p = &s[strlen(s) - 1];
268 while (p > s && strchr(edge, *p)) {
269 *p = '\0';
270 p--;
273 return s;
276 /* we choosed to not support multpile valued components */
277 static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component)
279 struct ldb_dn_component dc;
280 char *p;
281 int ret, qs, qe;
283 memset(&dc, 0, sizeof(dc));
285 if (raw_component == NULL) {
286 return dc;
289 /* find attribute type/value separator */
290 p = strchr(raw_component, '=');
291 LDB_DN_NULL_FAILED(p);
293 *p++ = '\0'; /* terminate name and point to value */
295 /* copy and trim name in the component */
296 dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n"));
297 if (!dc.name)
298 return dc;
300 if (! ldb_valid_attr_name(dc.name)) {
301 goto failed;
304 ret = get_quotes_position(p, &qs, &qe);
306 switch (ret) {
307 case 0: /* no quotes trim the string */
308 p = ldb_dn_trim_string(p, " \n");
309 dc.value = ldb_dn_unescape_value(mem_ctx, p);
310 break;
312 case 1: /* quotes found get the unquoted string */
313 p[qe] = '\0';
314 p = p + qs + 1;
315 dc.value.length = strlen(p);
316 dc.value.data = (uint8_t *)talloc_memdup(mem_ctx, p,
317 dc.value.length + 1);
318 break;
320 default: /* mismatched quotes ot other error, bail out */
321 goto failed;
324 if (dc.value.length == 0) {
325 goto failed;
328 return dc;
330 failed:
331 talloc_free(dc.name);
332 dc.name = NULL;
333 return dc;
336 struct ldb_dn *ldb_dn_new(void *mem_ctx)
338 struct ldb_dn *edn;
340 edn = talloc(mem_ctx, struct ldb_dn);
341 LDB_DN_NULL_FAILED(edn);
343 /* Initially there are no components */
344 edn->comp_num = 0;
345 edn->components = NULL;
347 return edn;
349 failed:
350 return NULL;
354 explode a DN string into a ldb_dn structure
356 struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
358 struct ldb_dn *edn; /* the exploded dn */
359 char *pdn, *p;
361 if (dn == NULL) return NULL;
363 /* Allocate a structure to hold the exploded DN */
364 edn = ldb_dn_new(mem_ctx);
365 if (edn == NULL) {
366 return NULL;
369 pdn = NULL;
371 /* Empty DNs */
372 if (dn[0] == '\0') {
373 return edn;
376 /* Special DNs case */
377 if (dn[0] == '@') {
378 edn->comp_num = 1;
379 edn->components = talloc(edn, struct ldb_dn_component);
380 if (edn->components == NULL) goto failed;
381 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
382 if (edn->components[0].name == NULL) goto failed;
383 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
384 if (edn->components[0].value.data== NULL) goto failed;
385 edn->components[0].value.length = strlen(dn);
386 return edn;
389 pdn = p = talloc_strdup(edn, dn);
390 LDB_DN_NULL_FAILED(pdn);
392 /* get the components */
393 do {
394 char *t;
396 /* terminate the current component and return pointer to the next one */
397 t = seek_to_separator(p, ",;");
398 LDB_DN_NULL_FAILED(t);
400 if (*t) { /* here there is a separator */
401 *t = '\0'; /*terminate */
402 t++; /* a separtor means another component follows */
405 /* allocate space to hold the dn component */
406 edn->components = talloc_realloc(edn, edn->components,
407 struct ldb_dn_component,
408 edn->comp_num + 1);
409 if (edn->components == NULL)
410 goto failed;
412 /* store the exploded component in the main structure */
413 edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p);
414 LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name);
416 edn->comp_num++;
418 /* jump to the next component if any */
419 p = t;
421 } while(*p);
423 talloc_free(pdn);
424 return edn;
426 failed:
427 talloc_free(pdn);
428 talloc_free(edn);
429 return NULL;
432 struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn)
434 struct ldb_dn *edn; /* the exploded dn */
436 if (dn == NULL) return NULL;
438 if (strncasecmp(dn, "<GUID=", 6) == 0) {
439 /* this is special DN returned when the
440 * exploded_dn control is used
443 /* Allocate a structure to hold the exploded DN */
444 if (!(edn = ldb_dn_new(mem_ctx))) {
445 return NULL;
448 edn->comp_num = 1;
449 edn->components = talloc(edn, struct ldb_dn_component);
450 if (edn->components == NULL) goto failed;
451 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
452 if (edn->components[0].name == NULL) goto failed;
453 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
454 if (edn->components[0].value.data== NULL) goto failed;
455 edn->components[0].value.length = strlen(dn);
456 return edn;
460 return ldb_dn_explode(mem_ctx, dn);
462 failed:
463 talloc_free(edn);
464 return NULL;
467 char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn)
469 char *dn, *value;
470 int i;
472 if (edn == NULL) return NULL;
474 /* Special DNs */
475 if (ldb_dn_is_special(edn)) {
476 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
477 return dn;
480 dn = talloc_strdup(mem_ctx, "");
481 LDB_DN_NULL_FAILED(dn);
483 for (i = 0; i < edn->comp_num; i++) {
484 value = ldb_dn_escape_value(dn, edn->components[i].value);
485 LDB_DN_NULL_FAILED(value);
487 if (i == 0) {
488 dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value);
489 } else {
490 dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value);
492 LDB_DN_NULL_FAILED(dn);
494 talloc_free(value);
497 return dn;
499 failed:
500 talloc_free(dn);
501 return NULL;
504 /* Determine if dn is below base, in the ldap tree. Used for
505 * evaluating a subtree search.
506 * 0 if they match, otherwise non-zero
509 int ldb_dn_compare_base(struct ldb_context *ldb,
510 const struct ldb_dn *base,
511 const struct ldb_dn *dn)
513 int ret;
514 int n0, n1;
516 if (base == NULL || base->comp_num == 0) return 0;
517 if (dn == NULL || dn->comp_num == 0) return -1;
519 /* if the base has more componts than the dn, then they differ */
520 if (base->comp_num > dn->comp_num) {
521 return (dn->comp_num - base->comp_num);
524 n0 = base->comp_num - 1;
525 n1 = dn->comp_num - 1;
526 while (n0 >= 0 && n1 >= 0) {
527 const struct ldb_attrib_handler *h;
529 /* compare names (attribute names are guaranteed to be ASCII only) */
530 ret = ldb_attr_cmp(base->components[n0].name,
531 dn->components[n1].name);
532 if (ret) {
533 return ret;
536 /* names match, compare values */
537 h = ldb_attrib_handler(ldb, base->components[n0].name);
538 ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value),
539 &(dn->components[n1].value));
540 if (ret) {
541 return ret;
543 n1--;
544 n0--;
547 return 0;
550 /* compare DNs using casefolding compare functions.
552 If they match, then return 0
555 int ldb_dn_compare(struct ldb_context *ldb,
556 const struct ldb_dn *edn0,
557 const struct ldb_dn *edn1)
559 if (edn0 == NULL || edn1 == NULL) return edn1 - edn0;
561 if (edn0->comp_num != edn1->comp_num)
562 return (edn1->comp_num - edn0->comp_num);
564 return ldb_dn_compare_base(ldb, edn0, edn1);
567 int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1)
569 struct ldb_dn *edn0;
570 struct ldb_dn *edn1;
571 int ret;
573 if (dn0 == NULL || dn1 == NULL) return dn1 - dn0;
575 edn0 = ldb_dn_explode_casefold(ldb, ldb, dn0);
576 if (edn0 == NULL) return 1;
578 edn1 = ldb_dn_explode_casefold(ldb, ldb, dn1);
579 if (edn1 == NULL) {
580 talloc_free(edn0);
581 return -1;
584 ret = ldb_dn_compare(ldb, edn0, edn1);
586 talloc_free(edn0);
587 talloc_free(edn1);
589 return ret;
593 casefold a dn. We need to casefold the attribute names, and canonicalize
594 attribute values of case insensitive attributes.
596 struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
598 struct ldb_dn *cedn;
599 int i, ret;
601 if (edn == NULL) return NULL;
603 cedn = ldb_dn_new(mem_ctx);
604 if (!cedn) {
605 return NULL;
608 cedn->comp_num = edn->comp_num;
609 cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num);
610 if (!cedn->components) {
611 talloc_free(cedn);
612 return NULL;
615 for (i = 0; i < edn->comp_num; i++) {
616 struct ldb_dn_component dc;
617 const struct ldb_attrib_handler *h;
619 memset(&dc, 0, sizeof(dc));
620 dc.name = ldb_attr_casefold(cedn->components, edn->components[i].name);
621 if (!dc.name) {
622 talloc_free(cedn);
623 return NULL;
626 h = ldb_attrib_handler(ldb, dc.name);
627 ret = h->canonicalise_fn(ldb, cedn->components,
628 &(edn->components[i].value),
629 &(dc.value));
630 if (ret != 0) {
631 talloc_free(cedn);
632 return NULL;
635 cedn->components[i] = dc;
638 return cedn;
641 struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, void *mem_ctx, const char *dn)
643 struct ldb_dn *edn, *cdn;
645 if (dn == NULL) return NULL;
647 edn = ldb_dn_explode(ldb, dn);
648 if (edn == NULL) return NULL;
650 cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
652 talloc_free(edn);
653 return cdn;
656 char *ldb_dn_linearize_casefold(struct ldb_context *ldb, void *mem_ctx, const struct ldb_dn *edn)
658 struct ldb_dn *cdn;
659 char *dn;
661 if (edn == NULL) return NULL;
663 /* Special DNs */
664 if (ldb_dn_is_special(edn)) {
665 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
666 return dn;
669 cdn = ldb_dn_casefold(ldb, mem_ctx, edn);
670 if (cdn == NULL) return NULL;
672 dn = ldb_dn_linearize(ldb, cdn);
673 if (dn == NULL) {
674 talloc_free(cdn);
675 return NULL;
678 talloc_free(cdn);
679 return dn;
682 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
684 struct ldb_dn_component dst;
686 memset(&dst, 0, sizeof(dst));
688 if (src == NULL) {
689 return dst;
692 dst.value = ldb_val_dup(mem_ctx, &(src->value));
693 if (dst.value.data == NULL) {
694 return dst;
697 dst.name = talloc_strdup(mem_ctx, src->name);
698 if (dst.name == NULL) {
699 talloc_free(dst.value.data);
700 dst.value.data = NULL;
703 return dst;
706 /* Copy a DN but replace the old with the new base DN. */
707 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)
709 struct ldb_dn *new_dn;
710 int i, offset;
712 /* Perhaps we don't need to rebase at all? */
713 if (!old_base || !new_base) {
714 return ldb_dn_copy(mem_ctx, old);
717 offset = old->comp_num - old_base->comp_num;
718 if (!(new_dn = ldb_dn_copy_partial(mem_ctx, new_base,
719 offset + new_base->comp_num))) {
720 return NULL;
722 for (i = 0; i < offset; i++) {
723 new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &(old->components[i]));
726 return new_dn;
729 /* copy specified number of elements of a dn into a new one
730 element are copied from top level up to the unique rdn
731 num_el may be greater than dn->comp_num (see ldb_dn_make_child)
733 struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el)
735 struct ldb_dn *newdn;
736 int i, n, e;
738 if (dn == NULL) return NULL;
739 if (num_el <= 0) return NULL;
741 newdn = ldb_dn_new(mem_ctx);
742 LDB_DN_NULL_FAILED(newdn);
744 newdn->comp_num = num_el;
745 n = newdn->comp_num - 1;
746 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
747 if (newdn->components == NULL) goto failed;
749 if (dn->comp_num == 0) return newdn;
750 e = dn->comp_num - 1;
752 for (i = 0; i < newdn->comp_num; i++) {
753 newdn->components[n - i] = ldb_dn_copy_component(newdn->components,
754 &(dn->components[e - i]));
755 if ((e - i) == 0) {
756 return newdn;
760 return newdn;
762 failed:
763 talloc_free(newdn);
764 return NULL;
767 struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn)
769 if (dn == NULL) return NULL;
770 return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num);
773 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn)
775 if (dn == NULL) return NULL;
776 return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1);
779 struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
780 const char *val)
782 struct ldb_dn_component *dc;
784 if (attr == NULL || val == NULL) return NULL;
786 dc = talloc(mem_ctx, struct ldb_dn_component);
787 if (dc == NULL) return NULL;
789 dc->name = talloc_strdup(dc, attr);
790 if (dc->name == NULL) {
791 talloc_free(dc);
792 return NULL;
795 dc->value.data = (uint8_t *)talloc_strdup(dc, val);
796 if (dc->value.data == NULL) {
797 talloc_free(dc);
798 return NULL;
801 dc->value.length = strlen(val);
803 return dc;
806 struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
807 const char * value,
808 const struct ldb_dn *base)
810 struct ldb_dn *newdn;
811 if (! ldb_valid_attr_name(attr)) return NULL;
812 if (value == NULL || value == '\0') return NULL;
814 if (base != NULL) {
815 newdn = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1);
816 LDB_DN_NULL_FAILED(newdn);
817 } else {
818 newdn = ldb_dn_new(mem_ctx);
819 LDB_DN_NULL_FAILED(newdn);
821 newdn->comp_num = 1;
822 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
823 LDB_DN_NULL_FAILED(newdn->components);
826 newdn->components[0].name = talloc_strdup(newdn->components, attr);
827 LDB_DN_NULL_FAILED(newdn->components[0].name);
829 newdn->components[0].value.data = (uint8_t *)talloc_strdup(newdn->components, value);
830 LDB_DN_NULL_FAILED(newdn->components[0].value.data);
831 newdn->components[0].value.length = strlen((char *)newdn->components[0].value.data);
833 return newdn;
835 failed:
836 talloc_free(newdn);
837 return NULL;
841 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2)
843 int i;
844 struct ldb_dn *newdn;
846 if (dn2 == NULL && dn1 == NULL) {
847 return NULL;
850 if (dn2 == NULL) {
851 newdn = ldb_dn_new(mem_ctx);
852 LDB_DN_NULL_FAILED(newdn);
854 newdn->comp_num = dn1->comp_num;
855 newdn->components = talloc_array(newdn, struct ldb_dn_component, newdn->comp_num);
856 LDB_DN_NULL_FAILED(newdn->components);
857 } else {
858 int comp_num = dn2->comp_num;
859 if (dn1 != NULL) comp_num += dn1->comp_num;
860 newdn = ldb_dn_copy_partial(mem_ctx, dn2, comp_num);
861 LDB_DN_NULL_FAILED(newdn);
864 if (dn1 == NULL) {
865 return newdn;
868 for (i = 0; i < dn1->comp_num; i++) {
869 newdn->components[i] = ldb_dn_copy_component(newdn->components,
870 &(dn1->components[i]));
871 if (newdn->components[i].value.data == NULL) {
872 goto failed;
876 return newdn;
878 failed:
879 talloc_free(newdn);
880 return NULL;
883 struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...)
885 struct ldb_dn *dn, *dn1;
886 char *child_str;
887 va_list ap;
889 if (child_fmt == NULL) return NULL;
891 va_start(ap, child_fmt);
892 child_str = talloc_vasprintf(mem_ctx, child_fmt, ap);
893 va_end(ap);
895 if (child_str == NULL) return NULL;
897 dn1 = ldb_dn_explode(mem_ctx, child_str);
898 dn = ldb_dn_compose(mem_ctx, dn1, base);
900 talloc_free(child_str);
901 talloc_free(dn1);
903 return dn;
906 /* Create a 'canonical name' string from a DN:
908 ie dc=samba,dc=org -> samba.org/
909 uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
911 There are two formats, the EX format has the last / replaced with a newline (\n).
914 static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) {
915 int i;
916 char *cracked = NULL;
918 /* Walk backwards down the DN, grabbing 'dc' components at first */
919 for (i = dn->comp_num - 1 ; i >= 0; i--) {
920 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
921 break;
923 if (cracked) {
924 cracked = talloc_asprintf(mem_ctx, "%s.%s",
925 ldb_dn_escape_value(mem_ctx, dn->components[i].value),
926 cracked);
927 } else {
928 cracked = ldb_dn_escape_value(mem_ctx, dn->components[i].value);
930 if (!cracked) {
931 return NULL;
935 /* Only domain components? Finish here */
936 if (i < 0) {
937 if (ex_format) {
938 cracked = talloc_asprintf(mem_ctx, "%s\n", cracked);
939 } else {
940 cracked = talloc_asprintf(mem_ctx, "%s/", cracked);
942 return cracked;
945 /* Now walk backwards appending remaining components */
946 for (; i > 0; i--) {
947 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked,
948 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
949 if (!cracked) {
950 return NULL;
954 /* Last one, possibly a newline for the 'ex' format */
955 if (ex_format) {
956 cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked,
957 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
958 } else {
959 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked,
960 ldb_dn_escape_value(mem_ctx, dn->components[i].value));
962 return cracked;
965 /* Wrapper functions for the above, for the two different string formats */
966 char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
967 return ldb_dn_canonical(mem_ctx, dn, 0);
971 char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
972 return ldb_dn_canonical(mem_ctx, dn, 1);
975 int ldb_dn_get_comp_num(const struct ldb_dn *dn)
977 return dn->comp_num;
980 const char *ldb_dn_get_component_name(const struct ldb_dn *dn, unsigned int num)
982 if (num >= dn->comp_num) return NULL;
983 return dn->components[num].name;
986 const struct ldb_val *ldb_dn_get_component_val(const struct ldb_dn *dn, unsigned int num)
988 if (num >= dn->comp_num) return NULL;
989 return &dn->components[num].value;
992 const char *ldb_dn_get_rdn_name(const struct ldb_dn *dn) {
993 if (dn->comp_num == 0) return NULL;
994 return dn->components[0].name;
997 const struct ldb_val *ldb_dn_get_rdn_val(const struct ldb_dn *dn) {
998 if (dn->comp_num == 0) return NULL;
999 return &dn->components[0].value;
1002 int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
1004 char *n;
1005 struct ldb_val v;
1007 if (num >= dn->comp_num) {
1008 return LDB_ERR_OTHER;
1011 n = talloc_strdup(dn, name);
1012 if ( ! n) {
1013 return LDB_ERR_OTHER;
1016 v.length = val.length;
1017 v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1018 if ( ! v.data) {
1019 return LDB_ERR_OTHER;
1022 talloc_free(dn->components[num].name);
1023 talloc_free(dn->components[num].value.data);
1024 dn->components[num].name = n;
1025 dn->components[num].value = v;
1027 return LDB_SUCCESS;