LCOV - code coverage report
Current view: top level - lib/util - data_blob.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 105 121 86.8 %
Date: 2023-11-21 12:31:41 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Easy management of byte-length data
       4             :    Copyright (C) Andrew Tridgell 2001
       5             :    Copyright (C) Andrew Bartlett 2001
       6             :    
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "replace.h"
      22             : #include "attr.h"
      23             : #include "data_blob.h"
      24             : #include "lib/util/samba_util.h"
      25             : 
      26             : const DATA_BLOB data_blob_null = { NULL, 0 };
      27             : 
      28             : /**
      29             :  * @file
      30             :  * @brief Manipulation of arbitrary data blobs
      31             :  **/
      32             : 
      33             : /**
      34             :  construct a data blob, must be freed with data_blob_free()
      35             :  you can pass NULL for p and get a blank data blob
      36             : **/
      37     3194430 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
      38             : {
      39     3194430 :         return data_blob_talloc_named(NULL, p, length, name);
      40             : }
      41             : 
      42             : /**
      43             :  construct a data blob, using supplied TALLOC_CTX
      44             : **/
      45   554480109 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
      46             : {
      47    11701012 :         DATA_BLOB ret;
      48             : 
      49   554480109 :         if (p == NULL && length == 0) {
      50     3071593 :                 ZERO_STRUCT(ret);
      51     3071593 :                 return ret;
      52             :         }
      53             : 
      54   551408516 :         if (p) {
      55   409340920 :                 ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
      56             :         } else {
      57   142067596 :                 ret.data = talloc_array(mem_ctx, uint8_t, length);
      58             :         }
      59   551408516 :         if (ret.data == NULL) {
      60           0 :                 ret.length = 0;
      61           0 :                 return ret;
      62             :         }
      63   551408516 :         talloc_set_name_const(ret.data, name);
      64   551408516 :         ret.length = length;
      65   551408516 :         return ret;
      66             : }
      67             : 
      68             : /**
      69             :  construct a zero data blob, using supplied TALLOC_CTX. 
      70             :  use this sparingly as it initialises data - better to initialise
      71             :  yourself if you want specific data in the blob
      72             : **/
      73      542784 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
      74             : {
      75      542784 :         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
      76      542784 :         data_blob_clear(&blob);
      77      542784 :         return blob;
      78             : }
      79             : 
      80             : /**
      81             : free a data blob
      82             : **/
      83   117044153 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
      84             : {
      85   117044153 :         if (d) {
      86   117044119 :                 TALLOC_FREE(d->data);
      87   117044119 :                 d->length = 0;
      88             :         }
      89   117044153 : }
      90             : 
      91             : /**
      92             : clear a DATA_BLOB's contents
      93             : **/
      94     1579472 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
      95             : {
      96     1579472 :         if (d->data) {
      97     1140663 :                 memset_s(d->data, d->length, 0, d->length);
      98             :         }
      99     1579472 : }
     100             : 
     101             : /**
     102             : free a data blob and clear its contents
     103             : **/
     104      723892 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
     105             : {
     106      723892 :         data_blob_clear(d);
     107      723892 :         data_blob_free(d);
     108      723892 : }
     109             : 
     110             : 
     111             : /**
     112             : check if two data blobs are equal
     113             : **/
     114    18293843 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
     115             : {
     116      544505 :         int ret;
     117    18293843 :         if (d1->data == NULL && d2->data != NULL) {
     118           0 :                 return -1;
     119             :         }
     120    18293843 :         if (d1->data != NULL && d2->data == NULL) {
     121           0 :                 return 1;
     122             :         }
     123    18293843 :         if (d1->data == d2->data) {
     124       18433 :                 return d1->length - d2->length;
     125             :         }
     126    18275410 :         ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
     127    18275410 :         if (ret == 0) {
     128             :                 /* Note this ordering is used in conditional aces */
     129     7398342 :                 return d1->length - d2->length;
     130             :         }
     131    10796735 :         return ret;
     132             : }
     133             : 
     134             : /**
     135             : check if two data blobs are equal, where the time taken should not depend on the
     136             : contents of either blob.
     137             : **/
     138        2367 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
     139             : {
     140          78 :         bool ret;
     141        2367 :         if (d1->data == NULL && d2->data != NULL) {
     142           0 :                 return false;
     143             :         }
     144        2363 :         if (d1->data != NULL && d2->data == NULL) {
     145           0 :                 return false;
     146             :         }
     147        2359 :         if (d1->length != d2->length) {
     148           0 :                 return false;
     149             :         }
     150        2353 :         if (d1->data == d2->data) {
     151           0 :                 return true;
     152             :         }
     153        2348 :         ret = mem_equal_const_time(d1->data, d2->data, d1->length);
     154        2348 :         return ret;
     155             : }
     156             : 
     157             : /**
     158             : print the data_blob as hex string
     159             : **/
     160     8690299 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     161             : {
     162      218266 :         size_t i;
     163      218266 :         char *hex_string;
     164             : 
     165     8690299 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     166     8690299 :         if (!hex_string) {
     167           0 :                 return NULL;
     168             :         }
     169             : 
     170             :         /* this must be lowercase or w2k8 cannot join a samba domain,
     171             :            as this routine is used to encode extended DNs and windows
     172             :            only accepts lowercase hexadecimal numbers */
     173   155835303 :         for (i = 0; i < blob->length; i++)
     174   147145004 :                 slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
     175             : 
     176     8690299 :         hex_string[(blob->length*2)] = '\0';
     177     8690299 :         return hex_string;
     178             : }
     179             : 
     180    14440097 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     181             : {
     182       21608 :         size_t i;
     183       21608 :         char *hex_string;
     184             : 
     185    14440097 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     186    14440097 :         if (!hex_string) {
     187           0 :                 return NULL;
     188             :         }
     189             : 
     190   433096090 :         for (i = 0; i < blob->length; i++)
     191   418655993 :                 slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
     192             : 
     193    14440097 :         hex_string[(blob->length*2)] = '\0';
     194    14440097 :         return hex_string;
     195             : }
     196             : 
     197             : /**
     198             :   useful for constructing data blobs in test suites, while
     199             :   avoiding const warnings
     200             : **/
     201    88094356 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
     202             : {
     203     3394106 :         DATA_BLOB blob;
     204    88094356 :         blob.data = discard_const_p(uint8_t, str);
     205    88094356 :         blob.length = str ? strlen(str) : 0;
     206    88094356 :         return blob;
     207             : }
     208             : 
     209             : /**
     210             :   useful for constructing data blobs in test suites, while
     211             :   avoiding const warnings
     212             : **/
     213      606600 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
     214             : {
     215        9228 :         DATA_BLOB blob;
     216      606600 :         blob.data = discard_const_p(uint8_t, str);
     217      606600 :         blob.length = str ? strlen(str)+1 : 0;
     218      606600 :         return blob;
     219             : }
     220             : 
     221             : /**
     222             :  * Create a new data blob from const data 
     223             :  */
     224             : 
     225    85899143 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
     226             : {
     227     1393750 :         DATA_BLOB blob;
     228    85899143 :         blob.data = discard_const_p(uint8_t, p);
     229    85899143 :         blob.length = length;
     230    85899143 :         return blob;
     231             : }
     232             : 
     233             : 
     234             : /**
     235             :   realloc a data_blob
     236             : **/
     237     4472215 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
     238             : {
     239     4472215 :         uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
     240     4472215 :         if (tmp == NULL) {
     241           0 :                 return false;
     242             :         }
     243     4472215 :         blob->data = tmp;
     244     4472215 :         blob->length = length;
     245     4472215 :         return true;
     246             : }
     247             : 
     248             : 
     249             : /**
     250             :   append some data to a data blob
     251             : **/
     252     1221617 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     253             :                                    const void *p, size_t length)
     254             : {
     255     1221617 :         size_t old_len = blob->length;
     256     1221617 :         size_t new_len = old_len + length;
     257             : 
     258     1221617 :         if (length == 0) {
     259        7569 :                 return true;
     260             :         }
     261             : 
     262     1213339 :         if (new_len < length || new_len < old_len) {
     263           0 :                 return false;
     264             :         }
     265             : 
     266     1213339 :         if ((const uint8_t *)p + length < (const uint8_t *)p) {
     267           0 :                 return false;
     268             :         }
     269             :         
     270     1213339 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     271           0 :                 return false;
     272             :         }
     273             : 
     274     1213339 :         memcpy(blob->data + old_len, p, length);
     275     1213339 :         return true;
     276             : }
     277             : 
     278             : /**
     279             :   pad the length of a data blob to a multiple of
     280             :   'pad'. 'pad' must be a power of two.
     281             : **/
     282       30226 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     283             :                             size_t pad)
     284             : {
     285       30226 :         size_t old_len = blob->length;
     286       30226 :         size_t new_len = (old_len + pad - 1) & ~(pad - 1);
     287             : 
     288       30226 :         if (new_len < old_len) {
     289           0 :                 return false;
     290             :         }
     291             : 
     292       30226 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     293           0 :                 return false;
     294             :         }
     295             : 
     296       30226 :         memset(blob->data + old_len, 0, new_len - old_len);
     297       30226 :         return true;
     298             : }

Generated by: LCOV version 1.14