LCOV - code coverage report
Current view: top level - source3/registry - reg_objects.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 149 196 76.0 %
Date: 2021-09-23 10:06:22 Functions: 28 32 87.5 %

          Line data    Source code
       1             : /*
       2             :  *  Unix SMB/CIFS implementation.
       3             :  *  Virtual Windows Registry Layer
       4             :  *  Copyright (C) Gerald Carter                     2002-2005
       5             :  *  Copyright (C) Michael Adam                      2007-2010
       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             : /* Implementation of registry frontend view functions. */
      22             : 
      23             : #include "includes.h"
      24             : #include "registry.h"
      25             : #include "reg_objects.h"
      26             : #include "util_tdb.h"
      27             : #include "dbwrap/dbwrap.h"
      28             : #include "dbwrap/dbwrap_rbt.h"
      29             : #include "../libcli/registry/util_reg.h"
      30             : #include "lib/util/string_wrappers.h"
      31             : 
      32             : #undef DBGC_CLASS
      33             : #define DBGC_CLASS DBGC_REGISTRY
      34             : 
      35             : /* low level structure to contain registry values */
      36             : 
      37             : struct regval_blob {
      38             :         fstring         valuename;
      39             :         uint32_t        type;
      40             :         /* this should be encapsulated in an RPC_DATA_BLOB */
      41             :         uint32_t        size;   /* in bytes */
      42             :         uint8_t         *data_p;
      43             : };
      44             : 
      45             : /* container for registry values */
      46             : 
      47             : struct regval_ctr {
      48             :         uint32_t num_values;
      49             :         struct regval_blob **values;
      50             :         int seqnum;
      51             : };
      52             : 
      53             : struct regsubkey_ctr {
      54             :         uint32_t        num_subkeys;
      55             :         char            **subkeys;
      56             :         struct db_context *subkeys_hash;
      57             :         int seqnum;
      58             : };
      59             : 
      60             : /**********************************************************************
      61             : 
      62             :  Note that the struct regsubkey_ctr and struct regval_ctr objects *must* be
      63             :  talloc()'d since the methods use the object pointer as the talloc
      64             :  context for internal private data.
      65             : 
      66             :  There is no longer a regval_ctr_init() and regval_ctr_destroy()
      67             :  pair of functions.  Simply talloc_zero() and TALLOC_FREE() the
      68             :  object.
      69             : 
      70             :  **********************************************************************/
      71             : 
      72     2442550 : WERROR regsubkey_ctr_init(TALLOC_CTX *mem_ctx, struct regsubkey_ctr **ctr)
      73             : {
      74     2442550 :         if (ctr == NULL) {
      75           0 :                 return WERR_INVALID_PARAMETER;
      76             :         }
      77             : 
      78     2442550 :         *ctr = talloc_zero(mem_ctx, struct regsubkey_ctr);
      79     2442550 :         if (*ctr == NULL) {
      80           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      81             :         }
      82             : 
      83     2442550 :         (*ctr)->subkeys_hash = db_open_rbt(*ctr);
      84     2442550 :         if ((*ctr)->subkeys_hash == NULL) {
      85           0 :                 talloc_free(*ctr);
      86           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      87             :         }
      88             : 
      89     2442550 :         return WERR_OK;
      90             : }
      91             : 
      92             : /**
      93             :  * re-initialize the list of subkeys (to the empty list)
      94             :  * in an already allocated regsubkey_ctr
      95             :  */
      96             : 
      97      426236 : WERROR regsubkey_ctr_reinit(struct regsubkey_ctr *ctr)
      98             : {
      99      426236 :         if (ctr == NULL) {
     100           0 :                 return WERR_INVALID_PARAMETER;
     101             :         }
     102             : 
     103      426236 :         talloc_free(ctr->subkeys_hash);
     104      426236 :         ctr->subkeys_hash = db_open_rbt(ctr);
     105      426236 :         W_ERROR_HAVE_NO_MEMORY(ctr->subkeys_hash);
     106             : 
     107      426236 :         TALLOC_FREE(ctr->subkeys);
     108             : 
     109      426236 :         ctr->num_subkeys = 0;
     110      426236 :         ctr->seqnum = 0;
     111             : 
     112      426236 :         return WERR_OK;
     113             : }
     114             : 
     115      419103 : WERROR regsubkey_ctr_set_seqnum(struct regsubkey_ctr *ctr, int seqnum)
     116             : {
     117      419103 :         if (ctr == NULL) {
     118           0 :                 return WERR_INVALID_PARAMETER;
     119             :         }
     120             : 
     121      419103 :         ctr->seqnum = seqnum;
     122             : 
     123      419103 :         return WERR_OK;
     124             : }
     125             : 
     126      313185 : int regsubkey_ctr_get_seqnum(struct regsubkey_ctr *ctr)
     127             : {
     128      313185 :         if (ctr == NULL) {
     129           0 :                 return -1;
     130             :         }
     131             : 
     132      313185 :         return ctr->seqnum;
     133             : }
     134             : 
     135     1424945 : static WERROR regsubkey_ctr_hash_keyname(struct regsubkey_ctr *ctr,
     136             :                                          const char *keyname,
     137             :                                          uint32_t idx)
     138             : {
     139             :         WERROR werr;
     140             : 
     141     1424945 :         werr = ntstatus_to_werror(dbwrap_store_bystring_upper(ctr->subkeys_hash,
     142             :                                                 keyname,
     143             :                                                 make_tdb_data((uint8_t *)&idx,
     144             :                                                               sizeof(idx)),
     145             :                                                 TDB_REPLACE));
     146     1424945 :         if (!W_ERROR_IS_OK(werr)) {
     147           0 :                 DEBUG(1, ("error hashing new key '%s' in container: %s\n",
     148             :                           keyname, win_errstr(werr)));
     149             :         }
     150             : 
     151     1424945 :         return werr;
     152             : }
     153             : 
     154        2831 : static WERROR regsubkey_ctr_unhash_keyname(struct regsubkey_ctr *ctr,
     155             :                                            const char *keyname)
     156             : {
     157             :         WERROR werr;
     158             : 
     159        2831 :         werr = ntstatus_to_werror(dbwrap_delete_bystring_upper(ctr->subkeys_hash,
     160             :                                   keyname));
     161        2831 :         if (!W_ERROR_IS_OK(werr)) {
     162           0 :                 DEBUG(1, ("error unhashing key '%s' in container: %s\n",
     163             :                           keyname, win_errstr(werr)));
     164             :         }
     165             : 
     166        2831 :         return werr;
     167             : }
     168             : 
     169     1023221 : static WERROR regsubkey_ctr_index_for_keyname(struct regsubkey_ctr *ctr,
     170             :                                               const char *keyname,
     171             :                                               uint32_t *idx)
     172             : {
     173             :         TDB_DATA data;
     174             :         NTSTATUS status;
     175             : 
     176     1023221 :         if ((ctr == NULL) || (keyname == NULL)) {
     177           0 :                 return WERR_INVALID_PARAMETER;
     178             :         }
     179             : 
     180     1023221 :         status = dbwrap_fetch_bystring_upper(ctr->subkeys_hash, ctr, keyname,
     181             :                                              &data);
     182     1023221 :         if (!NT_STATUS_IS_OK(status)) {
     183     1016121 :                 return WERR_NOT_FOUND;
     184             :         }
     185             : 
     186        7100 :         if (data.dsize != sizeof(*idx)) {
     187           0 :                 talloc_free(data.dptr);
     188           0 :                 return WERR_INVALID_DATATYPE;
     189             :         }
     190             : 
     191        7100 :         if (idx != NULL) {
     192        2831 :                 memcpy(idx, data.dptr, sizeof(*idx));
     193             :         }
     194             : 
     195        7100 :         talloc_free(data.dptr);
     196        7100 :         return WERR_OK;
     197             : }
     198             : 
     199             : /***********************************************************************
     200             :  Add a new key to the array
     201             :  **********************************************************************/
     202             : 
     203     1396729 : WERROR regsubkey_ctr_addkey( struct regsubkey_ctr *ctr, const char *keyname )
     204             : {
     205             :         char **newkeys;
     206             :         WERROR werr;
     207             : 
     208     1396729 :         if ( !keyname ) {
     209           0 :                 return WERR_OK;
     210             :         }
     211             : 
     212             :         /* make sure the keyname is not already there */
     213             : 
     214     1396729 :         if ( regsubkey_ctr_key_exists( ctr, keyname ) ) {
     215           0 :                 return WERR_OK;
     216             :         }
     217             : 
     218     1396729 :         if (!(newkeys = talloc_realloc(ctr, ctr->subkeys, char *,
     219             :                                              ctr->num_subkeys+1))) {
     220           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     221             :         }
     222             : 
     223     1396729 :         ctr->subkeys = newkeys;
     224             : 
     225     1396729 :         if (!(ctr->subkeys[ctr->num_subkeys] = talloc_strdup(ctr->subkeys,
     226             :                                                              keyname ))) {
     227             :                 /*
     228             :                  * Don't shrink the new array again, this wastes a pointer
     229             :                  */
     230           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     231             :         }
     232             : 
     233     1396729 :         werr = regsubkey_ctr_hash_keyname(ctr, keyname, ctr->num_subkeys);
     234     1396729 :         W_ERROR_NOT_OK_RETURN(werr);
     235             : 
     236     1396729 :         ctr->num_subkeys++;
     237             : 
     238     1396729 :         return WERR_OK;
     239             : }
     240             : 
     241             :  /***********************************************************************
     242             :  Delete a key from the array
     243             :  **********************************************************************/
     244             : 
     245        2831 : WERROR regsubkey_ctr_delkey( struct regsubkey_ctr *ctr, const char *keyname )
     246             : {
     247             :         WERROR werr;
     248             :         uint32_t idx, j;
     249             : 
     250        2831 :         if (keyname == NULL) {
     251           0 :                 return WERR_INVALID_PARAMETER;
     252             :         }
     253             : 
     254             :         /* make sure the keyname is actually already there */
     255             : 
     256        2831 :         werr = regsubkey_ctr_index_for_keyname(ctr, keyname, &idx);
     257        2831 :         W_ERROR_NOT_OK_RETURN(werr);
     258             : 
     259        2831 :         werr = regsubkey_ctr_unhash_keyname(ctr, keyname);
     260        2831 :         W_ERROR_NOT_OK_RETURN(werr);
     261             : 
     262             :         /* update if we have any keys left */
     263        2831 :         ctr->num_subkeys--;
     264        2831 :         if (idx < ctr->num_subkeys) {
     265         598 :                 memmove(&ctr->subkeys[idx], &ctr->subkeys[idx+1],
     266         598 :                         sizeof(char *) * (ctr->num_subkeys - idx));
     267             : 
     268             :                 /* we have to re-hash rest of the array...  :-( */
     269       28814 :                 for (j = idx; j < ctr->num_subkeys; j++) {
     270       28216 :                         werr = regsubkey_ctr_hash_keyname(ctr, ctr->subkeys[j], j);
     271       28216 :                         W_ERROR_NOT_OK_RETURN(werr);
     272             :                 }
     273             :         }
     274             : 
     275        2831 :         return WERR_OK;
     276             : }
     277             : 
     278             : /***********************************************************************
     279             :  Check for the existence of a key
     280             :  **********************************************************************/
     281             : 
     282     1407775 : bool regsubkey_ctr_key_exists( struct regsubkey_ctr *ctr, const char *keyname )
     283             : {
     284             :         WERROR werr;
     285             : 
     286     1407775 :         if (!ctr->subkeys) {
     287      386897 :                 return False;
     288             :         }
     289             : 
     290     1020390 :         werr = regsubkey_ctr_index_for_keyname(ctr, keyname, NULL);
     291     1020390 :         if (!W_ERROR_IS_OK(werr)) {
     292     1015691 :                 return false;
     293             :         }
     294             : 
     295        4269 :         return true;
     296             : }
     297             : 
     298             : /***********************************************************************
     299             :  How many keys does the container hold ?
     300             :  **********************************************************************/
     301             : 
     302      839232 : int regsubkey_ctr_numkeys( struct regsubkey_ctr *ctr )
     303             : {
     304      839232 :         return ctr->num_subkeys;
     305             : }
     306             : 
     307             : /***********************************************************************
     308             :  Retrieve a specific key string
     309             :  **********************************************************************/
     310             : 
     311      585534 : char* regsubkey_ctr_specific_key( struct regsubkey_ctr *ctr, uint32_t key_index )
     312             : {
     313      585534 :         if ( ! (key_index < ctr->num_subkeys) )
     314           0 :                 return NULL;
     315             : 
     316      585534 :         return ctr->subkeys[key_index];
     317             : }
     318             : 
     319             : /*
     320             :  * Utility functions for struct regval_ctr
     321             :  */
     322             : 
     323             : /**
     324             :  * allocate a regval_ctr structure.
     325             :  */
     326       56532 : WERROR regval_ctr_init(TALLOC_CTX *mem_ctx, struct regval_ctr **ctr)
     327             : {
     328       56532 :         if (ctr == NULL) {
     329           0 :                 return WERR_INVALID_PARAMETER;
     330             :         }
     331             : 
     332       56532 :         *ctr = talloc_zero(mem_ctx, struct regval_ctr);
     333       56532 :         if (*ctr == NULL) {
     334           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     335             :         }
     336             : 
     337       56532 :         return WERR_OK;
     338             : }
     339             : 
     340             : /***********************************************************************
     341             :  How many keys does the container hold ?
     342             :  **********************************************************************/
     343             : 
     344     1214596 : int regval_ctr_numvals(struct regval_ctr *ctr)
     345             : {
     346     1214596 :         return ctr->num_values;
     347             : }
     348             : 
     349             : /**********************************************************************
     350             :  *********************************************************************/
     351             : 
     352      516270 : uint8_t* regval_data_p(struct regval_blob *val)
     353             : {
     354      516270 :         return val->data_p;
     355             : }
     356             : 
     357             : /**********************************************************************
     358             :  *********************************************************************/
     359             : 
     360      780253 : uint32_t regval_size(struct regval_blob *val)
     361             : {
     362      780253 :         return val->size;
     363             : }
     364             : 
     365             : /**********************************************************************
     366             :  *********************************************************************/
     367             : 
     368     1301904 : char* regval_name(struct regval_blob *val)
     369             : {
     370     1301904 :         return val->valuename;
     371             : }
     372             : 
     373             : /**********************************************************************
     374             :  *********************************************************************/
     375             : 
     376      510973 : uint32_t regval_type(struct regval_blob *val)
     377             : {
     378      510973 :         return val->type;
     379             : }
     380             : 
     381             : /***********************************************************************
     382             :  Retrieve a pointer to a specific value. Caller should dup the structure
     383             :  since this memory will go away when the ctr is free()'d
     384             :  **********************************************************************/
     385             : 
     386     1309308 : struct regval_blob *regval_ctr_specific_value(struct regval_ctr *ctr,
     387             :                                               uint32_t idx)
     388             : {
     389     1309308 :         if ( !(idx < ctr->num_values) )
     390           0 :                 return NULL;
     391             : 
     392     1309308 :         return ctr->values[idx];
     393             : }
     394             : 
     395             : /***********************************************************************
     396             :  Check for the existence of a value
     397             :  **********************************************************************/
     398             : 
     399        3852 : bool regval_ctr_value_exists(struct regval_ctr *ctr, const char *value)
     400             : {
     401             :         uint32_t i;
     402             : 
     403        4815 :         for ( i=0; i<ctr->num_values; i++ ) {
     404        4579 :                 if ( strequal( ctr->values[i]->valuename, value) )
     405        3616 :                         return True;
     406             :         }
     407             : 
     408         228 :         return False;
     409             : }
     410             : 
     411             : /**
     412             :  * Get a value by its name
     413             :  */
     414           0 : struct regval_blob *regval_ctr_value_byname(struct regval_ctr *ctr,
     415             :                                             const char *value)
     416             : {
     417             :         uint32_t i;
     418             : 
     419           0 :         for (i = 0; i < ctr->num_values; i++) {
     420           0 :                 if (strequal(ctr->values[i]->valuename, value)) {
     421           0 :                         return ctr->values[i];
     422             :                 }
     423             :         }
     424             : 
     425           0 :         return NULL;
     426             : }
     427             : 
     428             : 
     429             : /***********************************************************************
     430             :  * compose a struct regval_blob from input data
     431             :  **********************************************************************/
     432             : 
     433      542774 : struct regval_blob *regval_compose(TALLOC_CTX *ctx, const char *name,
     434             :                                    uint32_t type,
     435             :                                    const uint8_t *data_p, size_t size)
     436             : {
     437      542774 :         struct regval_blob *regval = talloc(ctx, struct regval_blob);
     438             : 
     439      542774 :         if (regval == NULL) {
     440           0 :                 return NULL;
     441             :         }
     442             : 
     443      542774 :         fstrcpy(regval->valuename, name);
     444      542774 :         regval->type = type;
     445      542774 :         if (size) {
     446      527142 :                 regval->data_p = (uint8_t *)talloc_memdup(regval, data_p, size);
     447      527142 :                 if (!regval->data_p) {
     448           0 :                         TALLOC_FREE(regval);
     449           0 :                         return NULL;
     450             :                 }
     451             :         } else {
     452       15632 :                 regval->data_p = NULL;
     453             :         }
     454      542774 :         regval->size = size;
     455             : 
     456      542774 :         return regval;
     457             : }
     458             : 
     459             : /***********************************************************************
     460             :  Add a new registry value to the array
     461             :  **********************************************************************/
     462             : 
     463      542678 : int regval_ctr_addvalue(struct regval_ctr *ctr, const char *name, uint32_t type,
     464             :                         const uint8_t *data_p, size_t size)
     465             : {
     466      542678 :         if ( !name )
     467           0 :                 return ctr->num_values;
     468             : 
     469             :         /* Delete the current value (if it exists) and add the new one */
     470             : 
     471      542678 :         regval_ctr_delvalue( ctr, name );
     472             : 
     473             :         /* allocate a slot in the array of pointers */
     474             : 
     475      542678 :         if (  ctr->num_values == 0 ) {
     476       54348 :                 ctr->values = talloc( ctr, struct regval_blob *);
     477             :         } else {
     478      488330 :                 ctr->values = talloc_realloc(ctr, ctr->values,
     479             :                                                    struct regval_blob *,
     480             :                                                    ctr->num_values+1);
     481             :         }
     482             : 
     483      542678 :         if (!ctr->values) {
     484           0 :                 ctr->num_values = 0;
     485           0 :                 return 0;
     486             :         }
     487             : 
     488             :         /* allocate a new value and store the pointer in the array */
     489             : 
     490      542678 :         ctr->values[ctr->num_values] = regval_compose(ctr, name, type, data_p,
     491             :                                                       size);
     492      542678 :         if (ctr->values[ctr->num_values] == NULL) {
     493           0 :                 ctr->num_values = 0;
     494           0 :                 return 0;
     495             :         }
     496      542678 :         ctr->num_values++;
     497             : 
     498      542678 :         return ctr->num_values;
     499             : }
     500             : 
     501             : /***********************************************************************
     502             :  Add a new registry SZ value to the array
     503             :  **********************************************************************/
     504             : 
     505        1949 : int regval_ctr_addvalue_sz(struct regval_ctr *ctr, const char *name, const char *data)
     506             : {
     507             :         DATA_BLOB blob;
     508             : 
     509        1949 :         if (!push_reg_sz(ctr, &blob, data)) {
     510           0 :                 return -1;
     511             :         }
     512             : 
     513        3200 :         return regval_ctr_addvalue(ctr, name, REG_SZ,
     514        1949 :                                    (const uint8_t *)blob.data,
     515             :                                    blob.length);
     516             : }
     517             : 
     518             : /***********************************************************************
     519             :  Add a new registry MULTI_SZ value to the array
     520             :  **********************************************************************/
     521             : 
     522           0 : int regval_ctr_addvalue_multi_sz(struct regval_ctr *ctr, const char *name, const char **data)
     523             : {
     524             :         DATA_BLOB blob;
     525             : 
     526           0 :         if (!push_reg_multi_sz(ctr, &blob, data)) {
     527           0 :                 return -1;
     528             :         }
     529             : 
     530           0 :         return regval_ctr_addvalue(ctr, name, REG_MULTI_SZ,
     531           0 :                                    (const uint8_t *)blob.data,
     532             :                                    blob.length);
     533             : }
     534             : 
     535             : /***********************************************************************
     536             :  Add a new registry value to the array
     537             :  **********************************************************************/
     538             : 
     539           0 : int regval_ctr_copyvalue(struct regval_ctr *ctr, struct regval_blob *val)
     540             : {
     541           0 :         if ( val ) {
     542           0 :                 regval_ctr_addvalue(ctr, val->valuename, val->type,
     543           0 :                                     (uint8_t *)val->data_p, val->size);
     544             :         }
     545             : 
     546           0 :         return ctr->num_values;
     547             : }
     548             : 
     549             : /***********************************************************************
     550             :  Delete a single value from the registry container.
     551             :  No need to free memory since it is talloc'd.
     552             :  **********************************************************************/
     553             : 
     554      546668 : int regval_ctr_delvalue(struct regval_ctr *ctr, const char *name)
     555             : {
     556             :         uint32_t i;
     557             : 
     558     4938872 :         for ( i=0; i<ctr->num_values; i++ ) {
     559     4400252 :                 if ( strequal( ctr->values[i]->valuename, name ) )
     560        8048 :                         break;
     561             :         }
     562             : 
     563             :         /* just return if we don't find it */
     564             : 
     565      546668 :         if ( i == ctr->num_values )
     566      538620 :                 return ctr->num_values;
     567             : 
     568             :         /* If 'i' was not the last element, just shift everything down one */
     569        8048 :         ctr->num_values--;
     570        8048 :         if ( i < ctr->num_values )
     571         864 :                 memmove(&ctr->values[i], &ctr->values[i+1],
     572         864 :                         sizeof(struct regval_blob*)*(ctr->num_values-i));
     573             : 
     574        8048 :         return ctr->num_values;
     575             : }
     576             : 
     577             : /***********************************************************************
     578             :  Retrieve single value from the registry container.
     579             :  No need to free memory since it is talloc'd.
     580             :  **********************************************************************/
     581             : 
     582       22653 : struct regval_blob* regval_ctr_getvalue(struct regval_ctr *ctr,
     583             :                                         const char *name)
     584             : {
     585             :         uint32_t i;
     586             : 
     587             :         /* search for the value */
     588             : 
     589      141507 :         for ( i=0; i<ctr->num_values; i++ ) {
     590      128407 :                 if ( strequal( ctr->values[i]->valuename, name ) )
     591        9553 :                         return ctr->values[i];
     592             :         }
     593             : 
     594       13036 :         return NULL;
     595             : }
     596             : 
     597      261641 : int regval_ctr_get_seqnum(struct regval_ctr *ctr)
     598             : {
     599      261641 :         if (ctr == NULL) {
     600           0 :                 return -1;
     601             :         }
     602             : 
     603      261641 :         return ctr->seqnum;
     604             : }
     605             : 
     606       76856 : WERROR regval_ctr_set_seqnum(struct regval_ctr *ctr, int seqnum)
     607             : {
     608       76856 :         if (ctr == NULL) {
     609           0 :                 return WERR_INVALID_PARAMETER;
     610             :         }
     611             : 
     612       76856 :         ctr->seqnum = seqnum;
     613             : 
     614       76856 :         return WERR_OK;
     615             : }

Generated by: LCOV version 1.13