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