Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Andrew Tridgell 2004
5 :
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
9 :
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.
14 :
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.
19 :
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/>.
22 : */
23 :
24 : /*
25 : * Name: ldb
26 : *
27 : * Component: ldb message component utility functions
28 : *
29 : * Description: functions for manipulating ldb_message structures
30 : *
31 : * Author: Andrew Tridgell
32 : */
33 :
34 : #include "ldb_private.h"
35 :
36 : /*
37 : create a new ldb_message in a given memory context (NULL for top level)
38 : */
39 519776392 : struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
40 : {
41 519776392 : return talloc_zero(mem_ctx, struct ldb_message);
42 : }
43 :
44 : /*
45 : find an element in a message by attribute name
46 : */
47 6511418974 : struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48 : const char *attr_name)
49 : {
50 : unsigned int i;
51 91734938130 : for (i=0;i<msg->num_elements;i++) {
52 87139854316 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53 1916335160 : return &msg->elements[i];
54 : }
55 : }
56 4595083814 : return NULL;
57 : }
58 :
59 : /*
60 : see if two ldb_val structures contain exactly the same data
61 : return 1 for a match, 0 for a mis-match
62 : */
63 228056592 : int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
64 : {
65 228056592 : if (v1->length != v2->length) return 0;
66 39438347 : if (v1->data == v2->data) return 1;
67 39360803 : if (v1->length == 0) return 1;
68 :
69 39360803 : if (memcmp(v1->data, v2->data, v1->length) == 0) {
70 24127634 : return 1;
71 : }
72 :
73 15233169 : return 0;
74 : }
75 :
76 : /*
77 : find a value in an element
78 : assumes case sensitive comparison
79 : */
80 18029656 : struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
81 : struct ldb_val *val)
82 : {
83 : unsigned int i;
84 211426101 : for (i=0;i<el->num_values;i++) {
85 211177075 : if (ldb_val_equal_exact(val, &el->values[i])) {
86 17780630 : return &el->values[i];
87 : }
88 : }
89 249026 : return NULL;
90 : }
91 :
92 :
93 6441402 : static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
94 : {
95 6441402 : if (v1->length != v2->length) {
96 5384452 : return v1->length - v2->length;
97 : }
98 1056950 : return memcmp(v1->data, v2->data, v1->length);
99 : }
100 :
101 :
102 : /*
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).
105 :
106 : LDB_ERR_OPERATIONS_ERROR indicates an allocation failure or an unknown
107 : options flag, otherwise LDB_SUCCESS.
108 : */
109 : #define LDB_DUP_QUADRATIC_THRESHOLD 10
110 :
111 21920806 : 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)
116 : {
117 : unsigned int i, j;
118 : struct ldb_val *val;
119 :
120 21920806 : if (options != 0) {
121 0 : return LDB_ERR_OPERATIONS_ERROR;
122 : }
123 :
124 21920806 : *duplicate = NULL;
125 :
126 : /*
127 : If there are not many values, it is best to avoid the talloc
128 : overhead and just do a brute force search.
129 : */
130 21920806 : if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
131 45646658 : for (j = 0; j < el->num_values; j++) {
132 23767527 : val = &el->values[j];
133 27427791 : for ( i = j + 1; i < el->num_values; i++) {
134 3660267 : if (ldb_val_equal_exact(val, &el->values[i])) {
135 3 : *duplicate = val;
136 3 : return LDB_SUCCESS;
137 : }
138 : }
139 : }
140 : } else {
141 : struct ldb_val *values;
142 41672 : values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
143 41672 : if (values == NULL) {
144 0 : return LDB_ERR_OPERATIONS_ERROR;
145 : }
146 :
147 41672 : memcpy(values, el->values,
148 41672 : el->num_values * sizeof(struct ldb_val));
149 41672 : TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
150 1495819 : for (i = 1; i < el->num_values; i++) {
151 1454148 : if (ldb_val_equal_exact(&values[i],
152 1454148 : &values[i - 1])) {
153 : /* find the original location */
154 3 : for (j = 0; j < el->num_values; j++) {
155 3 : if (ldb_val_equal_exact(&values[i],
156 3 : &el->values[j])
157 : ) {
158 1 : *duplicate = &el->values[j];
159 1 : break;
160 : }
161 : }
162 1 : talloc_free(values);
163 1 : if (*duplicate == NULL) {
164 : /* how we got here, I don't know */
165 0 : return LDB_ERR_OPERATIONS_ERROR;
166 : }
167 1 : return LDB_SUCCESS;
168 : }
169 : }
170 41671 : talloc_free(values);
171 : }
172 21920802 : return LDB_SUCCESS;
173 : }
174 :
175 :
176 : /*
177 : Determine whether the values in an element are also in another element.
178 :
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.
183 :
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.
186 :
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.
189 : */
190 :
191 3472 : 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)
196 : {
197 : struct ldb_val *values;
198 : struct ldb_val *values2;
199 : unsigned int i, j, k, n_values;
200 :
201 3472 : bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
202 :
203 3472 : if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
204 0 : return LDB_ERR_OPERATIONS_ERROR;
205 : }
206 :
207 3472 : if (strcmp(el->name, el2->name) != 0) {
208 1 : return LDB_ERR_INAPPROPRIATE_MATCHING;
209 : }
210 3471 : if (el->num_values == 0 || el2->num_values == 0) {
211 12 : return LDB_SUCCESS;
212 : }
213 : /*
214 : With few values, it is better to do the brute-force search than the
215 : clever search involving tallocs, memcpys, sorts, etc.
216 : */
217 3591 : if (MIN(el->num_values, el2->num_values) == 1 ||
218 157 : MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
219 15396 : for (i = 0; i < el2->num_values; i++) {
220 24592 : for (j = 0; j < el->num_values; j++) {
221 12555 : if (ldb_val_equal_exact(&el->values[j],
222 12555 : &el2->values[i])) {
223 8 : if (! remove_duplicates) {
224 : return \
225 6 : LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
226 : }
227 : /*
228 : With the remove_duplicates flag, we
229 : resolve the intersection by removing
230 : the offending one from el.
231 : */
232 2 : el->num_values--;
233 3 : for (k = j; k < el->num_values; k++) {
234 1 : el->values[k] = \
235 1 : el->values[k + 1];
236 : }
237 2 : j--; /* rewind */
238 : }
239 : }
240 : }
241 3353 : return LDB_SUCCESS;
242 : }
243 :
244 100 : values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
245 100 : if (values == NULL) {
246 0 : return LDB_ERR_OPERATIONS_ERROR;
247 : }
248 100 : values2 = talloc_array(mem_ctx, struct ldb_val,
249 : el2->num_values);
250 100 : if (values2 == NULL) {
251 0 : return LDB_ERR_OPERATIONS_ERROR;
252 : }
253 :
254 100 : memcpy(values, el->values,
255 100 : el->num_values * sizeof(struct ldb_val));
256 100 : memcpy(values2, el2->values,
257 100 : el2->num_values * sizeof(struct ldb_val));
258 100 : TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
259 100 : TYPESAFE_QSORT(values2, el2->num_values, ldb_val_cmp);
260 :
261 : /*
262 : el->n_values may diverge from the number of values in the sorted
263 : list when the remove_duplicates flag is used.
264 : */
265 100 : n_values = el->num_values;
266 100 : i = 0;
267 100 : j = 0;
268 3380 : while (i != n_values && j < el2->num_values) {
269 3196 : int ret = ldb_val_cmp(&values[i], &values2[j]);
270 3196 : if (ret < 0) {
271 721 : i++;
272 2475 : } else if (ret > 0) {
273 2457 : j++;
274 : } else {
275 : /* we have a collision */
276 18 : if (! remove_duplicates) {
277 4 : TALLOC_FREE(values);
278 4 : TALLOC_FREE(values2);
279 4 : return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
280 : }
281 : /*
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.
285 : */
286 23 : for (k = 0; k < el->num_values; k++) {
287 23 : if (ldb_val_equal_exact(&el->values[k],
288 23 : &values[i])) {
289 14 : break;
290 : }
291 : }
292 14 : el->num_values--;
293 76 : for (; k < el->num_values; k++) {
294 62 : el->values[k] = el->values[k + 1];
295 : }
296 14 : i++;
297 : }
298 : }
299 96 : TALLOC_FREE(values);
300 96 : TALLOC_FREE(values2);
301 :
302 96 : return LDB_SUCCESS;
303 : }
304 :
305 : /*
306 : duplicate a ldb_val structure
307 : */
308 2135242436 : struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
309 : {
310 : struct ldb_val v2;
311 2135242436 : v2.length = v->length;
312 2135242436 : if (v->data == NULL) {
313 93122 : v2.data = NULL;
314 93122 : return v2;
315 : }
316 :
317 : /* the +1 is to cope with buggy C library routines like strndup
318 : that look one byte beyond */
319 2135149314 : v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
320 2135149314 : if (!v2.data) {
321 0 : v2.length = 0;
322 0 : return v2;
323 : }
324 :
325 2135149314 : memcpy(v2.data, v->data, v->length);
326 2135149314 : ((char *)v2.data)[v->length] = 0;
327 2135149314 : return v2;
328 : }
329 :
330 : /**
331 : * Adds new empty element to msg->elements
332 : */
333 168174511 : static int _ldb_msg_add_el(struct ldb_message *msg,
334 : struct ldb_message_element **return_el)
335 : {
336 : struct ldb_message_element *els;
337 :
338 : /*
339 : * TODO: Find out a way to assert on input parameters.
340 : * msg and return_el must be valid
341 : */
342 :
343 168174511 : els = talloc_realloc(msg, msg->elements,
344 : struct ldb_message_element, msg->num_elements + 1);
345 168174511 : if (!els) {
346 0 : return LDB_ERR_OPERATIONS_ERROR;
347 : }
348 :
349 168174511 : ZERO_STRUCT(els[msg->num_elements]);
350 :
351 168174511 : msg->elements = els;
352 168174511 : msg->num_elements++;
353 :
354 168174511 : *return_el = &els[msg->num_elements-1];
355 :
356 168174511 : return LDB_SUCCESS;
357 : }
358 :
359 : /**
360 : * Add an empty element with a given name to a message
361 : */
362 166590904 : int ldb_msg_add_empty(struct ldb_message *msg,
363 : const char *attr_name,
364 : int flags,
365 : struct ldb_message_element **return_el)
366 : {
367 : int ret;
368 : struct ldb_message_element *el;
369 :
370 166590904 : ret = _ldb_msg_add_el(msg, &el);
371 166590904 : if (ret != LDB_SUCCESS) {
372 0 : return ret;
373 : }
374 :
375 : /* initialize newly added element */
376 166590904 : el->flags = flags;
377 166590904 : el->name = talloc_strdup(msg->elements, attr_name);
378 166590904 : if (!el->name) {
379 0 : return LDB_ERR_OPERATIONS_ERROR;
380 : }
381 :
382 166590904 : if (return_el) {
383 166250677 : *return_el = el;
384 : }
385 :
386 166590904 : return LDB_SUCCESS;
387 : }
388 :
389 : /**
390 : * Adds an element to a message.
391 : *
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
396 : */
397 1583607 : int ldb_msg_add(struct ldb_message *msg,
398 : const struct ldb_message_element *el,
399 : int flags)
400 : {
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 1583607 : struct ldb_message_element el_copy = *el;
406 :
407 1583607 : ret = _ldb_msg_add_el(msg, &el_new);
408 1583607 : if (ret != LDB_SUCCESS) {
409 0 : return ret;
410 : }
411 :
412 1583607 : el_new->flags = flags;
413 1583607 : el_new->name = el_copy.name;
414 1583607 : el_new->num_values = el_copy.num_values;
415 1583607 : el_new->values = el_copy.values;
416 :
417 1583607 : return LDB_SUCCESS;
418 : }
419 :
420 : /*
421 : * add a value to a message element
422 : */
423 160770533 : int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
424 : struct ldb_message_element *el,
425 : const struct ldb_val *val)
426 : {
427 : struct ldb_val *vals;
428 :
429 160770533 : if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
430 : /*
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.
435 : */
436 26 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
437 :
438 26 : vals = talloc_array(mem_ctx, struct ldb_val,
439 : el->num_values + 1);
440 26 : if (vals == NULL) {
441 0 : return LDB_ERR_OPERATIONS_ERROR;
442 : }
443 :
444 26 : if (el->values != NULL) {
445 26 : memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
446 : }
447 : } else {
448 160770507 : vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
449 : el->num_values + 1);
450 160770507 : if (vals == NULL) {
451 0 : return LDB_ERR_OPERATIONS_ERROR;
452 : }
453 : }
454 160770533 : el->values = vals;
455 160770533 : el->values[el->num_values] = *val;
456 160770533 : el->num_values++;
457 :
458 160770533 : return LDB_SUCCESS;
459 : }
460 :
461 : /*
462 : add a value to a message
463 : */
464 160595918 : 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)
468 : {
469 : struct ldb_message_element *el;
470 : int ret;
471 :
472 160595918 : el = ldb_msg_find_element(msg, attr_name);
473 160595918 : if (!el) {
474 156791235 : ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
475 156791235 : if (ret != LDB_SUCCESS) {
476 0 : return ret;
477 : }
478 : }
479 :
480 160595918 : ret = ldb_msg_element_add_value(msg->elements, el, val);
481 160595918 : if (ret != LDB_SUCCESS) {
482 0 : return ret;
483 : }
484 :
485 160595918 : if (return_el) {
486 158888465 : *return_el = el;
487 : }
488 :
489 160595918 : return LDB_SUCCESS;
490 : }
491 :
492 :
493 : /*
494 : add a value to a message, stealing it into the 'right' place
495 : */
496 135777396 : int ldb_msg_add_steal_value(struct ldb_message *msg,
497 : const char *attr_name,
498 : struct ldb_val *val)
499 : {
500 : int ret;
501 : struct ldb_message_element *el;
502 :
503 135777396 : ret = ldb_msg_add_value(msg, attr_name, val, &el);
504 135777396 : if (ret == LDB_SUCCESS) {
505 135777396 : talloc_steal(el->values, val->data);
506 : }
507 135777396 : return ret;
508 : }
509 :
510 :
511 : /*
512 : add a string element to a message, specifying flags
513 : */
514 22710281 : int ldb_msg_add_string_flags(struct ldb_message *msg,
515 : const char *attr_name, const char *str,
516 : int flags)
517 : {
518 : struct ldb_val val;
519 : int ret;
520 22710281 : struct ldb_message_element *el = NULL;
521 :
522 22710281 : val.data = discard_const_p(uint8_t, str);
523 22710281 : val.length = strlen(str);
524 :
525 22710281 : if (val.length == 0) {
526 : /* allow empty strings as non-existent attributes */
527 266 : return LDB_SUCCESS;
528 : }
529 :
530 22710015 : ret = ldb_msg_add_value(msg, attr_name, &val, &el);
531 22710015 : if (ret != LDB_SUCCESS) {
532 0 : return ret;
533 : }
534 :
535 22710015 : if (flags != 0) {
536 62237 : el->flags = flags;
537 : }
538 :
539 22710015 : return LDB_SUCCESS;
540 : }
541 :
542 : /*
543 : add a string element to a message
544 : */
545 22648044 : int ldb_msg_add_string(struct ldb_message *msg,
546 : const char *attr_name, const char *str)
547 : {
548 22648044 : return ldb_msg_add_string_flags(msg, attr_name, str, 0);
549 : }
550 :
551 : /*
552 : add a string element to a message, stealing it into the 'right' place
553 : */
554 121895787 : int ldb_msg_add_steal_string(struct ldb_message *msg,
555 : const char *attr_name, char *str)
556 : {
557 : struct ldb_val val;
558 :
559 121895787 : val.data = (uint8_t *)str;
560 121895787 : val.length = strlen(str);
561 :
562 121895787 : if (val.length == 0) {
563 : /* allow empty strings as non-existent attributes */
564 0 : return LDB_SUCCESS;
565 : }
566 :
567 121895787 : return ldb_msg_add_steal_value(msg, attr_name, &val);
568 : }
569 :
570 : /*
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.
574 : */
575 1600 : int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
576 : struct ldb_dn *dn)
577 : {
578 1600 : char *str = ldb_dn_alloc_linearized(msg, dn);
579 :
580 1600 : if (str == NULL) {
581 : /* we don't want to have unknown DNs added */
582 0 : return LDB_ERR_OPERATIONS_ERROR;
583 : }
584 :
585 1600 : return ldb_msg_add_steal_string(msg, attr_name, str);
586 : }
587 :
588 : /*
589 : add a printf formatted element to a message
590 : */
591 7763844 : int ldb_msg_add_fmt(struct ldb_message *msg,
592 : const char *attr_name, const char *fmt, ...)
593 : {
594 : struct ldb_val val;
595 : va_list ap;
596 : char *str;
597 :
598 7763844 : va_start(ap, fmt);
599 7763844 : str = talloc_vasprintf(msg, fmt, ap);
600 7763844 : va_end(ap);
601 :
602 7763844 : if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
603 :
604 7763844 : val.data = (uint8_t *)str;
605 7763844 : val.length = strlen(str);
606 :
607 7763844 : return ldb_msg_add_steal_value(msg, attr_name, &val);
608 : }
609 :
610 174187 : 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)
615 : {
616 174187 : struct ldb_message_element *el = NULL;
617 : int ret;
618 :
619 174187 : ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
620 174187 : if (ret != LDB_SUCCESS) {
621 0 : return ret;
622 : }
623 :
624 174187 : ret = ldb_msg_element_add_value(msg->elements, el, val);
625 174187 : if (ret != LDB_SUCCESS) {
626 0 : return ret;
627 : }
628 :
629 174187 : if (return_el != NULL) {
630 1542 : *return_el = el;
631 : }
632 :
633 174187 : return LDB_SUCCESS;
634 : }
635 :
636 : /*
637 : append a value to a message
638 : */
639 172645 : int ldb_msg_append_value(struct ldb_message *msg,
640 : const char *attr_name,
641 : const struct ldb_val *val,
642 : int flags)
643 : {
644 172645 : return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
645 : }
646 :
647 : /*
648 : append a value to a message, stealing it into the 'right' place
649 : */
650 1542 : int ldb_msg_append_steal_value(struct ldb_message *msg,
651 : const char *attr_name,
652 : struct ldb_val *val,
653 : int flags)
654 : {
655 : int ret;
656 1542 : struct ldb_message_element *el = NULL;
657 :
658 1542 : ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
659 1542 : if (ret == LDB_SUCCESS) {
660 1542 : talloc_steal(el->values, val->data);
661 : }
662 1542 : return ret;
663 : }
664 :
665 : /*
666 : append a string element to a message, stealing it into the 'right' place
667 : */
668 696 : int ldb_msg_append_steal_string(struct ldb_message *msg,
669 : const char *attr_name, char *str,
670 : int flags)
671 : {
672 : struct ldb_val val;
673 :
674 696 : val.data = (uint8_t *)str;
675 696 : val.length = strlen(str);
676 :
677 696 : if (val.length == 0) {
678 : /* allow empty strings as non-existent attributes */
679 0 : return LDB_SUCCESS;
680 : }
681 :
682 696 : return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
683 : }
684 :
685 : /*
686 : append a string element to a message
687 : */
688 45659 : int ldb_msg_append_string(struct ldb_message *msg,
689 : const char *attr_name, const char *str, int flags)
690 : {
691 : struct ldb_val val;
692 :
693 45659 : val.data = discard_const_p(uint8_t, str);
694 45659 : val.length = strlen(str);
695 :
696 45659 : if (val.length == 0) {
697 : /* allow empty strings as non-existent attributes */
698 0 : return LDB_SUCCESS;
699 : }
700 :
701 45659 : return ldb_msg_append_value(msg, attr_name, &val, flags);
702 : }
703 :
704 : /*
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.
708 : */
709 0 : int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
710 : struct ldb_dn *dn, int flags)
711 : {
712 0 : char *str = ldb_dn_alloc_linearized(msg, dn);
713 :
714 0 : if (str == NULL) {
715 : /* we don't want to have unknown DNs added */
716 0 : return LDB_ERR_OPERATIONS_ERROR;
717 : }
718 :
719 0 : return ldb_msg_append_steal_string(msg, attr_name, str, flags);
720 : }
721 :
722 : /*
723 : append a printf formatted element to a message
724 : */
725 846 : int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
726 : const char *attr_name, const char *fmt, ...)
727 : {
728 : struct ldb_val val;
729 : va_list ap;
730 846 : char *str = NULL;
731 :
732 846 : va_start(ap, fmt);
733 846 : str = talloc_vasprintf(msg, fmt, ap);
734 846 : va_end(ap);
735 :
736 846 : if (str == NULL) {
737 0 : return LDB_ERR_OPERATIONS_ERROR;
738 : }
739 :
740 846 : val.data = (uint8_t *)str;
741 846 : val.length = strlen(str);
742 :
743 846 : return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
744 : }
745 :
746 : /*
747 : compare two ldb_message_element structures
748 : assumes case sensitive comparison
749 : */
750 13656510 : int ldb_msg_element_compare(struct ldb_message_element *el1,
751 : struct ldb_message_element *el2)
752 : {
753 : unsigned int i;
754 :
755 13656510 : if (el1->num_values != el2->num_values) {
756 95 : return el1->num_values - el2->num_values;
757 : }
758 :
759 30203098 : for (i=0;i<el1->num_values;i++) {
760 16601136 : if (!ldb_msg_find_val(el2, &el1->values[i])) {
761 54453 : return -1;
762 : }
763 : }
764 :
765 13601962 : return 0;
766 : }
767 :
768 : /*
769 : compare two ldb_message_element structures.
770 : Different ordering is considered a mismatch
771 : */
772 8687952 : bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
773 : const struct ldb_message_element *el2)
774 : {
775 : unsigned i;
776 8687952 : if (el1->num_values != el2->num_values) {
777 824538 : return false;
778 : }
779 11938582 : for (i=0;i<el1->num_values;i++) {
780 8319822 : if (ldb_val_equal_exact(&el1->values[i],
781 8319822 : &el2->values[i]) != 1) {
782 4244654 : return false;
783 : }
784 : }
785 3618760 : return true;
786 : }
787 :
788 : /*
789 : compare two ldb_message_element structures
790 : comparing by element name
791 : */
792 167410995 : int ldb_msg_element_compare_name(struct ldb_message_element *el1,
793 : struct ldb_message_element *el2)
794 : {
795 167410995 : return ldb_attr_cmp(el1->name, el2->name);
796 : }
797 :
798 4571470 : void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
799 : {
800 4571470 : el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
801 4571470 : }
802 :
803 149915925 : bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
804 : {
805 149915925 : return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
806 : }
807 :
808 1306591 : void ldb_msg_remove_inaccessible(struct ldb_message *msg)
809 : {
810 : unsigned i;
811 1306591 : unsigned num_del = 0;
812 :
813 9261278 : for (i = 0; i < msg->num_elements; ++i) {
814 7954687 : if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
815 4566818 : ++num_del;
816 3387869 : } else if (num_del) {
817 2473033 : msg->elements[i - num_del] = msg->elements[i];
818 : }
819 : }
820 :
821 1306591 : msg->num_elements -= num_del;
822 1306591 : }
823 :
824 : /*
825 : convenience functions to return common types from a message
826 : these return the first value if the attribute is multi-valued
827 : */
828 2267134604 : const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
829 : const char *attr_name)
830 : {
831 2267134604 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
832 2267134604 : if (!el || el->num_values == 0) {
833 1007832003 : return NULL;
834 : }
835 1259302601 : return &el->values[0];
836 : }
837 :
838 99200037 : int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
839 : const char *attr_name,
840 : int default_value)
841 : {
842 99200037 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
843 : char buf[sizeof("-2147483648")];
844 99200037 : char *end = NULL;
845 : int ret;
846 :
847 99200037 : if (!v || !v->data) {
848 1336648 : return default_value;
849 : }
850 :
851 97863389 : ZERO_STRUCT(buf);
852 97863389 : if (v->length >= sizeof(buf)) {
853 66 : return default_value;
854 : }
855 :
856 97863323 : memcpy(buf, v->data, v->length);
857 97863323 : errno = 0;
858 97863323 : ret = (int) strtoll(buf, &end, 10);
859 97863323 : if (errno != 0) {
860 0 : return default_value;
861 : }
862 97863323 : if (end && end[0] != '\0') {
863 0 : return default_value;
864 : }
865 97863323 : return ret;
866 : }
867 :
868 406199237 : unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
869 : const char *attr_name,
870 : unsigned int default_value)
871 : {
872 406199237 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
873 : char buf[sizeof("-2147483648")];
874 406199237 : char *end = NULL;
875 : unsigned int ret;
876 :
877 406199237 : if (!v || !v->data) {
878 202149852 : return default_value;
879 : }
880 :
881 204049385 : ZERO_STRUCT(buf);
882 204049385 : if (v->length >= sizeof(buf)) {
883 50 : return default_value;
884 : }
885 :
886 204049335 : memcpy(buf, v->data, v->length);
887 204049335 : errno = 0;
888 204049335 : ret = (unsigned int) strtoll(buf, &end, 10);
889 204049335 : if (errno != 0) {
890 0 : errno = 0;
891 0 : ret = (unsigned int) strtoull(buf, &end, 10);
892 0 : if (errno != 0) {
893 0 : return default_value;
894 : }
895 : }
896 204049335 : if (end && end[0] != '\0') {
897 39 : return default_value;
898 : }
899 204049296 : return ret;
900 : }
901 :
902 1826150 : int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
903 : const char *attr_name,
904 : int64_t default_value)
905 : {
906 1826150 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
907 : char buf[sizeof("-9223372036854775808")];
908 1826150 : char *end = NULL;
909 : int64_t ret;
910 :
911 1826150 : if (!v || !v->data) {
912 396461 : return default_value;
913 : }
914 :
915 1429689 : ZERO_STRUCT(buf);
916 1429689 : if (v->length >= sizeof(buf)) {
917 0 : return default_value;
918 : }
919 :
920 1429689 : memcpy(buf, v->data, v->length);
921 1429689 : errno = 0;
922 1429689 : ret = (int64_t) strtoll(buf, &end, 10);
923 1429689 : if (errno != 0) {
924 0 : return default_value;
925 : }
926 1429689 : if (end && end[0] != '\0') {
927 0 : return default_value;
928 : }
929 1429689 : return ret;
930 : }
931 :
932 159187020 : uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
933 : const char *attr_name,
934 : uint64_t default_value)
935 : {
936 159187020 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
937 : char buf[sizeof("-9223372036854775808")];
938 159187020 : char *end = NULL;
939 : uint64_t ret;
940 :
941 159187020 : if (!v || !v->data) {
942 78963658 : return default_value;
943 : }
944 :
945 80223362 : ZERO_STRUCT(buf);
946 80223362 : if (v->length >= sizeof(buf)) {
947 0 : return default_value;
948 : }
949 :
950 80223362 : memcpy(buf, v->data, v->length);
951 80223362 : errno = 0;
952 80223362 : ret = (uint64_t) strtoll(buf, &end, 10);
953 80223362 : if (errno != 0) {
954 0 : errno = 0;
955 0 : ret = (uint64_t) strtoull(buf, &end, 10);
956 0 : if (errno != 0) {
957 0 : return default_value;
958 : }
959 : }
960 80223362 : if (end && end[0] != '\0') {
961 0 : return default_value;
962 : }
963 80223362 : return ret;
964 : }
965 :
966 0 : double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
967 : const char *attr_name,
968 : double default_value)
969 : {
970 0 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
971 : char *buf;
972 0 : char *end = NULL;
973 : double ret;
974 :
975 0 : if (!v || !v->data) {
976 0 : return default_value;
977 : }
978 0 : buf = talloc_strndup(msg, (const char *)v->data, v->length);
979 0 : if (buf == NULL) {
980 0 : return default_value;
981 : }
982 :
983 0 : errno = 0;
984 0 : ret = strtod(buf, &end);
985 0 : talloc_free(buf);
986 0 : if (errno != 0) {
987 0 : return default_value;
988 : }
989 0 : if (end && end[0] != '\0') {
990 0 : return default_value;
991 : }
992 0 : return ret;
993 : }
994 :
995 6671959 : int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
996 : const char *attr_name,
997 : int default_value)
998 : {
999 6671959 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1000 6671959 : if (!v || !v->data) {
1001 2634959 : return default_value;
1002 : }
1003 4037000 : if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
1004 69770 : return 0;
1005 : }
1006 3967230 : if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
1007 3967230 : return 1;
1008 : }
1009 0 : return default_value;
1010 : }
1011 :
1012 529167844 : const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
1013 : const char *attr_name,
1014 : const char *default_value)
1015 : {
1016 529167844 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1017 529167844 : if (!v || !v->data) {
1018 337198418 : return default_value;
1019 : }
1020 191969426 : if (v->data[v->length] != '\0') {
1021 0 : return default_value;
1022 : }
1023 191969426 : return (const char *)v->data;
1024 : }
1025 :
1026 4193612 : 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)
1030 : {
1031 : struct ldb_dn *res_dn;
1032 : const struct ldb_val *v;
1033 :
1034 4193612 : v = ldb_msg_find_ldb_val(msg, attr_name);
1035 4193612 : if (!v || !v->data) {
1036 838625 : return NULL;
1037 : }
1038 3354987 : res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
1039 3354987 : if ( ! ldb_dn_validate(res_dn)) {
1040 0 : talloc_free(res_dn);
1041 0 : return NULL;
1042 : }
1043 3354987 : return res_dn;
1044 : }
1045 :
1046 : /*
1047 : sort the elements of a message by name
1048 : */
1049 1193426 : void ldb_msg_sort_elements(struct ldb_message *msg)
1050 : {
1051 1193426 : TYPESAFE_QSORT(msg->elements, msg->num_elements,
1052 : ldb_msg_element_compare_name);
1053 1193426 : }
1054 :
1055 6552207 : static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
1056 : const struct ldb_message *msg)
1057 : {
1058 : struct ldb_message *msg2;
1059 : unsigned int i;
1060 :
1061 6552207 : msg2 = talloc(mem_ctx, struct ldb_message);
1062 6552207 : if (msg2 == NULL) return NULL;
1063 :
1064 6552207 : *msg2 = *msg;
1065 :
1066 6552207 : msg2->elements = talloc_array(msg2, struct ldb_message_element,
1067 : msg2->num_elements);
1068 6552207 : if (msg2->elements == NULL) goto failed;
1069 :
1070 69776288 : for (i=0;i<msg2->num_elements;i++) {
1071 63224081 : msg2->elements[i] = msg->elements[i];
1072 : }
1073 :
1074 6552207 : return msg2;
1075 :
1076 0 : failed:
1077 0 : talloc_free(msg2);
1078 0 : return NULL;
1079 : }
1080 :
1081 : /*
1082 : shallow copy a message - copying only the elements array so that the caller
1083 : can safely add new elements without changing the message
1084 : */
1085 5226811 : struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
1086 : const struct ldb_message *msg)
1087 : {
1088 : struct ldb_message *msg2;
1089 : unsigned int i;
1090 :
1091 5226811 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1092 5226811 : if (msg2 == NULL) {
1093 0 : return NULL;
1094 : }
1095 :
1096 40666641 : for (i = 0; i < msg2->num_elements; ++i) {
1097 : /*
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.
1103 : */
1104 35439830 : struct ldb_message_element *el = &msg2->elements[i];
1105 35439830 : el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
1106 : }
1107 :
1108 5226811 : return msg2;
1109 : }
1110 :
1111 : /*
1112 : copy a message, allocating new memory for all parts
1113 : */
1114 1325396 : struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
1115 : const struct ldb_message *msg)
1116 : {
1117 : struct ldb_message *msg2;
1118 : unsigned int i, j;
1119 :
1120 1325396 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1121 1325396 : if (msg2 == NULL) return NULL;
1122 :
1123 1325396 : if (msg2->dn != NULL) {
1124 1325384 : msg2->dn = ldb_dn_copy(msg2, msg2->dn);
1125 1325384 : if (msg2->dn == NULL) goto failed;
1126 : }
1127 :
1128 29109647 : for (i=0;i<msg2->num_elements;i++) {
1129 27784251 : struct ldb_message_element *el = &msg2->elements[i];
1130 27784251 : struct ldb_val *values = el->values;
1131 27784251 : el->name = talloc_strdup(msg2->elements, el->name);
1132 27784251 : if (el->name == NULL) goto failed;
1133 27784251 : el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
1134 27784251 : if (el->values == NULL) goto failed;
1135 61398669 : for (j=0;j<el->num_values;j++) {
1136 33614418 : el->values[j] = ldb_val_dup(el->values, &values[j]);
1137 33614418 : if (el->values[j].data == NULL && values[j].length != 0) {
1138 0 : goto failed;
1139 : }
1140 : }
1141 :
1142 : /*
1143 : * Since we copied this element's values, we can mark them as
1144 : * not shared.
1145 : */
1146 27784251 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1147 : }
1148 :
1149 1325396 : return msg2;
1150 :
1151 0 : failed:
1152 0 : talloc_free(msg2);
1153 0 : return NULL;
1154 : }
1155 :
1156 :
1157 : /**
1158 : * Canonicalize a message, merging elements of the same name
1159 : */
1160 0 : struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
1161 : const struct ldb_message *msg)
1162 : {
1163 : int ret;
1164 : struct ldb_message *msg2;
1165 :
1166 : /*
1167 : * Preserve previous behavior and allocate
1168 : * *msg2 into *ldb context
1169 : */
1170 0 : ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
1171 0 : if (ret != LDB_SUCCESS) {
1172 0 : return NULL;
1173 : }
1174 :
1175 0 : return msg2;
1176 : }
1177 :
1178 : /**
1179 : * Canonicalize a message, merging elements of the same name
1180 : */
1181 1193251 : 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)
1185 : {
1186 : unsigned int i;
1187 : struct ldb_message *msg2;
1188 :
1189 1193251 : msg2 = ldb_msg_copy(mem_ctx, msg);
1190 1193251 : if (msg2 == NULL) {
1191 0 : return LDB_ERR_OPERATIONS_ERROR;
1192 : }
1193 :
1194 1193251 : ldb_msg_sort_elements(msg2);
1195 :
1196 26704237 : for (i=1; i < msg2->num_elements; i++) {
1197 25510986 : struct ldb_message_element *el1 = &msg2->elements[i-1];
1198 25510986 : struct ldb_message_element *el2 = &msg2->elements[i];
1199 :
1200 25510986 : if (ldb_msg_element_compare_name(el1, el2) == 0) {
1201 5377 : el1->values = talloc_realloc(msg2->elements,
1202 : el1->values, struct ldb_val,
1203 : el1->num_values + el2->num_values);
1204 5377 : if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
1205 0 : talloc_free(msg2);
1206 0 : return LDB_ERR_OPERATIONS_ERROR;
1207 : }
1208 10495 : memcpy(el1->values + el1->num_values,
1209 5377 : el2->values,
1210 5377 : sizeof(struct ldb_val) * el2->num_values);
1211 5377 : el1->num_values += el2->num_values;
1212 5377 : talloc_free(discard_const_p(char, el2->name));
1213 5377 : if ((i+1) < msg2->num_elements) {
1214 0 : memmove(el2, el2+1, sizeof(struct ldb_message_element) *
1215 0 : (msg2->num_elements - (i+1)));
1216 : }
1217 5377 : msg2->num_elements--;
1218 5377 : i--;
1219 : }
1220 : }
1221 :
1222 1193251 : *_msg_out = msg2;
1223 1193251 : return LDB_SUCCESS;
1224 : }
1225 :
1226 :
1227 : /**
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
1231 : */
1232 0 : struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
1233 : struct ldb_message *msg1,
1234 : struct ldb_message *msg2)
1235 : {
1236 : int ldb_ret;
1237 : struct ldb_message *mod;
1238 :
1239 0 : ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
1240 0 : if (ldb_ret != LDB_SUCCESS) {
1241 0 : return NULL;
1242 : }
1243 :
1244 0 : return mod;
1245 : }
1246 :
1247 : /**
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
1250 : *
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
1256 : *
1257 : * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1258 : */
1259 64914 : 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)
1264 : {
1265 : int ldb_res;
1266 : unsigned int i;
1267 : struct ldb_message *mod;
1268 : struct ldb_message_element *el;
1269 : TALLOC_CTX *temp_ctx;
1270 :
1271 64914 : temp_ctx = talloc_new(mem_ctx);
1272 64914 : if (!temp_ctx) {
1273 0 : return LDB_ERR_OPERATIONS_ERROR;
1274 : }
1275 :
1276 64914 : mod = ldb_msg_new(temp_ctx);
1277 64914 : if (mod == NULL) {
1278 0 : goto failed;
1279 : }
1280 :
1281 64914 : mod->dn = msg1->dn;
1282 64914 : mod->num_elements = 0;
1283 64914 : mod->elements = NULL;
1284 :
1285 : /*
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
1290 : */
1291 64914 : ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
1292 64914 : if (ldb_res != LDB_SUCCESS) {
1293 0 : goto failed;
1294 : }
1295 :
1296 : /* look in msg2 to find elements that need to be added or modified */
1297 13715880 : for (i=0;i<msg2->num_elements;i++) {
1298 13650966 : el = ldb_msg_find_element(msg1, msg2->elements[i].name);
1299 :
1300 13650966 : if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
1301 13595230 : continue;
1302 : }
1303 :
1304 111326 : ldb_res = ldb_msg_add(mod,
1305 55736 : &msg2->elements[i],
1306 : el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
1307 55736 : if (ldb_res != LDB_SUCCESS) {
1308 0 : goto failed;
1309 : }
1310 : }
1311 :
1312 : /* look in msg1 to find elements that need to be deleted */
1313 13715254 : for (i=0;i<msg1->num_elements;i++) {
1314 13650340 : el = ldb_msg_find_element(msg2, msg1->elements[i].name);
1315 13650340 : if (el == NULL) {
1316 575 : ldb_res = ldb_msg_add_empty(mod,
1317 575 : msg1->elements[i].name,
1318 : LDB_FLAG_MOD_DELETE, NULL);
1319 575 : if (ldb_res != LDB_SUCCESS) {
1320 0 : goto failed;
1321 : }
1322 : }
1323 : }
1324 :
1325 : /* steal resulting message into supplied context */
1326 64914 : talloc_steal(mem_ctx, mod);
1327 64914 : *_msg_out = mod;
1328 :
1329 64914 : talloc_free(temp_ctx);
1330 64914 : return LDB_SUCCESS;
1331 :
1332 0 : failed:
1333 0 : talloc_free(temp_ctx);
1334 0 : return LDB_ERR_OPERATIONS_ERROR;
1335 : }
1336 :
1337 :
1338 932473 : int ldb_msg_sanity_check(struct ldb_context *ldb,
1339 : const struct ldb_message *msg)
1340 : {
1341 : unsigned int i, j;
1342 :
1343 : /* basic check on DN */
1344 932473 : if (msg->dn == NULL) {
1345 0 : ldb_set_errstring(ldb, "ldb message lacks a DN!");
1346 0 : return LDB_ERR_INVALID_DN_SYNTAX;
1347 : }
1348 :
1349 : /* basic syntax checks */
1350 5222268 : for (i = 0; i < msg->num_elements; i++) {
1351 10103104 : for (j = 0; j < msg->elements[i].num_values; j++) {
1352 5813309 : if (msg->elements[i].values[j].length == 0) {
1353 : /* an attribute cannot be empty */
1354 4 : ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
1355 2 : msg->elements[i].name,
1356 0 : ldb_dn_get_linearized(msg->dn));
1357 2 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1358 : }
1359 : }
1360 : }
1361 :
1362 932471 : return LDB_SUCCESS;
1363 : }
1364 :
1365 :
1366 :
1367 :
1368 : /*
1369 : copy an attribute list. This only copies the array, not the elements
1370 : (ie. the elements are left as the same pointers)
1371 : */
1372 8010365 : const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
1373 : {
1374 : const char **ret;
1375 : unsigned int i;
1376 :
1377 15377791 : for (i=0;attrs && attrs[i];i++) /* noop */ ;
1378 8010365 : ret = talloc_array(mem_ctx, const char *, i+1);
1379 8010365 : if (ret == NULL) {
1380 0 : return NULL;
1381 : }
1382 214715127 : for (i=0;attrs && attrs[i];i++) {
1383 206704762 : ret[i] = attrs[i];
1384 : }
1385 8010365 : ret[i] = attrs[i];
1386 8010365 : return ret;
1387 : }
1388 :
1389 :
1390 : /*
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.
1393 : */
1394 8314060 : const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
1395 : {
1396 : const char **ret;
1397 : unsigned int i;
1398 8314060 : bool found = false;
1399 :
1400 191473450 : for (i=0;attrs && attrs[i];i++) {
1401 183159390 : if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
1402 5770423 : found = true;
1403 : }
1404 : }
1405 8314060 : if (found) {
1406 5141689 : return ldb_attr_list_copy(mem_ctx, attrs);
1407 : }
1408 3172371 : ret = talloc_array(mem_ctx, const char *, i+2);
1409 3172371 : if (ret == NULL) {
1410 0 : return NULL;
1411 : }
1412 26330142 : for (i=0;attrs && attrs[i];i++) {
1413 23157771 : ret[i] = attrs[i];
1414 : }
1415 3172371 : ret[i] = new_attr;
1416 3172371 : ret[i+1] = NULL;
1417 3172371 : return ret;
1418 : }
1419 :
1420 :
1421 : /*
1422 : return 1 if an attribute is in a list of attributes, or 0 otherwise
1423 : */
1424 1437996920 : int ldb_attr_in_list(const char * const *attrs, const char *attr)
1425 : {
1426 : unsigned int i;
1427 4104338148 : for (i=0;attrs && attrs[i];i++) {
1428 2738548174 : if (ldb_attr_cmp(attrs[i], attr) == 0) {
1429 72206946 : return 1;
1430 : }
1431 : }
1432 1365789974 : return 0;
1433 : }
1434 :
1435 :
1436 : /*
1437 : rename the specified attribute in a search result
1438 : */
1439 3 : int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
1440 : {
1441 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1442 3 : if (el == NULL) {
1443 0 : return LDB_SUCCESS;
1444 : }
1445 3 : el->name = talloc_strdup(msg->elements, replace);
1446 3 : if (el->name == NULL) {
1447 0 : return LDB_ERR_OPERATIONS_ERROR;
1448 : }
1449 3 : return LDB_SUCCESS;
1450 : }
1451 :
1452 :
1453 : /*
1454 : copy the specified attribute in a search result to a new attribute
1455 : */
1456 3 : int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
1457 : {
1458 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1459 : int ret;
1460 :
1461 3 : if (el == NULL) {
1462 0 : return LDB_SUCCESS;
1463 : }
1464 3 : ret = ldb_msg_add(msg, el, 0);
1465 3 : if (ret != LDB_SUCCESS) {
1466 0 : return ret;
1467 : }
1468 3 : return ldb_msg_rename_attr(msg, attr, replace);
1469 : }
1470 :
1471 : /*
1472 : remove the specified element in a search result
1473 : */
1474 44166363 : void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1475 : {
1476 44166363 : ptrdiff_t n = (el - msg->elements);
1477 44166363 : if (n >= msg->num_elements || n < 0) {
1478 : /* the element is not in the list. the caller is crazy. */
1479 0 : return;
1480 : }
1481 44166363 : msg->num_elements--;
1482 44166363 : if (n != msg->num_elements) {
1483 21365756 : memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
1484 : }
1485 : }
1486 :
1487 :
1488 : /*
1489 : remove the specified attribute in a search result
1490 : */
1491 1770211138 : void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1492 : {
1493 : struct ldb_message_element *el;
1494 :
1495 3196055405 : while ((el = ldb_msg_find_element(msg, attr)) != NULL) {
1496 37784538 : ldb_msg_remove_element(msg, el);
1497 : }
1498 1770211138 : }
1499 :
1500 : /* Reallocate elements to drop any excess capacity. */
1501 117671531 : void ldb_msg_shrink_to_fit(struct ldb_message *msg)
1502 : {
1503 117671531 : if (msg->num_elements > 0) {
1504 104617933 : struct ldb_message_element *elements = talloc_realloc(msg,
1505 : msg->elements,
1506 : struct ldb_message_element,
1507 : msg->num_elements);
1508 104617933 : if (elements != NULL) {
1509 104617933 : msg->elements = elements;
1510 : }
1511 : } else {
1512 13053598 : TALLOC_FREE(msg->elements);
1513 : }
1514 117671531 : }
1515 :
1516 : /*
1517 : return a LDAP formatted GeneralizedTime string
1518 : */
1519 4447878 : char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1520 : {
1521 4447878 : struct tm *tm = gmtime(&t);
1522 : char *ts;
1523 : int r;
1524 :
1525 4447878 : if (!tm) {
1526 2 : return NULL;
1527 : }
1528 :
1529 : /* we now excatly how long this string will be */
1530 4447876 : ts = talloc_array(mem_ctx, char, 18);
1531 :
1532 : /* formatted like: 20040408072012.0Z */
1533 12424644 : r = snprintf(ts, 18,
1534 : "%04u%02u%02u%02u%02u%02u.0Z",
1535 8436260 : tm->tm_year+1900, tm->tm_mon+1,
1536 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1537 : tm->tm_sec);
1538 :
1539 4447876 : if (r != 17) {
1540 4 : talloc_free(ts);
1541 4 : errno = EOVERFLOW;
1542 4 : return NULL;
1543 : }
1544 :
1545 4447872 : return ts;
1546 : }
1547 :
1548 : /*
1549 : convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1550 : */
1551 19972 : time_t ldb_string_to_time(const char *s)
1552 : {
1553 : struct tm tm;
1554 :
1555 19972 : if (s == NULL) return 0;
1556 :
1557 19946 : memset(&tm, 0, sizeof(tm));
1558 19946 : if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1559 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1560 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1561 0 : return 0;
1562 : }
1563 19946 : tm.tm_year -= 1900;
1564 19946 : tm.tm_mon -= 1;
1565 :
1566 19946 : return timegm(&tm);
1567 : }
1568 :
1569 : /*
1570 : convert a LDAP GeneralizedTime string in ldb_val format to a
1571 : time_t.
1572 : */
1573 4029438 : int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1574 : {
1575 4029438 : char val[15] = {0};
1576 4029438 : struct tm tm = {
1577 : .tm_year = 0,
1578 : };
1579 :
1580 4029438 : if (v == NULL) {
1581 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1582 : }
1583 :
1584 4029438 : if (v->data == NULL) {
1585 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1586 : }
1587 :
1588 4029438 : if (v->length < 16 && v->length != 13) {
1589 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1590 : }
1591 :
1592 4029438 : if (v->data[v->length - 1] != 'Z') {
1593 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1594 : }
1595 :
1596 4029438 : if (v->length == 13) {
1597 426 : memcpy(val, v->data, 12);
1598 :
1599 426 : if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
1600 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1601 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1602 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1603 : }
1604 426 : if (tm.tm_year < 50) {
1605 426 : tm.tm_year += 100;
1606 : }
1607 : } else {
1608 :
1609 : /*
1610 : * anything between '.' and 'Z' is silently ignored.
1611 : */
1612 4029012 : if (v->data[14] != '.') {
1613 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1614 : }
1615 :
1616 4029012 : memcpy(val, v->data, 14);
1617 :
1618 4029012 : if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
1619 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1620 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1621 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1622 : }
1623 4029012 : tm.tm_year -= 1900;
1624 : }
1625 4029438 : tm.tm_mon -= 1;
1626 :
1627 4029438 : *t = timegm(&tm);
1628 :
1629 4029438 : return LDB_SUCCESS;
1630 : }
1631 :
1632 : /*
1633 : return a LDAP formatted UTCTime string
1634 : */
1635 49 : char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1636 : {
1637 49 : struct tm *tm = gmtime(&t);
1638 : char *ts;
1639 : int r;
1640 :
1641 49 : if (!tm) {
1642 0 : return NULL;
1643 : }
1644 :
1645 : /* we now excatly how long this string will be */
1646 49 : ts = talloc_array(mem_ctx, char, 14);
1647 :
1648 : /* formatted like: 20040408072012.0Z => 040408072012Z */
1649 123 : r = snprintf(ts, 14,
1650 : "%02u%02u%02u%02u%02u%02uZ",
1651 86 : (tm->tm_year+1900)%100, tm->tm_mon+1,
1652 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1653 : tm->tm_sec);
1654 :
1655 49 : if (r != 13) {
1656 0 : talloc_free(ts);
1657 0 : return NULL;
1658 : }
1659 :
1660 49 : return ts;
1661 : }
1662 :
1663 : /*
1664 : convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1665 : */
1666 0 : time_t ldb_string_utc_to_time(const char *s)
1667 : {
1668 : struct tm tm;
1669 :
1670 0 : if (s == NULL) return 0;
1671 :
1672 0 : memset(&tm, 0, sizeof(tm));
1673 0 : if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1674 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1675 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1676 0 : return 0;
1677 : }
1678 0 : if (tm.tm_year < 50) {
1679 0 : tm.tm_year += 100;
1680 : }
1681 0 : tm.tm_mon -= 1;
1682 :
1683 0 : return timegm(&tm);
1684 : }
1685 :
1686 :
1687 : /*
1688 : dump a set of results to a file. Useful from within gdb
1689 : */
1690 0 : void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1691 : {
1692 : unsigned int i;
1693 :
1694 0 : for (i = 0; i < result->count; i++) {
1695 : struct ldb_ldif ldif;
1696 0 : fprintf(f, "# record %d\n", i+1);
1697 0 : ldif.changetype = LDB_CHANGETYPE_NONE;
1698 0 : ldif.msg = result->msgs[i];
1699 0 : ldb_ldif_write_file(ldb, f, &ldif);
1700 : }
1701 0 : }
1702 :
1703 : /*
1704 : checks for a string attribute. Returns "1" on match and otherwise "0".
1705 : */
1706 2491368 : int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1707 : const char *name, const char *value)
1708 : {
1709 : struct ldb_message_element *el;
1710 : struct ldb_val val;
1711 :
1712 2491368 : el = ldb_msg_find_element(msg, name);
1713 2491368 : if (el == NULL) {
1714 1288752 : return 0;
1715 : }
1716 :
1717 1202616 : val.data = discard_const_p(uint8_t, value);
1718 1202616 : val.length = strlen(value);
1719 :
1720 1202616 : if (ldb_msg_find_val(el, &val)) {
1721 1201887 : return 1;
1722 : }
1723 :
1724 729 : return 0;
1725 : }
1726 :
1727 :
1728 : /*
1729 : compare a ldb_val to a string
1730 : */
1731 2783922 : int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1732 : {
1733 2783922 : size_t len = strlen(str);
1734 2783922 : if (len != v->length) {
1735 0 : return len - v->length;
1736 : }
1737 2783922 : return strncmp((const char *)v->data, str, len);
1738 : }
|