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
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/>.
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(void *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)
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];
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) {
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,
84 for (i=0;i<el->num_values;i++) {
85 if (ldb_val_equal_exact(val, &el->values[i])) {
86 return &el->values[i];
93 duplicate a ldb_val structure
95 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
98 v2.length = v->length;
99 if (v->data == NULL) {
104 /* the +1 is to cope with buggy C library routines like strndup
105 that look one byte beyond */
106 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
112 memcpy(v2.data, v->data, v->length);
113 ((char *)v2.data)[v->length] = 0;
118 * Adds new empty element to msg->elements
120 static int _ldb_msg_add_el(struct ldb_message *msg,
121 struct ldb_message_element **return_el)
123 struct ldb_message_element *els;
125 /* TODO: Find out a way to assert
126 * on input parameters.
127 * msg and return_el must be valid */
129 els = talloc_realloc(msg, msg->elements,
130 struct ldb_message_element, msg->num_elements + 1);
133 return LDB_ERR_OPERATIONS_ERROR;
136 ZERO_STRUCT(els[msg->num_elements]);
141 *return_el = &els[msg->num_elements-1];
147 add an empty element to a message
149 int ldb_msg_add_empty( struct ldb_message *msg,
150 const char *attr_name,
152 struct ldb_message_element **return_el)
154 struct ldb_message_element *els;
156 els = talloc_realloc(msg, msg->elements,
157 struct ldb_message_element, msg->num_elements+1);
160 return LDB_ERR_OPERATIONS_ERROR;
163 els[msg->num_elements].values = NULL;
164 els[msg->num_elements].num_values = 0;
165 els[msg->num_elements].flags = flags;
166 els[msg->num_elements].name = talloc_strdup(els, attr_name);
167 if (!els[msg->num_elements].name) {
169 return LDB_ERR_OPERATIONS_ERROR;
176 *return_el = &els[msg->num_elements-1];
183 * Adds an element to a message.
185 * NOTE: Ownership of ldb_message_element fields
186 * is NOT transferred. Thus, if el pointer
187 * is invalidated for some reason, this will
188 * corrupt msg contents also
190 int ldb_msg_add(struct ldb_message *msg,
191 const struct ldb_message_element *el,
194 /* We have to copy this, just in case *el is a pointer into
195 * what ldb_msg_add_empty() is about to realloc() */
196 struct ldb_message_element el_copy = *el;
197 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != LDB_SUCCESS) {
198 return LDB_ERR_OPERATIONS_ERROR;
201 msg->elements[msg->num_elements-1] = el_copy;
202 msg->elements[msg->num_elements-1].flags = flags;
208 add a value to a message
210 int ldb_msg_add_value(struct ldb_message *msg,
211 const char *attr_name,
212 const struct ldb_val *val,
213 struct ldb_message_element **return_el)
215 struct ldb_message_element *el;
216 struct ldb_val *vals;
219 el = ldb_msg_find_element(msg, attr_name);
221 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
222 if (ret != LDB_SUCCESS) {
227 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
230 return LDB_ERR_OPERATIONS_ERROR;
233 el->values[el->num_values] = *val;
245 add a value to a message, stealing it into the 'right' place
247 int ldb_msg_add_steal_value(struct ldb_message *msg,
248 const char *attr_name,
252 struct ldb_message_element *el;
254 ret = ldb_msg_add_value(msg, attr_name, val, &el);
255 if (ret == LDB_SUCCESS) {
256 talloc_steal(el->values, val->data);
263 add a string element to a message
265 int ldb_msg_add_string(struct ldb_message *msg,
266 const char *attr_name, const char *str)
270 val.data = discard_const_p(uint8_t, str);
271 val.length = strlen(str);
273 if (val.length == 0) {
274 /* allow empty strings as non-existent attributes */
278 return ldb_msg_add_value(msg, attr_name, &val, NULL);
282 add a string element to a message, stealing it into the 'right' place
284 int ldb_msg_add_steal_string(struct ldb_message *msg,
285 const char *attr_name, char *str)
289 val.data = (uint8_t *)str;
290 val.length = strlen(str);
292 if (val.length == 0) {
293 /* allow empty strings as non-existent attributes */
297 return ldb_msg_add_steal_value(msg, attr_name, &val);
301 add a DN element to a message
302 WARNING: this uses the linearized string from the dn, and does not
305 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
308 return ldb_msg_add_steal_string(msg, attr_name,
309 ldb_dn_alloc_linearized(msg, dn));
313 add a printf formatted element to a message
315 int ldb_msg_add_fmt(struct ldb_message *msg,
316 const char *attr_name, const char *fmt, ...)
323 str = talloc_vasprintf(msg, fmt, ap);
326 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
328 val.data = (uint8_t *)str;
329 val.length = strlen(str);
331 return ldb_msg_add_steal_value(msg, attr_name, &val);
335 compare two ldb_message_element structures
336 assumes case sensitive comparison
338 int ldb_msg_element_compare(struct ldb_message_element *el1,
339 struct ldb_message_element *el2)
343 if (el1->num_values != el2->num_values) {
344 return el1->num_values - el2->num_values;
347 for (i=0;i<el1->num_values;i++) {
348 if (!ldb_msg_find_val(el2, &el1->values[i])) {
357 compare two ldb_message_element structures
358 comparing by element name
360 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
361 struct ldb_message_element *el2)
363 return ldb_attr_cmp(el1->name, el2->name);
367 convenience functions to return common types from a message
368 these return the first value if the attribute is multi-valued
370 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
371 const char *attr_name)
373 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
374 if (!el || el->num_values == 0) {
377 return &el->values[0];
380 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
381 const char *attr_name,
384 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
385 if (!v || !v->data) {
386 return default_value;
388 return strtol((const char *)v->data, NULL, 0);
391 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
392 const char *attr_name,
393 unsigned int default_value)
396 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
397 if (!v || !v->data) {
398 return default_value;
401 /* in LDAP there're only int32_t values */
403 ret = strtol((const char *)v->data, NULL, 0);
408 return strtoul((const char *)v->data, NULL, 0);
411 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
412 const char *attr_name,
413 int64_t default_value)
415 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
416 if (!v || !v->data) {
417 return default_value;
419 return strtoll((const char *)v->data, NULL, 0);
422 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
423 const char *attr_name,
424 uint64_t default_value)
427 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
428 if (!v || !v->data) {
429 return default_value;
432 /* in LDAP there're only int64_t values */
434 ret = strtoll((const char *)v->data, NULL, 0);
439 return strtoull((const char *)v->data, NULL, 0);
442 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
443 const char *attr_name,
444 double default_value)
446 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
447 if (!v || !v->data) {
448 return default_value;
450 return strtod((const char *)v->data, NULL);
453 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
454 const char *attr_name,
457 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
458 if (!v || !v->data) {
459 return default_value;
461 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
464 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
467 return default_value;
470 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
471 const char *attr_name,
472 const char *default_value)
474 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
475 if (!v || !v->data) {
476 return default_value;
478 return (const char *)v->data;
481 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
483 const struct ldb_message *msg,
484 const char *attr_name)
486 struct ldb_dn *res_dn;
487 const struct ldb_val *v;
489 v = ldb_msg_find_ldb_val(msg, attr_name);
490 if (!v || !v->data) {
493 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
494 if ( ! ldb_dn_validate(res_dn)) {
502 sort the elements of a message by name
504 void ldb_msg_sort_elements(struct ldb_message *msg)
506 TYPESAFE_QSORT(msg->elements, msg->num_elements,
507 ldb_msg_element_compare_name);
511 shallow copy a message - copying only the elements array so that the caller
512 can safely add new elements without changing the message
514 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
515 const struct ldb_message *msg)
517 struct ldb_message *msg2;
520 msg2 = talloc(mem_ctx, struct ldb_message);
521 if (msg2 == NULL) return NULL;
525 msg2->elements = talloc_array(msg2, struct ldb_message_element,
527 if (msg2->elements == NULL) goto failed;
529 for (i=0;i<msg2->num_elements;i++) {
530 msg2->elements[i] = msg->elements[i];
542 copy a message, allocating new memory for all parts
544 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
545 const struct ldb_message *msg)
547 struct ldb_message *msg2;
550 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
551 if (msg2 == NULL) return NULL;
553 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
554 if (msg2->dn == NULL) goto failed;
556 for (i=0;i<msg2->num_elements;i++) {
557 struct ldb_message_element *el = &msg2->elements[i];
558 struct ldb_val *values = el->values;
559 el->name = talloc_strdup(msg2->elements, el->name);
560 if (el->name == NULL) goto failed;
561 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
562 for (j=0;j<el->num_values;j++) {
563 el->values[j] = ldb_val_dup(el->values, &values[j]);
564 if (el->values[j].data == NULL && values[j].length != 0) {
579 canonicalise a message, merging elements of the same name
581 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
582 const struct ldb_message *msg)
585 struct ldb_message *msg2;
587 msg2 = ldb_msg_copy(ldb, msg);
588 if (msg2 == NULL) return NULL;
590 ldb_msg_sort_elements(msg2);
592 for (i=1;i<msg2->num_elements;i++) {
593 struct ldb_message_element *el1 = &msg2->elements[i-1];
594 struct ldb_message_element *el2 = &msg2->elements[i];
595 if (ldb_msg_element_compare_name(el1, el2) == 0) {
596 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
597 el1->num_values + el2->num_values);
598 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
601 memcpy(el1->values + el1->num_values,
603 sizeof(struct ldb_val) * el2->num_values);
604 el1->num_values += el2->num_values;
605 talloc_free(discard_const_p(char, el2->name));
606 if (i+1<msg2->num_elements) {
607 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
608 (msg2->num_elements - (i+1)));
610 msg2->num_elements--;
620 return a ldb_message representing the differences between msg1 and msg2. If you
621 then use this in a ldb_modify() call it can be used to save edits to a message
623 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
624 struct ldb_message *msg1,
625 struct ldb_message *msg2)
628 struct ldb_message *mod;
630 /* allocate mod message in NULL context
631 * so it should appear as 'leaked' in talloc reports */
632 ldb_ret = ldb_msg_diff_ex(ldb, msg1, msg2,
633 (TALLOC_CTX*)NULL, &mod);
634 if (ldb_ret != LDB_SUCCESS) {
642 * return a ldb_message representing the differences between msg1 and msg2.
643 * If you then use this in a ldb_modify() call it can be used to save edits to a message
645 * Result message is constructed as follows:
646 * - LDB_FLAG_MOD_ADD - elements found only in msg2
647 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
648 * Value for msg2 element is used
649 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
651 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
653 int ldb_msg_diff_ex(struct ldb_context *ldb,
654 struct ldb_message *msg1,
655 struct ldb_message *msg2,
657 struct ldb_message **_msg_out)
661 struct ldb_message *mod;
662 struct ldb_message_element *el;
663 TALLOC_CTX *temp_ctx;
665 temp_ctx = talloc_new(mem_ctx);
667 return LDB_ERR_OPERATIONS_ERROR;
670 mod = ldb_msg_new(temp_ctx);
676 mod->num_elements = 0;
677 mod->elements = NULL;
679 /* canonicalize msg2 so we have no
680 * repeated elements */
681 msg2 = ldb_msg_canonicalize(ldb, msg2);
686 /* steal msg2 into mod context as it is
687 * allocated in ldb's context */
688 talloc_steal(mod, msg2);
690 /* look in msg2 to find elements that need to be added
692 for (i=0;i<msg2->num_elements;i++) {
693 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
695 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
699 ldb_res = ldb_msg_add(mod,
701 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
702 if (ldb_res != LDB_SUCCESS) {
707 /* look in msg1 to find elements that need to be deleted */
708 for (i=0;i<msg1->num_elements;i++) {
709 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
711 ldb_res = ldb_msg_add_empty(mod,
712 msg1->elements[i].name,
713 LDB_FLAG_MOD_DELETE, NULL);
714 if (ldb_res != LDB_SUCCESS) {
720 /* steal resulting message into supplied context */
721 talloc_steal(mem_ctx, mod);
724 talloc_free(temp_ctx);
728 talloc_free(temp_ctx);
729 return LDB_ERR_OPERATIONS_ERROR;
733 int ldb_msg_sanity_check(struct ldb_context *ldb,
734 const struct ldb_message *msg)
738 /* basic check on DN */
739 if (msg->dn == NULL) {
740 /* TODO: return also an error string */
741 ldb_set_errstring(ldb, "ldb message lacks a DN!");
742 return LDB_ERR_INVALID_DN_SYNTAX;
745 /* basic syntax checks */
746 for (i = 0; i < msg->num_elements; i++) {
747 for (j = 0; j < msg->elements[i].num_values; j++) {
748 if (msg->elements[i].values[j].length == 0) {
749 TALLOC_CTX *mem_ctx = talloc_new(ldb);
750 /* an attribute cannot be empty */
751 /* TODO: return also an error string */
752 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
753 msg->elements[i].name,
754 ldb_dn_get_linearized(msg->dn));
755 talloc_free(mem_ctx);
756 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
768 copy an attribute list. This only copies the array, not the elements
769 (ie. the elements are left as the same pointers)
771 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
776 for (i=0;attrs && attrs[i];i++) /* noop */ ;
777 ret = talloc_array(mem_ctx, const char *, i+1);
781 for (i=0;attrs && attrs[i];i++) {
790 copy an attribute list. This only copies the array, not the elements
791 (ie. the elements are left as the same pointers). The new attribute is added to the list.
793 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
799 for (i=0;attrs && attrs[i];i++) {
800 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
805 return ldb_attr_list_copy(mem_ctx, attrs);
807 ret = talloc_array(mem_ctx, const char *, i+2);
811 for (i=0;attrs && attrs[i];i++) {
821 return 1 if an attribute is in a list of attributes, or 0 otherwise
823 int ldb_attr_in_list(const char * const *attrs, const char *attr)
826 for (i=0;attrs && attrs[i];i++) {
827 if (ldb_attr_cmp(attrs[i], attr) == 0) {
836 rename the specified attribute in a search result
838 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
840 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
844 el->name = talloc_strdup(msg->elements, replace);
845 if (el->name == NULL) {
846 return LDB_ERR_OPERATIONS_ERROR;
853 copy the specified attribute in a search result to a new attribute
855 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
857 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
861 if (ldb_msg_add(msg, el, 0) != 0) {
862 return LDB_ERR_OPERATIONS_ERROR;
864 return ldb_msg_rename_attr(msg, attr, replace);
868 remove the specified element in a search result
870 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
872 ptrdiff_t n = (el - msg->elements);
873 if (n >= msg->num_elements) {
874 /* should we abort() here? */
877 if (n != msg->num_elements-1) {
878 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
885 remove the specified attribute in a search result
887 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
889 struct ldb_message_element *el;
891 while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
892 ldb_msg_remove_element(msg, el);
897 return a LDAP formatted GeneralizedTime string
899 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
901 struct tm *tm = gmtime(&t);
909 /* we now excatly how long this string will be */
910 ts = talloc_array(mem_ctx, char, 18);
912 /* formatted like: 20040408072012.0Z */
914 "%04u%02u%02u%02u%02u%02u.0Z",
915 tm->tm_year+1900, tm->tm_mon+1,
916 tm->tm_mday, tm->tm_hour, tm->tm_min,
928 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
930 time_t ldb_string_to_time(const char *s)
934 if (s == NULL) return 0;
936 memset(&tm, 0, sizeof(tm));
937 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
938 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
939 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
949 convert a LDAP GeneralizedTime string in ldb_val format to a
952 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
956 if (v == NULL || !v->data || v->length < 17) {
957 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
960 memset(&tm, 0, sizeof(tm));
962 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
963 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
964 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
965 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
976 return a LDAP formatted UTCTime string
978 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
980 struct tm *tm = gmtime(&t);
988 /* we now excatly how long this string will be */
989 ts = talloc_array(mem_ctx, char, 14);
991 /* formatted like: 20040408072012.0Z => 040408072012Z */
993 "%02u%02u%02u%02u%02u%02uZ",
994 (tm->tm_year+1900)%100, tm->tm_mon+1,
995 tm->tm_mday, tm->tm_hour, tm->tm_min,
1007 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1009 time_t ldb_string_utc_to_time(const char *s)
1013 if (s == NULL) return 0;
1015 memset(&tm, 0, sizeof(tm));
1016 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1017 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1018 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1021 if (tm.tm_year < 50) {
1031 dump a set of results to a file. Useful from within gdb
1033 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1037 for (i = 0; i < result->count; i++) {
1038 struct ldb_ldif ldif;
1039 fprintf(f, "# record %d\n", i+1);
1040 ldif.changetype = LDB_CHANGETYPE_NONE;
1041 ldif.msg = result->msgs[i];
1042 ldb_ldif_write_file(ldb, f, &ldif);
1047 checks for a string attribute. Returns "1" on match and otherwise "0".
1049 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1050 const char *name, const char *value)
1052 struct ldb_message_element *el;
1055 el = ldb_msg_find_element(msg, name);
1060 val.data = discard_const_p(uint8_t, value);
1061 val.length = strlen(value);
1063 if (ldb_msg_find_val(el, &val)) {