24c506554b26aecc9235cbd09738bc8c22df6ca0
[metze/samba/wip.git] / lib / ldb / common / ldb_pack.c
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 /* change this if the data format ever changes */
37 #define LDB_PACKING_FORMAT 0x26011967
38
39 /* old packing formats */
40 #define LDB_PACKING_FORMAT_NODN 0x26011966
41
42 /* use a portable integer format */
43 static void put_uint32(uint8_t *p, int ofs, unsigned int val)
44 {
45         p += ofs;
46         p[0] = val&0xFF;
47         p[1] = (val>>8)  & 0xFF;
48         p[2] = (val>>16) & 0xFF;
49         p[3] = (val>>24) & 0xFF;
50 }
51
52 static unsigned int pull_uint32(uint8_t *p, int ofs)
53 {
54         p += ofs;
55         return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
56 }
57
58 static int attribute_storable_values(const struct ldb_message_element *el)
59 {
60         if (el->num_values == 0) return 0;
61
62         if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
63
64         return el->num_values;
65 }
66
67 /*
68   pack a ldb message into a linear buffer in a ldb_val
69
70   note that this routine avoids saving elements with zero values,
71   as these are equivalent to having no element
72
73   caller frees the data buffer after use
74 */
75 int ldb_pack_data(struct ldb_context *ldb,
76                   const struct ldb_message *message,
77                   struct ldb_val *data)
78 {
79         unsigned int i, j, real_elements=0;
80         size_t size, dn_len, attr_len, value_len;
81         const char *dn;
82         uint8_t *p;
83         size_t len;
84
85         dn = ldb_dn_get_linearized(message->dn);
86         if (dn == NULL) {
87                 errno = ENOMEM;
88                 return -1;
89         }
90
91         /* work out how big it needs to be */
92         size = 8;
93
94         size += 1;
95
96         dn_len = strlen(dn);
97         if (size + dn_len < size) {
98                 errno = ENOMEM;
99                 return -1;
100         }
101         size += dn_len;
102
103         /*
104          * First calcuate the buffer size we need, and check for
105          * overflows
106          */
107         for (i=0;i<message->num_elements;i++) {
108                 if (attribute_storable_values(&message->elements[i]) == 0) {
109                         continue;
110                 }
111
112                 real_elements++;
113
114                 if (size + 5 < size) {
115                         errno = ENOMEM;
116                         return -1;
117                 }
118                 size += 5;
119
120                 attr_len = strlen(message->elements[i].name);
121                 if (size + attr_len < size) {
122                         errno = ENOMEM;
123                         return -1;
124                 }
125                 size += attr_len;
126
127                 for (j=0;j<message->elements[i].num_values;j++) {
128                         if (size + 5 < size) {
129                                 errno = ENOMEM;
130                                 return -1;
131                         }
132                         size += 5;
133
134                         value_len = message->elements[i].values[j].length;
135                         if (size + value_len < size) {
136                                 errno = ENOMEM;
137                                 return -1;
138                         }
139                         size += value_len;
140                 }
141         }
142
143         /* allocate it */
144         data->data = talloc_array(ldb, uint8_t, size);
145         if (!data->data) {
146                 errno = ENOMEM;
147                 return -1;
148         }
149         data->length = size;
150
151         p = data->data;
152         put_uint32(p, 0, LDB_PACKING_FORMAT);
153         put_uint32(p, 4, real_elements);
154         p += 8;
155
156         /* the dn needs to be packed so we can be case preserving
157            while hashing on a case folded dn */
158         len = dn_len;
159         memcpy(p, dn, len+1);
160         p += len + 1;
161
162         for (i=0;i<message->num_elements;i++) {
163                 if (attribute_storable_values(&message->elements[i]) == 0) {
164                         continue;
165                 }
166                 len = strlen(message->elements[i].name);
167                 memcpy(p, message->elements[i].name, len+1);
168                 p += len + 1;
169                 put_uint32(p, 0, message->elements[i].num_values);
170                 p += 4;
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;
177                 }
178         }
179
180         return 0;
181 }
182
183 static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
184 {
185         unsigned int remaining = *premaining;
186         uint8_t *p = *pp;
187         uint32_t num_values = pull_uint32(p, 0);
188         uint32_t j, len;
189
190         p += 4;
191         if (remaining < 4) {
192                 return false;
193         }
194         remaining -= 4;
195         for (j = 0; j < num_values; j++) {
196                 len = pull_uint32(p, 0);
197                 if (remaining < 5) {
198                         return false;
199                 }
200                 remaining -= 5;
201                 if (len > remaining) {
202                         return false;
203                 }
204                 remaining -= len;
205                 p += len + 4 + 1;
206         }
207
208         *premaining = remaining;
209         *pp = p;
210         return true;
211 }
212
213
214 /*
215  * Unpack a ldb message from a linear buffer in ldb_val
216  *
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.
219  */
220 int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
221                                          const struct ldb_val *data,
222                                          struct ldb_message *message,
223                                          const char * const *list,
224                                          unsigned int list_size,
225                                          unsigned int flags,
226                                          unsigned int *nb_elements_in_db)
227 {
228         uint8_t *p;
229         size_t remaining;
230         size_t dn_len;
231         unsigned int i, j;
232         unsigned format;
233         unsigned int nelem = 0;
234         size_t len;
235         unsigned int found = 0;
236         struct ldb_val *ldb_val_single_array = NULL;
237
238         if (list == NULL) {
239                 list_size = 0;
240         }
241
242         message->elements = NULL;
243
244         p = data->data;
245         if (data->length < 8) {
246                 errno = EIO;
247                 goto failed;
248         }
249
250         format = pull_uint32(p, 0);
251         message->num_elements = pull_uint32(p, 4);
252         p += 8;
253         if (nb_elements_in_db) {
254                 *nb_elements_in_db = message->num_elements;
255         }
256
257         remaining = data->length - 8;
258
259         switch (format) {
260         case LDB_PACKING_FORMAT_NODN:
261                 message->dn = NULL;
262                 break;
263
264         case LDB_PACKING_FORMAT:
265                 /*
266                  * With this check, we know that the DN at p is \0
267                  * terminated.
268                  */
269                 dn_len = strnlen((char *)p, remaining);
270                 if (dn_len == remaining) {
271                         errno = EIO;
272                         goto failed;
273                 }
274                 if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
275                         message->dn = NULL;
276                 } else {
277                         struct ldb_val blob;
278                         blob.data = discard_const_p(uint8_t, p);
279                         blob.length = dn_len;
280                         message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
281                         if (message->dn == NULL) {
282                                 errno = ENOMEM;
283                                 goto failed;
284                         }
285                 }
286                 /*
287                  * Redundant: by definition, remaining must be more
288                  * than one less than dn_len, as otherwise it would be
289                  * == dn_len
290                  */
291                 if (remaining < dn_len + 1) {
292                         errno = EIO;
293                         goto failed;
294                 }
295                 remaining -= dn_len + 1;
296                 p += dn_len + 1;
297                 break;
298
299         default:
300                 errno = EIO;
301                 goto failed;
302         }
303
304         
305         if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
306                 return 0;
307         }
308         
309         if (message->num_elements == 0) {
310                 return 0;
311         }
312
313         if (message->num_elements > remaining / 6) {
314                 errno = EIO;
315                 goto failed;
316         }
317
318         message->elements = talloc_zero_array(message, struct ldb_message_element,
319                                               message->num_elements);
320         if (!message->elements) {
321                 errno = ENOMEM;
322                 goto failed;
323         }
324
325         /*
326          * In typical use, most values are single-valued.  This makes
327          * it quite expensive to allocate an array of ldb_val for each
328          * of these, just to then hold the pointer to the data buffer
329          * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
330          * ahead of time and use it for the single values where possible.
331          * (This is used the the normal search case, but not in the
332          * index case because of caller requirements).
333          */
334         if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
335                 ldb_val_single_array = talloc_array(message->elements, struct ldb_val,
336                                                     message->num_elements);
337                 if (ldb_val_single_array == NULL) {
338                         errno = ENOMEM;
339                         goto failed;
340                 }
341         }
342
343         for (i=0;i<message->num_elements;i++) {
344                 const char *attr = NULL;
345                 size_t attr_len;
346                 struct ldb_message_element *element = NULL;
347
348                 if (remaining < 10) {
349                         errno = EIO;
350                         goto failed;
351                 }
352                 /*
353                  * With this check, we know that the attribute name at
354                  * p is \0 terminated.
355                  */
356                 attr_len = strnlen((char *)p, remaining-6);
357                 if (attr_len == remaining-6) {
358                         errno = EIO;
359                         goto failed;
360                 }
361                 if (attr_len == 0) {
362                         errno = EIO;
363                         goto failed;
364                 }
365                 attr = (char *)p;
366
367                 /*
368                  * The general idea is to reduce allocations by skipping over
369                  * attributes that we do not actually care about.
370                  *
371                  * This is a bit expensive but normally the list is pretty small
372                  * also the cost of freeing unused attributes is quite important
373                  * and can dwarf the cost of looping.
374                  */
375                 if (list_size != 0) {
376                         bool keep = false;
377                         unsigned int h;
378
379                         /*
380                          * We know that p has a \0 terminator before the
381                          * end of the buffer due to the check above.
382                          */
383                         for (h = 0; h < list_size && found < list_size; h++) {
384                                 if (ldb_attr_cmp(attr, list[h]) == 0) {
385                                         keep = true;
386                                         found++;
387                                         break;
388                                 }
389                         }
390
391                         if (!keep) {
392                                 if (remaining < (attr_len + 1)) {
393                                         errno = EIO;
394                                         goto failed;
395                                 }
396                                 remaining -= attr_len + 1;
397                                 p += attr_len + 1;
398                                 if (!ldb_consume_element_data(&p, &remaining)) {
399                                         errno = EIO;
400                                         goto failed;
401                                 }
402                                 continue;
403                         }
404                 }
405                 element = &message->elements[nelem];
406                 element->name = attr;
407                 element->flags = 0;
408
409                 if (remaining < (attr_len + 1)) {
410                         errno = EIO;
411                         goto failed;
412                 }
413                 remaining -= attr_len + 1;
414                 p += attr_len + 1;
415                 element->num_values = pull_uint32(p, 0);
416                 element->values = NULL;
417                 if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
418                         element->values = &ldb_val_single_array[nelem];
419                 } else if (element->num_values != 0) {
420                         element->values = talloc_array(message->elements,
421                                                        struct ldb_val,
422                                                        element->num_values);
423                         if (!element->values) {
424                                 errno = ENOMEM;
425                                 goto failed;
426                         }
427                 }
428                 p += 4;
429                 if (remaining < 4) {
430                         errno = EIO;
431                         goto failed;
432                 }
433                 remaining -= 4;
434                 for (j = 0; j < element->num_values; j++) {
435                         if (remaining < 5) {
436                                 errno = EIO;
437                                 goto failed;
438                         }
439                         remaining -= 5;
440
441                         len = pull_uint32(p, 0);
442                         if (remaining < len) {
443                                 errno = EIO;
444                                 goto failed;
445                         }
446                         if (len + 1 < len) {
447                                 errno = EIO;
448                                 goto failed;
449                         }
450
451                         element->values[j].length = len;
452                         element->values[j].data = p + 4;
453                         remaining -= len;
454                         p += len+4+1;
455                 }
456                 nelem++;
457         }
458         /*
459          * Adapt the number of elements to the real number of unpacked elements,
460          * it means that we overallocated elements array.
461          */
462         message->num_elements = nelem;
463
464         /*
465          * Shrink the allocated size.  On current talloc behaviour
466          * this will help if we skipped 32 or more attributes.
467          */
468         message->elements = talloc_realloc(message, message->elements,
469                                            struct ldb_message_element,
470                                            message->num_elements);
471
472         if (remaining != 0) {
473                 ldb_debug(ldb, LDB_DEBUG_ERROR,
474                           "Error: %zu bytes unread in ldb_unpack_data_only_attr_list",
475                           remaining);
476         }
477
478         return 0;
479
480 failed:
481         talloc_free(message->elements);
482         return -1;
483 }
484
485 /*
486  * Unpack a ldb message from a linear buffer in ldb_val
487  *
488  * Providing a list of attributes to this function allows selective unpacking.
489  * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
490  *
491  * Free with ldb_unpack_data_free()
492  */
493 int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
494                                    const struct ldb_val *data,
495                                    struct ldb_message *message,
496                                    const char * const *list,
497                                    unsigned int list_size,
498                                    unsigned int *nb_elements_in_db)
499 {
500         return ldb_unpack_data_only_attr_list_flags(ldb,
501                                                     data,
502                                                     message,
503                                                     list,
504                                                     list_size,
505                                                     0,
506                                                     nb_elements_in_db);
507 }
508
509 int ldb_unpack_data(struct ldb_context *ldb,
510                     const struct ldb_val *data,
511                     struct ldb_message *message)
512 {
513         return ldb_unpack_data_only_attr_list(ldb, data, message, NULL, 0, NULL);
514 }
515
516 /*
517   add the special distinguishedName element
518 */
519 static int msg_add_distinguished_name(struct ldb_message *msg)
520 {
521         const char *dn_attr = "distinguishedName";
522         char *dn = NULL;
523
524         if (ldb_msg_find_element(msg, dn_attr)) {
525                 /*
526                  * This should not happen, but this is
527                  * existing behaviour...
528                  */
529                 return LDB_SUCCESS;
530         }
531
532         dn = ldb_dn_alloc_linearized(msg, msg->dn);
533         if (dn == NULL) {
534                 return LDB_ERR_OPERATIONS_ERROR;
535         }
536
537         return ldb_msg_add_steal_string(msg, dn_attr, dn);
538 }
539
540 /*
541  * filter the specified list of attributes from msg,
542  * adding requested attributes, and perhaps all for *,
543  * but not the DN to filtered_msg.
544  */
545 int ldb_filter_attrs(struct ldb_context *ldb,
546                      const struct ldb_message *msg,
547                      const char *const *attrs,
548                      struct ldb_message *filtered_msg)
549 {
550         unsigned int i;
551         bool keep_all = false;
552         bool add_dn = false;
553         uint32_t num_elements;
554         uint32_t elements_size;
555
556         if (attrs) {
557                 /* check for special attrs */
558                 for (i = 0; attrs[i]; i++) {
559                         int cmp = strcmp(attrs[i], "*");
560                         if (cmp == 0) {
561                                 keep_all = true;
562                                 break;
563                         }
564                         cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
565                         if (cmp == 0) {
566                                 add_dn = true;
567                         }
568                 }
569         } else {
570                 keep_all = true;
571         }
572
573         if (keep_all) {
574                 add_dn = true;
575                 elements_size = msg->num_elements + 1;
576
577         /* Shortcuts for the simple cases */
578         } else if (add_dn && i == 1) {
579                 if (msg_add_distinguished_name(filtered_msg) != 0) {
580                         goto failed;
581                 }
582                 return 0;
583         } else if (i == 0) {
584                 return 0;
585
586         /* Otherwise we are copying at most as many element as we have attributes */
587         } else {
588                 elements_size = i;
589         }
590
591         filtered_msg->elements = talloc_array(filtered_msg,
592                                               struct ldb_message_element,
593                                               elements_size);
594         if (filtered_msg->elements == NULL) goto failed;
595
596         num_elements = 0;
597
598         for (i = 0; i < msg->num_elements; i++) {
599                 struct ldb_message_element *el = &msg->elements[i];
600                 struct ldb_message_element *el2 = &filtered_msg->elements[num_elements];
601                 unsigned int j;
602
603                 if (keep_all == false) {
604                         bool found = false;
605                         for (j = 0; attrs[j]; j++) {
606                                 int cmp = ldb_attr_cmp(el->name, attrs[j]);
607                                 if (cmp == 0) {
608                                         found = true;
609                                         break;
610                                 }
611                         }
612                         if (found == false) {
613                                 continue;
614                         }
615                 }
616                 *el2 = *el;
617                 el2->name = talloc_strdup(filtered_msg->elements,
618                                           el->name);
619                 if (el2->name == NULL) {
620                         goto failed;
621                 }
622                 el2->values = talloc_array(filtered_msg->elements,
623                                            struct ldb_val, el->num_values);
624                 if (el2->values == NULL) {
625                         goto failed;
626                 }
627                 for (j=0;j<el->num_values;j++) {
628                         el2->values[j] = ldb_val_dup(el2->values, &el->values[j]);
629                         if (el2->values[j].data == NULL && el->values[j].length != 0) {
630                                 goto failed;
631                         }
632                 }
633                 num_elements++;
634
635                 /* Pidginhole principle: we can't have more elements
636                  * than the number of attributes if they are unique in
637                  * the DB */
638                 if (num_elements > elements_size) {
639                         goto failed;
640                 }
641         }
642
643         filtered_msg->num_elements = num_elements;
644
645         if (add_dn) {
646                 if (msg_add_distinguished_name(filtered_msg) != 0) {
647                         goto failed;
648                 }
649         }
650
651         if (filtered_msg->num_elements > 0) {
652                 filtered_msg->elements
653                         = talloc_realloc(filtered_msg,
654                                          filtered_msg->elements,
655                                          struct ldb_message_element,
656                                          filtered_msg->num_elements);
657                 if (filtered_msg->elements == NULL) {
658                         goto failed;
659                 }
660         } else {
661                 talloc_free(filtered_msg->elements);
662                 filtered_msg->elements = NULL;
663         }
664
665         return 0;
666 failed:
667         return -1;
668 }