LCOV - code coverage report
Current view: top level - lib/util - data_blob.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 105 121 86.8 %
Date: 2024-04-21 15:09:00 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             : #include "lib/util/tsort.h"
      26             : 
      27             : const DATA_BLOB data_blob_null = { NULL, 0 };
      28             : 
      29             : /**
      30             :  * @file
      31             :  * @brief Manipulation of arbitrary data blobs
      32             :  **/
      33             : 
      34             : /**
      35             :  construct a data blob, must be freed with data_blob_free()
      36             :  you can pass NULL for p and get a blank data blob
      37             : **/
      38     3271255 : _PUBLIC_ DATA_BLOB data_blob_named(const void *p, size_t length, const char *name)
      39             : {
      40     3271255 :         return data_blob_talloc_named(NULL, p, length, name);
      41             : }
      42             : 
      43             : /**
      44             :  construct a data blob, using supplied TALLOC_CTX
      45             : **/
      46   381703203 : _PUBLIC_ DATA_BLOB data_blob_talloc_named(TALLOC_CTX *mem_ctx, const void *p, size_t length, const char *name)
      47             : {
      48     5254260 :         DATA_BLOB ret;
      49             : 
      50   381703203 :         if (p == NULL && length == 0) {
      51     3150549 :                 ZERO_STRUCT(ret);
      52     3150549 :                 return ret;
      53             :         }
      54             : 
      55   378552654 :         if (p) {
      56   234645007 :                 ret.data = (uint8_t *)talloc_memdup(mem_ctx, p, length);
      57             :         } else {
      58   143907647 :                 ret.data = talloc_array(mem_ctx, uint8_t, length);
      59             :         }
      60   378552654 :         if (ret.data == NULL) {
      61           0 :                 ret.length = 0;
      62           0 :                 return ret;
      63             :         }
      64   378552654 :         talloc_set_name_const(ret.data, name);
      65   378552654 :         ret.length = length;
      66   378552654 :         return ret;
      67             : }
      68             : 
      69             : /**
      70             :  construct a zero data blob, using supplied TALLOC_CTX. 
      71             :  use this sparingly as it initialises data - better to initialise
      72             :  yourself if you want specific data in the blob
      73             : **/
      74      547444 : _PUBLIC_ DATA_BLOB data_blob_talloc_zero(TALLOC_CTX *mem_ctx, size_t length)
      75             : {
      76      547444 :         DATA_BLOB blob = data_blob_talloc(mem_ctx, NULL, length);
      77      547444 :         data_blob_clear(&blob);
      78      547444 :         return blob;
      79             : }
      80             : 
      81             : /**
      82             : free a data blob
      83             : **/
      84   118498938 : _PUBLIC_ void data_blob_free(DATA_BLOB *d)
      85             : {
      86   118498938 :         if (d) {
      87   118498904 :                 TALLOC_FREE(d->data);
      88   118498904 :                 d->length = 0;
      89             :         }
      90   118498938 : }
      91             : 
      92             : /**
      93             : clear a DATA_BLOB's contents
      94             : **/
      95     1609445 : _PUBLIC_ void data_blob_clear(DATA_BLOB *d)
      96             : {
      97     1609445 :         if (d->data) {
      98     1164504 :                 memset_s(d->data, d->length, 0, d->length);
      99             :         }
     100     1609445 : }
     101             : 
     102             : /**
     103             : free a data blob and clear its contents
     104             : **/
     105      733335 : _PUBLIC_ void data_blob_clear_free(DATA_BLOB *d)
     106             : {
     107      733335 :         data_blob_clear(d);
     108      733335 :         data_blob_free(d);
     109      733335 : }
     110             : 
     111             : 
     112             : /**
     113             : check if two data blobs are equal
     114             : **/
     115    18400682 : _PUBLIC_ int data_blob_cmp(const DATA_BLOB *d1, const DATA_BLOB *d2)
     116             : {
     117      545714 :         int ret;
     118    18400682 :         if (d1->data == NULL && d2->data != NULL) {
     119           0 :                 return -1;
     120             :         }
     121    18400682 :         if (d1->data != NULL && d2->data == NULL) {
     122           0 :                 return 1;
     123             :         }
     124    18400682 :         if (d1->data == d2->data) {
     125       19438 :                 return NUMERIC_CMP(d1->length, d2->length);
     126             :         }
     127    18381244 :         ret = memcmp(d1->data, d2->data, MIN(d1->length, d2->length));
     128    18381244 :         if (ret == 0) {
     129             :                 /* Note this ordering is used in conditional aces */
     130     7431344 :                 return NUMERIC_CMP(d1->length, d2->length);
     131             :         }
     132    10869104 :         return ret;
     133             : }
     134             : 
     135             : /**
     136             : check if two data blobs are equal, where the time taken should not depend on the
     137             : contents of either blob.
     138             : **/
     139        2476 : _PUBLIC_ bool data_blob_equal_const_time(const DATA_BLOB *d1, const DATA_BLOB *d2)
     140             : {
     141          78 :         bool ret;
     142        2476 :         if (d1->data == NULL && d2->data != NULL) {
     143           0 :                 return false;
     144             :         }
     145        2472 :         if (d1->data != NULL && d2->data == NULL) {
     146           0 :                 return false;
     147             :         }
     148        2468 :         if (d1->length != d2->length) {
     149           0 :                 return false;
     150             :         }
     151        2462 :         if (d1->data == d2->data) {
     152           0 :                 return true;
     153             :         }
     154        2457 :         ret = mem_equal_const_time(d1->data, d2->data, d1->length);
     155        2457 :         return ret;
     156             : }
     157             : 
     158             : /**
     159             : print the data_blob as hex string
     160             : **/
     161     8744824 : _PUBLIC_ char *data_blob_hex_string_lower(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     162             : {
     163      218398 :         size_t i;
     164      218398 :         char *hex_string;
     165             : 
     166     8744824 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     167     8744824 :         if (!hex_string) {
     168           0 :                 return NULL;
     169             :         }
     170             : 
     171             :         /* this must be lowercase or w2k8 cannot join a samba domain,
     172             :            as this routine is used to encode extended DNs and windows
     173             :            only accepts lowercase hexadecimal numbers */
     174   156832448 :         for (i = 0; i < blob->length; i++)
     175   148087624 :                 slprintf(&hex_string[i*2], 3, "%02x", blob->data[i]);
     176             : 
     177     8744824 :         hex_string[(blob->length*2)] = '\0';
     178     8744824 :         return hex_string;
     179             : }
     180             : 
     181    14708384 : _PUBLIC_ char *data_blob_hex_string_upper(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob)
     182             : {
     183       22422 :         size_t i;
     184       22422 :         char *hex_string;
     185             : 
     186    14708384 :         hex_string = talloc_array(mem_ctx, char, (blob->length*2)+1);
     187    14708384 :         if (!hex_string) {
     188           0 :                 return NULL;
     189             :         }
     190             : 
     191   439690171 :         for (i = 0; i < blob->length; i++)
     192   424981787 :                 slprintf(&hex_string[i*2], 3, "%02X", blob->data[i]);
     193             : 
     194    14708384 :         hex_string[(blob->length*2)] = '\0';
     195    14708384 :         return hex_string;
     196             : }
     197             : 
     198             : /**
     199             :   useful for constructing data blobs in test suites, while
     200             :   avoiding const warnings
     201             : **/
     202    89153801 : _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
     203             : {
     204     3409408 :         DATA_BLOB blob;
     205    89153801 :         blob.data = discard_const_p(uint8_t, str);
     206    89153801 :         blob.length = str ? strlen(str) : 0;
     207    89153801 :         return blob;
     208             : }
     209             : 
     210             : /**
     211             :   useful for constructing data blobs in test suites, while
     212             :   avoiding const warnings
     213             : **/
     214      612233 : _PUBLIC_ DATA_BLOB data_blob_string_const_null(const char *str)
     215             : {
     216        9228 :         DATA_BLOB blob;
     217      612233 :         blob.data = discard_const_p(uint8_t, str);
     218      612233 :         blob.length = str ? strlen(str)+1 : 0;
     219      612233 :         return blob;
     220             : }
     221             : 
     222             : /**
     223             :  * Create a new data blob from const data 
     224             :  */
     225             : 
     226    87199969 : _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length)
     227             : {
     228     1416466 :         DATA_BLOB blob;
     229    87199969 :         blob.data = discard_const_p(uint8_t, p);
     230    87199969 :         blob.length = length;
     231    87199969 :         return blob;
     232             : }
     233             : 
     234             : 
     235             : /**
     236             :   realloc a data_blob
     237             : **/
     238     4492210 : _PUBLIC_ bool data_blob_realloc(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, size_t length)
     239             : {
     240     4492210 :         uint8_t *tmp = talloc_realloc(mem_ctx, blob->data, uint8_t, length);
     241     4492210 :         if (tmp == NULL) {
     242           0 :                 return false;
     243             :         }
     244     4492210 :         blob->data = tmp;
     245     4492210 :         blob->length = length;
     246     4492210 :         return true;
     247             : }
     248             : 
     249             : 
     250             : /**
     251             :   append some data to a data blob
     252             : **/
     253     1233499 : _PUBLIC_ bool data_blob_append(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     254             :                                    const void *p, size_t length)
     255             : {
     256     1233499 :         size_t old_len = blob->length;
     257     1233499 :         size_t new_len = old_len + length;
     258             : 
     259     1233499 :         if (length == 0) {
     260        7610 :                 return true;
     261             :         }
     262             : 
     263     1225180 :         if (new_len < length || new_len < old_len) {
     264           0 :                 return false;
     265             :         }
     266             : 
     267     1225180 :         if ((const uint8_t *)p + length < (const uint8_t *)p) {
     268           0 :                 return false;
     269             :         }
     270             :         
     271     1225180 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     272           0 :                 return false;
     273             :         }
     274             : 
     275     1225180 :         memcpy(blob->data + old_len, p, length);
     276     1225180 :         return true;
     277             : }
     278             : 
     279             : /**
     280             :   pad the length of a data blob to a multiple of
     281             :   'pad'. 'pad' must be a power of two.
     282             : **/
     283       31067 : _PUBLIC_ bool data_blob_pad(TALLOC_CTX *mem_ctx, DATA_BLOB *blob,
     284             :                             size_t pad)
     285             : {
     286       31067 :         size_t old_len = blob->length;
     287       31067 :         size_t new_len = (old_len + pad - 1) & ~(pad - 1);
     288             : 
     289       31067 :         if (new_len < old_len) {
     290           0 :                 return false;
     291             :         }
     292             : 
     293       31067 :         if (!data_blob_realloc(mem_ctx, blob, new_len)) {
     294           0 :                 return false;
     295             :         }
     296             : 
     297       31067 :         memset(blob->data + old_len, 0, new_len - old_len);
     298       31067 :         return true;
     299             : }

Generated by: LCOV version 1.14