LDB:common - Change counters to "unsigned" where appropriate
[Samba/cd1.git] / source4 / lib / ldb / common / ldb_dn.c
blobd91e9d9fa9bbbcb1da602d84a854776a8cfa78d3
1 /*
2 ldb database library
4 Copyright (C) Simo Sorce 2005
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
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.
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.
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/>.
25 * Name: ldb
27 * Component: ldb dn creation and manipulation utility functions
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
33 * Author: Simo Sorce
36 #include "ldb_private.h"
37 #include <ctype.h>
39 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
41 #define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
43 /**
44 internal ldb exploded dn structures
46 struct ldb_dn_component {
48 char *name;
49 struct ldb_val value;
51 char *cf_name;
52 struct ldb_val cf_value;
55 struct ldb_dn_ext_component {
57 char *name;
58 struct ldb_val value;
61 struct ldb_dn {
63 struct ldb_context *ldb;
65 /* Special DNs are always linearized */
66 bool special;
67 bool invalid;
69 bool valid_case;
71 char *linearized;
72 char *ext_linearized;
73 char *casefold;
75 unsigned int comp_num;
76 struct ldb_dn_component *components;
78 unsigned int ext_comp_num;
79 struct ldb_dn_ext_component *ext_components;
82 /* it is helpful to be able to break on this in gdb */
83 static void ldb_dn_mark_invalid(struct ldb_dn *dn)
85 dn->invalid = true;
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)
93 struct ldb_dn *dn;
95 if (! ldb) return NULL;
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;
103 dn = talloc_zero(mem_ctx, struct ldb_dn);
104 LDB_DN_NULL_FAILED(dn);
106 dn->ldb = talloc_get_type(ldb, struct ldb_context);
107 if (dn->ldb == NULL) {
108 /* the caller probably got the arguments to
109 ldb_dn_new() mixed up */
110 talloc_free(dn);
111 return NULL;
114 if (strdn->data && strdn->length) {
115 const char *data = (const char *)strdn->data;
116 size_t length = strdn->length;
118 if (data[0] == '@') {
119 dn->special = true;
121 dn->ext_linearized = talloc_strndup(dn, data, length);
122 LDB_DN_NULL_FAILED(dn->ext_linearized);
124 if (data[0] == '<') {
125 const char *p_save, *p = dn->ext_linearized;
126 do {
127 p_save = p;
128 p = strstr(p, ">;");
129 if (p) {
130 p = p + 2;
132 } while (p);
134 if (p_save == dn->ext_linearized) {
135 dn->linearized = talloc_strdup(dn, "");
136 } else {
137 dn->linearized = talloc_strdup(dn, p_save);
139 LDB_DN_NULL_FAILED(dn->linearized);
140 } else {
141 dn->linearized = dn->ext_linearized;
142 dn->ext_linearized = NULL;
144 } else {
145 dn->linearized = talloc_strdup(dn, "");
146 LDB_DN_NULL_FAILED(dn->linearized);
149 return dn;
151 failed:
152 talloc_free(dn);
153 return NULL;
156 /* strdn may be NULL */
157 struct ldb_dn *ldb_dn_new(void *mem_ctx,
158 struct ldb_context *ldb,
159 const char *strdn)
161 struct ldb_val blob;
162 blob.data = discard_const_p(uint8_t, strdn);
163 blob.length = strdn ? strlen(strdn) : 0;
164 return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
167 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx,
168 struct ldb_context *ldb,
169 const char *new_fmt, ...)
171 char *strdn;
172 va_list ap;
174 if ( (! mem_ctx) || (! ldb)) return NULL;
176 va_start(ap, new_fmt);
177 strdn = talloc_vasprintf(mem_ctx, new_fmt, ap);
178 va_end(ap);
180 if (strdn) {
181 struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, strdn);
182 talloc_free(strdn);
183 return dn;
186 return NULL;
189 /* see RFC2253 section 2.4 */
190 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
192 const char *p, *s;
193 char *d;
194 size_t l;
196 p = s = src;
197 d = dst;
199 while (p - src < len) {
200 p += strcspn(p, ",=\n\r+<>#;\\\" ");
202 if (p - src == len) /* found no escapable chars */
203 break;
205 /* copy the part of the string before the stop */
206 memcpy(d, s, p - s);
207 d += (p - s); /* move to current position */
209 switch (*p) {
210 case ' ':
211 if (p == src || (p-src)==(len-1)) {
212 /* if at the beginning or end
213 * of the string then escape */
214 *d++ = '\\';
215 *d++ = *p++;
216 } else {
217 /* otherwise don't escape */
218 *d++ = *p++;
220 break;
222 case '#':
223 /* despite the RFC, windows escapes a #
224 anywhere in the string */
225 case ',':
226 case '+':
227 case '"':
228 case '\\':
229 case '<':
230 case '>':
231 case '?':
232 /* these must be escaped using \c form */
233 *d++ = '\\';
234 *d++ = *p++;
235 break;
237 default: {
238 /* any others get \XX form */
239 unsigned char v;
240 const char *hexbytes = "0123456789ABCDEF";
241 v = *(const unsigned char *)p;
242 *d++ = '\\';
243 *d++ = hexbytes[v>>4];
244 *d++ = hexbytes[v&0xF];
245 p++;
246 break;
249 s = p; /* move forward */
252 /* copy the last part (with zero) and return */
253 l = len - (s - src);
254 memcpy(d, s, l + 1);
256 /* return the length of the resulting string */
257 return (l + (d - dst));
260 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
262 char *dst;
264 if (!value.length)
265 return NULL;
267 /* allocate destination string, it will be at most 3 times the source */
268 dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
269 if ( ! dst) {
270 talloc_free(dst);
271 return NULL;
274 ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
276 dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
278 return dst;
282 explode a DN string into a ldb_dn structure
283 based on RFC4514 except that we don't support multiple valued RDNs
285 TODO: according to MS-ADTS:3.1.1.5.2 Naming Constraints
286 DN must be compliant with RFC2253
288 static bool ldb_dn_explode(struct ldb_dn *dn)
290 char *p, *ex_name, *ex_value, *data, *d, *dt, *t;
291 bool trim = false;
292 bool in_extended = false;
293 bool in_ex_name = false;
294 bool in_ex_value = false;
295 bool in_attr = false;
296 bool in_value = false;
297 bool in_quote = false;
298 bool is_oid = false;
299 bool escape = false;
300 unsigned int x;
301 size_t l;
302 int ret;
303 char *parse_dn;
304 bool is_index;
306 if ( ! dn || dn->invalid) return false;
308 if (dn->components) {
309 return true;
312 if (dn->ext_linearized) {
313 parse_dn = dn->ext_linearized;
314 } else {
315 parse_dn = dn->linearized;
318 if ( ! parse_dn ) {
319 return false;
322 is_index = (strncmp(parse_dn, "DN=@INDEX:", 10) == 0);
324 /* Empty DNs */
325 if (parse_dn[0] == '\0') {
326 return true;
329 /* Special DNs case */
330 if (dn->special) {
331 return true;
334 /* make sure we free this if alloced previously before replacing */
335 talloc_free(dn->components);
337 LDB_FREE(dn->ext_components);
338 dn->ext_comp_num = 0;
340 /* in the common case we have 3 or more components */
341 /* make sure all components are zeroed, other functions depend on it */
342 dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
343 if ( ! dn->components) {
344 return false;
346 dn->comp_num = 0;
348 /* Components data space is allocated here once */
349 data = talloc_array(dn->components, char, strlen(parse_dn) + 1);
350 if (!data) {
351 return false;
354 p = parse_dn;
355 in_extended = true;
356 in_ex_name = false;
357 in_ex_value = false;
358 trim = true;
359 t = NULL;
360 d = dt = data;
362 while (*p) {
363 if (in_extended) {
365 if (!in_ex_name && !in_ex_value) {
367 if (p[0] == '<') {
368 p++;
369 ex_name = d;
370 in_ex_name = true;
371 continue;
372 } else if (p[0] == '\0') {
373 p++;
374 continue;
375 } else {
376 in_extended = false;
377 in_attr = true;
378 dt = d;
380 continue;
384 if (in_ex_name && *p == '=') {
385 *d++ = '\0';
386 p++;
387 ex_value = d;
388 in_ex_name = false;
389 in_ex_value = true;
390 continue;
393 if (in_ex_value && *p == '>') {
394 const struct ldb_dn_extended_syntax *ext_syntax;
395 struct ldb_val ex_val = {
396 .data = (uint8_t *)ex_value,
397 .length = d - ex_value
400 *d++ = '\0';
401 p++;
402 in_ex_value = false;
404 /* Process name and ex_value */
406 dn->ext_components = talloc_realloc(dn,
407 dn->ext_components,
408 struct ldb_dn_ext_component,
409 dn->ext_comp_num + 1);
410 if ( ! dn->ext_components) {
411 /* ouch ! */
412 goto failed;
415 ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
416 if (!ext_syntax) {
417 /* We don't know about this type of extended DN */
418 goto failed;
421 dn->ext_components[dn->ext_comp_num].name = talloc_strdup(dn->ext_components, ex_name);
422 if (!dn->ext_components[dn->ext_comp_num].name) {
423 /* ouch */
424 goto failed;
426 ret = ext_syntax->read_fn(dn->ldb, dn->ext_components,
427 &ex_val, &dn->ext_components[dn->ext_comp_num].value);
428 if (ret != LDB_SUCCESS) {
429 ldb_dn_mark_invalid(dn);
430 goto failed;
433 dn->ext_comp_num++;
435 if (*p == '\0') {
436 /* We have reached the end (extended component only)! */
437 talloc_free(data);
438 return true;
440 } else if (*p == ';') {
441 p++;
442 continue;
443 } else {
444 ldb_dn_mark_invalid(dn);
445 goto failed;
449 *d++ = *p++;
450 continue;
452 if (in_attr) {
453 if (trim) {
454 if (*p == ' ') {
455 p++;
456 continue;
459 /* first char */
460 trim = false;
462 if (!isascii(*p)) {
463 /* attr names must be ascii only */
464 ldb_dn_mark_invalid(dn);
465 goto failed;
468 if (isdigit(*p)) {
469 is_oid = true;
470 } else
471 if ( ! isalpha(*p)) {
472 /* not a digit nor an alpha,
473 * invalid attribute name */
474 ldb_dn_mark_invalid(dn);
475 goto failed;
478 /* Copy this character across from parse_dn,
479 * now we have trimmed out spaces */
480 *d++ = *p++;
481 continue;
484 if (*p == ' ') {
485 p++;
486 /* valid only if we are at the end */
487 trim = true;
488 continue;
491 if (trim && (*p != '=')) {
492 /* spaces/tabs are not allowed */
493 ldb_dn_mark_invalid(dn);
494 goto failed;
497 if (*p == '=') {
498 /* attribute terminated */
499 in_attr = false;
500 in_value = true;
501 trim = true;
502 l = 0;
504 /* Terminate this string in d
505 * (which is a copy of parse_dn
506 * with spaces trimmed) */
507 *d++ = '\0';
508 dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
509 if ( ! dn->components[dn->comp_num].name) {
510 /* ouch */
511 goto failed;
514 dt = d;
516 p++;
517 continue;
520 if (!isascii(*p)) {
521 /* attr names must be ascii only */
522 ldb_dn_mark_invalid(dn);
523 goto failed;
526 if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
527 /* not a digit nor a dot,
528 * invalid attribute oid */
529 ldb_dn_mark_invalid(dn);
530 goto failed;
531 } else
532 if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
533 /* not ALPHA, DIGIT or HYPHEN */
534 ldb_dn_mark_invalid(dn);
535 goto failed;
538 *d++ = *p++;
539 continue;
542 if (in_value) {
543 if (in_quote) {
544 if (*p == '\"') {
545 if (p[-1] != '\\') {
546 p++;
547 in_quote = false;
548 continue;
551 *d++ = *p++;
552 l++;
553 continue;
556 if (trim) {
557 if (*p == ' ') {
558 p++;
559 continue;
562 /* first char */
563 trim = false;
565 if (*p == '\"') {
566 in_quote = true;
567 p++;
568 continue;
572 switch (*p) {
574 /* TODO: support ber encoded values
575 case '#':
578 case ',':
579 if (escape) {
580 *d++ = *p++;
581 l++;
582 escape = false;
583 continue;
585 /* ok found value terminator */
587 if ( t ) {
588 /* trim back */
589 d -= (p - t);
590 l -= (p - t);
593 in_attr = true;
594 in_value = false;
595 trim = true;
597 p++;
598 *d++ = '\0';
599 dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
600 dn->components[dn->comp_num].value.length = l;
601 if ( ! dn->components[dn->comp_num].value.data) {
602 /* ouch ! */
603 goto failed;
606 dt = d;
608 dn->comp_num++;
609 if (dn->comp_num > 2) {
610 dn->components = talloc_realloc(dn,
611 dn->components,
612 struct ldb_dn_component,
613 dn->comp_num + 1);
614 if ( ! dn->components) {
615 /* ouch ! */
616 goto failed;
618 /* make sure all components are zeroed, other functions depend on this */
619 memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
622 continue;
624 case '+':
625 case '=':
626 /* to main compatibility with earlier
627 versions of ldb indexing, we have to
628 accept the base64 encoded binary index
629 values, which contain a '+' or '='
630 which should normally be escaped */
631 if (is_index) {
632 if ( t ) t = NULL;
633 *d++ = *p++;
634 l++;
635 break;
637 /* fall through */
638 case '\"':
639 case '<':
640 case '>':
641 case ';':
642 /* a string with not escaped specials is invalid (tested) */
643 if ( ! escape) {
644 ldb_dn_mark_invalid(dn);
645 goto failed;
647 escape = false;
649 *d++ = *p++;
650 l++;
652 if ( t ) t = NULL;
653 break;
655 case '\\':
656 if ( ! escape) {
657 escape = true;
658 p++;
659 continue;
661 escape = false;
663 *d++ = *p++;
664 l++;
666 if ( t ) t = NULL;
667 break;
669 default:
670 if (escape) {
671 if (isxdigit(p[0]) && isxdigit(p[1])) {
672 if (sscanf(p, "%02x", &x) != 1) {
673 /* invalid escaping sequence */
674 ldb_dn_mark_invalid(dn);
675 goto failed;
677 p += 2;
678 *d++ = (unsigned char)x;
679 } else {
680 *d++ = *p++;
683 escape = false;
684 l++;
685 if ( t ) t = NULL;
686 break;
689 if (*p == ' ') {
690 if ( ! t) t = p;
691 } else {
692 if ( t ) t = NULL;
695 *d++ = *p++;
696 l++;
698 break;
704 if (in_attr || in_quote) {
705 /* invalid dn */
706 ldb_dn_mark_invalid(dn);
707 goto failed;
710 /* save last element */
711 if ( t ) {
712 /* trim back */
713 d -= (p - t);
714 l -= (p - t);
717 *d++ = '\0';
718 dn->components[dn->comp_num].value.length = l;
719 dn->components[dn->comp_num].value.data =
720 (uint8_t *)talloc_strdup(dn->components, dt);
721 if ( ! dn->components[dn->comp_num].value.data) {
722 /* ouch */
723 goto failed;
726 dn->comp_num++;
728 talloc_free(data);
729 return true;
731 failed:
732 dn->comp_num = 0;
733 talloc_free(dn->components);
734 return false;
737 bool ldb_dn_validate(struct ldb_dn *dn)
739 return ldb_dn_explode(dn);
742 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
744 unsigned int i;
745 size_t len;
746 char *d, *n;
748 if ( ! dn || ( dn->invalid)) return NULL;
750 if (dn->linearized) return dn->linearized;
752 if ( ! dn->components) {
753 ldb_dn_mark_invalid(dn);
754 return NULL;
757 if (dn->comp_num == 0) {
758 dn->linearized = talloc_strdup(dn, "");
759 if ( ! dn->linearized) return NULL;
760 return dn->linearized;
763 /* calculate maximum possible length of DN */
764 for (len = 0, i = 0; i < dn->comp_num; i++) {
765 /* name len */
766 len += strlen(dn->components[i].name);
767 /* max escaped data len */
768 len += (dn->components[i].value.length * 3);
769 len += 2; /* '=' and ',' */
771 dn->linearized = talloc_array(dn, char, len);
772 if ( ! dn->linearized) return NULL;
774 d = dn->linearized;
776 for (i = 0; i < dn->comp_num; i++) {
778 /* copy the name */
779 n = dn->components[i].name;
780 while (*n) *d++ = *n++;
782 *d++ = '=';
784 /* and the value */
785 d += ldb_dn_escape_internal( d,
786 (char *)dn->components[i].value.data,
787 dn->components[i].value.length);
788 *d++ = ',';
791 *(--d) = '\0';
793 /* don't waste more memory than necessary */
794 dn->linearized = talloc_realloc(dn, dn->linearized,
795 char, (d - dn->linearized + 1));
797 return dn->linearized;
800 static int ldb_dn_extended_component_compare(const void *p1, const void *p2)
802 const struct ldb_dn_ext_component *ec1 = (const struct ldb_dn_ext_component *)p1;
803 const struct ldb_dn_ext_component *ec2 = (const struct ldb_dn_ext_component *)p2;
804 return strcmp(ec1->name, ec2->name);
807 char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
809 const char *linearized = ldb_dn_get_linearized(dn);
810 char *p = NULL;
811 unsigned int i;
813 if (!linearized) {
814 return NULL;
817 if (!ldb_dn_has_extended(dn)) {
818 return talloc_strdup(mem_ctx, linearized);
821 if (!ldb_dn_validate(dn)) {
822 return NULL;
825 /* sort the extended components by name. The idea is to make
826 * the resulting DNs consistent, plus to ensure that we put
827 * 'DELETED' first, so it can be very quickly recognised
829 TYPESAFE_QSORT(dn->ext_components, dn->ext_comp_num,
830 ldb_dn_extended_component_compare);
832 for (i = 0; i < dn->ext_comp_num; i++) {
833 const struct ldb_dn_extended_syntax *ext_syntax;
834 const char *name = dn->ext_components[i].name;
835 struct ldb_val ec_val = dn->ext_components[i].value;
836 struct ldb_val val;
837 int ret;
839 ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
840 if (!ext_syntax) {
841 return NULL;
844 if (mode == 1) {
845 ret = ext_syntax->write_clear_fn(dn->ldb, mem_ctx,
846 &ec_val, &val);
847 } else if (mode == 0) {
848 ret = ext_syntax->write_hex_fn(dn->ldb, mem_ctx,
849 &ec_val, &val);
850 } else {
851 ret = -1;
854 if (ret != LDB_SUCCESS) {
855 return NULL;
858 if (i == 0) {
859 p = talloc_asprintf(mem_ctx, "<%s=%s>",
860 name, val.data);
861 } else {
862 p = talloc_asprintf_append_buffer(p, ";<%s=%s>",
863 name, val.data);
866 talloc_free(val.data);
868 if (!p) {
869 return NULL;
873 if (dn->ext_comp_num && *linearized) {
874 p = talloc_asprintf_append_buffer(p, ";%s", linearized);
877 if (!p) {
878 return NULL;
881 return p;
885 filter out all but an acceptable list of extended DN components
887 void ldb_dn_extended_filter(struct ldb_dn *dn, const char * const *accept)
889 unsigned int i;
890 for (i=0; i<dn->ext_comp_num; i++) {
891 if (!ldb_attr_in_list(accept, dn->ext_components[i].name)) {
892 memmove(&dn->ext_components[i],
893 &dn->ext_components[i+1],
894 (dn->ext_comp_num-(i+1))*sizeof(dn->ext_components[0]));
895 dn->ext_comp_num--;
896 i--;
899 LDB_FREE(dn->ext_linearized);
903 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
905 return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
909 casefold a dn. We need to casefold the attribute names, and canonicalize
910 attribute values of case insensitive attributes.
913 static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
915 unsigned int i;
916 int ret;
918 if ( ! dn || dn->invalid) return false;
920 if (dn->valid_case) return true;
922 if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
923 return false;
926 for (i = 0; i < dn->comp_num; i++) {
927 const struct ldb_schema_attribute *a;
929 dn->components[i].cf_name =
930 ldb_attr_casefold(dn->components,
931 dn->components[i].name);
932 if (!dn->components[i].cf_name) {
933 goto failed;
936 a = ldb_schema_attribute_by_name(dn->ldb,
937 dn->components[i].cf_name);
939 ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
940 &(dn->components[i].value),
941 &(dn->components[i].cf_value));
942 if (ret != 0) {
943 goto failed;
947 dn->valid_case = true;
949 return true;
951 failed:
952 for (i = 0; i < dn->comp_num; i++) {
953 LDB_FREE(dn->components[i].cf_name);
954 LDB_FREE(dn->components[i].cf_value.data);
956 return false;
959 const char *ldb_dn_get_casefold(struct ldb_dn *dn)
961 unsigned int i;
962 size_t len;
963 char *d, *n;
965 if (dn->casefold) return dn->casefold;
967 if (dn->special) {
968 dn->casefold = talloc_strdup(dn, dn->linearized);
969 if (!dn->casefold) return NULL;
970 dn->valid_case = true;
971 return dn->casefold;
974 if ( ! ldb_dn_casefold_internal(dn)) {
975 return NULL;
978 if (dn->comp_num == 0) {
979 dn->casefold = talloc_strdup(dn, "");
980 return dn->casefold;
983 /* calculate maximum possible length of DN */
984 for (len = 0, i = 0; i < dn->comp_num; i++) {
985 /* name len */
986 len += strlen(dn->components[i].cf_name);
987 /* max escaped data len */
988 len += (dn->components[i].cf_value.length * 3);
989 len += 2; /* '=' and ',' */
991 dn->casefold = talloc_array(dn, char, len);
992 if ( ! dn->casefold) return NULL;
994 d = dn->casefold;
996 for (i = 0; i < dn->comp_num; i++) {
998 /* copy the name */
999 n = dn->components[i].cf_name;
1000 while (*n) *d++ = *n++;
1002 *d++ = '=';
1004 /* and the value */
1005 d += ldb_dn_escape_internal( d,
1006 (char *)dn->components[i].cf_value.data,
1007 dn->components[i].cf_value.length);
1008 *d++ = ',';
1010 *(--d) = '\0';
1012 /* don't waste more memory than necessary */
1013 dn->casefold = talloc_realloc(dn, dn->casefold,
1014 char, strlen(dn->casefold) + 1);
1016 return dn->casefold;
1019 char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
1021 return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
1024 /* Determine if dn is below base, in the ldap tree. Used for
1025 * evaluating a subtree search.
1026 * 0 if they match, otherwise non-zero
1029 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
1031 int ret;
1032 long long int n_base, n_dn;
1034 if ( ! base || base->invalid) return 1;
1035 if ( ! dn || dn->invalid) return -1;
1037 if (( ! base->valid_case) || ( ! dn->valid_case)) {
1038 if (base->linearized && dn->linearized) {
1039 /* try with a normal compare first, if we are lucky
1040 * we will avoid exploding and casfolding */
1041 int dif;
1042 dif = strlen(dn->linearized) - strlen(base->linearized);
1043 if (dif < 0) {
1044 return dif;
1046 if (strcmp(base->linearized,
1047 &dn->linearized[dif]) == 0) {
1048 return 0;
1052 if ( ! ldb_dn_casefold_internal(base)) {
1053 return 1;
1056 if ( ! ldb_dn_casefold_internal(dn)) {
1057 return -1;
1062 /* if base has more components,
1063 * they don't have the same base */
1064 if (base->comp_num > dn->comp_num) {
1065 return (dn->comp_num - base->comp_num);
1068 if (dn->comp_num == 0) {
1069 if (dn->special && base->special) {
1070 return strcmp(base->linearized, dn->linearized);
1071 } else if (dn->special) {
1072 return -1;
1073 } else if (base->special) {
1074 return 1;
1075 } else {
1076 return 0;
1080 n_base = base->comp_num - 1;
1081 n_dn = dn->comp_num - 1;
1083 while (n_base >= 0) {
1084 char *b_name = base->components[n_base].cf_name;
1085 char *dn_name = dn->components[n_dn].cf_name;
1087 char *b_vdata = (char *)base->components[n_base].cf_value.data;
1088 char *dn_vdata = (char *)dn->components[n_dn].cf_value.data;
1090 size_t b_vlen = base->components[n_base].cf_value.length;
1091 size_t dn_vlen = dn->components[n_dn].cf_value.length;
1093 /* compare attr names */
1094 ret = strcmp(b_name, dn_name);
1095 if (ret != 0) return ret;
1097 /* compare attr.cf_value. */
1098 if (b_vlen != dn_vlen) {
1099 return b_vlen - dn_vlen;
1101 ret = strcmp(b_vdata, dn_vdata);
1102 if (ret != 0) return ret;
1104 n_base--;
1105 n_dn--;
1108 return 0;
1111 /* compare DNs using casefolding compare functions.
1113 If they match, then return 0
1116 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
1118 unsigned int i;
1119 int ret;
1121 if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
1122 return -1;
1125 if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
1126 if (dn0->linearized && dn1->linearized) {
1127 /* try with a normal compare first, if we are lucky
1128 * we will avoid exploding and casfolding */
1129 if (strcmp(dn0->linearized, dn1->linearized) == 0) {
1130 return 0;
1134 if ( ! ldb_dn_casefold_internal(dn0)) {
1135 return 1;
1138 if ( ! ldb_dn_casefold_internal(dn1)) {
1139 return -1;
1144 if (dn0->comp_num != dn1->comp_num) {
1145 return (dn1->comp_num - dn0->comp_num);
1148 if (dn0->comp_num == 0) {
1149 if (dn0->special && dn1->special) {
1150 return strcmp(dn0->linearized, dn1->linearized);
1151 } else if (dn0->special) {
1152 return 1;
1153 } else if (dn1->special) {
1154 return -1;
1155 } else {
1156 return 0;
1160 for (i = 0; i < dn0->comp_num; i++) {
1161 char *dn0_name = dn0->components[i].cf_name;
1162 char *dn1_name = dn1->components[i].cf_name;
1164 char *dn0_vdata = (char *)dn0->components[i].cf_value.data;
1165 char *dn1_vdata = (char *)dn1->components[i].cf_value.data;
1167 size_t dn0_vlen = dn0->components[i].cf_value.length;
1168 size_t dn1_vlen = dn1->components[i].cf_value.length;
1170 /* compare attr names */
1171 ret = strcmp(dn0_name, dn1_name);
1172 if (ret != 0) {
1173 return ret;
1176 /* compare attr.cf_value. */
1177 if (dn0_vlen != dn1_vlen) {
1178 return dn0_vlen - dn1_vlen;
1180 ret = strcmp(dn0_vdata, dn1_vdata);
1181 if (ret != 0) {
1182 return ret;
1186 return 0;
1189 static struct ldb_dn_component ldb_dn_copy_component(
1190 void *mem_ctx,
1191 struct ldb_dn_component *src)
1193 struct ldb_dn_component dst;
1195 memset(&dst, 0, sizeof(dst));
1197 if (src == NULL) {
1198 return dst;
1201 dst.value = ldb_val_dup(mem_ctx, &(src->value));
1202 if (dst.value.data == NULL) {
1203 return dst;
1206 dst.name = talloc_strdup(mem_ctx, src->name);
1207 if (dst.name == NULL) {
1208 LDB_FREE(dst.value.data);
1209 return dst;
1212 if (src->cf_value.data) {
1213 dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
1214 if (dst.cf_value.data == NULL) {
1215 LDB_FREE(dst.value.data);
1216 LDB_FREE(dst.name);
1217 return dst;
1220 dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
1221 if (dst.cf_name == NULL) {
1222 LDB_FREE(dst.cf_name);
1223 LDB_FREE(dst.value.data);
1224 LDB_FREE(dst.name);
1225 return dst;
1227 } else {
1228 dst.cf_value.data = NULL;
1229 dst.cf_name = NULL;
1232 return dst;
1235 static struct ldb_dn_ext_component ldb_dn_ext_copy_component(
1236 void *mem_ctx,
1237 struct ldb_dn_ext_component *src)
1239 struct ldb_dn_ext_component dst;
1241 memset(&dst, 0, sizeof(dst));
1243 if (src == NULL) {
1244 return dst;
1247 dst.value = ldb_val_dup(mem_ctx, &(src->value));
1248 if (dst.value.data == NULL) {
1249 return dst;
1252 dst.name = talloc_strdup(mem_ctx, src->name);
1253 if (dst.name == NULL) {
1254 LDB_FREE(dst.value.data);
1255 return dst;
1258 return dst;
1261 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
1263 struct ldb_dn *new_dn;
1265 if (!dn || dn->invalid) {
1266 return NULL;
1269 new_dn = talloc_zero(mem_ctx, struct ldb_dn);
1270 if ( !new_dn) {
1271 return NULL;
1274 *new_dn = *dn;
1276 if (dn->components) {
1277 unsigned int i;
1279 new_dn->components =
1280 talloc_zero_array(new_dn,
1281 struct ldb_dn_component,
1282 dn->comp_num);
1283 if ( ! new_dn->components) {
1284 talloc_free(new_dn);
1285 return NULL;
1288 for (i = 0; i < dn->comp_num; i++) {
1289 new_dn->components[i] =
1290 ldb_dn_copy_component(new_dn->components,
1291 &dn->components[i]);
1292 if ( ! new_dn->components[i].value.data) {
1293 talloc_free(new_dn);
1294 return NULL;
1299 if (dn->ext_components) {
1300 unsigned int i;
1302 new_dn->ext_components =
1303 talloc_zero_array(new_dn,
1304 struct ldb_dn_ext_component,
1305 dn->ext_comp_num);
1306 if ( ! new_dn->ext_components) {
1307 talloc_free(new_dn);
1308 return NULL;
1311 for (i = 0; i < dn->ext_comp_num; i++) {
1312 new_dn->ext_components[i] =
1313 ldb_dn_ext_copy_component(
1314 new_dn->ext_components,
1315 &dn->ext_components[i]);
1316 if ( ! new_dn->ext_components[i].value.data) {
1317 talloc_free(new_dn);
1318 return NULL;
1323 if (dn->casefold) {
1324 new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
1325 if ( ! new_dn->casefold) {
1326 talloc_free(new_dn);
1327 return NULL;
1331 if (dn->linearized) {
1332 new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
1333 if ( ! new_dn->linearized) {
1334 talloc_free(new_dn);
1335 return NULL;
1339 if (dn->ext_linearized) {
1340 new_dn->ext_linearized = talloc_strdup(new_dn,
1341 dn->ext_linearized);
1342 if ( ! new_dn->ext_linearized) {
1343 talloc_free(new_dn);
1344 return NULL;
1348 return new_dn;
1351 /* modify the given dn by adding a base.
1353 * return true if successful and false if not
1354 * if false is returned the dn may be marked invalid
1356 bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
1358 const char *s;
1359 char *t;
1361 if ( !base || base->invalid || !dn || dn->invalid) {
1362 return false;
1365 if (dn->components) {
1366 unsigned int i;
1368 if ( ! ldb_dn_validate(base)) {
1369 return false;
1372 s = NULL;
1373 if (dn->valid_case) {
1374 if ( ! (s = ldb_dn_get_casefold(base))) {
1375 return false;
1379 dn->components = talloc_realloc(dn,
1380 dn->components,
1381 struct ldb_dn_component,
1382 dn->comp_num + base->comp_num);
1383 if ( ! dn->components) {
1384 ldb_dn_mark_invalid(dn);
1385 return false;
1388 for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
1389 dn->components[dn->comp_num] =
1390 ldb_dn_copy_component(dn->components,
1391 &base->components[i]);
1392 if (dn->components[dn->comp_num].value.data == NULL) {
1393 ldb_dn_mark_invalid(dn);
1394 return false;
1398 if (dn->casefold && s) {
1399 if (*dn->casefold) {
1400 t = talloc_asprintf(dn, "%s,%s",
1401 dn->casefold, s);
1402 } else {
1403 t = talloc_strdup(dn, s);
1405 LDB_FREE(dn->casefold);
1406 dn->casefold = t;
1410 if (dn->linearized) {
1412 s = ldb_dn_get_linearized(base);
1413 if ( ! s) {
1414 return false;
1417 if (*dn->linearized) {
1418 t = talloc_asprintf(dn, "%s,%s",
1419 dn->linearized, s);
1420 } else {
1421 t = talloc_strdup(dn, s);
1423 if ( ! t) {
1424 ldb_dn_mark_invalid(dn);
1425 return false;
1427 LDB_FREE(dn->linearized);
1428 dn->linearized = t;
1431 /* Wipe the ext_linearized DN,
1432 * the GUID and SID are almost certainly no longer valid */
1433 LDB_FREE(dn->ext_linearized);
1435 LDB_FREE(dn->ext_components);
1436 dn->ext_comp_num = 0;
1437 return true;
1440 /* modify the given dn by adding a base.
1442 * return true if successful and false if not
1443 * if false is returned the dn may be marked invalid
1445 bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
1447 struct ldb_dn *base;
1448 char *base_str;
1449 va_list ap;
1450 bool ret;
1452 if ( !dn || dn->invalid) {
1453 return false;
1456 va_start(ap, base_fmt);
1457 base_str = talloc_vasprintf(dn, base_fmt, ap);
1458 va_end(ap);
1460 if (base_str == NULL) {
1461 return false;
1464 base = ldb_dn_new(base_str, dn->ldb, base_str);
1466 ret = ldb_dn_add_base(dn, base);
1468 talloc_free(base_str);
1470 return ret;
1473 /* modify the given dn by adding children elements.
1475 * return true if successful and false if not
1476 * if false is returned the dn may be marked invalid
1478 bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
1480 const char *s;
1481 char *t;
1483 if ( !child || child->invalid || !dn || dn->invalid) {
1484 return false;
1487 if (dn->components) {
1488 unsigned int n;
1489 long long int i, j;
1491 if ( ! ldb_dn_validate(child)) {
1492 return false;
1495 s = NULL;
1496 if (dn->valid_case) {
1497 if ( ! (s = ldb_dn_get_casefold(child))) {
1498 return false;
1502 n = dn->comp_num + child->comp_num;
1504 dn->components = talloc_realloc(dn,
1505 dn->components,
1506 struct ldb_dn_component,
1508 if ( ! dn->components) {
1509 ldb_dn_mark_invalid(dn);
1510 return false;
1513 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
1514 dn->components[j] = dn->components[i];
1517 for (i = 0; i < child->comp_num; i++) {
1518 dn->components[i] =
1519 ldb_dn_copy_component(dn->components,
1520 &child->components[i]);
1521 if (dn->components[i].value.data == NULL) {
1522 ldb_dn_mark_invalid(dn);
1523 return false;
1527 dn->comp_num = n;
1529 if (dn->casefold && s) {
1530 t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
1531 LDB_FREE(dn->casefold);
1532 dn->casefold = t;
1536 if (dn->linearized) {
1538 s = ldb_dn_get_linearized(child);
1539 if ( ! s) {
1540 return false;
1543 t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
1544 if ( ! t) {
1545 ldb_dn_mark_invalid(dn);
1546 return false;
1548 LDB_FREE(dn->linearized);
1549 dn->linearized = t;
1552 /* Wipe the ext_linearized DN,
1553 * the GUID and SID are almost certainly no longer valid */
1554 LDB_FREE(dn->ext_linearized);
1556 LDB_FREE(dn->ext_components);
1557 dn->ext_comp_num = 0;
1559 return true;
1562 /* modify the given dn by adding children elements.
1564 * return true if successful and false if not
1565 * if false is returned the dn may be marked invalid
1567 bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
1569 struct ldb_dn *child;
1570 char *child_str;
1571 va_list ap;
1572 bool ret;
1574 if ( !dn || dn->invalid) {
1575 return false;
1578 va_start(ap, child_fmt);
1579 child_str = talloc_vasprintf(dn, child_fmt, ap);
1580 va_end(ap);
1582 if (child_str == NULL) {
1583 return false;
1586 child = ldb_dn_new(child_str, dn->ldb, child_str);
1588 ret = ldb_dn_add_child(dn, child);
1590 talloc_free(child_str);
1592 return ret;
1595 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
1597 long long int i;
1599 if ( ! ldb_dn_validate(dn)) {
1600 return false;
1603 if (dn->comp_num < num) {
1604 return false;
1607 /* free components */
1608 for (i = num; i > 0; i--) {
1609 LDB_FREE(dn->components[dn->comp_num - i].name);
1610 LDB_FREE(dn->components[dn->comp_num - i].value.data);
1611 LDB_FREE(dn->components[dn->comp_num - i].cf_name);
1612 LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
1615 dn->comp_num -= num;
1617 if (dn->valid_case) {
1618 for (i = 0; i < dn->comp_num; i++) {
1619 LDB_FREE(dn->components[i].cf_name);
1620 LDB_FREE(dn->components[i].cf_value.data);
1622 dn->valid_case = false;
1625 LDB_FREE(dn->casefold);
1626 LDB_FREE(dn->linearized);
1628 /* Wipe the ext_linearized DN,
1629 * the GUID and SID are almost certainly no longer valid */
1630 LDB_FREE(dn->ext_linearized);
1632 LDB_FREE(dn->ext_components);
1633 dn->ext_comp_num = 0;
1635 return true;
1638 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
1640 unsigned int i, j;
1642 if ( ! ldb_dn_validate(dn)) {
1643 return false;
1646 if (dn->comp_num < num) {
1647 return false;
1650 for (i = 0, j = num; j < dn->comp_num; i++, j++) {
1651 if (i < num) {
1652 LDB_FREE(dn->components[i].name);
1653 LDB_FREE(dn->components[i].value.data);
1654 LDB_FREE(dn->components[i].cf_name);
1655 LDB_FREE(dn->components[i].cf_value.data);
1657 dn->components[i] = dn->components[j];
1660 dn->comp_num -= num;
1662 if (dn->valid_case) {
1663 for (i = 0; i < dn->comp_num; i++) {
1664 LDB_FREE(dn->components[i].cf_name);
1665 LDB_FREE(dn->components[i].cf_value.data);
1667 dn->valid_case = false;
1670 LDB_FREE(dn->casefold);
1671 LDB_FREE(dn->linearized);
1673 /* Wipe the ext_linearized DN,
1674 * the GUID and SID are almost certainly no longer valid */
1675 LDB_FREE(dn->ext_linearized);
1677 LDB_FREE(dn->ext_components);
1678 dn->ext_comp_num = 0;
1679 return true;
1682 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
1684 struct ldb_dn *new_dn;
1686 new_dn = ldb_dn_copy(mem_ctx, dn);
1687 if ( !new_dn ) {
1688 return NULL;
1691 if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
1692 talloc_free(new_dn);
1693 return NULL;
1696 /* Wipe the ext_linearized DN,
1697 * the GUID and SID are almost certainly no longer valid */
1698 LDB_FREE(dn->ext_linearized);
1700 LDB_FREE(dn->ext_components);
1701 dn->ext_comp_num = 0;
1702 return new_dn;
1705 /* Create a 'canonical name' string from a DN:
1707 ie dc=samba,dc=org -> samba.org/
1708 uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
1710 There are two formats,
1711 the EX format has the last '/' replaced with a newline (\n).
1714 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
1715 long long int i;
1716 TALLOC_CTX *tmpctx;
1717 char *cracked = NULL;
1718 const char *format = (ex_format ? "\n" : "/" );
1720 if ( ! ldb_dn_validate(dn)) {
1721 return NULL;
1724 tmpctx = talloc_new(mem_ctx);
1726 /* Walk backwards down the DN, grabbing 'dc' components at first */
1727 for (i = dn->comp_num - 1; i >= 0; i--) {
1728 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
1729 break;
1731 if (cracked) {
1732 cracked = talloc_asprintf(tmpctx, "%s.%s",
1733 ldb_dn_escape_value(tmpctx,
1734 dn->components[i].value),
1735 cracked);
1736 } else {
1737 cracked = ldb_dn_escape_value(tmpctx,
1738 dn->components[i].value);
1740 if (!cracked) {
1741 goto done;
1745 /* Only domain components? Finish here */
1746 if (i < 0) {
1747 cracked = talloc_strdup_append_buffer(cracked, format);
1748 talloc_steal(mem_ctx, cracked);
1749 goto done;
1752 /* Now walk backwards appending remaining components */
1753 for (; i > 0; i--) {
1754 cracked = talloc_asprintf_append_buffer(cracked, "/%s",
1755 ldb_dn_escape_value(tmpctx,
1756 dn->components[i].value));
1757 if (!cracked) {
1758 goto done;
1762 /* Last one, possibly a newline for the 'ex' format */
1763 cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
1764 ldb_dn_escape_value(tmpctx,
1765 dn->components[i].value));
1767 talloc_steal(mem_ctx, cracked);
1768 done:
1769 talloc_free(tmpctx);
1770 return cracked;
1773 /* Wrapper functions for the above, for the two different string formats */
1774 char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
1775 return ldb_dn_canonical(mem_ctx, dn, 0);
1779 char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
1780 return ldb_dn_canonical(mem_ctx, dn, 1);
1783 int ldb_dn_get_comp_num(struct ldb_dn *dn)
1785 if ( ! ldb_dn_validate(dn)) {
1786 return -1;
1788 return dn->comp_num;
1791 const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
1793 if ( ! ldb_dn_validate(dn)) {
1794 return NULL;
1796 if (num >= dn->comp_num) return NULL;
1797 return dn->components[num].name;
1800 const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn,
1801 unsigned int num)
1803 if ( ! ldb_dn_validate(dn)) {
1804 return NULL;
1806 if (num >= dn->comp_num) return NULL;
1807 return &dn->components[num].value;
1810 const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
1812 if ( ! ldb_dn_validate(dn)) {
1813 return NULL;
1815 if (dn->comp_num == 0) return NULL;
1816 return dn->components[0].name;
1819 const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
1821 if ( ! ldb_dn_validate(dn)) {
1822 return NULL;
1824 if (dn->comp_num == 0) return NULL;
1825 return &dn->components[0].value;
1828 int ldb_dn_set_component(struct ldb_dn *dn, int num,
1829 const char *name, const struct ldb_val val)
1831 char *n;
1832 struct ldb_val v;
1834 if ( ! ldb_dn_validate(dn)) {
1835 return LDB_ERR_OTHER;
1838 if (num >= dn->comp_num) {
1839 return LDB_ERR_OTHER;
1842 n = talloc_strdup(dn, name);
1843 if ( ! n) {
1844 return LDB_ERR_OTHER;
1847 v.length = val.length;
1848 v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1849 if ( ! v.data) {
1850 talloc_free(n);
1851 return LDB_ERR_OTHER;
1854 talloc_free(dn->components[num].name);
1855 talloc_free(dn->components[num].value.data);
1856 dn->components[num].name = n;
1857 dn->components[num].value = v;
1859 if (dn->valid_case) {
1860 unsigned int i;
1861 for (i = 0; i < dn->comp_num; i++) {
1862 LDB_FREE(dn->components[i].cf_name);
1863 LDB_FREE(dn->components[i].cf_value.data);
1865 dn->valid_case = false;
1867 LDB_FREE(dn->casefold);
1868 LDB_FREE(dn->linearized);
1870 /* Wipe the ext_linearized DN,
1871 * the GUID and SID are almost certainly no longer valid */
1872 LDB_FREE(dn->ext_linearized);
1874 dn->ext_comp_num = 0;
1875 LDB_FREE(dn->ext_components);
1876 return LDB_SUCCESS;
1879 const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn,
1880 const char *name)
1882 unsigned int i;
1883 if ( ! ldb_dn_validate(dn)) {
1884 return NULL;
1886 for (i=0; i < dn->ext_comp_num; i++) {
1887 if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
1888 return &dn->ext_components[i].value;
1891 return NULL;
1894 int ldb_dn_set_extended_component(struct ldb_dn *dn,
1895 const char *name, const struct ldb_val *val)
1897 struct ldb_dn_ext_component *p;
1898 unsigned int i;
1899 struct ldb_val v2;
1901 if ( ! ldb_dn_validate(dn)) {
1902 return LDB_ERR_OTHER;
1905 if (!ldb_dn_extended_syntax_by_name(dn->ldb, name)) {
1906 /* We don't know how to handle this type of thing */
1907 return LDB_ERR_INVALID_DN_SYNTAX;
1910 for (i=0; i < dn->ext_comp_num; i++) {
1911 if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
1912 if (val) {
1913 dn->ext_components[i].value =
1914 ldb_val_dup(dn->ext_components, val);
1916 dn->ext_components[i].name =
1917 talloc_strdup(dn->ext_components, name);
1918 if (!dn->ext_components[i].name ||
1919 !dn->ext_components[i].value.data) {
1920 ldb_dn_mark_invalid(dn);
1921 return LDB_ERR_OPERATIONS_ERROR;
1923 return LDB_SUCCESS;
1924 } else {
1925 if (i != (dn->ext_comp_num - 1)) {
1926 memmove(&dn->ext_components[i],
1927 &dn->ext_components[i+1],
1928 ((dn->ext_comp_num-1) - i) *
1929 sizeof(*dn->ext_components));
1931 dn->ext_comp_num--;
1933 dn->ext_components = talloc_realloc(dn,
1934 dn->ext_components,
1935 struct ldb_dn_ext_component,
1936 dn->ext_comp_num);
1937 if (!dn->ext_components) {
1938 ldb_dn_mark_invalid(dn);
1939 return LDB_ERR_OPERATIONS_ERROR;
1941 return LDB_SUCCESS;
1943 LDB_FREE(dn->ext_linearized);
1947 if (val == NULL) {
1948 /* removing a value that doesn't exist is not an error */
1949 return LDB_SUCCESS;
1952 v2 = *val;
1954 p = dn->ext_components
1955 = talloc_realloc(dn,
1956 dn->ext_components,
1957 struct ldb_dn_ext_component,
1958 dn->ext_comp_num + 1);
1959 if (!dn->ext_components) {
1960 ldb_dn_mark_invalid(dn);
1961 return LDB_ERR_OPERATIONS_ERROR;
1964 p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, &v2);
1965 p[dn->ext_comp_num].name = talloc_strdup(p, name);
1967 if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
1968 ldb_dn_mark_invalid(dn);
1969 return LDB_ERR_OPERATIONS_ERROR;
1971 dn->ext_components = p;
1972 dn->ext_comp_num++;
1974 return LDB_SUCCESS;
1977 void ldb_dn_remove_extended_components(struct ldb_dn *dn)
1979 dn->ext_comp_num = 0;
1980 LDB_FREE(dn->ext_components);
1981 LDB_FREE(dn->ext_linearized);
1984 bool ldb_dn_is_valid(struct ldb_dn *dn)
1986 if ( ! dn) return false;
1987 return ! dn->invalid;
1990 bool ldb_dn_is_special(struct ldb_dn *dn)
1992 if ( ! dn || dn->invalid) return false;
1993 return dn->special;
1996 bool ldb_dn_has_extended(struct ldb_dn *dn)
1998 if ( ! dn || dn->invalid) return false;
1999 if (dn->ext_linearized && (dn->ext_linearized[0] == '<')) return true;
2000 return dn->ext_comp_num != 0;
2003 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
2005 if ( ! dn || dn->invalid) return false;
2006 return ! strcmp(dn->linearized, check);
2009 bool ldb_dn_is_null(struct ldb_dn *dn)
2011 if ( ! dn || dn->invalid) return false;
2012 if (ldb_dn_has_extended(dn)) return false;
2013 if (dn->linearized && (dn->linearized[0] == '\0')) return true;
2014 return false;
2018 this updates dn->components, taking the components from ref_dn.
2019 This is used by code that wants to update the DN path of a DN
2020 while not impacting on the extended DN components
2022 int ldb_dn_update_components(struct ldb_dn *dn, const struct ldb_dn *ref_dn)
2024 dn->components = talloc_realloc(dn, dn->components,
2025 struct ldb_dn_component, ref_dn->comp_num);
2026 if (!dn->components) {
2027 return LDB_ERR_OPERATIONS_ERROR;
2029 memcpy(dn->components, ref_dn->components,
2030 sizeof(struct ldb_dn_component)*ref_dn->comp_num);
2031 dn->comp_num = ref_dn->comp_num;
2033 talloc_free(dn->linearized);
2034 talloc_free(dn->ext_linearized);
2035 dn->ext_linearized = NULL;
2036 dn->linearized = NULL;
2038 return LDB_SUCCESS;