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 784240562 : struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
40 : {
41 784240562 : return talloc_zero(mem_ctx, struct ldb_message);
42 : }
43 :
44 : /*
45 : find an element in a message by attribute name
46 : */
47 6937359243 : struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48 : const char *attr_name)
49 : {
50 187220361 : unsigned int i;
51 >10451*10^7 : for (i=0;i<msg->num_elements;i++) {
52 >10033*10^7 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53 2757607218 : return &msg->elements[i];
54 : }
55 : }
56 4068376781 : 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 mismatch
62 : */
63 376136826 : int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
64 : {
65 376136826 : if (v1->length != v2->length) return 0;
66 59921890 : if (v1->data == v2->data) return 1;
67 59819372 : if (v1->length == 0) return 1;
68 :
69 59819372 : if (memcmp(v1->data, v2->data, v1->length) == 0) {
70 36338304 : return 1;
71 : }
72 :
73 22377249 : return 0;
74 : }
75 :
76 : /*
77 : find a value in an element
78 : assumes case sensitive comparison
79 : */
80 29007423 : struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
81 : struct ldb_val *val)
82 : {
83 957547 : unsigned int i;
84 354701548 : for (i=0;i<el->num_values;i++) {
85 354057299 : if (ldb_val_equal_exact(val, &el->values[i])) {
86 28363174 : return &el->values[i];
87 : }
88 : }
89 623025 : return NULL;
90 : }
91 :
92 :
93 8704544 : static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
94 : {
95 8704544 : if (v1->length != v2->length) {
96 7298104 : return NUMERIC_CMP(v1->length, v2->length);
97 : }
98 1406440 : 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 30917975 : 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 2197858 : unsigned int i, j;
118 2197858 : struct ldb_val *val;
119 :
120 30917975 : if (options != 0) {
121 0 : return LDB_ERR_OPERATIONS_ERROR;
122 : }
123 :
124 30917975 : *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 30917975 : if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
131 64309438 : for (j = 0; j < el->num_values; j++) {
132 33448197 : val = &el->values[j];
133 38353136 : for ( i = j + 1; i < el->num_values; i++) {
134 4904945 : if (ldb_val_equal_exact(val, &el->values[i])) {
135 6 : *duplicate = val;
136 6 : return LDB_SUCCESS;
137 : }
138 : }
139 : }
140 : } else {
141 5679 : struct ldb_val *values;
142 56728 : values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
143 56728 : if (values == NULL) {
144 0 : return LDB_ERR_OPERATIONS_ERROR;
145 : }
146 :
147 56728 : memcpy(values, el->values,
148 56728 : el->num_values * sizeof(struct ldb_val));
149 56728 : TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
150 2033473 : for (i = 1; i < el->num_values; i++) {
151 1976746 : if (ldb_val_equal_exact(&values[i],
152 1976746 : &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 56727 : talloc_free(values);
171 : }
172 28720116 : 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 5248 : 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 556 : struct ldb_val *values;
198 556 : struct ldb_val *values2;
199 556 : unsigned int i, j, k, n_values;
200 :
201 5248 : bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
202 :
203 5248 : if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
204 0 : return LDB_ERR_OPERATIONS_ERROR;
205 : }
206 :
207 5248 : if (strcmp(el->name, el2->name) != 0) {
208 0 : return LDB_ERR_INAPPROPRIATE_MATCHING;
209 : }
210 5247 : if (el->num_values == 0 || el2->num_values == 0) {
211 0 : 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 5235 : if (MIN(el->num_values, el2->num_values) == 1 ||
218 224 : MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
219 22807 : for (i = 0; i < el2->num_values; i++) {
220 36200 : for (j = 0; j < el->num_values; j++) {
221 18510 : if (ldb_val_equal_exact(&el->values[j],
222 18510 : &el2->values[i])) {
223 21 : if (! remove_duplicates) {
224 : return \
225 17 : 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 4572 : return LDB_SUCCESS;
242 : }
243 :
244 118 : values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
245 118 : if (values == NULL) {
246 0 : return LDB_ERR_OPERATIONS_ERROR;
247 : }
248 118 : values2 = talloc_array(mem_ctx, struct ldb_val,
249 : el2->num_values);
250 118 : if (values2 == NULL) {
251 0 : return LDB_ERR_OPERATIONS_ERROR;
252 : }
253 :
254 118 : memcpy(values, el->values,
255 118 : el->num_values * sizeof(struct ldb_val));
256 118 : memcpy(values2, el2->values,
257 118 : el2->num_values * sizeof(struct ldb_val));
258 118 : TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
259 118 : 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 118 : n_values = el->num_values;
266 118 : i = 0;
267 118 : j = 0;
268 3637 : while (i != n_values && j < el2->num_values) {
269 3523 : int ret = ldb_val_cmp(&values[i], &values2[j]);
270 3523 : if (ret < 0) {
271 845 : i++;
272 2678 : } else if (ret > 0) {
273 2660 : 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 0 : &values[i])) {
289 0 : 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 114 : TALLOC_FREE(values);
300 114 : TALLOC_FREE(values2);
301 :
302 114 : return LDB_SUCCESS;
303 : }
304 :
305 : /*
306 : duplicate a ldb_val structure
307 : */
308 3170939429 : struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
309 : {
310 105731215 : struct ldb_val v2;
311 3170939429 : v2.length = v->length;
312 3170939429 : if (v->data == NULL) {
313 158410 : v2.data = NULL;
314 158410 : return v2;
315 : }
316 :
317 : /* the +1 is to cope with buggy C library routines like strndup
318 : that look one byte beyond */
319 3170781019 : v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
320 3170781019 : if (!v2.data) {
321 0 : v2.length = 0;
322 0 : return v2;
323 : }
324 :
325 3170781019 : memcpy(v2.data, v->data, v->length);
326 3170781019 : ((char *)v2.data)[v->length] = 0;
327 3170781019 : return v2;
328 : }
329 :
330 : /**
331 : * Adds new empty element to msg->elements
332 : */
333 242080716 : static int _ldb_msg_add_el(struct ldb_message *msg,
334 : struct ldb_message_element **return_el)
335 : {
336 8129745 : 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 242080716 : els = talloc_realloc(msg, msg->elements,
344 : struct ldb_message_element, msg->num_elements + 1);
345 242080716 : if (!els) {
346 0 : return LDB_ERR_OPERATIONS_ERROR;
347 : }
348 :
349 242080716 : els[msg->num_elements] = (struct ldb_message_element) {};
350 :
351 242080716 : msg->elements = els;
352 242080716 : msg->num_elements++;
353 :
354 242080716 : *return_el = &els[msg->num_elements-1];
355 :
356 242080716 : return LDB_SUCCESS;
357 : }
358 :
359 : /**
360 : * Add an empty element with a given name to a message
361 : */
362 240003140 : 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 8075227 : int ret;
368 8075227 : struct ldb_message_element *el;
369 :
370 240003140 : ret = _ldb_msg_add_el(msg, &el);
371 240003140 : if (ret != LDB_SUCCESS) {
372 0 : return ret;
373 : }
374 :
375 : /* initialize newly added element */
376 240003140 : el->flags = flags;
377 240003140 : el->name = talloc_strdup(msg->elements, attr_name);
378 240003140 : if (!el->name) {
379 0 : return LDB_ERR_OPERATIONS_ERROR;
380 : }
381 :
382 240003140 : if (return_el) {
383 238822856 : *return_el = el;
384 : }
385 :
386 231927913 : 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 2077576 : int ldb_msg_add(struct ldb_message *msg,
398 : const struct ldb_message_element *el,
399 : int flags)
400 : {
401 54518 : int ret;
402 54518 : 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 2077576 : struct ldb_message_element el_copy = *el;
406 :
407 2077576 : ret = _ldb_msg_add_el(msg, &el_new);
408 2077576 : if (ret != LDB_SUCCESS) {
409 0 : return ret;
410 : }
411 :
412 2077576 : el_new->flags = flags;
413 2077576 : el_new->name = el_copy.name;
414 2077576 : el_new->num_values = el_copy.num_values;
415 2077576 : el_new->values = el_copy.values;
416 :
417 2077576 : return LDB_SUCCESS;
418 : }
419 :
420 : /*
421 : * add a value to a message element
422 : */
423 232831165 : int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
424 : struct ldb_message_element *el,
425 : const struct ldb_val *val)
426 : {
427 7509867 : struct ldb_val *vals;
428 :
429 232831165 : 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 38 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
437 :
438 38 : vals = talloc_array(mem_ctx, struct ldb_val,
439 : el->num_values + 1);
440 38 : if (vals == NULL) {
441 0 : return LDB_ERR_OPERATIONS_ERROR;
442 : }
443 :
444 38 : if (el->values != NULL) {
445 38 : memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
446 : }
447 : } else {
448 232831127 : vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
449 : el->num_values + 1);
450 232831127 : if (vals == NULL) {
451 0 : return LDB_ERR_OPERATIONS_ERROR;
452 : }
453 : }
454 232831165 : el->values = vals;
455 232831165 : el->values[el->num_values] = *val;
456 232831165 : el->num_values++;
457 :
458 232831165 : return LDB_SUCCESS;
459 : }
460 :
461 : /*
462 : add a value to a message
463 : */
464 232482842 : 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 7504632 : struct ldb_message_element *el;
470 7504632 : int ret;
471 :
472 232482842 : el = ldb_msg_find_element(msg, attr_name);
473 232482842 : if (!el) {
474 226584585 : ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
475 226584585 : if (ret != LDB_SUCCESS) {
476 0 : return ret;
477 : }
478 : }
479 :
480 232482842 : ret = ldb_msg_element_add_value(msg->elements, el, val);
481 232482842 : if (ret != LDB_SUCCESS) {
482 0 : return ret;
483 : }
484 :
485 232482842 : if (return_el) {
486 229975019 : *return_el = el;
487 : }
488 :
489 224978210 : return LDB_SUCCESS;
490 : }
491 :
492 :
493 : /*
494 : add a value to a message, stealing it into the 'right' place
495 : */
496 193642551 : int ldb_msg_add_steal_value(struct ldb_message *msg,
497 : const char *attr_name,
498 : struct ldb_val *val)
499 : {
500 5638707 : int ret;
501 5638707 : struct ldb_message_element *el;
502 :
503 193642551 : ret = ldb_msg_add_value(msg, attr_name, val, &el);
504 193642551 : if (ret == LDB_SUCCESS) {
505 193642551 : talloc_steal(el->values, val->data);
506 : }
507 193642551 : return ret;
508 : }
509 :
510 :
511 : /*
512 : add a string element to a message, specifying flags
513 : */
514 35765455 : int ldb_msg_add_string_flags(struct ldb_message *msg,
515 : const char *attr_name, const char *str,
516 : int flags)
517 : {
518 1644136 : struct ldb_val val;
519 1644136 : int ret;
520 35765455 : struct ldb_message_element *el = NULL;
521 :
522 35765455 : val.data = discard_const_p(uint8_t, str);
523 35765455 : val.length = strlen(str);
524 :
525 35765455 : if (val.length == 0) {
526 : /* allow empty strings as non-existent attributes */
527 287 : return LDB_SUCCESS;
528 : }
529 :
530 35765146 : ret = ldb_msg_add_value(msg, attr_name, &val, &el);
531 35765146 : if (ret != LDB_SUCCESS) {
532 0 : return ret;
533 : }
534 :
535 35765146 : if (flags != 0) {
536 89979 : el->flags = flags;
537 : }
538 :
539 34121032 : return LDB_SUCCESS;
540 : }
541 :
542 : /*
543 : add a string element to a message
544 : */
545 35675476 : int ldb_msg_add_string(struct ldb_message *msg,
546 : const char *attr_name, const char *str)
547 : {
548 35675476 : 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 175818270 : int ldb_msg_add_steal_string(struct ldb_message *msg,
555 : const char *attr_name, char *str)
556 : {
557 4675263 : struct ldb_val val;
558 :
559 175818270 : val.data = (uint8_t *)str;
560 175818270 : val.length = strlen(str);
561 :
562 175818270 : if (val.length == 0) {
563 : /* allow empty strings as non-existent attributes */
564 0 : return LDB_SUCCESS;
565 : }
566 :
567 175818270 : return ldb_msg_add_steal_value(msg, attr_name, &val);
568 : }
569 :
570 : /*
571 : add a DN element to a message
572 : */
573 2004 : int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
574 : struct ldb_dn *dn)
575 : {
576 2004 : char *str = ldb_dn_alloc_linearized(msg, dn);
577 :
578 2004 : if (str == NULL) {
579 : /* we don't want to have unknown DNs added */
580 0 : return LDB_ERR_OPERATIONS_ERROR;
581 : }
582 :
583 2004 : return ldb_msg_add_steal_string(msg, attr_name, str);
584 : }
585 :
586 : /*
587 : add a printf formatted element to a message
588 : */
589 10501263 : int ldb_msg_add_fmt(struct ldb_message *msg,
590 : const char *attr_name, const char *fmt, ...)
591 : {
592 725363 : struct ldb_val val;
593 725363 : va_list ap;
594 725363 : char *str;
595 :
596 10501263 : va_start(ap, fmt);
597 10501263 : str = talloc_vasprintf(msg, fmt, ap);
598 10501263 : va_end(ap);
599 :
600 10501263 : if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
601 :
602 10501263 : val.data = (uint8_t *)str;
603 10501263 : val.length = strlen(str);
604 :
605 10501263 : return ldb_msg_add_steal_value(msg, attr_name, &val);
606 : }
607 :
608 347671 : static int ldb_msg_append_value_impl(struct ldb_message *msg,
609 : const char *attr_name,
610 : const struct ldb_val *val,
611 : int flags,
612 : struct ldb_message_element **return_el)
613 : {
614 347671 : struct ldb_message_element *el = NULL;
615 5229 : int ret;
616 :
617 347671 : ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
618 347671 : if (ret != LDB_SUCCESS) {
619 0 : return ret;
620 : }
621 :
622 347671 : ret = ldb_msg_element_add_value(msg->elements, el, val);
623 347671 : if (ret != LDB_SUCCESS) {
624 0 : return ret;
625 : }
626 :
627 347671 : if (return_el != NULL) {
628 2458 : *return_el = el;
629 : }
630 :
631 342442 : return LDB_SUCCESS;
632 : }
633 :
634 : /*
635 : append a value to a message
636 : */
637 345213 : int ldb_msg_append_value(struct ldb_message *msg,
638 : const char *attr_name,
639 : const struct ldb_val *val,
640 : int flags)
641 : {
642 345213 : return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
643 : }
644 :
645 : /*
646 : append a value to a message, stealing it into the 'right' place
647 : */
648 2458 : int ldb_msg_append_steal_value(struct ldb_message *msg,
649 : const char *attr_name,
650 : struct ldb_val *val,
651 : int flags)
652 : {
653 158 : int ret;
654 2458 : struct ldb_message_element *el = NULL;
655 :
656 2458 : ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
657 2458 : if (ret == LDB_SUCCESS) {
658 2458 : talloc_steal(el->values, val->data);
659 : }
660 2458 : return ret;
661 : }
662 :
663 : /*
664 : append a string element to a message, stealing it into the 'right' place
665 : */
666 1078 : int ldb_msg_append_steal_string(struct ldb_message *msg,
667 : const char *attr_name, char *str,
668 : int flags)
669 : {
670 132 : struct ldb_val val;
671 :
672 1078 : val.data = (uint8_t *)str;
673 1078 : val.length = strlen(str);
674 :
675 1078 : if (val.length == 0) {
676 : /* allow empty strings as non-existent attributes */
677 0 : return LDB_SUCCESS;
678 : }
679 :
680 1078 : return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
681 : }
682 :
683 : /*
684 : append a string element to a message
685 : */
686 73686 : int ldb_msg_append_string(struct ldb_message *msg,
687 : const char *attr_name, const char *str, int flags)
688 : {
689 588 : struct ldb_val val;
690 :
691 73686 : val.data = discard_const_p(uint8_t, str);
692 73686 : val.length = strlen(str);
693 :
694 73686 : if (val.length == 0) {
695 : /* allow empty strings as non-existent attributes */
696 0 : return LDB_SUCCESS;
697 : }
698 :
699 73686 : return ldb_msg_append_value(msg, attr_name, &val, flags);
700 : }
701 :
702 : /*
703 : append a DN element to a message
704 : */
705 99 : int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
706 : struct ldb_dn *dn, int flags)
707 : {
708 99 : char *str = ldb_dn_alloc_linearized(msg, dn);
709 :
710 99 : if (str == NULL) {
711 : /* we don't want to have unknown DNs added */
712 0 : return LDB_ERR_OPERATIONS_ERROR;
713 : }
714 :
715 99 : return ldb_msg_append_steal_string(msg, attr_name, str, flags);
716 : }
717 :
718 : /*
719 : append a printf formatted element to a message
720 : */
721 1125 : int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
722 : const char *attr_name, const char *fmt, ...)
723 : {
724 26 : struct ldb_val val;
725 26 : va_list ap;
726 1125 : char *str = NULL;
727 :
728 1125 : va_start(ap, fmt);
729 1125 : str = talloc_vasprintf(msg, fmt, ap);
730 1125 : va_end(ap);
731 :
732 1125 : if (str == NULL) {
733 0 : return LDB_ERR_OPERATIONS_ERROR;
734 : }
735 :
736 1125 : val.data = (uint8_t *)str;
737 1125 : val.length = strlen(str);
738 :
739 1125 : return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
740 : }
741 :
742 : /*
743 : compare two ldb_message_element structures
744 : assumes case sensitive comparison
745 : */
746 21941418 : int ldb_msg_element_compare(struct ldb_message_element *el1,
747 : struct ldb_message_element *el2)
748 : {
749 740152 : unsigned int i;
750 :
751 21941418 : if (el1->num_values != el2->num_values) {
752 243 : return NUMERIC_CMP(el1->num_values, el2->num_values);
753 : }
754 : /*
755 : * Note this is an inconsistent comparison, unsuitable for
756 : * sorting. If A has values {a, b} and B has values {b, c},
757 : * then
758 : *
759 : * ldb_msg_element_compare(A, B) returns -1, meaning A < B
760 : * ldb_msg_element_compare(B, A) returns -1, meaning B < A
761 : */
762 48603373 : for (i=0;i<el1->num_values;i++) {
763 26718655 : if (!ldb_msg_find_val(el2, &el1->values[i])) {
764 54517 : return -1;
765 : }
766 : }
767 :
768 21146507 : return 0;
769 : }
770 :
771 : /*
772 : compare two ldb_message_element structures.
773 : Different ordering is considered a mismatch
774 : */
775 12010716 : bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
776 : const struct ldb_message_element *el2)
777 : {
778 416766 : unsigned i;
779 12010716 : if (el1->num_values != el2->num_values) {
780 1084000 : return false;
781 : }
782 16455375 : for (i=0;i<el1->num_values;i++) {
783 11425491 : if (ldb_val_equal_exact(&el1->values[i],
784 11425491 : &el2->values[i]) != 1) {
785 5688399 : return false;
786 : }
787 : }
788 4821551 : return true;
789 : }
790 :
791 : /*
792 : compare two ldb_message_element structures
793 : comparing by element name
794 : */
795 256073547 : int ldb_msg_element_compare_name(struct ldb_message_element *el1,
796 : struct ldb_message_element *el2)
797 : {
798 256073547 : if (el1->name == el2->name) {
799 0 : return 0;
800 : }
801 :
802 256073547 : if (el1->name == NULL) {
803 0 : return -1;
804 : }
805 :
806 256073547 : if (el2->name == NULL) {
807 0 : return 1;
808 : }
809 :
810 256073547 : return ldb_attr_cmp(el1->name, el2->name);
811 : }
812 :
813 5079150 : void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
814 : {
815 5079150 : el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
816 5079150 : }
817 :
818 213063164 : bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
819 : {
820 213063164 : return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
821 : }
822 :
823 1487322 : void ldb_msg_remove_inaccessible(struct ldb_message *msg)
824 : {
825 268 : unsigned i;
826 1487322 : unsigned num_del = 0;
827 :
828 10689201 : for (i = 0; i < msg->num_elements; ++i) {
829 9201879 : if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
830 5074405 : ++num_del;
831 4127474 : } else if (num_del) {
832 2982354 : msg->elements[i - num_del] = msg->elements[i];
833 : }
834 : }
835 :
836 1487322 : msg->num_elements -= num_del;
837 1487322 : }
838 :
839 : /*
840 : convenience functions to return common types from a message
841 : these return the first value if the attribute is multi-valued
842 : */
843 3344339166 : const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
844 : const char *attr_name)
845 : {
846 3344339166 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
847 3344339166 : if (!el || el->num_values == 0) {
848 1442872438 : return NULL;
849 : }
850 1863644805 : return &el->values[0];
851 : }
852 :
853 148295828 : int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
854 : const char *attr_name,
855 : int default_value)
856 : {
857 148295828 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
858 148295828 : char buf[sizeof("-2147483648")] = {};
859 148295828 : char *end = NULL;
860 3224615 : int ret;
861 :
862 148295828 : if (!v || !v->data) {
863 1888099 : return default_value;
864 : }
865 :
866 146258385 : if (v->length >= sizeof(buf)) {
867 66 : return default_value;
868 : }
869 :
870 146258319 : memcpy(buf, v->data, v->length);
871 146258319 : errno = 0;
872 146258319 : ret = (int) strtoll(buf, &end, 10);
873 146258319 : if (errno != 0) {
874 0 : return default_value;
875 : }
876 146258319 : if (end && end[0] != '\0') {
877 0 : return default_value;
878 : }
879 143183048 : return ret;
880 : }
881 :
882 597671642 : unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
883 : const char *attr_name,
884 : unsigned int default_value)
885 : {
886 597671642 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
887 597671642 : char buf[sizeof("-2147483648")] = {};
888 597671642 : char *end = NULL;
889 15006874 : unsigned int ret;
890 :
891 597671642 : if (!v || !v->data) {
892 290033129 : return default_value;
893 : }
894 :
895 300078154 : if (v->length >= sizeof(buf)) {
896 39 : return default_value;
897 : }
898 :
899 300078115 : memcpy(buf, v->data, v->length);
900 300078115 : errno = 0;
901 300078115 : ret = (unsigned int) strtoll(buf, &end, 10);
902 300078115 : if (errno != 0) {
903 0 : errno = 0;
904 0 : ret = (unsigned int) strtoull(buf, &end, 10);
905 0 : if (errno != 0) {
906 0 : return default_value;
907 : }
908 : }
909 300078115 : if (end && end[0] != '\0') {
910 0 : return default_value;
911 : }
912 292631600 : return ret;
913 : }
914 :
915 2502131 : int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
916 : const char *attr_name,
917 : int64_t default_value)
918 : {
919 2502131 : int64_t val = 0;
920 2502131 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
921 2502131 : int ret = ldb_val_as_int64(v, &val);
922 2502131 : return ret ? default_value : val;
923 : }
924 :
925 2502454 : int ldb_val_as_int64(const struct ldb_val *v, int64_t *val)
926 : {
927 2502454 : char buf[sizeof("-9223372036854775808")] = {};
928 2502454 : char *end = NULL;
929 72788 : int64_t result;
930 :
931 2502454 : if (!v || !v->data) {
932 536879 : return LDB_ERR_OPERATIONS_ERROR;
933 : }
934 :
935 1949712 : if (v->length >= sizeof(buf)) {
936 0 : return LDB_ERR_OPERATIONS_ERROR;
937 : }
938 :
939 1949712 : memcpy(buf, v->data, v->length);
940 1949712 : errno = 0;
941 1949712 : result = (int64_t) strtoll(buf, &end, 10);
942 1949712 : if (errno != 0) {
943 0 : return LDB_ERR_OPERATIONS_ERROR;
944 : }
945 1949712 : if (end && end[0] != '\0') {
946 0 : return LDB_ERR_OPERATIONS_ERROR;
947 : }
948 :
949 1949712 : *val = result;
950 1949712 : return LDB_SUCCESS;
951 : }
952 :
953 249447959 : uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
954 : const char *attr_name,
955 : uint64_t default_value)
956 : {
957 249447959 : uint64_t val = 0;
958 249447959 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
959 249447959 : int ret = ldb_val_as_uint64(v, &val);
960 249447959 : return ret ? default_value : val;
961 : }
962 :
963 249447959 : int ldb_val_as_uint64(const struct ldb_val *v, uint64_t *val)
964 : {
965 249447959 : char buf[sizeof("-9223372036854775808")] = {};
966 249447959 : char *end = NULL;
967 6903481 : uint64_t result;
968 :
969 249447959 : if (!v || !v->data) {
970 113162322 : return LDB_ERR_OPERATIONS_ERROR;
971 : }
972 :
973 133400555 : if (v->length >= sizeof(buf)) {
974 0 : return LDB_ERR_OPERATIONS_ERROR;
975 : }
976 :
977 133400555 : memcpy(buf, v->data, v->length);
978 133400555 : errno = 0;
979 133400555 : result = (uint64_t) strtoll(buf, &end, 10);
980 133400555 : if (errno != 0) {
981 0 : errno = 0;
982 0 : result = (uint64_t) strtoull(buf, &end, 10);
983 0 : if (errno != 0) {
984 0 : return LDB_ERR_OPERATIONS_ERROR;
985 : }
986 : }
987 133400555 : if (end && end[0] != '\0') {
988 0 : return LDB_ERR_OPERATIONS_ERROR;
989 : }
990 :
991 133400555 : *val = result;
992 133400555 : return LDB_SUCCESS;
993 : }
994 :
995 0 : double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
996 : const char *attr_name,
997 : double default_value)
998 : {
999 0 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1000 0 : char *buf;
1001 0 : char *end = NULL;
1002 0 : double ret;
1003 :
1004 0 : if (!v || !v->data) {
1005 0 : return default_value;
1006 : }
1007 0 : buf = talloc_strndup(msg, (const char *)v->data, v->length);
1008 0 : if (buf == NULL) {
1009 0 : return default_value;
1010 : }
1011 :
1012 0 : errno = 0;
1013 0 : ret = strtod(buf, &end);
1014 0 : talloc_free(buf);
1015 0 : if (errno != 0) {
1016 0 : return default_value;
1017 : }
1018 0 : if (end && end[0] != '\0') {
1019 0 : return default_value;
1020 : }
1021 0 : return ret;
1022 : }
1023 :
1024 8407316 : int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
1025 : const char *attr_name,
1026 : int default_value)
1027 : {
1028 8407316 : bool val = false;
1029 8407316 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1030 8407316 : int ret = ldb_val_as_bool(v, &val);
1031 8407316 : return ret ? default_value : val;
1032 : }
1033 :
1034 8407345 : int ldb_val_as_bool(const struct ldb_val *v, bool *val)
1035 : {
1036 8407345 : if (!v || !v->data) {
1037 2897902 : return LDB_ERR_OPERATIONS_ERROR;
1038 : }
1039 5509190 : if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
1040 121600 : *val = false;
1041 121600 : return LDB_SUCCESS;
1042 : }
1043 5387590 : if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
1044 5387590 : *val = true;
1045 5387590 : return LDB_SUCCESS;
1046 : }
1047 0 : return LDB_ERR_OPERATIONS_ERROR;
1048 : }
1049 :
1050 778856047 : const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
1051 : const char *attr_name,
1052 : const char *default_value)
1053 : {
1054 778856047 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1055 778856047 : if (!v || !v->data) {
1056 483950922 : return default_value;
1057 : }
1058 282709802 : if (v->data[v->length] != '\0') {
1059 0 : return default_value;
1060 : }
1061 275648475 : return (const char *)v->data;
1062 : }
1063 :
1064 5736334 : struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
1065 : TALLOC_CTX *mem_ctx,
1066 : const struct ldb_message *msg,
1067 : const char *attr_name)
1068 : {
1069 5736334 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1070 5736334 : return ldb_val_as_dn(ldb, mem_ctx, v);
1071 : }
1072 :
1073 5741417 : struct ldb_dn *ldb_val_as_dn(struct ldb_context *ldb,
1074 : TALLOC_CTX *mem_ctx,
1075 : const struct ldb_val *v)
1076 : {
1077 164299 : struct ldb_dn *res_dn;
1078 :
1079 5741417 : if (!v || !v->data) {
1080 1130746 : return NULL;
1081 : }
1082 4508012 : res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
1083 4508012 : if ( ! ldb_dn_validate(res_dn)) {
1084 0 : talloc_free(res_dn);
1085 0 : return NULL;
1086 : }
1087 4446372 : return res_dn;
1088 : }
1089 :
1090 : /*
1091 : sort the elements of a message by name
1092 : */
1093 1695572 : void ldb_msg_sort_elements(struct ldb_message *msg)
1094 : {
1095 1695572 : TYPESAFE_QSORT(msg->elements, msg->num_elements,
1096 : ldb_msg_element_compare_name);
1097 1695572 : }
1098 :
1099 9792579 : static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
1100 : const struct ldb_message *msg)
1101 : {
1102 869428 : struct ldb_message *msg2;
1103 869428 : unsigned int i;
1104 :
1105 9792579 : msg2 = talloc(mem_ctx, struct ldb_message);
1106 9792579 : if (msg2 == NULL) return NULL;
1107 :
1108 9792579 : *msg2 = *msg;
1109 :
1110 9792579 : msg2->elements = talloc_array(msg2, struct ldb_message_element,
1111 : msg2->num_elements);
1112 9792579 : if (msg2->elements == NULL) goto failed;
1113 :
1114 107916702 : for (i=0;i<msg2->num_elements;i++) {
1115 98124123 : msg2->elements[i] = msg->elements[i];
1116 : }
1117 :
1118 8923151 : return msg2;
1119 :
1120 0 : failed:
1121 0 : talloc_free(msg2);
1122 0 : return NULL;
1123 : }
1124 :
1125 : /*
1126 : shallow copy a message - copying only the elements array so that the caller
1127 : can safely add new elements without changing the message
1128 : */
1129 7922662 : struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
1130 : const struct ldb_message *msg)
1131 : {
1132 716983 : struct ldb_message *msg2;
1133 716983 : unsigned int i;
1134 :
1135 7922662 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1136 7922662 : if (msg2 == NULL) {
1137 0 : return NULL;
1138 : }
1139 :
1140 64944794 : for (i = 0; i < msg2->num_elements; ++i) {
1141 : /*
1142 : * Mark this message's elements as sharing their values with the
1143 : * original message, so that we don't inadvertently modify or
1144 : * free them. We don't mark the original message element as
1145 : * shared, so the original message element should not be
1146 : * modified or freed while the shallow copy lives.
1147 : */
1148 57022132 : struct ldb_message_element *el = &msg2->elements[i];
1149 57022132 : el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
1150 : }
1151 :
1152 7205679 : return msg2;
1153 : }
1154 :
1155 : /*
1156 : copy a message, allocating new memory for all parts
1157 : */
1158 1869917 : struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
1159 : const struct ldb_message *msg)
1160 : {
1161 152445 : struct ldb_message *msg2;
1162 152445 : unsigned int i, j;
1163 :
1164 1869917 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1165 1869917 : if (msg2 == NULL) return NULL;
1166 :
1167 1869917 : if (msg2->dn != NULL) {
1168 1869902 : msg2->dn = ldb_dn_copy(msg2, msg2->dn);
1169 1869902 : if (msg2->dn == NULL) goto failed;
1170 : }
1171 :
1172 42971908 : for (i=0;i<msg2->num_elements;i++) {
1173 41101991 : struct ldb_message_element *el = &msg2->elements[i];
1174 41101991 : struct ldb_val *values = el->values;
1175 41101991 : if (el->name != NULL) {
1176 41101991 : el->name = talloc_strdup(msg2->elements, el->name);
1177 41101991 : if (el->name == NULL) goto failed;
1178 : }
1179 41101991 : el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
1180 41101991 : if (el->values == NULL) goto failed;
1181 91203015 : for (j=0;j<el->num_values;j++) {
1182 50101024 : el->values[j] = ldb_val_dup(el->values, &values[j]);
1183 50101024 : if (el->values[j].data == NULL && values[j].length != 0) {
1184 0 : goto failed;
1185 : }
1186 : }
1187 :
1188 : /*
1189 : * Since we copied this element's values, we can mark them as
1190 : * not shared.
1191 : */
1192 41101991 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1193 : }
1194 :
1195 1717472 : return msg2;
1196 :
1197 0 : failed:
1198 0 : talloc_free(msg2);
1199 0 : return NULL;
1200 : }
1201 :
1202 :
1203 : /**
1204 : * Canonicalize a message, merging elements of the same name
1205 : */
1206 0 : struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
1207 : const struct ldb_message *msg)
1208 : {
1209 0 : int ret;
1210 0 : struct ldb_message *msg2;
1211 :
1212 : /*
1213 : * Preserve previous behavior and allocate
1214 : * *msg2 into *ldb context
1215 : */
1216 0 : ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
1217 0 : if (ret != LDB_SUCCESS) {
1218 0 : return NULL;
1219 : }
1220 :
1221 0 : return msg2;
1222 : }
1223 :
1224 : /**
1225 : * Canonicalize a message, merging elements of the same name
1226 : */
1227 1694946 : int ldb_msg_normalize(struct ldb_context *ldb,
1228 : TALLOC_CTX *mem_ctx,
1229 : const struct ldb_message *msg,
1230 : struct ldb_message **_msg_out)
1231 : {
1232 142046 : unsigned int i;
1233 142046 : struct ldb_message *msg2;
1234 :
1235 1694946 : msg2 = ldb_msg_copy(mem_ctx, msg);
1236 1694946 : if (msg2 == NULL) {
1237 0 : return LDB_ERR_OPERATIONS_ERROR;
1238 : }
1239 :
1240 1694946 : ldb_msg_sort_elements(msg2);
1241 :
1242 39716546 : for (i=1; i < msg2->num_elements; i++) {
1243 37879554 : struct ldb_message_element *el1 = &msg2->elements[i-1];
1244 37879554 : struct ldb_message_element *el2 = &msg2->elements[i];
1245 :
1246 37879554 : if (ldb_msg_element_compare_name(el1, el2) == 0) {
1247 15360 : el1->values = talloc_realloc(msg2->elements,
1248 : el1->values, struct ldb_val,
1249 : el1->num_values + el2->num_values);
1250 15360 : if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
1251 0 : talloc_free(msg2);
1252 0 : return LDB_ERR_OPERATIONS_ERROR;
1253 : }
1254 15360 : memcpy(el1->values + el1->num_values,
1255 15360 : el2->values,
1256 15360 : sizeof(struct ldb_val) * el2->num_values);
1257 15360 : el1->num_values += el2->num_values;
1258 15360 : talloc_free(discard_const_p(char, el2->name));
1259 15360 : if ((i + 1 > i) && ((i + 1) < msg2->num_elements)) {
1260 633 : memmove(el2, el2+1, sizeof(struct ldb_message_element) *
1261 0 : (msg2->num_elements - (i+1)));
1262 : }
1263 15360 : msg2->num_elements--;
1264 15360 : i--;
1265 : }
1266 : }
1267 :
1268 1694946 : *_msg_out = msg2;
1269 1694946 : return LDB_SUCCESS;
1270 : }
1271 :
1272 :
1273 : /**
1274 : * return a ldb_message representing the differences between msg1 and msg2.
1275 : * If you then use this in a ldb_modify() call,
1276 : * it can be used to save edits to a message
1277 : */
1278 0 : struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
1279 : struct ldb_message *msg1,
1280 : struct ldb_message *msg2)
1281 : {
1282 0 : int ldb_ret;
1283 0 : struct ldb_message *mod;
1284 :
1285 0 : ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
1286 0 : if (ldb_ret != LDB_SUCCESS) {
1287 0 : return NULL;
1288 : }
1289 :
1290 0 : return mod;
1291 : }
1292 :
1293 : /**
1294 : * return a ldb_message representing the differences between msg1 and msg2.
1295 : * If you then use this in a ldb_modify() call it can be used to save edits to a message
1296 : *
1297 : * Result message is constructed as follows:
1298 : * - LDB_FLAG_MOD_ADD - elements found only in msg2
1299 : * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1300 : * Value for msg2 element is used
1301 : * - LDB_FLAG_MOD_DELETE - elements found only in msg2
1302 : *
1303 : * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1304 : */
1305 91809 : int ldb_msg_difference(struct ldb_context *ldb,
1306 : TALLOC_CTX *mem_ctx,
1307 : struct ldb_message *msg1,
1308 : struct ldb_message *msg2,
1309 : struct ldb_message **_msg_out)
1310 : {
1311 2299 : int ldb_res;
1312 2299 : unsigned int i;
1313 2299 : struct ldb_message *mod;
1314 2299 : struct ldb_message_element *el;
1315 2299 : TALLOC_CTX *temp_ctx;
1316 :
1317 91809 : temp_ctx = talloc_new(mem_ctx);
1318 91809 : if (!temp_ctx) {
1319 0 : return LDB_ERR_OPERATIONS_ERROR;
1320 : }
1321 :
1322 91809 : mod = ldb_msg_new(temp_ctx);
1323 91809 : if (mod == NULL) {
1324 0 : goto failed;
1325 : }
1326 :
1327 91809 : mod->dn = msg1->dn;
1328 91809 : mod->num_elements = 0;
1329 91809 : mod->elements = NULL;
1330 :
1331 : /*
1332 : * Canonicalize *msg2 so we have no repeated elements
1333 : * Resulting message is allocated in *mod's mem context,
1334 : * as we are going to move some elements from *msg2 to
1335 : * *mod object later
1336 : */
1337 91809 : ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
1338 91809 : if (ldb_res != LDB_SUCCESS) {
1339 0 : goto failed;
1340 : }
1341 :
1342 : /* look in msg2 to find elements that need to be added or modified */
1343 22027021 : for (i=0;i<msg2->num_elements;i++) {
1344 21935212 : el = ldb_msg_find_element(msg1, msg2->elements[i].name);
1345 :
1346 21935212 : if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
1347 21877244 : continue;
1348 : }
1349 :
1350 57968 : ldb_res = ldb_msg_add(mod,
1351 57968 : &msg2->elements[i],
1352 : el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
1353 57968 : if (ldb_res != LDB_SUCCESS) {
1354 0 : goto failed;
1355 : }
1356 : }
1357 :
1358 : /* look in msg1 to find elements that need to be deleted */
1359 22027769 : for (i=0;i<msg1->num_elements;i++) {
1360 21935960 : el = ldb_msg_find_element(msg2, msg1->elements[i].name);
1361 21935960 : if (el == NULL) {
1362 2043 : ldb_res = ldb_msg_add_empty(mod,
1363 2029 : msg1->elements[i].name,
1364 : LDB_FLAG_MOD_DELETE, NULL);
1365 2029 : if (ldb_res != LDB_SUCCESS) {
1366 0 : goto failed;
1367 : }
1368 : }
1369 : }
1370 :
1371 : /* steal resulting message into supplied context */
1372 91809 : talloc_steal(mem_ctx, mod);
1373 91809 : *_msg_out = mod;
1374 :
1375 91809 : talloc_free(temp_ctx);
1376 91809 : return LDB_SUCCESS;
1377 :
1378 0 : failed:
1379 0 : talloc_free(temp_ctx);
1380 0 : return LDB_ERR_OPERATIONS_ERROR;
1381 : }
1382 :
1383 :
1384 1392599 : int ldb_msg_sanity_check(struct ldb_context *ldb,
1385 : const struct ldb_message *msg)
1386 : {
1387 117646 : unsigned int i, j;
1388 :
1389 : /* basic check on DN */
1390 1392599 : if (msg->dn == NULL) {
1391 0 : ldb_set_errstring(ldb, "ldb message lacks a DN!");
1392 0 : return LDB_ERR_INVALID_DN_SYNTAX;
1393 : }
1394 :
1395 : /* basic syntax checks */
1396 8365766 : for (i = 0; i < msg->num_elements; i++) {
1397 16385074 : for (j = 0; j < msg->elements[i].num_values; j++) {
1398 9411907 : if (msg->elements[i].values[j].length == 0) {
1399 : /* an attribute cannot be empty */
1400 4 : ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
1401 2 : msg->elements[i].name,
1402 2 : ldb_dn_get_linearized(msg->dn));
1403 2 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1404 : }
1405 : }
1406 : }
1407 :
1408 1274951 : return LDB_SUCCESS;
1409 : }
1410 :
1411 :
1412 :
1413 :
1414 : /*
1415 : copy an attribute list. This only copies the array, not the elements
1416 : (ie. the elements are left as the same pointers)
1417 : */
1418 10300725 : const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
1419 : {
1420 208241 : const char **ret;
1421 208241 : unsigned int i;
1422 :
1423 309935684 : for (i=0;attrs && attrs[i];i++) /* noop */ ;
1424 10300725 : ret = talloc_array(mem_ctx, const char *, i+1);
1425 10300725 : if (ret == NULL) {
1426 0 : return NULL;
1427 : }
1428 309935684 : for (i=0;attrs && attrs[i];i++) {
1429 299634959 : ret[i] = attrs[i];
1430 : }
1431 10300725 : ret[i] = attrs[i];
1432 10300725 : return ret;
1433 : }
1434 :
1435 :
1436 : /*
1437 : copy an attribute list. This only copies the array, not the elements
1438 : (ie. the elements are left as the same pointers). The new attribute is added to the list.
1439 : */
1440 11108102 : const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
1441 : {
1442 232656 : const char **ret;
1443 232656 : unsigned int i;
1444 11108102 : bool found = false;
1445 :
1446 291903924 : for (i=0;attrs && attrs[i];i++) {
1447 280795822 : if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
1448 7911003 : found = true;
1449 : }
1450 : }
1451 11108102 : if (found) {
1452 7048013 : return ldb_attr_list_copy(mem_ctx, attrs);
1453 : }
1454 4060089 : ret = talloc_array(mem_ctx, const char *, i+2);
1455 4060089 : if (ret == NULL) {
1456 0 : return NULL;
1457 : }
1458 38281018 : for (i=0;attrs && attrs[i];i++) {
1459 34220929 : ret[i] = attrs[i];
1460 : }
1461 4060089 : ret[i] = new_attr;
1462 4060089 : ret[i+1] = NULL;
1463 4060089 : return ret;
1464 : }
1465 :
1466 :
1467 : /*
1468 : return 1 if an attribute is in a list of attributes, or 0 otherwise
1469 : */
1470 2347366135 : int ldb_attr_in_list(const char * const *attrs, const char *attr)
1471 : {
1472 96015906 : unsigned int i;
1473 6426908713 : for (i=0;attrs && attrs[i];i++) {
1474 4179226644 : if (ldb_attr_cmp(attrs[i], attr) == 0) {
1475 98371889 : return 1;
1476 : }
1477 : }
1478 2152978340 : return 0;
1479 : }
1480 :
1481 :
1482 : /*
1483 : rename the specified attribute in a search result
1484 : */
1485 3 : int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
1486 : {
1487 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1488 3 : if (el == NULL) {
1489 0 : return LDB_SUCCESS;
1490 : }
1491 3 : el->name = talloc_strdup(msg->elements, replace);
1492 3 : if (el->name == NULL) {
1493 0 : return LDB_ERR_OPERATIONS_ERROR;
1494 : }
1495 3 : return LDB_SUCCESS;
1496 : }
1497 :
1498 :
1499 : /*
1500 : copy the specified attribute in a search result to a new attribute
1501 : */
1502 3 : int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
1503 : {
1504 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1505 0 : int ret;
1506 :
1507 3 : if (el == NULL) {
1508 0 : return LDB_SUCCESS;
1509 : }
1510 3 : ret = ldb_msg_add(msg, el, 0);
1511 3 : if (ret != LDB_SUCCESS) {
1512 0 : return ret;
1513 : }
1514 3 : return ldb_msg_rename_attr(msg, attr, replace);
1515 : }
1516 :
1517 : /*
1518 : remove the specified element in a search result
1519 : */
1520 8971789 : void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1521 : {
1522 8971789 : ptrdiff_t n = (el - msg->elements);
1523 8971789 : if (n >= msg->num_elements || n < 0) {
1524 : /* the element is not in the list. the caller is crazy. */
1525 0 : return;
1526 : }
1527 8971789 : msg->num_elements--;
1528 8971789 : if (n != msg->num_elements) {
1529 5051735 : memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
1530 : }
1531 : }
1532 :
1533 :
1534 : /*
1535 : remove the specified attribute in a search result
1536 : */
1537 2621316904 : void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1538 : {
1539 78366154 : unsigned int i;
1540 2621316904 : unsigned int num_del = 0;
1541 :
1542 31904323632 : for (i = 0; i < msg->num_elements; ++i) {
1543 29283006728 : if (ldb_attr_cmp(msg->elements[i].name, attr) == 0) {
1544 58648522 : ++num_del;
1545 29224358206 : } else if (num_del) {
1546 113200130 : msg->elements[i - num_del] = msg->elements[i];
1547 : }
1548 : }
1549 :
1550 2621316904 : msg->num_elements -= num_del;
1551 2621316904 : }
1552 :
1553 : /* Reallocate elements to drop any excess capacity. */
1554 170647718 : void ldb_msg_shrink_to_fit(struct ldb_message *msg)
1555 : {
1556 170647718 : if (msg->num_elements > 0) {
1557 151573537 : struct ldb_message_element *elements = talloc_realloc(msg,
1558 : msg->elements,
1559 : struct ldb_message_element,
1560 : msg->num_elements);
1561 151573537 : if (elements != NULL) {
1562 151573537 : msg->elements = elements;
1563 : }
1564 : } else {
1565 19074181 : TALLOC_FREE(msg->elements);
1566 : }
1567 170647718 : }
1568 :
1569 : /*
1570 : return a LDAP formatted GeneralizedTime string
1571 : */
1572 6389438 : char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1573 : {
1574 6389438 : struct tm *tm = gmtime(&t);
1575 375211 : char *ts;
1576 375211 : int r;
1577 :
1578 6389438 : if (!tm) {
1579 2 : return NULL;
1580 : }
1581 :
1582 : /* we know exactly how long this string will be */
1583 6389436 : ts = talloc_array(mem_ctx, char, 18);
1584 :
1585 : /* formatted like: 20040408072012.0Z */
1586 6389436 : r = snprintf(ts, 18,
1587 : "%04u%02u%02u%02u%02u%02u.0Z",
1588 6389436 : tm->tm_year+1900, tm->tm_mon+1,
1589 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1590 : tm->tm_sec);
1591 :
1592 6389436 : if (r != 17) {
1593 4 : talloc_free(ts);
1594 4 : errno = EOVERFLOW;
1595 4 : return NULL;
1596 : }
1597 :
1598 6014221 : return ts;
1599 : }
1600 :
1601 : /*
1602 : convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1603 : */
1604 23552 : time_t ldb_string_to_time(const char *s)
1605 : {
1606 72 : struct tm tm;
1607 72 : time_t t;
1608 :
1609 23552 : if (s == NULL) return 0;
1610 :
1611 23526 : memset(&tm, 0, sizeof(tm));
1612 23526 : if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1613 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1614 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1615 0 : return 0;
1616 : }
1617 23526 : tm.tm_year -= 1900;
1618 23526 : tm.tm_mon -= 1;
1619 :
1620 23526 : t = timegm(&tm);
1621 :
1622 23526 : if (t == (time_t)-1 && errno != 0) {
1623 : /*
1624 : * timegm() returns -1 on error, but also for '19691231235959.0Z'.
1625 : */
1626 0 : return 0;
1627 : }
1628 23454 : return t;
1629 : }
1630 :
1631 : /*
1632 : convert a LDAP GeneralizedTime string in ldb_val format to a
1633 : time_t.
1634 : */
1635 4733546 : int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1636 : {
1637 4733546 : char val[15] = {0};
1638 4733546 : struct tm tm = {
1639 : .tm_year = 0,
1640 : };
1641 :
1642 4733546 : if (v == NULL) {
1643 264 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1644 : }
1645 :
1646 4733282 : if (v->data == NULL) {
1647 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1648 : }
1649 :
1650 4733282 : if (v->length < 16 && v->length != 13) {
1651 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1652 : }
1653 :
1654 4733282 : if (v->data[v->length - 1] != 'Z') {
1655 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1656 : }
1657 :
1658 4733282 : if (v->length == 13) {
1659 538 : memcpy(val, v->data, 12);
1660 :
1661 538 : if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
1662 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1663 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1664 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1665 : }
1666 538 : if (tm.tm_year < 50) {
1667 538 : tm.tm_year += 100;
1668 : }
1669 : } else {
1670 :
1671 : /*
1672 : * anything between '.' and 'Z' is silently ignored.
1673 : */
1674 4732744 : if (v->data[14] != '.') {
1675 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1676 : }
1677 :
1678 4732744 : memcpy(val, v->data, 14);
1679 :
1680 4732744 : if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
1681 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1682 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1683 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1684 : }
1685 4732744 : tm.tm_year -= 1900;
1686 : }
1687 4733282 : tm.tm_mon -= 1;
1688 :
1689 4733282 : *t = timegm(&tm);
1690 :
1691 4733282 : return LDB_SUCCESS;
1692 : }
1693 :
1694 : /*
1695 : return a LDAP formatted UTCTime string
1696 : */
1697 63 : char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1698 : {
1699 63 : struct tm *tm = gmtime(&t);
1700 3 : char *ts;
1701 3 : int r;
1702 :
1703 63 : if (!tm) {
1704 0 : return NULL;
1705 : }
1706 :
1707 : /* we know exactly how long this string will be */
1708 63 : ts = talloc_array(mem_ctx, char, 14);
1709 :
1710 : /* formatted like: 20040408072012.0Z => 040408072012Z */
1711 63 : r = snprintf(ts, 14,
1712 : "%02u%02u%02u%02u%02u%02uZ",
1713 63 : (tm->tm_year+1900)%100, tm->tm_mon+1,
1714 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1715 : tm->tm_sec);
1716 :
1717 63 : if (r != 13) {
1718 0 : talloc_free(ts);
1719 0 : return NULL;
1720 : }
1721 :
1722 60 : return ts;
1723 : }
1724 :
1725 : /*
1726 : convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1727 : */
1728 0 : time_t ldb_string_utc_to_time(const char *s)
1729 : {
1730 0 : struct tm tm;
1731 :
1732 0 : if (s == NULL) return 0;
1733 :
1734 0 : memset(&tm, 0, sizeof(tm));
1735 0 : if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1736 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1737 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1738 0 : return 0;
1739 : }
1740 0 : if (tm.tm_year < 50) {
1741 0 : tm.tm_year += 100;
1742 : }
1743 0 : tm.tm_mon -= 1;
1744 :
1745 0 : return timegm(&tm);
1746 : }
1747 :
1748 :
1749 : /*
1750 : dump a set of results to a file. Useful from within gdb
1751 : */
1752 0 : void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1753 : {
1754 0 : unsigned int i;
1755 :
1756 0 : for (i = 0; i < result->count; i++) {
1757 0 : struct ldb_ldif ldif;
1758 0 : fprintf(f, "# record %d\n", i+1);
1759 0 : ldif.changetype = LDB_CHANGETYPE_NONE;
1760 0 : ldif.msg = result->msgs[i];
1761 0 : ldb_ldif_write_file(ldb, f, &ldif);
1762 : }
1763 0 : }
1764 :
1765 : /*
1766 : checks for a string attribute. Returns "1" on match and otherwise "0".
1767 : */
1768 3271152 : int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1769 : const char *name, const char *value)
1770 : {
1771 45294 : struct ldb_message_element *el;
1772 45294 : struct ldb_val val;
1773 :
1774 3271152 : el = ldb_msg_find_element(msg, name);
1775 3271152 : if (el == NULL) {
1776 1592540 : return 0;
1777 : }
1778 :
1779 1654695 : val.data = discard_const_p(uint8_t, value);
1780 1654695 : val.length = strlen(value);
1781 :
1782 1654695 : if (ldb_msg_find_val(el, &val)) {
1783 1653898 : return 1;
1784 : }
1785 :
1786 797 : return 0;
1787 : }
1788 :
1789 :
1790 : /*
1791 : compare a ldb_val to a string
1792 : */
1793 3391827 : int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1794 : {
1795 3391827 : size_t len = strlen(str);
1796 3391827 : if (len != v->length) {
1797 0 : return len - v->length;
1798 : }
1799 3391827 : return strncmp((const char *)v->data, str, len);
1800 : }
|