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
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 2 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, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * Component: ldb dn creation and manipulation utility functions
30 * Description: - explode a dn into it's own basic elements
31 * and put them in a structure (only if necessary)
32 * - manipulate ldb_dn structures
39 #include "ldb/include/includes.h"
41 #define LDB_DN_NULL_FAILED(x) if (!(x)) goto failed
43 #define LDB_FREE(x) do { talloc_free(x); x = NULL; } while(0)
46 internal ldb exploded dn structures
48 struct ldb_dn_component {
54 struct ldb_val cf_value;
59 struct ldb_context *ldb;
61 /* Special DNs are always linearized */
70 unsigned int comp_num;
71 struct ldb_dn_component *components;
75 /* strdn may be NULL */
76 struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
80 if ( (! mem_ctx) || (! ldb)) return NULL;
82 dn = talloc_zero(mem_ctx, struct ldb_dn);
83 LDB_DN_NULL_FAILED(dn);
88 if (strdn[0] == '@') {
91 if (strncasecmp(strdn, "<GUID=", 6) == 0) {
92 /* this is special DN returned when the
93 * exploded_dn control is used */
95 /* FIXME: add a GUID string to ldb_dn structure */
96 } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
97 /* this is special DN returned when the
98 * exploded_dn control is used */
100 /* FIXME: add a SID string to ldb_dn structure */
101 } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
102 /* this is special DN returned when the
103 * exploded_dn control is used */
105 /* FIXME: add a WKGUID string to ldb_dn structure */
107 dn->linearized = talloc_strdup(dn, strdn);
109 dn->linearized = talloc_strdup(dn, "");
111 LDB_DN_NULL_FAILED(dn->linearized);
120 struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
126 if ( (! mem_ctx) || (! ldb)) return NULL;
128 dn = talloc_zero(mem_ctx, struct ldb_dn);
129 LDB_DN_NULL_FAILED(dn);
133 va_start(ap, new_fmt);
134 strdn = talloc_vasprintf(dn, new_fmt, ap);
136 LDB_DN_NULL_FAILED(strdn);
138 if (strdn[0] == '@') {
141 if (strncasecmp(strdn, "<GUID=", 6) == 0) {
142 /* this is special DN returned when the
143 * exploded_dn control is used */
145 /* FIXME: add a GUID string to ldb_dn structure */
147 dn->linearized = strdn;
156 static int ldb_dn_escape_internal(char *dst, const char *src, int len)
165 while (p - src < len) {
167 p += strcspn(p, ",=\n+<>#;\\\"");
169 if (p - src == len) /* found no escapable chars */
172 memcpy(d, s, p - s); /* copy the part of the string before the stop */
173 d += (p - s); /* move to current position */
175 if (*p) { /* it is a normal escapable character */
178 } else { /* we have a zero byte in the string */
179 strncpy(d, "\00", 3); /* escape the zero */
181 p++; /* skip the zero */
183 s = p; /* move forward */
186 /* copy the last part (with zero) and return */
190 /* return the length of the resulting string */
191 return (l + (d - dst));
194 char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
201 /* allocate destination string, it will be at most 3 times the source */
202 dst = talloc_array(mem_ctx, char, value.length * 3 + 1);
208 ldb_dn_escape_internal(dst, (const char *)value.data, value.length);
210 dst = talloc_realloc(mem_ctx, dst, char, strlen(dst) + 1);
216 explode a DN string into a ldb_dn structure
217 based on RFC4514 except that we don't support multiple valued RDNs
219 static bool ldb_dn_explode(struct ldb_dn *dn)
221 char *p, *data, *d, *dt, *t;
223 bool in_attr = false;
224 bool in_value = false;
225 bool in_quote = false;
231 if ( ! dn || dn->invalid) return false;
233 if (dn->components) {
237 if ( ! dn->linearized) {
242 if (dn->linearized[0] == '\0') {
246 /* Special DNs case */
251 /* make sure we free this if alloced previously before replacing */
252 talloc_free(dn->components);
254 /* in the common case we have 3 or more components */
255 /* make sure all components are zeroed, other functions depend on this */
256 dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
257 if ( ! dn->components) {
262 /* Components data space is allocated here once */
263 data = talloc_array(dn->components, char, strlen(dn->linearized) + 1);
289 if ( ! isalpha(*p)) {
290 /* not a digit nor an alpha, invalid attribute name */
301 /* valid only if we are at the end */
306 if (trim && (*p != '=')) {
307 /* spaces/tabs are not allowed in attribute names */
313 /* attribute terminated */
320 dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
321 if ( ! dn->components[dn->comp_num].name) {
332 if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
333 /* not a digit nor a dot, invalid attribute oid */
337 if ( ! (isalpha(*p) || isdigit(*p) || (*p == '-'))) {
338 /* not ALPHA, DIGIT or HYPHEN */
379 /* TODO: support ber encoded values
390 /* ok found value terminator */
404 dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
405 dn->components[dn->comp_num].value.length = l;
406 if ( ! dn->components[dn->comp_num].value.data) {
414 if (dn->comp_num > 2) {
415 dn->components = talloc_realloc(dn,
417 struct ldb_dn_component,
419 if ( ! dn->components) {
423 /* make sure all components are zeroed, other functions depend on this */
424 memset(&dn->components[dn->comp_num], '\0', sizeof(struct ldb_dn_component));
437 /* a string with not escaped specials is invalid (tested) */
466 if (sscanf(p, "%02x", &x) != 1) {
467 /* invalid escaping sequence */
474 *d++ = (unsigned char)x;
496 if (in_attr || in_quote) {
502 /* save last element */
510 dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
511 dn->components[dn->comp_num].value.length = l;
513 if ( ! dn->components[dn->comp_num].value.data) {
525 talloc_free(dn->components);
529 bool ldb_dn_validate(struct ldb_dn *dn)
531 return ldb_dn_explode(dn);
534 const char *ldb_dn_get_linearized(struct ldb_dn *dn)
539 if ( ! dn || ( dn->invalid)) return NULL;
541 if (dn->linearized) return dn->linearized;
543 if ( ! dn->components) {
548 if (dn->comp_num == 0) {
549 dn->linearized = talloc_strdup(dn, "");
550 if ( ! dn->linearized) return NULL;
551 return dn->linearized;
554 /* calculate maximum possible length of DN */
555 for (len = 0, i = 0; i < dn->comp_num; i++) {
556 len += strlen(dn->components[i].name); /* name len */
557 len += (dn->components[i].value.length * 3); /* max escaped data len */
558 len += 2; /* '=' and ',' */
560 dn->linearized = talloc_array(dn, char, len);
561 if ( ! dn->linearized) return NULL;
565 for (i = 0; i < dn->comp_num; i++) {
568 n = dn->components[i].name;
569 while (*n) *d++ = *n++;
574 d += ldb_dn_escape_internal( d,
575 (char *)dn->components[i].value.data,
576 dn->components[i].value.length);
582 /* don't waste more memory than necessary */
583 dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));
585 return dn->linearized;
588 char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
590 return talloc_strdup(mem_ctx, ldb_dn_get_linearized(dn));
594 casefold a dn. We need to casefold the attribute names, and canonicalize
595 attribute values of case insensitive attributes.
598 static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
602 if ( ! dn || dn->invalid) return false;
604 if (dn->valid_case) return true;
606 if (( ! dn->components) && ( ! ldb_dn_explode(dn))) {
610 for (i = 0; i < dn->comp_num; i++) {
611 const struct ldb_attrib_handler *h;
613 dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
614 if (!dn->components[i].cf_name) {
618 h = ldb_attrib_handler(dn->ldb, dn->components[i].cf_name);
619 ret = h->canonicalise_fn(dn->ldb, dn->components,
620 &(dn->components[i].value),
621 &(dn->components[i].cf_value));
627 dn->valid_case = true;
632 for (i = 0; i < dn->comp_num; i++) {
633 LDB_FREE(dn->components[i].cf_name);
634 LDB_FREE(dn->components[i].cf_value.data);
639 const char *ldb_dn_get_casefold(struct ldb_dn *dn)
644 if (dn->casefold) return dn->casefold;
647 dn->casefold = talloc_strdup(dn, dn->linearized);
648 if (!dn->casefold) return NULL;
649 dn->valid_case = true;
653 if ( ! ldb_dn_casefold_internal(dn)) {
657 if (dn->comp_num == 0) {
658 if (dn->linearized && dn->linearized[0] == '\0') {
659 /* hmm a NULL dn, should we faild casefolding ? */
660 dn->casefold = talloc_strdup(dn, "");
663 /* A DN must be NULL, special, or have components */
668 /* calculate maximum possible length of DN */
669 for (len = 0, i = 0; i < dn->comp_num; i++) {
670 len += strlen(dn->components[i].cf_name); /* name len */
671 len += (dn->components[i].cf_value.length * 3); /* max escaped data len */
672 len += 2; /* '=' and ',' */
674 dn->casefold = talloc_array(dn, char, len);
675 if ( ! dn->casefold) return NULL;
679 for (i = 0; i < dn->comp_num; i++) {
682 n = dn->components[i].cf_name;
683 while (*n) *d++ = *n++;
688 d += ldb_dn_escape_internal( d,
689 (char *)dn->components[i].cf_value.data,
690 dn->components[i].cf_value.length);
695 /* don't waste more memory than necessary */
696 dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);
701 char *ldb_dn_alloc_casefold(void *mem_ctx, struct ldb_dn *dn)
703 return talloc_strdup(mem_ctx, ldb_dn_get_casefold(dn));
706 /* Determine if dn is below base, in the ldap tree. Used for
707 * evaluating a subtree search.
708 * 0 if they match, otherwise non-zero
711 int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
716 if ( ! base || base->invalid) return 1;
717 if ( ! dn || dn->invalid) return -1;
719 if (( ! base->valid_case) || ( ! dn->valid_case)) {
720 if (base->linearized && dn->linearized) {
721 /* try with a normal compare first, if we are lucky
722 * we will avoid exploding and casfolding */
724 dif = strlen(dn->linearized) - strlen(base->linearized);
725 if (dif < 0) return dif;
726 if (strcmp(base->linearized, &dn->linearized[dif]) == 0) return 0;
729 if ( ! ldb_dn_casefold_internal(base)) {
733 if ( ! ldb_dn_casefold_internal(dn)) {
739 /* if base has more components,
740 * they don't have the same base */
741 if (base->comp_num > dn->comp_num) {
742 return (dn->comp_num - base->comp_num);
745 if (dn->comp_num == 0) {
746 if (dn->special && base->special) {
747 return strcmp(base->linearized, dn->linearized);
748 } else if (dn->special) {
750 } else if (base->special) {
757 n_base = base->comp_num - 1;
758 n_dn = dn->comp_num - 1;
760 while (n_base >= 0) {
761 /* compare attr names */
762 ret = strcmp(base->components[n_base].cf_name, dn->components[n_dn].cf_name);
763 if (ret != 0) return ret;
765 /* compare attr.cf_value. */
766 if (base->components[n_base].cf_value.length != dn->components[n_dn].cf_value.length) {
767 return base->components[n_base].cf_value.length - dn->components[n_dn].cf_value.length;
769 ret = strcmp((char *)base->components[n_base].cf_value.data, (char *)dn->components[n_dn].cf_value.data);
770 if (ret != 0) return ret;
779 /* compare DNs using casefolding compare functions.
781 If they match, then return 0
784 int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
788 if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) return -1;
790 if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
791 if (dn0->linearized && dn1->linearized) {
792 /* try with a normal compare first, if we are lucky
793 * we will avoid exploding and casfolding */
794 if (strcmp(dn0->linearized, dn1->linearized) == 0) return 0;
797 if ( ! ldb_dn_casefold_internal(dn0)) {
801 if ( ! ldb_dn_casefold_internal(dn1)) {
807 if (dn0->comp_num != dn1->comp_num) {
808 return (dn1->comp_num - dn0->comp_num);
811 if (dn0->comp_num == 0) {
812 if (dn0->special && dn1->special) {
813 return strcmp(dn0->linearized, dn1->linearized);
814 } else if (dn0->special) {
816 } else if (dn1->special) {
823 for (i = 0; i < dn0->comp_num; i++) {
824 /* compare attr names */
825 ret = strcmp(dn0->components[i].cf_name, dn1->components[i].cf_name);
826 if (ret != 0) return ret;
828 /* compare attr.cf_value. */
829 if (dn0->components[i].cf_value.length != dn1->components[i].cf_value.length) {
830 return dn0->components[i].cf_value.length - dn1->components[i].cf_value.length;
832 ret = strcmp((char *)dn0->components[i].cf_value.data, (char *)dn1->components[i].cf_value.data);
833 if (ret != 0) return ret;
839 static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
841 struct ldb_dn_component dst;
843 memset(&dst, 0, sizeof(dst));
849 dst.value = ldb_val_dup(mem_ctx, &(src->value));
850 if (dst.value.data == NULL) {
854 dst.name = talloc_strdup(mem_ctx, src->name);
855 if (dst.name == NULL) {
856 LDB_FREE(dst.value.data);
860 if (src->cf_value.data) {
861 dst.cf_value = ldb_val_dup(mem_ctx, &(src->cf_value));
862 if (dst.cf_value.data == NULL) {
863 LDB_FREE(dst.value.data);
868 dst.cf_name = talloc_strdup(mem_ctx, src->cf_name);
869 if (dst.cf_name == NULL) {
870 LDB_FREE(dst.cf_name);
871 LDB_FREE(dst.value.data);
876 dst.cf_value.data = NULL;
883 struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
885 struct ldb_dn *new_dn;
887 if (!dn || dn->invalid) {
891 new_dn = talloc_zero(mem_ctx, struct ldb_dn);
898 if (dn->components) {
901 new_dn->components = talloc_zero_array(new_dn, struct ldb_dn_component, dn->comp_num);
902 if ( ! new_dn->components) {
907 for (i = 0; i < dn->comp_num; i++) {
908 new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &dn->components[i]);
909 if ( ! new_dn->components[i].value.data) {
917 new_dn->casefold = talloc_strdup(new_dn, dn->casefold);
918 if ( ! new_dn->casefold) {
924 if (dn->linearized) {
925 new_dn->linearized = talloc_strdup(new_dn, dn->linearized);
926 if ( ! new_dn->linearized) {
935 /* modify the given dn by adding a base.
937 * return true if successful and false if not
938 * if false is returned the dn may be marked invalid
940 bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
945 if ( !base || base->invalid || !dn || dn->invalid) {
949 if (dn->components) {
952 if ( ! ldb_dn_validate(base)) {
957 if (dn->valid_case) {
958 if ( ! (s = ldb_dn_get_casefold(base))) {
963 dn->components = talloc_realloc(dn,
965 struct ldb_dn_component,
966 dn->comp_num + base->comp_num);
967 if ( ! dn->components) {
972 for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
973 dn->components[dn->comp_num] = ldb_dn_copy_component(dn->components, &base->components[i]);
974 if (dn->components[dn->comp_num].value.data == NULL) {
980 if (dn->casefold && s) {
981 t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
982 LDB_FREE(dn->casefold);
987 if (dn->linearized) {
989 s = ldb_dn_get_linearized(base);
994 t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
999 LDB_FREE(dn->linearized);
1006 /* modify the given dn by adding a base.
1008 * return true if successful and false if not
1009 * if false is returned the dn may be marked invalid
1011 bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
1013 struct ldb_dn *base;
1018 if ( !dn || dn->invalid) {
1022 va_start(ap, base_fmt);
1023 base_str = talloc_vasprintf(dn, base_fmt, ap);
1026 if (base_str == NULL) {
1030 base = ldb_dn_new(base_str, dn->ldb, base_str);
1032 ret = ldb_dn_add_base(dn, base);
1034 talloc_free(base_str);
1039 /* modify the given dn by adding children elements.
1041 * return true if successful and false if not
1042 * if false is returned the dn may be marked invalid
1044 bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
1049 if ( !child || child->invalid || !dn || dn->invalid) {
1053 if (dn->components) {
1056 if ( ! ldb_dn_validate(child)) {
1061 if (dn->valid_case) {
1062 if ( ! (s = ldb_dn_get_casefold(child))) {
1067 n = dn->comp_num + child->comp_num;
1069 dn->components = talloc_realloc(dn,
1071 struct ldb_dn_component,
1073 if ( ! dn->components) {
1078 for (i = dn->comp_num - 1, j = n - 1; i >= 0; i--, j--) {
1079 dn->components[j] = dn->components[i];
1082 for (i = 0; i < child->comp_num; i++) {
1083 dn->components[i] = ldb_dn_copy_component(dn->components, &child->components[i]);
1084 if (dn->components[i].value.data == NULL) {
1092 if (dn->casefold && s) {
1093 t = talloc_asprintf(dn, "%s,%s", s, dn->casefold);
1094 LDB_FREE(dn->casefold);
1099 if (dn->linearized) {
1101 s = ldb_dn_get_linearized(child);
1106 t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
1111 LDB_FREE(dn->linearized);
1118 /* modify the given dn by adding children elements.
1120 * return true if successful and false if not
1121 * if false is returned the dn may be marked invalid
1123 bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
1125 struct ldb_dn *child;
1130 if ( !dn || dn->invalid) {
1134 va_start(ap, child_fmt);
1135 child_str = talloc_vasprintf(dn, child_fmt, ap);
1138 if (child_str == NULL) {
1142 child = ldb_dn_new(child_str, dn->ldb, child_str);
1144 ret = ldb_dn_add_child(dn, child);
1146 talloc_free(child_str);
1151 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
1155 if ( ! ldb_dn_validate(dn)) {
1159 if (dn->comp_num < num) {
1163 /* free components */
1164 for (i = num; i > 0; i--) {
1165 LDB_FREE(dn->components[dn->comp_num - i].name);
1166 LDB_FREE(dn->components[dn->comp_num - i].value.data);
1167 LDB_FREE(dn->components[dn->comp_num - i].cf_name);
1168 LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
1171 dn->comp_num -= num;
1173 if (dn->valid_case) {
1174 for (i = 0; i < dn->comp_num; i++) {
1175 LDB_FREE(dn->components[i].cf_name);
1176 LDB_FREE(dn->components[i].cf_value.data);
1178 dn->valid_case = false;
1181 LDB_FREE(dn->casefold);
1182 LDB_FREE(dn->linearized);
1187 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
1191 if ( ! ldb_dn_validate(dn)) {
1195 if (dn->comp_num < num) {
1199 for (i = 0, j = num; j < dn->comp_num; i++, j++) {
1201 LDB_FREE(dn->components[i].name);
1202 LDB_FREE(dn->components[i].value.data);
1203 LDB_FREE(dn->components[i].cf_name);
1204 LDB_FREE(dn->components[i].cf_value.data);
1206 dn->components[i] = dn->components[j];
1209 dn->comp_num -= num;
1211 if (dn->valid_case) {
1212 for (i = 0; i < dn->comp_num; i++) {
1213 LDB_FREE(dn->components[i].cf_name);
1214 LDB_FREE(dn->components[i].cf_value.data);
1216 dn->valid_case = false;
1219 LDB_FREE(dn->casefold);
1220 LDB_FREE(dn->linearized);
1225 struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
1227 struct ldb_dn *new_dn;
1229 new_dn = ldb_dn_copy(mem_ctx, dn);
1234 if ( ! ldb_dn_remove_child_components(new_dn, 1)) {
1235 talloc_free(new_dn);
1242 /* Create a 'canonical name' string from a DN:
1244 ie dc=samba,dc=org -> samba.org/
1245 uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
1247 There are two formats, the EX format has the last / replaced with a newline (\n).
1250 static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
1253 char *cracked = NULL;
1255 if ( ! ldb_dn_validate(dn)) {
1259 tmpctx = talloc_new(mem_ctx);
1261 /* Walk backwards down the DN, grabbing 'dc' components at first */
1262 for (i = dn->comp_num - 1 ; i >= 0; i--) {
1263 if (ldb_attr_cmp(dn->components[i].name, "dc") != 0) {
1267 cracked = talloc_asprintf(tmpctx, "%s.%s",
1268 ldb_dn_escape_value(tmpctx, dn->components[i].value),
1271 cracked = ldb_dn_escape_value(tmpctx, dn->components[i].value);
1278 /* Only domain components? Finish here */
1281 cracked = talloc_append_string(tmpctx, cracked, "\n");
1283 cracked = talloc_append_string(tmpctx, cracked, "/");
1285 talloc_steal(mem_ctx, cracked);
1289 /* Now walk backwards appending remaining components */
1290 for (; i > 0; i--) {
1291 cracked = talloc_asprintf_append(cracked, "/%s",
1292 ldb_dn_escape_value(tmpctx, dn->components[i].value));
1298 /* Last one, possibly a newline for the 'ex' format */
1300 cracked = talloc_asprintf_append(cracked, "\n%s",
1301 ldb_dn_escape_value(tmpctx, dn->components[i].value));
1303 cracked = talloc_asprintf_append(cracked, "/%s",
1304 ldb_dn_escape_value(tmpctx, dn->components[i].value));
1307 talloc_steal(mem_ctx, cracked);
1309 talloc_free(tmpctx);
1313 /* Wrapper functions for the above, for the two different string formats */
1314 char *ldb_dn_canonical_string(void *mem_ctx, struct ldb_dn *dn) {
1315 return ldb_dn_canonical(mem_ctx, dn, 0);
1319 char *ldb_dn_canonical_ex_string(void *mem_ctx, struct ldb_dn *dn) {
1320 return ldb_dn_canonical(mem_ctx, dn, 1);
1323 int ldb_dn_get_comp_num(struct ldb_dn *dn)
1325 if ( ! ldb_dn_validate(dn)) {
1328 return dn->comp_num;
1331 const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
1333 if ( ! ldb_dn_validate(dn)) {
1336 if (num >= dn->comp_num) return NULL;
1337 return dn->components[num].name;
1340 const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num)
1342 if ( ! ldb_dn_validate(dn)) {
1345 if (num >= dn->comp_num) return NULL;
1346 return &dn->components[num].value;
1349 const char *ldb_dn_get_rdn_name(struct ldb_dn *dn)
1351 if ( ! ldb_dn_validate(dn)) {
1354 if (dn->comp_num == 0) return NULL;
1355 return dn->components[0].name;
1358 const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
1360 if ( ! ldb_dn_validate(dn)) {
1363 if (dn->comp_num == 0) return NULL;
1364 return &dn->components[0].value;
1367 int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
1372 if ( ! ldb_dn_validate(dn)) {
1373 return LDB_ERR_OTHER;
1376 if (num >= dn->comp_num) {
1377 return LDB_ERR_OTHER;
1380 n = talloc_strdup(dn, name);
1382 return LDB_ERR_OTHER;
1385 v.length = val.length;
1386 v.data = (uint8_t *)talloc_memdup(dn, val.data, v.length+1);
1389 return LDB_ERR_OTHER;
1392 talloc_free(dn->components[num].name);
1393 talloc_free(dn->components[num].value.data);
1394 dn->components[num].name = n;
1395 dn->components[num].value = v;
1397 if (dn->valid_case) {
1399 for (i = 0; i < dn->comp_num; i++) {
1400 LDB_FREE(dn->components[i].cf_name);
1401 LDB_FREE(dn->components[i].cf_value.data);
1403 dn->valid_case = false;
1405 LDB_FREE(dn->casefold);
1410 bool ldb_dn_is_valid(struct ldb_dn *dn)
1412 if ( ! dn) return false;
1413 return ! dn->invalid;
1416 bool ldb_dn_is_special(struct ldb_dn *dn)
1418 if ( ! dn || dn->invalid) return false;
1422 bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
1424 if ( ! dn || dn->invalid) return false;
1425 return ! strcmp(dn->linearized, check);
1428 bool ldb_dn_is_null(struct ldb_dn *dn)
1430 if ( ! dn || dn->invalid) return false;
1431 if (dn->linearized && (dn->linearized[0] == '\0')) return true;