CVE-2023-0614 ldb: Add functions for handling inaccessible message elements
[Samba.git] / lib / ldb / common / ldb_msg.c
blobcbc7e32b2ba668390feaebc3c718b0ae0e495d57
1 /*
2 ldb database library
4 Copyright (C) Andrew Tridgell 2004
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 message component utility functions
29 * Description: functions for manipulating ldb_message structures
31 * Author: Andrew Tridgell
34 #include "ldb_private.h"
37 create a new ldb_message in a given memory context (NULL for top level)
39 struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
41 return talloc_zero(mem_ctx, struct ldb_message);
45 find an element in a message by attribute name
47 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48 const char *attr_name)
50 unsigned int i;
51 for (i=0;i<msg->num_elements;i++) {
52 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53 return &msg->elements[i];
56 return NULL;
60 see if two ldb_val structures contain exactly the same data
61 return 1 for a match, 0 for a mis-match
63 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
65 if (v1->length != v2->length) return 0;
66 if (v1->data == v2->data) return 1;
67 if (v1->length == 0) return 1;
69 if (memcmp(v1->data, v2->data, v1->length) == 0) {
70 return 1;
73 return 0;
77 find a value in an element
78 assumes case sensitive comparison
80 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
81 struct ldb_val *val)
83 unsigned int i;
84 for (i=0;i<el->num_values;i++) {
85 if (ldb_val_equal_exact(val, &el->values[i])) {
86 return &el->values[i];
89 return NULL;
93 static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
95 if (v1->length != v2->length) {
96 return v1->length - v2->length;
98 return memcmp(v1->data, v2->data, v1->length);
103 ldb_msg_find_duplicate_val() will set the **duplicate pointer to the first
104 duplicate value it finds. It does a case sensitive comparison (memcmp).
106 LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
107 options flag, otherwise LDB_SUCCESS.
109 #define LDB_DUP_QUADRATIC_THRESHOLD 10
111 int ldb_msg_find_duplicate_val(struct ldb_context *ldb,
112 TALLOC_CTX *mem_ctx,
113 const struct ldb_message_element *el,
114 struct ldb_val **duplicate,
115 uint32_t options)
117 unsigned int i, j;
118 struct ldb_val *val;
120 if (options != 0) {
121 return LDB_ERR_OPERATIONS_ERROR;
124 *duplicate = NULL;
127 If there are not many values, it is best to avoid the talloc
128 overhead and just do a brute force search.
130 if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
131 for (j = 0; j < el->num_values; j++) {
132 val = &el->values[j];
133 for ( i = j + 1; i < el->num_values; i++) {
134 if (ldb_val_equal_exact(val, &el->values[i])) {
135 *duplicate = val;
136 return LDB_SUCCESS;
140 } else {
141 struct ldb_val *values;
142 values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
143 if (values == NULL) {
144 return LDB_ERR_OPERATIONS_ERROR;
147 memcpy(values, el->values,
148 el->num_values * sizeof(struct ldb_val));
149 TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
150 for (i = 1; i < el->num_values; i++) {
151 if (ldb_val_equal_exact(&values[i],
152 &values[i - 1])) {
153 /* find the original location */
154 for (j = 0; j < el->num_values; j++) {
155 if (ldb_val_equal_exact(&values[i],
156 &el->values[j])
158 *duplicate = &el->values[j];
159 break;
162 talloc_free(values);
163 if (*duplicate == NULL) {
164 /* how we got here, I don't know */
165 return LDB_ERR_OPERATIONS_ERROR;
167 return LDB_SUCCESS;
170 talloc_free(values);
172 return LDB_SUCCESS;
177 Determine whether the values in an element are also in another element.
179 Without any flags, return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS if the elements
180 share values, or LDB_SUCCESS if they don't. In this case, the function
181 simply determines the set intersection and it doesn't matter in which order
182 the elements are provided.
184 With the LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES flag, any values in common are
185 removed from the first element and LDB_SUCCESS is returned.
187 LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown option.
188 LDB_ERR_INAPPROPRIATE_MATCHING is returned if the elements differ in name.
191 int ldb_msg_find_common_values(struct ldb_context *ldb,
192 TALLOC_CTX *mem_ctx,
193 struct ldb_message_element *el,
194 struct ldb_message_element *el2,
195 uint32_t options)
197 struct ldb_val *values;
198 struct ldb_val *values2;
199 unsigned int i, j, k, n_values;
201 bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
203 if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
204 return LDB_ERR_OPERATIONS_ERROR;
207 if (strcmp(el->name, el2->name) != 0) {
208 return LDB_ERR_INAPPROPRIATE_MATCHING;
210 if (el->num_values == 0 || el2->num_values == 0) {
211 return LDB_SUCCESS;
214 With few values, it is better to do the brute-force search than the
215 clever search involving tallocs, memcpys, sorts, etc.
217 if (MIN(el->num_values, el2->num_values) == 1 ||
218 MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
219 for (i = 0; i < el2->num_values; i++) {
220 for (j = 0; j < el->num_values; j++) {
221 if (ldb_val_equal_exact(&el->values[j],
222 &el2->values[i])) {
223 if (! remove_duplicates) {
224 return \
225 LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
228 With the remove_duplicates flag, we
229 resolve the intersection by removing
230 the offending one from el.
232 el->num_values--;
233 for (k = j; k < el->num_values; k++) {
234 el->values[k] = \
235 el->values[k + 1];
237 j--; /* rewind */
241 return LDB_SUCCESS;
244 values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
245 if (values == NULL) {
246 return LDB_ERR_OPERATIONS_ERROR;
248 values2 = talloc_array(mem_ctx, struct ldb_val,
249 el2->num_values);
250 if (values2 == NULL) {
251 return LDB_ERR_OPERATIONS_ERROR;
254 memcpy(values, el->values,
255 el->num_values * sizeof(struct ldb_val));
256 memcpy(values2, el2->values,
257 el2->num_values * sizeof(struct ldb_val));
258 TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
259 TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp);
262 el->n_values may diverge from the number of values in the sorted
263 list when the remove_duplicates flag is used.
265 n_values = el->num_values;
266 i = 0;
267 j = 0;
268 while (i != n_values && j < el2->num_values) {
269 int ret = ldb_val_cmp(&values[i], &values2[j]);
270 if (ret < 0) {
271 i++;
272 } else if (ret > 0) {
273 j++;
274 } else {
275 /* we have a collision */
276 if (! remove_duplicates) {
277 TALLOC_FREE(values);
278 TALLOC_FREE(values2);
279 return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
282 With the remove_duplicates flag we need to find
283 this in the original list and remove it, which is
284 inefficient but hopefully rare.
286 for (k = 0; k < el->num_values; k++) {
287 if (ldb_val_equal_exact(&el->values[k],
288 &values[i])) {
289 break;
292 el->num_values--;
293 for (; k < el->num_values; k++) {
294 el->values[k] = el->values[k + 1];
296 i++;
299 TALLOC_FREE(values);
300 TALLOC_FREE(values2);
302 return LDB_SUCCESS;
306 duplicate a ldb_val structure
308 struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
310 struct ldb_val v2;
311 v2.length = v->length;
312 if (v->data == NULL) {
313 v2.data = NULL;
314 return v2;
317 /* the +1 is to cope with buggy C library routines like strndup
318 that look one byte beyond */
319 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
320 if (!v2.data) {
321 v2.length = 0;
322 return v2;
325 memcpy(v2.data, v->data, v->length);
326 ((char *)v2.data)[v->length] = 0;
327 return v2;
331 * Adds new empty element to msg->elements
333 static int _ldb_msg_add_el(struct ldb_message *msg,
334 struct ldb_message_element **return_el)
336 struct ldb_message_element *els;
339 * TODO: Find out a way to assert on input parameters.
340 * msg and return_el must be valid
343 els = talloc_realloc(msg, msg->elements,
344 struct ldb_message_element, msg->num_elements + 1);
345 if (!els) {
346 return LDB_ERR_OPERATIONS_ERROR;
349 ZERO_STRUCT(els[msg->num_elements]);
351 msg->elements = els;
352 msg->num_elements++;
354 *return_el = &els[msg->num_elements-1];
356 return LDB_SUCCESS;
360 * Add an empty element with a given name to a message
362 int ldb_msg_add_empty(struct ldb_message *msg,
363 const char *attr_name,
364 int flags,
365 struct ldb_message_element **return_el)
367 int ret;
368 struct ldb_message_element *el;
370 ret = _ldb_msg_add_el(msg, &el);
371 if (ret != LDB_SUCCESS) {
372 return ret;
375 /* initialize newly added element */
376 el->flags = flags;
377 el->name = talloc_strdup(msg->elements, attr_name);
378 if (!el->name) {
379 return LDB_ERR_OPERATIONS_ERROR;
382 if (return_el) {
383 *return_el = el;
386 return LDB_SUCCESS;
390 * Adds an element to a message.
392 * NOTE: Ownership of ldb_message_element fields
393 * is NOT transferred. Thus, if *el pointer
394 * is invalidated for some reason, this will
395 * corrupt *msg contents also
397 int ldb_msg_add(struct ldb_message *msg,
398 const struct ldb_message_element *el,
399 int flags)
401 int ret;
402 struct ldb_message_element *el_new;
403 /* We have to copy this, just in case *el is a pointer into
404 * what ldb_msg_add_empty() is about to realloc() */
405 struct ldb_message_element el_copy = *el;
407 ret = _ldb_msg_add_el(msg, &el_new);
408 if (ret != LDB_SUCCESS) {
409 return ret;
412 el_new->flags = flags;
413 el_new->name = el_copy.name;
414 el_new->num_values = el_copy.num_values;
415 el_new->values = el_copy.values;
417 return LDB_SUCCESS;
421 * add a value to a message element
423 int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
424 struct ldb_message_element *el,
425 const struct ldb_val *val)
427 struct ldb_val *vals;
429 if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
431 * Another message is using this message element's values array,
432 * so we don't want to make any modifications to the original
433 * message, or potentially invalidate its own values by calling
434 * talloc_realloc(). Make a copy instead.
436 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
438 vals = talloc_array(mem_ctx, struct ldb_val,
439 el->num_values + 1);
440 if (vals == NULL) {
441 return LDB_ERR_OPERATIONS_ERROR;
444 if (el->values != NULL) {
445 memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
447 } else {
448 vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
449 el->num_values + 1);
450 if (vals == NULL) {
451 return LDB_ERR_OPERATIONS_ERROR;
454 el->values = vals;
455 el->values[el->num_values] = *val;
456 el->num_values++;
458 return LDB_SUCCESS;
462 add a value to a message
464 int ldb_msg_add_value(struct ldb_message *msg,
465 const char *attr_name,
466 const struct ldb_val *val,
467 struct ldb_message_element **return_el)
469 struct ldb_message_element *el;
470 int ret;
472 el = ldb_msg_find_element(msg, attr_name);
473 if (!el) {
474 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
475 if (ret != LDB_SUCCESS) {
476 return ret;
480 ret = ldb_msg_element_add_value(msg->elements, el, val);
481 if (ret != LDB_SUCCESS) {
482 return ret;
485 if (return_el) {
486 *return_el = el;
489 return LDB_SUCCESS;
494 add a value to a message, stealing it into the 'right' place
496 int ldb_msg_add_steal_value(struct ldb_message *msg,
497 const char *attr_name,
498 struct ldb_val *val)
500 int ret;
501 struct ldb_message_element *el;
503 ret = ldb_msg_add_value(msg, attr_name, val, &el);
504 if (ret == LDB_SUCCESS) {
505 talloc_steal(el->values, val->data);
507 return ret;
512 add a string element to a message, specifying flags
514 int ldb_msg_add_string_flags(struct ldb_message *msg,
515 const char *attr_name, const char *str,
516 int flags)
518 struct ldb_val val;
519 int ret;
520 struct ldb_message_element *el = NULL;
522 val.data = discard_const_p(uint8_t, str);
523 val.length = strlen(str);
525 if (val.length == 0) {
526 /* allow empty strings as non-existent attributes */
527 return LDB_SUCCESS;
530 ret = ldb_msg_add_value(msg, attr_name, &val, &el);
531 if (ret != LDB_SUCCESS) {
532 return ret;
535 if (flags != 0) {
536 el->flags = flags;
539 return LDB_SUCCESS;
543 add a string element to a message
545 int ldb_msg_add_string(struct ldb_message *msg,
546 const char *attr_name, const char *str)
548 return ldb_msg_add_string_flags(msg, attr_name, str, 0);
552 add a string element to a message, stealing it into the 'right' place
554 int ldb_msg_add_steal_string(struct ldb_message *msg,
555 const char *attr_name, char *str)
557 struct ldb_val val;
559 val.data = (uint8_t *)str;
560 val.length = strlen(str);
562 if (val.length == 0) {
563 /* allow empty strings as non-existent attributes */
564 return LDB_SUCCESS;
567 return ldb_msg_add_steal_value(msg, attr_name, &val);
571 add a DN element to a message
572 WARNING: this uses the linearized string from the dn, and does not
573 copy the string.
575 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
576 struct ldb_dn *dn)
578 char *str = ldb_dn_alloc_linearized(msg, dn);
580 if (str == NULL) {
581 /* we don't want to have unknown DNs added */
582 return LDB_ERR_OPERATIONS_ERROR;
585 return ldb_msg_add_steal_string(msg, attr_name, str);
589 add a printf formatted element to a message
591 int ldb_msg_add_fmt(struct ldb_message *msg,
592 const char *attr_name, const char *fmt, ...)
594 struct ldb_val val;
595 va_list ap;
596 char *str;
598 va_start(ap, fmt);
599 str = talloc_vasprintf(msg, fmt, ap);
600 va_end(ap);
602 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
604 val.data = (uint8_t *)str;
605 val.length = strlen(str);
607 return ldb_msg_add_steal_value(msg, attr_name, &val);
610 static int ldb_msg_append_value_impl(struct ldb_message *msg,
611 const char *attr_name,
612 const struct ldb_val *val,
613 int flags,
614 struct ldb_message_element **return_el)
616 struct ldb_message_element *el = NULL;
617 int ret;
619 ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
620 if (ret != LDB_SUCCESS) {
621 return ret;
624 ret = ldb_msg_element_add_value(msg->elements, el, val);
625 if (ret != LDB_SUCCESS) {
626 return ret;
629 if (return_el != NULL) {
630 *return_el = el;
633 return LDB_SUCCESS;
637 append a value to a message
639 int ldb_msg_append_value(struct ldb_message *msg,
640 const char *attr_name,
641 const struct ldb_val *val,
642 int flags)
644 return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
648 append a value to a message, stealing it into the 'right' place
650 int ldb_msg_append_steal_value(struct ldb_message *msg,
651 const char *attr_name,
652 struct ldb_val *val,
653 int flags)
655 int ret;
656 struct ldb_message_element *el = NULL;
658 ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
659 if (ret == LDB_SUCCESS) {
660 talloc_steal(el->values, val->data);
662 return ret;
666 append a string element to a message, stealing it into the 'right' place
668 int ldb_msg_append_steal_string(struct ldb_message *msg,
669 const char *attr_name, char *str,
670 int flags)
672 struct ldb_val val;
674 val.data = (uint8_t *)str;
675 val.length = strlen(str);
677 if (val.length == 0) {
678 /* allow empty strings as non-existent attributes */
679 return LDB_SUCCESS;
682 return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
686 append a string element to a message
688 int ldb_msg_append_string(struct ldb_message *msg,
689 const char *attr_name, const char *str, int flags)
691 struct ldb_val val;
693 val.data = discard_const_p(uint8_t, str);
694 val.length = strlen(str);
696 if (val.length == 0) {
697 /* allow empty strings as non-existent attributes */
698 return LDB_SUCCESS;
701 return ldb_msg_append_value(msg, attr_name, &val, flags);
705 append a DN element to a message
706 WARNING: this uses the linearized string from the dn, and does not
707 copy the string.
709 int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
710 struct ldb_dn *dn, int flags)
712 char *str = ldb_dn_alloc_linearized(msg, dn);
714 if (str == NULL) {
715 /* we don't want to have unknown DNs added */
716 return LDB_ERR_OPERATIONS_ERROR;
719 return ldb_msg_append_steal_string(msg, attr_name, str, flags);
723 append a printf formatted element to a message
725 int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
726 const char *attr_name, const char *fmt, ...)
728 struct ldb_val val;
729 va_list ap;
730 char *str = NULL;
732 va_start(ap, fmt);
733 str = talloc_vasprintf(msg, fmt, ap);
734 va_end(ap);
736 if (str == NULL) {
737 return LDB_ERR_OPERATIONS_ERROR;
740 val.data = (uint8_t *)str;
741 val.length = strlen(str);
743 return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
747 compare two ldb_message_element structures
748 assumes case sensitive comparison
750 int ldb_msg_element_compare(struct ldb_message_element *el1,
751 struct ldb_message_element *el2)
753 unsigned int i;
755 if (el1->num_values != el2->num_values) {
756 return el1->num_values - el2->num_values;
759 for (i=0;i<el1->num_values;i++) {
760 if (!ldb_msg_find_val(el2, &el1->values[i])) {
761 return -1;
765 return 0;
769 compare two ldb_message_element structures.
770 Different ordering is considered a mismatch
772 bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
773 const struct ldb_message_element *el2)
775 unsigned i;
776 if (el1->num_values != el2->num_values) {
777 return false;
779 for (i=0;i<el1->num_values;i++) {
780 if (ldb_val_equal_exact(&el1->values[i],
781 &el2->values[i]) != 1) {
782 return false;
785 return true;
789 compare two ldb_message_element structures
790 comparing by element name
792 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
793 struct ldb_message_element *el2)
795 return ldb_attr_cmp(el1->name, el2->name);
798 void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
800 el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
803 bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
805 return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
808 void ldb_msg_remove_inaccessible(struct ldb_message *msg)
810 unsigned i;
811 unsigned num_del = 0;
813 for (i = 0; i < msg->num_elements; ++i) {
814 if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
815 ++num_del;
816 } else if (num_del) {
817 msg->elements[i - num_del] = msg->elements[i];
821 msg->num_elements -= num_del;
825 convenience functions to return common types from a message
826 these return the first value if the attribute is multi-valued
828 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
829 const char *attr_name)
831 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
832 if (!el || el->num_values == 0) {
833 return NULL;
835 return &el->values[0];
838 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
839 const char *attr_name,
840 int default_value)
842 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
843 char buf[sizeof("-2147483648")];
844 char *end = NULL;
845 int ret;
847 if (!v || !v->data) {
848 return default_value;
851 ZERO_STRUCT(buf);
852 if (v->length >= sizeof(buf)) {
853 return default_value;
856 memcpy(buf, v->data, v->length);
857 errno = 0;
858 ret = (int) strtoll(buf, &end, 10);
859 if (errno != 0) {
860 return default_value;
862 if (end && end[0] != '\0') {
863 return default_value;
865 return ret;
868 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
869 const char *attr_name,
870 unsigned int default_value)
872 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
873 char buf[sizeof("-2147483648")];
874 char *end = NULL;
875 unsigned int ret;
877 if (!v || !v->data) {
878 return default_value;
881 ZERO_STRUCT(buf);
882 if (v->length >= sizeof(buf)) {
883 return default_value;
886 memcpy(buf, v->data, v->length);
887 errno = 0;
888 ret = (unsigned int) strtoll(buf, &end, 10);
889 if (errno != 0) {
890 errno = 0;
891 ret = (unsigned int) strtoull(buf, &end, 10);
892 if (errno != 0) {
893 return default_value;
896 if (end && end[0] != '\0') {
897 return default_value;
899 return ret;
902 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
903 const char *attr_name,
904 int64_t default_value)
906 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
907 char buf[sizeof("-9223372036854775808")];
908 char *end = NULL;
909 int64_t ret;
911 if (!v || !v->data) {
912 return default_value;
915 ZERO_STRUCT(buf);
916 if (v->length >= sizeof(buf)) {
917 return default_value;
920 memcpy(buf, v->data, v->length);
921 errno = 0;
922 ret = (int64_t) strtoll(buf, &end, 10);
923 if (errno != 0) {
924 return default_value;
926 if (end && end[0] != '\0') {
927 return default_value;
929 return ret;
932 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
933 const char *attr_name,
934 uint64_t default_value)
936 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
937 char buf[sizeof("-9223372036854775808")];
938 char *end = NULL;
939 uint64_t ret;
941 if (!v || !v->data) {
942 return default_value;
945 ZERO_STRUCT(buf);
946 if (v->length >= sizeof(buf)) {
947 return default_value;
950 memcpy(buf, v->data, v->length);
951 errno = 0;
952 ret = (uint64_t) strtoll(buf, &end, 10);
953 if (errno != 0) {
954 errno = 0;
955 ret = (uint64_t) strtoull(buf, &end, 10);
956 if (errno != 0) {
957 return default_value;
960 if (end && end[0] != '\0') {
961 return default_value;
963 return ret;
966 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
967 const char *attr_name,
968 double default_value)
970 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
971 char *buf;
972 char *end = NULL;
973 double ret;
975 if (!v || !v->data) {
976 return default_value;
978 buf = talloc_strndup(msg, (const char *)v->data, v->length);
979 if (buf == NULL) {
980 return default_value;
983 errno = 0;
984 ret = strtod(buf, &end);
985 talloc_free(buf);
986 if (errno != 0) {
987 return default_value;
989 if (end && end[0] != '\0') {
990 return default_value;
992 return ret;
995 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
996 const char *attr_name,
997 int default_value)
999 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1000 if (!v || !v->data) {
1001 return default_value;
1003 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
1004 return 0;
1006 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
1007 return 1;
1009 return default_value;
1012 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
1013 const char *attr_name,
1014 const char *default_value)
1016 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1017 if (!v || !v->data) {
1018 return default_value;
1020 if (v->data[v->length] != '\0') {
1021 return default_value;
1023 return (const char *)v->data;
1026 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
1027 TALLOC_CTX *mem_ctx,
1028 const struct ldb_message *msg,
1029 const char *attr_name)
1031 struct ldb_dn *res_dn;
1032 const struct ldb_val *v;
1034 v = ldb_msg_find_ldb_val(msg, attr_name);
1035 if (!v || !v->data) {
1036 return NULL;
1038 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
1039 if ( ! ldb_dn_validate(res_dn)) {
1040 talloc_free(res_dn);
1041 return NULL;
1043 return res_dn;
1047 sort the elements of a message by name
1049 void ldb_msg_sort_elements(struct ldb_message *msg)
1051 TYPESAFE_QSORT(msg->elements, msg->num_elements,
1052 ldb_msg_element_compare_name);
1055 static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
1056 const struct ldb_message *msg)
1058 struct ldb_message *msg2;
1059 unsigned int i;
1061 msg2 = talloc(mem_ctx, struct ldb_message);
1062 if (msg2 == NULL) return NULL;
1064 *msg2 = *msg;
1066 msg2->elements = talloc_array(msg2, struct ldb_message_element,
1067 msg2->num_elements);
1068 if (msg2->elements == NULL) goto failed;
1070 for (i=0;i<msg2->num_elements;i++) {
1071 msg2->elements[i] = msg->elements[i];
1074 return msg2;
1076 failed:
1077 talloc_free(msg2);
1078 return NULL;
1082 shallow copy a message - copying only the elements array so that the caller
1083 can safely add new elements without changing the message
1085 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
1086 const struct ldb_message *msg)
1088 struct ldb_message *msg2;
1089 unsigned int i;
1091 msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1092 if (msg2 == NULL) {
1093 return NULL;
1096 for (i = 0; i < msg2->num_elements; ++i) {
1098 * Mark this message's elements as sharing their values with the
1099 * original message, so that we don't inadvertently modify or
1100 * free them. We don't mark the original message element as
1101 * shared, so the original message element should not be
1102 * modified or freed while the shallow copy lives.
1104 struct ldb_message_element *el = &msg2->elements[i];
1105 el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
1108 return msg2;
1112 copy a message, allocating new memory for all parts
1114 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
1115 const struct ldb_message *msg)
1117 struct ldb_message *msg2;
1118 unsigned int i, j;
1120 msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1121 if (msg2 == NULL) return NULL;
1123 if (msg2->dn != NULL) {
1124 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
1125 if (msg2->dn == NULL) goto failed;
1128 for (i=0;i<msg2->num_elements;i++) {
1129 struct ldb_message_element *el = &msg2->elements[i];
1130 struct ldb_val *values = el->values;
1131 el->name = talloc_strdup(msg2->elements, el->name);
1132 if (el->name == NULL) goto failed;
1133 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
1134 if (el->values == NULL) goto failed;
1135 for (j=0;j<el->num_values;j++) {
1136 el->values[j] = ldb_val_dup(el->values, &values[j]);
1137 if (el->values[j].data == NULL && values[j].length != 0) {
1138 goto failed;
1143 * Since we copied this element's values, we can mark them as
1144 * not shared.
1146 el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1149 return msg2;
1151 failed:
1152 talloc_free(msg2);
1153 return NULL;
1158 * Canonicalize a message, merging elements of the same name
1160 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
1161 const struct ldb_message *msg)
1163 int ret;
1164 struct ldb_message *msg2;
1167 * Preserve previous behavior and allocate
1168 * *msg2 into *ldb context
1170 ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
1171 if (ret != LDB_SUCCESS) {
1172 return NULL;
1175 return msg2;
1179 * Canonicalize a message, merging elements of the same name
1181 int ldb_msg_normalize(struct ldb_context *ldb,
1182 TALLOC_CTX *mem_ctx,
1183 const struct ldb_message *msg,
1184 struct ldb_message **_msg_out)
1186 unsigned int i;
1187 struct ldb_message *msg2;
1189 msg2 = ldb_msg_copy(mem_ctx, msg);
1190 if (msg2 == NULL) {
1191 return LDB_ERR_OPERATIONS_ERROR;
1194 ldb_msg_sort_elements(msg2);
1196 for (i=1; i < msg2->num_elements; i++) {
1197 struct ldb_message_element *el1 = &msg2->elements[i-1];
1198 struct ldb_message_element *el2 = &msg2->elements[i];
1200 if (ldb_msg_element_compare_name(el1, el2) == 0) {
1201 el1->values = talloc_realloc(msg2->elements,
1202 el1->values, struct ldb_val,
1203 el1->num_values + el2->num_values);
1204 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
1205 talloc_free(msg2);
1206 return LDB_ERR_OPERATIONS_ERROR;
1208 memcpy(el1->values + el1->num_values,
1209 el2->values,
1210 sizeof(struct ldb_val) * el2->num_values);
1211 el1->num_values += el2->num_values;
1212 talloc_free(discard_const_p(char, el2->name));
1213 if ((i+1) < msg2->num_elements) {
1214 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
1215 (msg2->num_elements - (i+1)));
1217 msg2->num_elements--;
1218 i--;
1222 *_msg_out = msg2;
1223 return LDB_SUCCESS;
1228 * return a ldb_message representing the differences between msg1 and msg2.
1229 * If you then use this in a ldb_modify() call,
1230 * it can be used to save edits to a message
1232 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
1233 struct ldb_message *msg1,
1234 struct ldb_message *msg2)
1236 int ldb_ret;
1237 struct ldb_message *mod;
1239 ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
1240 if (ldb_ret != LDB_SUCCESS) {
1241 return NULL;
1244 return mod;
1248 * return a ldb_message representing the differences between msg1 and msg2.
1249 * If you then use this in a ldb_modify() call it can be used to save edits to a message
1251 * Result message is constructed as follows:
1252 * - LDB_FLAG_MOD_ADD - elements found only in msg2
1253 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1254 * Value for msg2 element is used
1255 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
1257 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1259 int ldb_msg_difference(struct ldb_context *ldb,
1260 TALLOC_CTX *mem_ctx,
1261 struct ldb_message *msg1,
1262 struct ldb_message *msg2,
1263 struct ldb_message **_msg_out)
1265 int ldb_res;
1266 unsigned int i;
1267 struct ldb_message *mod;
1268 struct ldb_message_element *el;
1269 TALLOC_CTX *temp_ctx;
1271 temp_ctx = talloc_new(mem_ctx);
1272 if (!temp_ctx) {
1273 return LDB_ERR_OPERATIONS_ERROR;
1276 mod = ldb_msg_new(temp_ctx);
1277 if (mod == NULL) {
1278 goto failed;
1281 mod->dn = msg1->dn;
1282 mod->num_elements = 0;
1283 mod->elements = NULL;
1286 * Canonicalize *msg2 so we have no repeated elements
1287 * Resulting message is allocated in *mod's mem context,
1288 * as we are going to move some elements from *msg2 to
1289 * *mod object later
1291 ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
1292 if (ldb_res != LDB_SUCCESS) {
1293 goto failed;
1296 /* look in msg2 to find elements that need to be added or modified */
1297 for (i=0;i<msg2->num_elements;i++) {
1298 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
1300 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
1301 continue;
1304 ldb_res = ldb_msg_add(mod,
1305 &msg2->elements[i],
1306 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
1307 if (ldb_res != LDB_SUCCESS) {
1308 goto failed;
1312 /* look in msg1 to find elements that need to be deleted */
1313 for (i=0;i<msg1->num_elements;i++) {
1314 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
1315 if (el == NULL) {
1316 ldb_res = ldb_msg_add_empty(mod,
1317 msg1->elements[i].name,
1318 LDB_FLAG_MOD_DELETE, NULL);
1319 if (ldb_res != LDB_SUCCESS) {
1320 goto failed;
1325 /* steal resulting message into supplied context */
1326 talloc_steal(mem_ctx, mod);
1327 *_msg_out = mod;
1329 talloc_free(temp_ctx);
1330 return LDB_SUCCESS;
1332 failed:
1333 talloc_free(temp_ctx);
1334 return LDB_ERR_OPERATIONS_ERROR;
1338 int ldb_msg_sanity_check(struct ldb_context *ldb,
1339 const struct ldb_message *msg)
1341 unsigned int i, j;
1343 /* basic check on DN */
1344 if (msg->dn == NULL) {
1345 ldb_set_errstring(ldb, "ldb message lacks a DN!");
1346 return LDB_ERR_INVALID_DN_SYNTAX;
1349 /* basic syntax checks */
1350 for (i = 0; i < msg->num_elements; i++) {
1351 for (j = 0; j < msg->elements[i].num_values; j++) {
1352 if (msg->elements[i].values[j].length == 0) {
1353 /* an attribute cannot be empty */
1354 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
1355 msg->elements[i].name,
1356 ldb_dn_get_linearized(msg->dn));
1357 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1362 return LDB_SUCCESS;
1369 copy an attribute list. This only copies the array, not the elements
1370 (ie. the elements are left as the same pointers)
1372 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
1374 const char **ret;
1375 unsigned int i;
1377 for (i=0;attrs && attrs[i];i++) /* noop */ ;
1378 ret = talloc_array(mem_ctx, const char *, i+1);
1379 if (ret == NULL) {
1380 return NULL;
1382 for (i=0;attrs && attrs[i];i++) {
1383 ret[i] = attrs[i];
1385 ret[i] = attrs[i];
1386 return ret;
1391 copy an attribute list. This only copies the array, not the elements
1392 (ie. the elements are left as the same pointers). The new attribute is added to the list.
1394 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
1396 const char **ret;
1397 unsigned int i;
1398 bool found = false;
1400 for (i=0;attrs && attrs[i];i++) {
1401 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
1402 found = true;
1405 if (found) {
1406 return ldb_attr_list_copy(mem_ctx, attrs);
1408 ret = talloc_array(mem_ctx, const char *, i+2);
1409 if (ret == NULL) {
1410 return NULL;
1412 for (i=0;attrs && attrs[i];i++) {
1413 ret[i] = attrs[i];
1415 ret[i] = new_attr;
1416 ret[i+1] = NULL;
1417 return ret;
1422 return 1 if an attribute is in a list of attributes, or 0 otherwise
1424 int ldb_attr_in_list(const char * const *attrs, const char *attr)
1426 unsigned int i;
1427 for (i=0;attrs && attrs[i];i++) {
1428 if (ldb_attr_cmp(attrs[i], attr) == 0) {
1429 return 1;
1432 return 0;
1437 rename the specified attribute in a search result
1439 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
1441 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1442 if (el == NULL) {
1443 return LDB_SUCCESS;
1445 el->name = talloc_strdup(msg->elements, replace);
1446 if (el->name == NULL) {
1447 return LDB_ERR_OPERATIONS_ERROR;
1449 return LDB_SUCCESS;
1454 copy the specified attribute in a search result to a new attribute
1456 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
1458 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1459 int ret;
1461 if (el == NULL) {
1462 return LDB_SUCCESS;
1464 ret = ldb_msg_add(msg, el, 0);
1465 if (ret != LDB_SUCCESS) {
1466 return ret;
1468 return ldb_msg_rename_attr(msg, attr, replace);
1472 remove the specified element in a search result
1474 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1476 ptrdiff_t n = (el - msg->elements);
1477 if (n >= msg->num_elements || n < 0) {
1478 /* the element is not in the list. the caller is crazy. */
1479 return;
1481 msg->num_elements--;
1482 if (n != msg->num_elements) {
1483 memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
1489 remove the specified attribute in a search result
1491 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1493 struct ldb_message_element *el;
1495 while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
1496 ldb_msg_remove_element(msg, el);
1501 return a LDAP formatted GeneralizedTime string
1503 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1505 struct tm *tm = gmtime(&t);
1506 char *ts;
1507 int r;
1509 if (!tm) {
1510 return NULL;
1513 /* we now excatly how long this string will be */
1514 ts = talloc_array(mem_ctx, char, 18);
1516 /* formatted like: 20040408072012.0Z */
1517 r = snprintf(ts, 18,
1518 "%04u%02u%02u%02u%02u%02u.0Z",
1519 tm->tm_year+1900, tm->tm_mon+1,
1520 tm->tm_mday, tm->tm_hour, tm->tm_min,
1521 tm->tm_sec);
1523 if (r != 17) {
1524 talloc_free(ts);
1525 errno = EOVERFLOW;
1526 return NULL;
1529 return ts;
1533 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1535 time_t ldb_string_to_time(const char *s)
1537 struct tm tm;
1539 if (s == NULL) return 0;
1541 memset(&tm, 0, sizeof(tm));
1542 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1543 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1544 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1545 return 0;
1547 tm.tm_year -= 1900;
1548 tm.tm_mon -= 1;
1550 return timegm(&tm);
1554 convert a LDAP GeneralizedTime string in ldb_val format to a
1555 time_t.
1557 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1559 char val[15] = {0};
1560 struct tm tm = {
1561 .tm_year = 0,
1564 if (v == NULL) {
1565 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1568 if (v->data == NULL) {
1569 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1572 if (v->length < 16 && v->length != 13) {
1573 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1576 if (v->data[v->length - 1] != 'Z') {
1577 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1580 if (v->length == 13) {
1581 memcpy(val, v->data, 12);
1583 if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
1584 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1585 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1586 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1588 if (tm.tm_year < 50) {
1589 tm.tm_year += 100;
1591 } else {
1594 * anything between '.' and 'Z' is silently ignored.
1596 if (v->data[14] != '.') {
1597 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1600 memcpy(val, v->data, 14);
1602 if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
1603 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1604 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1605 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1607 tm.tm_year -= 1900;
1609 tm.tm_mon -= 1;
1611 *t = timegm(&tm);
1613 return LDB_SUCCESS;
1617 return a LDAP formatted UTCTime string
1619 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1621 struct tm *tm = gmtime(&t);
1622 char *ts;
1623 int r;
1625 if (!tm) {
1626 return NULL;
1629 /* we now excatly how long this string will be */
1630 ts = talloc_array(mem_ctx, char, 14);
1632 /* formatted like: 20040408072012.0Z => 040408072012Z */
1633 r = snprintf(ts, 14,
1634 "%02u%02u%02u%02u%02u%02uZ",
1635 (tm->tm_year+1900)%100, tm->tm_mon+1,
1636 tm->tm_mday, tm->tm_hour, tm->tm_min,
1637 tm->tm_sec);
1639 if (r != 13) {
1640 talloc_free(ts);
1641 return NULL;
1644 return ts;
1648 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1650 time_t ldb_string_utc_to_time(const char *s)
1652 struct tm tm;
1654 if (s == NULL) return 0;
1656 memset(&tm, 0, sizeof(tm));
1657 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1658 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1659 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1660 return 0;
1662 if (tm.tm_year < 50) {
1663 tm.tm_year += 100;
1665 tm.tm_mon -= 1;
1667 return timegm(&tm);
1672 dump a set of results to a file. Useful from within gdb
1674 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1676 unsigned int i;
1678 for (i = 0; i < result->count; i++) {
1679 struct ldb_ldif ldif;
1680 fprintf(f, "# record %d\n", i+1);
1681 ldif.changetype = LDB_CHANGETYPE_NONE;
1682 ldif.msg = result->msgs[i];
1683 ldb_ldif_write_file(ldb, f, &ldif);
1688 checks for a string attribute. Returns "1" on match and otherwise "0".
1690 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1691 const char *name, const char *value)
1693 struct ldb_message_element *el;
1694 struct ldb_val val;
1696 el = ldb_msg_find_element(msg, name);
1697 if (el == NULL) {
1698 return 0;
1701 val.data = discard_const_p(uint8_t, value);
1702 val.length = strlen(value);
1704 if (ldb_msg_find_val(el, &val)) {
1705 return 1;
1708 return 0;
1713 compare a ldb_val to a string
1715 int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1717 size_t len = strlen(str);
1718 if (len != v->length) {
1719 return len - v->length;
1721 return strncmp((const char *)v->data, str, len);