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