r25068: Older samba3 DCs will return DCERPC_FAULT_OP_RNG_ERROR for every opcode on the
[Samba.git] / source / lib / ldb / common / ldb_msg.c
blobbf217d2787f3f38292da1149e1584a1543a31153
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 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
26 * Name: ldb
28 * Component: ldb message component utility functions
30 * Description: functions for manipulating ldb_message structures
32 * Author: Andrew Tridgell
35 #include "includes.h"
36 #include "ldb/include/includes.h"
38 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f);
39 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
40 struct ldb_message_element *el2);
43 create a new ldb_message in a given memory context (NULL for top level)
45 struct ldb_message *ldb_msg_new(void *mem_ctx)
47 return talloc_zero(mem_ctx, struct ldb_message);
51 find an element in a message by attribute name
53 struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
54 const char *attr_name)
56 unsigned int i;
57 for (i=0;i<msg->num_elements;i++) {
58 if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
59 return &msg->elements[i];
62 return NULL;
66 see if two ldb_val structures contain exactly the same data
67 return 1 for a match, 0 for a mis-match
69 int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
71 if (v1->length != v2->length) return 0;
73 if (v1->length == 0) return 1;
75 if (memcmp(v1->data, v2->data, v1->length) == 0) {
76 return 1;
79 return 0;
83 find a value in an element
84 assumes case sensitive comparison
86 struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
87 struct ldb_val *val)
89 unsigned int i;
90 for (i=0;i<el->num_values;i++) {
91 if (ldb_val_equal_exact(val, &el->values[i])) {
92 return &el->values[i];
95 return NULL;
99 duplicate a ldb_val structure
101 struct ldb_val ldb_val_dup(void *mem_ctx, const struct ldb_val *v)
103 struct ldb_val v2;
104 v2.length = v->length;
105 if (v->data == NULL) {
106 v2.data = NULL;
107 return v2;
110 /* the +1 is to cope with buggy C library routines like strndup
111 that look one byte beyond */
112 v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
113 if (!v2.data) {
114 v2.length = 0;
115 return v2;
118 memcpy(v2.data, v->data, v->length);
119 ((char *)v2.data)[v->length] = 0;
120 return v2;
124 add an empty element to a message
126 int ldb_msg_add_empty( struct ldb_message *msg,
127 const char *attr_name,
128 int flags,
129 struct ldb_message_element **return_el)
131 struct ldb_message_element *els;
133 if (! ldb_valid_attr_name(attr_name)) {
134 return LDB_ERR_OPERATIONS_ERROR;
137 els = talloc_realloc(msg, msg->elements,
138 struct ldb_message_element, msg->num_elements+1);
139 if (!els) {
140 errno = ENOMEM;
141 return LDB_ERR_OPERATIONS_ERROR;
144 els[msg->num_elements].values = NULL;
145 els[msg->num_elements].num_values = 0;
146 els[msg->num_elements].flags = flags;
147 els[msg->num_elements].name = talloc_strdup(els, attr_name);
148 if (!els[msg->num_elements].name) {
149 errno = ENOMEM;
150 return LDB_ERR_OPERATIONS_ERROR;
153 msg->elements = els;
154 msg->num_elements++;
156 if (return_el) {
157 *return_el = &els[msg->num_elements-1];
160 return LDB_SUCCESS;
164 add an empty element to a message
166 int ldb_msg_add(struct ldb_message *msg,
167 const struct ldb_message_element *el,
168 int flags)
170 if (ldb_msg_add_empty(msg, el->name, flags, NULL) != 0) {
171 return LDB_ERR_OPERATIONS_ERROR;
174 msg->elements[msg->num_elements-1] = *el;
175 msg->elements[msg->num_elements-1].flags = flags;
177 return LDB_SUCCESS;
181 add a value to a message
183 int ldb_msg_add_value(struct ldb_message *msg,
184 const char *attr_name,
185 const struct ldb_val *val,
186 struct ldb_message_element **return_el)
188 struct ldb_message_element *el;
189 struct ldb_val *vals;
190 int ret;
192 el = ldb_msg_find_element(msg, attr_name);
193 if (!el) {
194 ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
195 if (ret != LDB_SUCCESS) {
196 return ret;
200 vals = talloc_realloc(msg, el->values, struct ldb_val, el->num_values+1);
201 if (!vals) {
202 errno = ENOMEM;
203 return LDB_ERR_OPERATIONS_ERROR;
205 el->values = vals;
206 el->values[el->num_values] = *val;
207 el->num_values++;
209 if (return_el) {
210 *return_el = el;
213 return LDB_SUCCESS;
218 add a value to a message, stealing it into the 'right' place
220 int ldb_msg_add_steal_value(struct ldb_message *msg,
221 const char *attr_name,
222 struct ldb_val *val)
224 int ret;
225 struct ldb_message_element *el;
227 ret = ldb_msg_add_value(msg, attr_name, val, &el);
228 if (ret == LDB_SUCCESS) {
229 talloc_steal(el->values, val->data);
231 return ret;
236 add a string element to a message
238 int ldb_msg_add_string(struct ldb_message *msg,
239 const char *attr_name, const char *str)
241 struct ldb_val val;
243 val.data = discard_const_p(uint8_t, str);
244 val.length = strlen(str);
246 if (val.length == 0) {
247 /* allow empty strings as non-existant attributes */
248 return LDB_SUCCESS;
251 return ldb_msg_add_value(msg, attr_name, &val, NULL);
255 add a string element to a message, stealing it into the 'right' place
257 int ldb_msg_add_steal_string(struct ldb_message *msg,
258 const char *attr_name, char *str)
260 struct ldb_val val;
262 val.data = (uint8_t *)str;
263 val.length = strlen(str);
265 return ldb_msg_add_steal_value(msg, attr_name, &val);
269 add a printf formatted element to a message
271 int ldb_msg_add_fmt(struct ldb_message *msg,
272 const char *attr_name, const char *fmt, ...)
274 struct ldb_val val;
275 va_list ap;
276 char *str;
278 va_start(ap, fmt);
279 str = talloc_vasprintf(msg, fmt, ap);
280 va_end(ap);
282 if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
284 val.data = (uint8_t *)str;
285 val.length = strlen(str);
287 return ldb_msg_add_steal_value(msg, attr_name, &val);
291 compare two ldb_message_element structures
292 assumes case senistive comparison
294 int ldb_msg_element_compare(struct ldb_message_element *el1,
295 struct ldb_message_element *el2)
297 unsigned int i;
299 if (el1->num_values != el2->num_values) {
300 return el1->num_values - el2->num_values;
303 for (i=0;i<el1->num_values;i++) {
304 if (!ldb_msg_find_val(el2, &el1->values[i])) {
305 return -1;
309 return 0;
313 compare two ldb_message_element structures
314 comparing by element name
316 int ldb_msg_element_compare_name(struct ldb_message_element *el1,
317 struct ldb_message_element *el2)
319 return ldb_attr_cmp(el1->name, el2->name);
323 convenience functions to return common types from a message
324 these return the first value if the attribute is multi-valued
326 const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg, const char *attr_name)
328 struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
329 if (!el || el->num_values == 0) {
330 return NULL;
332 return &el->values[0];
335 int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
336 const char *attr_name,
337 int default_value)
339 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
340 if (!v || !v->data) {
341 return default_value;
343 return strtol((const char *)v->data, NULL, 0);
346 unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
347 const char *attr_name,
348 unsigned int default_value)
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 strtoul((const char *)v->data, NULL, 0);
357 int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
358 const char *attr_name,
359 int64_t default_value)
361 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
362 if (!v || !v->data) {
363 return default_value;
365 return strtoll((const char *)v->data, NULL, 0);
368 uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
369 const char *attr_name,
370 uint64_t default_value)
372 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
373 if (!v || !v->data) {
374 return default_value;
376 return strtoull((const char *)v->data, NULL, 0);
379 double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
380 const char *attr_name,
381 double default_value)
383 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
384 if (!v || !v->data) {
385 return default_value;
387 return strtod((const char *)v->data, NULL);
390 int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
391 const char *attr_name,
392 int default_value)
394 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
395 if (!v || !v->data) {
396 return default_value;
398 if (strcasecmp((const char *)v->data, "FALSE") == 0) {
399 return 0;
401 if (strcasecmp((const char *)v->data, "TRUE") == 0) {
402 return 1;
404 return default_value;
407 const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
408 const char *attr_name,
409 const char *default_value)
411 const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
412 if (!v || !v->data) {
413 return default_value;
415 return (const char *)v->data;
418 struct ldb_dn *ldb_msg_find_attr_as_dn(void *mem_ctx,
419 const struct ldb_message *msg,
420 const char *attr_name)
422 const struct ldb_val *v;
424 v = ldb_msg_find_ldb_val(msg, attr_name);
425 if (!v || !v->data) {
426 return NULL;
428 return ldb_dn_explode(mem_ctx, (const char *)v->data);
432 sort the elements of a message by name
434 void ldb_msg_sort_elements(struct ldb_message *msg)
436 qsort(msg->elements, msg->num_elements, sizeof(struct ldb_message_element),
437 (comparison_fn_t)ldb_msg_element_compare_name);
441 shallow copy a message - copying only the elements array so that the caller
442 can safely add new elements without changing the message
444 struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
445 const struct ldb_message *msg)
447 struct ldb_message *msg2;
448 int i;
450 msg2 = talloc(mem_ctx, struct ldb_message);
451 if (msg2 == NULL) return NULL;
453 *msg2 = *msg;
454 msg2->private_data = NULL;
456 msg2->elements = talloc_array(msg2, struct ldb_message_element,
457 msg2->num_elements);
458 if (msg2->elements == NULL) goto failed;
460 for (i=0;i<msg2->num_elements;i++) {
461 msg2->elements[i] = msg->elements[i];
464 return msg2;
466 failed:
467 talloc_free(msg2);
468 return NULL;
473 copy a message, allocating new memory for all parts
475 struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
476 const struct ldb_message *msg)
478 struct ldb_message *msg2;
479 int i, j;
481 msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
482 if (msg2 == NULL) return NULL;
484 msg2->dn = ldb_dn_copy(msg2, msg2->dn);
485 if (msg2->dn == NULL) goto failed;
487 for (i=0;i<msg2->num_elements;i++) {
488 struct ldb_message_element *el = &msg2->elements[i];
489 struct ldb_val *values = el->values;
490 el->name = talloc_strdup(msg2->elements, el->name);
491 if (el->name == NULL) goto failed;
492 el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
493 for (j=0;j<el->num_values;j++) {
494 el->values[j] = ldb_val_dup(el->values, &values[j]);
495 if (el->values[j].data == NULL && values[j].length != 0) {
496 goto failed;
501 return msg2;
503 failed:
504 talloc_free(msg2);
505 return NULL;
510 canonicalise a message, merging elements of the same name
512 struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
513 const struct ldb_message *msg)
515 int i;
516 struct ldb_message *msg2;
518 msg2 = ldb_msg_copy(ldb, msg);
519 if (msg2 == NULL) return NULL;
521 ldb_msg_sort_elements(msg2);
523 for (i=1;i<msg2->num_elements;i++) {
524 struct ldb_message_element *el1 = &msg2->elements[i-1];
525 struct ldb_message_element *el2 = &msg2->elements[i];
526 if (ldb_msg_element_compare_name(el1, el2) == 0) {
527 el1->values = talloc_realloc(msg2->elements, el1->values, struct ldb_val,
528 el1->num_values + el2->num_values);
529 if (el1->values == NULL) {
530 return NULL;
532 memcpy(el1->values + el1->num_values,
533 el2->values,
534 sizeof(struct ldb_val) * el2->num_values);
535 el1->num_values += el2->num_values;
536 talloc_free(discard_const_p(char, el2->name));
537 if (i+1<msg2->num_elements) {
538 memmove(el2, el2+1, sizeof(struct ldb_message_element) *
539 (msg2->num_elements - (i+1)));
541 msg2->num_elements--;
542 i--;
546 return msg2;
551 return a ldb_message representing the differences between msg1 and msg2. If you
552 then use this in a ldb_modify() call it can be used to save edits to a message
554 struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
555 struct ldb_message *msg1,
556 struct ldb_message *msg2)
558 struct ldb_message *mod;
559 struct ldb_message_element *el;
560 unsigned int i;
562 mod = ldb_msg_new(ldb);
564 mod->dn = msg1->dn;
565 mod->num_elements = 0;
566 mod->elements = NULL;
568 msg2 = ldb_msg_canonicalize(ldb, msg2);
569 if (msg2 == NULL) {
570 return NULL;
573 /* look in msg2 to find elements that need to be added
574 or modified */
575 for (i=0;i<msg2->num_elements;i++) {
576 el = ldb_msg_find_element(msg1, msg2->elements[i].name);
578 if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
579 continue;
582 if (ldb_msg_add(mod,
583 &msg2->elements[i],
584 el?LDB_FLAG_MOD_REPLACE:LDB_FLAG_MOD_ADD) != 0) {
585 return NULL;
589 /* look in msg1 to find elements that need to be deleted */
590 for (i=0;i<msg1->num_elements;i++) {
591 el = ldb_msg_find_element(msg2, msg1->elements[i].name);
592 if (!el) {
593 if (ldb_msg_add_empty(mod,
594 msg1->elements[i].name,
595 LDB_FLAG_MOD_DELETE, NULL) != 0) {
596 return NULL;
601 return mod;
604 int ldb_msg_sanity_check(struct ldb_context *ldb,
605 const struct ldb_message *msg)
607 int i, j;
609 /* basic check on DN */
610 if (msg->dn == NULL) {
611 /* TODO: return also an error string */
612 ldb_set_errstring(ldb, "ldb message lacks a DN!");
613 return LDB_ERR_INVALID_DN_SYNTAX;
616 /* basic syntax checks */
617 for (i = 0; i < msg->num_elements; i++) {
618 for (j = 0; j < msg->elements[i].num_values; j++) {
619 if (msg->elements[i].values[j].length == 0) {
620 TALLOC_CTX *mem_ctx = talloc_new(ldb);
621 /* an attribute cannot be empty */
622 /* TODO: return also an error string */
623 ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
624 msg->elements[i].name,
625 ldb_dn_linearize(mem_ctx, msg->dn));
626 talloc_free(mem_ctx);
627 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
632 return LDB_SUCCESS;
639 copy an attribute list. This only copies the array, not the elements
640 (ie. the elements are left as the same pointers)
642 const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
644 const char **ret;
645 int i;
646 for (i=0;attrs[i];i++) /* noop */ ;
647 ret = talloc_array(mem_ctx, const char *, i+1);
648 if (ret == NULL) {
649 return NULL;
651 for (i=0;attrs[i];i++) {
652 ret[i] = attrs[i];
654 ret[i] = attrs[i];
655 return ret;
660 copy an attribute list. This only copies the array, not the elements
661 (ie. the elements are left as the same pointers). The new attribute is added to the list.
663 const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
665 const char **ret;
666 int i;
667 for (i=0;attrs[i];i++) /* noop */ ;
668 ret = talloc_array(mem_ctx, const char *, i+2);
669 if (ret == NULL) {
670 return NULL;
672 for (i=0;attrs[i];i++) {
673 ret[i] = attrs[i];
675 ret[i] = new_attr;
676 ret[i+1] = NULL;
677 return ret;
682 return 1 if an attribute is in a list of attributes, or 0 otherwise
684 int ldb_attr_in_list(const char * const *attrs, const char *attr)
686 int i;
687 for (i=0;attrs[i];i++) {
688 if (ldb_attr_cmp(attrs[i], attr) == 0) {
689 return 1;
692 return 0;
697 rename the specified attribute in a search result
699 int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
701 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
702 if (el == NULL) {
703 return LDB_SUCCESS;
705 el->name = talloc_strdup(msg->elements, replace);
706 if (el->name == NULL) {
707 return LDB_ERR_OPERATIONS_ERROR;
709 return LDB_SUCCESS;
714 copy the specified attribute in a search result to a new attribute
716 int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
718 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
719 if (el == NULL) {
720 return LDB_SUCCESS;
722 if (ldb_msg_add(msg, el, 0) != 0) {
723 return LDB_ERR_OPERATIONS_ERROR;
725 return ldb_msg_rename_attr(msg, attr, replace);
730 remove the specified attribute in a search result
732 void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
734 struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
735 if (el) {
736 int n = (el - msg->elements);
737 if (n != msg->num_elements-1) {
738 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
740 msg->num_elements--;
745 remove the specified element in a search result
747 void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
749 int n = (el - msg->elements);
750 if (n != msg->num_elements-1) {
751 memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
753 msg->num_elements--;
757 return a LDAP formatted time string
759 char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
761 struct tm *tm = gmtime(&t);
763 if (!tm) {
764 return NULL;
767 /* formatted like: 20040408072012.0Z */
768 return talloc_asprintf(mem_ctx,
769 "%04u%02u%02u%02u%02u%02u.0Z",
770 tm->tm_year+1900, tm->tm_mon+1,
771 tm->tm_mday, tm->tm_hour, tm->tm_min,
772 tm->tm_sec);
777 convert a LDAP time string to a time_t. Return 0 if unable to convert
779 time_t ldb_string_to_time(const char *s)
781 struct tm tm;
783 if (s == NULL) return 0;
785 memset(&tm, 0, sizeof(tm));
786 if (sscanf(s, "%04u%02u%02u%02u%02u%02u",
787 &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
788 &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
789 return 0;
791 tm.tm_year -= 1900;
792 tm.tm_mon -= 1;
794 return timegm(&tm);
799 dump a set of results to a file. Useful from within gdb
801 void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
803 int i;
805 for (i = 0; i < result->count; i++) {
806 struct ldb_ldif ldif;
807 fprintf(f, "# record %d\n", i+1);
808 ldif.changetype = LDB_CHANGETYPE_NONE;
809 ldif.msg = result->msgs[i];
810 ldb_ldif_write_file(ldb, f, &ldif);
814 int ldb_msg_check_string_attribute(const struct ldb_message *msg, const char *name, const char *value)
816 struct ldb_message_element *el;
817 struct ldb_val val;
819 el = ldb_msg_find_element(msg, name);
820 if (el == NULL)
821 return 0;
823 val.data = discard_const_p(uint8_t, value);
824 val.length = strlen(value);
826 if (ldb_msg_find_val(el, &val))
827 return 1;
829 return 0;