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