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