4 Copyright (C) Andrew Tridgell 2004
6 ** NOTE! The following LGPL license applies to the ldb
7 ** library. This does NOT imply that all of Samba is released
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.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public
21 License along with this library; if not, see <http://www.gnu.org/licenses/>.
27 * Component: ldb pack/unpack
29 * Description: pack/unpack routines for ldb messages as key/value blobs
31 * Author: Andrew Tridgell
34 #include "ldb_private.h"
36 /* change this if the data format ever changes */
37 #define LDB_PACKING_FORMAT 0x26011967
39 /* old packing formats */
40 #define LDB_PACKING_FORMAT_NODN 0x26011966
42 /* use a portable integer format */
43 static void put_uint32(uint8_t *p, int ofs, unsigned int val)
47 p[1] = (val>>8) & 0xFF;
48 p[2] = (val>>16) & 0xFF;
49 p[3] = (val>>24) & 0xFF;
52 static unsigned int pull_uint32(uint8_t *p, int ofs)
55 return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
58 static int attribute_storable_values(const struct ldb_message_element *el)
60 if (el->num_values == 0) return 0;
62 if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
64 return el->num_values;
68 pack a ldb message into a linear buffer in a ldb_val
70 note that this routine avoids saving elements with zero values,
71 as these are equivalent to having no element
73 caller frees the data buffer after use
75 int ldb_pack_data(struct ldb_context *ldb,
76 const struct ldb_message *message,
79 unsigned int i, j, real_elements=0;
80 size_t size, dn_len, attr_len, value_len;
85 dn = ldb_dn_get_linearized(message->dn);
91 /* work out how big it needs to be */
97 if (size + dn_len < size) {
104 * First calcuate the buffer size we need, and check for
107 for (i=0;i<message->num_elements;i++) {
108 if (attribute_storable_values(&message->elements[i]) == 0) {
114 if (size + 5 < size) {
120 attr_len = strlen(message->elements[i].name);
121 if (size + attr_len < size) {
127 for (j=0;j<message->elements[i].num_values;j++) {
128 if (size + 5 < size) {
134 value_len = message->elements[i].values[j].length;
135 if (size + value_len < size) {
144 data->data = talloc_array(ldb, uint8_t, size);
152 put_uint32(p, 0, LDB_PACKING_FORMAT);
153 put_uint32(p, 4, real_elements);
156 /* the dn needs to be packed so we can be case preserving
157 while hashing on a case folded dn */
159 memcpy(p, dn, len+1);
162 for (i=0;i<message->num_elements;i++) {
163 if (attribute_storable_values(&message->elements[i]) == 0) {
166 len = strlen(message->elements[i].name);
167 memcpy(p, message->elements[i].name, len+1);
169 put_uint32(p, 0, message->elements[i].num_values);
171 for (j=0;j<message->elements[i].num_values;j++) {
172 put_uint32(p, 0, message->elements[i].values[j].length);
173 memcpy(p+4, message->elements[i].values[j].data,
174 message->elements[i].values[j].length);
175 p[4+message->elements[i].values[j].length] = 0;
176 p += 4 + message->elements[i].values[j].length + 1;
183 static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
185 unsigned int remaining = *premaining;
187 uint32_t num_values = pull_uint32(p, 0);
196 for (j = 0; j < num_values; j++) {
197 len = pull_uint32(p, 0);
202 if (len > remaining) {
209 *premaining = remaining;
215 * Unpack a ldb message from a linear buffer in ldb_val
217 * Providing a list of attributes to this function allows selective unpacking.
218 * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
220 * Free with ldb_unpack_data_free()
222 int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
223 const struct ldb_val *data,
224 struct ldb_message *message,
225 const char * const *list,
226 unsigned int list_size,
227 unsigned int *nb_elements_in_db)
234 unsigned int nelem = 0;
236 unsigned int found = 0;
242 message->elements = NULL;
245 if (data->length < 8) {
250 format = pull_uint32(p, 0);
251 message->num_elements = pull_uint32(p, 4);
253 if (nb_elements_in_db) {
254 *nb_elements_in_db = message->num_elements;
257 remaining = data->length - 8;
260 case LDB_PACKING_FORMAT_NODN:
264 case LDB_PACKING_FORMAT:
266 * With this check, we know that the DN at p is \0
269 dn_len = strnlen((char *)p, remaining);
270 if (dn_len == remaining) {
274 message->dn = ldb_dn_new(message, ldb, (char *)p);
275 if (message->dn == NULL) {
280 * Redundant: by definition, remaining must be more
281 * than one less than dn_len, as otherwise it would be
284 if (remaining < dn_len + 1) {
288 remaining -= dn_len + 1;
297 if (message->num_elements == 0) {
301 if (message->num_elements > remaining / 6) {
306 message->elements = talloc_zero_array(message, struct ldb_message_element,
307 message->num_elements);
308 if (!message->elements) {
313 for (i=0;i<message->num_elements;i++) {
314 const char *attr = NULL;
316 struct ldb_message_element *element = NULL;
318 if (remaining < 10) {
323 * With this check, we know that the attribute name at
324 * p is \0 terminated.
326 attr_len = strnlen((char *)p, remaining-6);
327 if (attr_len == remaining-6) {
338 * The general idea is to reduce allocations by skipping over
339 * attributes that we do not actually care about.
341 * This is a bit expensive but normally the list is pretty small
342 * also the cost of freeing unused attributes is quite important
343 * and can dwarf the cost of looping.
345 if (list_size != 0) {
350 * We know that p has a \0 terminator before the
351 * end of the buffer due to the check above.
353 for (h = 0; h < list_size && found < list_size; h++) {
354 if (ldb_attr_cmp(attr, list[h]) == 0) {
362 if (remaining < (attr_len + 1)) {
366 remaining -= attr_len + 1;
368 if (!ldb_consume_element_data(&p, &remaining)) {
375 element = &message->elements[nelem];
376 element->name = talloc_strndup(message->elements, (char *)p, attr_len);
377 if (element->name == NULL) {
383 if (remaining < (attr_len + 1)) {
387 remaining -= attr_len + 1;
389 element->num_values = pull_uint32(p, 0);
390 element->values = NULL;
391 if (element->num_values != 0) {
392 element->values = talloc_array(message->elements,
394 element->num_values);
395 if (!element->values) {
406 for (j = 0; j < element->num_values; j++) {
413 len = pull_uint32(p, 0);
414 if (remaining < len) {
423 element->values[j].length = len;
424 element->values[j].data = talloc_size(element->values, len+1);
425 if (element->values[j].data == NULL) {
429 memcpy(element->values[j].data, p + 4,
431 element->values[j].data[len] = 0;
439 * Adapt the number of elements to the real number of unpacked elements,
440 * it means that we overallocated elements array.
442 message->num_elements = nelem;
445 * Shrink the allocated size. On current talloc behaviour
446 * this will help if we skipped 32 or more attributes.
448 message->elements = talloc_realloc(message, message->elements,
449 struct ldb_message_element,
450 message->num_elements);
452 if (remaining != 0) {
453 ldb_debug(ldb, LDB_DEBUG_ERROR,
454 "Error: %zu bytes unread in ldb_unpack_data_only_attr_list",
461 talloc_free(message->elements);
465 int ldb_unpack_data(struct ldb_context *ldb,
466 const struct ldb_val *data,
467 struct ldb_message *message)
469 return ldb_unpack_data_only_attr_list(ldb, data, message, NULL, 0, NULL);