Add support in the ldb_dn.c code for MS-ADTS:3.1.1.5.1.2 Naming Constraints
[sfrench/samba-autobuild/.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 3 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, see <http://www.gnu.org/licenses/>.
22 */
23
24 /*
25  *  Name: ldb
26  *
27  *  Component: ldb dn creation and manipulation utility functions
28  *
29  *  Description: - explode a dn into it's own basic elements
30  *                 and put them in a structure (only if necessary)
31  *               - manipulate ldb_dn structures
32  *
33  *  Author: Simo Sorce
34  */
35
36 #include "ldb_private.h"
37 #include <ctype.h>
38
39 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
40
41 #define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
42
43 /**
44    internal ldb exploded dn structures
45 */
46 struct ldb_dn_component {
47
48         char *name;
49         struct ldb_val value;
50
51         char *cf_name;
52         struct ldb_val cf_value;
53 };
54
55 struct ldb_dn_ext_component {
56
57         char *name;
58         struct ldb_val value;
59 };
60
61 struct ldb_dn {
62
63         struct ldb_context *ldb;
64
65         /* Special DNs are always linearized */
66         bool special;
67         bool invalid;
68
69         bool valid_case;
70
71         char *linearized;
72         char *ext_linearized;
73         char *casefold;
74
75         unsigned int comp_num;
76         struct ldb_dn_component *components;
77
78         unsigned int ext_comp_num;
79         struct ldb_dn_ext_component *ext_components;
80 };
81
82 /* strdn may be NULL */
83 struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
84                                    struct ldb_context *ldb,
85                                    const struct ldb_val *strdn)
86 {
87         struct ldb_dn *dn;
88
89         if (! ldb) return NULL;
90
91         dn = talloc_zero(mem_ctx, struct ldb_dn);
92         LDB_DN_NULL_FAILED(dn);
93
94         dn->ldb = ldb;
95
96         if (strdn->data && strdn->length) {
97                 const char *data = (const char *)strdn->data;
98                 size_t length = strdn->length;
99
100                 if (data[0] == '@') {
101                         dn->special = true;
102                 }
103                 dn->ext_linearized = talloc_strndup(dn, data, length);
104                 LDB_DN_NULL_FAILED(dn->ext_linearized);
105
106                 if (strlen(data) != length) {
107                         /* The RDN must not contain a character with value 0x0 */
108                         return NULL;
109                 }
110
111                 if (data[0] == '<') {
112                         const char *p_save, *p = dn->ext_linearized;
113                         do {
114                                 p_save = p;
115                                 p = strstr(p, ">;");
116                                 if (p) {
117                                         p = p + 2;
118                                 }
119                         } while (p);
120
121                         if (p_save == dn->ext_linearized) {
122                                 dn->linearized = talloc_strdup(dn, "");
123                         } else {
124                                 dn->linearized = talloc_strdup(dn, p_save);
125                         }
126                         LDB_DN_NULL_FAILED(dn->linearized);
127                 } else {
128                         dn->linearized = dn->ext_linearized;
129                         dn->ext_linearized = NULL;
130                 }
131         } else {
132                 dn->linearized = talloc_strdup(dn, "");
133                 LDB_DN_NULL_FAILED(dn->linearized);
134         }
135
136         return dn;
137
138 failed:
139         talloc_free(dn);
140         return NULL;
141 }
142
143 /* strdn may be NULL */
144 struct ldb_dn *ldb_dn_new(void *mem_ctx,
145                           struct ldb_context *ldb,
146                           const char *strdn)
147 {
148         struct ldb_val blob;
149         blob.data = strdn;
150         blob.length = strdn ? strlen(strdn) : 0;
151         return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
152 }
153
154 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx,
155                               struct ldb_context *ldb,
156                               const char *new_fmt, ...)
157 {
158         char *strdn;
159         va_list ap;
160
161         if ( (! mem_ctx) || (! ldb)) return NULL;
162
163         va_start(ap, new_fmt);
164         strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
165         va_end(ap);
166
167         if (strdn) {
168                 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
169                 talloc_free(strdn);
170                 return dn;
171         }
172
173         return NULL;
174 }
175
176 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
177 {
178         const char *p, *s;
179         char *d;
180         int l;
181
182         p = s = src;
183         d = dst;
184
185         while (p - src < len) {
186
187                 p += strcspn(p, ",=\n+<>#;\\\"");
188
189                 if (p - src == len) /* found no escapable chars */
190                         break;
191
192                 /* copy the part of the string before the stop */
193                 memcpy(d, s, p - s);
194                 d += (p - s); /* move to current position */
195
196                 if (*p) { /* it is a normal escapable character */
197                         *d++ = '\\';
198                         *d++ = *p++;
199                 } else { /* we have a zero byte in the string */
200                         strncpy(d, "\00", 3); /* escape the zero */
201                         d += 3;
202                         p++; /* skip the zero */
203                 }
204                 s = p; /* move forward */
205         }
206
207         /* copy the last part (with zero) and return */
208         l = len - (s - src);
209         memcpy(d, s, l + 1);
210
211         /* return the length of the resulting string */
212         return (l + (d - dst));
213 }
214
215 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
216 {
217         char *dst;
218
219         if (!value.length)
220                 return NULL;
221
222         /* allocate destination string, it will be at most 3 times the source */
223         dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
224         if ( ! dst) {
225                 talloc_free(dst);
226                 return NULL;
227         }
228
229         ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
230
231         dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
232
233         return dst;
234 }
235
236 /*
237   explode a DN string into a ldb_dn structure
238   based on RFC4514 except that we don't support multiple valued RDNs
239
240   TODO: according to MS-ADTS:3.1.1.5.2 Naming Constraints
241   DN must be compliant with RFC2253
242 */
243 static bool ldb_dn_explode(struct ldb_dn *dn)
244 {
245         char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
246         bool trim = false;
247         bool in_extended = false;
248         bool in_ex_name = false;
249         bool in_ex_value = false;
250         bool in_attr = false;
251         bool in_value = false;
252         bool in_quote = false;
253         bool is_oid = false;
254         bool escape = false;
255         unsigned x;
256         int l, ret;
257         char *parse_dn;
258
259         if ( ! dn || dn->invalid) return false;
260
261         if (dn->components) {
262                 return true;
263         }
264
265         if (dn->ext_linearized) {
266                 parse_dn = dn->ext_linearized;
267         } else {
268                 parse_dn = dn->linearized;
269         }
270
271         if ( ! parse_dn ) {
272                 return false;
273         }
274
275         /* The RDN size must be less than 255 characters */
276         if (strlen(parse_dn) > 255) {
277                 return false;
278         }
279
280         /* Empty DNs */
281         if (parse_dn[0] == '\0') {
282                 return true;
283         }
284
285         /* Special DNs case */
286         if (dn->special) {
287                 return true;
288         }
289
290         /* make sure we free this if alloced previously before replacing */
291         talloc_free(dn->components);
292
293         talloc_free(dn->ext_components);
294         dn->ext_components = NULL;
295
296         /* in the common case we have 3 or more components */
297         /* make sure all components are zeroed, other functions depend on it */
298         dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
299         if ( ! dn->components) {
300                 return false;
301         }
302         dn->comp_num = 0;
303
304         /* Components data space is allocated here once */
305         data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
306         if (!data) {
307                 return false;
308         }
309
310         p = parse_dn;
311         in_extended = true;
312         in_ex_name = false;
313         in_ex_value = false;
314         trim = true;
315         t = NULL;
316         d = dt = data;
317
318         while (*p) {
319                 if (in_extended) {
320
321                         if (!in_ex_name && !in_ex_value) {
322
323                                 if (p[0] == '<') {
324                                         p++;
325                                         ex_name = d;
326                                         in_ex_name = true;
327                                         continue;
328                                 } else if (p[0] == '\0') {
329                                         p++;
330                                         continue;
331                                 } else {
332                                         in_extended = false;
333                                         in_attr = true;
334                                         dt = d;
335
336                                         continue;
337                                 }
338                         }
339
340                         if (in_ex_name && *p == '=') {
341                                 *d++ = '\0';
342                                 p++;
343                                 ex_value = d;
344                                 in_ex_name = false;
345                                 in_ex_value = true;
346                                 continue;
347                         }
348
349                         if (in_ex_value && *p == '>') {
350                                 const struct ldb_dn_extended_syntax *ext_syntax;
351                                 struct ldb_val ex_val = {
352                                         .data = (uint8_t *)ex_value,
353                                         .length = d - ex_value
354                                 };
355
356                                 *d++ = '\0';
357                                 p++;
358                                 in_ex_value = false;
359
360                                 /* Process name and ex_value */
361
362                                 dn->ext_components = talloc_realloc(dn,
363                                                                     dn->ext_components,
364                                                                     struct ldb_dn_ext_component,
365                                                                     dn->ext_comp_num + 1);
366                                 if ( ! dn->ext_components) {
367                                         /* ouch ! */
368                                         goto failed;
369                                 }
370
371                                 ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
372                                 if (!ext_syntax) {
373                                         /* We don't know about this type of extended DN */
374                                         goto failed;
375                                 }
376
377                                 dn->ext_components[dn->ext_comp_num].name = talloc_strdup(dn->ext_components, ex_name);
378                                 if (!dn->ext_components[dn->ext_comp_num].name) {
379                                         /* ouch */
380                                         goto failed;
381                                 }
382                                 ret = ext_syntax->read_fn(dn->ldb, dn->ext_components,
383                                                           &ex_val, &dn->ext_components[dn->ext_comp_num].value);
384                                 if (ret != LDB_SUCCESS) {
385                                         dn->invalid = true;
386                                         goto failed;
387                                 }
388
389                                 dn->ext_comp_num++;
390
391                                 if (*p == '\0') {
392                                         /* We have reached the end (extended component only)! */
393                                         talloc_free(data);
394                                         return true;
395
396                                 } else if (*p == ';') {
397                                         p++;
398                                         continue;
399                                 } else {
400                                         dn->invalid = true;
401                                         goto failed;
402                                 }
403                         }
404
405                         *d++ = *p++;
406                         continue;
407                 }
408                 if (in_attr) {
409                         if (trim) {
410                                 if (*p == ' ') {
411                                         p++;
412                                         continue;
413                                 }
414
415                                 /* first char */
416                                 trim = false;
417
418                                 if (!isascii(*p)) {
419                                         /* attr names must be ascii only */
420                                         dn->invalid = true;
421                                         goto failed;
422                                 }
423
424                                 if (isdigit(*p)) {
425                                         is_oid = true;
426                                 } else
427                                 if ( ! isalpha(*p)) {
428                                         /* not a digit nor an alpha,
429                                          * invalid attribute name */
430                                         dn->invalid = true;
431                                         goto failed;
432                                 }
433
434                                 /* Copy this character across from parse_dn,
435                                  * now we have trimmed out spaces */
436                                 *d++ = *p++;
437                                 continue;
438                         }
439
440                         if (*p == ' ') {
441                                 p++;
442                                 /* valid only if we are at the end */
443                                 trim = true;
444                                 continue;
445                         }
446
447                         if (trim && (*p != '=')) {
448                                 /* spaces/tabs are not allowed */
449                                 dn->invalid = true;
450                                 goto failed;
451                         }
452
453                         if (*p == '=') {
454                                 /* attribute terminated */
455                                 in_attr = false;
456                                 in_value = true;
457                                 trim = true;
458                                 l = 0;
459
460                                 /* Terminate this string in d
461                                  * (which is a copy of parse_dn
462                                  *  with spaces trimmed) */
463                                 *d++ = '\0';
464                                 dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
465                                 if ( ! dn->components[dn->comp_num].name) {
466                                         /* ouch */
467                                         goto failed;
468                                 }
469
470                                 dt = d;
471
472                                 p++;
473                                 continue;
474                         }
475
476                         if (!isascii(*p)) {
477                                 /* attr names must be ascii only */
478                                 dn->invalid = true;
479                                 goto failed;
480                         }
481
482                         if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
483                                 /* not a digit nor a dot,
484                                  * invalid attribute oid */
485                                 dn->invalid = true;
486                                 goto failed;
487                         } else
488                         if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
489                                 /* not ALPHA, DIGIT or HYPHEN */
490                                 dn->invalid = true;
491                                 goto failed;
492                         }
493
494                         *d++ = *p++;
495                         continue;
496                 }
497
498                 if (in_value) {
499                         if (in_quote) {
500                                 if (*p == '\"') {
501                                         if (p[-1] != '\\') {
502                                                 p++;
503                                                 in_quote = false;
504                                                 continue;
505                                         }
506                                 }
507                                 *d++ = *p++;
508                                 l++;
509                                 continue;
510                         }
511
512                         if (trim) {
513                                 if (*p == ' ') {
514                                         p++;
515                                         continue;
516                                 }
517
518                                 /* first char */
519                                 trim = false;
520
521                                 if (*p == '\"') {
522                                         in_quote = true;
523                                         p++;
524                                         continue;
525                                 }
526                         }
527
528                         switch (*p) {
529
530                         /* TODO: support ber encoded values
531                         case '#':
532                         */
533
534                         case ',':
535                                 if (escape) {
536                                         *d++ = *p++;
537                                         l++;
538                                         escape = false;
539                                         continue;
540                                 }
541                                 /* ok found value terminator */
542
543                                 if ( t ) {
544                                         /* trim back */
545                                         d -= (p - t);
546                                         l -= (p - t);
547                                 }
548
549                                 in_attr = true;
550                                 in_value = false;
551                                 trim = true;
552
553                                 p++;
554                                 *d++ = '\0';
555                                 dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
556                                 dn->components[dn->comp_num].value.length = l;
557                                 if ( ! dn->components[dn->comp_num].value.data) {
558                                         /* ouch ! */
559                                         goto failed;
560                                 }
561
562                                 dt = d;
563
564                                 dn->comp_num++;
565                                 if (dn->comp_num > 2) {
566                                         dn->components = talloc_realloc(dn,
567                                                                         dn->components,
568                                                                         struct ldb_dn_component,
569                                                                         dn->comp_num + 1);
570                                         if ( ! dn->components) {
571                                                 /* ouch ! */
572                                                 goto failed;
573                                         }
574                                         /* make sure all components are zeroed, other functions depend on this */
575                                         memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
576                                 }
577
578                                 continue;
579
580                         case '=':
581                         case '\n':
582                         case '+':
583                         case '<':
584                         case '>':
585                         case '#':
586                         case ';':
587                         case '\"':
588                                 /* a string with not escaped specials is invalid (tested) */
589                                 if ( ! escape) {
590                                         dn->invalid = true;
591                                         goto failed;
592                                 }
593                                 escape = false;
594
595                                 *d++ = *p++;
596                                 l++;
597
598                                 if ( t ) t = NULL;
599                                 break;
600
601                         case '\\':
602                                 if ( ! escape) {
603                                         escape = true;
604                                         p++;
605                                         continue;
606                                 }
607                                 escape = false;
608
609                                 *d++ = *p++;
610                                 l++;
611
612                                 if ( t ) t = NULL;
613                                 break;
614
615                         default:
616                                 if (escape) {
617                                         if (sscanf(p, "%02x", &x) != 1) {
618                                                 /* invalid escaping sequence */
619                                                 dn->invalid = true;
620                                                 goto failed;
621                                         }
622                                         escape = false;
623
624                                         p += 2;
625                                         *d++ = (unsigned char)x;
626                                         l++;
627
628                                         if ( t ) t = NULL;
629                                         break;
630                                 }
631
632                                 if (*p == ' ') {
633                                         if ( ! t) t = p;
634                                 } else {
635                                         if ( t ) t = NULL;
636                                 }
637
638                                 *d++ = *p++;
639                                 l++;
640
641                                 break;
642                         }
643
644                 }
645         }
646
647         if (in_attr || in_quote) {
648                 /* invalid dn */
649                 dn->invalid = true;
650                 goto failed;
651         }
652
653         /* save last element */
654         if ( t ) {
655                 /* trim back */
656                 d -= (p - t);
657                 l -= (p - t);
658         }
659
660         *d++ = '\0';
661         dn->components[dn->comp_num].value.length = l;
662         dn->components[dn->comp_num].value.data =
663                                 (uint8_t *)talloc_strdup(dn->components, dt);
664         if ( ! dn->components[dn->comp_num].value.data) {
665                 /* ouch */
666                 goto failed;
667         }
668
669         dn->comp_num++;
670
671         talloc_free(data);
672         return true;
673
674 failed:
675         dn->comp_num = 0;
676         talloc_free(dn->components);
677         return false;
678 }
679
680 bool ldb_dn_validate(struct ldb_dn *dn)
681 {
682         return ldb_dn_explode(dn);
683 }
684
685 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
686 {
687         int i, len;
688         char *d, *n;
689
690         if ( ! dn || ( dn->invalid)) return NULL;
691
692         if (dn->linearized) return dn->linearized;
693
694         if ( ! dn->components) {
695                 dn->invalid = true;
696                 return NULL;
697         }
698
699         if (dn->comp_num == 0) {
700                 dn->linearized = talloc_strdup(dn, "");
701                 if ( ! dn->linearized) return NULL;
702                 return dn->linearized;
703         }
704
705         /* calculate maximum possible length of DN */
706         for (len = 0, i = 0; i < dn->comp_num; i++) {
707                 /* name len */
708                 len += strlen(dn->components[i].name);
709                 /* max escaped data len */
710                 len += (dn->components[i].value.length * 3);
711                 len += 2; /* '=' and ',' */
712         }
713         dn->linearized = talloc_array(dn, char, len);
714         if ( ! dn->linearized) return NULL;
715
716         d = dn->linearized;
717
718         for (i = 0; i < dn->comp_num; i++) {
719
720                 /* copy the name */
721                 n = dn->components[i].name;
722                 while (*n) *d++ = *n++;
723
724                 *d++ = '=';
725
726                 /* and the value */
727                 d += ldb_dn_escape_internal( d,
728                                 (char *)dn->components[i].value.data,
729                                 dn->components[i].value.length);
730                 *d++ = ',';
731         }
732
733         *(--d) = '\0';
734
735         /* don't waste more memory than necessary */
736         dn->linearized = talloc_realloc(dn, dn->linearized,
737                                         char, (d - dn->linearized + 1));
738
739         return dn->linearized;
740 }
741
742 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
743 {
744         const char *linearized = ldb_dn_get_linearized(dn);
745         char *p;
746         int i;
747
748         if (!linearized) {
749                 return NULL;
750         }
751
752         if (!ldb_dn_has_extended(dn)) {
753                 return talloc_strdup(mem_ctx, linearized);
754         }
755
756         if (!ldb_dn_validate(dn)) {
757                 return NULL;
758         }
759
760         for (i = 0; i < dn->ext_comp_num; i++) {
761                 const struct ldb_dn_extended_syntax *ext_syntax;
762                 const char *name = dn->ext_components[i].name;
763                 struct ldb_val ec_val = dn->ext_components[i].value;
764                 struct ldb_val val;
765                 int ret;
766
767                 ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
768
769                 if (mode == 1) {
770                         ret = ext_syntax->write_clear_fn(dn->ldb, mem_ctx,
771                                                         &ec_val, &val);
772                 } else if (mode == 0) {
773                         ret = ext_syntax->write_hex_fn(dn->ldb, mem_ctx,
774                                                         &ec_val, &val);
775                 } else {
776                         ret = -1;
777                 }
778
779                 if (ret != LDB_SUCCESS) {
780                         return NULL;
781                 }
782
783                 if (i == 0) {
784                         p = talloc_asprintf(mem_ctx, "<%s=%s>",
785                                                         name, val.data);
786                 } else {
787                         p = talloc_asprintf_append(p, ";<%s=%s>",
788                                                         name, val.data);
789                 }
790
791                 talloc_free(val.data);
792
793                 if (!p) {
794                         return NULL;
795                 }
796         }
797
798         if (dn->ext_comp_num && *linearized) {
799                 p = talloc_asprintf_append(p, ";%s", linearized);
800         }
801
802         if (!p) {
803                 return NULL;
804         }
805
806         return p;
807 }
808
809
810
811 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
812 {
813         return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
814 }
815
816 /*
817   casefold a dn. We need to casefold the attribute names, and canonicalize
818   attribute values of case insensitive attributes.
819 */
820
821 static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
822 {
823         int i, ret;
824
825         if ( ! dn || dn->invalid) return false;
826
827         if (dn->valid_case) return true;
828
829         if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
830                 return false;
831         }
832
833         for (i = 0; i < dn->comp_num; i++) {
834                 const struct ldb_schema_attribute *a;
835
836                 dn->components[i].cf_name =
837                         ldb_attr_casefold(dn->components,
838                                           dn->components[i].name);
839                 if (!dn->components[i].cf_name) {
840                         goto failed;
841                 }
842
843                 a = ldb_schema_attribute_by_name(dn->ldb,
844                                                  dn->components[i].cf_name);
845
846                 ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
847                                                  &(dn->components[i].value),
848                                                  &(dn->components[i].cf_value));
849                 if (ret != 0) {
850                         goto failed;
851                 }
852         }
853
854         dn->valid_case = true;
855
856         return true;
857
858 failed:
859         for (i = 0; i < dn->comp_num; i++) {
860                 LDB_FREE(dn->components[i].cf_name);
861                 LDB_FREE(dn->components[i].cf_value.data);
862         }
863         return false;
864 }
865
866 const char *ldb_dn_get_casefold(struct ldb_dn *dn)
867 {
868         int i, len;
869         char *d, *n;
870
871         if (dn->casefold) return dn->casefold;
872
873         if (dn->special) {
874                 dn->casefold = talloc_strdup(dn, dn->linearized);
875                 if (!dn->casefold) return NULL;
876                 dn->valid_case = true;
877                 return dn->casefold;
878         }
879
880         if ( ! ldb_dn_casefold_internal(dn)) {
881                 return NULL;
882         }
883
884         if (dn->comp_num == 0) {
885                 dn->casefold = talloc_strdup(dn, "");
886                 return dn->casefold;
887         }
888
889         /* calculate maximum possible length of DN */
890         for (len = 0, i = 0; i < dn->comp_num; i++) {
891                 /* name len */
892                 len += strlen(dn->components[i].cf_name);
893                 /* max escaped data len */
894                 len += (dn->components[i].cf_value.length * 3);
895                 len += 2; /* '=' and ',' */
896         }
897         dn->casefold = talloc_array(dn, char, len);
898         if ( ! dn->casefold) return NULL;
899
900         d = dn->casefold;
901
902         for (i = 0; i < dn->comp_num; i++) {
903
904                 /* copy the name */
905                 n = dn->components[i].cf_name;
906                 while (*n) *d++ = *n++;
907
908                 *d++ = '=';
909
910                 /* and the value */
911                 d += ldb_dn_escape_internal( d,
912                                 (char *)dn->components[i].cf_value.data,
913                                 dn->components[i].cf_value.length);
914                 *d++ = ',';
915         }
916         *(--d) = '\0';
917
918         /* don't waste more memory than necessary */
919         dn->casefold = talloc_realloc(dn, dn->casefold,
920                                       char, strlen(dn->casefold) + 1);
921
922         return dn->casefold;
923 }
924
925 char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
926 {
927         return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
928 }
929
930 /* Determine if dn is below base, in the ldap tree.  Used for
931  * evaluating a subtree search.
932  * 0 if they match, otherwise non-zero
933  */
934
935 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
936 {
937         int ret;
938         int n_base, n_dn;
939
940         if ( ! base || base->invalid) return 1;
941         if ( ! dn || dn->invalid) return -1;
942
943         if (( ! base->valid_case) || ( ! dn->valid_case)) {
944                 if (base->linearized && dn->linearized) {
945                         /* try with a normal compare first, if we are lucky
946                          * we will avoid exploding and casfolding */
947                         int dif;
948                         dif = strlen(dn->linearized) - strlen(base->linearized);
949                         if (dif < 0) {
950                                 return dif;
951                         }
952                         if (strcmp(base->linearized,
953                                    &dn->linearized[dif]) == 0) {
954                                 return 0;
955                         }
956                 }
957
958                 if ( ! ldb_dn_casefold_internal(base)) {
959                         return 1;
960                 }
961
962                 if ( ! ldb_dn_casefold_internal(dn)) {
963                         return -1;
964                 }
965
966         }
967
968         /* if base has more components,
969          * they don't have the same base */
970         if (base->comp_num > dn->comp_num) {
971                 return (dn->comp_num - base->comp_num);
972         }
973
974         if (dn->comp_num == 0) {
975                 if (dn->special && base->special) {
976                         return strcmp(base->linearized, dn->linearized);
977                 } else if (dn->special) {
978                         return -1;
979                 } else if (base->special) {
980                         return 1;
981                 } else {
982                         return 0;
983                 }
984         }
985
986         n_base = base->comp_num - 1;
987         n_dn = dn->comp_num - 1;
988
989         while (n_base >= 0) {
990                 char *b_name = base->components[n_base].cf_name;
991                 char *dn_name = dn->components[n_dn].cf_name;
992
993                 char *b_vdata = (char *)base->components[n_base].cf_value.data;
994                 char *dn_vdata = (char *)dn->components[n_dn].cf_value.data;
995
996                 size_t b_vlen = base->components[n_base].cf_value.length;
997                 size_t dn_vlen = dn->components[n_dn].cf_value.length;
998
999                 /* compare attr names */
1000                 ret = strcmp(b_name, dn_name);
1001                 if (ret != 0) return ret;
1002
1003                 /* compare attr.cf_value. */
1004                 if (b_vlen != dn_vlen) {
1005                         return b_vlen - dn_vlen;
1006                 }
1007                 ret = strcmp(b_vdata, dn_vdata);
1008                 if (ret != 0) return ret;
1009
1010                 n_base--;
1011                 n_dn--;
1012         }
1013
1014         return 0;
1015 }
1016
1017 /* compare DNs using casefolding compare functions.
1018
1019    If they match, then return 0
1020  */
1021
1022 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
1023 {
1024         int i, ret;
1025
1026         if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
1027                 return -1;
1028         }
1029
1030         if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
1031                 if (dn0->linearized && dn1->linearized) {
1032                         /* try with a normal compare first, if we are lucky
1033                          * we will avoid exploding and casfolding */
1034                         if (strcmp(dn0->linearized, dn1->linearized) == 0) {
1035                                 return 0;
1036                         }
1037                 }
1038
1039                 if ( ! ldb_dn_casefold_internal(dn0)) {
1040                         return 1;
1041                 }
1042
1043                 if ( ! ldb_dn_casefold_internal(dn1)) {
1044                         return -1;
1045                 }
1046
1047         }
1048
1049         if (dn0->comp_num != dn1->comp_num) {
1050                 return (dn1->comp_num - dn0->comp_num);
1051         }
1052
1053         if (dn0->comp_num == 0) {
1054                 if (dn0->special && dn1->special) {
1055                         return strcmp(dn0->linearized, dn1->linearized);
1056                 } else if (dn0->special) {
1057                         return 1;
1058                 } else if (dn1->special) {
1059                         return -1;
1060                 } else {
1061                         return 0;
1062                 }
1063         }
1064
1065         for (i = 0; i < dn0->comp_num; i++) {
1066                 char *dn0_name = dn0->components[i].cf_name;
1067                 char *dn1_name = dn1->components[i].cf_name;
1068
1069                 char *dn0_vdata = (char *)dn0->components[i].cf_value.data;
1070                 char *dn1_vdata = (char *)dn1->components[i].cf_value.data;
1071
1072                 size_t dn0_vlen = dn0->components[i].cf_value.length;
1073                 size_t dn1_vlen = dn1->components[i].cf_value.length;
1074
1075                 /* compare attr names */
1076                 ret = strcmp(dn0_name, dn1_name);
1077                 if (ret != 0) {
1078                         return ret;
1079                 }
1080
1081                 /* compare attr.cf_value. */
1082                 if (dn0_vlen != dn1_vlen) {
1083                         return dn0_vlen - dn1_vlen;
1084                 }
1085                 ret = strcmp(dn0_vdata, dn1_vdata);
1086                 if (ret != 0) {
1087                         return ret;
1088                 }
1089         }
1090
1091         return 0;
1092 }
1093
1094 static struct ldb_dn_component ldb_dn_copy_component(
1095                                                 void *mem_ctx,
1096                                                 struct ldb_dn_component *src)
1097 {
1098         struct ldb_dn_component dst;
1099
1100         memset(&dst, 0, sizeof(dst));
1101
1102         if (src == NULL) {
1103                 return dst;
1104         }
1105
1106         dst.value = ldb_val_dup(mem_ctx, &(src->value));
1107         if (dst.value.data == NULL) {
1108                 return dst;
1109         }
1110
1111         dst.name = talloc_strdup(mem_ctx, src->name);
1112         if (dst.name == NULL) {
1113                 LDB_FREE(dst.value.data);
1114                 return dst;
1115         }
1116
1117         if (src->cf_value.data) {
1118                 dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
1119                 if (dst.cf_value.data == NULL) {
1120                         LDB_FREE(dst.value.data);
1121                         LDB_FREE(dst.name);
1122                         return dst;
1123                 }
1124
1125                 dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
1126                 if (dst.cf_name == NULL) {
1127                         LDB_FREE(dst.cf_name);
1128                         LDB_FREE(dst.value.data);
1129                         LDB_FREE(dst.name);
1130                         return dst;
1131                 }
1132         } else {
1133                 dst.cf_value.data = NULL;
1134                 dst.cf_name = NULL;
1135         }
1136
1137         return dst;
1138 }
1139
1140 static struct ldb_dn_ext_component ldb_dn_ext_copy_component(
1141                                                 void *mem_ctx,
1142                                                 struct ldb_dn_ext_component *src)
1143 {
1144         struct ldb_dn_ext_component dst;
1145
1146         memset(&dst, 0, sizeof(dst));
1147
1148         if (src == NULL) {
1149                 return dst;
1150         }
1151
1152         dst.value = ldb_val_dup(mem_ctx, &(src->value));
1153         if (dst.value.data == NULL) {
1154                 return dst;
1155         }
1156
1157         dst.name = talloc_strdup(mem_ctx, src->name);
1158         if (dst.name == NULL) {
1159                 LDB_FREE(dst.value.data);
1160                 return dst;
1161         }
1162
1163         return dst;
1164 }
1165
1166 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
1167 {
1168         struct ldb_dn *new_dn;
1169
1170         if (!dn || dn->invalid) {
1171                 return NULL;
1172         }
1173
1174         new_dn = talloc_zero(mem_ctx, struct ldb_dn);
1175         if ( !new_dn) {
1176                 return NULL;
1177         }
1178
1179         *new_dn = *dn;
1180
1181         if (dn->components) {
1182                 int i;
1183
1184                 new_dn->components =
1185                         talloc_zero_array(new_dn,
1186                                           struct ldb_dn_component,
1187                                           dn->comp_num);
1188                 if ( ! new_dn->components) {
1189                         talloc_free(new_dn);
1190                         return NULL;
1191                 }
1192
1193                 for (i = 0; i < dn->comp_num; i++) {
1194                         new_dn->components[i] =
1195                                 ldb_dn_copy_component(new_dn->components,
1196                                                       &dn->components[i]);
1197                         if ( ! new_dn->components[i].value.data) {
1198                                 talloc_free(new_dn);
1199                                 return NULL;
1200                         }
1201                 }
1202         }
1203
1204         if (dn->ext_components) {
1205                 int i;
1206
1207                 new_dn->ext_components =
1208                         talloc_zero_array(new_dn,
1209                                           struct ldb_dn_ext_component,
1210                                           dn->ext_comp_num);
1211                 if ( ! new_dn->ext_components) {
1212                         talloc_free(new_dn);
1213                         return NULL;
1214                 }
1215
1216                 for (i = 0; i < dn->ext_comp_num; i++) {
1217                         new_dn->ext_components[i] =
1218                                  ldb_dn_ext_copy_component(
1219                                                 new_dn->ext_components,
1220                                                 &dn->ext_components[i]);
1221                         if ( ! new_dn->ext_components[i].value.data) {
1222                                 talloc_free(new_dn);
1223                                 return NULL;
1224                         }
1225                 }
1226         }
1227
1228         if (dn->casefold) {
1229                 new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
1230                 if ( ! new_dn->casefold) {
1231                         talloc_free(new_dn);
1232                         return NULL;
1233                 }
1234         }
1235
1236         if (dn->linearized) {
1237                 new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
1238                 if ( ! new_dn->linearized) {
1239                         talloc_free(new_dn);
1240                         return NULL;
1241                 }
1242         }
1243
1244         if (dn->ext_linearized) {
1245                 new_dn->ext_linearized = talloc_strdup(new_dn,
1246                                                         dn->ext_linearized);
1247                 if ( ! new_dn->ext_linearized) {
1248                         talloc_free(new_dn);
1249                         return NULL;
1250                 }
1251         }
1252
1253         return new_dn;
1254 }
1255
1256 /* modify the given dn by adding a base.
1257  *
1258  * return true if successful and false if not
1259  * if false is returned the dn may be marked invalid
1260  */
1261 bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
1262 {
1263         const char *s;
1264         char *t;
1265
1266         if ( !base || base->invalid || !dn || dn->invalid) {
1267                 return false;
1268         }
1269
1270         if (dn->components) {
1271                 int i;
1272
1273                 if ( ! ldb_dn_validate(base)) {
1274                         return false;
1275                 }
1276
1277                 s = NULL;
1278                 if (dn->valid_case) {
1279                         if ( ! (s = ldb_dn_get_casefold(base))) {
1280                                 return false;
1281                         }
1282                 }
1283
1284                 dn->components = talloc_realloc(dn,
1285                                                 dn->components,
1286                                                 struct ldb_dn_component,
1287                                                 dn->comp_num + base->comp_num);
1288                 if ( ! dn->components) {
1289                         dn->invalid = true;
1290                         return false;
1291                 }
1292
1293                 for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
1294                         dn->components[dn->comp_num] =
1295                                 ldb_dn_copy_component(dn->components,
1296                                                         &base->components[i]);
1297                         if (dn->components[dn->comp_num].value.data == NULL) {
1298                                 dn->invalid = true;
1299                                 return false;
1300                         }
1301                 }
1302
1303                 if (dn->casefold && s) {
1304                         if (*dn->casefold) {
1305                                 t = talloc_asprintf(dn, "%s,%s",
1306                                                     dn->casefold, s);
1307                         } else {
1308                                 t = talloc_strdup(dn, s);
1309                         }
1310                         LDB_FREE(dn->casefold);
1311                         dn->casefold = t;
1312                 }
1313         }
1314
1315         if (dn->linearized) {
1316
1317                 s = ldb_dn_get_linearized(base);
1318                 if ( ! s) {
1319                         return false;
1320                 }
1321
1322                 if (*dn->linearized) {
1323                         t = talloc_asprintf(dn, "%s,%s",
1324                                             dn->linearized, s);
1325                 } else {
1326                         t = talloc_strdup(dn, s);
1327                 }
1328                 if ( ! t) {
1329                         dn->invalid = true;
1330                         return false;
1331                 }
1332                 LDB_FREE(dn->linearized);
1333                 dn->linearized = t;
1334         }
1335
1336         /* Wipe the ext_linearized DN,
1337          * the GUID and SID are almost certainly no longer valid */
1338         if (dn->ext_linearized) {
1339                 LDB_FREE(dn->ext_linearized);
1340         }
1341
1342         LDB_FREE(dn->ext_components);
1343         dn->ext_comp_num = 0;
1344         return true;
1345 }
1346
1347 /* modify the given dn by adding a base.
1348  *
1349  * return true if successful and false if not
1350  * if false is returned the dn may be marked invalid
1351  */
1352 bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
1353 {
1354         struct ldb_dn *base;
1355         char *base_str;
1356         va_list ap;
1357         bool ret;
1358
1359         if ( !dn || dn->invalid) {
1360                 return false;
1361         }
1362
1363         va_start(ap, base_fmt);
1364         base_str = talloc_vasprintf(dn, base_fmt, ap);
1365         va_end(ap);
1366
1367         if (base_str == NULL) {
1368                 return false;
1369         }
1370
1371         base = ldb_dn_new(base_str, dn->ldb, base_str);
1372
1373         ret = ldb_dn_add_base(dn, base);
1374
1375         talloc_free(base_str);
1376
1377         return ret;
1378 }
1379
1380 /* modify the given dn by adding children elements.
1381  *
1382  * return true if successful and false if not
1383  * if false is returned the dn may be marked invalid
1384  */
1385 bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
1386 {
1387         const char *s;
1388         char *t;
1389
1390         if ( !child || child->invalid || !dn || dn->invalid) {
1391                 return false;
1392         }
1393
1394         if (dn->components) {
1395                 int n, i, j;
1396
1397                 if ( ! ldb_dn_validate(child)) {
1398                         return false;
1399                 }
1400
1401                 s = NULL;
1402                 if (dn->valid_case) {
1403                         if ( ! (s = ldb_dn_get_casefold(child))) {
1404                                 return false;
1405                         }
1406                 }
1407
1408                 n = dn->comp_num + child->comp_num;
1409
1410                 dn->components = talloc_realloc(dn,
1411                                                 dn->components,
1412                                                 struct ldb_dn_component,
1413                                                 n);
1414                 if ( ! dn->components) {
1415                         dn->invalid = true;
1416                         return false;
1417                 }
1418
1419                 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
1420                         dn->components[j] = dn->components[i];
1421                 }
1422
1423                 for (i = 0; i < child->comp_num; i++) {
1424                         dn->components[i] =
1425                                 ldb_dn_copy_component(dn->components,
1426                                                         &child->components[i]);
1427                         if (dn->components[i].value.data == NULL) {
1428                                 dn->invalid = true;
1429                                 return false;
1430                         }
1431                 }
1432
1433                 dn->comp_num = n;
1434
1435                 if (dn->casefold && s) {
1436                         t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
1437                         LDB_FREE(dn->casefold);
1438                         dn->casefold = t;
1439                 }
1440         }
1441
1442         if (dn->linearized) {
1443
1444                 s = ldb_dn_get_linearized(child);
1445                 if ( ! s) {
1446                         return false;
1447                 }
1448
1449                 t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
1450                 if ( ! t) {
1451                         dn->invalid = true;
1452                         return false;
1453                 }
1454                 LDB_FREE(dn->linearized);
1455                 dn->linearized = t;
1456         }
1457
1458         /* Wipe the ext_linearized DN,
1459          * the GUID and SID are almost certainly no longer valid */
1460         LDB_FREE(dn->ext_linearized);
1461
1462         LDB_FREE(dn->ext_components);
1463         dn->ext_comp_num = 0;
1464
1465         return true;
1466 }
1467
1468 /* modify the given dn by adding children elements.
1469  *
1470  * return true if successful and false if not
1471  * if false is returned the dn may be marked invalid
1472  */
1473 bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
1474 {
1475         struct ldb_dn *child;
1476         char *child_str;
1477         va_list ap;
1478         bool ret;
1479
1480         if ( !dn || dn->invalid) {
1481                 return false;
1482         }
1483
1484         va_start(ap, child_fmt);
1485         child_str = talloc_vasprintf(dn, child_fmt, ap);
1486         va_end(ap);
1487
1488         if (child_str == NULL) {
1489                 return false;
1490         }
1491
1492         child = ldb_dn_new(child_str, dn->ldb, child_str);
1493
1494         ret = ldb_dn_add_child(dn, child);
1495
1496         talloc_free(child_str);
1497
1498         return ret;
1499 }
1500
1501 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
1502 {
1503         int i;
1504
1505         if ( ! ldb_dn_validate(dn)) {
1506                 return false;
1507         }
1508
1509         if (dn->comp_num < num) {
1510                 return false;
1511         }
1512
1513         /* free components */
1514         for (i = num; i > 0; i--) {
1515                 LDB_FREE(dn->components[dn->comp_num - i].name);
1516                 LDB_FREE(dn->components[dn->comp_num - i].value.data);
1517                 LDB_FREE(dn->components[dn->comp_num - i].cf_name);
1518                 LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
1519         }
1520
1521         dn->comp_num -= num;
1522
1523         if (dn->valid_case) {
1524                 for (i = 0; i < dn->comp_num; i++) {
1525                         LDB_FREE(dn->components[i].cf_name);
1526                         LDB_FREE(dn->components[i].cf_value.data);
1527                 }
1528                 dn->valid_case = false;
1529         }
1530
1531         LDB_FREE(dn->casefold);
1532         LDB_FREE(dn->linearized);
1533
1534         /* Wipe the ext_linearized DN,
1535          * the GUID and SID are almost certainly no longer valid */
1536         LDB_FREE(dn->ext_linearized);
1537
1538         LDB_FREE(dn->ext_components);
1539         dn->ext_comp_num = 0;
1540
1541         return true;
1542 }
1543
1544 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
1545 {
1546         int i, j;
1547
1548         if ( ! ldb_dn_validate(dn)) {
1549                 return false;
1550         }
1551
1552         if (dn->comp_num < num) {
1553                 return false;
1554         }
1555
1556         for (i = 0, j = num; j < dn->comp_num; i++, j++) {
1557                 if (i < num) {
1558                         LDB_FREE(dn->components[i].name);
1559                         LDB_FREE(dn->components[i].value.data);
1560                         LDB_FREE(dn->components[i].cf_name);
1561                         LDB_FREE(dn->components[i].cf_value.data);
1562                 }
1563                 dn->components[i] = dn->components[j];
1564         }
1565
1566         dn->comp_num -= num;
1567
1568         if (dn->valid_case) {
1569                 for (i = 0; i < dn->comp_num; i++) {
1570                         LDB_FREE(dn->components[i].cf_name);
1571                         LDB_FREE(dn->components[i].cf_value.data);
1572                 }
1573                 dn->valid_case = false;
1574         }
1575
1576         LDB_FREE(dn->casefold);
1577         LDB_FREE(dn->linearized);
1578
1579         /* Wipe the ext_linearized DN,
1580          * the GUID and SID are almost certainly no longer valid */
1581         LDB_FREE(dn->ext_linearized);
1582
1583         LDB_FREE(dn->ext_components);
1584         dn->ext_comp_num = 0;
1585         return true;
1586 }
1587
1588 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
1589 {
1590         struct ldb_dn *new_dn;
1591
1592         new_dn = ldb_dn_copy(mem_ctx, dn);
1593         if ( !new_dn ) {
1594                 return NULL;
1595         }
1596
1597         if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
1598                 talloc_free(new_dn);
1599                 return NULL;
1600         }
1601
1602         /* Wipe the ext_linearized DN,
1603          * the GUID and SID are almost certainly no longer valid */
1604         LDB_FREE(dn->ext_linearized);
1605
1606         LDB_FREE(dn->ext_components);
1607         dn->ext_comp_num = 0;
1608         return new_dn;
1609 }
1610
1611 /* Create a 'canonical name' string from a DN:
1612
1613    ie dc=samba,dc=org -> samba.org/
1614       uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
1615
1616    There are two formats,
1617    the EX format has the last '/' replaced with a newline (\n).
1618
1619 */
1620 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
1621         int i;
1622         TALLOC_CTX *tmpctx;
1623         char *cracked = NULL;
1624         const char *format = (ex_format ? "\n" : "/" );
1625
1626         if ( ! ldb_dn_validate(dn)) {
1627                 return NULL;
1628         }
1629
1630         tmpctx = talloc_new(mem_ctx);
1631
1632         /* Walk backwards down the DN, grabbing 'dc' components at first */
1633         for (i = dn->comp_num - 1 ; i >= 0; i--) {
1634                 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
1635                         break;
1636                 }
1637                 if (cracked) {
1638                         cracked = talloc_asprintf(tmpctx, "%s.%s",
1639                                                   ldb_dn_escape_value(tmpctx,
1640                                                         dn->components[i].value),
1641                                                   cracked);
1642                 } else {
1643                         cracked = ldb_dn_escape_value(tmpctx,
1644                                                         dn->components[i].value);
1645                 }
1646                 if (!cracked) {
1647                         goto done;
1648                 }
1649         }
1650
1651         /* Only domain components?  Finish here */
1652         if (i < 0) {
1653                 cracked = talloc_strdup_append_buffer(cracked, format);
1654                 talloc_steal(mem_ctx, cracked);
1655                 goto done;
1656         }
1657
1658         /* Now walk backwards appending remaining components */
1659         for (; i > 0; i--) {
1660                 cracked = talloc_asprintf_append_buffer(cracked, "/%s",
1661                                                         ldb_dn_escape_value(tmpctx,
1662                                                         dn->components[i].value));
1663                 if (!cracked) {
1664                         goto done;
1665                 }
1666         }
1667
1668         /* Last one, possibly a newline for the 'ex' format */
1669         cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
1670                                                 ldb_dn_escape_value(tmpctx,
1671                                                         dn->components[i].value));
1672
1673         talloc_steal(mem_ctx, cracked);
1674 done:
1675         talloc_free(tmpctx);
1676         return cracked;
1677 }
1678
1679 /* Wrapper functions for the above, for the two different string formats */
1680 char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
1681         return ldb_dn_canonical(mem_ctx, dn, 0);
1682
1683 }
1684
1685 char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
1686         return ldb_dn_canonical(mem_ctx, dn, 1);
1687 }
1688
1689 int ldb_dn_get_comp_num(struct ldb_dn *dn)
1690 {
1691         if ( ! ldb_dn_validate(dn)) {
1692                 return -1;
1693         }
1694         return dn->comp_num;
1695 }
1696
1697 const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
1698 {
1699         if ( ! ldb_dn_validate(dn)) {
1700                 return NULL;
1701         }
1702         if (num >= dn->comp_num) return NULL;
1703         return dn->components[num].name;
1704 }
1705
1706 const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn,
1707                                                 unsigned int num)
1708 {
1709         if ( ! ldb_dn_validate(dn)) {
1710                 return NULL;
1711         }
1712         if (num >= dn->comp_num) return NULL;
1713         return &dn->components[num].value;
1714 }
1715
1716 const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
1717 {
1718         if ( ! ldb_dn_validate(dn)) {
1719                 return NULL;
1720         }
1721         if (dn->comp_num == 0) return NULL;
1722         return dn->components[0].name;
1723 }
1724
1725 const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
1726 {
1727         if ( ! ldb_dn_validate(dn)) {
1728                 return NULL;
1729         }
1730         if (dn->comp_num == 0) return NULL;
1731         return &dn->components[0].value;
1732 }
1733
1734 int ldb_dn_set_component(struct ldb_dn *dn, int num,
1735                          const char *name, const struct ldb_val val)
1736 {
1737         char *n;
1738         struct ldb_val v;
1739
1740         if ( ! ldb_dn_validate(dn)) {
1741                 return LDB_ERR_OTHER;
1742         }
1743
1744         if (num >= dn->comp_num) {
1745                 return LDB_ERR_OTHER;
1746         }
1747
1748         n = talloc_strdup(dn, name);
1749         if ( ! n) {
1750                 return LDB_ERR_OTHER;
1751         }
1752
1753         v.length = val.length;
1754         v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1755         if ( ! v.data) {
1756                 talloc_free(n);
1757                 return LDB_ERR_OTHER;
1758         }
1759
1760         talloc_free(dn->components[num].name);
1761         talloc_free(dn->components[num].value.data);
1762         dn->components[num].name = n;
1763         dn->components[num].value = v;
1764
1765         if (dn->valid_case) {
1766                 int i;
1767                 for (i = 0; i < dn->comp_num; i++) {
1768                         LDB_FREE(dn->components[i].cf_name);
1769                         LDB_FREE(dn->components[i].cf_value.data);
1770                 }
1771                 dn->valid_case = false;
1772         }
1773         LDB_FREE(dn->casefold);
1774         LDB_FREE(dn->linearized);
1775
1776         /* Wipe the ext_linearized DN,
1777          * the GUID and SID are almost certainly no longer valid */
1778         LDB_FREE(dn->ext_linearized);
1779
1780         dn->ext_comp_num = 0;
1781         LDB_FREE(dn->ext_components);
1782         return LDB_SUCCESS;
1783 }
1784
1785 const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn,
1786                                                     const char *name)
1787 {
1788         int i;
1789         if ( ! ldb_dn_validate(dn)) {
1790                 return NULL;
1791         }
1792         for (i=0; i < dn->ext_comp_num; i++) {
1793                 if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
1794                         return &dn->ext_components[i].value;
1795                 }
1796         }
1797         return NULL;
1798 }
1799
1800 int ldb_dn_set_extended_component(struct ldb_dn *dn,
1801                                   const char *name, const struct ldb_val *val)
1802 {
1803         struct ldb_dn_ext_component *p;
1804         int i;
1805
1806         if ( ! ldb_dn_validate(dn)) {
1807                 return LDB_ERR_OTHER;
1808         }
1809
1810         for (i=0; i < dn->ext_comp_num; i++) {
1811                 if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
1812                         if (val) {
1813                                 dn->ext_components[i].value =
1814                                         ldb_val_dup(dn->ext_components, val);
1815
1816                                 dn->ext_components[i].name =
1817                                         talloc_strdup(dn->ext_components, name);
1818                                 if (!dn->ext_components[i].name ||
1819                                     !dn->ext_components[i].value.data) {
1820                                         dn->invalid = true;
1821                                         return LDB_ERR_OPERATIONS_ERROR;
1822                                 }
1823
1824                         } else {
1825                                 if (i != (dn->ext_comp_num - 1)) {
1826                                         memmove(&dn->ext_components[i],
1827                                                 &dn->ext_components[i+1],
1828                                                 ((dn->ext_comp_num-1) - i) *
1829                                                   sizeof(*dn->ext_components));
1830                                 }
1831                                 dn->ext_comp_num--;
1832
1833                                 dn->ext_components = talloc_realloc(dn,
1834                                                    dn->ext_components,
1835                                                    struct ldb_dn_ext_component,
1836                                                    dn->ext_comp_num);
1837                                 if (!dn->ext_components) {
1838                                         dn->invalid = true;
1839                                         return LDB_ERR_OPERATIONS_ERROR;
1840                                 }
1841                                 return LDB_SUCCESS;
1842                         }
1843                 }
1844         }
1845
1846         p = dn->ext_components
1847                 = talloc_realloc(dn,
1848                                  dn->ext_components,
1849                                  struct ldb_dn_ext_component,
1850                                  dn->ext_comp_num + 1);
1851         if (!dn->ext_components) {
1852                 dn->invalid = true;
1853                 return LDB_ERR_OPERATIONS_ERROR;
1854         }
1855
1856         p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, val);
1857         p[dn->ext_comp_num].name = talloc_strdup(p, name);
1858
1859         if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
1860                 dn->invalid = true;
1861                 return LDB_ERR_OPERATIONS_ERROR;
1862         }
1863         dn->ext_components = p;
1864         dn->ext_comp_num++;
1865
1866         return LDB_SUCCESS;
1867 }
1868
1869 void ldb_dn_remove_extended_components(struct ldb_dn *dn)
1870 {
1871         dn->ext_comp_num = 0;
1872         LDB_FREE(dn->ext_components);
1873 }
1874
1875 bool ldb_dn_is_valid(struct ldb_dn *dn)
1876 {
1877         if ( ! dn) return false;
1878         return ! dn->invalid;
1879 }
1880
1881 bool ldb_dn_is_special(struct ldb_dn *dn)
1882 {
1883         if ( ! dn || dn->invalid) return false;
1884         return dn->special;
1885 }
1886
1887 bool ldb_dn_has_extended(struct ldb_dn *dn)
1888 {
1889         if ( ! dn || dn->invalid) return false;
1890         if (dn->ext_linearized && (dn->ext_linearized[0] == '<')) return true;
1891         return dn->ext_comp_num != 0;
1892 }
1893
1894 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
1895 {
1896         if ( ! dn || dn->invalid) return false;
1897         return ! strcmp(dn->linearized, check);
1898 }
1899
1900 bool ldb_dn_is_null(struct ldb_dn *dn)
1901 {
1902         if ( ! dn || dn->invalid) return false;
1903         if (ldb_dn_has_extended(dn)) return false;
1904         if (dn->linearized && (dn->linearized[0] == '\0')) return true;
1905         return false;
1906 }