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