LCOV - code coverage report
Current view: top level - source3/utils - net_registry.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 338 773 43.7 %
Date: 2021-09-23 10:06:22 Functions: 23 41 56.1 %

          Line data    Source code
       1             : /*
       2             :  * Samba Unix/Linux SMB client library
       3             :  * Distributed SMB/CIFS Server Management Utility
       4             :  * Local registry interface
       5             :  *
       6             :  * Copyright (C) Michael Adam 2008
       7             :  *
       8             :  * This program is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published by
      10             :  * the Free Software Foundation; either version 3 of the License, or
      11             :  * (at your option) any later version.
      12             :  *
      13             :  * This program is distributed in the hope that it will be useful,
      14             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :  * GNU General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License
      19             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             :  */
      21             : 
      22             : #include "includes.h"
      23             : #include "registry.h"
      24             : #include "registry/reg_api.h"
      25             : #include "registry/reg_util_token.h"
      26             : #include "registry/reg_init_basic.h"
      27             : #include "utils/net.h"
      28             : #include "utils/net_registry_util.h"
      29             : #include "include/g_lock.h"
      30             : #include "registry/reg_backend_db.h"
      31             : #include "registry/reg_import.h"
      32             : #include "registry/reg_format.h"
      33             : #include "registry/reg_api_util.h"
      34             : #include <assert.h>
      35             : #include "../libcli/security/display_sec.h"
      36             : #include "../libcli/security/sddl.h"
      37             : #include "../libcli/registry/util_reg.h"
      38             : #include "passdb/machine_sid.h"
      39             : #include "net_registry_check.h"
      40             : #include "lib/util/util_tdb.h"
      41             : #include "lib/util/smb_strtox.h"
      42             : 
      43             : /*
      44             :  *
      45             :  * Helper functions
      46             :  *
      47             :  */
      48             : 
      49             : /**
      50             :  * split given path into hive and remaining path and open the hive key
      51             :  */
      52         314 : static WERROR open_hive(TALLOC_CTX *ctx, const char *path,
      53             :                         uint32_t desired_access,
      54             :                         struct registry_key **hive,
      55             :                         char **subkeyname)
      56             : {
      57             :         WERROR werr;
      58         314 :         struct security_token *token = NULL;
      59         314 :         char *hivename = NULL;
      60         314 :         char *tmp_subkeyname = NULL;
      61         314 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
      62             : 
      63         314 :         if ((hive == NULL) || (subkeyname == NULL)) {
      64           0 :                 werr = WERR_INVALID_PARAMETER;
      65           0 :                 goto done;
      66             :         }
      67             : 
      68         314 :         werr = split_hive_key(tmp_ctx, path, &hivename, &tmp_subkeyname);
      69         314 :         if (!W_ERROR_IS_OK(werr)) {
      70           0 :                 goto done;
      71             :         }
      72         314 :         *subkeyname = talloc_strdup(ctx, tmp_subkeyname);
      73         314 :         if (*subkeyname == NULL) {
      74           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
      75           0 :                 goto done;
      76             :         }
      77             : 
      78         314 :         werr = ntstatus_to_werror(registry_create_admin_token(tmp_ctx, &token));
      79         314 :         if (!W_ERROR_IS_OK(werr)) {
      80           0 :                 goto done;
      81             :         }
      82             : 
      83         314 :         werr = reg_openhive(ctx, hivename, desired_access, token, hive);
      84         314 :         if (!W_ERROR_IS_OK(werr)) {
      85           2 :                 goto done;
      86             :         }
      87             : 
      88         312 :         werr = WERR_OK;
      89             : 
      90         314 : done:
      91         314 :         TALLOC_FREE(tmp_ctx);
      92         314 :         return werr;
      93             : }
      94             : 
      95          34 : static WERROR open_key(TALLOC_CTX *ctx, const char *path,
      96             :                        uint32_t desired_access,
      97             :                        struct registry_key **key)
      98             : {
      99             :         WERROR werr;
     100          34 :         char *subkey_name = NULL;
     101          34 :         struct registry_key *hive = NULL;
     102          34 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     103             : 
     104          34 :         if ((path == NULL) || (key == NULL)) {
     105           0 :                 return WERR_INVALID_PARAMETER;
     106             :         }
     107             : 
     108          34 :         werr = open_hive(tmp_ctx, path, desired_access, &hive, &subkey_name);
     109          34 :         if (!W_ERROR_IS_OK(werr)) {
     110           0 :                 d_fprintf(stderr, _("open_hive failed: %s\n"),
     111             :                           win_errstr(werr));
     112           0 :                 goto done;
     113             :         }
     114             : 
     115          34 :         werr = reg_openkey(ctx, hive, subkey_name, desired_access, key);
     116          34 :         if (!W_ERROR_IS_OK(werr)) {
     117           0 :                 d_fprintf(stderr, _("reg_openkey failed: %s\n"),
     118             :                           win_errstr(werr));
     119           0 :                 goto done;
     120             :         }
     121             : 
     122          34 :         werr = WERR_OK;
     123             : 
     124          34 : done:
     125          34 :         TALLOC_FREE(tmp_ctx);
     126          34 :         return werr;
     127             : }
     128             : 
     129          52 : static WERROR registry_enumkey(struct registry_key *parent, const char *keyname,
     130             :                                bool recursive)
     131             : {
     132             :         WERROR werr;
     133          52 :         TALLOC_CTX *ctx = talloc_stackframe();
     134             :         char *subkey_name;
     135             :         NTTIME modtime;
     136             :         uint32_t count;
     137          52 :         char *valname = NULL;
     138          52 :         struct registry_value *valvalue = NULL;
     139          52 :         struct registry_key *key = NULL;
     140             : 
     141          52 :         werr = reg_openkey(ctx, parent, keyname, REG_KEY_READ, &key);
     142          52 :         if (!W_ERROR_IS_OK(werr)) {
     143           8 :                 goto done;
     144             :         }
     145             : 
     146          44 :         if (recursive) {
     147           0 :                 printf("[%s]\n\n", key->key->name);
     148             :         } else {
     149         158 :                 for (count = 0;
     150         114 :                      werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
     151         114 :                      W_ERROR_IS_OK(werr);
     152          70 :                      count++)
     153             :                 {
     154          70 :                         print_registry_key(subkey_name, &modtime);
     155             :                 }
     156          44 :                 if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
     157           0 :                         goto done;
     158             :                 }
     159             :         }
     160             : 
     161          92 :         for (count = 0;
     162          48 :              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
     163          48 :              W_ERROR_IS_OK(werr);
     164           4 :              count++)
     165             :         {
     166           4 :                 print_registry_value_with_name(valname, valvalue);
     167             :         }
     168          44 :         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
     169           0 :                 goto done;
     170             :         }
     171             : 
     172          44 :         if (!recursive) {
     173          44 :                 werr = WERR_OK;
     174          44 :                 goto done;
     175             :         }
     176             : 
     177           0 :         for (count = 0;
     178           0 :              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
     179           0 :              W_ERROR_IS_OK(werr);
     180           0 :              count++)
     181             :         {
     182           0 :                 werr = registry_enumkey(key, subkey_name, recursive);
     183           0 :                 if (!W_ERROR_IS_OK(werr)) {
     184           0 :                         goto done;
     185             :                 }
     186             :         }
     187           0 :         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
     188           0 :                 goto done;
     189             :         }
     190             : 
     191           0 :         werr = WERR_OK;
     192             : 
     193          52 : done:
     194          52 :         TALLOC_FREE(ctx);
     195          52 :         return werr;
     196             : }
     197             : 
     198             : 
     199             : 
     200             : /*
     201             :  *
     202             :  * the main "net registry" function implementations
     203             :  *
     204             :  */
     205          56 : static int net_registry_enumerate(struct net_context *c, int argc,
     206             :                                   const char **argv)
     207             : {
     208             :         WERROR werr;
     209          56 :         struct registry_key *key = NULL;
     210          56 :         char *name = NULL;
     211          56 :         TALLOC_CTX *ctx = talloc_stackframe();
     212          56 :         int ret = -1;
     213             : 
     214          56 :         if (argc != 1 || c->display_usage) {
     215           2 :                 d_printf("%s\n%s",
     216             :                          _("Usage:"),
     217             :                          _("net registry enumerate <path>\n"));
     218           2 :                 d_printf("%s\n%s",
     219             :                          _("Example:"),
     220             :                          _("net registry enumerate 'HKLM\\Software\\Samba'\n"));
     221           2 :                 goto done;
     222             :         }
     223             : 
     224          54 :         werr = open_hive(ctx, argv[0], REG_KEY_READ, &key, &name);
     225          54 :         if (!W_ERROR_IS_OK(werr)) {
     226           2 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
     227           2 :                 goto done;
     228             :         }
     229             : 
     230          52 :         werr = registry_enumkey(key, name, c->opt_reboot);
     231          52 :         if (W_ERROR_IS_OK(werr)) {
     232          44 :                 ret = 0;
     233             :         }
     234          64 : done:
     235          56 :         TALLOC_FREE(ctx);
     236          56 :         return ret;
     237             : }
     238             : 
     239           0 : static int net_registry_enumerate_recursive(struct net_context *c, int argc,
     240             :                                             const char **argv)
     241             : {
     242             :         WERROR werr;
     243           0 :         struct registry_key *key = NULL;
     244           0 :         char *name = NULL;
     245           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     246           0 :         int ret = -1;
     247             : 
     248           0 :         if (argc != 1 || c->display_usage) {
     249           0 :                 d_printf("%s\n%s",
     250             :                          _("Usage:"),
     251             :                          _("net registry enumerate <path>\n"));
     252           0 :                 d_printf("%s\n%s",
     253             :                          _("Example:"),
     254             :                          _("net registry enumerate 'HKLM\\Software\\Samba'\n"));
     255           0 :                 goto done;
     256             :         }
     257             : 
     258           0 :         werr = open_hive(ctx, argv[0], REG_KEY_READ, &key, &name);
     259           0 :         if (!W_ERROR_IS_OK(werr)) {
     260           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
     261           0 :                 goto done;
     262             :         }
     263             : 
     264           0 :         werr = registry_enumkey(key, name, true);
     265           0 :         if (W_ERROR_IS_OK(werr)) {
     266           0 :                 ret = 0;
     267             :         }
     268           0 : done:
     269           0 :         TALLOC_FREE(ctx);
     270           0 :         return ret;
     271             : }
     272             : 
     273             : 
     274          20 : static int net_registry_createkey(struct net_context *c, int argc,
     275             :                                   const char **argv)
     276             : {
     277             :         WERROR werr;
     278             :         enum winreg_CreateAction action;
     279          20 :         char *subkeyname = NULL;
     280          20 :         struct registry_key *hivekey = NULL;
     281          20 :         struct registry_key *subkey = NULL;
     282          20 :         TALLOC_CTX *ctx = talloc_stackframe();
     283          20 :         int ret = -1;
     284             : 
     285          20 :         if (argc != 1 || c->display_usage) {
     286           0 :                 d_printf("%s\n%s",
     287             :                          _("Usage:"),
     288             :                          _("net registry createkey <path>\n"));
     289           0 :                 d_printf("%s\n%s",
     290             :                          _("Example:"),
     291             :                          _("net registry createkey "
     292             :                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
     293           0 :                 goto done;
     294             :         }
     295          20 :         if (strlen(argv[0]) == 0) {
     296           0 :                 d_fprintf(stderr, _("error: zero length key name given\n"));
     297           0 :                 goto done;
     298             :         }
     299             : 
     300          20 :         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
     301          20 :         if (!W_ERROR_IS_OK(werr)) {
     302           0 :                 d_fprintf(stderr, _("open_hive failed: %s\n"),
     303             :                           win_errstr(werr));
     304           0 :                 goto done;
     305             :         }
     306             : 
     307          20 :         werr = reg_createkey(ctx, hivekey, subkeyname, REG_KEY_WRITE,
     308             :                              &subkey, &action);
     309          20 :         if (!W_ERROR_IS_OK(werr)) {
     310           0 :                 d_fprintf(stderr, _("reg_createkey failed: %s\n"),
     311             :                           win_errstr(werr));
     312           0 :                 goto done;
     313             :         }
     314          20 :         switch (action) {
     315           0 :                 case REG_ACTION_NONE:
     316           0 :                         d_printf(_("createkey did nothing -- huh?\n"));
     317           0 :                         break;
     318          10 :                 case REG_CREATED_NEW_KEY:
     319          10 :                         d_printf(_("createkey created %s\n"), argv[0]);
     320          10 :                         break;
     321          10 :                 case REG_OPENED_EXISTING_KEY:
     322          10 :                         d_printf(_("createkey opened existing %s\n"), argv[0]);
     323          10 :                         break;
     324             :         }
     325             : 
     326          20 :         ret = 0;
     327             : 
     328          20 : done:
     329          20 :         TALLOC_FREE(ctx);
     330          20 :         return ret;
     331             : }
     332             : 
     333          18 : static int net_registry_deletekey_internal(struct net_context *c, int argc,
     334             :                                            const char **argv,
     335             :                                            bool recursive)
     336             : {
     337             :         WERROR werr;
     338          18 :         char *subkeyname = NULL;
     339          18 :         struct registry_key *hivekey = NULL;
     340          18 :         TALLOC_CTX *ctx = talloc_stackframe();
     341          18 :         int ret = -1;
     342             : 
     343          18 :         if (argc != 1 || c->display_usage) {
     344           0 :                 d_printf("%s\n%s",
     345             :                          _("Usage:"),
     346             :                          _("net registry deletekey <path>\n"));
     347           0 :                 d_printf("%s\n%s",
     348             :                          _("Example:"),
     349             :                          _("net registry deletekey "
     350             :                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
     351           0 :                 goto done;
     352             :         }
     353          18 :         if (strlen(argv[0]) == 0) {
     354           0 :                 d_fprintf(stderr, _("error: zero length key name given\n"));
     355           0 :                 goto done;
     356             :         }
     357             : 
     358          18 :         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
     359          18 :         if (!W_ERROR_IS_OK(werr)) {
     360           0 :                 d_fprintf(stderr, "open_hive %s: %s\n", _("failed"),
     361             :                           win_errstr(werr));
     362           0 :                 goto done;
     363             :         }
     364             : 
     365          18 :         if (recursive) {
     366           0 :                 werr = reg_deletekey_recursive(hivekey, subkeyname);
     367             :         } else {
     368          18 :                 werr = reg_deletekey(hivekey, subkeyname);
     369             :         }
     370          22 :         if (!W_ERROR_IS_OK(werr) &&
     371           4 :             !(c->opt_force && W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)))
     372             :         {
     373           4 :                 d_fprintf(stderr, "reg_deletekey %s: %s\n", _("failed"),
     374             :                           win_errstr(werr));
     375           4 :                 goto done;
     376             :         }
     377             : 
     378          14 :         ret = 0;
     379             : 
     380          18 : done:
     381          18 :         TALLOC_FREE(ctx);
     382          18 :         return ret;
     383             : }
     384             : 
     385          18 : static int net_registry_deletekey(struct net_context *c, int argc,
     386             :                                   const char **argv)
     387             : {
     388          18 :         return net_registry_deletekey_internal(c, argc, argv, false);
     389             : }
     390             : 
     391           0 : static int net_registry_deletekey_recursive(struct net_context *c, int argc,
     392             :                                             const char **argv)
     393             : {
     394           0 :         return net_registry_deletekey_internal(c, argc, argv, true);
     395             : }
     396             : 
     397           6 : static int net_registry_getvalue_internal(struct net_context *c, int argc,
     398             :                                           const char **argv, bool raw)
     399             : {
     400             :         WERROR werr;
     401           6 :         int ret = -1;
     402           6 :         struct registry_key *key = NULL;
     403           6 :         struct registry_value *value = NULL;
     404           6 :         TALLOC_CTX *ctx = talloc_stackframe();
     405             : 
     406           6 :         if (argc != 2 || c->display_usage) {
     407           0 :                 d_fprintf(stderr, "%s\n%s",
     408             :                           _("Usage:"),
     409             :                           _("net registry getvalue <key> <valuename>\n"));
     410           0 :                 goto done;
     411             :         }
     412             : 
     413           6 :         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
     414           6 :         if (!W_ERROR_IS_OK(werr)) {
     415           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
     416           0 :                 goto done;
     417             :         }
     418             : 
     419           6 :         werr = reg_queryvalue(ctx, key, argv[1], &value);
     420           6 :         if (!W_ERROR_IS_OK(werr)) {
     421           0 :                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
     422             :                           win_errstr(werr));
     423           0 :                 goto done;
     424             :         }
     425             : 
     426           6 :         print_registry_value(value, raw);
     427             : 
     428           6 :         ret = 0;
     429             : 
     430           6 : done:
     431           6 :         TALLOC_FREE(ctx);
     432           6 :         return ret;
     433             : }
     434             : 
     435           0 : static int net_registry_getvalue(struct net_context *c, int argc,
     436             :                                  const char **argv)
     437             : {
     438           0 :         return net_registry_getvalue_internal(c, argc, argv, false);
     439             : }
     440             : 
     441           6 : static int net_registry_getvalueraw(struct net_context *c, int argc,
     442             :                                     const char **argv)
     443             : {
     444           6 :         return net_registry_getvalue_internal(c, argc, argv, true);
     445             : }
     446             : 
     447           0 : static int net_registry_getvaluesraw(struct net_context *c, int argc,
     448             :                                      const char **argv)
     449             : {
     450             :         WERROR werr;
     451           0 :         int ret = -1;
     452           0 :         struct registry_key *key = NULL;
     453           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     454             :         uint32_t idx;
     455             : 
     456           0 :         if (argc != 1 || c->display_usage) {
     457           0 :                 d_fprintf(stderr, "usage: net rpc registry getvaluesraw "
     458             :                           "<key>\n");
     459           0 :                 goto done;
     460             :         }
     461             : 
     462           0 :         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
     463           0 :         if (!W_ERROR_IS_OK(werr)) {
     464           0 :                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
     465           0 :                 goto done;
     466             :         }
     467             : 
     468           0 :         idx = 0;
     469           0 :         while (true) {
     470             :                 struct registry_value *val;
     471             : 
     472           0 :                 werr = reg_enumvalue(talloc_tos(), key, idx, NULL, &val);
     473             : 
     474           0 :                 if (W_ERROR_EQUAL(werr, WERR_NO_MORE_ITEMS)) {
     475           0 :                         ret = 0;
     476           0 :                         break;
     477             :                 }
     478           0 :                 if (!W_ERROR_IS_OK(werr)) {
     479           0 :                         break;
     480             :                 }
     481           0 :                 print_registry_value(val, true);
     482           0 :                 TALLOC_FREE(val);
     483           0 :                 idx += 1;
     484             :         }
     485           0 : done:
     486           0 :         TALLOC_FREE(ctx);
     487           0 :         return ret;
     488             : }
     489             : 
     490           8 : static int net_registry_setvalue(struct net_context *c, int argc,
     491             :                                  const char **argv)
     492             : {
     493             :         WERROR werr;
     494             :         struct registry_value value;
     495           8 :         struct registry_key *key = NULL;
     496           8 :         int ret = -1;
     497           8 :         TALLOC_CTX *ctx = talloc_stackframe();
     498             : 
     499           8 :         if (argc < 4 || c->display_usage) {
     500           0 :                 d_fprintf(stderr, "%s\n%s",
     501             :                           _("Usage:"),
     502             :                           _("net registry setvalue <key> <valuename> "
     503             :                             "<type> [<val>]+\n"));
     504           0 :                 goto done;
     505             :         }
     506             : 
     507           8 :         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
     508           0 :                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
     509           0 :                 goto done;
     510             :         }
     511             : 
     512           8 :         if (strequal(argv[2], "dword")) {
     513           2 :                 int error = 0;
     514             :                 uint32_t v;
     515             : 
     516           2 :                 v = smb_strtoul(argv[3], NULL, 10, &error, SMB_STR_STANDARD);
     517           2 :                 if (error != 0) {
     518           0 :                         goto done;
     519             :                 }
     520             : 
     521           2 :                 value.type = REG_DWORD;
     522           2 :                 value.data = data_blob_talloc(ctx, NULL, 4);
     523           2 :                 SIVAL(value.data.data, 0, v);
     524           6 :         } else if (strequal(argv[2], "sz")) {
     525           6 :                 value.type = REG_SZ;
     526           6 :                 if (!push_reg_sz(ctx, &value.data, argv[3])) {
     527           0 :                         goto done;
     528             :                 }
     529           0 :         } else if (strequal(argv[2], "multi_sz")) {
     530             :                 const char **array;
     531           0 :                 int count = argc - 3;
     532             :                 int i;
     533           0 :                 value.type = REG_MULTI_SZ;
     534           0 :                 array = talloc_zero_array(ctx, const char *, count + 1);
     535           0 :                 if (array == NULL) {
     536           0 :                         goto done;
     537             :                 }
     538           0 :                 for (i=0; i < count; i++) {
     539           0 :                         array[i] = talloc_strdup(array, argv[count+i]);
     540           0 :                         if (array[i] == NULL) {
     541           0 :                                 goto done;
     542             :                         }
     543             :                 }
     544           0 :                 if (!push_reg_multi_sz(ctx, &value.data, array)) {
     545           0 :                         goto done;
     546             :                 }
     547             :         } else {
     548           0 :                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
     549           0 :                 goto done;
     550             :         }
     551             : 
     552           8 :         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
     553           8 :         if (!W_ERROR_IS_OK(werr)) {
     554           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
     555           0 :                 goto done;
     556             :         }
     557             : 
     558           8 :         werr = reg_setvalue(key, argv[1], &value);
     559           8 :         if (!W_ERROR_IS_OK(werr)) {
     560           0 :                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
     561             :                           win_errstr(werr));
     562           0 :                 goto done;
     563             :         }
     564             : 
     565           8 :         ret = 0;
     566             : 
     567           8 : done:
     568           8 :         TALLOC_FREE(ctx);
     569           8 :         return ret;
     570             : }
     571             : 
     572           0 : static int net_registry_increment(struct net_context *c, int argc,
     573             :                                   const char **argv)
     574             : {
     575           0 :         TDB_DATA lock_key = string_term_tdb_data("registry_increment_lock");
     576           0 :         struct g_lock_ctx *ctx = NULL;
     577           0 :         const char *keyname = NULL;
     578           0 :         struct registry_key *key = NULL;
     579           0 :         const char *valuename = NULL;
     580           0 :         struct registry_value *value = NULL;
     581             :         uint32_t v;
     582             :         uint32_t increment;
     583             :         uint32_t newvalue;
     584             :         NTSTATUS status;
     585             :         WERROR werr;
     586           0 :         int ret = -1;
     587             : 
     588           0 :         if (argc < 2 || c->display_usage) {
     589           0 :                 d_fprintf(stderr, "%s\n%s",
     590             :                           _("Usage:"),
     591             :                           _("net registry increment <key> <valuename> "
     592             :                             "[<increment>]\n"));
     593           0 :                 goto done;
     594             :         }
     595             : 
     596           0 :         keyname = argv[0];
     597           0 :         valuename = argv[1];
     598             : 
     599           0 :         increment = 1;
     600           0 :         if (argc == 3) {
     601           0 :                 int error = 0;
     602             : 
     603           0 :                 increment = smb_strtoul(
     604           0 :                         argv[2], NULL, 10, &error, SMB_STR_STANDARD);
     605           0 :                 if (error != 0) {
     606           0 :                         goto done;
     607             :                 }
     608             :         }
     609             : 
     610           0 :         ctx = g_lock_ctx_init(c, c->msg_ctx);
     611           0 :         if (ctx == NULL) {
     612           0 :                 d_fprintf(stderr, _("g_lock_ctx_init failed\n"));
     613           0 :                 goto done;
     614             :         }
     615             : 
     616           0 :         status = g_lock_lock(ctx, lock_key, G_LOCK_WRITE, timeval_set(600, 0));
     617           0 :         if (!NT_STATUS_IS_OK(status)) {
     618           0 :                 d_fprintf(stderr, _("g_lock_lock failed: %s\n"),
     619             :                           nt_errstr(status));
     620           0 :                 goto done;
     621             :         }
     622             : 
     623           0 :         werr = open_key(c, keyname, REG_KEY_READ|REG_KEY_WRITE, &key);
     624           0 :         if (!W_ERROR_IS_OK(werr)) {
     625           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"),
     626             :                           win_errstr(werr));
     627           0 :                 goto done;
     628             :         }
     629             : 
     630           0 :         werr = reg_queryvalue(key, key, valuename, &value);
     631           0 :         if (!W_ERROR_IS_OK(werr)) {
     632           0 :                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
     633             :                           win_errstr(werr));
     634           0 :                 goto done;
     635             :         }
     636             : 
     637           0 :         if (value->type != REG_DWORD) {
     638           0 :                 d_fprintf(stderr, _("value not a DWORD: %s\n"),
     639           0 :                           str_regtype(value->type));
     640           0 :                 goto done;
     641             :         }
     642             : 
     643           0 :         if (value->data.length < 4) {
     644           0 :                 d_fprintf(stderr, _("value too short for regular DWORD\n"));
     645           0 :                 goto done;
     646             :         }
     647             : 
     648           0 :         v = IVAL(value->data.data, 0);
     649           0 :         v += increment;
     650           0 :         newvalue = v;
     651             : 
     652           0 :         SIVAL(value->data.data, 0, v);
     653             : 
     654           0 :         werr = reg_setvalue(key, valuename, value);
     655           0 :         if (!W_ERROR_IS_OK(werr)) {
     656           0 :                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
     657             :                           win_errstr(werr));
     658           0 :                 goto done;
     659             :         }
     660             : 
     661           0 :         if (!W_ERROR_IS_OK(werr)) {
     662           0 :                 d_fprintf(stderr, _("increment failed: %s\n"),
     663             :                           win_errstr(werr));
     664           0 :                 goto done;
     665             :         }
     666             : 
     667           0 :         g_lock_unlock(ctx, lock_key);
     668             : 
     669           0 :         d_printf(_("%"PRIu32"\n"), newvalue);
     670             : 
     671           0 :         ret = 0;
     672             : 
     673           0 : done:
     674           0 :         TALLOC_FREE(value);
     675           0 :         TALLOC_FREE(key);
     676           0 :         TALLOC_FREE(ctx);
     677           0 :         return ret;
     678             : }
     679             : 
     680           8 : static int net_registry_deletevalue(struct net_context *c, int argc,
     681             :                                     const char **argv)
     682             : {
     683             :         WERROR werr;
     684           8 :         struct registry_key *key = NULL;
     685           8 :         TALLOC_CTX *ctx = talloc_stackframe();
     686           8 :         int ret = -1;
     687             : 
     688           8 :         if (argc != 2 || c->display_usage) {
     689           0 :                 d_fprintf(stderr, "%s\n%s",
     690             :                           _("Usage:"),
     691             :                           _("net registry deletevalue <key> <valuename>\n"));
     692           0 :                 goto done;
     693             :         }
     694             : 
     695           8 :         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
     696           8 :         if (!W_ERROR_IS_OK(werr)) {
     697           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
     698           0 :                 goto done;
     699             :         }
     700             : 
     701           8 :         werr = reg_deletevalue(key, argv[1]);
     702           8 :         if (!W_ERROR_IS_OK(werr)) {
     703           4 :                 d_fprintf(stderr, _("reg_deletevalue failed: %s\n"),
     704             :                           win_errstr(werr));
     705           4 :                 goto done;
     706             :         }
     707             : 
     708           4 :         ret = 0;
     709             : 
     710           8 : done:
     711           8 :         TALLOC_FREE(ctx);
     712           8 :         return ret;
     713             : }
     714             : 
     715           2 : static WERROR net_registry_getsd_internal(struct net_context *c,
     716             :                                           TALLOC_CTX *mem_ctx,
     717             :                                           const char *keyname,
     718             :                                           struct security_descriptor **sd)
     719             : {
     720             :         WERROR werr;
     721           2 :         struct registry_key *key = NULL;
     722           2 :         TALLOC_CTX *ctx = talloc_stackframe();
     723           2 :         uint32_t access_mask = REG_KEY_READ |
     724             :                                SEC_FLAG_MAXIMUM_ALLOWED |
     725             :                                SEC_FLAG_SYSTEM_SECURITY;
     726             : 
     727             :         /*
     728             :          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
     729             :          * is denied with these perms right now...
     730             :          */
     731           2 :         access_mask = REG_KEY_READ;
     732             : 
     733           2 :         if (sd == NULL) {
     734           0 :                 d_fprintf(stderr, _("internal error: invalid argument\n"));
     735           0 :                 werr = WERR_INVALID_PARAMETER;
     736           0 :                 goto done;
     737             :         }
     738             : 
     739           2 :         if (strlen(keyname) == 0) {
     740           0 :                 d_fprintf(stderr, _("error: zero length key name given\n"));
     741           0 :                 werr = WERR_INVALID_PARAMETER;
     742           0 :                 goto done;
     743             :         }
     744             : 
     745           2 :         werr = open_key(ctx, keyname, access_mask, &key);
     746           2 :         if (!W_ERROR_IS_OK(werr)) {
     747           0 :                 d_fprintf(stderr, "%s%s\n", _("open_key failed: "),
     748             :                           win_errstr(werr));
     749           0 :                 goto done;
     750             :         }
     751             : 
     752           2 :         werr = reg_getkeysecurity(mem_ctx, key, sd);
     753           2 :         if (!W_ERROR_IS_OK(werr)) {
     754           0 :                 d_fprintf(stderr, "%s%s\n", _("reg_getkeysecurity failed: "),
     755             :                           win_errstr(werr));
     756           0 :                 goto done;
     757             :         }
     758             : 
     759           2 :         werr = WERR_OK;
     760             : 
     761           2 : done:
     762           2 :         TALLOC_FREE(ctx);
     763           2 :         return werr;
     764             : }
     765             : 
     766           2 : static int net_registry_getsd(struct net_context *c, int argc,
     767             :                               const char **argv)
     768             : {
     769             :         WERROR werr;
     770           2 :         int ret = -1;
     771           2 :         struct security_descriptor *secdesc = NULL;
     772           2 :         TALLOC_CTX *ctx = talloc_stackframe();
     773             : 
     774           2 :         if (argc != 1 || c->display_usage) {
     775           0 :                 d_printf("%s\n%s",
     776             :                          _("Usage:"),
     777             :                          _("net registry getsd <path>\n"));
     778           0 :                 d_printf("%s\n%s",
     779             :                          _("Example:"),
     780             :                          _("net registry getsd 'HKLM\\Software\\Samba'\n"));
     781           0 :                 goto done;
     782             :         }
     783             : 
     784           2 :         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
     785           2 :         if (!W_ERROR_IS_OK(werr)) {
     786           0 :                 goto done;
     787             :         }
     788             : 
     789           2 :         display_sec_desc(secdesc);
     790             : 
     791           2 :         ret = 0;
     792             : 
     793           2 : done:
     794           2 :         TALLOC_FREE(ctx);
     795           2 :         return ret;
     796             : }
     797             : 
     798           0 : static int net_registry_getsd_sddl(struct net_context *c,
     799             :                                    int argc, const char **argv)
     800             : {
     801             :         WERROR werr;
     802           0 :         int ret = -1;
     803           0 :         struct security_descriptor *secdesc = NULL;
     804           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     805             : 
     806           0 :         if (argc != 1 || c->display_usage) {
     807           0 :                 d_printf("%s\n%s",
     808             :                          _("Usage:"),
     809             :                          _("net registry getsd_sddl <path>\n"));
     810           0 :                 d_printf("%s\n%s",
     811             :                          _("Example:"),
     812             :                          _("net registry getsd_sddl 'HKLM\\Software\\Samba'\n"));
     813           0 :                 goto done;
     814             :         }
     815             : 
     816           0 :         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
     817           0 :         if (!W_ERROR_IS_OK(werr)) {
     818           0 :                 goto done;
     819             :         }
     820             : 
     821           0 :         d_printf("%s\n", sddl_encode(ctx, secdesc, get_global_sam_sid()));
     822             : 
     823           0 :         ret = 0;
     824             : 
     825           0 : done:
     826           0 :         TALLOC_FREE(ctx);
     827           0 :         return ret;
     828             : }
     829             : 
     830           0 : static WERROR net_registry_setsd_internal(struct net_context *c,
     831             :                                           TALLOC_CTX *mem_ctx,
     832             :                                           const char *keyname,
     833             :                                           struct security_descriptor *sd)
     834             : {
     835             :         WERROR werr;
     836           0 :         struct registry_key *key = NULL;
     837           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     838           0 :         uint32_t access_mask = REG_KEY_WRITE |
     839             :                                SEC_FLAG_MAXIMUM_ALLOWED |
     840             :                                SEC_FLAG_SYSTEM_SECURITY;
     841             : 
     842             :         /*
     843             :          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
     844             :          * is denied with these perms right now...
     845             :          */
     846           0 :         access_mask = REG_KEY_WRITE;
     847             : 
     848           0 :         if (strlen(keyname) == 0) {
     849           0 :                 d_fprintf(stderr, _("error: zero length key name given\n"));
     850           0 :                 werr = WERR_INVALID_PARAMETER;
     851           0 :                 goto done;
     852             :         }
     853             : 
     854           0 :         werr = open_key(ctx, keyname, access_mask, &key);
     855           0 :         if (!W_ERROR_IS_OK(werr)) {
     856           0 :                 d_fprintf(stderr, "%s%s\n", _("open_key failed: "),
     857             :                           win_errstr(werr));
     858           0 :                 goto done;
     859             :         }
     860             : 
     861           0 :         werr = reg_setkeysecurity(key, sd);
     862           0 :         if (!W_ERROR_IS_OK(werr)) {
     863           0 :                 d_fprintf(stderr, "%s%s\n", _("reg_setkeysecurity failed: "),
     864             :                           win_errstr(werr));
     865           0 :                 goto done;
     866             :         }
     867             : 
     868           0 :         werr = WERR_OK;
     869             : 
     870           0 : done:
     871           0 :         TALLOC_FREE(ctx);
     872           0 :         return werr;
     873             : }
     874             : 
     875           0 : static int net_registry_setsd_sddl(struct net_context *c,
     876             :                                    int argc, const char **argv)
     877             : {
     878             :         WERROR werr;
     879           0 :         int ret = -1;
     880           0 :         struct security_descriptor *secdesc = NULL;
     881           0 :         TALLOC_CTX *ctx = talloc_stackframe();
     882             : 
     883           0 :         if (argc != 2 || c->display_usage) {
     884           0 :                 d_printf("%s\n%s",
     885             :                          _("Usage:"),
     886             :                          _("net registry setsd_sddl <path> <security_descriptor>\n"));
     887           0 :                 d_printf("%s\n%s",
     888             :                          _("Example:"),
     889             :                          _("net registry setsd_sddl 'HKLM\\Software\\Samba'\n"));
     890           0 :                 goto done;
     891             :         }
     892             : 
     893           0 :         secdesc = sddl_decode(ctx, argv[1], get_global_sam_sid());
     894           0 :         if (secdesc == NULL) {
     895           0 :                 goto done;
     896             :         }
     897             : 
     898           0 :         werr = net_registry_setsd_internal(c, ctx, argv[0], secdesc);
     899           0 :         if (!W_ERROR_IS_OK(werr)) {
     900           0 :                 goto done;
     901             :         }
     902             : 
     903           0 :         ret = 0;
     904             : 
     905           0 : done:
     906           0 :         TALLOC_FREE(ctx);
     907           0 :         return ret;
     908             : }
     909             : 
     910             : /******************************************************************************/
     911             : /**
     912             :  * @defgroup net_registry net registry
     913             :  */
     914             : 
     915             : /**
     916             :  * @defgroup net_registry_import Import
     917             :  * @ingroup net_registry
     918             :  * @{
     919             :  */
     920             : 
     921             : struct import_ctx {
     922             :         TALLOC_CTX *mem_ctx;
     923             : };
     924             : 
     925             : 
     926         188 : static WERROR import_create_key(struct import_ctx *ctx,
     927             :                                 struct registry_key *parent,
     928             :                                 const char *name, void **pkey, bool *existing)
     929             : {
     930             :         WERROR werr;
     931         188 :         TALLOC_CTX *mem_ctx = talloc_new(ctx->mem_ctx);
     932             : 
     933         188 :         struct registry_key *key = NULL;
     934             :         enum winreg_CreateAction action;
     935             : 
     936         188 :         if (parent == NULL) {
     937         188 :                 char *subkeyname = NULL;
     938         188 :                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
     939             :                          &parent, &subkeyname);
     940         188 :                 if (!W_ERROR_IS_OK(werr)) {
     941           0 :                         d_fprintf(stderr, _("open_hive failed: %s\n"),
     942             :                                   win_errstr(werr));
     943           0 :                         goto done;
     944             :                 }
     945         188 :                 name = subkeyname;
     946             :         }
     947             : 
     948         188 :         action = REG_ACTION_NONE;
     949         188 :         werr = reg_createkey(mem_ctx, parent, name, REG_KEY_WRITE,
     950             :                              &key, &action);
     951         188 :         if (!W_ERROR_IS_OK(werr)) {
     952           0 :                 d_fprintf(stderr, _("reg_createkey failed: %s\n"),
     953             :                           win_errstr(werr));
     954           0 :                 goto done;
     955             :         }
     956             : 
     957         188 :         if (action == REG_ACTION_NONE) {
     958           0 :                 d_fprintf(stderr, _("createkey did nothing -- huh?\n"));
     959           0 :                 werr = WERR_CREATE_FAILED;
     960           0 :                 goto done;
     961             :         }
     962             : 
     963         188 :         if (existing != NULL) {
     964         188 :                 *existing = (action == REG_OPENED_EXISTING_KEY);
     965             :         }
     966             : 
     967         188 :         if (pkey!=NULL) {
     968         188 :                 *pkey = talloc_steal(ctx->mem_ctx, key);
     969             :         }
     970             : 
     971         188 : done:
     972         188 :         talloc_free(mem_ctx);
     973         188 :         return werr;
     974             : }
     975             : 
     976         186 : static WERROR import_close_key(struct import_ctx *ctx,
     977             :                                struct registry_key *key)
     978             : {
     979         186 :         return WERR_OK;
     980             : }
     981             : 
     982           0 : static WERROR import_delete_key(struct import_ctx *ctx,
     983             :                                 struct registry_key *parent, const char *name)
     984             : {
     985             :         WERROR werr;
     986           0 :         TALLOC_CTX *mem_ctx = talloc_new(talloc_tos());
     987             : 
     988           0 :         if (parent == NULL) {
     989           0 :                 char *subkeyname = NULL;
     990           0 :                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
     991             :                          &parent, &subkeyname);
     992           0 :                 if (!W_ERROR_IS_OK(werr)) {
     993           0 :                         d_fprintf(stderr, _("open_hive failed: %s\n"),
     994             :                                   win_errstr(werr));
     995           0 :                         goto done;
     996             :                 }
     997           0 :                 name = subkeyname;
     998             :         }
     999             : 
    1000           0 :         werr = reg_deletekey_recursive(parent, name);
    1001           0 :         if (!W_ERROR_IS_OK(werr)) {
    1002           0 :                 d_fprintf(stderr, "reg_deletekey_recursive %s: %s\n",
    1003             :                           _("failed"), win_errstr(werr));
    1004           0 :                 goto done;
    1005             :         }
    1006             : 
    1007           0 : done:
    1008           0 :         talloc_free(mem_ctx);
    1009           0 :         return werr;
    1010             : }
    1011             : 
    1012         920 : static WERROR import_create_val (struct import_ctx *ctx,
    1013             :                                  struct registry_key *parent, const char *name,
    1014             :                                  const struct registry_value *value)
    1015             : {
    1016             :         WERROR werr;
    1017             : 
    1018         920 :         if (parent == NULL) {
    1019           0 :                 return WERR_INVALID_PARAMETER;
    1020             :         }
    1021             : 
    1022         920 :         werr = reg_setvalue(parent, name, value);
    1023         920 :         if (!W_ERROR_IS_OK(werr)) {
    1024           0 :                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
    1025             :                           win_errstr(werr));
    1026             :         }
    1027         920 :         return werr;
    1028             : }
    1029             : 
    1030           0 : static WERROR import_delete_val (struct import_ctx *ctx,
    1031             :                                  struct registry_key *parent, const char *name)
    1032             : {
    1033             :         WERROR werr;
    1034             : 
    1035           0 :         if (parent == NULL) {
    1036           0 :                 return WERR_INVALID_PARAMETER;
    1037             :         }
    1038             : 
    1039           0 :         werr = reg_deletevalue(parent, name);
    1040           0 :         if (!W_ERROR_IS_OK(werr)) {
    1041           0 :                 d_fprintf(stderr, _("reg_deletevalue failed: %s\n"),
    1042             :                           win_errstr(werr));
    1043             :         }
    1044             : 
    1045           0 :         return werr;
    1046             : }
    1047             : 
    1048             : struct precheck_ctx {
    1049             :         TALLOC_CTX *mem_ctx;
    1050             :         bool failed;
    1051             : };
    1052             : 
    1053           0 : static WERROR precheck_create_key(struct precheck_ctx *ctx,
    1054             :                                   struct registry_key *parent,
    1055             :                                   const char *name, void **pkey, bool *existing)
    1056             : {
    1057             :         WERROR werr;
    1058           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1059           0 :         struct registry_key *key = NULL;
    1060             : 
    1061           0 :         if (parent == NULL) {
    1062           0 :                 char *subkeyname = NULL;
    1063           0 :                 werr = open_hive(frame, name, REG_KEY_READ,
    1064             :                                  &parent, &subkeyname);
    1065           0 :                 if (!W_ERROR_IS_OK(werr)) {
    1066           0 :                         d_printf("Precheck: open_hive of [%s] failed: %s\n",
    1067             :                                  name, win_errstr(werr));
    1068           0 :                         goto done;
    1069             :                 }
    1070           0 :                 name = subkeyname;
    1071             :         }
    1072             : 
    1073           0 :         werr = reg_openkey(frame, parent, name, 0, &key);
    1074           0 :         if (!W_ERROR_IS_OK(werr)) {
    1075           0 :                 d_printf("Precheck: openkey [%s] failed: %s\n",
    1076             :                          name, win_errstr(werr));
    1077           0 :                 goto done;
    1078             :         }
    1079             : 
    1080           0 :         if (existing != NULL) {
    1081           0 :                 *existing = true;
    1082             :         }
    1083             : 
    1084           0 :         if (pkey != NULL) {
    1085           0 :                 *pkey = talloc_steal(ctx->mem_ctx, key);
    1086             :         }
    1087             : 
    1088           0 : done:
    1089           0 :         talloc_free(frame);
    1090           0 :         ctx->failed = !W_ERROR_IS_OK(werr);
    1091           0 :         return werr;
    1092             : }
    1093             : 
    1094           0 : static WERROR precheck_close_key(struct precheck_ctx *ctx,
    1095             :                                  struct registry_key *key)
    1096             : {
    1097           0 :         talloc_free(key);
    1098           0 :         return WERR_OK;
    1099             : }
    1100             : 
    1101           0 : static WERROR precheck_delete_key(struct precheck_ctx *ctx,
    1102             :                                   struct registry_key *parent, const char *name)
    1103             : {
    1104             :         WERROR werr;
    1105           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1106             :         struct registry_key *key;
    1107             : 
    1108           0 :         if (parent == NULL) {
    1109           0 :                 char *subkeyname = NULL;
    1110           0 :                 werr = open_hive(frame, name, REG_KEY_READ,
    1111             :                                  &parent, &subkeyname);
    1112           0 :                 if (!W_ERROR_IS_OK(werr)) {
    1113           0 :                         d_printf("Precheck: open_hive of [%s] failed: %s\n",
    1114             :                                  name, win_errstr(werr));
    1115           0 :                         goto done;
    1116             :                 }
    1117           0 :                 name = subkeyname;
    1118             :         }
    1119             : 
    1120           0 :         werr = reg_openkey(ctx->mem_ctx, parent, name, 0, &key);
    1121           0 :         if (W_ERROR_IS_OK(werr)) {
    1122           0 :                 d_printf("Precheck: key [%s\\%s] should not exist\n",
    1123           0 :                          parent->key->name, name);
    1124           0 :                 werr = WERR_FILE_EXISTS;
    1125           0 :         } else if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    1126           0 :                 werr = WERR_OK;
    1127             :         } else {
    1128           0 :                 d_printf("Precheck: openkey [%s\\%s] failed: %s\n",
    1129           0 :                          parent->key->name, name, win_errstr(werr));
    1130             :         }
    1131             : 
    1132           0 : done:
    1133           0 :         talloc_free(frame);
    1134           0 :         ctx->failed = !W_ERROR_IS_OK(werr);
    1135           0 :         return werr;
    1136             : }
    1137             : 
    1138           0 : static WERROR precheck_create_val(struct precheck_ctx *ctx,
    1139             :                                   struct registry_key *parent,
    1140             :                                   const char *name,
    1141             :                                   const struct registry_value *value)
    1142             : {
    1143           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1144             :         struct registry_value *old;
    1145             :         WERROR werr;
    1146             : 
    1147           0 :         SMB_ASSERT(parent);
    1148             : 
    1149           0 :         werr = reg_queryvalue(frame, parent, name, &old);
    1150           0 :         if (!W_ERROR_IS_OK(werr)) {
    1151           0 :                 d_printf("Precheck: queryvalue \"%s\" of [%s] failed: %s\n",
    1152           0 :                          name, parent->key->name, win_errstr(werr));
    1153           0 :                 goto done;
    1154             :         }
    1155           0 :         if (registry_value_cmp(value, old) != 0) {
    1156           0 :                 d_printf("Precheck: unexpected value \"%s\" of key [%s]\n",
    1157           0 :                          name, parent->key->name);
    1158           0 :                 ctx->failed = true;
    1159             :         }
    1160           0 : done:
    1161           0 :         talloc_free(frame);
    1162           0 :         return werr;
    1163             : }
    1164             : 
    1165           0 : static WERROR precheck_delete_val(struct precheck_ctx *ctx,
    1166             :                                   struct registry_key *parent,
    1167             :                                   const char *name)
    1168             : {
    1169           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1170             :         struct registry_value *old;
    1171             :         WERROR werr;
    1172             : 
    1173           0 :         SMB_ASSERT(parent);
    1174             : 
    1175           0 :         werr = reg_queryvalue(frame, parent, name, &old);
    1176           0 :         if (W_ERROR_IS_OK(werr)) {
    1177           0 :                 d_printf("Precheck: value \"%s\" of key [%s] should not exist\n",
    1178           0 :                          name, parent->key->name);
    1179           0 :                 werr = WERR_FILE_EXISTS;
    1180           0 :         } else if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
    1181           0 :                 werr = WERR_OK;
    1182             :         } else {
    1183           0 :                 printf("Precheck: queryvalue \"%s\" of key [%s] failed: %s\n",
    1184           0 :                        name, parent->key->name, win_errstr(werr));
    1185             :         }
    1186             : 
    1187           0 :         talloc_free(frame);
    1188           0 :         ctx->failed = !W_ERROR_IS_OK(werr);
    1189           0 :         return werr;
    1190             : }
    1191             : 
    1192           2 : static bool import_precheck(const char *fname, const char *parse_options)
    1193             : {
    1194           2 :         TALLOC_CTX *mem_ctx = talloc_tos();
    1195           2 :         struct precheck_ctx precheck_ctx = {
    1196             :                 .mem_ctx = mem_ctx,
    1197             :                 .failed = false,
    1198             :         };
    1199           2 :         struct reg_import_callback precheck_callback = {
    1200             :                 .openkey     = NULL,
    1201             :                 .closekey    = (reg_import_callback_closekey_t)&precheck_close_key,
    1202             :                 .createkey   = (reg_import_callback_createkey_t)&precheck_create_key,
    1203             :                 .deletekey   = (reg_import_callback_deletekey_t)&precheck_delete_key,
    1204             :                 .deleteval   = (reg_import_callback_deleteval_t)&precheck_delete_val,
    1205             :                 .setval      = {
    1206             :                         .registry_value = (reg_import_callback_setval_registry_value_t)
    1207             :                                           &precheck_create_val,
    1208             :                 },
    1209             :                 .setval_type = REGISTRY_VALUE,
    1210             :                 .data        = &precheck_ctx
    1211             :         };
    1212             :         struct reg_parse_callback *parse_callback;
    1213             :         int ret;
    1214             : 
    1215           2 :         if (!fname) {
    1216           2 :                 return true;
    1217             :         }
    1218             : 
    1219           0 :         parse_callback = reg_import_adapter(mem_ctx, precheck_callback);
    1220           0 :         if (parse_callback == NULL) {
    1221           0 :                 d_printf("talloc failed\n");
    1222           0 :                 return false;
    1223             :         }
    1224             : 
    1225           0 :         ret = reg_parse_file(fname, parse_callback, parse_options);
    1226             : 
    1227           0 :         if (ret < 0 || precheck_ctx.failed) {
    1228           0 :                 d_printf("Precheck failed\n");
    1229           0 :                 return false;
    1230             :         }
    1231           0 :         return true;
    1232             : }
    1233             : 
    1234           2 : static int import_with_precheck_action(const char *import_fname,
    1235             :                                        const char *precheck_fname,
    1236             :                                        const char *parse_options)
    1237             : {
    1238           2 :         TALLOC_CTX *frame = talloc_stackframe();
    1239           2 :         struct import_ctx import_ctx = {
    1240             :                 .mem_ctx = frame,
    1241             :         };
    1242           2 :         struct reg_import_callback import_callback = {
    1243             :                 .openkey     = NULL,
    1244             :                 .closekey    = (reg_import_callback_closekey_t)&import_close_key,
    1245             :                 .createkey   = (reg_import_callback_createkey_t)&import_create_key,
    1246             :                 .deletekey   = (reg_import_callback_deletekey_t)&import_delete_key,
    1247             :                 .deleteval   = (reg_import_callback_deleteval_t)&import_delete_val,
    1248             :                 .setval      = {
    1249             :                         .registry_value = (reg_import_callback_setval_registry_value_t)
    1250             :                                           &import_create_val,
    1251             :                 },
    1252             :                 .setval_type = REGISTRY_VALUE,
    1253             :                 .data        = &import_ctx
    1254             :         };
    1255             :         struct reg_parse_callback *parse_callback;
    1256           2 :         int ret = -1;
    1257             :         bool precheck_ok;
    1258             : 
    1259           2 :         precheck_ok = import_precheck(precheck_fname, parse_options);
    1260           2 :         if (!precheck_ok) {
    1261           0 :                 goto done;
    1262             :         }
    1263             : 
    1264           2 :         parse_callback = reg_import_adapter(frame, import_callback);
    1265           2 :         if (parse_callback == NULL) {
    1266           0 :                 d_printf("talloc failed\n");
    1267           0 :                 goto done;
    1268             :         }
    1269             : 
    1270           2 :         ret = reg_parse_file(import_fname, parse_callback, parse_options);
    1271             : 
    1272           2 : done:
    1273           2 :         talloc_free(frame);
    1274           2 :         return ret;
    1275             : }
    1276             : 
    1277           2 : static int net_registry_import(struct net_context *c, int argc,
    1278             :                                const char **argv)
    1279             : {
    1280           2 :         const char *parse_options =  (argc > 1) ? argv[1] : NULL;
    1281           2 :         int ret = -1;
    1282             :         WERROR werr;
    1283             : 
    1284           2 :         if (argc < 1 || argc > 2 || c->display_usage) {
    1285           0 :                 d_printf("%s\n%s",
    1286             :                          _("Usage:"),
    1287             :                          _("net registry import <reg> [options]\n"));
    1288           0 :                 d_printf("%s\n%s",
    1289             :                          _("Example:"),
    1290             :                          _("net registry import file.reg enc=CP1252\n"));
    1291           0 :                 return -1;
    1292             :         }
    1293             : 
    1294           2 :         werr = regdb_open();
    1295           2 :         if (!W_ERROR_IS_OK(werr)) {
    1296           0 :                 d_printf("Failed to open regdb: %s\n", win_errstr(werr));
    1297           0 :                 return -1;
    1298             :         }
    1299             : 
    1300           2 :         werr = regdb_transaction_start();
    1301           2 :         if (!W_ERROR_IS_OK(werr)) {
    1302           0 :                 d_printf("Failed to start transaction on regdb: %s\n",
    1303             :                          win_errstr(werr));
    1304           0 :                 goto done;
    1305             :         }
    1306             : 
    1307           2 :         ret = import_with_precheck_action(argv[0], c->opt_precheck,
    1308             :                                           parse_options);
    1309             : 
    1310           2 :         if (ret < 0) {
    1311           0 :                 d_printf("Transaction canceled!\n");
    1312           0 :                 regdb_transaction_cancel();
    1313           0 :                 goto done;
    1314             :         }
    1315             : 
    1316           2 :         SMB_ASSERT(ret == 0);
    1317             : 
    1318           2 :         if (c->opt_testmode) {
    1319           0 :                 d_printf("Testmode: not committing changes.\n");
    1320           0 :                 regdb_transaction_cancel();
    1321           0 :                 goto done;
    1322             :         }
    1323             : 
    1324           2 :         werr = regdb_transaction_commit();
    1325           2 :         if (!W_ERROR_IS_OK(werr)) {
    1326           0 :                 d_printf("Failed to commit transaction on regdb: %s\n",
    1327             :                          win_errstr(werr));
    1328           0 :                 ret = -1;
    1329             :         }
    1330             : 
    1331           4 : done:
    1332           2 :         regdb_close();
    1333           2 :         return ret;
    1334             : }
    1335             : /**@}*/
    1336             : 
    1337             : /******************************************************************************/
    1338             : 
    1339             : /**
    1340             :  * @defgroup net_registry_export Export
    1341             :  * @ingroup net_registry
    1342             :  * @{
    1343             :  */
    1344             : 
    1345         652 : static int registry_export(TALLOC_CTX *ctx, /*const*/ struct registry_key *key,
    1346             :                            struct reg_format *f)
    1347             : {
    1348         652 :         int ret=-1;
    1349             :         WERROR werr;
    1350             :         uint32_t count;
    1351             : 
    1352         652 :         struct registry_value *valvalue = NULL;
    1353         652 :         char *valname = NULL;
    1354             : 
    1355         652 :         char *subkey_name = NULL;
    1356         652 :         NTTIME modtime = 0;
    1357             : 
    1358         652 :         reg_format_registry_key(f, key, false);
    1359             : 
    1360             :         /* print values */
    1361        3168 :         for (count = 0;
    1362        2516 :              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
    1363        2516 :                      W_ERROR_IS_OK(werr);
    1364        1864 :              count++)
    1365             :         {
    1366        1864 :                 reg_format_registry_value(f, valname, valvalue);
    1367             :         }
    1368         652 :         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
    1369           0 :                 d_fprintf(stderr, _("reg_enumvalue failed: %s\n"),
    1370             :                           win_errstr(werr));
    1371           0 :                 goto done;
    1372             :         }
    1373             : 
    1374             :         /* recurse on subkeys */
    1375        1946 :         for (count = 0;
    1376        1294 :              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
    1377        1294 :                      W_ERROR_IS_OK(werr);
    1378         642 :              count++)
    1379             :         {
    1380         642 :                 struct registry_key *subkey = NULL;
    1381             : 
    1382         642 :                 werr = reg_openkey(ctx, key, subkey_name, REG_KEY_READ,
    1383             :                                    &subkey);
    1384         642 :                 if (!W_ERROR_IS_OK(werr)) {
    1385           0 :                         d_fprintf(stderr, _("reg_openkey failed: %s\n"),
    1386             :                                   win_errstr(werr));
    1387           0 :                         goto done;
    1388             :                 }
    1389             : 
    1390         642 :                 registry_export(ctx, subkey, f);
    1391         642 :                 TALLOC_FREE(subkey);
    1392             :         }
    1393         652 :         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
    1394           0 :                 d_fprintf(stderr, _("reg_enumkey failed: %s\n"),
    1395             :                           win_errstr(werr));
    1396           0 :                 goto done;
    1397             :         }
    1398         652 :         ret = 0;
    1399         652 : done:
    1400         652 :         return ret;
    1401             : }
    1402             : 
    1403          10 : static int net_registry_export(struct net_context *c, int argc,
    1404             :                                const char **argv)
    1405             : {
    1406          10 :         int ret=-1;
    1407             :         WERROR werr;
    1408          10 :         struct registry_key *key = NULL;
    1409          10 :         TALLOC_CTX *ctx = talloc_stackframe();
    1410          10 :         struct reg_format *f=NULL;
    1411             : 
    1412          10 :         if (argc < 2 || argc > 3 || c->display_usage) {
    1413           0 :                 d_printf("%s\n%s",
    1414             :                          _("Usage:"),
    1415             :                          _("net registry export <path> <file> [opt]\n"));
    1416           0 :                 d_printf("%s\n%s",
    1417             :                          _("Example:"),
    1418             :                          _("net registry export 'HKLM\\Software\\Samba' "
    1419             :                            "samba.reg regedit5\n"));
    1420           0 :                 goto done;
    1421             :         }
    1422             : 
    1423          10 :         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
    1424          10 :         if (!W_ERROR_IS_OK(werr)) {
    1425           0 :                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
    1426           0 :                 goto done;
    1427             :         }
    1428             : 
    1429          10 :         f = reg_format_file(ctx, argv[1], (argc > 2) ? argv[2] : NULL);
    1430          10 :         if (f == NULL) {
    1431           0 :                 d_fprintf(stderr, _("open file failed: %s\n"), strerror(errno));
    1432           0 :                 goto done;
    1433             :         }
    1434             : 
    1435          10 :         ret = registry_export(ctx, key, f);
    1436             : 
    1437          10 : done:
    1438          10 :         TALLOC_FREE(ctx);
    1439          10 :         return ret;
    1440             : }
    1441             : /**@}*/
    1442             : 
    1443             : /******************************************************************************/
    1444             : /**
    1445             :  * @defgroup net_registry_convert Convert
    1446             :  * @ingroup net_registry
    1447             :  * @{
    1448             :  */
    1449             : 
    1450           0 : static int net_registry_convert(struct net_context *c, int argc,
    1451             :                                const char **argv)
    1452             : {
    1453             :         int ret;
    1454             :         TALLOC_CTX *mem_ctx;
    1455           0 :         const char *in_opt  = NULL;
    1456           0 :         const char *out_opt = NULL;
    1457             : 
    1458           0 :         if (argc < 2 || argc > 4|| c->display_usage) {
    1459           0 :                 d_printf("%s\n%s",
    1460             :                          _("Usage:"),
    1461             :                          _("net registry convert <in> <out> [in_opt] [out_opt]\n"
    1462             :                            "net registry convert <in> <out> [out_opt]\n"));
    1463           0 :                 d_printf("%s\n%s",
    1464             :                          _("Example:"),
    1465             :                          _("net registry convert in.reg out.reg regedit4,enc=CP1252\n"));
    1466           0 :                 return -1;
    1467             :         }
    1468             : 
    1469           0 :         mem_ctx = talloc_stackframe();
    1470             : 
    1471           0 :         switch (argc ) {
    1472           0 :         case 2:
    1473           0 :                 break;
    1474           0 :         case 3:
    1475           0 :                 out_opt = argv[2];
    1476           0 :                 break;
    1477           0 :         case 4:
    1478           0 :                 out_opt = argv[3];
    1479           0 :                 in_opt  = argv[2];
    1480           0 :                 break;
    1481           0 :         default:
    1482           0 :                 assert(false);
    1483             :         }
    1484             : 
    1485             : 
    1486           0 :         ret = reg_parse_file(argv[0], (struct reg_parse_callback*)
    1487           0 :                              reg_format_file(mem_ctx, argv[1], out_opt),
    1488             :                              in_opt);
    1489             : 
    1490           0 :         talloc_free(mem_ctx);
    1491             : 
    1492           0 :         return ret;
    1493             : }
    1494             : /**@}*/
    1495             : 
    1496          28 : static int net_registry_check(struct net_context *c, int argc,
    1497             :                               const char **argv)
    1498             : {
    1499             :         char *dbfile;
    1500             :         struct check_options opts;
    1501             :         int ret;
    1502             : 
    1503          28 :         if (argc > 1|| c->display_usage) {
    1504           0 :                 d_printf("%s\n%s",
    1505             :                          _("Usage:"),
    1506             :                          _("net registry check  [-vraTfl] [-o <ODB>] [--wipe] [<TDB>]\n"
    1507             :                            "  Check a registry database.\n"
    1508             :                            "    -v|--verbose\t be verbose\n"
    1509             :                            "    -r|--repair\t\t interactive repair mode\n"
    1510             :                            "    -a|--auto\t\t noninteractive repair mode\n"
    1511             :                            "    -T|--test\t\t dry run\n"
    1512             :                            "    -f|--force\t\t force\n"
    1513             :                            "    -l|--lock\t\t lock <TDB> while doing the check\n"
    1514             :                            "    -o|--output=<ODB>\t output database\n"
    1515             :                            "    --reg-version=n\t assume database format version {n|1,2,3}\n"
    1516             :                            "    --wipe\t\t create a new database from scratch\n"
    1517             :                            "    --db=<TDB>\t\t registry database to open\n"));
    1518           0 :                 return c->display_usage ? 0 : -1;
    1519             :         }
    1520             : 
    1521          28 :         if (c->opt_db != NULL) {
    1522           0 :                 dbfile = talloc_strdup(talloc_tos(), c->opt_db);
    1523          28 :         } else if (argc > 0) {
    1524          20 :                 dbfile = talloc_strdup(talloc_tos(), argv[0]);
    1525             :         } else {
    1526           8 :                 dbfile = state_path(talloc_tos(), "registry.tdb");
    1527             :         }
    1528          28 :         if (dbfile == NULL) {
    1529           0 :                 return -1;
    1530             :         }
    1531             : 
    1532          28 :         opts = (struct check_options) {
    1533          28 :                 .lock = c->opt_lock || c->opt_long_list_entries,
    1534          28 :                 .test = c->opt_testmode,
    1535          28 :                 .automatic = c->opt_auto,
    1536          28 :                 .verbose = c->opt_verbose,
    1537          28 :                 .force = c->opt_force,
    1538          28 :                 .repair = c->opt_repair || c->opt_reboot,
    1539          28 :                 .version = c->opt_reg_version,
    1540          28 :                 .output  = c->opt_output,
    1541          28 :                 .wipe = c->opt_wipe,
    1542          28 :                 .implicit_db = (c->opt_db == NULL) && (argc == 0),
    1543             :         };
    1544             : 
    1545          28 :         ret = net_registry_check_db(dbfile, &opts);
    1546          28 :         talloc_free(dbfile);
    1547          28 :         return ret;
    1548             : }
    1549             : 
    1550             : 
    1551             : /******************************************************************************/
    1552             : 
    1553         158 : int net_registry(struct net_context *c, int argc, const char **argv)
    1554             : {
    1555         158 :         int ret = -1;
    1556             : 
    1557         158 :         struct functable func[] = {
    1558             :                 {
    1559             :                         "enumerate",
    1560             :                         net_registry_enumerate,
    1561             :                         NET_TRANSPORT_LOCAL,
    1562             :                         N_("Enumerate registry keys and values"),
    1563             :                         N_("net registry enumerate\n"
    1564             :                            "    Enumerate registry keys and values")
    1565             :                 },
    1566             :                 {
    1567             :                         "enumerate_recursive",
    1568             :                         net_registry_enumerate_recursive,
    1569             :                         NET_TRANSPORT_LOCAL,
    1570             :                         N_("Enumerate registry keys and values"),
    1571             :                         N_("net registry enumerate_recursive\n"
    1572             :                            "    Enumerate registry keys and values")
    1573             :                 },
    1574             :                 {
    1575             :                         "createkey",
    1576             :                         net_registry_createkey,
    1577             :                         NET_TRANSPORT_LOCAL,
    1578             :                         N_("Create a new registry key"),
    1579             :                         N_("net registry createkey\n"
    1580             :                            "    Create a new registry key")
    1581             :                 },
    1582             :                 {
    1583             :                         "deletekey",
    1584             :                         net_registry_deletekey,
    1585             :                         NET_TRANSPORT_LOCAL,
    1586             :                         N_("Delete a registry key"),
    1587             :                         N_("net registry deletekey\n"
    1588             :                            "    Delete a registry key")
    1589             :                 },
    1590             :                 {
    1591             :                         "deletekey_recursive",
    1592             :                         net_registry_deletekey_recursive,
    1593             :                         NET_TRANSPORT_LOCAL,
    1594             :                         N_("Delete a registry key with subkeys"),
    1595             :                         N_("net registry deletekey_recursive\n"
    1596             :                            "    Delete a registry key with subkeys")
    1597             :                 },
    1598             :                 {
    1599             :                         "getvalue",
    1600             :                         net_registry_getvalue,
    1601             :                         NET_TRANSPORT_LOCAL,
    1602             :                         N_("Print a registry value"),
    1603             :                         N_("net registry getvalue\n"
    1604             :                            "    Print a registry value")
    1605             :                 },
    1606             :                 {
    1607             :                         "getvalueraw",
    1608             :                         net_registry_getvalueraw,
    1609             :                         NET_TRANSPORT_LOCAL,
    1610             :                         N_("Print a registry value (raw format)"),
    1611             :                         N_("net registry getvalueraw\n"
    1612             :                            "    Print a registry value (raw format)")
    1613             :                 },
    1614             :                 {
    1615             :                         "getvaluesraw",
    1616             :                         net_registry_getvaluesraw,
    1617             :                         NET_TRANSPORT_LOCAL,
    1618             :                         "Print all values of a key in raw format",
    1619             :                         "net registry getvaluesraw <key>\n"
    1620             :                         "    Print a registry value (raw format)"
    1621             :                 },
    1622             :                 {
    1623             :                         "setvalue",
    1624             :                         net_registry_setvalue,
    1625             :                         NET_TRANSPORT_LOCAL,
    1626             :                         N_("Set a new registry value"),
    1627             :                         N_("net registry setvalue\n"
    1628             :                            "    Set a new registry value")
    1629             :                 },
    1630             :                 {
    1631             :                         "increment",
    1632             :                         net_registry_increment,
    1633             :                         NET_TRANSPORT_LOCAL,
    1634             :                         N_("Increment a DWORD registry value under a lock"),
    1635             :                         N_("net registry increment\n"
    1636             :                            "    Increment a DWORD registry value under a lock")
    1637             :                 },
    1638             :                 {
    1639             :                         "deletevalue",
    1640             :                         net_registry_deletevalue,
    1641             :                         NET_TRANSPORT_LOCAL,
    1642             :                         N_("Delete a registry value"),
    1643             :                         N_("net registry deletevalue\n"
    1644             :                            "    Delete a registry value")
    1645             :                 },
    1646             :                 {
    1647             :                         "getsd",
    1648             :                         net_registry_getsd,
    1649             :                         NET_TRANSPORT_LOCAL,
    1650             :                         N_("Get security descriptor"),
    1651             :                         N_("net registry getsd\n"
    1652             :                            "    Get security descriptor")
    1653             :                 },
    1654             :                 {
    1655             :                         "getsd_sddl",
    1656             :                         net_registry_getsd_sddl,
    1657             :                         NET_TRANSPORT_LOCAL,
    1658             :                         N_("Get security descriptor in sddl format"),
    1659             :                         N_("net registry getsd_sddl\n"
    1660             :                            "    Get security descriptor in sddl format")
    1661             :                 },
    1662             :                 {
    1663             :                         "setsd_sddl",
    1664             :                         net_registry_setsd_sddl,
    1665             :                         NET_TRANSPORT_LOCAL,
    1666             :                         N_("Set security descriptor from sddl format string"),
    1667             :                         N_("net registry setsd_sddl\n"
    1668             :                            "    Set security descriptor from sddl format string")
    1669             :                 },
    1670             :                 {
    1671             :                         "import",
    1672             :                         net_registry_import,
    1673             :                         NET_TRANSPORT_LOCAL,
    1674             :                         N_("Import .reg file"),
    1675             :                         N_("net registry import\n"
    1676             :                            "    Import .reg file")
    1677             :                 },
    1678             :                 {
    1679             :                         "export",
    1680             :                         net_registry_export,
    1681             :                         NET_TRANSPORT_LOCAL,
    1682             :                         N_("Export .reg file"),
    1683             :                         N_("net registry export\n"
    1684             :                            "    Export .reg file")
    1685             :                 },
    1686             :                 {
    1687             :                         "convert",
    1688             :                         net_registry_convert,
    1689             :                         NET_TRANSPORT_LOCAL,
    1690             :                         N_("Convert .reg file"),
    1691             :                         N_("net registry convert\n"
    1692             :                            "    Convert .reg file")
    1693             :                 },
    1694             :                 {
    1695             :                         "check",
    1696             :                         net_registry_check,
    1697             :                         NET_TRANSPORT_LOCAL,
    1698             :                         N_("Check a registry database"),
    1699             :                         N_("net registry check\n"
    1700             :                            "    Check a registry database")
    1701             :                 },
    1702             :         { NULL, NULL, 0, NULL, NULL }
    1703             :         };
    1704             : 
    1705         158 :         if (!c->display_usage
    1706         158 :             && argc > 0
    1707         158 :             && (strcasecmp_m(argv[0], "convert") != 0)
    1708         158 :             && (strcasecmp_m(argv[0], "check") != 0))
    1709             :         {
    1710         130 :                 if (!W_ERROR_IS_OK(registry_init_basic())) {
    1711           0 :                         return -1;
    1712             :                 }
    1713             :         }
    1714             : 
    1715         158 :         ret = net_run_function(c, argc, argv, "net registry", func);
    1716             : 
    1717         158 :         return ret;
    1718             : }

Generated by: LCOV version 1.13