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 787508276 : struct ldb_message *ldb_msg_new(TALLOC_CTX *mem_ctx)
40 : {
41 787508276 : return talloc_zero(mem_ctx, struct ldb_message);
42 : }
43 :
44 : /*
45 : find an element in a message by attribute name
46 : */
47 6854773892 : struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
48 : const char *attr_name)
49 : {
50 184432507 : unsigned int i;
51 >10301*10^7 : for (i=0;i<msg->num_elements;i++) {
52 98889204044 : if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
53 2728822892 : return &msg->elements[i];
54 : }
55 : }
56 4016332126 : 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 369605535 : int ldb_val_equal_exact(const struct ldb_val *v1, const struct ldb_val *v2)
64 : {
65 369605535 : if (v1->length != v2->length) return 0;
66 59918393 : if (v1->data == v2->data) return 1;
67 59816938 : if (v1->length == 0) return 1;
68 :
69 59816938 : if (memcmp(v1->data, v2->data, v1->length) == 0) {
70 36438157 : return 1;
71 : }
72 :
73 22292983 : return 0;
74 : }
75 :
76 : /*
77 : find a value in an element
78 : assumes case sensitive comparison
79 : */
80 28372765 : struct ldb_val *ldb_msg_find_val(const struct ldb_message_element *el,
81 : struct ldb_val *val)
82 : {
83 930740 : unsigned int i;
84 347272243 : for (i=0;i<el->num_values;i++) {
85 346939365 : if (ldb_val_equal_exact(val, &el->values[i])) {
86 28039887 : return &el->values[i];
87 : }
88 : }
89 321985 : return NULL;
90 : }
91 :
92 :
93 8706512 : static int ldb_val_cmp(const struct ldb_val *v1, const struct ldb_val *v2)
94 : {
95 8706488 : if (v1->length != v2->length) {
96 7300640 : return v1->length - v2->length;
97 : }
98 1405872 : 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 31627459 : 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 2173167 : unsigned int i, j;
118 2173167 : struct ldb_val *val;
119 :
120 31627459 : if (options != 0) {
121 0 : return LDB_ERR_OPERATIONS_ERROR;
122 : }
123 :
124 31627459 : *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 31627459 : if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
131 65683870 : for (j = 0; j < el->num_values; j++) {
132 34113177 : val = &el->values[j];
133 39092217 : for ( i = j + 1; i < el->num_values; i++) {
134 4979044 : if (ldb_val_equal_exact(val, &el->values[i])) {
135 4 : *duplicate = val;
136 4 : return LDB_SUCCESS;
137 : }
138 : }
139 : }
140 : } else {
141 5677 : struct ldb_val *values;
142 56762 : values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
143 56762 : if (values == NULL) {
144 0 : return LDB_ERR_OPERATIONS_ERROR;
145 : }
146 :
147 56762 : memcpy(values, el->values,
148 56762 : el->num_values * sizeof(struct ldb_val));
149 56762 : TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
150 2033931 : for (i = 1; i < el->num_values; i++) {
151 1977170 : if (ldb_val_equal_exact(&values[i],
152 1977170 : &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 56761 : talloc_free(values);
171 : }
172 29454287 : 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 5234 : 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 482 : struct ldb_val *values;
198 482 : struct ldb_val *values2;
199 482 : unsigned int i, j, k, n_values;
200 :
201 5234 : bool remove_duplicates = options & LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES;
202 :
203 5234 : if ((options & ~LDB_MSG_FIND_COMMON_REMOVE_DUPLICATES) != 0) {
204 0 : return LDB_ERR_OPERATIONS_ERROR;
205 : }
206 :
207 5234 : if (strcmp(el->name, el2->name) != 0) {
208 1 : return LDB_ERR_INAPPROPRIATE_MATCHING;
209 : }
210 5233 : 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 5221 : if (MIN(el->num_values, el2->num_values) == 1 ||
218 224 : MAX(el->num_values, el2->num_values) < LDB_DUP_QUADRATIC_THRESHOLD) {
219 22779 : for (i = 0; i < el2->num_values; i++) {
220 36170 : for (j = 0; j < el->num_values; j++) {
221 18494 : if (ldb_val_equal_exact(&el->values[j],
222 18494 : &el2->values[i])) {
223 21 : if (! remove_duplicates) {
224 : return \
225 19 : 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 4604 : 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 3636 : while (i != n_values && j < el2->num_values) {
269 3522 : int ret = ldb_val_cmp(&values[i], &values2[j]);
270 3522 : if (ret < 0) {
271 845 : i++;
272 2677 : } else if (ret > 0) {
273 2659 : 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 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 3140768435 : struct ldb_val ldb_val_dup(TALLOC_CTX *mem_ctx, const struct ldb_val *v)
309 : {
310 104548569 : struct ldb_val v2;
311 3140768435 : v2.length = v->length;
312 3140768435 : 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 3140610025 : v2.data = talloc_array(mem_ctx, uint8_t, v->length+1);
320 3140610025 : if (!v2.data) {
321 0 : v2.length = 0;
322 0 : return v2;
323 : }
324 :
325 3140610025 : memcpy(v2.data, v->data, v->length);
326 3140610025 : ((char *)v2.data)[v->length] = 0;
327 3140610025 : return v2;
328 : }
329 :
330 : /**
331 : * Adds new empty element to msg->elements
332 : */
333 241015440 : static int _ldb_msg_add_el(struct ldb_message *msg,
334 : struct ldb_message_element **return_el)
335 : {
336 8061164 : 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 241015440 : els = talloc_realloc(msg, msg->elements,
344 : struct ldb_message_element, msg->num_elements + 1);
345 241015440 : if (!els) {
346 0 : return LDB_ERR_OPERATIONS_ERROR;
347 : }
348 :
349 241015440 : els[msg->num_elements] = (struct ldb_message_element) {};
350 :
351 241015440 : msg->elements = els;
352 241015440 : msg->num_elements++;
353 :
354 241015440 : *return_el = &els[msg->num_elements-1];
355 :
356 241015440 : return LDB_SUCCESS;
357 : }
358 :
359 : /**
360 : * Add an empty element with a given name to a message
361 : */
362 238962064 : 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 8006964 : int ret;
368 8006964 : struct ldb_message_element *el;
369 :
370 238962064 : ret = _ldb_msg_add_el(msg, &el);
371 238962064 : if (ret != LDB_SUCCESS) {
372 0 : return ret;
373 : }
374 :
375 : /* initialize newly added element */
376 238962064 : el->flags = flags;
377 238962064 : el->name = talloc_strdup(msg->elements, attr_name);
378 238962064 : if (!el->name) {
379 0 : return LDB_ERR_OPERATIONS_ERROR;
380 : }
381 :
382 238962064 : if (return_el) {
383 237795055 : *return_el = el;
384 : }
385 :
386 230955100 : 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 2053376 : int ldb_msg_add(struct ldb_message *msg,
398 : const struct ldb_message_element *el,
399 : int flags)
400 : {
401 54200 : int ret;
402 54200 : 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 2053376 : struct ldb_message_element el_copy = *el;
406 :
407 2053376 : ret = _ldb_msg_add_el(msg, &el_new);
408 2053376 : if (ret != LDB_SUCCESS) {
409 0 : return ret;
410 : }
411 :
412 2053376 : el_new->flags = flags;
413 2053376 : el_new->name = el_copy.name;
414 2053376 : el_new->num_values = el_copy.num_values;
415 2053376 : el_new->values = el_copy.values;
416 :
417 2053376 : return LDB_SUCCESS;
418 : }
419 :
420 : /*
421 : * add a value to a message element
422 : */
423 231780509 : int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
424 : struct ldb_message_element *el,
425 : const struct ldb_val *val)
426 : {
427 7441247 : struct ldb_val *vals;
428 :
429 231780509 : 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 231780471 : vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
449 : el->num_values + 1);
450 231780471 : if (vals == NULL) {
451 0 : return LDB_ERR_OPERATIONS_ERROR;
452 : }
453 : }
454 231780509 : el->values = vals;
455 231780509 : el->values[el->num_values] = *val;
456 231780509 : el->num_values++;
457 :
458 231780509 : return LDB_SUCCESS;
459 : }
460 :
461 : /*
462 : add a value to a message
463 : */
464 231411598 : 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 7436284 : struct ldb_message_element *el;
470 7436284 : int ret;
471 :
472 231411598 : el = ldb_msg_find_element(msg, attr_name);
473 231411598 : if (!el) {
474 225541880 : ret = ldb_msg_add_empty(msg, attr_name, 0, &el);
475 225541880 : if (ret != LDB_SUCCESS) {
476 0 : return ret;
477 : }
478 : }
479 :
480 231411598 : ret = ldb_msg_element_add_value(msg->elements, el, val);
481 231411598 : if (ret != LDB_SUCCESS) {
482 0 : return ret;
483 : }
484 :
485 231411598 : if (return_el) {
486 228826876 : *return_el = el;
487 : }
488 :
489 223975314 : return LDB_SUCCESS;
490 : }
491 :
492 :
493 : /*
494 : add a value to a message, stealing it into the 'right' place
495 : */
496 192827081 : int ldb_msg_add_steal_value(struct ldb_message *msg,
497 : const char *attr_name,
498 : struct ldb_val *val)
499 : {
500 5596636 : int ret;
501 5596636 : struct ldb_message_element *el;
502 :
503 192827081 : ret = ldb_msg_add_value(msg, attr_name, val, &el);
504 192827081 : if (ret == LDB_SUCCESS) {
505 192827081 : talloc_steal(el->values, val->data);
506 : }
507 192827081 : return ret;
508 : }
509 :
510 :
511 : /*
512 : add a string element to a message, specifying flags
513 : */
514 35408831 : int ldb_msg_add_string_flags(struct ldb_message *msg,
515 : const char *attr_name, const char *str,
516 : int flags)
517 : {
518 1619196 : struct ldb_val val;
519 1619196 : int ret;
520 35408831 : struct ldb_message_element *el = NULL;
521 :
522 35408831 : val.data = discard_const_p(uint8_t, str);
523 35408831 : val.length = strlen(str);
524 :
525 35408831 : if (val.length == 0) {
526 : /* allow empty strings as non-existent attributes */
527 286 : return LDB_SUCCESS;
528 : }
529 :
530 35408523 : ret = ldb_msg_add_value(msg, attr_name, &val, &el);
531 35408523 : if (ret != LDB_SUCCESS) {
532 0 : return ret;
533 : }
534 :
535 35408523 : if (flags != 0) {
536 88964 : el->flags = flags;
537 : }
538 :
539 33789349 : return LDB_SUCCESS;
540 : }
541 :
542 : /*
543 : add a string element to a message
544 : */
545 35319867 : int ldb_msg_add_string(struct ldb_message *msg,
546 : const char *attr_name, const char *str)
547 : {
548 35319867 : 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 175000291 : int ldb_msg_add_steal_string(struct ldb_message *msg,
555 : const char *attr_name, char *str)
556 : {
557 4637561 : struct ldb_val val;
558 :
559 175000291 : val.data = (uint8_t *)str;
560 175000291 : val.length = strlen(str);
561 :
562 175000291 : if (val.length == 0) {
563 : /* allow empty strings as non-existent attributes */
564 0 : return LDB_SUCCESS;
565 : }
566 :
567 175000291 : return ldb_msg_add_steal_value(msg, attr_name, &val);
568 : }
569 :
570 : /*
571 : add a DN element to a message
572 : */
573 1987 : int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
574 : struct ldb_dn *dn)
575 : {
576 1987 : char *str = ldb_dn_alloc_linearized(msg, dn);
577 :
578 1987 : if (str == NULL) {
579 : /* we don't want to have unknown DNs added */
580 0 : return LDB_ERR_OPERATIONS_ERROR;
581 : }
582 :
583 1987 : return ldb_msg_add_steal_string(msg, attr_name, str);
584 : }
585 :
586 : /*
587 : add a printf formatted element to a message
588 : */
589 10509038 : int ldb_msg_add_fmt(struct ldb_message *msg,
590 : const char *attr_name, const char *fmt, ...)
591 : {
592 721039 : struct ldb_val val;
593 721039 : va_list ap;
594 721039 : char *str;
595 :
596 10509038 : va_start(ap, fmt);
597 10509038 : str = talloc_vasprintf(msg, fmt, ap);
598 10509038 : va_end(ap);
599 :
600 10509038 : if (str == NULL) return LDB_ERR_OPERATIONS_ERROR;
601 :
602 10509038 : val.data = (uint8_t *)str;
603 10509038 : val.length = strlen(str);
604 :
605 10509038 : return ldb_msg_add_steal_value(msg, attr_name, &val);
606 : }
607 :
608 368265 : 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 368265 : struct ldb_message_element *el = NULL;
615 4957 : int ret;
616 :
617 368265 : ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
618 368265 : if (ret != LDB_SUCCESS) {
619 0 : return ret;
620 : }
621 :
622 368265 : ret = ldb_msg_element_add_value(msg->elements, el, val);
623 368265 : if (ret != LDB_SUCCESS) {
624 0 : return ret;
625 : }
626 :
627 368265 : if (return_el != NULL) {
628 2089 : *return_el = el;
629 : }
630 :
631 363308 : return LDB_SUCCESS;
632 : }
633 :
634 : /*
635 : append a value to a message
636 : */
637 366176 : 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 366176 : 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 2089 : 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 136 : int ret;
654 2089 : struct ldb_message_element *el = NULL;
655 :
656 2089 : ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
657 2089 : if (ret == LDB_SUCCESS) {
658 2089 : talloc_steal(el->values, val->data);
659 : }
660 2089 : return ret;
661 : }
662 :
663 : /*
664 : append a string element to a message, stealing it into the 'right' place
665 : */
666 981 : int ldb_msg_append_steal_string(struct ldb_message *msg,
667 : const char *attr_name, char *str,
668 : int flags)
669 : {
670 110 : struct ldb_val val;
671 :
672 981 : val.data = (uint8_t *)str;
673 981 : val.length = strlen(str);
674 :
675 981 : if (val.length == 0) {
676 : /* allow empty strings as non-existent attributes */
677 0 : return LDB_SUCCESS;
678 : }
679 :
680 981 : return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
681 : }
682 :
683 : /*
684 : append a string element to a message
685 : */
686 88750 : int ldb_msg_append_string(struct ldb_message *msg,
687 : const char *attr_name, const char *str, int flags)
688 : {
689 412 : struct ldb_val val;
690 :
691 88750 : val.data = discard_const_p(uint8_t, str);
692 88750 : val.length = strlen(str);
693 :
694 88750 : if (val.length == 0) {
695 : /* allow empty strings as non-existent attributes */
696 0 : return LDB_SUCCESS;
697 : }
698 :
699 88750 : return ldb_msg_append_value(msg, attr_name, &val, flags);
700 : }
701 :
702 : /*
703 : append a DN element to a message
704 : */
705 2 : int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
706 : struct ldb_dn *dn, int flags)
707 : {
708 2 : char *str = ldb_dn_alloc_linearized(msg, dn);
709 :
710 2 : if (str == NULL) {
711 : /* we don't want to have unknown DNs added */
712 0 : return LDB_ERR_OPERATIONS_ERROR;
713 : }
714 :
715 2 : 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 1108 : 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 1108 : char *str = NULL;
727 :
728 1108 : va_start(ap, fmt);
729 1108 : str = talloc_vasprintf(msg, fmt, ap);
730 1108 : va_end(ap);
731 :
732 1108 : if (str == NULL) {
733 0 : return LDB_ERR_OPERATIONS_ERROR;
734 : }
735 :
736 1108 : val.data = (uint8_t *)str;
737 1108 : val.length = strlen(str);
738 :
739 1108 : 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 21646889 : int ldb_msg_element_compare(struct ldb_message_element *el1,
747 : struct ldb_message_element *el2)
748 : {
749 727192 : unsigned int i;
750 :
751 21646889 : if (el1->num_values != el2->num_values) {
752 244 : return el1->num_values - el2->num_values;
753 : }
754 :
755 47943760 : for (i=0;i<el1->num_values;i++) {
756 26353572 : if (!ldb_msg_find_val(el2, &el1->values[i])) {
757 54517 : return -1;
758 : }
759 : }
760 :
761 20864937 : return 0;
762 : }
763 :
764 : /*
765 : compare two ldb_message_element structures.
766 : Different ordering is considered a mismatch
767 : */
768 12510789 : bool ldb_msg_element_equal_ordered(const struct ldb_message_element *el1,
769 : const struct ldb_message_element *el2)
770 : {
771 404775 : unsigned i;
772 12510789 : if (el1->num_values != el2->num_values) {
773 1069799 : return false;
774 : }
775 17408659 : for (i=0;i<el1->num_values;i++) {
776 11977854 : if (ldb_val_equal_exact(&el1->values[i],
777 11977854 : &el2->values[i]) != 1) {
778 5808687 : return false;
779 : }
780 : }
781 5227528 : return true;
782 : }
783 :
784 : /*
785 : compare two ldb_message_element structures
786 : comparing by element name
787 : */
788 253564642 : int ldb_msg_element_compare_name(struct ldb_message_element *el1,
789 : struct ldb_message_element *el2)
790 : {
791 253564642 : if (el1->name == el2->name) {
792 0 : return 0;
793 : }
794 :
795 253564642 : if (el1->name == NULL) {
796 0 : return -1;
797 : }
798 :
799 253564642 : if (el2->name == NULL) {
800 0 : return 1;
801 : }
802 :
803 253564642 : return ldb_attr_cmp(el1->name, el2->name);
804 : }
805 :
806 5066778 : void ldb_msg_element_mark_inaccessible(struct ldb_message_element *el)
807 : {
808 5066778 : el->flags |= LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE;
809 5066778 : }
810 :
811 211591312 : bool ldb_msg_element_is_inaccessible(const struct ldb_message_element *el)
812 : {
813 211591312 : return (el->flags & LDB_FLAG_INTERNAL_INACCESSIBLE_ATTRIBUTE) != 0;
814 : }
815 :
816 1481961 : void ldb_msg_remove_inaccessible(struct ldb_message *msg)
817 : {
818 268 : unsigned i;
819 1481961 : unsigned num_del = 0;
820 :
821 10624835 : for (i = 0; i < msg->num_elements; ++i) {
822 9142874 : if (ldb_msg_element_is_inaccessible(&msg->elements[i])) {
823 5062046 : ++num_del;
824 4080828 : } else if (num_del) {
825 2955448 : msg->elements[i - num_del] = msg->elements[i];
826 : }
827 : }
828 :
829 1481961 : msg->num_elements -= num_del;
830 1481961 : }
831 :
832 : /*
833 : convenience functions to return common types from a message
834 : these return the first value if the attribute is multi-valued
835 : */
836 3298413112 : const struct ldb_val *ldb_msg_find_ldb_val(const struct ldb_message *msg,
837 : const char *attr_name)
838 : {
839 3298413112 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr_name);
840 3298413112 : if (!el || el->num_values == 0) {
841 1420939120 : return NULL;
842 : }
843 1840209594 : return &el->values[0];
844 : }
845 :
846 149385165 : int ldb_msg_find_attr_as_int(const struct ldb_message *msg,
847 : const char *attr_name,
848 : int default_value)
849 : {
850 149385165 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
851 149385165 : char buf[sizeof("-2147483648")] = {};
852 149385165 : char *end = NULL;
853 3158903 : int ret;
854 :
855 149385165 : if (!v || !v->data) {
856 1912867 : return default_value;
857 : }
858 :
859 147325513 : if (v->length >= sizeof(buf)) {
860 66 : return default_value;
861 : }
862 :
863 147325447 : memcpy(buf, v->data, v->length);
864 147325447 : errno = 0;
865 147325447 : ret = (int) strtoll(buf, &end, 10);
866 147325447 : if (errno != 0) {
867 0 : return default_value;
868 : }
869 147325447 : if (end && end[0] != '\0') {
870 0 : return default_value;
871 : }
872 144313329 : return ret;
873 : }
874 :
875 587901036 : unsigned int ldb_msg_find_attr_as_uint(const struct ldb_message *msg,
876 : const char *attr_name,
877 : unsigned int default_value)
878 : {
879 587901036 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
880 587901036 : char buf[sizeof("-2147483648")] = {};
881 587901036 : char *end = NULL;
882 14765137 : unsigned int ret;
883 :
884 587901036 : if (!v || !v->data) {
885 285423470 : return default_value;
886 : }
887 :
888 295033022 : if (v->length >= sizeof(buf)) {
889 39 : return default_value;
890 : }
891 :
892 295032983 : memcpy(buf, v->data, v->length);
893 295032983 : errno = 0;
894 295032983 : ret = (unsigned int) strtoll(buf, &end, 10);
895 295032983 : if (errno != 0) {
896 0 : errno = 0;
897 0 : ret = (unsigned int) strtoull(buf, &end, 10);
898 0 : if (errno != 0) {
899 0 : return default_value;
900 : }
901 : }
902 295032983 : if (end && end[0] != '\0') {
903 0 : return default_value;
904 : }
905 287712390 : return ret;
906 : }
907 :
908 2475228 : int64_t ldb_msg_find_attr_as_int64(const struct ldb_message *msg,
909 : const char *attr_name,
910 : int64_t default_value)
911 : {
912 2475228 : int64_t val = 0;
913 2475228 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
914 2475228 : int ret = ldb_val_as_int64(v, &val);
915 2475228 : return ret ? default_value : val;
916 : }
917 :
918 2475551 : int ldb_val_as_int64(const struct ldb_val *v, int64_t *val)
919 : {
920 2475551 : char buf[sizeof("-9223372036854775808")] = {};
921 2475551 : char *end = NULL;
922 72116 : int64_t result;
923 :
924 2475551 : if (!v || !v->data) {
925 531844 : return LDB_ERR_OPERATIONS_ERROR;
926 : }
927 :
928 1927991 : if (v->length >= sizeof(buf)) {
929 0 : return LDB_ERR_OPERATIONS_ERROR;
930 : }
931 :
932 1927991 : memcpy(buf, v->data, v->length);
933 1927991 : errno = 0;
934 1927991 : result = (int64_t) strtoll(buf, &end, 10);
935 1927991 : if (errno != 0) {
936 0 : return LDB_ERR_OPERATIONS_ERROR;
937 : }
938 1927991 : if (end && end[0] != '\0') {
939 0 : return LDB_ERR_OPERATIONS_ERROR;
940 : }
941 :
942 1927991 : *val = result;
943 1927991 : return LDB_SUCCESS;
944 : }
945 :
946 246835161 : uint64_t ldb_msg_find_attr_as_uint64(const struct ldb_message *msg,
947 : const char *attr_name,
948 : uint64_t default_value)
949 : {
950 246835161 : uint64_t val = 0;
951 246835161 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
952 246835161 : int ret = ldb_val_as_uint64(v, &val);
953 246835161 : return ret ? default_value : val;
954 : }
955 :
956 246835161 : int ldb_val_as_uint64(const struct ldb_val *v, uint64_t *val)
957 : {
958 246835161 : char buf[sizeof("-9223372036854775808")] = {};
959 246835161 : char *end = NULL;
960 6790231 : uint64_t result;
961 :
962 246835161 : if (!v || !v->data) {
963 111368283 : return LDB_ERR_OPERATIONS_ERROR;
964 : }
965 :
966 132627190 : if (v->length >= sizeof(buf)) {
967 0 : return LDB_ERR_OPERATIONS_ERROR;
968 : }
969 :
970 132627190 : memcpy(buf, v->data, v->length);
971 132627190 : errno = 0;
972 132627190 : result = (uint64_t) strtoll(buf, &end, 10);
973 132627190 : if (errno != 0) {
974 0 : errno = 0;
975 0 : result = (uint64_t) strtoull(buf, &end, 10);
976 0 : if (errno != 0) {
977 0 : return LDB_ERR_OPERATIONS_ERROR;
978 : }
979 : }
980 132627190 : if (end && end[0] != '\0') {
981 0 : return LDB_ERR_OPERATIONS_ERROR;
982 : }
983 :
984 132627190 : *val = result;
985 132627190 : return LDB_SUCCESS;
986 : }
987 :
988 0 : double ldb_msg_find_attr_as_double(const struct ldb_message *msg,
989 : const char *attr_name,
990 : double default_value)
991 : {
992 0 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
993 0 : char *buf;
994 0 : char *end = NULL;
995 0 : double ret;
996 :
997 0 : if (!v || !v->data) {
998 0 : return default_value;
999 : }
1000 0 : buf = talloc_strndup(msg, (const char *)v->data, v->length);
1001 0 : if (buf == NULL) {
1002 0 : return default_value;
1003 : }
1004 :
1005 0 : errno = 0;
1006 0 : ret = strtod(buf, &end);
1007 0 : talloc_free(buf);
1008 0 : if (errno != 0) {
1009 0 : return default_value;
1010 : }
1011 0 : if (end && end[0] != '\0') {
1012 0 : return default_value;
1013 : }
1014 0 : return ret;
1015 : }
1016 :
1017 8378562 : int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
1018 : const char *attr_name,
1019 : int default_value)
1020 : {
1021 8378562 : bool val = false;
1022 8378562 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1023 8378562 : int ret = ldb_val_as_bool(v, &val);
1024 8378562 : return ret ? default_value : val;
1025 : }
1026 :
1027 8378591 : int ldb_val_as_bool(const struct ldb_val *v, bool *val)
1028 : {
1029 8378591 : if (!v || !v->data) {
1030 2881584 : return LDB_ERR_OPERATIONS_ERROR;
1031 : }
1032 5496795 : if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
1033 83530 : *val = false;
1034 83530 : return LDB_SUCCESS;
1035 : }
1036 5413265 : if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
1037 5413265 : *val = true;
1038 5413265 : return LDB_SUCCESS;
1039 : }
1040 0 : return LDB_ERR_OPERATIONS_ERROR;
1041 : }
1042 :
1043 766459640 : const char *ldb_msg_find_attr_as_string(const struct ldb_message *msg,
1044 : const char *attr_name,
1045 : const char *default_value)
1046 : {
1047 766459640 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1048 766459640 : if (!v || !v->data) {
1049 476241403 : return default_value;
1050 : }
1051 278217781 : if (v->data[v->length] != '\0') {
1052 0 : return default_value;
1053 : }
1054 271270218 : return (const char *)v->data;
1055 : }
1056 :
1057 5619328 : struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
1058 : TALLOC_CTX *mem_ctx,
1059 : const struct ldb_message *msg,
1060 : const char *attr_name)
1061 : {
1062 5619328 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr_name);
1063 5619328 : return ldb_val_as_dn(ldb, mem_ctx, v);
1064 : }
1065 :
1066 5624411 : struct ldb_dn *ldb_val_as_dn(struct ldb_context *ldb,
1067 : TALLOC_CTX *mem_ctx,
1068 : const struct ldb_val *v)
1069 : {
1070 162598 : struct ldb_dn *res_dn;
1071 :
1072 5624411 : if (!v || !v->data) {
1073 1123960 : return NULL;
1074 : }
1075 4398003 : res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
1076 4398003 : if ( ! ldb_dn_validate(res_dn)) {
1077 0 : talloc_free(res_dn);
1078 0 : return NULL;
1079 : }
1080 4337853 : return res_dn;
1081 : }
1082 :
1083 : /*
1084 : sort the elements of a message by name
1085 : */
1086 1727406 : void ldb_msg_sort_elements(struct ldb_message *msg)
1087 : {
1088 1727406 : TYPESAFE_QSORT(msg->elements, msg->num_elements,
1089 : ldb_msg_element_compare_name);
1090 1727406 : }
1091 :
1092 9874479 : static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
1093 : const struct ldb_message *msg)
1094 : {
1095 864193 : struct ldb_message *msg2;
1096 864193 : unsigned int i;
1097 :
1098 9874479 : msg2 = talloc(mem_ctx, struct ldb_message);
1099 9874479 : if (msg2 == NULL) return NULL;
1100 :
1101 9874479 : *msg2 = *msg;
1102 :
1103 9874479 : msg2->elements = talloc_array(msg2, struct ldb_message_element,
1104 : msg2->num_elements);
1105 9874479 : if (msg2->elements == NULL) goto failed;
1106 :
1107 108021250 : for (i=0;i<msg2->num_elements;i++) {
1108 98146771 : msg2->elements[i] = msg->elements[i];
1109 : }
1110 :
1111 9010286 : return msg2;
1112 :
1113 0 : failed:
1114 0 : talloc_free(msg2);
1115 0 : return NULL;
1116 : }
1117 :
1118 : /*
1119 : shallow copy a message - copying only the elements array so that the caller
1120 : can safely add new elements without changing the message
1121 : */
1122 7973082 : struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
1123 : const struct ldb_message *msg)
1124 : {
1125 716187 : struct ldb_message *msg2;
1126 716187 : unsigned int i;
1127 :
1128 7973082 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1129 7973082 : if (msg2 == NULL) {
1130 0 : return NULL;
1131 : }
1132 :
1133 65185337 : for (i = 0; i < msg2->num_elements; ++i) {
1134 : /*
1135 : * Mark this message's elements as sharing their values with the
1136 : * original message, so that we don't inadvertently modify or
1137 : * free them. We don't mark the original message element as
1138 : * shared, so the original message element should not be
1139 : * modified or freed while the shallow copy lives.
1140 : */
1141 57212255 : struct ldb_message_element *el = &msg2->elements[i];
1142 57212255 : el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
1143 : }
1144 :
1145 7256895 : return msg2;
1146 : }
1147 :
1148 : /*
1149 : copy a message, allocating new memory for all parts
1150 : */
1151 1901397 : struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
1152 : const struct ldb_message *msg)
1153 : {
1154 148006 : struct ldb_message *msg2;
1155 148006 : unsigned int i, j;
1156 :
1157 1901397 : msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
1158 1901397 : if (msg2 == NULL) return NULL;
1159 :
1160 1901397 : if (msg2->dn != NULL) {
1161 1901382 : msg2->dn = ldb_dn_copy(msg2, msg2->dn);
1162 1901382 : if (msg2->dn == NULL) goto failed;
1163 : }
1164 :
1165 42835913 : for (i=0;i<msg2->num_elements;i++) {
1166 40934516 : struct ldb_message_element *el = &msg2->elements[i];
1167 40934516 : struct ldb_val *values = el->values;
1168 40934516 : if (el->name != NULL) {
1169 40934516 : el->name = talloc_strdup(msg2->elements, el->name);
1170 40934516 : if (el->name == NULL) goto failed;
1171 : }
1172 40934516 : el->values = talloc_array(msg2->elements, struct ldb_val, el->num_values);
1173 40934516 : if (el->values == NULL) goto failed;
1174 90797727 : for (j=0;j<el->num_values;j++) {
1175 49863211 : el->values[j] = ldb_val_dup(el->values, &values[j]);
1176 49863211 : if (el->values[j].data == NULL && values[j].length != 0) {
1177 0 : goto failed;
1178 : }
1179 : }
1180 :
1181 : /*
1182 : * Since we copied this element's values, we can mark them as
1183 : * not shared.
1184 : */
1185 40934516 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1186 : }
1187 :
1188 1753391 : return msg2;
1189 :
1190 0 : failed:
1191 0 : talloc_free(msg2);
1192 0 : return NULL;
1193 : }
1194 :
1195 :
1196 : /**
1197 : * Canonicalize a message, merging elements of the same name
1198 : */
1199 0 : struct ldb_message *ldb_msg_canonicalize(struct ldb_context *ldb,
1200 : const struct ldb_message *msg)
1201 : {
1202 0 : int ret;
1203 0 : struct ldb_message *msg2;
1204 :
1205 : /*
1206 : * Preserve previous behavior and allocate
1207 : * *msg2 into *ldb context
1208 : */
1209 0 : ret = ldb_msg_normalize(ldb, ldb, msg, &msg2);
1210 0 : if (ret != LDB_SUCCESS) {
1211 0 : return NULL;
1212 : }
1213 :
1214 0 : return msg2;
1215 : }
1216 :
1217 : /**
1218 : * Canonicalize a message, merging elements of the same name
1219 : */
1220 1726780 : int ldb_msg_normalize(struct ldb_context *ldb,
1221 : TALLOC_CTX *mem_ctx,
1222 : const struct ldb_message *msg,
1223 : struct ldb_message **_msg_out)
1224 : {
1225 137629 : unsigned int i;
1226 137629 : struct ldb_message *msg2;
1227 :
1228 1726780 : msg2 = ldb_msg_copy(mem_ctx, msg);
1229 1726780 : if (msg2 == NULL) {
1230 0 : return LDB_ERR_OPERATIONS_ERROR;
1231 : }
1232 :
1233 1726780 : ldb_msg_sort_elements(msg2);
1234 :
1235 39547062 : for (i=1; i < msg2->num_elements; i++) {
1236 37682653 : struct ldb_message_element *el1 = &msg2->elements[i-1];
1237 37682653 : struct ldb_message_element *el2 = &msg2->elements[i];
1238 :
1239 37682653 : if (ldb_msg_element_compare_name(el1, el2) == 0) {
1240 14396 : el1->values = talloc_realloc(msg2->elements,
1241 : el1->values, struct ldb_val,
1242 : el1->num_values + el2->num_values);
1243 14396 : if (el1->num_values + el2->num_values > 0 && el1->values == NULL) {
1244 0 : talloc_free(msg2);
1245 0 : return LDB_ERR_OPERATIONS_ERROR;
1246 : }
1247 14396 : memcpy(el1->values + el1->num_values,
1248 14396 : el2->values,
1249 14396 : sizeof(struct ldb_val) * el2->num_values);
1250 14396 : el1->num_values += el2->num_values;
1251 14396 : talloc_free(discard_const_p(char, el2->name));
1252 14396 : if ((i+1) < msg2->num_elements) {
1253 626 : memmove(el2, el2+1, sizeof(struct ldb_message_element) *
1254 0 : (msg2->num_elements - (i+1)));
1255 : }
1256 14396 : msg2->num_elements--;
1257 14396 : i--;
1258 : }
1259 : }
1260 :
1261 1726780 : *_msg_out = msg2;
1262 1726780 : return LDB_SUCCESS;
1263 : }
1264 :
1265 :
1266 : /**
1267 : * return a ldb_message representing the differences between msg1 and msg2.
1268 : * If you then use this in a ldb_modify() call,
1269 : * it can be used to save edits to a message
1270 : */
1271 0 : struct ldb_message *ldb_msg_diff(struct ldb_context *ldb,
1272 : struct ldb_message *msg1,
1273 : struct ldb_message *msg2)
1274 : {
1275 0 : int ldb_ret;
1276 0 : struct ldb_message *mod;
1277 :
1278 0 : ldb_ret = ldb_msg_difference(ldb, ldb, msg1, msg2, &mod);
1279 0 : if (ldb_ret != LDB_SUCCESS) {
1280 0 : return NULL;
1281 : }
1282 :
1283 0 : return mod;
1284 : }
1285 :
1286 : /**
1287 : * return a ldb_message representing the differences between msg1 and msg2.
1288 : * If you then use this in a ldb_modify() call it can be used to save edits to a message
1289 : *
1290 : * Result message is constructed as follows:
1291 : * - LDB_FLAG_MOD_ADD - elements found only in msg2
1292 : * - LDB_FLAG_MOD_REPLACE - elements in msg2 that have different value in msg1
1293 : * Value for msg2 element is used
1294 : * - LDB_FLAG_MOD_DELETE - elements found only in msg2
1295 : *
1296 : * @return LDB_SUCCESS or LDB_ERR_OPERATIONS_ERROR
1297 : */
1298 90896 : int ldb_msg_difference(struct ldb_context *ldb,
1299 : TALLOC_CTX *mem_ctx,
1300 : struct ldb_message *msg1,
1301 : struct ldb_message *msg2,
1302 : struct ldb_message **_msg_out)
1303 : {
1304 2259 : int ldb_res;
1305 2259 : unsigned int i;
1306 2259 : struct ldb_message *mod;
1307 2259 : struct ldb_message_element *el;
1308 2259 : TALLOC_CTX *temp_ctx;
1309 :
1310 90896 : temp_ctx = talloc_new(mem_ctx);
1311 90896 : if (!temp_ctx) {
1312 0 : return LDB_ERR_OPERATIONS_ERROR;
1313 : }
1314 :
1315 90896 : mod = ldb_msg_new(temp_ctx);
1316 90896 : if (mod == NULL) {
1317 0 : goto failed;
1318 : }
1319 :
1320 90896 : mod->dn = msg1->dn;
1321 90896 : mod->num_elements = 0;
1322 90896 : mod->elements = NULL;
1323 :
1324 : /*
1325 : * Canonicalize *msg2 so we have no repeated elements
1326 : * Resulting message is allocated in *mod's mem context,
1327 : * as we are going to move some elements from *msg2 to
1328 : * *mod object later
1329 : */
1330 90896 : ldb_res = ldb_msg_normalize(ldb, mod, msg2, &msg2);
1331 90896 : if (ldb_res != LDB_SUCCESS) {
1332 0 : goto failed;
1333 : }
1334 :
1335 : /* look in msg2 to find elements that need to be added or modified */
1336 21731555 : for (i=0;i<msg2->num_elements;i++) {
1337 21640659 : el = ldb_msg_find_element(msg1, msg2->elements[i].name);
1338 :
1339 21640659 : if (el && ldb_msg_element_compare(el, &msg2->elements[i]) == 0) {
1340 21582693 : continue;
1341 : }
1342 :
1343 57966 : ldb_res = ldb_msg_add(mod,
1344 57966 : &msg2->elements[i],
1345 : el ? LDB_FLAG_MOD_REPLACE : LDB_FLAG_MOD_ADD);
1346 57966 : if (ldb_res != LDB_SUCCESS) {
1347 0 : goto failed;
1348 : }
1349 : }
1350 :
1351 : /* look in msg1 to find elements that need to be deleted */
1352 21732303 : for (i=0;i<msg1->num_elements;i++) {
1353 21641407 : el = ldb_msg_find_element(msg2, msg1->elements[i].name);
1354 21641407 : if (el == NULL) {
1355 2043 : ldb_res = ldb_msg_add_empty(mod,
1356 2029 : msg1->elements[i].name,
1357 : LDB_FLAG_MOD_DELETE, NULL);
1358 2029 : if (ldb_res != LDB_SUCCESS) {
1359 0 : goto failed;
1360 : }
1361 : }
1362 : }
1363 :
1364 : /* steal resulting message into supplied context */
1365 90896 : talloc_steal(mem_ctx, mod);
1366 90896 : *_msg_out = mod;
1367 :
1368 90896 : talloc_free(temp_ctx);
1369 90896 : return LDB_SUCCESS;
1370 :
1371 0 : failed:
1372 0 : talloc_free(temp_ctx);
1373 0 : return LDB_ERR_OPERATIONS_ERROR;
1374 : }
1375 :
1376 :
1377 1433882 : int ldb_msg_sanity_check(struct ldb_context *ldb,
1378 : const struct ldb_message *msg)
1379 : {
1380 112715 : unsigned int i, j;
1381 :
1382 : /* basic check on DN */
1383 1433882 : if (msg->dn == NULL) {
1384 0 : ldb_set_errstring(ldb, "ldb message lacks a DN!");
1385 0 : return LDB_ERR_INVALID_DN_SYNTAX;
1386 : }
1387 :
1388 : /* basic syntax checks */
1389 8556320 : for (i = 0; i < msg->num_elements; i++) {
1390 16681365 : for (j = 0; j < msg->elements[i].num_values; j++) {
1391 9558927 : if (msg->elements[i].values[j].length == 0) {
1392 : /* an attribute cannot be empty */
1393 4 : ldb_asprintf_errstring(ldb, "Element %s has empty attribute in ldb message (%s)!",
1394 2 : msg->elements[i].name,
1395 2 : ldb_dn_get_linearized(msg->dn));
1396 2 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1397 : }
1398 : }
1399 : }
1400 :
1401 1321165 : return LDB_SUCCESS;
1402 : }
1403 :
1404 :
1405 :
1406 :
1407 : /*
1408 : copy an attribute list. This only copies the array, not the elements
1409 : (ie. the elements are left as the same pointers)
1410 : */
1411 10203311 : const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
1412 : {
1413 206085 : const char **ret;
1414 206085 : unsigned int i;
1415 :
1416 306074204 : for (i=0;attrs && attrs[i];i++) /* noop */ ;
1417 10203311 : ret = talloc_array(mem_ctx, const char *, i+1);
1418 10203311 : if (ret == NULL) {
1419 0 : return NULL;
1420 : }
1421 306074204 : for (i=0;attrs && attrs[i];i++) {
1422 295870893 : ret[i] = attrs[i];
1423 : }
1424 10203311 : ret[i] = attrs[i];
1425 10203311 : return ret;
1426 : }
1427 :
1428 :
1429 : /*
1430 : copy an attribute list. This only copies the array, not the elements
1431 : (ie. the elements are left as the same pointers). The new attribute is added to the list.
1432 : */
1433 10912097 : const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *attrs, const char *new_attr)
1434 : {
1435 230223 : const char **ret;
1436 230223 : unsigned int i;
1437 10912097 : bool found = false;
1438 :
1439 287371120 : for (i=0;attrs && attrs[i];i++) {
1440 276459023 : if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
1441 7793952 : found = true;
1442 : }
1443 : }
1444 10912097 : if (found) {
1445 6942726 : return ldb_attr_list_copy(mem_ctx, attrs);
1446 : }
1447 3969371 : ret = talloc_array(mem_ctx, const char *, i+2);
1448 3969371 : if (ret == NULL) {
1449 0 : return NULL;
1450 : }
1451 37447581 : for (i=0;attrs && attrs[i];i++) {
1452 33478210 : ret[i] = attrs[i];
1453 : }
1454 3969371 : ret[i] = new_attr;
1455 3969371 : ret[i+1] = NULL;
1456 3969371 : return ret;
1457 : }
1458 :
1459 :
1460 : /*
1461 : return 1 if an attribute is in a list of attributes, or 0 otherwise
1462 : */
1463 2346185643 : int ldb_attr_in_list(const char * const *attrs, const char *attr)
1464 : {
1465 95256928 : unsigned int i;
1466 6408749684 : for (i=0;attrs && attrs[i];i++) {
1467 4162730657 : if (ldb_attr_cmp(attrs[i], attr) == 0) {
1468 98859829 : return 1;
1469 : }
1470 : }
1471 2152068886 : return 0;
1472 : }
1473 :
1474 :
1475 : /*
1476 : rename the specified attribute in a search result
1477 : */
1478 3 : int ldb_msg_rename_attr(struct ldb_message *msg, const char *attr, const char *replace)
1479 : {
1480 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1481 3 : if (el == NULL) {
1482 0 : return LDB_SUCCESS;
1483 : }
1484 3 : el->name = talloc_strdup(msg->elements, replace);
1485 3 : if (el->name == NULL) {
1486 0 : return LDB_ERR_OPERATIONS_ERROR;
1487 : }
1488 3 : return LDB_SUCCESS;
1489 : }
1490 :
1491 :
1492 : /*
1493 : copy the specified attribute in a search result to a new attribute
1494 : */
1495 3 : int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *replace)
1496 : {
1497 3 : struct ldb_message_element *el = ldb_msg_find_element(msg, attr);
1498 0 : int ret;
1499 :
1500 3 : if (el == NULL) {
1501 0 : return LDB_SUCCESS;
1502 : }
1503 3 : ret = ldb_msg_add(msg, el, 0);
1504 3 : if (ret != LDB_SUCCESS) {
1505 0 : return ret;
1506 : }
1507 3 : return ldb_msg_rename_attr(msg, attr, replace);
1508 : }
1509 :
1510 : /*
1511 : remove the specified element in a search result
1512 : */
1513 9136809 : void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
1514 : {
1515 9136809 : ptrdiff_t n = (el - msg->elements);
1516 9136809 : if (n >= msg->num_elements || n < 0) {
1517 : /* the element is not in the list. the caller is crazy. */
1518 0 : return;
1519 : }
1520 9136809 : msg->num_elements--;
1521 9136809 : if (n != msg->num_elements) {
1522 5108008 : memmove(el, el+1, (msg->num_elements - n)*sizeof(*el));
1523 : }
1524 : }
1525 :
1526 :
1527 : /*
1528 : remove the specified attribute in a search result
1529 : */
1530 2593305259 : void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr)
1531 : {
1532 77446660 : unsigned int i;
1533 2593305259 : unsigned int num_del = 0;
1534 :
1535 31445880395 : for (i = 0; i < msg->num_elements; ++i) {
1536 28852575136 : if (ldb_attr_cmp(msg->elements[i].name, attr) == 0) {
1537 58724208 : ++num_del;
1538 28793850928 : } else if (num_del) {
1539 113834449 : msg->elements[i - num_del] = msg->elements[i];
1540 : }
1541 : }
1542 :
1543 2593305259 : msg->num_elements -= num_del;
1544 2593305259 : }
1545 :
1546 : /* Reallocate elements to drop any excess capacity. */
1547 169739669 : void ldb_msg_shrink_to_fit(struct ldb_message *msg)
1548 : {
1549 169739669 : if (msg->num_elements > 0) {
1550 150006978 : struct ldb_message_element *elements = talloc_realloc(msg,
1551 : msg->elements,
1552 : struct ldb_message_element,
1553 : msg->num_elements);
1554 150006978 : if (elements != NULL) {
1555 150006978 : msg->elements = elements;
1556 : }
1557 : } else {
1558 19732691 : TALLOC_FREE(msg->elements);
1559 : }
1560 169739669 : }
1561 :
1562 : /*
1563 : return a LDAP formatted GeneralizedTime string
1564 : */
1565 6539305 : char *ldb_timestring(TALLOC_CTX *mem_ctx, time_t t)
1566 : {
1567 6539305 : struct tm *tm = gmtime(&t);
1568 368486 : char *ts;
1569 368486 : int r;
1570 :
1571 6539305 : if (!tm) {
1572 3 : return NULL;
1573 : }
1574 :
1575 : /* we know exactly how long this string will be */
1576 6539302 : ts = talloc_array(mem_ctx, char, 18);
1577 :
1578 : /* formatted like: 20040408072012.0Z */
1579 6539302 : r = snprintf(ts, 18,
1580 : "%04u%02u%02u%02u%02u%02u.0Z",
1581 6539302 : tm->tm_year+1900, tm->tm_mon+1,
1582 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1583 : tm->tm_sec);
1584 :
1585 6539302 : if (r != 17) {
1586 6 : talloc_free(ts);
1587 6 : errno = EOVERFLOW;
1588 6 : return NULL;
1589 : }
1590 :
1591 6170810 : return ts;
1592 : }
1593 :
1594 : /*
1595 : convert a LDAP GeneralizedTime string to a time_t. Return 0 if unable to convert
1596 : */
1597 23271 : time_t ldb_string_to_time(const char *s)
1598 : {
1599 72 : struct tm tm;
1600 72 : time_t t;
1601 :
1602 23271 : if (s == NULL) return 0;
1603 :
1604 23245 : memset(&tm, 0, sizeof(tm));
1605 23245 : if (sscanf(s, "%04u%02u%02u%02u%02u%02u.0Z",
1606 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1607 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1608 0 : return 0;
1609 : }
1610 23245 : tm.tm_year -= 1900;
1611 23245 : tm.tm_mon -= 1;
1612 :
1613 23245 : t = timegm(&tm);
1614 :
1615 23245 : if (t == (time_t)-1 && errno != 0) {
1616 : /*
1617 : * timegm() returns -1 on error, but also for '19691231235959.0Z'.
1618 : */
1619 0 : return 0;
1620 : }
1621 23173 : return t;
1622 : }
1623 :
1624 : /*
1625 : convert a LDAP GeneralizedTime string in ldb_val format to a
1626 : time_t.
1627 : */
1628 4707693 : int ldb_val_to_time(const struct ldb_val *v, time_t *t)
1629 : {
1630 4707693 : char val[15] = {0};
1631 4707693 : struct tm tm = {
1632 : .tm_year = 0,
1633 : };
1634 :
1635 4707693 : if (v == NULL) {
1636 160 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1637 : }
1638 :
1639 4707533 : if (v->data == NULL) {
1640 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1641 : }
1642 :
1643 4707533 : if (v->length < 16 && v->length != 13) {
1644 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1645 : }
1646 :
1647 4707533 : if (v->data[v->length - 1] != 'Z') {
1648 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1649 : }
1650 :
1651 4707533 : if (v->length == 13) {
1652 526 : memcpy(val, v->data, 12);
1653 :
1654 526 : if (sscanf(val, "%02u%02u%02u%02u%02u%02u",
1655 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1656 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1657 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1658 : }
1659 526 : if (tm.tm_year < 50) {
1660 526 : tm.tm_year += 100;
1661 : }
1662 : } else {
1663 :
1664 : /*
1665 : * anything between '.' and 'Z' is silently ignored.
1666 : */
1667 4707007 : if (v->data[14] != '.') {
1668 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1669 : }
1670 :
1671 4707007 : memcpy(val, v->data, 14);
1672 :
1673 4707007 : if (sscanf(val, "%04u%02u%02u%02u%02u%02u",
1674 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1675 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1676 0 : return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
1677 : }
1678 4707007 : tm.tm_year -= 1900;
1679 : }
1680 4707533 : tm.tm_mon -= 1;
1681 :
1682 4707533 : *t = timegm(&tm);
1683 :
1684 4707533 : return LDB_SUCCESS;
1685 : }
1686 :
1687 : /*
1688 : return a LDAP formatted UTCTime string
1689 : */
1690 62 : char *ldb_timestring_utc(TALLOC_CTX *mem_ctx, time_t t)
1691 : {
1692 62 : struct tm *tm = gmtime(&t);
1693 3 : char *ts;
1694 3 : int r;
1695 :
1696 62 : if (!tm) {
1697 0 : return NULL;
1698 : }
1699 :
1700 : /* we know exactly how long this string will be */
1701 62 : ts = talloc_array(mem_ctx, char, 14);
1702 :
1703 : /* formatted like: 20040408072012.0Z => 040408072012Z */
1704 62 : r = snprintf(ts, 14,
1705 : "%02u%02u%02u%02u%02u%02uZ",
1706 62 : (tm->tm_year+1900)%100, tm->tm_mon+1,
1707 : tm->tm_mday, tm->tm_hour, tm->tm_min,
1708 : tm->tm_sec);
1709 :
1710 62 : if (r != 13) {
1711 0 : talloc_free(ts);
1712 0 : return NULL;
1713 : }
1714 :
1715 59 : return ts;
1716 : }
1717 :
1718 : /*
1719 : convert a LDAP UTCTime string to a time_t. Return 0 if unable to convert
1720 : */
1721 0 : time_t ldb_string_utc_to_time(const char *s)
1722 : {
1723 0 : struct tm tm;
1724 :
1725 0 : if (s == NULL) return 0;
1726 :
1727 0 : memset(&tm, 0, sizeof(tm));
1728 0 : if (sscanf(s, "%02u%02u%02u%02u%02u%02uZ",
1729 : &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
1730 : &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
1731 0 : return 0;
1732 : }
1733 0 : if (tm.tm_year < 50) {
1734 0 : tm.tm_year += 100;
1735 : }
1736 0 : tm.tm_mon -= 1;
1737 :
1738 0 : return timegm(&tm);
1739 : }
1740 :
1741 :
1742 : /*
1743 : dump a set of results to a file. Useful from within gdb
1744 : */
1745 0 : void ldb_dump_results(struct ldb_context *ldb, struct ldb_result *result, FILE *f)
1746 : {
1747 0 : unsigned int i;
1748 :
1749 0 : for (i = 0; i < result->count; i++) {
1750 0 : struct ldb_ldif ldif;
1751 0 : fprintf(f, "# record %d\n", i+1);
1752 0 : ldif.changetype = LDB_CHANGETYPE_NONE;
1753 0 : ldif.msg = result->msgs[i];
1754 0 : ldb_ldif_write_file(ldb, f, &ldif);
1755 : }
1756 0 : }
1757 :
1758 : /*
1759 : checks for a string attribute. Returns "1" on match and otherwise "0".
1760 : */
1761 3336670 : int ldb_msg_check_string_attribute(const struct ldb_message *msg,
1762 : const char *name, const char *value)
1763 : {
1764 44911 : struct ldb_message_element *el;
1765 44911 : struct ldb_val val;
1766 :
1767 3336670 : el = ldb_msg_find_element(msg, name);
1768 3336670 : if (el == NULL) {
1769 1616103 : return 0;
1770 : }
1771 :
1772 1696664 : val.data = discard_const_p(uint8_t, value);
1773 1696664 : val.length = strlen(value);
1774 :
1775 1696664 : if (ldb_msg_find_val(el, &val)) {
1776 1695867 : return 1;
1777 : }
1778 :
1779 797 : return 0;
1780 : }
1781 :
1782 :
1783 : /*
1784 : compare a ldb_val to a string
1785 : */
1786 3379985 : int ldb_val_string_cmp(const struct ldb_val *v, const char *str)
1787 : {
1788 3379985 : size_t len = strlen(str);
1789 3379985 : if (len != v->length) {
1790 0 : return len - v->length;
1791 : }
1792 3379985 : return strncmp((const char *)v->data, str, len);
1793 : }
|