LCOV - code coverage report
Current view: top level - lib/ldb/common - ldb_pack.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 454 593 76.6 %
Date: 2024-06-13 04:01:37 Functions: 13 13 100.0 %

          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   196709222 : static int attribute_storable_values(const struct ldb_message_element *el)
      90             : {
      91   196709222 :         if (el->num_values == 0) return 0;
      92             : 
      93   196709222 :         if (ldb_attr_cmp(el->name, "distinguishedName") == 0) return 0;
      94             : 
      95   196698897 :         return el->num_values;
      96             : }
      97             : 
      98     4722661 : static int ldb_pack_data_v1(struct ldb_context *ldb,
      99             :                             const struct ldb_message *message,
     100             :                             struct ldb_val *data)
     101             : {
     102     4722661 :         unsigned int i, j, real_elements=0;
     103             :         size_t size, dn_len, attr_len, value_len;
     104             :         const char *dn;
     105             :         uint8_t *p;
     106             :         size_t len;
     107             : 
     108     4722661 :         dn = ldb_dn_get_linearized(message->dn);
     109     4722661 :         if (dn == NULL) {
     110           0 :                 errno = ENOMEM;
     111           0 :                 return -1;
     112             :         }
     113             : 
     114             :         /* work out how big it needs to be */
     115     4722661 :         size = U32_LEN * 2 + NULL_PAD_BYTE_LEN;
     116             : 
     117     4722661 :         dn_len = strlen(dn);
     118     4722661 :         if (size + dn_len < size) {
     119           0 :                 errno = ENOMEM;
     120           0 :                 return -1;
     121             :         }
     122     4722661 :         size += dn_len;
     123             : 
     124             :         /*
     125             :          * First calcuate the buffer size we need, and check for
     126             :          * overflows
     127             :          */
     128    27501461 :         for (i=0;i<message->num_elements;i++) {
     129    22778800 :                 if (attribute_storable_values(&message->elements[i]) == 0) {
     130        2344 :                         continue;
     131             :                 }
     132             : 
     133    22776456 :                 real_elements++;
     134             : 
     135    22776456 :                 if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) {
     136           0 :                         errno = ENOMEM;
     137           0 :                         return -1;
     138             :                 }
     139    22776456 :                 size += U32_LEN + NULL_PAD_BYTE_LEN;
     140             : 
     141    22776456 :                 attr_len = strlen(message->elements[i].name);
     142    22776456 :                 if (size + attr_len < size) {
     143           0 :                         errno = ENOMEM;
     144           0 :                         return -1;
     145             :                 }
     146    22776456 :                 size += attr_len;
     147             : 
     148    48989600 :                 for (j=0;j<message->elements[i].num_values;j++) {
     149    26213144 :                         if (size + U32_LEN + NULL_PAD_BYTE_LEN < size) {
     150           0 :                                 errno = ENOMEM;
     151           0 :                                 return -1;
     152             :                         }
     153    26213144 :                         size += U32_LEN + NULL_PAD_BYTE_LEN;
     154             : 
     155    26213144 :                         value_len = message->elements[i].values[j].length;
     156    26213144 :                         if (size + value_len < size) {
     157           0 :                                 errno = ENOMEM;
     158           0 :                                 return -1;
     159             :                         }
     160    26213144 :                         size += value_len;
     161             :                 }
     162             :         }
     163             : 
     164             :         /* allocate it */
     165     4722661 :         data->data = talloc_array(ldb, uint8_t, size);
     166     4722661 :         if (!data->data) {
     167           0 :                 errno = ENOMEM;
     168           0 :                 return -1;
     169             :         }
     170     4722661 :         data->length = size;
     171             : 
     172     4722661 :         p = data->data;
     173     4722661 :         PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT);
     174     4722661 :         p += U32_LEN;
     175     4722661 :         PUSH_LE_U32(p, 0, real_elements);
     176     4722661 :         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     4722661 :         len = dn_len;
     181     4722661 :         memcpy(p, dn, len+NULL_PAD_BYTE_LEN);
     182     4722661 :         p += len + NULL_PAD_BYTE_LEN;
     183             : 
     184    27501461 :         for (i=0;i<message->num_elements;i++) {
     185    22778800 :                 if (attribute_storable_values(&message->elements[i]) == 0) {
     186        2344 :                         continue;
     187             :                 }
     188    22776456 :                 len = strlen(message->elements[i].name);
     189    22776456 :                 memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN);
     190    22776456 :                 p += len + NULL_PAD_BYTE_LEN;
     191    22776456 :                 PUSH_LE_U32(p, 0, message->elements[i].num_values);
     192    22776456 :                 p += U32_LEN;
     193    48989600 :                 for (j=0;j<message->elements[i].num_values;j++) {
     194    26213144 :                         PUSH_LE_U32(p, 0,
     195             :                                     message->elements[i].values[j].length);
     196    26213144 :                         p += U32_LEN;
     197    26213144 :                         memcpy(p, message->elements[i].values[j].data,
     198    26213144 :                                message->elements[i].values[j].length);
     199    26213144 :                         p[message->elements[i].values[j].length] = 0;
     200    26213144 :                         p += message->elements[i].values[j].length +
     201             :                                 NULL_PAD_BYTE_LEN;
     202             :                 }
     203             :         }
     204             : 
     205     4722661 :         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    10771965 : static int ldb_pack_data_v2(struct ldb_context *ldb,
     245             :                             const struct ldb_message *message,
     246             :                             struct ldb_val *data)
     247             : {
     248    10771965 :         unsigned int i, j, real_elements=0;
     249             :         size_t size, dn_len, dn_canon_len, attr_len, value_len;
     250             :         const char *dn, *dn_canon;
     251             :         uint8_t *p, *q;
     252             :         size_t len;
     253             :         size_t max_val_len;
     254             :         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    10771965 :         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    10771965 :         dn = ldb_dn_get_linearized(message->dn);
     268    10771965 :         if (dn == NULL) {
     269           0 :                 errno = ENOMEM;
     270           0 :                 return -1;
     271             :         }
     272             : 
     273    10771965 :         dn_len = strlen(dn) + NULL_PAD_BYTE_LEN;
     274    10771965 :         if (size + dn_len < size) {
     275           0 :                 errno = ENOMEM;
     276           0 :                 return -1;
     277             :         }
     278    10771965 :         size += dn_len;
     279             : 
     280    10771965 :         if (ldb_dn_is_special(message->dn)) {
     281     9252495 :                 dn_canon_len = NULL_PAD_BYTE_LEN;
     282     9252495 :                 dn_canon = discard_const_p(char, "\0");
     283             :         } else {
     284     1519470 :                 dn_canon = ldb_dn_canonical_string(message->dn, message->dn);
     285     1519470 :                 if (dn_canon == NULL) {
     286           0 :                         errno = ENOMEM;
     287           0 :                         return -1;
     288             :                 }
     289             : 
     290     1519470 :                 dn_canon_len = strlen(dn_canon) + NULL_PAD_BYTE_LEN;
     291     1519470 :                 if (size + dn_canon_len < size) {
     292           0 :                         errno = ENOMEM;
     293           0 :                         return -1;
     294             :                 }
     295             :         }
     296    10771965 :         size += dn_canon_len;
     297             : 
     298             :         /* Add the size required by each element */
     299    61155839 :         for (i=0;i<message->num_elements;i++) {
     300    50383874 :                 if (attribute_storable_values(&message->elements[i]) == 0) {
     301        1879 :                         continue;
     302             :                 }
     303             : 
     304    50381995 :                 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    50381995 :                 attr_len = strlen(message->elements[i].name);
     313    50381995 :                 if (size + attr_len + U32_LEN * 2 + NULL_PAD_BYTE_LEN < size) {
     314           0 :                         errno = ENOMEM;
     315           0 :                         return -1;
     316             :                 }
     317    50381995 :                 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    50381995 :                 max_val_len = 0;
     324   107052191 :                 for (j=0;j<message->elements[i].num_values;j++) {
     325    56670196 :                         value_len = message->elements[i].values[j].length;
     326    56670196 :                         if (value_len > max_val_len) {
     327    52489834 :                                 max_val_len = value_len;
     328             :                         }
     329             : 
     330    56670196 :                         if (size + value_len + NULL_PAD_BYTE_LEN < size) {
     331           0 :                                 errno = ENOMEM;
     332           0 :                                 return -1;
     333             :                         }
     334    56670196 :                         size += value_len + NULL_PAD_BYTE_LEN;
     335             :                 }
     336             : 
     337    50381995 :                 if (max_val_len <= UCHAR_MAX) {
     338    47138205 :                         val_len_width = U8_LEN;
     339     3243790 :                 } else if (max_val_len <= USHRT_MAX) {
     340     3224977 :                         val_len_width = U16_LEN;
     341       18813 :                 } else if (max_val_len <= UINT_MAX) {
     342       18813 :                         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    50381995 :                 max_val_len = (val_len_width*message->elements[i].num_values);
     350             : 
     351             :                 /* Add one for storing the width */
     352    50381995 :                 max_val_len += U8_LEN;
     353    50381995 :                 if (size + max_val_len < size) {
     354           0 :                         errno = ENOMEM;
     355           0 :                         return -1;
     356             :                 }
     357    50381995 :                 size += max_val_len;
     358             :         }
     359             : 
     360             :         /* Allocate */
     361    10771965 :         data->data = talloc_array(ldb, uint8_t, size);
     362    10771965 :         if (!data->data) {
     363           0 :                 errno = ENOMEM;
     364           0 :                 return -1;
     365             :         }
     366    10771965 :         data->length = size;
     367             : 
     368             :         /* Packing format version and number of element */
     369    10771965 :         p = data->data;
     370    10771965 :         PUSH_LE_U32(p, 0, LDB_PACKING_FORMAT_V2);
     371    10771965 :         p += U32_LEN;
     372    10771965 :         PUSH_LE_U32(p, 0, real_elements);
     373    10771965 :         p += U32_LEN;
     374             : 
     375             :         /* Pack DN and Canonicalized DN */
     376    10771965 :         PUSH_LE_U32(p, 0, dn_len-NULL_PAD_BYTE_LEN);
     377    10771965 :         p += U32_LEN;
     378    10771965 :         memcpy(p, dn, dn_len);
     379    10771965 :         p += dn_len;
     380             : 
     381    10771965 :         PUSH_LE_U32(p, 0, dn_canon_len-NULL_PAD_BYTE_LEN);
     382    10771965 :         p += U32_LEN;
     383    10771965 :         memcpy(p, dn_canon, dn_canon_len);
     384    10771965 :         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    10771965 :         q = p;
     392    10771965 :         p += U32_LEN;
     393             : 
     394    61155839 :         for (i=0;i<message->num_elements;i++) {
     395    50383874 :                 if (attribute_storable_values(&message->elements[i]) == 0) {
     396        1879 :                         continue;
     397             :                 }
     398             : 
     399             :                 /* Length of el name */
     400    50381995 :                 len = strlen(message->elements[i].name);
     401    50381995 :                 PUSH_LE_U32(p, 0, len);
     402    50381995 :                 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    50381995 :                 memcpy(p, message->elements[i].name, len+NULL_PAD_BYTE_LEN);
     411    50381995 :                 p += len + NULL_PAD_BYTE_LEN;
     412             :                 /* Num values */
     413    50381995 :                 PUSH_LE_U32(p, 0, message->elements[i].num_values);
     414    50381995 :                 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    50381995 :                 max_val_len = 0;
     422   107052191 :                 for (j=0;j<message->elements[i].num_values;j++) {
     423    56670196 :                         value_len = message->elements[i].values[j].length;
     424    56670196 :                         if (value_len > max_val_len) {
     425    52489834 :                                 max_val_len = value_len;
     426             :                         }
     427             :                 }
     428             : 
     429    50381995 :                 if (max_val_len <= UCHAR_MAX) {
     430    47138205 :                         val_len_width = U8_LEN;
     431     3243790 :                 } else if (max_val_len <= USHRT_MAX) {
     432     3224977 :                         val_len_width = U16_LEN;
     433       18813 :                 } else if (max_val_len <= UINT_MAX) {
     434       18813 :                         val_len_width = U32_LEN;
     435             :                 } else {
     436           0 :                         errno = EMSGSIZE;
     437           0 :                         return -1;
     438             :                 }
     439             : 
     440             :                 /* Pack the width */
     441    50381995 :                 *p = val_len_width & 0xFF;
     442    50381995 :                 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    50381995 :                 if (val_len_width == U8_LEN) {
     450    99873584 :                         for (j=0;j<message->elements[i].num_values;j++) {
     451    52735379 :                                 PUSH_LE_U8(p, 0,
     452             :                                         message->elements[i].values[j].length);
     453    52735379 :                                 p += U8_LEN;
     454             :                         }
     455     3243790 :                 } else if (val_len_width == U16_LEN) {
     456     7140981 :                         for (j=0;j<message->elements[i].num_values;j++) {
     457     3916004 :                                 PUSH_LE_U16(p, 0,
     458             :                                         message->elements[i].values[j].length);
     459     3916004 :                                 p += U16_LEN;
     460             :                         }
     461       18813 :                 } else if (val_len_width == U32_LEN) {
     462       37626 :                         for (j=0;j<message->elements[i].num_values;j++) {
     463       18813 :                                 PUSH_LE_U32(p, 0,
     464             :                                         message->elements[i].values[j].length);
     465       18813 :                                 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    10771965 :         PUSH_LE_U32(q, 0, p-q);
     476             : 
     477             :         /* Now pack the values */
     478    61155839 :         for (i=0;i<message->num_elements;i++) {
     479    50383874 :                 if (attribute_storable_values(&message->elements[i]) == 0) {
     480        1879 :                         continue;
     481             :                 }
     482   107052191 :                 for (j=0;j<message->elements[i].num_values;j++) {
     483    56670196 :                         memcpy(p, message->elements[i].values[j].data,
     484    56670196 :                                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    56670196 :                         p[message->elements[i].values[j].length] = 0;
     493    56670196 :                         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    10771965 :         if (p != data->data + size) {
     503           0 :                 errno = ENOMEM;
     504           0 :                 return -1;
     505             :         }
     506             : 
     507    10771965 :         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    15494626 : 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    15494626 :         if (pack_format_version == LDB_PACKING_FORMAT) {
     524     4722661 :                 return ldb_pack_data_v1(ldb, message, data);
     525    10771965 :         } else if (pack_format_version == LDB_PACKING_FORMAT_V2) {
     526    10771965 :                 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    22226141 : 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             :         uint8_t *p;
     543             :         size_t remaining;
     544             :         size_t dn_len;
     545             :         unsigned int i, j;
     546    22226141 :         unsigned int nelem = 0;
     547             :         size_t len;
     548    22226141 :         struct ldb_val *ldb_val_single_array = NULL;
     549             : 
     550    22226141 :         message->elements = NULL;
     551             : 
     552    22226141 :         p = data->data;
     553             : 
     554             :         /* Format (U32, already read) + U32 for num_elements */
     555    22226141 :         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    22226141 :         p += U32_LEN;
     562    22226141 :         message->num_elements = PULL_LE_U32(p, 0);
     563    22226141 :         p += U32_LEN;
     564             : 
     565    22226141 :         remaining = data->length - U32_LEN * 2;
     566             : 
     567    22226141 :         switch (format) {
     568           0 :         case LDB_PACKING_FORMAT_NODN:
     569           0 :                 message->dn = NULL;
     570           0 :                 break;
     571             : 
     572    22226141 :         case LDB_PACKING_FORMAT:
     573             :                 /*
     574             :                  * With this check, we know that the DN at p is \0
     575             :                  * terminated.
     576             :                  */
     577    22226141 :                 dn_len = strnlen((char *)p, remaining);
     578    22226141 :                 if (dn_len == remaining) {
     579           0 :                         errno = EIO;
     580           0 :                         goto failed;
     581             :                 }
     582    22226141 :                 if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
     583      732605 :                         message->dn = NULL;
     584    20039772 :                 } else {
     585             :                         struct ldb_val blob;
     586    21493536 :                         blob.data = discard_const_p(uint8_t, p);
     587    21493536 :                         blob.length = dn_len;
     588    21493536 :                         message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
     589    21493536 :                         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    22226141 :                 if (remaining < dn_len + NULL_PAD_BYTE_LEN) {
     600           0 :                         errno = EIO;
     601           0 :                         goto failed;
     602             :                 }
     603    22226141 :                 remaining -= dn_len + NULL_PAD_BYTE_LEN;
     604    22226141 :                 p += dn_len + NULL_PAD_BYTE_LEN;
     605    22226141 :                 break;
     606             : 
     607           0 :         default:
     608           0 :                 errno = EIO;
     609           0 :                 goto failed;
     610             :         }
     611             : 
     612    22226141 :         if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
     613     5646744 :                 return 0;
     614             :         }
     615             :         
     616    16579397 :         if (message->num_elements == 0) {
     617          33 :                 return 0;
     618             :         }
     619             : 
     620    16579364 :         if (message->num_elements > remaining / 6) {
     621           0 :                 errno = EIO;
     622           0 :                 goto failed;
     623             :         }
     624             : 
     625    16579364 :         message->elements = talloc_zero_array(message, struct ldb_message_element,
     626             :                                               message->num_elements);
     627    16579364 :         if (!message->elements) {
     628           0 :                 errno = ENOMEM;
     629           0 :                 goto failed;
     630             :         }
     631             : 
     632             :         /*
     633             :          * In typical use, most values are single-valued.  This makes
     634             :          * it quite expensive to allocate an array of ldb_val for each
     635             :          * of these, just to then hold the pointer to the data buffer
     636             :          * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
     637             :          * ahead of time and use it for the single values where possible.
     638             :          * (This is used the the normal search case, but not in the
     639             :          * index case because of caller requirements).
     640             :          */
     641    16579364 :         if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
     642     8611718 :                 ldb_val_single_array = talloc_array(message->elements, struct ldb_val,
     643             :                                                     message->num_elements);
     644     8611718 :                 if (ldb_val_single_array == NULL) {
     645           0 :                         errno = ENOMEM;
     646           0 :                         goto failed;
     647             :                 }
     648             :         }
     649             : 
     650   186212183 :         for (i=0;i<message->num_elements;i++) {
     651   169632819 :                 const char *attr = NULL;
     652             :                 size_t attr_len;
     653   169632819 :                 struct ldb_message_element *element = NULL;
     654             : 
     655             :                 /*
     656             :                  * Sanity check: Element must be at least the size of empty
     657             :                  * attr name and value and NULL terms for each.
     658             :                  */
     659   169632819 :                 if (remaining < U32_LEN * 2 + NULL_PAD_BYTE_LEN * 2) {
     660           0 :                         errno = EIO;
     661           0 :                         goto failed;
     662             :                 }
     663             : 
     664             :                 /*
     665             :                  * With this check, we know that the attribute name at
     666             :                  * p is \0 terminated.
     667             :                  */
     668   169632819 :                 attr_len = strnlen((char *)p, remaining-6);
     669   169632819 :                 if (attr_len == remaining-6) {
     670           0 :                         errno = EIO;
     671           0 :                         goto failed;
     672             :                 }
     673   169632819 :                 if (attr_len == 0) {
     674           0 :                         errno = EIO;
     675           0 :                         goto failed;
     676             :                 }
     677   169632819 :                 attr = (char *)p;
     678             : 
     679   169632819 :                 element = &message->elements[nelem];
     680   169632819 :                 element->name = attr;
     681   169632819 :                 element->flags = 0;
     682             : 
     683   169632819 :                 if (remaining < (attr_len + NULL_PAD_BYTE_LEN)) {
     684           0 :                         errno = EIO;
     685           0 :                         goto failed;
     686             :                 }
     687   169632819 :                 remaining -= attr_len + NULL_PAD_BYTE_LEN;
     688   169632819 :                 p += attr_len + NULL_PAD_BYTE_LEN;
     689   169632819 :                 element->num_values = PULL_LE_U32(p, 0);
     690   169632819 :                 element->values = NULL;
     691   169632819 :                 if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
     692   123107834 :                         element->values = &ldb_val_single_array[nelem];
     693   123107834 :                         element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
     694    46524985 :                 } else if (element->num_values != 0) {
     695    46524985 :                         element->values = talloc_array(message->elements,
     696             :                                                        struct ldb_val,
     697             :                                                        element->num_values);
     698    46524985 :                         if (!element->values) {
     699           0 :                                 errno = ENOMEM;
     700           0 :                                 goto failed;
     701             :                         }
     702             :                 }
     703   169632819 :                 p += U32_LEN;
     704   169632819 :                 if (remaining < U32_LEN) {
     705           0 :                         errno = EIO;
     706           0 :                         goto failed;
     707             :                 }
     708   169632819 :                 remaining -= U32_LEN;
     709   377141204 :                 for (j = 0; j < element->num_values; j++) {
     710             :                         /*
     711             :                          * Sanity check: Value must be at least the size of
     712             :                          * empty val and NULL terminator.
     713             :                          */
     714   207508385 :                         if (remaining < U32_LEN + NULL_PAD_BYTE_LEN) {
     715           0 :                                 errno = EIO;
     716           0 :                                 goto failed;
     717             :                         }
     718   207508385 :                         remaining -= U32_LEN + NULL_PAD_BYTE_LEN;
     719             : 
     720   207508385 :                         len = PULL_LE_U32(p, 0);
     721   207508385 :                         if (remaining < len) {
     722           0 :                                 errno = EIO;
     723           0 :                                 goto failed;
     724             :                         }
     725   207508385 :                         if (len + NULL_PAD_BYTE_LEN < len) {
     726           0 :                                 errno = EIO;
     727           0 :                                 goto failed;
     728             :                         }
     729             : 
     730   207508385 :                         element->values[j].length = len;
     731   207508385 :                         element->values[j].data = p + U32_LEN;
     732   207508385 :                         remaining -= len;
     733   207508385 :                         p += len + U32_LEN + NULL_PAD_BYTE_LEN;
     734             :                 }
     735   169632819 :                 nelem++;
     736             :         }
     737             :         /*
     738             :          * Adapt the number of elements to the real number of unpacked elements,
     739             :          * it means that we overallocated elements array.
     740             :          */
     741    16579364 :         message->num_elements = nelem;
     742             : 
     743             :         /*
     744             :          * Shrink the allocated size.  On current talloc behaviour
     745             :          * this will help if we skipped 32 or more attributes.
     746             :          */
     747    16579364 :         message->elements = talloc_realloc(message, message->elements,
     748             :                                            struct ldb_message_element,
     749             :                                            message->num_elements);
     750             : 
     751    16579364 :         if (remaining != 0) {
     752           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     753             :                           "Error: %zu bytes unread in ldb_unpack_data_flags",
     754             :                           remaining);
     755             :         }
     756             : 
     757    16579364 :         return 0;
     758             : 
     759           0 : failed:
     760           0 :         talloc_free(message->elements);
     761           0 :         return -1;
     762             : }
     763             : 
     764             : /*
     765             :  * Unpack a ldb message from a linear buffer in ldb_val
     766             :  */
     767   412194933 : static int ldb_unpack_data_flags_v2(struct ldb_context *ldb,
     768             :                                     const struct ldb_val *data,
     769             :                                     struct ldb_message *message,
     770             :                                     unsigned int flags)
     771             : {
     772             :         uint8_t *p, *q, *end_p, *value_section_p;
     773             :         unsigned int i, j;
     774   412194933 :         unsigned int nelem = 0;
     775             :         size_t len;
     776   412194933 :         struct ldb_val *ldb_val_single_array = NULL;
     777             :         uint8_t val_len_width;
     778             : 
     779   412194933 :         message->elements = NULL;
     780             : 
     781   412194933 :         p = data->data;
     782   412194933 :         end_p = p + data->length;
     783             : 
     784             :         /* Skip first 4 bytes, format already read */
     785   412194933 :         p += U32_LEN;
     786             : 
     787             :         /* First fields are fixed: num_elements, DN length */
     788   412194933 :         if (p + U32_LEN * 2 > end_p) {
     789           0 :                 errno = EIO;
     790           0 :                 goto failed;
     791             :         }
     792             : 
     793   412194933 :         message->num_elements = PULL_LE_U32(p, 0);
     794   412194933 :         p += U32_LEN;
     795             : 
     796   412194933 :         len = PULL_LE_U32(p, 0);
     797   412194933 :         p += U32_LEN;
     798             : 
     799   412194933 :         if (p + len + NULL_PAD_BYTE_LEN > end_p) {
     800           0 :                 errno = EIO;
     801           0 :                 goto failed;
     802             :         }
     803             : 
     804   412194933 :         if (flags & LDB_UNPACK_DATA_FLAG_NO_DN) {
     805    95280303 :                 message->dn = NULL;
     806             :         } else {
     807             :                 struct ldb_val blob;
     808   316914630 :                 blob.data = discard_const_p(uint8_t, p);
     809   316914630 :                 blob.length = len;
     810   316914630 :                 message->dn = ldb_dn_from_ldb_val(message, ldb, &blob);
     811   316914630 :                 if (message->dn == NULL) {
     812           0 :                         errno = ENOMEM;
     813           0 :                         goto failed;
     814             :                 }
     815             :         }
     816             : 
     817   412194933 :         p += len + NULL_PAD_BYTE_LEN;
     818             : 
     819   412194933 :         if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
     820           0 :                 errno = EINVAL;
     821           0 :                 goto failed;
     822             :         }
     823             : 
     824             :         /* Now skip the canonicalized DN and its length */
     825   412194933 :         len = PULL_LE_U32(p, 0) + NULL_PAD_BYTE_LEN;
     826   412194933 :         p += U32_LEN;
     827             : 
     828   412194933 :         if (p + len > end_p) {
     829           0 :                 errno = EIO;
     830           0 :                 goto failed;
     831             :         }
     832             : 
     833   412194933 :         p += len;
     834             : 
     835   412194933 :         if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
     836           0 :                 errno = EINVAL;
     837           0 :                 goto failed;
     838             :         }
     839             : 
     840   412194933 :         if (flags & LDB_UNPACK_DATA_FLAG_NO_ATTRS) {
     841    75648971 :                 return 0;
     842             :         }
     843             : 
     844   336545962 :         if (message->num_elements == 0) {
     845          32 :                 return 0;
     846             :         }
     847             : 
     848             :         /*
     849             :          * Sanity check (17 bytes is the minimum element size)
     850             :          */
     851   336545930 :         if (message->num_elements > (end_p - p) / 17) {
     852           0 :                 errno = EIO;
     853           0 :                 goto failed;
     854             :         }
     855             : 
     856   336545930 :         message->elements = talloc_zero_array(message,
     857             :                                               struct ldb_message_element,
     858             :                                               message->num_elements);
     859   336545930 :         if (!message->elements) {
     860           0 :                 errno = ENOMEM;
     861           0 :                 goto failed;
     862             :         }
     863             : 
     864             :         /*
     865             :          * In typical use, most values are single-valued.  This makes
     866             :          * it quite expensive to allocate an array of ldb_val for each
     867             :          * of these, just to then hold the pointer to the data buffer.
     868             :          * So with LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this
     869             :          * ahead of time and use it for the single values where possible.
     870             :          * (This is used the the normal search case, but not in the
     871             :          * index case because of caller requirements).
     872             :          */
     873   336545930 :         if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
     874   193437667 :                 ldb_val_single_array = talloc_array(message->elements,
     875             :                                                     struct ldb_val,
     876             :                                                     message->num_elements);
     877   193437667 :                 if (ldb_val_single_array == NULL) {
     878           0 :                         errno = ENOMEM;
     879           0 :                         goto failed;
     880             :                 }
     881             :         }
     882             : 
     883   336545930 :         q = p + PULL_LE_U32(p, 0);
     884   336545930 :         value_section_p = q;
     885   336545930 :         p += U32_LEN;
     886             : 
     887  4771081092 :         for (i=0;i<message->num_elements;i++) {
     888  4434535162 :                 const char *attr = NULL;
     889             :                 size_t attr_len;
     890  4434535162 :                 struct ldb_message_element *element = NULL;
     891             : 
     892             :                 /* Sanity check: minimum element size */
     893  4434535162 :                 if (p + (U32_LEN * 2) + /* attr name len, num values */
     894  4434535162 :                         (U8_LEN * 2) + /* value length width, one val length */
     895             :                         (NULL_PAD_BYTE_LEN * 2) /* null for attr name + val */
     896             :                         > value_section_p) {
     897           0 :                         errno = EIO;
     898           0 :                         goto failed;
     899             :                 }
     900             : 
     901  4434535162 :                 attr_len = PULL_LE_U32(p, 0);
     902  4434535162 :                 p += U32_LEN;
     903             : 
     904  4434535162 :                 if (attr_len == 0) {
     905           0 :                         errno = EIO;
     906           0 :                         goto failed;
     907             :                 }
     908  4434535162 :                 attr = (char *)p;
     909             : 
     910  4434535162 :                 p += attr_len + NULL_PAD_BYTE_LEN;
     911             :                 /*
     912             :                  * num_values, val_len_width
     913             :                  *
     914             :                  * val_len_width is the width specifier
     915             :                  * for the variable length encoding
     916             :                  */
     917  4434535162 :                 if (p + U32_LEN + U8_LEN > value_section_p) {
     918           0 :                         errno = EIO;
     919           0 :                         goto failed;
     920             :                 }
     921             : 
     922  4434535162 :                 if (*(p-NULL_PAD_BYTE_LEN) != '\0') {
     923           0 :                         errno = EINVAL;
     924           0 :                         goto failed;
     925             :                 }
     926             : 
     927  4434535162 :                 element = &message->elements[nelem];
     928  4434535162 :                 element->name = attr;
     929  4434535162 :                 element->flags = 0;
     930             : 
     931  4434535162 :                 element->num_values = PULL_LE_U32(p, 0);
     932  4434535162 :                 element->values = NULL;
     933  7566313758 :                 if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) &&
     934  4102023361 :                     element->num_values == 1) {
     935  3856210539 :                         element->values = &ldb_val_single_array[nelem];
     936  3856210539 :                         element->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
     937   578324623 :                 } else if (element->num_values != 0) {
     938   578324623 :                         element->values = talloc_array(message->elements,
     939             :                                                        struct ldb_val,
     940             :                                                        element->num_values);
     941   578324623 :                         if (!element->values) {
     942           0 :                                 errno = ENOMEM;
     943           0 :                                 goto failed;
     944             :                         }
     945             :                 }
     946             : 
     947  4434535162 :                 p += U32_LEN;
     948             : 
     949             :                 /*
     950             :                  * Here we read how wide the remaining lengths are
     951             :                  * which avoids storing and parsing a lot of leading
     952             :                  * 0s
     953             :                  */
     954  4434535162 :                 val_len_width = *p;
     955  4434535162 :                 p += U8_LEN;
     956             : 
     957  4434535162 :                 if (p + val_len_width * element->num_values >
     958             :                     value_section_p) {
     959           0 :                         errno = EIO;
     960           0 :                         goto failed;
     961             :                 }
     962             : 
     963             :                 /*
     964             :                  * This is structured weird for compiler optimization
     965             :                  * purposes, but we need to pull the array of widths
     966             :                  * with different macros depending on how wide the
     967             :                  * biggest one is (specified by val_len_width)
     968             :                  */
     969  4434535162 :                 if (val_len_width == U8_LEN) {
     970  8807960953 :                         for (j = 0; j < element->num_values; j++) {
     971  4706268207 :                                 element->values[j].length = PULL_LE_U8(p, 0);
     972  4706268207 :                                 p += U8_LEN;
     973             :                         }
     974   332842416 :                 } else if (val_len_width == U16_LEN) {
     975   698705051 :                         for (j = 0; j < element->num_values; j++) {
     976   365908868 :                                 element->values[j].length = PULL_LE_U16(p, 0);
     977   365908868 :                                 p += U16_LEN;
     978             :                         }
     979       46233 :                 } else if (val_len_width == U32_LEN) {
     980       92466 :                         for (j = 0; j < element->num_values; j++) {
     981       46233 :                                 element->values[j].length = PULL_LE_U32(p, 0);
     982       46233 :                                 p += U32_LEN;
     983             :                         }
     984             :                 } else {
     985           0 :                         errno = ERANGE;
     986           0 :                         goto failed;
     987             :                 }
     988             : 
     989  9506758470 :                 for (j = 0; j < element->num_values; j++) {
     990  5072223308 :                         len = element->values[j].length;
     991  5072223308 :                         if (len + NULL_PAD_BYTE_LEN < len) {
     992           0 :                                 errno = EIO;
     993           0 :                                 goto failed;
     994             :                         }
     995  5072223308 :                         if (q + len + NULL_PAD_BYTE_LEN > end_p) {
     996           0 :                                 errno = EIO;
     997           0 :                                 goto failed;
     998             :                         }
     999             : 
    1000  5072223308 :                         element->values[j].data = q;
    1001  5072223308 :                         q += len + NULL_PAD_BYTE_LEN;
    1002             :                 }
    1003  4434535162 :                 nelem++;
    1004             :         }
    1005             : 
    1006             :         /*
    1007             :          * If p isn't now pointing at the beginning of the value section,
    1008             :          * something went very wrong.
    1009             :          */
    1010   336545930 :         if (p != value_section_p) {
    1011           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
    1012             :                           "Error: Data corruption in ldb_unpack_data_flags");
    1013           0 :                 errno = EIO;
    1014           0 :                 goto failed;
    1015             :         }
    1016             : 
    1017             :         /*
    1018             :          * Adapt the number of elements to the real number of unpacked
    1019             :          * elements it means that we overallocated elements array.
    1020             :          */
    1021   336545930 :         message->num_elements = nelem;
    1022             : 
    1023             :         /*
    1024             :          * Shrink the allocated size.  On current talloc behaviour
    1025             :          * this will help if we skipped 32 or more attributes.
    1026             :          */
    1027   336545930 :         message->elements = talloc_realloc(message, message->elements,
    1028             :                                            struct ldb_message_element,
    1029             :                                            message->num_elements);
    1030             : 
    1031   336545930 :         if (q != end_p) {
    1032           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
    1033             :                           "Error: %zu bytes unread in ldb_unpack_data_flags",
    1034             :                           end_p - q);
    1035           0 :                 errno = EIO;
    1036           0 :                 goto failed;
    1037             :         }
    1038             : 
    1039   336545930 :         return 0;
    1040             : 
    1041           0 : failed:
    1042           0 :         talloc_free(message->elements);
    1043           0 :         return -1;
    1044             : }
    1045             : 
    1046    27684864 : int ldb_unpack_get_format(const struct ldb_val *data,
    1047             :                           uint32_t *pack_format_version)
    1048             : {
    1049    27684864 :         if (data->length < U32_LEN) {
    1050           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    1051             :         }
    1052    27684864 :         *pack_format_version = PULL_LE_U32(data->data, 0);
    1053    27684864 :         return LDB_SUCCESS;
    1054             : }
    1055             : 
    1056             : /*
    1057             :  * Unpack a ldb message from a linear buffer in ldb_val
    1058             :  */
    1059   434421074 : int ldb_unpack_data_flags(struct ldb_context *ldb,
    1060             :                           const struct ldb_val *data,
    1061             :                           struct ldb_message *message,
    1062             :                           unsigned int flags)
    1063             : {
    1064             :         unsigned format;
    1065             : 
    1066   434421074 :         if (data->length < U32_LEN) {
    1067           0 :                 errno = EIO;
    1068           0 :                 return -1;
    1069             :         }
    1070             : 
    1071   434421074 :         format = PULL_LE_U32(data->data, 0);
    1072   434421074 :         if (format == LDB_PACKING_FORMAT_V2) {
    1073   412194933 :                 return ldb_unpack_data_flags_v2(ldb, data, message, flags);
    1074             :         }
    1075             : 
    1076             :         /*
    1077             :          * The v1 function we're about to call takes either LDB_PACKING_FORMAT
    1078             :          * or LDB_PACKING_FORMAT_NODN packing format versions, and will error
    1079             :          * if given some other version, so we don't need to do any further
    1080             :          * checks on 'format'.
    1081             :          */
    1082    22226141 :         return ldb_unpack_data_flags_v1(ldb, data, message, flags, format);
    1083             : }
    1084             : 
    1085             : 
    1086             : /*
    1087             :  * Unpack a ldb message from a linear buffer in ldb_val
    1088             :  *
    1089             :  * Free with ldb_unpack_data_free()
    1090             :  */
    1091     5487075 : int ldb_unpack_data(struct ldb_context *ldb,
    1092             :                     const struct ldb_val *data,
    1093             :                     struct ldb_message *message)
    1094             : {
    1095     5487075 :         return ldb_unpack_data_flags(ldb, data, message, 0);
    1096             : }
    1097             : 
    1098             : /*
    1099             :   add the special distinguishedName element
    1100             : */
    1101   117671537 : int ldb_msg_add_distinguished_name(struct ldb_message *msg)
    1102             : {
    1103   117671537 :         const char *dn_attr = "distinguishedName";
    1104   117671537 :         char *dn = NULL;
    1105             : 
    1106   117671537 :         if (ldb_msg_find_element(msg, dn_attr)) {
    1107             :                 /*
    1108             :                  * This should not happen, but this is
    1109             :                  * existing behaviour...
    1110             :                  */
    1111           0 :                 return LDB_SUCCESS;
    1112             :         }
    1113             : 
    1114   117671537 :         dn = ldb_dn_alloc_linearized(msg, msg->dn);
    1115   117671537 :         if (dn == NULL) {
    1116           1 :                 return LDB_ERR_OPERATIONS_ERROR;
    1117             :         }
    1118             : 
    1119   117671536 :         return ldb_msg_add_steal_string(msg, dn_attr, dn);
    1120             : }
    1121             : 
    1122             : /*
    1123             :  * filter the specified list of attributes from msg,
    1124             :  * adding requested attributes, and perhaps all for *,
    1125             :  * but not the DN to filtered_msg.
    1126             :  */
    1127          14 : int ldb_filter_attrs(struct ldb_context *ldb,
    1128             :                      const struct ldb_message *msg,
    1129             :                      const char *const *attrs,
    1130             :                      struct ldb_message *filtered_msg)
    1131             : {
    1132             :         unsigned int i;
    1133          14 :         bool keep_all = false;
    1134          14 :         bool add_dn = false;
    1135             :         uint32_t num_elements;
    1136             :         uint32_t elements_size;
    1137             : 
    1138          14 :         if (attrs) {
    1139             :                 /* check for special attrs */
    1140          27 :                 for (i = 0; attrs[i]; i++) {
    1141          18 :                         int cmp = strcmp(attrs[i], "*");
    1142          18 :                         if (cmp == 0) {
    1143           5 :                                 keep_all = true;
    1144           5 :                                 break;
    1145             :                         }
    1146          13 :                         cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
    1147          13 :                         if (cmp == 0) {
    1148           1 :                                 add_dn = true;
    1149             :                         }
    1150             :                 }
    1151             :         } else {
    1152           0 :                 keep_all = true;
    1153             :         }
    1154             : 
    1155          14 :         if (keep_all) {
    1156           5 :                 add_dn = true;
    1157           5 :                 elements_size = msg->num_elements + 1;
    1158             : 
    1159             :         /* Shortcuts for the simple cases */
    1160           9 :         } else if (add_dn && i == 1) {
    1161           1 :                 if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
    1162           0 :                         goto failed;
    1163             :                 }
    1164           1 :                 return 0;
    1165           8 :         } else if (i == 0) {
    1166           1 :                 return 0;
    1167             : 
    1168             :         /*
    1169             :          * Otherwise we are copying at most as many elements as we
    1170             :          * have attributes
    1171             :          */
    1172             :         } else {
    1173           7 :                 elements_size = i;
    1174             :         }
    1175             : 
    1176          12 :         filtered_msg->elements = talloc_array(filtered_msg,
    1177             :                                               struct ldb_message_element,
    1178             :                                               elements_size);
    1179          12 :         if (filtered_msg->elements == NULL) goto failed;
    1180             : 
    1181          12 :         num_elements = 0;
    1182             : 
    1183          30 :         for (i = 0; i < msg->num_elements; i++) {
    1184          19 :                 struct ldb_message_element *el = &msg->elements[i];
    1185             : 
    1186             :                 /*
    1187             :                  * el2 is assigned after the Pigeonhole principle
    1188             :                  * check below for clarity
    1189             :                  */
    1190          19 :                 struct ldb_message_element *el2 = NULL;
    1191             :                 unsigned int j;
    1192             : 
    1193          19 :                 if (keep_all == false) {
    1194          12 :                         bool found = false;
    1195          14 :                         for (j = 0; attrs[j]; j++) {
    1196          13 :                                 int cmp = ldb_attr_cmp(el->name, attrs[j]);
    1197          13 :                                 if (cmp == 0) {
    1198          11 :                                         found = true;
    1199          11 :                                         break;
    1200             :                                 }
    1201             :                         }
    1202          12 :                         if (found == false) {
    1203           1 :                                 continue;
    1204             :                         }
    1205             :                 }
    1206             : 
    1207             :                 /*
    1208             :                  * Pigeonhole principle: we can't have more elements
    1209             :                  * than the number of attributes if they are unique in
    1210             :                  * the DB.
    1211             :                  */
    1212          18 :                 if (num_elements >= elements_size) {
    1213           1 :                         goto failed;
    1214             :                 }
    1215             : 
    1216          17 :                 el2 = &filtered_msg->elements[num_elements];
    1217             : 
    1218          17 :                 *el2 = *el;
    1219          17 :                 el2->name = talloc_strdup(filtered_msg->elements,
    1220             :                                           el->name);
    1221          17 :                 if (el2->name == NULL) {
    1222           0 :                         goto failed;
    1223             :                 }
    1224          17 :                 el2->values = talloc_array(filtered_msg->elements,
    1225             :                                            struct ldb_val, el->num_values);
    1226          17 :                 if (el2->values == NULL) {
    1227           0 :                         goto failed;
    1228             :                 }
    1229          34 :                 for (j=0;j<el->num_values;j++) {
    1230          17 :                         el2->values[j] = ldb_val_dup(el2->values, &el->values[j]);
    1231          17 :                         if (el2->values[j].data == NULL && el->values[j].length != 0) {
    1232           0 :                                 goto failed;
    1233             :                         }
    1234             :                 }
    1235          17 :                 num_elements++;
    1236             :         }
    1237             : 
    1238          11 :         filtered_msg->num_elements = num_elements;
    1239             : 
    1240          11 :         if (add_dn) {
    1241           5 :                 if (ldb_msg_add_distinguished_name(filtered_msg) != 0) {
    1242           1 :                         goto failed;
    1243             :                 }
    1244             :         }
    1245             : 
    1246          10 :         if (filtered_msg->num_elements > 0) {
    1247             :                 filtered_msg->elements
    1248          10 :                         = talloc_realloc(filtered_msg,
    1249             :                                          filtered_msg->elements,
    1250             :                                          struct ldb_message_element,
    1251             :                                          filtered_msg->num_elements);
    1252          10 :                 if (filtered_msg->elements == NULL) {
    1253           0 :                         goto failed;
    1254             :                 }
    1255             :         } else {
    1256           0 :                 TALLOC_FREE(filtered_msg->elements);
    1257             :         }
    1258             : 
    1259          10 :         return 0;
    1260           2 : failed:
    1261           2 :         TALLOC_FREE(filtered_msg->elements);
    1262           2 :         return -1;
    1263             : }
    1264             : 
    1265             : /*
    1266             :  * filter the specified list of attributes from msg,
    1267             :  * adding requested attributes, and perhaps all for *.
    1268             :  * Unlike ldb_filter_attrs(), the DN will not be added
    1269             :  * if it is missing.
    1270             :  */
    1271   117671545 : int ldb_filter_attrs_in_place(struct ldb_message *msg,
    1272             :                               const char *const *attrs)
    1273             : {
    1274   117671545 :         unsigned int i = 0;
    1275   117671545 :         bool keep_all = false;
    1276   117671545 :         unsigned int num_del = 0;
    1277             : 
    1278   117671545 :         if (attrs) {
    1279             :                 /* check for special attrs */
    1280  3200167791 :                 for (i = 0; attrs[i]; i++) {
    1281  3087607897 :                         int cmp = strcmp(attrs[i], "*");
    1282  3087607897 :                         if (cmp == 0) {
    1283     3770349 :                                 keep_all = true;
    1284     3770349 :                                 break;
    1285             :                         }
    1286             :                 }
    1287   116330243 :                 if (!keep_all && i == 0) {
    1288     9728286 :                         msg->num_elements = 0;
    1289     9728286 :                         return LDB_SUCCESS;
    1290             :                 }
    1291             :         } else {
    1292     1341302 :                 keep_all = true;
    1293             :         }
    1294             : 
    1295  2739493154 :         for (i = 0; i < msg->num_elements; i++) {
    1296  2631549895 :                 bool found = false;
    1297             :                 unsigned int j;
    1298             : 
    1299  2631549895 :                 if (keep_all) {
    1300   117856273 :                         found = true;
    1301             :                 } else {
    1302 46737127681 :                         for (j = 0; attrs[j]; j++) {
    1303 45304693028 :                                 int cmp = ldb_attr_cmp(msg->elements[i].name, attrs[j]);
    1304 45304693028 :                                 if (cmp == 0) {
    1305  1081258969 :                                         found = true;
    1306  1081258969 :                                         break;
    1307             :                                 }
    1308             :                         }
    1309             :                 }
    1310             : 
    1311  2631549895 :                 if (!found) {
    1312  1432434653 :                         ++num_del;
    1313  1199115242 :                 } else if (num_del != 0) {
    1314   950539960 :                         msg->elements[i - num_del] = msg->elements[i];
    1315             :                 }
    1316             :         }
    1317             : 
    1318   107943259 :         msg->num_elements -= num_del;
    1319             : 
    1320   107943259 :         return LDB_SUCCESS;
    1321             : }
    1322             : 
    1323             : /* Have an unpacked ldb message take talloc ownership of its elements. */
    1324   117671531 : int ldb_msg_elements_take_ownership(struct ldb_message *msg)
    1325             : {
    1326   117671531 :         unsigned int i = 0;
    1327             : 
    1328  1316786750 :         for (i = 0; i < msg->num_elements; i++) {
    1329  1199115219 :                 struct ldb_message_element *el = &msg->elements[i];
    1330             :                 const char *name;
    1331             :                 unsigned int j;
    1332             : 
    1333  1199115219 :                 name = talloc_strdup(msg->elements,
    1334             :                                      el->name);
    1335  1199115219 :                 if (name == NULL) {
    1336           0 :                         return -1;
    1337             :                 }
    1338  1199115219 :                 el->name = name;
    1339             : 
    1340  1199115219 :                 if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
    1341  1107677516 :                         struct ldb_val *values = talloc_memdup(msg->elements, el->values,
    1342             :                                                                sizeof(struct ldb_val) * el->num_values);
    1343  1107677516 :                         if (values == NULL) {
    1344           0 :                                 return -1;
    1345             :                         }
    1346  1107677516 :                         el->values = values;
    1347  1107677516 :                         el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
    1348             :                 }
    1349             : 
    1350  2577191670 :                 for (j = 0; j < el->num_values; j++) {
    1351  1378076451 :                         struct ldb_val val = ldb_val_dup(el->values, &el->values[j]);
    1352  1378076451 :                         if (val.data == NULL && el->values[j].length != 0) {
    1353           0 :                                 return -1;
    1354             :                         }
    1355  1378076451 :                         el->values[j] = val;
    1356             :                 }
    1357             :         }
    1358             : 
    1359   117671531 :         return LDB_SUCCESS;
    1360             : }

Generated by: LCOV version 1.13