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

Generated by: LCOV version 1.14