LCOV - code coverage report
Current view: top level - source4/lib/registry - util.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 86 141 61.0 %
Date: 2021-09-23 10:06:22 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Transparent registry backend handling
       4             :    Copyright (C) Jelmer Vernooij                        2003-2007.
       5             :    Copyright (C) Wilco Baan Hofman                      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             : #include "includes.h"
      22             : #include "lib/registry/registry.h"
      23             : #include "librpc/gen_ndr/winreg.h"
      24             : #include "lib/util/data_blob.h"
      25             : 
      26         237 : _PUBLIC_ char *reg_val_data_string(TALLOC_CTX *mem_ctx, uint32_t type,
      27             :                                    const DATA_BLOB data)
      28             : {
      29         237 :         size_t converted_size = 0;
      30         237 :         char *ret = NULL;
      31             : 
      32         237 :         if (data.length == 0)
      33           1 :                 return talloc_strdup(mem_ctx, "");
      34             : 
      35         236 :         switch (type) {
      36         232 :                 case REG_EXPAND_SZ:
      37             :                 case REG_SZ:
      38         403 :                         convert_string_talloc(mem_ctx,
      39             :                                               CH_UTF16, CH_UNIX,
      40         232 :                                               data.data, data.length,
      41             :                                               (void **)&ret, &converted_size);
      42         232 :                         break;
      43           2 :                 case REG_DWORD:
      44             :                 case REG_DWORD_BIG_ENDIAN:
      45           2 :                         SMB_ASSERT(data.length == sizeof(uint32_t));
      46           2 :                         ret = talloc_asprintf(mem_ctx, "0x%8.8x",
      47           2 :                                               IVAL(data.data, 0));
      48           2 :                         break;
      49           1 :                 case REG_QWORD:
      50           1 :                         SMB_ASSERT(data.length == sizeof(uint64_t));
      51           1 :                         ret = talloc_asprintf(mem_ctx, "0x%16.16llx",
      52           1 :                                               (long long)BVAL(data.data, 0));
      53           1 :                         break;
      54           1 :                 case REG_BINARY:
      55           1 :                         ret = data_blob_hex_string_upper(mem_ctx, &data);
      56           1 :                         break;
      57           0 :                 case REG_NONE:
      58             :                         /* "NULL" is the right return value */
      59           0 :                         break;
      60           0 :                 case REG_MULTI_SZ:
      61             :                         /* FIXME: We don't support this yet */
      62           0 :                         break;
      63           0 :                 default:
      64             :                         /* FIXME */
      65             :                         /* Other datatypes aren't supported -> return "NULL" */
      66           0 :                         break;
      67             :         }
      68             : 
      69         236 :         return ret;
      70             : }
      71             : 
      72             : /** Generate a string that describes a registry value */
      73           2 : _PUBLIC_ char *reg_val_description(TALLOC_CTX *mem_ctx,
      74             :                                    const char *name,
      75             :                                    uint32_t data_type,
      76             :                                    const DATA_BLOB data)
      77             : {
      78           2 :         return talloc_asprintf(mem_ctx, "%s = %s : %s", name?name:"<No Name>",
      79             :                                str_regtype(data_type),
      80             :                                reg_val_data_string(mem_ctx, data_type, data));
      81             : }
      82             : 
      83             : /*
      84             :  * This implements reading hex bytes that include comma's.
      85             :  * It was previously handled by strhex_to_data_blob, but that did not cover
      86             :  * the format used by windows.
      87             :  */
      88           0 : static DATA_BLOB reg_strhex_to_data_blob(TALLOC_CTX *mem_ctx, const char *str)
      89             : {
      90             :         DATA_BLOB ret;
      91           0 :         const char *HEXCHARS = "0123456789ABCDEF";
      92             :         size_t i, j;
      93             :         char *hi, *lo;
      94             : 
      95           0 :         ret = data_blob_talloc_zero(mem_ctx, (strlen(str)+(strlen(str) % 3))/3);
      96           0 :         j = 0;
      97           0 :         for (i = 0; i < strlen(str); i++) {
      98           0 :                 hi = strchr(HEXCHARS, toupper(str[i]));
      99           0 :                 if (hi == NULL)
     100           0 :                         continue;
     101             : 
     102           0 :                 i++;
     103           0 :                 lo = strchr(HEXCHARS, toupper(str[i]));
     104           0 :                 if (lo == NULL)
     105           0 :                         break;
     106             : 
     107           0 :                 ret.data[j] = PTR_DIFF(hi, HEXCHARS) << 4;
     108           0 :                 ret.data[j] += PTR_DIFF(lo, HEXCHARS);
     109           0 :                 j++;
     110             : 
     111           0 :                 if (j > ret.length) {
     112           0 :                         DEBUG(0, ("Trouble converting hex string to bin\n"));
     113           0 :                         break;
     114             :                 }
     115             :         }
     116           0 :         return ret;
     117             : }
     118             : 
     119             : 
     120         580 : _PUBLIC_ bool reg_string_to_val(TALLOC_CTX *mem_ctx, const char *type_str,
     121             :                                 const char *data_str, uint32_t *type, DATA_BLOB *data)
     122             : {
     123             :         char *tmp_type_str, *p, *q;
     124             :         int result;
     125             : 
     126         580 :         *type = regtype_by_string(type_str);
     127             : 
     128         580 :         if (*type == -1) {
     129             :                 /* Normal windows format is hex, hex(type int as string),
     130             :                    dword or just a string. */
     131         194 :                 if (strncmp(type_str, "hex(", 4) == 0) {
     132             :                         /* there is a hex string with the value type between
     133             :                            the braces */
     134           0 :                         tmp_type_str = talloc_strdup(mem_ctx, type_str);
     135           0 :                         q = p = tmp_type_str + strlen("hex(");
     136             : 
     137             :                         /* Go to the closing brace or end of the string */
     138           0 :                         while (*q != ')' && *q != '\0') q++;
     139           0 :                         *q = '\0';
     140             : 
     141             :                         /* Convert hex string to int, store it in type */
     142           0 :                         result = sscanf(p, "%x", type);
     143           0 :                         if (!result) {
     144           0 :                                 DEBUG(0, ("Could not convert hex to int\n"));
     145           0 :                                 return false;
     146             :                         }
     147           0 :                         talloc_free(tmp_type_str);
     148         194 :                 } else if (strcmp(type_str, "hex") == 0) {
     149           0 :                         *type = REG_BINARY;
     150         194 :                 } else if (strcmp(type_str, "dword") == 0) {
     151         194 :                         *type = REG_DWORD;
     152             :                 }
     153             :         }
     154             : 
     155         580 :         if (*type == -1)
     156           0 :                 return false;
     157             : 
     158             :         /* Convert data appropriately */
     159             : 
     160         580 :         switch (*type) {
     161         386 :                 case REG_SZ:
     162         710 :                         return convert_string_talloc(mem_ctx,
     163             :                                                      CH_UNIX, CH_UTF16,
     164         386 :                                                      data_str, strlen(data_str)+1,
     165         386 :                                                      (void **)&data->data,
     166             :                                                      &data->length);
     167             :                         break;
     168           0 :                 case REG_MULTI_SZ:
     169             :                 case REG_EXPAND_SZ:
     170             :                 case REG_BINARY:
     171           0 :                         *data = reg_strhex_to_data_blob(mem_ctx, data_str);
     172           0 :                         break;
     173         194 :                 case REG_DWORD:
     174             :                 case REG_DWORD_BIG_ENDIAN: {
     175         194 :                         uint32_t tmp = strtol(data_str, NULL, 16);
     176         194 :                         *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint32_t));
     177         194 :                         if (data->data == NULL) return false;
     178         194 :                         SIVAL(data->data, 0, tmp);
     179             :                         }
     180         194 :                         break;
     181           0 :                 case REG_QWORD: {
     182           0 :                         uint64_t tmp = strtoll(data_str, NULL, 16);
     183           0 :                         *data = data_blob_talloc(mem_ctx, NULL, sizeof(uint64_t));
     184           0 :                         if (data->data == NULL) return false;
     185           0 :                         SBVAL(data->data, 0, tmp);
     186             :                         }
     187           0 :                         break;
     188           0 :                 case REG_NONE:
     189           0 :                         ZERO_STRUCTP(data);
     190           0 :                         break;
     191           0 :                 default:
     192             :                         /* FIXME */
     193             :                         /* Other datatypes aren't supported -> return no success */
     194           0 :                         return false;
     195             :         }
     196         171 :         return true;
     197             : }
     198             : 
     199             : /** Open a key by name (including the predefined key name!) */
     200       10650 : WERROR reg_open_key_abs(TALLOC_CTX *mem_ctx, struct registry_context *handle,
     201             :                         const char *name, struct registry_key **result)
     202             : {
     203             :         struct registry_key *predef;
     204             :         WERROR error;
     205             :         size_t predeflength;
     206             :         char *predefname;
     207             : 
     208       10650 :         if (strchr(name, '\\') != NULL)
     209        7359 :                 predeflength = strchr(name, '\\')-name;
     210             :         else
     211        3291 :                 predeflength = strlen(name);
     212             : 
     213       10650 :         predefname = talloc_strndup(mem_ctx, name, predeflength);
     214       10650 :         W_ERROR_HAVE_NO_MEMORY(predefname);
     215       10650 :         error = reg_get_predefined_key_by_name(handle, predefname, &predef);
     216       10650 :         talloc_free(predefname);
     217             : 
     218       10650 :         if (!W_ERROR_IS_OK(error)) {
     219           0 :                 return error;
     220             :         }
     221             : 
     222       10650 :         if (strchr(name, '\\')) {
     223        7359 :                 return reg_open_key(mem_ctx, predef, strchr(name, '\\')+1,
     224             :                                     result);
     225             :         } else {
     226        3291 :                 *result = predef;
     227        3291 :                 return WERR_OK;
     228             :         }
     229             : }
     230             : 
     231       10069 : static WERROR get_abs_parent(TALLOC_CTX *mem_ctx, struct registry_context *ctx,
     232             :                              const char *path, struct registry_key **parent,
     233             :                              const char **name)
     234             : {
     235             :         char *parent_name;
     236             :         WERROR error;
     237             : 
     238       10069 :         if (strchr(path, '\\') == NULL) {
     239           0 :                 return WERR_FOOBAR;
     240             :         }
     241             : 
     242       10069 :         parent_name = talloc_strndup(mem_ctx, path, strrchr(path, '\\')-path);
     243       10069 :         W_ERROR_HAVE_NO_MEMORY(parent_name);
     244       10069 :         error = reg_open_key_abs(mem_ctx, ctx, parent_name, parent);
     245       10069 :         talloc_free(parent_name);
     246       10069 :         if (!W_ERROR_IS_OK(error)) {
     247           2 :                 return error;
     248             :         }
     249             : 
     250       10067 :         *name = talloc_strdup(mem_ctx, strrchr(path, '\\')+1);
     251       10067 :         W_ERROR_HAVE_NO_MEMORY(*name);
     252             : 
     253       10067 :         return WERR_OK;
     254             : }
     255             : 
     256           4 : WERROR reg_key_del_abs(struct registry_context *ctx, const char *path)
     257             : {
     258             :         struct registry_key *parent;
     259             :         const char *n;
     260           4 :         TALLOC_CTX *mem_ctx = talloc_init("reg_key_del_abs");
     261             :         WERROR error;
     262             : 
     263           4 :         if (!strchr(path, '\\')) {
     264           0 :                 return WERR_FOOBAR;
     265             :         }
     266             : 
     267           4 :         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
     268           4 :         if (W_ERROR_IS_OK(error)) {
     269           2 :                 error = reg_key_del(mem_ctx, parent, n);
     270             :         }
     271             : 
     272           4 :         talloc_free(mem_ctx);
     273             : 
     274           4 :         return error;
     275             : }
     276             : 
     277       13933 : WERROR reg_key_add_abs(TALLOC_CTX *mem_ctx, struct registry_context *ctx,
     278             :                        const char *path, uint32_t access_mask,
     279             :                        struct security_descriptor *sec_desc,
     280             :                        struct registry_key **result)
     281             : {
     282             :         struct registry_key *parent;
     283             :         const char *n;
     284             :         WERROR error;
     285             : 
     286       13933 :         *result = NULL;
     287             : 
     288       13933 :         if (!strchr(path, '\\')) {
     289        3868 :                 return WERR_ALREADY_EXISTS;
     290             :         }
     291             : 
     292       10065 :         error = get_abs_parent(mem_ctx, ctx, path, &parent, &n);
     293       10065 :         if (!W_ERROR_IS_OK(error)) {
     294           0 :                 DEBUG(2, ("Opening parent of %s failed with %s\n", path,
     295             :                                   win_errstr(error)));
     296           0 :                 return error;
     297             :         }
     298             : 
     299       10065 :         error = reg_key_add_name(mem_ctx, parent, n, NULL, sec_desc, result);
     300             : 
     301       10065 :         return error;
     302             : }

Generated by: LCOV version 1.13