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 add an empty element to a message
120 int ldb_msg_add_empty( struct ldb_message *msg,
121 const char *attr_name,
123 struct ldb_message_element **return_el)
125 struct ldb_message_element *els;
127 els = talloc_realloc(msg, msg->elements,
128 struct ldb_message_element, msg->num_elements+1);
131 return LDB_ERR_OPERATIONS_ERROR;
134 els[msg->num_elements].values = NULL;
135 els[msg->num_elements].num_values = 0;
136 els[msg->num_elements].flags = flags;
137 els[msg->num_elements].name = talloc_strdup(els, attr_name);
138 if (!els[msg->num_elements].name) {
140 return LDB_ERR_OPERATIONS_ERROR;
147 *return_el = &els[msg->num_elements-1];
154 add an empty element to a message
156 int ldb_msg_add(struct ldb_message *msg,
157 const struct ldb_message_element *el,
160 /* We have to copy this, just in case *el is a pointer into
161 * what ldb_msg_add_empty() is about to realloc() */
162 struct ldb_message_element el_copy = *el;
163 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != LDB_SUCCESS) {
164 return LDB_ERR_OPERATIONS_ERROR;
167 msg->elements[msg->num_elements-1] = el_copy;
168 msg->elements[msg->num_elements-1].flags = flags;
174 add a value to a message
176 int ldb_msg_add_value(struct ldb_message *msg,
177 const char *attr_name,
178 const struct ldb_val *val,
179 struct ldb_message_element **return_el)
181 struct ldb_message_element *el;
182 struct ldb_val *vals;
185 el = ldb_msg_find_element(msg, attr_name);
187 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
188 if (ret != LDB_SUCCESS) {
193 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
196 return LDB_ERR_OPERATIONS_ERROR;
199 el->values[el->num_values] = *val;
211 add a value to a message, stealing it into the 'right' place
213 int ldb_msg_add_steal_value(struct ldb_message *msg,
214 const char *attr_name,
218 struct ldb_message_element *el;
220 ret = ldb_msg_add_value(msg, attr_name, val, &el);
221 if (ret == LDB_SUCCESS) {
222 talloc_steal(el->values, val->data);
229 add a string element to a message
231 int ldb_msg_add_string(struct ldb_message *msg,
232 const char *attr_name, const char *str)
236 val.data = discard_const_p(uint8_t, str);
237 val.length = strlen(str);
239 if (val.length == 0) {
240 /* allow empty strings as non-existent attributes */
244 return ldb_msg_add_value(msg, attr_name, &val, NULL);
248 add a string element to a message, stealing it into the 'right' place
250 int ldb_msg_add_steal_string(struct ldb_message *msg,
251 const char *attr_name, char *str)
255 val.data = (uint8_t *)str;
256 val.length = strlen(str);
258 if (val.length == 0) {
259 /* allow empty strings as non-existent attributes */
263 return ldb_msg_add_steal_value(msg, attr_name, &val);
267 add a DN element to a message
268 WARNING: this uses the linearized string from the dn, and does not
271 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
274 return ldb_msg_add_steal_string(msg, attr_name,
275 ldb_dn_alloc_linearized(msg, dn));
279 add a printf formatted element to a message
281 int ldb_msg_add_fmt(struct ldb_message *msg,
282 const char *attr_name, const char *fmt, ...)
289 str = talloc_vasprintf(msg, fmt, ap);
292 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
294 val.data = (uint8_t *)str;
295 val.length = strlen(str);
297 return ldb_msg_add_steal_value(msg, attr_name, &val);
301 compare two ldb_message_element structures
302 assumes case sensitive comparison
304 int ldb_msg_element_compare(struct ldb_message_element *el1,
305 struct ldb_message_element *el2)
309 if (el1->num_values != el2->num_values) {
310 return el1->num_values - el2->num_values;
313 for (i=0;i<el1->num_values;i++) {
314 if (!ldb_msg_find_val(el2, &el1->values[i])) {
323 compare two ldb_message_element structures
324 comparing by element name
326 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
327 struct ldb_message_element *el2)
329 return ldb_attr_cmp(el1->name, el2->name);
333 convenience functions to return common types from a message
334 these return the first value if the attribute is multi-valued
336 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
337 const char *attr_name)
339 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
340 if (!el || el->num_values == 0) {
343 return &el->values[0];
346 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
347 const char *attr_name,
350 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
351 if (!v || !v->data) {
352 return default_value;
354 return strtol((const char *)v->data, NULL, 0);
357 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
358 const char *attr_name,
359 unsigned int default_value)
362 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
363 if (!v || !v->data) {
364 return default_value;
367 /* in LDAP there're only int32_t values */
369 ret = strtol((const char *)v->data, NULL, 0);
374 return strtoul((const char *)v->data, NULL, 0);
377 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
378 const char *attr_name,
379 int64_t default_value)
381 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
382 if (!v || !v->data) {
383 return default_value;
385 return strtoll((const char *)v->data, NULL, 0);
388 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
389 const char *attr_name,
390 uint64_t default_value)
393 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
394 if (!v || !v->data) {
395 return default_value;
398 /* in LDAP there're only int64_t values */
400 ret = strtoll((const char *)v->data, NULL, 0);
405 return strtoull((const char *)v->data, NULL, 0);
408 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
409 const char *attr_name,
410 double default_value)
412 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
413 if (!v || !v->data) {
414 return default_value;
416 return strtod((const char *)v->data, NULL);
419 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
420 const char *attr_name,
423 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
424 if (!v || !v->data) {
425 return default_value;
427 if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
430 if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
433 return default_value;
436 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
437 const char *attr_name,
438 const char *default_value)
440 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
441 if (!v || !v->data) {
442 return default_value;
444 return (const char *)v->data;
447 struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
449 const struct ldb_message *msg,
450 const char *attr_name)
452 struct ldb_dn *res_dn;
453 const struct ldb_val *v;
455 v = ldb_msg_find_ldb_val(msg, attr_name);
456 if (!v || !v->data) {
459 res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
460 if ( ! ldb_dn_validate(res_dn)) {
468 sort the elements of a message by name
470 void ldb_msg_sort_elements(struct ldb_message *msg)
472 TYPESAFE_QSORT(msg->elements, msg->num_elements,
473 ldb_msg_element_compare_name);
477 shallow copy a message - copying only the elements array so that the caller
478 can safely add new elements without changing the message
480 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
481 const struct ldb_message *msg)
483 struct ldb_message *msg2;
486 msg2 = talloc(mem_ctx, struct ldb_message);
487 if (msg2 == NULL) return NULL;
491 msg2->elements = talloc_array(msg2, struct ldb_message_element,
493 if (msg2->elements == NULL) goto failed;
495 for (i=0;i<msg2->num_elements;i++) {
496 msg2->elements[i] = msg->elements[i];
508 copy a message, allocating new memory for all parts
510 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
511 const struct ldb_message *msg)
513 struct ldb_message *msg2;
516 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
517 if (msg2 == NULL) return NULL;
519 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
520 if (msg2->dn == NULL) goto failed;
522 for (i=0;i<msg2->num_elements;i++) {
523 struct ldb_message_element *el = &msg2->elements[i];
524 struct ldb_val *values = el->values;
525 el->name = talloc_strdup(msg2->elements, el->name);
526 if (el->name == NULL) goto failed;
527 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
528 for (j=0;j<el->num_values;j++) {
529 el->values[j] = ldb_val_dup(el->values, &values[j]);
530 if (el->values[j].data == NULL && values[j].length != 0) {
545 canonicalise a message, merging elements of the same name
547 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
548 const struct ldb_message *msg)
551 struct ldb_message *msg2;
553 msg2 = ldb_msg_copy(ldb, msg);
554 if (msg2 == NULL) return NULL;
556 ldb_msg_sort_elements(msg2);
558 for (i=1;i<msg2->num_elements;i++) {
559 struct ldb_message_element *el1 = &msg2->elements[i-1];
560 struct ldb_message_element *el2 = &msg2->elements[i];
561 if (ldb_msg_element_compare_name(el1, el2) == 0) {
562 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
563 el1->num_values + el2->num_values);
564 if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
567 memcpy(el1->values + el1->num_values,
569 sizeof(struct ldb_val) * el2->num_values);
570 el1->num_values += el2->num_values;
571 talloc_free(discard_const_p(char, el2->name));
572 if (i+1<msg2->num_elements) {
573 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
574 (msg2->num_elements - (i+1)));
576 msg2->num_elements--;
586 return a ldb_message representing the differences between msg1 and msg2. If you
587 then use this in a ldb_modify() call it can be used to save edits to a message
589 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
590 struct ldb_message *msg1,
591 struct ldb_message *msg2)
593 struct ldb_message *mod;
594 struct ldb_message_element *el;
597 mod = ldb_msg_new(ldb);
603 mod->num_elements = 0;
604 mod->elements = NULL;
606 msg2 = ldb_msg_canonicalize(ldb, msg2);
612 /* look in msg2 to find elements that need to be added
614 for (i=0;i<msg2->num_elements;i++) {
615 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
617 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
623 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != LDB_SUCCESS) {
629 /* look in msg1 to find elements that need to be deleted */
630 for (i=0;i<msg1->num_elements;i++) {
631 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
633 if (ldb_msg_add_empty(mod,
634 msg1->elements[i].name,
635 LDB_FLAG_MOD_DELETE, NULL) != LDB_SUCCESS) {
646 * return a ldb_message representing the differences between msg1 and msg2.
647 * If you then use this in a ldb_modify() call it can be used to save edits to a message
649 * Result message is constructed as follows:
650 * - LDB_FLAG_MOD_ADD - elements found only in msg2
651 * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
652 * Value for msg2 element is used
653 * - LDB_FLAG_MOD_DELETE - elements found only in msg2
655 * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
657 int ldb_msg_diff_ex(struct ldb_context *ldb,
658 struct ldb_message *msg1,
659 struct ldb_message *msg2,
661 struct ldb_message **_msg_out)
665 struct ldb_message *mod;
666 struct ldb_message_element *el;
667 TALLOC_CTX *temp_ctx;
669 temp_ctx = talloc_new(mem_ctx);
671 return LDB_ERR_OPERATIONS_ERROR;
674 mod = ldb_msg_new(temp_ctx);
680 mod->num_elements = 0;
681 mod->elements = NULL;
683 /* canonicalize msg2 so we have no
684 * repeated elements */
685 msg2 = ldb_msg_canonicalize(ldb, msg2);
690 /* steal msg2 into mod context as it is
691 * allocated in ldb's context */
692 talloc_steal(mod, msg2);
694 /* look in msg2 to find elements that need to be added
696 for (i=0;i<msg2->num_elements;i++) {
697 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
699 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
703 ldb_res = ldb_msg_add(mod,
705 el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
706 if (ldb_res != LDB_SUCCESS) {
711 /* look in msg1 to find elements that need to be deleted */
712 for (i=0;i<msg1->num_elements;i++) {
713 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
715 ldb_res = ldb_msg_add_empty(mod,
716 msg1->elements[i].name,
717 LDB_FLAG_MOD_DELETE, NULL);
718 if (ldb_res != LDB_SUCCESS) {
724 /* steal resulting message into supplied context */
725 talloc_steal(mem_ctx, mod);
728 talloc_free(temp_ctx);
732 talloc_free(temp_ctx);
733 return LDB_ERR_OPERATIONS_ERROR;
737 int ldb_msg_sanity_check(struct ldb_context *ldb,
738 const struct ldb_message *msg)
742 /* basic check on DN */
743 if (msg->dn == NULL) {
744 /* TODO: return also an error string */
745 ldb_set_errstring(ldb, "ldb message lacks a DN!");
746 return LDB_ERR_INVALID_DN_SYNTAX;
749 /* basic syntax checks */
750 for (i = 0; i < msg->num_elements; i++) {
751 for (j = 0; j < msg->elements[i].num_values; j++) {
752 if (msg->elements[i].values[j].length == 0) {
753 TALLOC_CTX *mem_ctx = talloc_new(ldb);
754 /* an attribute cannot be empty */
755 /* TODO: return also an error string */
756 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
757 msg->elements[i].name,
758 ldb_dn_get_linearized(msg->dn));
759 talloc_free(mem_ctx);
760 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
772 copy an attribute list. This only copies the array, not the elements
773 (ie. the elements are left as the same pointers)
775 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
780 for (i=0;attrs && attrs[i];i++) /* noop */ ;
781 ret = talloc_array(mem_ctx, const char *, i+1);
785 for (i=0;attrs && attrs[i];i++) {
794 copy an attribute list. This only copies the array, not the elements
795 (ie. the elements are left as the same pointers). The new attribute is added to the list.
797 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
803 for (i=0;attrs && attrs[i];i++) {
804 if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
809 return ldb_attr_list_copy(mem_ctx, attrs);
811 ret = talloc_array(mem_ctx, const char *, i+2);
815 for (i=0;attrs && attrs[i];i++) {
825 return 1 if an attribute is in a list of attributes, or 0 otherwise
827 int ldb_attr_in_list(const char * const *attrs, const char *attr)
830 for (i=0;attrs && attrs[i];i++) {
831 if (ldb_attr_cmp(attrs[i], attr) == 0) {
840 rename the specified attribute in a search result
842 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
844 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
848 el->name = talloc_strdup(msg->elements, replace);
849 if (el->name == NULL) {
850 return LDB_ERR_OPERATIONS_ERROR;
857 copy the specified attribute in a search result to a new attribute
859 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
861 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
865 if (ldb_msg_add(msg, el, 0) != 0) {
866 return LDB_ERR_OPERATIONS_ERROR;
868 return ldb_msg_rename_attr(msg, attr, replace);
872 remove the specified element in a search result
874 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
876 ptrdiff_t n = (el - msg->elements);
877 if (n >= msg->num_elements) {
878 /* should we abort() here? */
881 if (n != msg->num_elements-1) {
882 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
889 remove the specified attribute in a search result
891 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
893 struct ldb_message_element *el;
895 while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
896 ldb_msg_remove_element(msg, el);
901 return a LDAP formatted GeneralizedTime string
903 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
905 struct tm *tm = gmtime(&t);
913 /* we now excatly how long this string will be */
914 ts = talloc_array(mem_ctx, char, 18);
916 /* formatted like: 20040408072012.0Z */
918 "%04u%02u%02u%02u%02u%02u.0Z",
919 tm->tm_year+1900, tm->tm_mon+1,
920 tm->tm_mday, tm->tm_hour, tm->tm_min,
932 convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
934 time_t ldb_string_to_time(const char *s)
938 if (s == NULL) return 0;
940 memset(&tm, 0, sizeof(tm));
941 if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
942 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
943 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
953 convert a LDAP GeneralizedTime string in ldb_val format to a
956 int ldb_val_to_time(const struct ldb_val *v, time_t *t)
960 if (v == NULL || !v->data || v->length < 17) {
961 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
964 memset(&tm, 0, sizeof(tm));
966 if (sscanf((char *)v->data, "%04u%02u%02u%02u%02u%02u.0Z",
967 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
968 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
969 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
980 return a LDAP formatted UTCTime string
982 char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
984 struct tm *tm = gmtime(&t);
992 /* we now excatly how long this string will be */
993 ts = talloc_array(mem_ctx, char, 14);
995 /* formatted like: 20040408072012.0Z => 040408072012Z */
997 "%02u%02u%02u%02u%02u%02uZ",
998 (tm->tm_year+1900)%100, tm->tm_mon+1,
999 tm->tm_mday, tm->tm_hour, tm->tm_min,
1011 convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1013 time_t ldb_string_utc_to_time(const char *s)
1017 if (s == NULL) return 0;
1019 memset(&tm, 0, sizeof(tm));
1020 if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1021 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1022 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1025 if (tm.tm_year < 50) {
1035 dump a set of results to a file. Useful from within gdb
1037 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1041 for (i = 0; i < result->count; i++) {
1042 struct ldb_ldif ldif;
1043 fprintf(f, "# record %d\n", i+1);
1044 ldif.changetype = LDB_CHANGETYPE_NONE;
1045 ldif.msg = result->msgs[i];
1046 ldb_ldif_write_file(ldb, f, &ldif);
1051 checks for a string attribute. Returns "1" on match and otherwise "0".
1053 int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1054 const char *name, const char *value)
1056 struct ldb_message_element *el;
1059 el = ldb_msg_find_element(msg, name);
1064 val.data = discard_const_p(uint8_t, value);
1065 val.length = strlen(value);
1067 if (ldb_msg_find_val(el, &val)) {