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