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 pack/unpack
28 : *
29 : * Description: pack/unpack routines for ldb messages as key/value blobs
30 : *
31 : * Author: Andrew Tridgell
32 : */
33 :
34 : #include "ldb_private.h"
35 :
36 : /*
37 : * These macros are from byte_array.h via libssh
38 : * TODO: This will be replaced with use of the byte_array.h header when it
39 : * becomes available.
40 : *
41 : * Macros for handling integer types in byte arrays
42 : *
43 : * This file is originally from the libssh.org project
44 : *
45 : * Copyright (c) 2018 Andreas Schneider <asn@cryptomilk.org>
46 : *
47 : * This library is free software; you can redistribute it and/or
48 : * modify it under the terms of the GNU Lesser General Public
49 : * License as published by the Free Software Foundation; either
50 : * version 2.1 of the License, or (at your option) any later version.
51 : *
52 : * This library is distributed in the hope that it will be useful,
53 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
54 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
55 : * Lesser General Public License for more details.
56 : *
57 : * You should have received a copy of the GNU Lesser General Public
58 : * License along with this library; if not, write to the Free Software
59 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
60 : */
61 : #define _DATA_BYTE_CONST(data, pos) \
62 : ((uint8_t)(((const uint8_t *)(data))[(pos)]))
63 : #define PULL_LE_U8(data, pos) \
64 : (_DATA_BYTE_CONST(data, pos))
65 : #define PULL_LE_U16(data, pos) \
66 : ((uint16_t)PULL_LE_U8(data, pos) |\
67 : ((uint16_t)(PULL_LE_U8(data, (pos) + 1))) << 8)
68 : #define PULL_LE_U32(data, pos) \
69 : ((uint32_t)(PULL_LE_U16(data, pos) |\
70 : ((uint32_t)PULL_LE_U16(data, (pos) + 2)) << 16))
71 :
72 : #define _DATA_BYTE(data, pos) \
73 : (((uint8_t *)(data))[(pos)])
74 : #define PUSH_LE_U8(data, pos, val) \
75 : (_DATA_BYTE(data, pos) = ((uint8_t)(val)))
76 : #define PUSH_LE_U16(data, pos, val) \
77 : (PUSH_LE_U8((data), (pos), (uint8_t)((uint16_t)(val) & 0xff)),\
78 : PUSH_LE_U8((data), (pos) + 1,\
79 : (uint8_t)((uint16_t)(val) >> 8)))
80 : #define PUSH_LE_U32(data, pos, val) \
81 : (PUSH_LE_U16((data), (pos), (uint16_t)((uint32_t)(val) & 0xffff)),\
82 : PUSH_LE_U16((data), (pos) + 2, (uint16_t)((uint32_t)(val) >> 16)))
83 :
84 : #define U32_LEN 4
85 : #define U16_LEN 2
86 : #define U8_LEN 1
87 : #define NULL_PAD_BYTE_LEN 1
88 :
89 287393004 : static int attribute_storable_values(const struct ldb_message_element *el)
90 : {
91 287393004 : if (el->num_values == 0) return 0;
92 :
93 287393004 : if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
94 :
95 282955941 : return el->num_values;
96 : }
97 :
98 7238554 : static int ldb_pack_data_v1(struct ldb_context *ldb,
99 : const struct ldb_message *message,
100 : struct ldb_val *data)
101 : {
102 7238554 : unsigned int i, j, real_elements=0;
103 823563 : size_t size, dn_len, attr_len, value_len;
104 823563 : const char *dn;
105 823563 : uint8_t *p;
106 823563 : size_t len;
107 :
108 7238554 : dn = ldb_dn_get_linearized(message->dn);
109 7238554 : if (dn == NULL) {
110 0 : errno = ENOMEM;
111 0 : return -1;
112 : }
113 :
114 : /* work out how big it needs to be */
115 7238554 : size = U32_LEN * 2 + NULL_PAD_BYTE_LEN;
116 :
117 7238554 : dn_len = strlen(dn);
118 7238554 : if (size + dn_len < size) {
119 0 : errno = ENOMEM;
120 0 : return -1;
121 : }
122 6414991 : size += dn_len;
123 :
124 : /*
125 : * First calculate the buffer size we need, and check for
126 : * overflows
127 : */
128 41588806 : for (i=0;i<message->num_elements;i++) {
129 34350252 : if (attribute_storable_values(&message->elements[i]) == 0) {
130 3442 : continue;
131 : }
132 :
133 34346810 : real_elements++;
134 :
135 34346810 : if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) {
136 0 : errno = ENOMEM;
137 0 : return -1;
138 : }
139 34346810 : size += U32_LEN + NULL_PAD_BYTE_LEN;
140 :
141 34346810 : attr_len = strlen(message->elements[i].name);
142 34346810 : if (size + attr_len < size) {
143 0 : errno = ENOMEM;
144 0 : return -1;
145 : }
146 30604486 : size += attr_len;
147 :
148 73657109 : for (j=0;j<message->elements[i].num_values;j++) {
149 39310299 : if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) {
150 0 : errno = ENOMEM;
151 0 : return -1;
152 : }
153 39310299 : size += U32_LEN + NULL_PAD_BYTE_LEN;
154 :
155 39310299 : value_len = message->elements[i].values[j].length;
156 39310299 : if (size + value_len < size) {
157 0 : errno = ENOMEM;
158 0 : return -1;
159 : }
160 39310299 : size += value_len;
161 : }
162 : }
163 :
164 : /* allocate it */
165 7238554 : data->data = talloc_array(ldb, uint8_t, size);
166 7238554 : if (!data->data) {
167 0 : errno = ENOMEM;
168 0 : return -1;
169 : }
170 7238554 : data->length = size;
171 :
172 7238554 : p = data->data;
173 7238554 : PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT);
174 7238554 : p += U32_LEN;
175 7238554 : PUSH_LE_U32(p, 0, real_elements);
176 7238554 : p += U32_LEN;
177 :
178 : /* the dn needs to be packed so we can be case preserving
179 : while hashing on a case folded dn */
180 7238554 : len = dn_len;
181 7238554 : memcpy(p, dn, len+NULL_PAD_BYTE_LEN);
182 7238554 : p += len + NULL_PAD_BYTE_LEN;
183 :
184 41588806 : for (i=0;i<message->num_elements;i++) {
185 34350252 : if (attribute_storable_values(&message->elements[i]) == 0) {
186 3442 : continue;
187 : }
188 34346810 : len = strlen(message->elements[i].name);
189 34346810 : memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN);
190 34346810 : p += len + NULL_PAD_BYTE_LEN;
191 34346810 : PUSH_LE_U32(p, 0, message->elements[i].num_values);
192 34346810 : p += U32_LEN;
193 73657109 : for (j=0;j<message->elements[i].num_values;j++) {
194 39310299 : PUSH_LE_U32(p, 0,
195 : message->elements[i].values[j].length);
196 39310299 : p += U32_LEN;
197 39310299 : memcpy(p, message->elements[i].values[j].data,
198 39310299 : message->elements[i].values[j].length);
199 39310299 : p[message->elements[i].values[j].length] = 0;
200 39310299 : p += message->elements[i].values[j].length +
201 : NULL_PAD_BYTE_LEN;
202 : }
203 : }
204 :
205 6414991 : return 0;
206 : }
207 :
208 : /*
209 : * New pack version designed based on performance profiling of version 1.
210 : * The approach is to separate value data from the rest of the record's data.
211 : * This improves performance because value data is not needed during unpacking
212 : * or filtering of the message's attribute list. During filtering we only copy
213 : * attributes which are present in the attribute list, however at the parse
214 : * stage we need to point to all attributes as they may be referenced in the
215 : * search expression.
216 : * With this new format, we don't lose time loading data (eg via
217 : * talloc_memdup()) that is never needed (for the vast majority of attributes
218 : * are are never found in either the search expression or attribute list).
219 : * Additional changes include adding a canonicalized DN (for later
220 : * optimizations) and variable width length fields for faster unpacking.
221 : * The pack and unpack performance improvement is tested in the torture
222 : * test torture_ldb_pack_format_perf.
223 : *
224 : * Layout:
225 : *
226 : * Version (4 bytes)
227 : * Number of Elements (4 bytes)
228 : * DN length (4 bytes)
229 : * DN with null terminator (DN length + 1 bytes)
230 : * Canonicalized DN length (4 bytes)
231 : * Canonicalized DN with null terminator (Canonicalized DN length + 1 bytes)
232 : * Number of bytes from here to value data section (4 bytes)
233 : * # For each element:
234 : * Element name length (4 bytes)
235 : * Element name with null terminator (Element name length + 1 bytes)
236 : * Number of values (4 bytes)
237 : * Width of value lengths
238 : * # For each value:
239 : * Value data length (#bytes given by width field above)
240 : * # For each element:
241 : * # For each value:
242 : * Value data (#bytes given by corresponding length above)
243 : */
244 14735493 : static int ldb_pack_data_v2(struct ldb_context *ldb,
245 : const struct ldb_message *message,
246 : struct ldb_val *data)
247 : {
248 14735493 : unsigned int i, j, real_elements=0;
249 850594 : size_t size, dn_len, dn_canon_len, attr_len, value_len;
250 850594 : const char *dn, *dn_canon;
251 850594 : uint8_t *p, *q;
252 850594 : size_t len;
253 850594 : size_t max_val_len;
254 850594 : uint8_t val_len_width;
255 :
256 : /*
257 : * First half of this function will calculate required size for
258 : * packed data. Initial size is 20 = 5 * 4. 5 fixed fields are:
259 : * version, num elements, dn len, canon dn len, attr section len
260 : */
261 14735493 : size = U32_LEN * 5;
262 :
263 : /*
264 : * Get linearized and canonicalized form of the DN and add the lengths
265 : * of each to size, plus 1 for null terminator.
266 : */
267 14735493 : dn = ldb_dn_get_linearized(message->dn);
268 14735493 : if (dn == NULL) {
269 0 : errno = ENOMEM;
270 0 : return -1;
271 : }
272 :
273 14735493 : dn_len = strlen(dn) + NULL_PAD_BYTE_LEN;
274 14735493 : if (size + dn_len < size) {
275 0 : errno = ENOMEM;
276 0 : return -1;
277 : }
278 14735493 : size += dn_len;
279 :
280 14735493 : if (ldb_dn_is_special(message->dn)) {
281 11767374 : dn_canon_len = NULL_PAD_BYTE_LEN;
282 11767374 : dn_canon = discard_const_p(char, "\0");
283 : } else {
284 2254034 : dn_canon = ldb_dn_canonical_string(message->dn, message->dn);
285 2254034 : if (dn_canon == NULL) {
286 0 : errno = ENOMEM;
287 0 : return -1;
288 : }
289 :
290 2254034 : dn_canon_len = strlen(dn_canon) + NULL_PAD_BYTE_LEN;
291 2254034 : if (size + dn_canon_len < size) {
292 0 : errno = ENOMEM;
293 0 : return -1;
294 : }
295 : }
296 14735493 : size += dn_canon_len;
297 :
298 : /* Add the size required by each element */
299 87632993 : for (i=0;i<message->num_elements;i++) {
300 72897500 : if (attribute_storable_values(&message->elements[i]) == 0) {
301 2132 : continue;
302 : }
303 :
304 72895368 : real_elements++;
305 :
306 : /*
307 : * Add length of element name + 9 for:
308 : * 1 for null terminator
309 : * 4 for element name length field
310 : * 4 for number of values field
311 : */
312 72895368 : attr_len = strlen(message->elements[i].name);
313 72895368 : if (size + attr_len + U32_LEN * 2 + NULL_PAD_BYTE_LEN < size) {
314 0 : errno = ENOMEM;
315 0 : return -1;
316 : }
317 68471585 : size += attr_len + U32_LEN * 2 + NULL_PAD_BYTE_LEN;
318 :
319 : /*
320 : * Find the max value length, so we can calculate the width
321 : * required for the value length fields.
322 : */
323 68471585 : max_val_len = 0;
324 167217060 : for (j=0;j<message->elements[i].num_values;j++) {
325 94321692 : value_len = message->elements[i].values[j].length;
326 94321692 : if (value_len > max_val_len) {
327 71456214 : max_val_len = value_len;
328 : }
329 :
330 94321692 : if (size + value_len + NULL_PAD_BYTE_LEN < size) {
331 0 : errno = ENOMEM;
332 0 : return -1;
333 : }
334 94321692 : size += value_len + NULL_PAD_BYTE_LEN;
335 : }
336 :
337 72895368 : if (max_val_len <= UCHAR_MAX) {
338 64025342 : val_len_width = U8_LEN;
339 4613353 : } else if (max_val_len <= USHRT_MAX) {
340 4414479 : val_len_width = U16_LEN;
341 31764 : } else if (max_val_len <= UINT_MAX) {
342 31764 : val_len_width = U32_LEN;
343 : } else {
344 0 : errno = EMSGSIZE;
345 0 : return -1;
346 : }
347 :
348 : /* Total size required for val lengths (re-using variable) */
349 72895368 : max_val_len = (val_len_width*message->elements[i].num_values);
350 :
351 : /* Add one for storing the width */
352 72895368 : max_val_len += U8_LEN;
353 72895368 : if (size + max_val_len < size) {
354 0 : errno = ENOMEM;
355 0 : return -1;
356 : }
357 68471585 : size += max_val_len;
358 : }
359 :
360 : /* Allocate */
361 14735493 : data->data = talloc_array(ldb, uint8_t, size);
362 14735493 : if (!data->data) {
363 0 : errno = ENOMEM;
364 0 : return -1;
365 : }
366 14735493 : data->length = size;
367 :
368 : /* Packing format version and number of element */
369 14735493 : p = data->data;
370 14735493 : PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT_V2);
371 14735493 : p += U32_LEN;
372 14735493 : PUSH_LE_U32(p, 0, real_elements);
373 14735493 : p += U32_LEN;
374 :
375 : /* Pack DN and Canonicalized DN */
376 14735493 : PUSH_LE_U32(p, 0, dn_len-NULL_PAD_BYTE_LEN);
377 14735493 : p += U32_LEN;
378 14735493 : memcpy(p, dn, dn_len);
379 14735493 : p += dn_len;
380 :
381 14735493 : PUSH_LE_U32(p, 0, dn_canon_len-NULL_PAD_BYTE_LEN);
382 14735493 : p += U32_LEN;
383 14735493 : memcpy(p, dn_canon, dn_canon_len);
384 14735493 : p += dn_canon_len;
385 :
386 : /*
387 : * Save pointer at this point and leave a U32_LEN gap for
388 : * storing the size of the attribute names and value lengths
389 : * section
390 : */
391 14735493 : q = p;
392 14735493 : p += U32_LEN;
393 :
394 87632993 : for (i=0;i<message->num_elements;i++) {
395 72897500 : if (attribute_storable_values(&message->elements[i]) == 0) {
396 2132 : continue;
397 : }
398 :
399 : /* Length of el name */
400 72895368 : len = strlen(message->elements[i].name);
401 72895368 : PUSH_LE_U32(p, 0, len);
402 72895368 : p += U32_LEN;
403 :
404 : /*
405 : * Even though we have the element name's length, put a null
406 : * terminator at the end so if any code uses the name
407 : * directly, it'll be safe to do things requiring null
408 : * termination like strlen
409 : */
410 72895368 : memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN);
411 72895368 : p += len + NULL_PAD_BYTE_LEN;
412 : /* Num values */
413 72895368 : PUSH_LE_U32(p, 0, message->elements[i].num_values);
414 72895368 : p += U32_LEN;
415 :
416 : /*
417 : * Calculate value length width again. It's faster to
418 : * calculate it again than do the array management to
419 : * store the result during size calculation.
420 : */
421 72895368 : max_val_len = 0;
422 167217060 : for (j=0;j<message->elements[i].num_values;j++) {
423 94321692 : value_len = message->elements[i].values[j].length;
424 94321692 : if (value_len > max_val_len) {
425 71456214 : max_val_len = value_len;
426 : }
427 : }
428 :
429 72895368 : if (max_val_len <= UCHAR_MAX) {
430 64025342 : val_len_width = U8_LEN;
431 4613353 : } else if (max_val_len <= USHRT_MAX) {
432 4414479 : val_len_width = U16_LEN;
433 31764 : } else if (max_val_len <= UINT_MAX) {
434 31764 : val_len_width = U32_LEN;
435 : } else {
436 0 : errno = EMSGSIZE;
437 0 : return -1;
438 : }
439 :
440 : /* Pack the width */
441 72895368 : *p = val_len_width & 0xFF;
442 72895368 : p += U8_LEN;
443 :
444 : /*
445 : * Pack each value's length using the minimum number of bytes
446 : * required, which we just calculated. We repeat the loop
447 : * for each case here so the compiler can inline code.
448 : */
449 72895368 : if (val_len_width == U8_LEN) {
450 154887937 : for (j=0;j<message->elements[i].num_values;j++) {
451 86605922 : PUSH_LE_U8(p, 0,
452 : message->elements[i].values[j].length);
453 86605922 : p += U8_LEN;
454 : }
455 4613353 : } else if (val_len_width == U16_LEN) {
456 12265595 : for (j=0;j<message->elements[i].num_values;j++) {
457 7684006 : PUSH_LE_U16(p, 0,
458 : message->elements[i].values[j].length);
459 7684006 : p += U16_LEN;
460 : }
461 31764 : } else if (val_len_width == U32_LEN) {
462 63528 : for (j=0;j<message->elements[i].num_values;j++) {
463 31764 : PUSH_LE_U32(p, 0,
464 : message->elements[i].values[j].length);
465 31764 : p += U32_LEN;
466 : }
467 : }
468 : }
469 :
470 : /*
471 : * We've finished packing the attr names and value lengths
472 : * section, so store the size in the U32_LEN gap we left
473 : * earlier
474 : */
475 14735493 : PUSH_LE_U32(q, 0, p-q);
476 :
477 : /* Now pack the values */
478 87632993 : for (i=0;i<message->num_elements;i++) {
479 72897500 : if (attribute_storable_values(&message->elements[i]) == 0) {
480 2132 : continue;
481 : }
482 167217060 : for (j=0;j<message->elements[i].num_values;j++) {
483 94321692 : memcpy(p, message->elements[i].values[j].data,
484 94321692 : message->elements[i].values[j].length);
485 :
486 : /*
487 : * Even though we have the data length, put a null
488 : * terminator at the end of each value's data so if
489 : * any code uses the data directly, it'll be safe to
490 : * do things requiring null termination like strlen.
491 : */
492 94321692 : p[message->elements[i].values[j].length] = 0;
493 94321692 : p += message->elements[i].values[j].length +
494 : NULL_PAD_BYTE_LEN;
495 : }
496 : }
497 :
498 : /*
499 : * If we didn't end up at the end of the data here, something has
500 : * gone very wrong.
501 : */
502 14735493 : if (p != data->data + size) {
503 0 : errno = ENOMEM;
504 0 : return -1;
505 : }
506 :
507 13884899 : return 0;
508 : }
509 :
510 : /*
511 : pack a ldb message into a linear buffer in a ldb_val
512 :
513 : note that this routine avoids saving elements with zero values,
514 : as these are equivalent to having no element
515 :
516 : caller frees the data buffer after use
517 : */
518 21974047 : int ldb_pack_data(struct ldb_context *ldb,
519 : const struct ldb_message *message,
520 : struct ldb_val *data,
521 : uint32_t pack_format_version) {
522 :
523 21974047 : if (pack_format_version == LDB_PACKING_FORMAT) {
524 7238554 : return ldb_pack_data_v1(ldb, message, data);
525 14735493 : } else if (pack_format_version == LDB_PACKING_FORMAT_V2) {
526 14735493 : return ldb_pack_data_v2(ldb, message, data);
527 : } else {
528 0 : errno = EINVAL;
529 0 : return -1;
530 : }
531 : }
532 :
533 : /*
534 : * Unpack a ldb message from a linear buffer in ldb_val
535 : */
536 36424100 : static int ldb_unpack_data_flags_v1(struct ldb_context *ldb,
537 : const struct ldb_val *data,
538 : struct ldb_message *message,
539 : unsigned int flags,
540 : unsigned format)
541 : {
542 2434700 : uint8_t *p;
543 2434700 : size_t remaining;
544 2434700 : size_t dn_len;
545 2434700 : unsigned int i, j;
546 36424100 : unsigned int nelem = 0;
547 2434700 : size_t len;
548 36424100 : struct ldb_val *ldb_val_single_array = NULL;
549 :
550 36424100 : message->elements = NULL;
551 :
552 36424100 : p = data->data;
553 :
554 : /* Format (U32, already read) + U32 for num_elements */
555 36424100 : if (data->length < U32_LEN * 2) {
556 0 : errno = EIO;
557 0 : goto failed;
558 : }
559 :
560 : /* Skip first 4 bytes, format already read */
561 36424100 : p += U32_LEN;
562 36424100 : message->num_elements = PULL_LE_U32(p, 0);
563 36424100 : p += U32_LEN;
564 :
565 36424100 : remaining = data->length - U32_LEN * 2;
566 :
567 36424100 : switch (format) {
568 0 : case LDB_PACKING_FORMAT_NODN:
569 0 : message->dn = NULL;
570 0 : break;
571 :
572 36424096 : case LDB_PACKING_FORMAT:
573 : /*
574 : * With this check, we know that the DN at p is \0
575 : * terminated.
576 : */
577 36424096 : dn_len = strnlen((char *)p, remaining);
578 36424096 : if (dn_len == remaining) {
579 0 : errno = EIO;
580 0 : goto failed;
581 : }
582 36424096 : if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
583 1205133 : message->dn = NULL;
584 : } else {
585 2357216 : struct ldb_val blob;
586 35218963 : blob.data = discard_const_p(uint8_t, p);
587 35218963 : blob.length = dn_len;
588 35218963 : message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
589 35218963 : if (message->dn == NULL) {
590 0 : errno = ENOMEM;
591 0 : goto failed;
592 : }
593 : }
594 : /*
595 : * Redundant: by definition, remaining must be more
596 : * than one less than dn_len, as otherwise it would be
597 : * == dn_len
598 : */
599 36424096 : if (remaining < dn_len + NULL_PAD_BYTE_LEN) {
600 0 : errno = EIO;
601 0 : goto failed;
602 : }
603 36424096 : remaining -= dn_len + NULL_PAD_BYTE_LEN;
604 36424096 : p += dn_len + NULL_PAD_BYTE_LEN;
605 36424096 : break;
606 :
607 4 : default:
608 4 : errno = EIO;
609 4 : goto failed;
610 : }
611 :
612 36424096 : if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
613 9594427 : message->num_elements = 0;
614 9594427 : return 0;
615 : }
616 :
617 26829669 : if (message->num_elements == 0) {
618 66 : return 0;
619 : }
620 :
621 26829591 : if (message->num_elements > remaining / 6) {
622 0 : errno = EIO;
623 0 : goto failed;
624 : }
625 :
626 26829591 : message->elements = talloc_zero_array(message, struct ldb_message_element,
627 : message->num_elements);
628 26829591 : if (!message->elements) {
629 0 : errno = ENOMEM;
630 0 : goto failed;
631 : }
632 :
633 : /*
634 : * In typical use, most values are single-valued. This makes
635 : * it quite expensive to allocate an array of ldb_val for each
636 : * of these, just to then hold the pointer to the data buffer
637 : * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
638 : * ahead of time and use it for the single values where possible.
639 : * (This is used the the normal search case, but not in the
640 : * index case because of caller requirements).
641 : */
642 26829591 : if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
643 13778812 : ldb_val_single_array = talloc_array(message->elements, struct ldb_val,
644 : message->num_elements);
645 13778812 : if (ldb_val_single_array == NULL) {
646 0 : errno = ENOMEM;
647 0 : goto failed;
648 : }
649 : }
650 :
651 291916861 : for (i=0;i<message->num_elements;i++) {
652 265087270 : const char *attr = NULL;
653 20556004 : size_t attr_len;
654 265087270 : struct ldb_message_element *element = NULL;
655 :
656 : /*
657 : * Sanity check: Element must be at least the size of empty
658 : * attr name and value and NULL terms for each.
659 : */
660 265087270 : if (remaining < U32_LEN * 2 + NULL_PAD_BYTE_LEN * 2) {
661 0 : errno = EIO;
662 0 : goto failed;
663 : }
664 :
665 : /*
666 : * With this check, we know that the attribute name at
667 : * p is \0 terminated.
668 : */
669 265087270 : attr_len = strnlen((char *)p, remaining-6);
670 265087270 : if (attr_len == remaining-6) {
671 0 : errno = EIO;
672 0 : goto failed;
673 : }
674 265087270 : if (attr_len == 0) {
675 0 : errno = EIO;
676 0 : goto failed;
677 : }
678 265087270 : attr = (char *)p;
679 :
680 265087270 : element = &message->elements[nelem];
681 265087270 : element->name = attr;
682 265087270 : element->flags = 0;
683 :
684 265087270 : if (remaining < (attr_len + NULL_PAD_BYTE_LEN)) {
685 0 : errno = EIO;
686 0 : goto failed;
687 : }
688 265087270 : remaining -= attr_len + NULL_PAD_BYTE_LEN;
689 265087270 : p += attr_len + NULL_PAD_BYTE_LEN;
690 265087270 : element->num_values = PULL_LE_U32(p, 0);
691 265087270 : element->values = NULL;
692 265087270 : if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
693 191524967 : element->values = &ldb_val_single_array[nelem];
694 191524967 : element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
695 73562303 : } else if (element->num_values != 0) {
696 73562303 : element->values = talloc_array(message->elements,
697 : struct ldb_val,
698 : element->num_values);
699 73562303 : if (!element->values) {
700 0 : errno = ENOMEM;
701 0 : goto failed;
702 : }
703 : }
704 265087270 : p += U32_LEN;
705 265087270 : if (remaining < U32_LEN) {
706 0 : errno = EIO;
707 0 : goto failed;
708 : }
709 265087270 : remaining -= U32_LEN;
710 584161264 : for (j = 0; j < element->num_values; j++) {
711 : /*
712 : * Sanity check: Value must be at least the size of
713 : * empty val and NULL terminator.
714 : */
715 319073994 : if (remaining < U32_LEN + NULL_PAD_BYTE_LEN) {
716 0 : errno = EIO;
717 0 : goto failed;
718 : }
719 319073994 : remaining -= U32_LEN + NULL_PAD_BYTE_LEN;
720 :
721 319073994 : len = PULL_LE_U32(p, 0);
722 319073994 : if (remaining < len) {
723 0 : errno = EIO;
724 0 : goto failed;
725 : }
726 319073994 : if (len + NULL_PAD_BYTE_LEN < len) {
727 0 : errno = EIO;
728 0 : goto failed;
729 : }
730 :
731 319073994 : element->values[j].length = len;
732 319073994 : element->values[j].data = p + U32_LEN;
733 319073994 : remaining -= len;
734 319073994 : p += len + U32_LEN + NULL_PAD_BYTE_LEN;
735 : }
736 265087270 : nelem++;
737 : }
738 : /*
739 : * Adapt the number of elements to the real number of unpacked elements,
740 : * it means that we overallocated elements array.
741 : */
742 26829591 : message->num_elements = nelem;
743 :
744 : /*
745 : * Shrink the allocated size. On current talloc behaviour
746 : * this will help if we skipped 32 or more attributes.
747 : */
748 26829591 : message->elements = talloc_realloc(message, message->elements,
749 : struct ldb_message_element,
750 : message->num_elements);
751 :
752 26829591 : if (remaining != 0) {
753 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
754 : "Error: %zu bytes unread in ldb_unpack_data_flags",
755 : remaining);
756 : }
757 :
758 24560401 : return 0;
759 :
760 4 : failed:
761 4 : talloc_free(message->elements);
762 4 : return -1;
763 : }
764 :
765 : /*
766 : * Unpack a ldb message from a linear buffer in ldb_val
767 : */
768 619914861 : static int ldb_unpack_data_flags_v2(struct ldb_context *ldb,
769 : const struct ldb_val *data,
770 : struct ldb_message *message,
771 : unsigned int flags)
772 : {
773 11731300 : uint8_t *p, *q, *end_p, *value_section_p;
774 11731300 : unsigned int i, j;
775 619914861 : unsigned int nelem = 0;
776 11731300 : size_t len;
777 619914861 : struct ldb_val *ldb_val_single_array = NULL;
778 11731300 : uint8_t val_len_width;
779 :
780 619914861 : message->elements = NULL;
781 :
782 619914861 : p = data->data;
783 619914861 : end_p = p + data->length;
784 :
785 : /* Skip first 4 bytes, format already read */
786 619914861 : p += U32_LEN;
787 :
788 : /* First fields are fixed: num_elements, DN length */
789 619914861 : if (U32_LEN * 2 > end_p - p) {
790 0 : errno = EIO;
791 0 : goto failed;
792 : }
793 :
794 619914861 : message->num_elements = PULL_LE_U32(p, 0);
795 619914861 : p += U32_LEN;
796 :
797 619914861 : len = PULL_LE_U32(p, 0);
798 619914861 : p += U32_LEN;
799 :
800 619914861 : if (len + NULL_PAD_BYTE_LEN > end_p - p) {
801 3 : errno = EIO;
802 3 : goto failed;
803 : }
804 :
805 619914858 : if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
806 143673856 : message->dn = NULL;
807 : } else {
808 8862198 : struct ldb_val blob;
809 476241002 : blob.data = discard_const_p(uint8_t, p);
810 476241002 : blob.length = len;
811 476241002 : message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
812 476241002 : if (message->dn == NULL) {
813 1 : errno = ENOMEM;
814 1 : goto failed;
815 : }
816 : }
817 :
818 619914857 : p += len + NULL_PAD_BYTE_LEN;
819 :
820 619914857 : if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
821 1 : errno = EINVAL;
822 1 : goto failed;
823 : }
824 :
825 : /* Now skip the canonicalized DN and its length */
826 619914856 : len = PULL_LE_U32(p, 0) + NULL_PAD_BYTE_LEN;
827 619914856 : p += U32_LEN;
828 :
829 619914856 : if (len > end_p - p) {
830 3 : errno = EIO;
831 3 : goto failed;
832 : }
833 :
834 619914853 : p += len;
835 :
836 619914853 : if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
837 2 : errno = EINVAL;
838 2 : goto failed;
839 : }
840 :
841 619914851 : if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
842 116340269 : message->num_elements = 0;
843 116340269 : return 0;
844 : }
845 :
846 503574582 : if (message->num_elements == 0) {
847 61 : return 0;
848 : }
849 :
850 : /*
851 : * Sanity check (17 bytes is the minimum element size)
852 : */
853 503574521 : if (message->num_elements > (end_p - p) / 17) {
854 4 : errno = EIO;
855 4 : goto failed;
856 : }
857 :
858 503574517 : message->elements = talloc_zero_array(message,
859 : struct ldb_message_element,
860 : message->num_elements);
861 503574517 : if (!message->elements) {
862 0 : errno = ENOMEM;
863 0 : goto failed;
864 : }
865 :
866 : /*
867 : * In typical use, most values are single-valued. This makes
868 : * it quite expensive to allocate an array of ldb_val for each
869 : * of these, just to then hold the pointer to the data buffer.
870 : * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
871 : * ahead of time and use it for the single values where possible.
872 : * (This is used the the normal search case, but not in the
873 : * index case because of caller requirements).
874 : */
875 503574517 : if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
876 272447326 : ldb_val_single_array = talloc_array(message->elements,
877 : struct ldb_val,
878 : message->num_elements);
879 272447326 : if (ldb_val_single_array == NULL) {
880 0 : errno = ENOMEM;
881 0 : goto failed;
882 : }
883 : }
884 :
885 503574517 : q = p + PULL_LE_U32(p, 0);
886 503574517 : value_section_p = q;
887 503574517 : p += U32_LEN;
888 :
889 6796115039 : for (i=0;i<message->num_elements;i++) {
890 6292540534 : const char *attr = NULL;
891 111274346 : size_t attr_len;
892 6292540534 : struct ldb_message_element *element = NULL;
893 :
894 : /* Sanity check: minimum element size */
895 6292540534 : if ((U32_LEN * 2) + /* attr name len, num values */
896 : (U8_LEN * 2) + /* value length width, one val length */
897 : (NULL_PAD_BYTE_LEN * 2) /* null for attr name + val */
898 6292540534 : > value_section_p - p) {
899 0 : errno = EIO;
900 0 : goto failed;
901 : }
902 :
903 6292540534 : attr_len = PULL_LE_U32(p, 0);
904 6292540534 : p += U32_LEN;
905 :
906 6292540534 : if (attr_len == 0) {
907 0 : errno = EIO;
908 0 : goto failed;
909 : }
910 6292540534 : attr = (char *)p;
911 :
912 6292540534 : p += attr_len + NULL_PAD_BYTE_LEN;
913 : /*
914 : * num_values, val_len_width
915 : *
916 : * val_len_width is the width specifier
917 : * for the variable length encoding
918 : */
919 6292540534 : if (U32_LEN + U8_LEN > value_section_p - p) {
920 3 : errno = EIO;
921 3 : goto failed;
922 : }
923 :
924 6292540531 : if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
925 2 : errno = EINVAL;
926 2 : goto failed;
927 : }
928 :
929 6292540529 : element = &message->elements[nelem];
930 6292540529 : element->name = attr;
931 6292540529 : element->flags = 0;
932 :
933 6292540529 : element->num_values = PULL_LE_U32(p, 0);
934 6292540529 : element->values = NULL;
935 6292540529 : if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) &&
936 5671435238 : element->num_values == 1) {
937 5422967560 : element->values = &ldb_val_single_array[nelem];
938 5422967560 : element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
939 869572969 : } else if (element->num_values != 0) {
940 869572969 : element->values = talloc_array(message->elements,
941 : struct ldb_val,
942 : element->num_values);
943 869572969 : if (!element->values) {
944 1 : errno = ENOMEM;
945 1 : goto failed;
946 : }
947 : }
948 :
949 6292540528 : p += U32_LEN;
950 :
951 : /*
952 : * Here we read how wide the remaining lengths are
953 : * which avoids storing and parsing a lot of leading
954 : * 0s
955 : */
956 6292540528 : val_len_width = *p;
957 6292540528 : p += U8_LEN;
958 :
959 6292540528 : if (val_len_width * element->num_values >
960 6292540528 : value_section_p - p) {
961 4 : errno = EIO;
962 4 : goto failed;
963 : }
964 :
965 : /*
966 : * This is structured weird for compiler optimization
967 : * purposes, but we need to pull the array of widths
968 : * with different macros depending on how wide the
969 : * biggest one is (specified by val_len_width)
970 : */
971 6292540524 : if (val_len_width == U8_LEN) {
972 12518103542 : for (j = 0; j < element->num_values; j++) {
973 6673838197 : element->values[j].length = PULL_LE_U8(p, 0);
974 6673838197 : p += U8_LEN;
975 : }
976 448275179 : } else if (val_len_width == U16_LEN) {
977 963533103 : for (j = 0; j < element->num_values; j++) {
978 515317130 : element->values[j].length = PULL_LE_U16(p, 0);
979 515317130 : p += U16_LEN;
980 : }
981 59206 : } else if (val_len_width == U32_LEN) {
982 118412 : for (j = 0; j < element->num_values; j++) {
983 59206 : element->values[j].length = PULL_LE_U32(p, 0);
984 59206 : p += U32_LEN;
985 : }
986 : } else {
987 0 : errno = ERANGE;
988 0 : goto failed;
989 : }
990 :
991 13481755055 : for (j = 0; j < element->num_values; j++) {
992 7189214533 : len = element->values[j].length;
993 7189214533 : if (len + NULL_PAD_BYTE_LEN < len) {
994 0 : errno = EIO;
995 0 : goto failed;
996 : }
997 7189214533 : if (len + NULL_PAD_BYTE_LEN > end_p - q) {
998 2 : errno = EIO;
999 2 : goto failed;
1000 : }
1001 :
1002 7189214531 : element->values[j].data = q;
1003 7189214531 : q += len + NULL_PAD_BYTE_LEN;
1004 : }
1005 6292540522 : nelem++;
1006 : }
1007 :
1008 : /*
1009 : * If p isn't now pointing at the beginning of the value section,
1010 : * something went very wrong.
1011 : */
1012 503574505 : if (p != value_section_p) {
1013 3 : ldb_debug(ldb, LDB_DEBUG_ERROR,
1014 : "Error: Data corruption in ldb_unpack_data_flags");
1015 3 : errno = EIO;
1016 3 : goto failed;
1017 : }
1018 :
1019 : /*
1020 : * Adapt the number of elements to the real number of unpacked
1021 : * elements it means that we overallocated elements array.
1022 : */
1023 503574502 : message->num_elements = nelem;
1024 :
1025 : /*
1026 : * Shrink the allocated size. On current talloc behaviour
1027 : * this will help if we skipped 32 or more attributes.
1028 : */
1029 503574502 : message->elements = talloc_realloc(message, message->elements,
1030 : struct ldb_message_element,
1031 : message->num_elements);
1032 :
1033 503574502 : if (q != end_p) {
1034 0 : ldb_debug(ldb, LDB_DEBUG_ERROR,
1035 : "Error: %zu bytes unread in ldb_unpack_data_flags",
1036 : end_p - q);
1037 0 : errno = EIO;
1038 0 : goto failed;
1039 : }
1040 :
1041 494007464 : return 0;
1042 :
1043 29 : failed:
1044 29 : talloc_free(message->elements);
1045 29 : return -1;
1046 : }
1047 :
1048 57742759 : int ldb_unpack_get_format(const struct ldb_val *data,
1049 : uint32_t *pack_format_version)
1050 : {
1051 57742759 : if (data->length < U32_LEN) {
1052 0 : return LDB_ERR_OPERATIONS_ERROR;
1053 : }
1054 57742759 : *pack_format_version = PULL_LE_U32(data->data, 0);
1055 57742759 : return LDB_SUCCESS;
1056 : }
1057 :
1058 : /*
1059 : * Unpack a ldb message from a linear buffer in ldb_val
1060 : */
1061 656338961 : int ldb_unpack_data_flags(struct ldb_context *ldb,
1062 : const struct ldb_val *data,
1063 : struct ldb_message *message,
1064 : unsigned int flags)
1065 : {
1066 14166000 : unsigned format;
1067 :
1068 656338961 : if (data->length < U32_LEN) {
1069 0 : errno = EIO;
1070 0 : return -1;
1071 : }
1072 :
1073 656338961 : format = PULL_LE_U32(data->data, 0);
1074 656338961 : if (format == LDB_PACKING_FORMAT_V2) {
1075 619914861 : return ldb_unpack_data_flags_v2(ldb, data, message, flags);
1076 : }
1077 :
1078 : /*
1079 : * The v1 function we're about to call takes either LDB_PACKING_FORMAT
1080 : * or LDB_PACKING_FORMAT_NODN packing format versions, and will error
1081 : * if given some other version, so we don't need to do any further
1082 : * checks on 'format'.
1083 : */
1084 36424100 : return ldb_unpack_data_flags_v1(ldb, data, message, flags, format);
1085 : }
1086 :
1087 :
1088 : /*
1089 : * Unpack a ldb message from a linear buffer in ldb_val
1090 : *
1091 : * Free with ldb_unpack_data_free()
1092 : */
1093 7794233 : int ldb_unpack_data(struct ldb_context *ldb,
1094 : const struct ldb_val *data,
1095 : struct ldb_message *message)
1096 : {
1097 7794233 : return ldb_unpack_data_flags(ldb, data, message, 0);
1098 : }
1099 :
1100 : /*
1101 : add the special distinguishedName element
1102 : */
1103 169739675 : int ldb_msg_add_distinguished_name(struct ldb_message *msg)
1104 : {
1105 169739675 : const char *dn_attr = "distinguishedName";
1106 169739675 : char *dn = NULL;
1107 :
1108 169739675 : if (ldb_msg_find_element(msg, dn_attr)) {
1109 : /*
1110 : * This should not happen, but this is
1111 : * existing behaviour...
1112 : */
1113 0 : return LDB_SUCCESS;
1114 : }
1115 :
1116 169739675 : dn = ldb_dn_alloc_linearized(msg, msg->dn);
1117 169739675 : if (dn == NULL) {
1118 1 : return LDB_ERR_OPERATIONS_ERROR;
1119 : }
1120 :
1121 169739674 : return ldb_msg_add_steal_string(msg, dn_attr, dn);
1122 : }
1123 :
1124 : /*
1125 : * filter the specified list of attributes from msg,
1126 : * adding requested attributes, and perhaps all for *,
1127 : * but not the DN to filtered_msg.
1128 : */
1129 14 : int ldb_filter_attrs(struct ldb_context *ldb,
1130 : const struct ldb_message *msg,
1131 : const char *const *attrs,
1132 : struct ldb_message *filtered_msg)
1133 : {
1134 0 : unsigned int i;
1135 14 : bool keep_all = false;
1136 14 : bool add_dn = false;
1137 0 : uint32_t num_elements;
1138 0 : uint32_t elements_size;
1139 :
1140 14 : if (attrs) {
1141 : /* check for special attrs */
1142 27 : for (i = 0; attrs[i]; i++) {
1143 18 : int cmp = strcmp(attrs[i], "*");
1144 18 : if (cmp == 0) {
1145 5 : keep_all = true;
1146 5 : break;
1147 : }
1148 13 : cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
1149 13 : if (cmp == 0) {
1150 1 : add_dn = true;
1151 : }
1152 : }
1153 : } else {
1154 0 : keep_all = true;
1155 : }
1156 :
1157 14 : if (keep_all) {
1158 5 : add_dn = true;
1159 5 : elements_size = msg->num_elements + 1;
1160 :
1161 : /* Shortcuts for the simple cases */
1162 9 : } else if (add_dn && i == 1) {
1163 1 : if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
1164 0 : goto failed;
1165 : }
1166 1 : return 0;
1167 8 : } else if (i == 0) {
1168 1 : return 0;
1169 :
1170 : /*
1171 : * Otherwise we are copying at most as many elements as we
1172 : * have attributes
1173 : */
1174 : } else {
1175 7 : elements_size = i;
1176 : }
1177 :
1178 12 : filtered_msg->elements = talloc_array(filtered_msg,
1179 : struct ldb_message_element,
1180 : elements_size);
1181 12 : if (filtered_msg->elements == NULL) goto failed;
1182 :
1183 12 : num_elements = 0;
1184 :
1185 30 : for (i = 0; i < msg->num_elements; i++) {
1186 19 : struct ldb_message_element *el = &msg->elements[i];
1187 :
1188 : /*
1189 : * el2 is assigned after the Pigeonhole principle
1190 : * check below for clarity
1191 : */
1192 19 : struct ldb_message_element *el2 = NULL;
1193 0 : unsigned int j;
1194 :
1195 19 : if (keep_all == false) {
1196 12 : bool found = false;
1197 14 : for (j = 0; attrs[j]; j++) {
1198 13 : int cmp = ldb_attr_cmp(el->name, attrs[j]);
1199 13 : if (cmp == 0) {
1200 11 : found = true;
1201 11 : break;
1202 : }
1203 : }
1204 12 : if (found == false) {
1205 1 : continue;
1206 : }
1207 : }
1208 :
1209 : /*
1210 : * Pigeonhole principle: we can't have more elements
1211 : * than the number of attributes if they are unique in
1212 : * the DB.
1213 : */
1214 18 : if (num_elements >= elements_size) {
1215 1 : goto failed;
1216 : }
1217 :
1218 17 : el2 = &filtered_msg->elements[num_elements];
1219 :
1220 17 : *el2 = *el;
1221 17 : el2->name = talloc_strdup(filtered_msg->elements,
1222 : el->name);
1223 17 : if (el2->name == NULL) {
1224 0 : goto failed;
1225 : }
1226 17 : el2->values = talloc_array(filtered_msg->elements,
1227 : struct ldb_val, el->num_values);
1228 17 : if (el2->values == NULL) {
1229 0 : goto failed;
1230 : }
1231 34 : for (j=0;j<el->num_values;j++) {
1232 17 : el2->values[j] = ldb_val_dup(el2->values, &el->values[j]);
1233 17 : if (el2->values[j].data == NULL && el->values[j].length != 0) {
1234 0 : goto failed;
1235 : }
1236 : }
1237 17 : num_elements++;
1238 : }
1239 :
1240 11 : filtered_msg->num_elements = num_elements;
1241 :
1242 11 : if (add_dn) {
1243 5 : if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
1244 1 : goto failed;
1245 : }
1246 : }
1247 :
1248 10 : if (filtered_msg->num_elements > 0) {
1249 0 : filtered_msg->elements
1250 10 : = talloc_realloc(filtered_msg,
1251 : filtered_msg->elements,
1252 : struct ldb_message_element,
1253 : filtered_msg->num_elements);
1254 10 : if (filtered_msg->elements == NULL) {
1255 0 : goto failed;
1256 : }
1257 : } else {
1258 0 : TALLOC_FREE(filtered_msg->elements);
1259 : }
1260 :
1261 10 : return 0;
1262 2 : failed:
1263 2 : TALLOC_FREE(filtered_msg->elements);
1264 2 : return -1;
1265 : }
1266 :
1267 : /*
1268 : * filter the specified list of attributes from msg,
1269 : * adding requested attributes, and perhaps all for *.
1270 : * Unlike ldb_filter_attrs(), the DN will not be added
1271 : * if it is missing.
1272 : */
1273 169739685 : int ldb_filter_attrs_in_place(struct ldb_message *msg,
1274 : const char *const *attrs)
1275 : {
1276 169739685 : unsigned int i = 0;
1277 169739685 : bool keep_all = false;
1278 169739685 : unsigned int num_del = 0;
1279 :
1280 169739685 : if (attrs) {
1281 : /* check for special attrs */
1282 4645594571 : for (i = 0; attrs[i]; i++) {
1283 4482888035 : int cmp = strcmp(attrs[i], "*");
1284 4482888035 : if (cmp == 0) {
1285 4534703 : keep_all = true;
1286 4534703 : break;
1287 : }
1288 : }
1289 167420423 : if (!keep_all && i == 0) {
1290 14720172 : msg->num_elements = 0;
1291 14720172 : return LDB_SUCCESS;
1292 : }
1293 : } else {
1294 2121406 : keep_all = true;
1295 : }
1296 :
1297 3934212315 : for (i = 0; i < msg->num_elements; i++) {
1298 3779192802 : bool found = false;
1299 104480536 : unsigned int j;
1300 :
1301 3779192802 : if (keep_all) {
1302 151506512 : found = true;
1303 : } else {
1304 67856963116 : for (j = 0; attrs[j]; j++) {
1305 65807056684 : int cmp = ldb_attr_cmp(msg->elements[i].name, attrs[j]);
1306 65807056684 : if (cmp == 0) {
1307 1532987427 : found = true;
1308 1532987427 : break;
1309 : }
1310 : }
1311 : }
1312 :
1313 3772627343 : if (!found) {
1314 2049906432 : ++num_del;
1315 1729286370 : } else if (num_del != 0) {
1316 1382739209 : msg->elements[i - num_del] = msg->elements[i];
1317 : }
1318 : }
1319 :
1320 155019513 : msg->num_elements -= num_del;
1321 :
1322 155019513 : return LDB_SUCCESS;
1323 : }
1324 :
1325 : /* Have an unpacked ldb message take talloc ownership of its elements. */
1326 169739669 : int ldb_msg_elements_take_ownership(struct ldb_message *msg)
1327 : {
1328 169739669 : unsigned int i = 0;
1329 :
1330 1899026004 : for (i = 0; i < msg->num_elements; i++) {
1331 1729286335 : struct ldb_message_element *el = &msg->elements[i];
1332 44792419 : const char *name;
1333 44792419 : unsigned int j;
1334 :
1335 1729286335 : name = talloc_strdup(msg->elements,
1336 : el->name);
1337 1729286335 : if (name == NULL) {
1338 0 : return -1;
1339 : }
1340 1729286335 : el->name = name;
1341 :
1342 1729286335 : if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
1343 1598653235 : struct ldb_val *values = talloc_memdup(msg->elements, el->values,
1344 : sizeof(struct ldb_val) * el->num_values);
1345 1598653235 : if (values == NULL) {
1346 0 : return -1;
1347 : }
1348 1598653235 : el->values = values;
1349 1598653235 : el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
1350 : }
1351 :
1352 3720221910 : for (j = 0; j < el->num_values; j++) {
1353 1990935575 : struct ldb_val val = ldb_val_dup(el->values, &el->values[j]);
1354 1990935575 : if (val.data == NULL && el->values[j].length != 0) {
1355 0 : return -1;
1356 : }
1357 1990935575 : el->values[j] = val;
1358 : }
1359 : }
1360 :
1361 165215051 : return LDB_SUCCESS;
1362 : }
|