r12748: Fix wrong handling of separation characters for RDNs
[kai/samba.git] / source / 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, *q;
218         int ret, qs, qe, escaped;
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         q = p;
246         do {
247                 escaped = 0;
248                 ret = strcspn(q, separators);
249                 
250                 if (q[ret - 1] == '\\') {
251                         escaped = 1;
252                         q = q + ret + 1;
253                 }
254         } while (escaped);
255
256         if (ret == 0 && p == q) /* no separators ?! bail out */
257                 return NULL;
258
259         return q + ret;
260
261 failed:
262         return NULL;
263 }
264
265 static char *ldb_dn_trim_string(char *string, const char *edge)
266 {
267         char *s, *p;
268
269         /* seek out edge from start of string */
270         s = string + strspn(string, edge);
271
272         /* backwards skip from end of string */
273         p = &s[strlen(s) - 1];
274         while (p > s && strchr(edge, *p)) {
275                 *p = '\0';
276                 p--;
277         }
278
279         return s;
280 }
281
282 /* we choosed to not support multpile valued components */
283 static struct ldb_dn_component ldb_dn_explode_component(void *mem_ctx, char *raw_component)
284 {
285         struct ldb_dn_component dc;
286         char *p;
287         int ret, qs, qe;
288
289         memset(&dc, 0, sizeof(dc));
290
291         if (raw_component == NULL) {
292                 return dc;
293         }
294
295         /* find attribute type/value separator */
296         p = strchr(raw_component, '=');
297         LDB_DN_NULL_FAILED(p);
298
299         *p++ = '\0'; /* terminate name and point to value */
300
301         /* copy and trim name in the component */
302         dc.name = talloc_strdup(mem_ctx, ldb_dn_trim_string(raw_component, " \n"));
303         if (!dc.name)
304                 return dc;
305
306         if (! ldb_dn_is_valid_attribute_name(dc.name)) {
307                 goto failed;
308         }
309
310         ret = get_quotes_position(p, &qs, &qe);
311
312         switch (ret) {
313         case 0: /* no quotes trim the string */
314                 p = ldb_dn_trim_string(p, " \n");
315                 dc.value = ldb_dn_unescape_value(mem_ctx, p);
316                 break;
317
318         case 1: /* quotes found get the unquoted string */
319                 p[qe] = '\0';
320                 p = p + qs + 1;
321                 dc.value.length = strlen(p);
322                 dc.value.data = talloc_memdup(mem_ctx, p, dc.value.length + 1);
323                 break;
324
325         default: /* mismatched quotes ot other error, bail out */
326                 goto failed;
327         }
328
329         if (dc.value.length == 0) {
330                 goto failed;
331         }
332
333         return dc;
334
335 failed:
336         talloc_free(dc.name);
337         dc.name = NULL;
338         return dc;
339 }
340
341 struct ldb_dn *ldb_dn_new(void *mem_ctx)
342 {
343         struct ldb_dn *edn;
344
345         edn = talloc(mem_ctx, struct ldb_dn);
346         LDB_DN_NULL_FAILED(edn);
347
348         /* Initially there are no components */
349         edn->comp_num = 0;
350         edn->components = NULL;
351
352         return edn;
353
354 failed:
355         return NULL;
356 }
357
358 struct ldb_dn *ldb_dn_explode(void *mem_ctx, const char *dn)
359 {
360         struct ldb_dn *edn; /* the exploded dn */
361         char *pdn, *p;
362
363         if (dn == NULL) return NULL;
364
365         /* Allocate a structure to hold the exploded DN */
366         edn = ldb_dn_new(mem_ctx);
367         pdn = NULL;
368
369         /* Empty DNs */
370         if (dn[0] == '\0') {
371                 return edn;
372         }
373
374         /* Special DNs case */
375         if (dn[0] == '@') {
376                 edn->comp_num = 1;
377                 edn->components = talloc(edn, struct ldb_dn_component);
378                 if (edn->components == NULL) goto failed;
379                 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
380                 if (edn->components[0].name == NULL) goto failed;
381                 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
382                 if (edn->components[0].value.data== NULL) goto failed;
383                 edn->components[0].value.length = strlen(dn);
384                 return edn;
385         }
386
387         pdn = p = talloc_strdup(edn, dn);
388         LDB_DN_NULL_FAILED(pdn);
389
390         /* get the components */
391         do {
392                 char *t;
393
394                 /* terminate the current component and return pointer to the next one */
395                 t = seek_to_separator(p, ",;");
396                 LDB_DN_NULL_FAILED(t);
397
398                 if (*t) { /* here there is a separator */
399                         *t = '\0'; /*terminate */
400                         t++; /* a separtor means another component follows */
401                 }
402
403                 /* allocate space to hold the dn component */
404                 edn->components = talloc_realloc(edn, edn->components,
405                                                  struct ldb_dn_component,
406                                                  edn->comp_num + 1);
407                 if (edn->components == NULL)
408                         goto failed;
409
410                 /* store the exploded component in the main structure */
411                 edn->components[edn->comp_num] = ldb_dn_explode_component(edn, p);
412                 LDB_DN_NULL_FAILED(edn->components[edn->comp_num].name);
413
414                 edn->comp_num++;
415
416                 /* jump to the next component if any */
417                 p = t;
418
419         } while(*p);
420
421         talloc_free(pdn);
422         return edn;
423
424 failed:
425         talloc_free(pdn);
426         talloc_free(edn);
427         return NULL;
428 }
429
430 struct ldb_dn *ldb_dn_explode_or_special(void *mem_ctx, const char *dn)
431 {
432         struct ldb_dn *edn; /* the exploded dn */
433
434         if (dn == NULL) return NULL;
435
436         if (strncasecmp(dn, "<GUID=", 6) == 0) {
437                 /* this is special DN returned when the
438                  * exploded_dn control is used
439                  */
440
441                 /* Allocate a structure to hold the exploded DN */
442                 edn = ldb_dn_new(mem_ctx);
443
444                 edn->comp_num = 1;
445                 edn->components = talloc(edn, struct ldb_dn_component);
446                 if (edn->components == NULL) goto failed;
447                 edn->components[0].name = talloc_strdup(edn->components, LDB_SPECIAL);
448                 if (edn->components[0].name == NULL) goto failed;
449                 edn->components[0].value.data = (uint8_t *)talloc_strdup(edn->components, dn);
450                 if (edn->components[0].value.data== NULL) goto failed;
451                 edn->components[0].value.length = strlen(dn);
452                 return edn;
453
454         }
455         
456         return ldb_dn_explode(mem_ctx, dn);
457
458 failed:
459         talloc_free(edn);
460         return NULL;
461 }
462
463 char *ldb_dn_linearize(void *mem_ctx, const struct ldb_dn *edn)
464 {
465         char *dn, *value;
466         int i;
467
468         if (edn == NULL) return NULL;
469
470         /* Special DNs */
471         if (ldb_dn_is_special(edn)) {
472                 dn = talloc_strdup(mem_ctx, (char *)edn->components[0].value.data);
473                 return dn;
474         }
475
476         dn = talloc_strdup(mem_ctx, "");
477         LDB_DN_NULL_FAILED(dn);
478
479         for (i = 0; i < edn->comp_num; i++) {
480                 value = ldb_dn_escape_value(dn, edn->components[i].value);
481                 LDB_DN_NULL_FAILED(value);
482
483                 if (i == 0) {
484                         dn = talloc_asprintf_append(dn, "%s=%s", edn->components[i].name, value);
485                 } else {
486                         dn = talloc_asprintf_append(dn, ",%s=%s", edn->components[i].name, value);
487                 }
488                 LDB_DN_NULL_FAILED(dn);
489
490                 talloc_free(value);
491         }
492
493         return dn;
494
495 failed:
496         talloc_free(dn);
497         return NULL;
498 }
499
500 /* compare DNs using casefolding compare functions */
501
502 int ldb_dn_compare_base(struct ldb_context *ldb,
503                    const struct ldb_dn *base,
504                    const struct ldb_dn *dn)
505 {
506         int ret;
507         int n0, n1;
508
509         if (base->comp_num > dn->comp_num) {
510                 return (dn->comp_num - base->comp_num);
511         }
512
513         if (base == NULL || base->comp_num == 0) return 0;
514         if (dn == NULL || dn->comp_num == 0) return -1;
515         if (base->comp_num > dn->comp_num) return -1;
516
517         /* if the number of components doesn't match they differ */
518         n0 = base->comp_num - 1;
519         n1 = dn->comp_num - 1;
520         while (n0 >= 0 && n1 >= 0) {
521                 const struct ldb_attrib_handler *h;
522
523                 /* compare names (attribute names are guaranteed to be ASCII only) */
524                 ret = ldb_caseless_cmp(base->components[n0].name,
525                                        dn->components[n1].name);
526                 if (ret) {
527                         return ret;
528                 }
529
530                 /* names match, compare values */
531                 h = ldb_attrib_handler(ldb, base->components[n0].name);
532                 ret = h->comparison_fn(ldb, ldb, &(base->components[n0].value),
533                                                   &(dn->components[n1].value));
534                 if (ret) {
535                         return ret;
536                 }
537                 n1--;
538                 n0--;
539         }
540
541         return 0;
542 }
543
544 int ldb_dn_compare(struct ldb_context *ldb,
545                    const struct ldb_dn *edn0,
546                    const struct ldb_dn *edn1)
547 {
548         if (edn0 == NULL || edn1 == NULL) return edn1 - edn0;
549
550         if (edn0->comp_num != edn1->comp_num)
551                 return (edn1->comp_num - edn0->comp_num);
552
553         return ldb_dn_compare_base(ldb, edn0, edn1);
554 }
555
556 int ldb_dn_cmp(struct ldb_context *ldb, const char *dn0, const char *dn1)
557 {
558         struct ldb_dn *edn0;
559         struct ldb_dn *edn1;
560         int ret;
561
562         if (dn0 == NULL || dn1 == NULL) return dn1 - dn0;
563
564         edn0 = ldb_dn_explode_casefold(ldb, dn0);
565         if (edn0 == NULL) return 1;
566
567         edn1 = ldb_dn_explode_casefold(ldb, dn1);
568         if (edn1 == NULL) {
569                 talloc_free(edn0);
570                 return -1;
571         }
572
573         ret = ldb_dn_compare(ldb, edn0, edn1);
574
575         talloc_free(edn0);
576         talloc_free(edn1);
577
578         return ret;
579 }
580
581 /*
582   casefold a dn. We need to casefold the attribute names, and canonicalize 
583   attribute values of case insensitive attributes.
584 */
585 struct ldb_dn *ldb_dn_casefold(struct ldb_context *ldb, const struct ldb_dn *edn)
586 {
587         struct ldb_dn *cedn;
588         int i;
589
590         if (edn == NULL) return NULL;
591
592         cedn = ldb_dn_new(ldb);
593         LDB_DN_NULL_FAILED(cedn);
594
595         cedn->comp_num = edn->comp_num;
596         cedn->components = talloc_array(cedn, struct ldb_dn_component, edn->comp_num);
597         LDB_DN_NULL_FAILED(cedn->components);
598
599         for (i = 0; i < edn->comp_num; i++) {
600                 struct ldb_dn_component dc;
601                 const struct ldb_attrib_handler *h;
602
603                 dc.name = ldb_casefold(cedn, edn->components[i].name);
604                 LDB_DN_NULL_FAILED(dc.name);
605
606                 h = ldb_attrib_handler(ldb, dc.name);
607                 if (h->canonicalise_fn(ldb, cedn, &(edn->components[i].value), &(dc.value)) != 0) {
608                         goto failed;
609                 }
610
611                 cedn->components[i] = dc;
612         }
613
614         return cedn;
615
616 failed:
617         talloc_free(cedn);
618         return NULL;
619 }
620
621 struct ldb_dn *ldb_dn_explode_casefold(struct ldb_context *ldb, const char *dn)
622 {
623         struct ldb_dn *edn, *cdn;
624
625         if (dn == NULL) return NULL;
626
627         edn = ldb_dn_explode(ldb, dn);
628         if (edn == NULL) return NULL;
629
630         cdn = ldb_dn_casefold(ldb, edn);
631         
632         talloc_free(edn);
633         return cdn;
634 }
635
636 char *ldb_dn_linearize_casefold(struct ldb_context *ldb, const struct ldb_dn *edn)
637 {
638         struct ldb_dn *cdn;
639         char *dn;
640
641         if (edn == NULL) return NULL;
642
643         /* Special DNs */
644         if (ldb_dn_is_special(edn)) {
645                 dn = talloc_strdup(ldb, (char *)edn->components[0].value.data);
646                 return dn;
647         }
648
649         cdn = ldb_dn_casefold(ldb, edn);
650         if (cdn == NULL) return NULL;
651
652         dn = ldb_dn_linearize(ldb, cdn);
653         if (dn == NULL) {
654                 talloc_free(cdn);
655                 return NULL;
656         }
657
658         talloc_free(cdn);
659         return dn;
660 }
661
662 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
663 {
664         struct ldb_dn_component dst;
665
666         memset(&dst, 0, sizeof(dst));
667
668         if (src == NULL) {
669                 return dst;
670         }
671
672         dst.value = ldb_val_dup(mem_ctx, &(src->value));
673         if (dst.value.data == NULL) {
674                 return dst;
675         }
676
677         dst.name = talloc_strdup(mem_ctx, src->name);
678         if (dst.name == NULL) {
679                 talloc_free(dst.value.data);
680         }
681
682         return dst;
683 }
684
685 /* copy specified number of elements of a dn into a new one
686    element are copied from top level up to the unique rdn
687    num_el may be greater then dn->comp_num (see ldb_dn_make_child)
688 */
689 struct ldb_dn *ldb_dn_copy_partial(void *mem_ctx, const struct ldb_dn *dn, int num_el)
690 {
691         struct ldb_dn *new;
692         int i, n, e;
693
694         if (dn == NULL) return NULL;
695         if (num_el <= 0) return NULL;
696
697         new = ldb_dn_new(mem_ctx);
698         LDB_DN_NULL_FAILED(new);
699
700         new->comp_num = num_el;
701         n = new->comp_num - 1;
702         new->components = talloc_array(new, struct ldb_dn_component, new->comp_num);
703
704         if (dn->comp_num == 0) return new;
705         e = dn->comp_num - 1;
706
707         for (i = 0; i < new->comp_num; i++) {
708                 new->components[n - i] = ldb_dn_copy_component(new->components,
709                                                                 &(dn->components[e - i]));
710                 if ((e - i) == 0) {
711                         return new;
712                 }
713         }
714
715         return new;
716
717 failed:
718         talloc_free(new);
719         return NULL;
720 }
721
722 struct ldb_dn *ldb_dn_copy(void *mem_ctx, const struct ldb_dn *dn)
723 {
724         if (dn == NULL) return NULL;
725         return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num);
726 }
727
728 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, const struct ldb_dn *dn)
729 {
730         if (dn == NULL) return NULL;
731         return ldb_dn_copy_partial(mem_ctx, dn, dn->comp_num - 1);
732 }
733
734 struct ldb_dn_component *ldb_dn_build_component(void *mem_ctx, const char *attr,
735                                                 const char *val)
736 {
737         struct ldb_dn_component *dc;
738
739         if (attr == NULL || val == NULL) return NULL;
740
741         dc = talloc(mem_ctx, struct ldb_dn_component);
742         if (dc == NULL) return NULL;
743
744         dc->name = talloc_strdup(dc, attr);
745         if (dc->name ==  NULL) {
746                 talloc_free(dc);
747                 return NULL;
748         }
749
750         dc->value.data = (uint8_t *)talloc_strdup(dc, val);
751         if (dc->value.data ==  NULL) {
752                 talloc_free(dc);
753                 return NULL;
754         }
755
756         dc->value.length = strlen(val);
757
758         return dc;
759 }
760
761 struct ldb_dn *ldb_dn_build_child(void *mem_ctx, const char *attr,
762                                                  const char * value,
763                                                  const struct ldb_dn *base)
764 {
765         struct ldb_dn *new;
766         if (! ldb_dn_is_valid_attribute_name(attr)) return NULL;
767         if (value == NULL || value == '\0') return NULL; 
768
769         if (base != NULL) {
770                 new = ldb_dn_copy_partial(mem_ctx, base, base->comp_num + 1);
771                 LDB_DN_NULL_FAILED(new);
772         } else {
773                 new = ldb_dn_new(mem_ctx);
774                 LDB_DN_NULL_FAILED(new);
775
776                 new->comp_num = 1;
777                 new->components = talloc_array(new, struct ldb_dn_component, new->comp_num);
778         }
779
780         new->components[0].name = talloc_strdup(new->components, attr);
781         LDB_DN_NULL_FAILED(new->components[0].name);
782
783         new->components[0].value.data = (uint8_t *)talloc_strdup(new->components, value);
784         LDB_DN_NULL_FAILED(new->components[0].value.data);
785         new->components[0].value.length = strlen((char *)new->components[0].value.data);
786
787         return new;
788
789 failed:
790         talloc_free(new);
791         return NULL;
792
793 }
794
795 struct ldb_dn *ldb_dn_make_child(void *mem_ctx, const struct ldb_dn_component *component,
796                                                 const struct ldb_dn *base)
797 {
798         if (component == NULL) return NULL;
799
800         return ldb_dn_build_child(mem_ctx, component->name, 
801                                   (char *)component->value.data, base);
802 }
803
804 struct ldb_dn *ldb_dn_compose(void *mem_ctx, const struct ldb_dn *dn1, const struct ldb_dn *dn2)
805 {
806         int i;
807         struct ldb_dn *new;
808
809         if (dn2 == NULL && dn1 == NULL) {
810                 return NULL;
811         }
812
813         if (dn2 == NULL) {
814                 new = ldb_dn_new(mem_ctx);
815                 LDB_DN_NULL_FAILED(new);
816
817                 new->comp_num = dn1->comp_num;
818                 new->components = talloc_array(new, struct ldb_dn_component, new->comp_num);
819         } else {
820                 int comp_num = dn2->comp_num;
821                 if (dn1 != NULL) comp_num += dn1->comp_num;
822                 new = ldb_dn_copy_partial(mem_ctx, dn2, comp_num);
823         }
824
825         if (dn1 == NULL) {
826                 return new;
827         }
828
829         for (i = 0; i < dn1->comp_num; i++) {
830                 new->components[i] = ldb_dn_copy_component(new->components,
831                                                            &(dn1->components[i]));
832         }
833
834         return new;
835
836 failed:
837         talloc_free(new);
838         return NULL;
839 }
840
841 struct ldb_dn *ldb_dn_string_compose(void *mem_ctx, const struct ldb_dn *base, const char *child_fmt, ...)
842 {
843         struct ldb_dn *dn;
844         char *child_str;
845         va_list ap;
846         int ret;
847         
848         if (child_fmt == NULL) return NULL;
849
850         va_start(ap, child_fmt);
851         ret = vasprintf(&child_str, child_fmt, ap);
852         va_end(ap);
853
854         if (ret <= 0) return NULL;
855
856         dn = ldb_dn_compose(mem_ctx, ldb_dn_explode(mem_ctx, child_str), base);
857
858         free(child_str);
859
860         return dn;
861 }
862
863 struct ldb_dn_component *ldb_dn_get_rdn(void *mem_ctx, const struct ldb_dn *dn)
864 {
865         struct ldb_dn_component *rdn;
866
867         if (dn == NULL) return NULL;
868
869         if (dn->comp_num < 1) {
870                 return NULL;
871         }
872
873         rdn = talloc(mem_ctx, struct ldb_dn_component);
874         if (rdn == NULL) return NULL;
875
876         *rdn = ldb_dn_copy_component(mem_ctx, &dn->components[0]);
877         if (rdn->name == NULL) {
878                 talloc_free(rdn);
879                 return NULL;
880         }
881
882         return rdn;
883 }
884
885 /* Create a 'canonical name' string from a DN:
886
887    ie dc=samba,dc=org -> samba.org/
888       uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
889
890    There are two formats, the EX format has the last / replaced with a newline (\n).
891
892 */
893 static char *ldb_dn_canonical(void *mem_ctx, const struct ldb_dn *dn, int ex_format) {
894         int i;
895         char *cracked = NULL;
896
897         /* Walk backwards down the DN, grabbing 'dc' components at first */
898         for (i = dn->comp_num - 1 ; i >= 0; i--) {
899                 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
900                         break;
901                 }
902                 if (cracked) {
903                         cracked = talloc_asprintf(mem_ctx, "%s.%s",
904                                                   ldb_dn_escape_value(mem_ctx, dn->components[i].value),
905                                                   cracked);
906                 } else {
907                         cracked = ldb_dn_escape_value(mem_ctx, dn->components[i].value);
908                 }
909                 if (!cracked) {
910                         return NULL;
911                 }
912         }
913
914         /* Only domain components?  Finish here */
915         if (i < 0) {
916                 if (ex_format) {
917                         cracked = talloc_asprintf(mem_ctx, "%s\n", cracked);
918                 } else {
919                         cracked = talloc_asprintf(mem_ctx, "%s/", cracked);
920                 }
921                 return cracked;
922         }
923
924         /* Now walk backwards appending remaining components */
925         for (; i > 0; i--) {
926                 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
927                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
928                 if (!cracked) {
929                         return NULL;
930                 }
931         }
932
933         /* Last one, possibly a newline for the 'ex' format */
934         if (ex_format) {
935                 cracked = talloc_asprintf(mem_ctx, "%s\n%s", cracked, 
936                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
937         } else {
938                 cracked = talloc_asprintf(mem_ctx, "%s/%s", cracked, 
939                                           ldb_dn_escape_value(mem_ctx, dn->components[i].value));
940         }
941         return cracked;
942 }
943
944 /* Wrapper functions for the above, for the two different string formats */
945 char *ldb_dn_canonical_string(void *mem_ctx, const struct ldb_dn *dn) {
946         return ldb_dn_canonical(mem_ctx, dn, 0);
947
948 }
949
950 char *ldb_dn_canonical_ex_string(void *mem_ctx, const struct ldb_dn *dn) {
951         return ldb_dn_canonical(mem_ctx, dn, 1);
952 }