LCOV - code coverage report
Current view: top level - source3/utils - net_rpc_registry.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 443 882 50.2 %
Date: 2021-09-23 10:06:22 Functions: 29 49 59.2 %

          Line data    Source code
       1             : /* 
       2             :    Samba Unix/Linux SMB client library 
       3             :    Distributed SMB/CIFS Server Management Utility 
       4             : 
       5             :    Copyright (C) Gerald (Jerry) Carter          2005-2006
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             :    
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             :    
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      19             :  
      20             : #include "includes.h"
      21             : #include "system/filesys.h"
      22             : #include "rpc_client/rpc_client.h"
      23             : #include "registry.h"
      24             : #include "utils/net.h"
      25             : #include "utils/net_registry_util.h"
      26             : #include "registry/regfio.h"
      27             : #include "../librpc/gen_ndr/ndr_winreg_c.h"
      28             : #include "../librpc/gen_ndr/ndr_security.h"
      29             : #include "registry/reg_format.h"
      30             : #include "registry/reg_import.h"
      31             : #include <assert.h>
      32             : #include "../libcli/security/display_sec.h"
      33             : #include "../libcli/registry/util_reg.h"
      34             : #include "client.h"
      35             : #include "lib/util/smb_strtox.h"
      36             : 
      37             : 
      38             : /*******************************************************************
      39             :  connect to a registry hive root (open a registry policy)
      40             : *******************************************************************/
      41             : 
      42         136 : static NTSTATUS dcerpc_winreg_Connect(struct dcerpc_binding_handle *b, TALLOC_CTX *mem_ctx,
      43             :                                       uint32_t reg_type, uint32_t access_mask,
      44             :                                       struct policy_handle *reg_hnd, WERROR *werr)
      45             : {
      46         136 :         ZERO_STRUCTP(reg_hnd);
      47             : 
      48         136 :         switch (reg_type)
      49             :         {
      50           0 :         case HKEY_CLASSES_ROOT:
      51           0 :                 return dcerpc_winreg_OpenHKCR(b, mem_ctx, NULL,
      52             :                         access_mask, reg_hnd, werr);
      53             : 
      54         136 :         case HKEY_LOCAL_MACHINE:
      55         136 :                 return dcerpc_winreg_OpenHKLM(b, mem_ctx, NULL,
      56             :                         access_mask, reg_hnd, werr);
      57             : 
      58           0 :         case HKEY_USERS:
      59           0 :                 return dcerpc_winreg_OpenHKU(b, mem_ctx, NULL,
      60             :                         access_mask, reg_hnd, werr);
      61             : 
      62           0 :         case HKEY_CURRENT_USER:
      63           0 :                 return dcerpc_winreg_OpenHKCU(b, mem_ctx, NULL,
      64             :                         access_mask, reg_hnd, werr);
      65             : 
      66           0 :         case HKEY_PERFORMANCE_DATA:
      67           0 :                 return dcerpc_winreg_OpenHKPD(b, mem_ctx, NULL,
      68             :                         access_mask, reg_hnd, werr);
      69             : 
      70           0 :         default:
      71             :                 /* fall through to end of function */
      72           0 :                 break;
      73             :         }
      74             : 
      75           0 :         return NT_STATUS_INVALID_PARAMETER;
      76             : }
      77             : 
      78         138 : static bool reg_hive_key(TALLOC_CTX *ctx, const char *fullname,
      79             :                          uint32_t *reg_type, const char **key_name)
      80             : {
      81             :         WERROR werr;
      82         138 :         char *hivename = NULL;
      83         138 :         char *tmp_keyname = NULL;
      84         138 :         bool ret = false;
      85         138 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
      86             : 
      87         138 :         werr = split_hive_key(tmp_ctx, fullname, &hivename, &tmp_keyname);
      88         138 :         if (!W_ERROR_IS_OK(werr)) {
      89           0 :                 goto done;
      90             :         }
      91             : 
      92         138 :         *key_name = talloc_strdup(ctx, tmp_keyname);
      93         138 :         if (*key_name == NULL) {
      94           0 :                 goto done;
      95             :         }
      96             : 
      97         158 :         if (strequal(hivename, "HKLM") ||
      98          20 :             strequal(hivename, "HKEY_LOCAL_MACHINE"))
      99             :         {
     100         136 :                 (*reg_type) = HKEY_LOCAL_MACHINE;
     101           4 :         } else if (strequal(hivename, "HKCR") ||
     102           2 :                    strequal(hivename, "HKEY_CLASSES_ROOT"))
     103             :         {
     104           0 :                 (*reg_type) = HKEY_CLASSES_ROOT;
     105           4 :         } else if (strequal(hivename, "HKU") ||
     106           2 :                    strequal(hivename, "HKEY_USERS"))
     107             :         {
     108           0 :                 (*reg_type) = HKEY_USERS;
     109           4 :         } else if (strequal(hivename, "HKCU") ||
     110           2 :                    strequal(hivename, "HKEY_CURRENT_USER"))
     111             :         {
     112           0 :                 (*reg_type) = HKEY_CURRENT_USER;
     113           4 :         } else if (strequal(hivename, "HKPD") ||
     114           2 :                    strequal(hivename, "HKEY_PERFORMANCE_DATA"))
     115             :         {
     116           0 :                 (*reg_type) = HKEY_PERFORMANCE_DATA;
     117             :         } else {
     118           2 :                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
     119             :                           fullname));
     120           2 :                 goto done;
     121             :         }
     122             : 
     123         136 :         ret = true;
     124             : 
     125         138 : done:
     126         138 :         TALLOC_FREE(tmp_ctx);
     127         138 :         return ret;
     128             : }
     129             : 
     130          74 : static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
     131             :                                  struct rpc_pipe_client *pipe_hnd,
     132             :                                  const char *name, uint32_t access_mask,
     133             :                                  struct policy_handle *hive_hnd,
     134             :                                  struct policy_handle *key_hnd)
     135             : {
     136             :         uint32_t hive;
     137             :         NTSTATUS status;
     138             :         WERROR werr;
     139             :         struct winreg_String key;
     140          74 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     141             : 
     142          74 :         ZERO_STRUCT(key);
     143             : 
     144          74 :         if (!reg_hive_key(mem_ctx, name, &hive, &key.name)) {
     145           2 :                 return NT_STATUS_INVALID_PARAMETER;
     146             :         }
     147             : 
     148          72 :         status = dcerpc_winreg_Connect(b, mem_ctx, hive, access_mask,
     149             :                                        hive_hnd, &werr);
     150          72 :         if (!(NT_STATUS_IS_OK(status))) {
     151           0 :                 return status;
     152             :         }
     153          72 :         if (!W_ERROR_IS_OK(werr)) {
     154           0 :                 return werror_to_ntstatus(werr);
     155             :         }
     156             : 
     157          72 :         status = dcerpc_winreg_OpenKey(b, mem_ctx, hive_hnd, key, 0,
     158             :                                        access_mask, key_hnd, &werr);
     159          72 :         if (!(NT_STATUS_IS_OK(status))) {
     160           0 :                 dcerpc_winreg_CloseKey(b, mem_ctx, hive_hnd, &werr);
     161           0 :                 return status;
     162             :         }
     163          72 :         if (!(W_ERROR_IS_OK(werr))) {
     164             :                 WERROR _werr;
     165           8 :                 dcerpc_winreg_CloseKey(b, mem_ctx, hive_hnd, &_werr);
     166           8 :                 return werror_to_ntstatus(werr);
     167             :         }
     168             : 
     169          64 :         return NT_STATUS_OK;
     170             : }
     171             : 
     172          54 : static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
     173             :                                   struct rpc_pipe_client *pipe_hnd,
     174             :                                   struct policy_handle *key_hnd,
     175             :                                   uint32_t *pnum_keys, char ***pnames,
     176             :                                   char ***pclasses, NTTIME ***pmodtimes)
     177             : {
     178             :         TALLOC_CTX *mem_ctx;
     179             :         NTSTATUS status;
     180             :         WERROR werr;
     181             :         uint32_t num_subkeys, max_subkeylen, max_classlen;
     182             :         uint32_t num_values, max_valnamelen, max_valbufsize;
     183             :         uint32_t i;
     184             :         NTTIME last_changed_time;
     185             :         uint32_t secdescsize;
     186             :         struct winreg_String classname;
     187             :         char **names, **classes;
     188             :         NTTIME **modtimes;
     189          54 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     190             : 
     191          54 :         if (!(mem_ctx = talloc_new(ctx))) {
     192           0 :                 return NT_STATUS_NO_MEMORY;
     193             :         }
     194             : 
     195          54 :         ZERO_STRUCT(classname);
     196          54 :         status = dcerpc_winreg_QueryInfoKey(
     197             :                 b, mem_ctx, key_hnd, &classname, &num_subkeys,
     198             :                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
     199             :                 &max_valbufsize, &secdescsize, &last_changed_time, &werr);
     200             : 
     201          54 :         if (!NT_STATUS_IS_OK(status)) {
     202           0 :                 goto error;
     203             :         }
     204          54 :         if (!W_ERROR_IS_OK(werr)) {
     205           0 :                 status = werror_to_ntstatus(werr);
     206           0 :                 goto error;
     207             :         }
     208             : 
     209          54 :         if (num_subkeys == 0) {
     210          24 :                 *pnum_keys = 0;
     211          24 :                 TALLOC_FREE(mem_ctx);
     212          24 :                 return NT_STATUS_OK;
     213             :         }
     214             : 
     215          60 :         if ((!(names = talloc_zero_array(mem_ctx, char *, num_subkeys))) ||
     216          60 :             (!(classes = talloc_zero_array(mem_ctx, char *, num_subkeys))) ||
     217          30 :             (!(modtimes = talloc_zero_array(mem_ctx, NTTIME *,
     218             :                                             num_subkeys)))) {
     219           0 :                 status = NT_STATUS_NO_MEMORY;
     220           0 :                 goto error;
     221             :         }
     222             : 
     223         200 :         for (i=0; i<num_subkeys; i++) {
     224             :                 char c, n;
     225             :                 struct winreg_StringBuf class_buf;
     226             :                 struct winreg_StringBuf name_buf;
     227             :                 NTTIME modtime;
     228             : 
     229          70 :                 c = '\0';
     230          70 :                 class_buf.name = &c;
     231          70 :                 class_buf.size = max_classlen+2;
     232             : 
     233          70 :                 n = '\0';
     234          70 :                 name_buf.name = &n;
     235          70 :                 name_buf.size = max_subkeylen+2;
     236             : 
     237          70 :                 ZERO_STRUCT(modtime);
     238             : 
     239          70 :                 status = dcerpc_winreg_EnumKey(b, mem_ctx, key_hnd,
     240             :                                                i, &name_buf, &class_buf,
     241             :                                                &modtime, &werr);
     242          70 :                 if (!NT_STATUS_IS_OK(status)) {
     243           0 :                         goto error;
     244             :                 }
     245          70 :                 if (W_ERROR_EQUAL(werr,
     246             :                                   WERR_NO_MORE_ITEMS) ) {
     247           0 :                         status = NT_STATUS_OK;
     248           0 :                         break;
     249             :                 }
     250          70 :                 if (!W_ERROR_IS_OK(werr)) {
     251           0 :                         status = werror_to_ntstatus(werr);
     252           0 :                         goto error;
     253             :                 }
     254             : 
     255          70 :                 classes[i] = NULL;
     256             : 
     257         140 :                 if (class_buf.name &&
     258          70 :                     (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
     259           0 :                         status = NT_STATUS_NO_MEMORY;
     260           0 :                         goto error;
     261             :                 }
     262             : 
     263          70 :                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
     264           0 :                         status = NT_STATUS_NO_MEMORY;
     265           0 :                         goto error;
     266             :                 }
     267             : 
     268          70 :                 if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
     269             :                                modtimes, &modtime, sizeof(modtime))))) {
     270           0 :                         status = NT_STATUS_NO_MEMORY;
     271           0 :                         goto error;
     272             :                 }
     273             :         }
     274             : 
     275          30 :         *pnum_keys = num_subkeys;
     276             : 
     277          30 :         if (pnames) {
     278          30 :                 *pnames = talloc_move(ctx, &names);
     279             :         }
     280          30 :         if (pclasses) {
     281          30 :                 *pclasses = talloc_move(ctx, &classes);
     282             :         }
     283          30 :         if (pmodtimes) {
     284          30 :                 *pmodtimes = talloc_move(ctx, &modtimes);
     285             :         }
     286             : 
     287          30 :         status = NT_STATUS_OK;
     288             : 
     289          30 :  error:
     290          30 :         TALLOC_FREE(mem_ctx);
     291          30 :         return status;
     292             : }
     293             : 
     294          38 : static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
     295             :                                     struct rpc_pipe_client *pipe_hnd,
     296             :                                     struct policy_handle *key_hnd,
     297             :                                     uint32_t *pnum_values, char ***pvalnames,
     298             :                                     struct registry_value ***pvalues)
     299             : {
     300             :         TALLOC_CTX *mem_ctx;
     301             :         NTSTATUS status;
     302             :         WERROR werr;
     303             :         uint32_t num_subkeys, max_subkeylen, max_classlen;
     304             :         uint32_t num_values, max_valnamelen, max_valbufsize;
     305             :         uint32_t i;
     306             :         NTTIME last_changed_time;
     307             :         uint32_t secdescsize;
     308             :         struct winreg_String classname;
     309             :         struct registry_value **values;
     310             :         char **names;
     311          38 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     312             : 
     313          38 :         if (!(mem_ctx = talloc_new(ctx))) {
     314           0 :                 return NT_STATUS_NO_MEMORY;
     315             :         }
     316             : 
     317          38 :         ZERO_STRUCT(classname);
     318          38 :         status = dcerpc_winreg_QueryInfoKey(
     319             :                 b, mem_ctx, key_hnd, &classname, &num_subkeys,
     320             :                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
     321             :                 &max_valbufsize, &secdescsize, &last_changed_time, &werr);
     322             : 
     323          38 :         if (!NT_STATUS_IS_OK(status)) {
     324           0 :                 goto error;
     325             :         }
     326          38 :         if (!W_ERROR_IS_OK(werr)) {
     327           0 :                 status = werror_to_ntstatus(werr);
     328           0 :                 goto error;
     329             :         }
     330             : 
     331          38 :         if (num_values == 0) {
     332          34 :                 *pnum_values = 0;
     333          34 :                 TALLOC_FREE(mem_ctx);
     334          34 :                 return NT_STATUS_OK;
     335             :         }
     336             : 
     337           8 :         if ((!(names = talloc_array(mem_ctx, char *, num_values))) ||
     338           4 :             (!(values = talloc_array(mem_ctx, struct registry_value *,
     339             :                                      num_values)))) {
     340           0 :                 status = NT_STATUS_NO_MEMORY;
     341           0 :                 goto error;
     342             :         }
     343             : 
     344          16 :         for (i=0; i<num_values; i++) {
     345           4 :                 enum winreg_Type type = REG_NONE;
     346           4 :                 uint8_t *data = NULL;
     347             :                 uint32_t data_size;
     348             :                 uint32_t value_length;
     349             : 
     350             :                 char n;
     351             :                 struct winreg_ValNameBuf name_buf;
     352             :                 WERROR err;
     353             : 
     354           4 :                 n = '\0';
     355           4 :                 name_buf.name = &n;
     356           4 :                 name_buf.size = max_valnamelen + 2;
     357             : 
     358           4 :                 data_size = max_valbufsize;
     359           4 :                 data = (uint8_t *)TALLOC(mem_ctx, data_size);
     360           4 :                 value_length = 0;
     361             : 
     362           4 :                 status = dcerpc_winreg_EnumValue(b, mem_ctx, key_hnd,
     363             :                                                  i, &name_buf, &type,
     364             :                                                  data, &data_size,
     365             :                                                  &value_length, &err);
     366           4 :                 if (!(NT_STATUS_IS_OK(status))) {
     367           0 :                         goto error;
     368             :                 }
     369             : 
     370           4 :                 if ( W_ERROR_EQUAL(err,
     371             :                                    WERR_NO_MORE_ITEMS) ) {
     372           0 :                         status = NT_STATUS_OK;
     373           0 :                         break;
     374             :                 }
     375             : 
     376           4 :                 if (!W_ERROR_IS_OK(err)) {
     377           0 :                         status = werror_to_ntstatus(err);
     378           0 :                         goto error;
     379             :                 }
     380             : 
     381           4 :                 if (name_buf.name == NULL) {
     382           0 :                         status = NT_STATUS_INVALID_PARAMETER;
     383           0 :                         goto error;
     384             :                 }
     385             : 
     386           4 :                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
     387           0 :                         status = NT_STATUS_NO_MEMORY;
     388           0 :                         goto error;
     389             :                 }
     390             : 
     391           4 :                 values[i] = talloc_zero(values, struct registry_value);
     392           4 :                 if (values[i] == NULL) {
     393           0 :                         status = NT_STATUS_NO_MEMORY;
     394           0 :                         goto error;
     395             :                 }
     396             : 
     397           4 :                 values[i]->type      = type;
     398           4 :                 values[i]->data = data_blob_talloc(values[i], data, data_size);
     399             :         }
     400             : 
     401           4 :         *pnum_values = num_values;
     402             : 
     403           4 :         if (pvalnames) {
     404           4 :                 *pvalnames = talloc_move(ctx, &names);
     405             :         }
     406           4 :         if (pvalues) {
     407           4 :                 *pvalues = talloc_move(ctx, &values);
     408             :         }
     409             : 
     410           4 :         status = NT_STATUS_OK;
     411             : 
     412           4 :  error:
     413           4 :         TALLOC_FREE(mem_ctx);
     414           4 :         return status;
     415             : }
     416             : 
     417          16 : static NTSTATUS registry_enumvalues2(TALLOC_CTX *ctx,
     418             :                                      struct rpc_pipe_client *pipe_hnd,
     419             :                                      struct policy_handle *key_hnd,
     420             :                                      uint32_t *pnum_values, char ***pvalnames,
     421             :                                      struct regval_blob ***pvalues)
     422             : {
     423             :         TALLOC_CTX *mem_ctx;
     424             :         NTSTATUS status;
     425             :         WERROR werr;
     426             :         uint32_t num_subkeys, max_subkeylen, max_classlen;
     427             :         uint32_t num_values, max_valnamelen, max_valbufsize;
     428             :         uint32_t i;
     429             :         NTTIME last_changed_time;
     430             :         uint32_t secdescsize;
     431             :         struct winreg_String classname;
     432             :         struct regval_blob **values;
     433             :         char **names;
     434          16 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     435             : 
     436          16 :         if (!(mem_ctx = talloc_new(ctx))) {
     437           0 :                 return NT_STATUS_NO_MEMORY;
     438             :         }
     439             : 
     440          16 :         ZERO_STRUCT(classname);
     441          16 :         status = dcerpc_winreg_QueryInfoKey(
     442             :                 b, mem_ctx, key_hnd, &classname, &num_subkeys,
     443             :                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
     444             :                 &max_valbufsize, &secdescsize, &last_changed_time, &werr);
     445             : 
     446          16 :         if (!NT_STATUS_IS_OK(status)) {
     447           0 :                 goto error;
     448             :         }
     449          16 :         if (!W_ERROR_IS_OK(werr)) {
     450           0 :                 status = werror_to_ntstatus(werr);
     451           0 :                 goto error;
     452             :         }
     453             : 
     454          16 :         if (num_values == 0) {
     455          12 :                 *pnum_values = 0;
     456          12 :                 TALLOC_FREE(mem_ctx);
     457          12 :                 return NT_STATUS_OK;
     458             :         }
     459             : 
     460           8 :         if ((!(names = talloc_array(mem_ctx, char *, num_values))) ||
     461           4 :             (!(values = talloc_array(mem_ctx, struct regval_blob *,
     462             :                                      num_values)))) {
     463           0 :                 status = NT_STATUS_NO_MEMORY;
     464           0 :                 goto error;
     465             :         }
     466             : 
     467         200 :         for (i=0; i<num_values; i++) {
     468          96 :                 enum winreg_Type type = REG_NONE;
     469          96 :                 uint8_t *data = NULL;
     470             :                 uint32_t data_size;
     471             :                 uint32_t value_length;
     472             : 
     473             :                 char n;
     474             :                 struct winreg_ValNameBuf name_buf;
     475             :                 WERROR err;
     476             : 
     477          96 :                 n = '\0';
     478          96 :                 name_buf.name = &n;
     479          96 :                 name_buf.size = max_valnamelen + 2;
     480             : 
     481          96 :                 data_size = max_valbufsize;
     482          96 :                 data = (uint8_t *)TALLOC(mem_ctx, data_size);
     483          96 :                 value_length = 0;
     484             : 
     485          96 :                 status = dcerpc_winreg_EnumValue(b, mem_ctx, key_hnd,
     486             :                                                  i, &name_buf, &type,
     487             :                                                  data, &data_size,
     488             :                                                  &value_length, &err);
     489          96 :                 if (!(NT_STATUS_IS_OK(status))) {
     490           0 :                         goto error;
     491             :                 }
     492             : 
     493          96 :                 if ( W_ERROR_EQUAL(err, WERR_NO_MORE_ITEMS) ) {
     494           0 :                         status = NT_STATUS_OK;
     495           0 :                         break;
     496             :                 }
     497             : 
     498          96 :                 if (!W_ERROR_IS_OK(err)) {
     499           0 :                         status = werror_to_ntstatus(err);
     500           0 :                         goto error;
     501             :                 }
     502             : 
     503          96 :                 if (name_buf.name == NULL) {
     504           0 :                         status = NT_STATUS_INVALID_PARAMETER;
     505           0 :                         goto error;
     506             :                 }
     507             : 
     508          96 :                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
     509           0 :                         status = NT_STATUS_NO_MEMORY;
     510           0 :                         goto error;
     511             :                 }
     512             : 
     513          96 :                 assert(value_length<=data_size); /*??? */
     514             : 
     515          96 :                 values[i] = regval_compose(values,
     516             :                                            name_buf.name,
     517             :                                            type,
     518             :                                            data, value_length);
     519          96 :                 if (!values[i]) {
     520           0 :                         status = NT_STATUS_NO_MEMORY;
     521           0 :                         goto error;
     522             :                 }
     523             :         }
     524             : 
     525           4 :         *pnum_values = num_values;
     526             : 
     527           4 :         if (pvalnames) {
     528           4 :                 *pvalnames = talloc_move(ctx, &names);
     529             :         }
     530           4 :         if (pvalues) {
     531           4 :                 *pvalues = talloc_move(ctx, &values);
     532             :         }
     533             : 
     534           4 :         status = NT_STATUS_OK;
     535             : 
     536           4 :  error:
     537           4 :         TALLOC_FREE(mem_ctx);
     538           4 :         return status;
     539             : }
     540             : 
     541           0 : static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,
     542             :                                struct dcerpc_binding_handle *b,
     543             :                                struct policy_handle *key_hnd,
     544             :                                uint32_t sec_info,
     545             :                                struct KeySecurityData *sd,
     546             :                                WERROR *werr)
     547             : {
     548           0 :         return dcerpc_winreg_GetKeySecurity(b, mem_ctx, key_hnd,
     549             :                                             sec_info, sd, werr);
     550             : }
     551             : 
     552             : 
     553           8 : static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
     554             :                                   struct rpc_pipe_client *pipe_hnd,
     555             :                                   struct policy_handle *key_hnd,
     556             :                                   const char *name,
     557             :                                   const struct registry_value *value)
     558             : {
     559             :         struct winreg_String name_string;
     560             :         NTSTATUS result;
     561             :         WERROR werr;
     562           8 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     563             : 
     564           8 :         ZERO_STRUCT(name_string);
     565             : 
     566           8 :         name_string.name = name;
     567           8 :         result = dcerpc_winreg_SetValue(b, mem_ctx, key_hnd,
     568           0 :                                         name_string, value->type,
     569           8 :                                         value->data.data, value->data.length, &werr);
     570           8 :         if (!NT_STATUS_IS_OK(result)) {
     571           0 :                 return result;
     572             :         }
     573             : 
     574           8 :         return werror_to_ntstatus(werr);
     575             : }
     576             : 
     577           8 : static NTSTATUS rpc_registry_setvalue_internal(struct net_context *c,
     578             :                                                const struct dom_sid *domain_sid,
     579             :                                                const char *domain_name,
     580             :                                                struct cli_state *cli,
     581             :                                                struct rpc_pipe_client *pipe_hnd,
     582             :                                                TALLOC_CTX *mem_ctx,
     583             :                                                int argc,
     584             :                                                const char **argv )
     585             : {
     586             :         struct policy_handle hive_hnd, key_hnd;
     587             :         NTSTATUS status;
     588             :         WERROR werr;
     589             :         struct registry_value value;
     590           8 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     591             : 
     592           8 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
     593             :                                   SEC_FLAG_MAXIMUM_ALLOWED,
     594             :                                   &hive_hnd, &key_hnd);
     595           8 :         if (!NT_STATUS_IS_OK(status)) {
     596           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
     597             :                           nt_errstr(status));
     598           0 :                 return status;
     599             :         }
     600             : 
     601           8 :         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
     602           0 :                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
     603           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     604             :         }
     605             : 
     606           8 :         if (strequal(argv[2], "dword")) {
     607           2 :                 int error = 0;
     608             :                 uint32_t v;
     609             : 
     610           2 :                 v = smb_strtoul(argv[3], NULL, 10, &error, SMB_STR_STANDARD);
     611           2 :                 if (error != 0) {
     612           0 :                         goto error;
     613             :                 }
     614             : 
     615           2 :                 value.type = REG_DWORD;
     616           2 :                 value.data = data_blob_talloc(mem_ctx, NULL, 4);
     617           2 :                 SIVAL(value.data.data, 0, v);
     618             :         }
     619           6 :         else if (strequal(argv[2], "sz")) {
     620           6 :                 value.type = REG_SZ;
     621           6 :                 if (!push_reg_sz(mem_ctx, &value.data, argv[3])) {
     622           0 :                         status = NT_STATUS_NO_MEMORY;
     623           0 :                         goto error;
     624             :                 }
     625             :         }
     626             :         else {
     627           0 :                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
     628           0 :                 status = NT_STATUS_NOT_IMPLEMENTED;
     629           0 :                 goto error;
     630             :         }
     631             : 
     632           8 :         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
     633           8 :                                    argv[1], &value);
     634             : 
     635           8 :         if (!NT_STATUS_IS_OK(status)) {
     636           0 :                 d_fprintf(stderr, _("registry_setvalue failed: %s\n"),
     637             :                           nt_errstr(status));
     638             :         }
     639             : 
     640          16 :  error:
     641           8 :         dcerpc_winreg_CloseKey(b, mem_ctx, &key_hnd, &werr);
     642           8 :         dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &werr);
     643             : 
     644           8 :         return NT_STATUS_OK;
     645             : }
     646             : 
     647           8 : static int rpc_registry_setvalue(struct net_context *c, int argc,
     648             :                                  const char **argv )
     649             : {
     650           8 :         if (argc < 4 || c->display_usage) {
     651           0 :                 d_fprintf(stderr, "%s\n%s",
     652             :                           _("Usage:"),
     653             :                           _("net rpc registry setvalue <key> <valuename> "
     654             :                             "<type> [<val>]+\n"));
     655           0 :                 return -1;
     656             :         }
     657             : 
     658           8 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
     659             :                 rpc_registry_setvalue_internal, argc, argv );
     660             : }
     661             : 
     662           8 : static NTSTATUS rpc_registry_deletevalue_internal(struct net_context *c,
     663             :                                                   const struct dom_sid *domain_sid,
     664             :                                                   const char *domain_name,
     665             :                                                   struct cli_state *cli,
     666             :                                                   struct rpc_pipe_client *pipe_hnd,
     667             :                                                   TALLOC_CTX *mem_ctx,
     668             :                                                   int argc,
     669             :                                                   const char **argv )
     670             : {
     671             :         struct policy_handle hive_hnd, key_hnd;
     672             :         NTSTATUS status;
     673             :         WERROR werr;
     674             :         struct winreg_String valuename;
     675           8 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     676             : 
     677           8 :         ZERO_STRUCT(valuename);
     678             : 
     679           8 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
     680             :                                   SEC_FLAG_MAXIMUM_ALLOWED,
     681             :                                   &hive_hnd, &key_hnd);
     682           8 :         if (!NT_STATUS_IS_OK(status)) {
     683           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
     684             :                           nt_errstr(status));
     685           0 :                 return status;
     686             :         }
     687             : 
     688           8 :         valuename.name = argv[1];
     689             : 
     690           8 :         status = dcerpc_winreg_DeleteValue(b, mem_ctx, &key_hnd,
     691             :                                            valuename, &werr);
     692           8 :         if (!NT_STATUS_IS_OK(status)) {
     693           0 :                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
     694             :                           nt_errstr(status));
     695             :         }
     696           8 :         if (!W_ERROR_IS_OK(werr)) {
     697           4 :                 status = werror_to_ntstatus(werr);
     698           4 :                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
     699             :                           win_errstr(werr));
     700             :         }
     701             : 
     702           8 :         dcerpc_winreg_CloseKey(b, mem_ctx, &key_hnd, &werr);
     703           8 :         dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &werr);
     704             : 
     705           8 :         return status;
     706             : }
     707             : 
     708           8 : static int rpc_registry_deletevalue(struct net_context *c, int argc,
     709             :                                     const char **argv )
     710             : {
     711           8 :         if (argc != 2 || c->display_usage) {
     712           0 :                 d_fprintf(stderr, "%s\n%s",
     713             :                           _("Usage:"),
     714             :                           _("net rpc registry deletevalue <key> <valuename>\n"));
     715           0 :                 return -1;
     716             :         }
     717             : 
     718           8 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
     719             :                 rpc_registry_deletevalue_internal, argc, argv );
     720             : }
     721             : 
     722           6 : static NTSTATUS rpc_registry_getvalue_internal(struct net_context *c,
     723             :                                                const struct dom_sid *domain_sid,
     724             :                                                const char *domain_name,
     725             :                                                struct cli_state *cli,
     726             :                                                struct rpc_pipe_client *pipe_hnd,
     727             :                                                TALLOC_CTX *mem_ctx,
     728             :                                                bool raw,
     729             :                                                int argc,
     730             :                                                const char **argv)
     731             : {
     732             :         struct policy_handle hive_hnd, key_hnd;
     733             :         NTSTATUS status;
     734             :         WERROR werr;
     735             :         struct winreg_String valuename;
     736           6 :         struct registry_value *value = NULL;
     737           6 :         enum winreg_Type type = REG_NONE;
     738           6 :         uint32_t data_size = 0;
     739           6 :         uint32_t value_length = 0;
     740           6 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     741           6 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     742             : 
     743           6 :         ZERO_STRUCT(valuename);
     744             : 
     745           6 :         status = registry_openkey(tmp_ctx, pipe_hnd, argv[0],
     746             :                                   SEC_FLAG_MAXIMUM_ALLOWED,
     747             :                                   &hive_hnd, &key_hnd);
     748           6 :         if (!NT_STATUS_IS_OK(status)) {
     749           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
     750             :                           nt_errstr(status));
     751           0 :                 return status;
     752             :         }
     753             : 
     754           6 :         valuename.name = argv[1];
     755             : 
     756           6 :         value = talloc_zero(tmp_ctx, struct registry_value);
     757           6 :         if (value == NULL) {
     758           0 :                 return NT_STATUS_NO_MEMORY;
     759             :         }
     760             : 
     761             :         /*
     762             :          * call QueryValue once with data == NULL to get the
     763             :          * needed memory size to be allocated, then allocate
     764             :          * data buffer and call again.
     765             :          */
     766           6 :         status = dcerpc_winreg_QueryValue(b, tmp_ctx, &key_hnd,
     767             :                                           &valuename,
     768             :                                           &type,
     769             :                                           NULL,
     770             :                                           &data_size,
     771             :                                           &value_length,
     772             :                                           &werr);
     773             : 
     774           6 :         if (!NT_STATUS_IS_OK(status)) {
     775           0 :                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
     776             :                           nt_errstr(status));
     777           0 :                 goto done;
     778             :         }
     779           6 :         if (!W_ERROR_IS_OK(werr)) {
     780           0 :                 status = werror_to_ntstatus(werr);
     781           0 :                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
     782             :                           nt_errstr(status));
     783           0 :                 goto done;
     784             :         }
     785             : 
     786           6 :         value->data = data_blob_talloc(tmp_ctx, NULL, data_size);
     787             : 
     788           6 :         status = dcerpc_winreg_QueryValue(b, tmp_ctx, &key_hnd,
     789             :                                           &valuename,
     790             :                                           &type,
     791             :                                           value->data.data,
     792             :                                           &data_size,
     793             :                                           &value_length,
     794             :                                           &werr);
     795             : 
     796           6 :         if (!NT_STATUS_IS_OK(status)) {
     797           0 :                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
     798             :                           nt_errstr(status));
     799           0 :                 goto done;
     800             :         }
     801           6 :         if (!W_ERROR_IS_OK(werr)) {
     802           0 :                 status = werror_to_ntstatus(werr);
     803           0 :                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
     804             :                           win_errstr(werr));
     805           0 :                 goto done;
     806             :         }
     807             : 
     808             : 
     809           6 :         value->type = type;
     810             : 
     811           6 :         print_registry_value(value, raw);
     812             : 
     813           6 : done:
     814           6 :         dcerpc_winreg_CloseKey(b, tmp_ctx, &key_hnd, &werr);
     815           6 :         dcerpc_winreg_CloseKey(b, tmp_ctx, &hive_hnd, &werr);
     816             : 
     817           6 :         TALLOC_FREE(tmp_ctx);
     818             : 
     819           6 :         return status;
     820             : }
     821             : 
     822           0 : static NTSTATUS rpc_registry_getvalue_full(struct net_context *c,
     823             :                                            const struct dom_sid *domain_sid,
     824             :                                            const char *domain_name,
     825             :                                            struct cli_state *cli,
     826             :                                            struct rpc_pipe_client *pipe_hnd,
     827             :                                            TALLOC_CTX *mem_ctx,
     828             :                                            int argc,
     829             :                                            const char **argv)
     830             : {
     831           0 :         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
     832             :                                               cli, pipe_hnd, mem_ctx, false,
     833             :                                               argc, argv);
     834             : }
     835             : 
     836           0 : static int rpc_registry_getvalue(struct net_context *c, int argc,
     837             :                                  const char **argv)
     838             : {
     839           0 :         if (argc != 2 || c->display_usage) {
     840           0 :                 d_fprintf(stderr, "%s\n%s",
     841             :                           _("Usage:"),
     842             :                           _("net rpc registry getvalue <key> <valuename>\n"));
     843           0 :                 return -1;
     844             :         }
     845             : 
     846           0 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
     847             :                 rpc_registry_getvalue_full, argc, argv);
     848             : }
     849             : 
     850           6 : static NTSTATUS rpc_registry_getvalue_raw(struct net_context *c,
     851             :                                           const struct dom_sid *domain_sid,
     852             :                                           const char *domain_name,
     853             :                                           struct cli_state *cli,
     854             :                                           struct rpc_pipe_client *pipe_hnd,
     855             :                                           TALLOC_CTX *mem_ctx,
     856             :                                           int argc,
     857             :                                           const char **argv)
     858             : {
     859           6 :         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
     860             :                                               cli, pipe_hnd, mem_ctx, true,
     861             :                                               argc, argv);
     862             : }
     863             : 
     864           6 : static int rpc_registry_getvalueraw(struct net_context *c, int argc,
     865             :                                     const char **argv)
     866             : {
     867           6 :         if (argc != 2 || c->display_usage) {
     868           0 :                 d_fprintf(stderr, "%s\n%s",
     869             :                           _("Usage:"),
     870             :                           _("net rpc registry getvalue <key> <valuename>\n"));
     871           0 :                 return -1;
     872             :         }
     873             : 
     874           6 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
     875             :                 rpc_registry_getvalue_raw, argc, argv);
     876             : }
     877             : 
     878          20 : static NTSTATUS rpc_registry_createkey_internal(struct net_context *c,
     879             :                                                 const struct dom_sid *domain_sid,
     880             :                                                 const char *domain_name,
     881             :                                                 struct cli_state *cli,
     882             :                                                 struct rpc_pipe_client *pipe_hnd,
     883             :                                                 TALLOC_CTX *mem_ctx,
     884             :                                                 int argc,
     885             :                                                 const char **argv )
     886             : {
     887             :         uint32_t hive;
     888             :         struct policy_handle hive_hnd, key_hnd;
     889             :         struct winreg_String key, keyclass;
     890             :         enum winreg_CreateAction action;
     891             :         NTSTATUS status;
     892             :         WERROR werr;
     893          20 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     894             : 
     895          20 :         ZERO_STRUCT(key);
     896          20 :         ZERO_STRUCT(keyclass);
     897             : 
     898          20 :         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
     899           0 :                 return NT_STATUS_INVALID_PARAMETER;
     900             :         }
     901             : 
     902          20 :         status = dcerpc_winreg_Connect(b, mem_ctx, hive,
     903             :                                        SEC_FLAG_MAXIMUM_ALLOWED,
     904             :                                        &hive_hnd, &werr);
     905          20 :         if (!(NT_STATUS_IS_OK(status))) {
     906           0 :                 return status;
     907             :         }
     908          20 :         if (!W_ERROR_IS_OK(werr)) {
     909           0 :                 return werror_to_ntstatus(werr);
     910             :         }
     911             : 
     912          20 :         action = REG_ACTION_NONE;
     913          20 :         keyclass.name = "";
     914             : 
     915          20 :         status = dcerpc_winreg_CreateKey(b, mem_ctx, &hive_hnd, key,
     916             :                                          keyclass, 0, REG_KEY_READ, NULL,
     917             :                                          &key_hnd, &action, &werr);
     918          20 :         if (!NT_STATUS_IS_OK(status)) {
     919           0 :                 d_fprintf(stderr, _("createkey returned %s\n"),
     920             :                           nt_errstr(status));
     921           0 :                 dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &werr);
     922           0 :                 return status;
     923             :         }
     924          20 :         if (!W_ERROR_IS_OK(werr)) {
     925             :                 WERROR _werr;
     926           0 :                 d_fprintf(stderr, _("createkey returned %s\n"),
     927             :                           win_errstr(werr));
     928           0 :                 dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &_werr);
     929           0 :                 return werror_to_ntstatus(werr);
     930             :         }
     931             : 
     932          20 :         switch (action) {
     933           0 :                 case REG_ACTION_NONE:
     934           0 :                         d_printf(_("createkey did nothing -- huh?\n"));
     935           0 :                         break;
     936          10 :                 case REG_CREATED_NEW_KEY:
     937          10 :                         d_printf(_("createkey created %s\n"), argv[0]);
     938          10 :                         break;
     939          10 :                 case REG_OPENED_EXISTING_KEY:
     940          10 :                         d_printf(_("createkey opened existing %s\n"), argv[0]);
     941          10 :                         break;
     942             :         }
     943             : 
     944          20 :         dcerpc_winreg_CloseKey(b, mem_ctx, &key_hnd, &werr);
     945          20 :         dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &werr);
     946             : 
     947          20 :         return status;
     948             : }
     949             : 
     950          20 : static int rpc_registry_createkey(struct net_context *c, int argc,
     951             :                                   const char **argv )
     952             : {
     953          20 :         if (argc != 1 || c->display_usage) {
     954           0 :                 d_fprintf(stderr, "%s\n%s",
     955             :                           _("Usage:"),
     956             :                           _("net rpc registry createkey <key>\n"));
     957           0 :                 return -1;
     958             :         }
     959             : 
     960          20 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
     961             :                 rpc_registry_createkey_internal, argc, argv );
     962             : }
     963             : 
     964          18 : static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
     965             :                                                 const struct dom_sid *domain_sid,
     966             :                                                 const char *domain_name,
     967             :                                                 struct cli_state *cli,
     968             :                                                 struct rpc_pipe_client *pipe_hnd,
     969             :                                                 TALLOC_CTX *mem_ctx,
     970             :                                                 int argc,
     971             :                                                 const char **argv )
     972             : {
     973             :         uint32_t hive;
     974             :         struct policy_handle hive_hnd;
     975             :         struct winreg_String key;
     976             :         NTSTATUS status;
     977             :         WERROR werr;
     978          18 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
     979             : 
     980          18 :         ZERO_STRUCT(key);
     981             : 
     982          18 :         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
     983           0 :                 return NT_STATUS_INVALID_PARAMETER;
     984             :         }
     985             : 
     986          18 :         status = dcerpc_winreg_Connect(b, mem_ctx, hive,
     987             :                                        SEC_FLAG_MAXIMUM_ALLOWED,
     988             :                                        &hive_hnd, &werr);
     989          18 :         if (!(NT_STATUS_IS_OK(status))) {
     990           0 :                 return status;
     991             :         }
     992          18 :         if (!W_ERROR_IS_OK(werr)) {
     993           0 :                 return werror_to_ntstatus(werr);
     994             :         }
     995             : 
     996          18 :         status = dcerpc_winreg_DeleteKey(b, mem_ctx, &hive_hnd, key, &werr);
     997          18 :         if (is_valid_policy_hnd(&hive_hnd)) {
     998             :                 WERROR _werr;
     999          18 :                 dcerpc_winreg_CloseKey(b, mem_ctx, &hive_hnd, &_werr);
    1000             :         }
    1001             : 
    1002          18 :         if (!NT_STATUS_IS_OK(status)) {
    1003           0 :                 d_fprintf(stderr, _("deletekey returned %s\n"),
    1004             :                           nt_errstr(status));
    1005           0 :                 return status;
    1006             :         }
    1007             : 
    1008          18 :         if (!W_ERROR_IS_OK(werr)) {
    1009           4 :                 d_fprintf(stderr, _("deletekey returned %s\n"),
    1010             :                           win_errstr(werr));
    1011           4 :                 return werror_to_ntstatus(werr);
    1012             :         }
    1013             : 
    1014          14 :         return status;
    1015             : }
    1016             : 
    1017          18 : static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
    1018             : {
    1019          18 :         if (argc != 1 || c->display_usage) {
    1020           0 :                 d_fprintf(stderr, "%s\n%s",
    1021             :                           _("Usage:"),
    1022             :                           _("net rpc registry deletekey <key>\n"));
    1023           0 :                 return -1;
    1024             :         }
    1025             : 
    1026          18 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    1027             :                 rpc_registry_deletekey_internal, argc, argv );
    1028             : }
    1029             : 
    1030             : /********************************************************************
    1031             : ********************************************************************/
    1032             : 
    1033          50 : static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
    1034             :                                                 const struct dom_sid *domain_sid,
    1035             :                                                 const char *domain_name,
    1036             :                                                 struct cli_state *cli,
    1037             :                                                 struct rpc_pipe_client *pipe_hnd,
    1038             :                                                 TALLOC_CTX *mem_ctx,
    1039             :                                                 int argc,
    1040             :                                                 const char **argv )
    1041             : {
    1042             :         struct policy_handle pol_hive, pol_key;
    1043             :         NTSTATUS status;
    1044             :         WERROR werr;
    1045          50 :         uint32_t num_subkeys = 0;
    1046          50 :         uint32_t num_values = 0;
    1047          50 :         char **names = NULL, **classes = NULL;
    1048          50 :         NTTIME **modtimes = NULL;
    1049             :         uint32_t i;
    1050          50 :         struct registry_value **values = NULL;
    1051          50 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
    1052             : 
    1053          50 :         if (argc != 1 || c->display_usage) {
    1054           2 :                 d_printf("%s\n%s",
    1055             :                          _("Usage:"),
    1056             :                          _("net rpc registry enumerate <path>\n"));
    1057           2 :                 d_printf("%s  net rpc registry enumerate "
    1058             :                          "'HKLM\\Software\\Samba'\n", _("Example:"));
    1059           2 :                 return NT_STATUS_INVALID_PARAMETER;
    1060             :         }
    1061             : 
    1062          48 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
    1063             :                                   &pol_hive, &pol_key);
    1064          48 :         if (!NT_STATUS_IS_OK(status)) {
    1065          10 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
    1066             :                           nt_errstr(status));
    1067          10 :                 return status;
    1068             :         }
    1069             : 
    1070          38 :         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
    1071             :                                    &names, &classes, &modtimes);
    1072          38 :         if (!NT_STATUS_IS_OK(status)) {
    1073           0 :                 d_fprintf(stderr, _("enumerating keys failed: %s\n"),
    1074             :                           nt_errstr(status));
    1075           0 :                 return status;
    1076             :         }
    1077             : 
    1078          96 :         for (i=0; i<num_subkeys; i++) {
    1079          58 :                 print_registry_key(names[i], modtimes[i]);
    1080             :         }
    1081             : 
    1082          38 :         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
    1083             :                                      &names, &values);
    1084          38 :         if (!NT_STATUS_IS_OK(status)) {
    1085           0 :                 d_fprintf(stderr, _("enumerating values failed: %s\n"),
    1086             :                           nt_errstr(status));
    1087           0 :                 return status;
    1088             :         }
    1089             : 
    1090          42 :         for (i=0; i<num_values; i++) {
    1091           4 :                 print_registry_value_with_name(names[i], values[i]);
    1092             :         }
    1093             : 
    1094          38 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_key, &werr);
    1095          38 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_hive, &werr);
    1096             : 
    1097          38 :         return status;
    1098             : }
    1099             : 
    1100             : /********************************************************************
    1101             : ********************************************************************/
    1102             : 
    1103          50 : static int rpc_registry_enumerate(struct net_context *c, int argc,
    1104             :                                   const char **argv )
    1105             : {
    1106          50 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    1107             :                 rpc_registry_enumerate_internal, argc, argv );
    1108             : }
    1109             : 
    1110             : /********************************************************************
    1111             : ********************************************************************/
    1112             : 
    1113           0 : static NTSTATUS rpc_registry_save_internal(struct net_context *c,
    1114             :                                         const struct dom_sid *domain_sid,
    1115             :                                         const char *domain_name,
    1116             :                                         struct cli_state *cli,
    1117             :                                         struct rpc_pipe_client *pipe_hnd,
    1118             :                                         TALLOC_CTX *mem_ctx,
    1119             :                                         int argc,
    1120             :                                         const char **argv )
    1121             : {
    1122           0 :         WERROR result = WERR_GEN_FAILURE;
    1123             :         struct policy_handle pol_hive, pol_key;
    1124           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    1125             :         struct winreg_String filename;
    1126           0 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
    1127             : 
    1128           0 :         if (argc != 2 || c->display_usage) {
    1129           0 :                 d_printf("%s\n%s",
    1130             :                          _("Usage:"),
    1131             :                          _("net rpc registry backup <path> <file> \n"));
    1132           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1133             :         }
    1134             : 
    1135           0 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
    1136             :                                   &pol_hive, &pol_key);
    1137           0 :         if (!NT_STATUS_IS_OK(status)) {
    1138           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
    1139             :                           nt_errstr(status));
    1140           0 :                 return status;
    1141             :         }
    1142             : 
    1143           0 :         filename.name = argv[1];
    1144           0 :         status = dcerpc_winreg_SaveKey(b, mem_ctx, &pol_key, &filename, NULL, &result);
    1145           0 :         if (!NT_STATUS_IS_OK(status)) {
    1146           0 :                 d_fprintf(stderr, _("Unable to save [%s] to %s:%s\n"), argv[0],
    1147           0 :                           pipe_hnd->desthost, argv[1]);
    1148             :         }
    1149           0 :         if (!W_ERROR_IS_OK(result)) {
    1150           0 :                 status = werror_to_ntstatus(result);
    1151           0 :                 d_fprintf(stderr, _("Unable to save [%s] to %s:%s\n"), argv[0],
    1152           0 :                           pipe_hnd->desthost, argv[1]);
    1153             :         }
    1154             : 
    1155             :         /* cleanup */
    1156             : 
    1157           0 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_key, &result);
    1158           0 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_hive, &result);
    1159             : 
    1160           0 :         return status;
    1161             : }
    1162             : 
    1163             : /********************************************************************
    1164             : ********************************************************************/
    1165             : 
    1166           0 : static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
    1167             : {
    1168           0 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    1169             :                 rpc_registry_save_internal, argc, argv );
    1170             : }
    1171             : 
    1172             : 
    1173             : /********************************************************************
    1174             : ********************************************************************/
    1175             : 
    1176           0 : static void dump_values( REGF_NK_REC *nk )
    1177             : {
    1178             :         int i, j;
    1179           0 :         const char *data_str = NULL;
    1180             :         uint32_t data_size, data;
    1181             :         DATA_BLOB blob;
    1182             : 
    1183           0 :         if ( !nk->values )
    1184           0 :                 return;
    1185             : 
    1186           0 :         for ( i=0; i<nk->num_values; i++ ) {
    1187           0 :                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
    1188           0 :                 d_printf( "(%s) ", str_regtype( nk->values[i].type ) );
    1189             : 
    1190           0 :                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
    1191           0 :                 switch ( nk->values[i].type ) {
    1192           0 :                         case REG_SZ:
    1193           0 :                                 blob = data_blob_const(nk->values[i].data, data_size);
    1194           0 :                                 if (!pull_reg_sz(talloc_tos(), &blob,
    1195             :                                                  &data_str)) {
    1196           0 :                                         data_str = NULL;
    1197             :                                 }
    1198           0 :                                 if (!data_str) {
    1199           0 :                                         break;
    1200             :                                 }
    1201           0 :                                 d_printf( "%s", data_str );
    1202           0 :                                 break;
    1203           0 :                         case REG_MULTI_SZ:
    1204             :                         case REG_EXPAND_SZ:
    1205           0 :                                 for ( j=0; j<data_size; j++ ) {
    1206           0 :                                         d_printf( "%c", nk->values[i].data[j] );
    1207             :                                 }
    1208           0 :                                 break;
    1209           0 :                         case REG_DWORD:
    1210           0 :                                 data = IVAL( nk->values[i].data, 0 );
    1211           0 :                                 d_printf("0x%x", data );
    1212           0 :                                 break;
    1213           0 :                         case REG_BINARY:
    1214           0 :                                 for ( j=0; j<data_size; j++ ) {
    1215           0 :                                         d_printf( "%x", nk->values[i].data[j] );
    1216             :                                 }
    1217           0 :                                 break;
    1218           0 :                         default:
    1219           0 :                                 d_printf(_("unknown"));
    1220           0 :                                 break;
    1221             :                 }
    1222             : 
    1223           0 :                 d_printf( "\n" );
    1224             :         }
    1225             : 
    1226             : }
    1227             : 
    1228             : /********************************************************************
    1229             : ********************************************************************/
    1230             : 
    1231           0 : static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
    1232             : {
    1233             :         REGF_NK_REC *key;
    1234             : 
    1235             :         /* depth first dump of the registry tree */
    1236             : 
    1237           0 :         while ( (key = regfio_fetch_subkey( file, nk )) ) {
    1238             :                 char *regpath;
    1239           0 :                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
    1240           0 :                         break;
    1241             :                 }
    1242           0 :                 d_printf("[%s]\n", regpath );
    1243           0 :                 dump_values( key );
    1244           0 :                 d_printf("\n");
    1245           0 :                 dump_registry_tree( file, key, regpath );
    1246           0 :                 SAFE_FREE(regpath);
    1247             :         }
    1248             : 
    1249           0 :         return true;
    1250             : }
    1251             : 
    1252             : /********************************************************************
    1253             : ********************************************************************/
    1254             : 
    1255           0 : static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
    1256             :                                  REGF_NK_REC *parent, REGF_FILE *outfile,
    1257             :                                  const char *parentpath )
    1258             : {
    1259             :         REGF_NK_REC *key, *subkey;
    1260           0 :         struct regval_ctr *values = NULL;
    1261           0 :         struct regsubkey_ctr *subkeys = NULL;
    1262             :         int i;
    1263           0 :         char *path = NULL;
    1264             :         WERROR werr;
    1265             : 
    1266           0 :         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
    1267           0 :         if (!W_ERROR_IS_OK(werr)) {
    1268           0 :                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
    1269             :                           "%s\n", win_errstr(werr)));
    1270           0 :                 return false;
    1271             :         }
    1272             : 
    1273           0 :         werr = regval_ctr_init(subkeys, &values);
    1274           0 :         if (!W_ERROR_IS_OK(werr)) {
    1275           0 :                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
    1276           0 :                 TALLOC_FREE(subkeys);
    1277           0 :                 return false;
    1278             :         }
    1279             : 
    1280             :         /* copy values into the struct regval_ctr */
    1281             : 
    1282           0 :         for ( i=0; i<nk->num_values; i++ ) {
    1283           0 :                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
    1284           0 :                         nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
    1285             :         }
    1286             : 
    1287             :         /* copy subkeys into the struct regsubkey_ctr */
    1288             : 
    1289           0 :         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
    1290           0 :                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
    1291             :         }
    1292             : 
    1293           0 :         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
    1294             : 
    1295             :         /* write each one of the subkeys out */
    1296             : 
    1297           0 :         path = talloc_asprintf(subkeys,
    1298             :                         "%s%s%s",
    1299             :                         parentpath,
    1300             :                         parent ? "\\" : "",
    1301             :                         nk->keyname);
    1302           0 :         if (!path) {
    1303           0 :                 TALLOC_FREE(subkeys);
    1304           0 :                 return false;
    1305             :         }
    1306             : 
    1307           0 :         nk->subkey_index = 0;
    1308           0 :         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
    1309           0 :                 write_registry_tree( infile, subkey, key, outfile, path );
    1310             :         }
    1311             : 
    1312           0 :         d_printf("[%s]\n", path );
    1313           0 :         TALLOC_FREE(subkeys);
    1314             : 
    1315           0 :         return true;
    1316             : }
    1317             : 
    1318             : /********************************************************************
    1319             : ********************************************************************/
    1320             : 
    1321           0 : static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
    1322             : {
    1323             :         REGF_FILE   *registry;
    1324             :         REGF_NK_REC *nk;
    1325             : 
    1326           0 :         if (argc != 1 || c->display_usage) {
    1327           0 :                 d_printf("%s\n%s",
    1328             :                          _("Usage:"),
    1329             :                          _("net rpc registry dump <file> \n"));
    1330           0 :                 return -1;
    1331             :         }
    1332             : 
    1333           0 :         d_printf(_("Opening %s...."), argv[0]);
    1334           0 :         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
    1335           0 :                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
    1336           0 :                 return 1;
    1337             :         }
    1338           0 :         d_printf(_("ok\n"));
    1339             : 
    1340             :         /* get the root of the registry file */
    1341             : 
    1342           0 :         if ((nk = regfio_rootkey( registry )) == NULL) {
    1343           0 :                 d_fprintf(stderr, _("Could not get rootkey\n"));
    1344           0 :                 regfio_close( registry );
    1345           0 :                 return 1;
    1346             :         }
    1347           0 :         d_printf("[%s]\n", nk->keyname);
    1348           0 :         dump_values( nk );
    1349           0 :         d_printf("\n");
    1350             : 
    1351           0 :         dump_registry_tree( registry, nk, nk->keyname );
    1352             : 
    1353             : #if 0
    1354             :         talloc_report_full( registry->mem_ctx, stderr );
    1355             : #endif
    1356           0 :         d_printf(_("Closing registry..."));
    1357           0 :         regfio_close( registry );
    1358           0 :         d_printf(_("ok\n"));
    1359             : 
    1360           0 :         return 0;
    1361             : }
    1362             : 
    1363             : /********************************************************************
    1364             : ********************************************************************/
    1365             : 
    1366           0 : static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
    1367             : {
    1368           0 :         REGF_FILE   *infile = NULL, *outfile = NULL;
    1369             :         REGF_NK_REC *nk;
    1370           0 :         int result = 1;
    1371             : 
    1372           0 :         if (argc != 2 || c->display_usage) {
    1373           0 :                 d_printf("%s\n%s",
    1374             :                          _("Usage:"),
    1375             :                          _("net rpc registry copy <srcfile> <newfile>\n"));
    1376           0 :                 return -1;
    1377             :         }
    1378             : 
    1379           0 :         d_printf(_("Opening %s...."), argv[0]);
    1380           0 :         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
    1381           0 :                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
    1382           0 :                 return 1;
    1383             :         }
    1384           0 :         d_printf(_("ok\n"));
    1385             : 
    1386           0 :         d_printf(_("Opening %s...."), argv[1]);
    1387           0 :         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC),
    1388             :                                       (S_IRUSR|S_IWUSR) )) ) {
    1389           0 :                 d_fprintf(stderr, _("Failed to open %s for writing\n"),argv[1]);
    1390           0 :                 goto out;
    1391             :         }
    1392           0 :         d_printf(_("ok\n"));
    1393             : 
    1394             :         /* get the root of the registry file */
    1395             : 
    1396           0 :         if ((nk = regfio_rootkey( infile )) == NULL) {
    1397           0 :                 d_fprintf(stderr, _("Could not get rootkey\n"));
    1398           0 :                 goto out;
    1399             :         }
    1400           0 :         d_printf(_("RootKey: [%s]\n"), nk->keyname);
    1401             : 
    1402           0 :         write_registry_tree( infile, nk, NULL, outfile, "" );
    1403             : 
    1404           0 :         result = 0;
    1405             : 
    1406           0 : out:
    1407             : 
    1408           0 :         d_printf(_("Closing %s..."), argv[1]);
    1409           0 :         if (outfile) {
    1410           0 :                 regfio_close( outfile );
    1411             :         }
    1412           0 :         d_printf(_("ok\n"));
    1413             : 
    1414           0 :         d_printf(_("Closing %s..."), argv[0]);
    1415           0 :         if (infile) {
    1416           0 :                 regfio_close( infile );
    1417             :         }
    1418           0 :         d_printf(_("ok\n"));
    1419             : 
    1420           0 :         return( result);
    1421             : }
    1422             : 
    1423             : /********************************************************************
    1424             : ********************************************************************/
    1425             : 
    1426           0 : static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
    1427             :                                             const struct dom_sid *domain_sid,
    1428             :                                             const char *domain_name,
    1429             :                                             struct cli_state *cli,
    1430             :                                             struct rpc_pipe_client *pipe_hnd,
    1431             :                                             TALLOC_CTX *mem_ctx,
    1432             :                                             int argc,
    1433             :                                             const char **argv)
    1434             : {
    1435             :         struct policy_handle pol_hive, pol_key;
    1436             :         NTSTATUS status;
    1437             :         WERROR werr;
    1438             :         enum ndr_err_code ndr_err;
    1439           0 :         struct KeySecurityData *sd = NULL;
    1440             :         uint32_t sec_info;
    1441             :         DATA_BLOB blob;
    1442             :         struct security_descriptor sec_desc;
    1443           0 :         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED |
    1444             :                                SEC_FLAG_SYSTEM_SECURITY;
    1445           0 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
    1446             : 
    1447           0 :         if (argc <1 || argc > 2 || c->display_usage) {
    1448           0 :                 d_printf("%s\n%s",
    1449             :                          _("Usage:"),
    1450             :                          _("net rpc registry getsd <path> <secinfo>\n"));
    1451           0 :                 d_printf("%s  net rpc registry getsd "
    1452             :                            "'HKLM\\Software\\Samba'\n", _("Example:"));
    1453           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1454             :         }
    1455             : 
    1456           0 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
    1457             :                                   access_mask,
    1458             :                                   &pol_hive, &pol_key);
    1459           0 :         if (!NT_STATUS_IS_OK(status)) {
    1460           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
    1461             :                           nt_errstr(status));
    1462           0 :                 return status;
    1463             :         }
    1464             : 
    1465           0 :         sd = talloc_zero(mem_ctx, struct KeySecurityData);
    1466           0 :         if (!sd) {
    1467           0 :                 status = NT_STATUS_NO_MEMORY;
    1468           0 :                 goto out;
    1469             :         }
    1470             : 
    1471           0 :         sd->size = 0x1000;
    1472             : 
    1473           0 :         if (argc >= 2) {
    1474           0 :                 sscanf(argv[1], "%x", &sec_info);
    1475             :         } else {
    1476           0 :                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
    1477             :         }
    1478             : 
    1479           0 :         status = registry_getsd(mem_ctx, b, &pol_key, sec_info, sd, &werr);
    1480           0 :         if (!NT_STATUS_IS_OK(status)) {
    1481           0 :                 d_fprintf(stderr, _("getting sd failed: %s\n"),
    1482             :                           nt_errstr(status));
    1483           0 :                 goto out;
    1484             :         }
    1485           0 :         if (!W_ERROR_IS_OK(werr)) {
    1486           0 :                 status = werror_to_ntstatus(werr);
    1487           0 :                 d_fprintf(stderr, _("getting sd failed: %s\n"),
    1488             :                           win_errstr(werr));
    1489           0 :                 goto out;
    1490             :         }
    1491             : 
    1492           0 :         blob.data = sd->data;
    1493           0 :         blob.length = sd->size;
    1494             : 
    1495           0 :         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
    1496             :                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
    1497           0 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    1498           0 :                 status = ndr_map_error2ntstatus(ndr_err);
    1499           0 :                 goto out;
    1500             :         }
    1501           0 :         status = NT_STATUS_OK;
    1502             : 
    1503           0 :         display_sec_desc(&sec_desc);
    1504             : 
    1505           0 :  out:
    1506           0 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_key, &werr);
    1507           0 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_hive, &werr);
    1508             : 
    1509           0 :         return status;
    1510             : }
    1511             : 
    1512             : 
    1513           0 : static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
    1514             : {
    1515           0 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    1516             :                 rpc_registry_getsd_internal, argc, argv);
    1517             : }
    1518             : 
    1519             : /********************************************************************
    1520             :  ********************************************************************/
    1521             : /**
    1522             :  * @defgroup net_rpc_registry net rpc registry
    1523             :  */
    1524             : 
    1525             : /**
    1526             :  * @defgroup net_rpc_registry_export Export
    1527             :  * @ingroup net_rpc_registry
    1528             :  * @{
    1529             :  */
    1530             : 
    1531          16 : static NTSTATUS registry_export(struct rpc_pipe_client* pipe_hnd,
    1532             :                                 TALLOC_CTX* ctx,
    1533             :                                 struct policy_handle* key_hnd,
    1534             :                                 struct reg_format* f,
    1535             :                                 const char* parentfullname,
    1536             :                                 const char* name)
    1537             : {
    1538             :         NTSTATUS status;
    1539          16 :         uint32_t num_subkeys = 0;
    1540          16 :         uint32_t num_values = 0;
    1541          16 :         char **names = NULL, **classes = NULL;
    1542          16 :         NTTIME **modtimes = NULL;
    1543          16 :         struct regval_blob **values = NULL;
    1544             :         uint32_t i;
    1545          16 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
    1546             : 
    1547          16 :         TALLOC_CTX* mem_ctx = talloc_new(ctx);
    1548             : 
    1549             : 
    1550          16 :         const char* fullname = name
    1551           0 :                 ? talloc_asprintf(mem_ctx, "%s\\%s", parentfullname, name)
    1552          16 :                 : parentfullname;
    1553          16 :         reg_format_key(f, &fullname, 1, false);
    1554             : 
    1555          16 :         status = registry_enumvalues2(mem_ctx, pipe_hnd, key_hnd, &num_values,
    1556             :                                       &names, &values);
    1557          16 :         if (!NT_STATUS_IS_OK(status)) {
    1558           0 :                 d_fprintf(stderr, _("enumerating values failed: %s\n"),
    1559             :                           nt_errstr(status));
    1560           0 :                 goto done;
    1561             :         }
    1562             : 
    1563         112 :         for (i=0; i<num_values; i++) {
    1564          96 :                 reg_format_regval_blob(f, names[i], values[i]);
    1565             :         }
    1566             : 
    1567             : 
    1568          16 :         status = registry_enumkeys(mem_ctx, pipe_hnd, key_hnd, &num_subkeys,
    1569             :                                    &names, &classes, &modtimes);
    1570          16 :         if (!NT_STATUS_IS_OK(status)) {
    1571           0 :                 d_fprintf(stderr, _("enumerating keys failed: %s\n"),
    1572             :                           nt_errstr(status));
    1573           0 :                 goto done;
    1574             :         }
    1575             : 
    1576          28 :         for (i=0; i<num_subkeys; i++) {
    1577             :                 struct policy_handle subkey_hnd;
    1578             :                 struct winreg_String key;
    1579             :                 WERROR werr;
    1580          12 :                 ZERO_STRUCT(key);
    1581             :                 /* key.name = talloc_strdup(mem_ctx, names[i]); ??? */
    1582          12 :                 key.name = names[i];
    1583             : 
    1584          12 :                 status = dcerpc_winreg_OpenKey(b, mem_ctx, key_hnd, key,
    1585             :                                                0, REG_KEY_READ,
    1586             :                                                &subkey_hnd, &werr);
    1587          12 :                 if (!NT_STATUS_IS_OK(status)) {
    1588           0 :                         d_fprintf(stderr,
    1589           0 :                                   _("dcerpc_winreg_OpenKey failed: %s %s\n"),
    1590           0 :                                   names[i], nt_errstr(status));
    1591           0 :                         continue;
    1592             :                 }
    1593          12 :                 if (!W_ERROR_IS_OK(werr)) {
    1594           0 :                         status = werror_to_ntstatus(werr);
    1595           0 :                         d_fprintf(stderr,
    1596           0 :                                   _("dcerpc_winreg_OpenKey failed: %s %s\n"),
    1597           0 :                                   names[i], win_errstr(werr));
    1598           0 :                         continue;
    1599             :                 }
    1600             : 
    1601          12 :                 status = registry_export(pipe_hnd, mem_ctx, &subkey_hnd,
    1602          12 :                                          f, fullname, names[i]);
    1603          12 :                 if (!(NT_STATUS_IS_OK(status))) {
    1604           0 :                         d_fprintf(stderr,
    1605           0 :                                   _("export key failed: %s %s\n"),
    1606           0 :                                   names[i], nt_errstr(status));
    1607             :                 }
    1608          12 :                 dcerpc_winreg_CloseKey(b, mem_ctx,
    1609             :                                        &subkey_hnd, &werr);
    1610             :         }
    1611          16 : done:
    1612          16 :         talloc_free(mem_ctx);
    1613          16 :         return status;
    1614             : }
    1615             : 
    1616           4 : static NTSTATUS rpc_registry_export_internal(struct net_context *c,
    1617             :                                              const struct dom_sid *domain_sid,
    1618             :                                              const char *domain_name,
    1619             :                                              struct cli_state *cli,
    1620             :                                              struct rpc_pipe_client *pipe_hnd,
    1621             :                                              TALLOC_CTX *mem_ctx,
    1622             :                                              int argc,
    1623             :                                              const char **argv )
    1624             : {
    1625             :         struct policy_handle pol_hive, pol_key;
    1626             :         NTSTATUS status;
    1627             :         WERROR werr;
    1628             :         struct reg_format* f;
    1629           4 :         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
    1630             : 
    1631           4 :         if (argc < 2 || argc > 3 || c->display_usage) {
    1632           0 :                 d_printf("%s\n%s",
    1633             :                          _("Usage:"),
    1634             :                          _("net rpc registry export <path> <file> [opt]\n"));
    1635           0 :                 d_printf("%s  net rpc registry export "
    1636             :                          "'HKLM\\Software\\Samba' samba.reg\n", _("Example:"));
    1637           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1638             :         }
    1639             : 
    1640           4 :         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
    1641             :                                   &pol_hive, &pol_key);
    1642           4 :         if (!NT_STATUS_IS_OK(status)) {
    1643           0 :                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
    1644             :                           nt_errstr(status));
    1645           0 :                 return status;
    1646             :         }
    1647             : 
    1648           4 :         f = reg_format_file(mem_ctx, argv[1], (argc > 2) ? argv[2] : NULL);
    1649           4 :         if (f == NULL) {
    1650           0 :                 d_fprintf(stderr, _("open file failed: %s\n"), strerror(errno));
    1651           0 :                 return map_nt_error_from_unix(errno);
    1652             :         }
    1653             : 
    1654           4 :         status = registry_export(pipe_hnd, mem_ctx, &pol_key,
    1655             :                                  f, argv[0], NULL );
    1656           4 :         if (!NT_STATUS_IS_OK(status))
    1657           0 :                 return status;
    1658             : 
    1659           4 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_key, &werr);
    1660           4 :         dcerpc_winreg_CloseKey(b, mem_ctx, &pol_hive, &werr);
    1661             : 
    1662           4 :         return status;
    1663             : }
    1664             : /********************************************************************
    1665             :  ********************************************************************/
    1666             : 
    1667           4 : static int rpc_registry_export(struct net_context *c, int argc,
    1668             :                                const char **argv )
    1669             : {
    1670           4 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    1671             :                                rpc_registry_export_internal, argc, argv );
    1672             : }
    1673             : 
    1674             : /**@}*/
    1675             : 
    1676             : /********************************************************************
    1677             :  ********************************************************************/
    1678             : 
    1679             : /**
    1680             :  * @defgroup net_rpc_registry_import Import
    1681             :  * @ingroup net_rpc_registry
    1682             :  * @{
    1683             :  */
    1684             : 
    1685             : struct import_ctx {
    1686             :         struct rpc_pipe_client *pipe_hnd;
    1687             :         TALLOC_CTX *mem_ctx;
    1688             : };
    1689             : 
    1690          26 : static WERROR import_create_key(struct import_ctx* ctx,
    1691             :                                 struct policy_handle* parent, const char* name,
    1692             :                                 void** pkey, bool* existing)
    1693             : {
    1694             :         WERROR werr;
    1695             :         NTSTATUS status;
    1696          26 :         void* mem_ctx = talloc_new(ctx->mem_ctx);
    1697             : 
    1698          26 :         struct policy_handle* key = NULL;
    1699             :         struct policy_handle  hive;
    1700             :         struct winreg_String  keyclass, keyname;
    1701          26 :         enum winreg_CreateAction action = REG_ACTION_NONE;
    1702          26 :         struct dcerpc_binding_handle *b = ctx->pipe_hnd->binding_handle;
    1703             : 
    1704          26 :         ZERO_STRUCT(keyname);
    1705          26 :         keyname.name = name;
    1706             : 
    1707          26 :         if (parent == NULL) {
    1708          26 :                 uint32_t hive_idx = 0;
    1709          26 :                 if (!reg_hive_key(mem_ctx, name, &hive_idx, &keyname.name)) {
    1710           0 :                         werr = WERR_FOOBAR;
    1711           0 :                         goto done;
    1712             :                 }
    1713             : 
    1714          26 :                 status = dcerpc_winreg_Connect(b, mem_ctx,
    1715             :                                                hive_idx, SEC_FLAG_MAXIMUM_ALLOWED,
    1716             :                                                &hive, &werr);
    1717          26 :                 if (!NT_STATUS_IS_OK(status)) {
    1718           0 :                         werr = ntstatus_to_werror(status);
    1719           0 :                         d_fprintf(stderr, _("dcerpc_winreg_Connect returned %s\n"),
    1720             :                                   nt_errstr(status));
    1721           0 :                         goto done;
    1722             :                 }
    1723          26 :                 if (!W_ERROR_IS_OK(werr)) {
    1724           0 :                         d_fprintf(stderr, _("dcerpc_winreg_Connect returned %s\n"),
    1725             :                                   win_errstr(werr));
    1726           0 :                         goto done;
    1727             :                 }
    1728             : 
    1729          26 :                 parent = &hive;
    1730             :         }
    1731             : 
    1732          26 :         key = talloc_zero(mem_ctx, struct policy_handle);
    1733          26 :         if (key == NULL) {
    1734           0 :                 werr = WERR_NOT_ENOUGH_MEMORY;
    1735           0 :                 goto done;
    1736             :         }
    1737             : 
    1738          26 :         ZERO_STRUCT(keyclass);
    1739          26 :         keyclass.name = "";
    1740             : 
    1741          26 :         status = dcerpc_winreg_CreateKey(b, mem_ctx,
    1742             :                                          parent, keyname,
    1743             :                                          keyclass, 0, REG_KEY_READ, NULL,
    1744             :                                          key, &action, &werr);
    1745          26 :         if (!NT_STATUS_IS_OK(status)) {
    1746           0 :                 werr = ntstatus_to_werror(status);
    1747           0 :                 d_fprintf(stderr, _("dcerpc_winreg_CreateKey returned %s\n"),
    1748             :                           nt_errstr(status));
    1749           0 :                 goto done;
    1750             :         }
    1751          26 :         if (!W_ERROR_IS_OK(werr)) {
    1752           0 :                 d_fprintf(stderr, _("dcerpc_winreg_CreateKey returned %s\n"),
    1753             :                           win_errstr(werr));
    1754           0 :                 goto done;
    1755             :         }
    1756             : 
    1757          26 :         switch (action) {
    1758           2 :         case REG_CREATED_NEW_KEY:
    1759           2 :                 d_printf(_("createkey created %s\n"), name);
    1760           2 :                 if (existing != NULL)
    1761           2 :                         *existing = false;
    1762           2 :                 break;
    1763             : 
    1764          24 :         case REG_OPENED_EXISTING_KEY:
    1765          24 :                 d_printf(_("createkey opened existing %s\n"), name);
    1766          24 :                 if (existing != NULL)
    1767          24 :                         *existing = true;
    1768          24 :                 break;
    1769             : 
    1770           0 :         case REG_ACTION_NONE:
    1771           0 :                 d_printf(_("createkey did nothing -- huh?\n"));
    1772           0 :                 werr = WERR_CREATE_FAILED;
    1773           0 :                 break;
    1774           0 :         default:
    1775           0 :                 assert(false);
    1776             :         }
    1777             : 
    1778          26 : done:
    1779          26 :         if ( parent == &hive ) {
    1780             :                 WERROR _result;
    1781          26 :                 dcerpc_winreg_CloseKey(b, mem_ctx,
    1782             :                                        parent, &_result);
    1783             :         }
    1784             : 
    1785          26 :         if (pkey!=NULL) {
    1786          26 :                 *pkey = talloc_steal(ctx->mem_ctx, key);
    1787             :         }
    1788             : 
    1789          26 :         talloc_free(mem_ctx);
    1790          26 :         return werr;
    1791             : }
    1792             : 
    1793           0 : static WERROR import_delete_key(struct import_ctx* ctx,
    1794             :                                 struct policy_handle* parent, const char* name)
    1795             : {
    1796             :         WERROR werr;
    1797             :         NTSTATUS status;
    1798           0 :         void* mem_ctx = talloc_new(ctx->mem_ctx);
    1799           0 :         struct winreg_String  keyname = { 0, };
    1800             :         struct policy_handle  hive;
    1801           0 :         struct dcerpc_binding_handle *b = ctx->pipe_hnd->binding_handle;
    1802             : 
    1803           0 :         keyname.name = name;
    1804             : 
    1805           0 :         if (parent == NULL) {
    1806             :                 uint32_t hive_idx;
    1807           0 :                 if (!reg_hive_key(mem_ctx, name, &hive_idx, &keyname.name)) {
    1808           0 :                         werr = WERR_FOOBAR;
    1809           0 :                         goto done;
    1810             :                 }
    1811             : 
    1812           0 :                 status = dcerpc_winreg_Connect(b, mem_ctx, hive_idx,
    1813             :                                                SEC_FLAG_MAXIMUM_ALLOWED, &hive,
    1814             :                                                &werr);
    1815           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1816           0 :                         werr = ntstatus_to_werror(status);
    1817           0 :                         d_fprintf(stderr, _("dcerpc_winreg_Connect returned %s\n"),
    1818             :                                   nt_errstr(status));
    1819           0 :                         goto done;
    1820             :                 }
    1821           0 :                 if (!W_ERROR_IS_OK(werr)) {
    1822           0 :                         d_fprintf(stderr, _("dcerpc_winreg_Connect returned %s\n"),
    1823             :                                   win_errstr(werr));
    1824           0 :                         goto done;
    1825             :                 }
    1826             : 
    1827           0 :                 parent = &hive;
    1828             :         }
    1829             : 
    1830           0 :         status = dcerpc_winreg_DeleteKey(b, mem_ctx, parent,
    1831             :                                          keyname, &werr);
    1832           0 :         if (!NT_STATUS_IS_OK(status)) {
    1833           0 :                 werr = ntstatus_to_werror(status);
    1834           0 :                 d_fprintf(stderr, _("dcerpc_winreg_DeleteKey returned %s\n"),
    1835             :                           nt_errstr(status));
    1836           0 :                 goto done;
    1837             :         }
    1838           0 :         if (!W_ERROR_IS_OK(werr)) {
    1839           0 :                 d_fprintf(stderr, _("dcerpc_winreg_DeleteKey returned %s\n"),
    1840             :                           win_errstr(werr));
    1841           0 :                 goto done;
    1842             :         }
    1843             : 
    1844           0 : done:
    1845           0 :         if ( parent == &hive ) {
    1846             :                 WERROR _result;
    1847           0 :                 dcerpc_winreg_CloseKey(b, mem_ctx, parent, &_result);
    1848             :         }
    1849             : 
    1850           0 :         talloc_free(mem_ctx);
    1851           0 :         return werr;
    1852             : }
    1853             : 
    1854          22 : static WERROR import_close_key(struct import_ctx* ctx,
    1855             :                                struct policy_handle* key)
    1856             : {
    1857             :         WERROR werr;
    1858             :         NTSTATUS status;
    1859          22 :         void* mem_ctx = talloc_new(ctx->mem_ctx);
    1860          22 :         struct dcerpc_binding_handle *b = ctx->pipe_hnd->binding_handle;
    1861             : 
    1862          22 :         status = dcerpc_winreg_CloseKey(b, mem_ctx, key, &werr);
    1863          22 :         if (!NT_STATUS_IS_OK(status)) {
    1864           0 :                 werr = ntstatus_to_werror(status);
    1865           0 :                 d_fprintf(stderr, _("dcerpc_winreg_CloseKey returned %s\n"),
    1866             :                           nt_errstr(status));
    1867           0 :                 goto done;
    1868             :         }
    1869          22 :         if (!W_ERROR_IS_OK(werr)) {
    1870           0 :                 d_fprintf(stderr, _("dcerpc_winreg_CloseKey returned %s\n"),
    1871             :                           win_errstr(werr));
    1872           0 :                 goto done;
    1873             :         }
    1874             : 
    1875          22 :         werr = (talloc_free(key) == 0) ? WERR_OK : WERR_GEN_FAILURE;
    1876          22 : done:
    1877          22 :         talloc_free(mem_ctx);
    1878          22 :         return werr;
    1879             : }
    1880             : 
    1881          52 : static WERROR import_create_val(struct import_ctx* ctx,
    1882             :                                 struct policy_handle* parent, const char* name,
    1883             :                                 uint32_t type, const uint8_t* val, uint32_t len)
    1884             : {
    1885             :         WERROR werr;
    1886             :         NTSTATUS status;
    1887          52 :         void* mem_ctx = talloc_new(ctx->mem_ctx);
    1888             :         struct winreg_String valuename;
    1889          52 :         struct dcerpc_binding_handle *b = ctx->pipe_hnd->binding_handle;
    1890             : 
    1891          52 :         if (parent == NULL) {
    1892           0 :                 return WERR_INVALID_PARAMETER;
    1893             :         }
    1894             : 
    1895          52 :         ZERO_STRUCT(valuename);
    1896          52 :         valuename.name = name;
    1897             : 
    1898          52 :         status = dcerpc_winreg_SetValue(b, mem_ctx, parent,
    1899             :                                         valuename, type,
    1900             :                                         (uint8_t *)discard_const(val), len, &werr);
    1901          52 :         if (!NT_STATUS_IS_OK(status)) {
    1902           0 :                 werr = ntstatus_to_werror(status);
    1903           0 :                 d_fprintf(stderr, _("registry_setvalue failed: %s\n"),
    1904             :                           nt_errstr(status));
    1905           0 :                 goto done;
    1906             :         }
    1907          52 :         if (!W_ERROR_IS_OK(werr)) {
    1908           2 :                 d_fprintf(stderr, _("registry_setvalue failed: %s\n"),
    1909             :                           win_errstr(werr));
    1910           2 :                 goto done;
    1911             :         }
    1912             : 
    1913         102 : done:
    1914          52 :         talloc_free(mem_ctx);
    1915          52 :         return werr;
    1916             : }
    1917             : 
    1918           0 : static WERROR import_delete_val(struct import_ctx* ctx,
    1919             :                                 struct policy_handle* parent, const char* name)
    1920             : {
    1921             :         WERROR werr;
    1922             :         NTSTATUS status;
    1923           0 :         void* mem_ctx = talloc_new(ctx->mem_ctx);
    1924             :         struct winreg_String valuename;
    1925           0 :         struct dcerpc_binding_handle *b = ctx->pipe_hnd->binding_handle;
    1926             : 
    1927           0 :         if (parent == NULL) {
    1928           0 :                 return WERR_INVALID_PARAMETER;
    1929             :         }
    1930             : 
    1931           0 :         ZERO_STRUCT(valuename);
    1932           0 :         valuename.name = name;
    1933             : 
    1934           0 :         status = dcerpc_winreg_DeleteValue(b, mem_ctx,
    1935             :                                            parent, valuename, &werr);
    1936             : 
    1937           0 :         if (!NT_STATUS_IS_OK(status)) {
    1938           0 :                 werr = ntstatus_to_werror(status);
    1939           0 :                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
    1940             :                           nt_errstr(status));
    1941           0 :                 goto done;
    1942             :         }
    1943           0 :         if (!NT_STATUS_IS_OK(status)) {
    1944           0 :                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
    1945             :                           win_errstr(werr));
    1946           0 :                 goto done;
    1947             :         }
    1948             : 
    1949           0 : done:
    1950           0 :         talloc_free(mem_ctx);
    1951           0 :         return werr;
    1952             : }
    1953             : 
    1954             : 
    1955             : 
    1956           8 : static NTSTATUS rpc_registry_import_internal(struct net_context *c,
    1957             :                                              const struct dom_sid *domain_sid,
    1958             :                                              const char *domain_name,
    1959             :                                              struct cli_state *cli,
    1960             :                                              struct rpc_pipe_client *pipe_hnd,
    1961             :                                              TALLOC_CTX *mem_ctx,
    1962             :                                              int argc,
    1963             :                                              const char **argv )
    1964             : {
    1965             :         struct import_ctx import_ctx;
    1966             : 
    1967           8 :         struct reg_import_callback import_callback = {
    1968             :                 .openkey     = NULL,
    1969             :                 .closekey    = (reg_import_callback_closekey_t)&import_close_key,
    1970             :                 .createkey   = (reg_import_callback_createkey_t)&import_create_key,
    1971             :                 .deletekey   = (reg_import_callback_deletekey_t)&import_delete_key,
    1972             :                 .deleteval   = (reg_import_callback_deleteval_t)&import_delete_val,
    1973             :                 .setval      = {
    1974             :                         .blob = (reg_import_callback_setval_blob_t)&import_create_val,
    1975             :                 },
    1976             :                 .setval_type = BLOB,
    1977             :                 .data = &import_ctx
    1978             :         };
    1979             : 
    1980             :         int ret;
    1981           8 :         if (argc < 1 || argc > 2 || c->display_usage) {
    1982           0 :                 d_printf("%s\n%s",
    1983             :                          _("Usage:"),
    1984             :                          _("net rpc registry import <file> [options]\n"));
    1985           0 :                 d_printf("%s  net rpc registry export "
    1986             :                          "samba.reg enc=CP1252,flags=0\n", _("Example:"));
    1987           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1988             :         }
    1989           8 :         ZERO_STRUCT(import_ctx);
    1990           8 :         import_ctx.pipe_hnd = pipe_hnd;
    1991           8 :         import_ctx.mem_ctx  = mem_ctx;
    1992          16 :         ret = reg_parse_file(argv[0],
    1993           8 :                              reg_import_adapter(import_ctx.mem_ctx,
    1994             :                                                 import_callback
    1995             :                                      ),
    1996             :                              (argc > 1) ? argv[1] : NULL
    1997             :                 );
    1998             : 
    1999           8 :         return ret==0 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
    2000             : }
    2001             : 
    2002             : /********************************************************************
    2003             :  ********************************************************************/
    2004             : 
    2005           8 : static int rpc_registry_import(struct net_context *c, int argc,
    2006             :                                const char **argv )
    2007             : {
    2008           8 :         return run_rpc_command(c, NULL, &ndr_table_winreg, 0,
    2009             :                                rpc_registry_import_internal, argc, argv );
    2010             : }
    2011             : 
    2012             : /**@}*/
    2013             : /********************************************************************
    2014             :  ********************************************************************/
    2015             : 
    2016         122 : int net_rpc_registry(struct net_context *c, int argc, const char **argv)
    2017             : {
    2018         122 :         struct functable func[] = {
    2019             :                 {
    2020             :                         "enumerate",
    2021             :                         rpc_registry_enumerate,
    2022             :                         NET_TRANSPORT_RPC,
    2023             :                         N_("Enumerate registry keys and values"),
    2024             :                         N_("net rpc registry enumerate\n"
    2025             :                            "    Enumerate registry keys and values")
    2026             :                 },
    2027             :                 {
    2028             :                         "createkey",
    2029             :                         rpc_registry_createkey,
    2030             :                         NET_TRANSPORT_RPC,
    2031             :                         N_("Create a new registry key"),
    2032             :                         N_("net rpc registry createkey\n"
    2033             :                            "    Create a new registry key")
    2034             :                 },
    2035             :                 {
    2036             :                         "deletekey",
    2037             :                         rpc_registry_deletekey,
    2038             :                         NET_TRANSPORT_RPC,
    2039             :                         N_("Delete a registry key"),
    2040             :                         N_("net rpc registry deletekey\n"
    2041             :                            "    Delete a registry key")
    2042             :                 },
    2043             :                 {
    2044             :                         "getvalue",
    2045             :                         rpc_registry_getvalue,
    2046             :                         NET_TRANSPORT_RPC,
    2047             :                         N_("Print a registry value"),
    2048             :                         N_("net rpc registry getvalue\n"
    2049             :                            "    Print a registry value")
    2050             :                 },
    2051             :                 {
    2052             :                         "getvalueraw",
    2053             :                         rpc_registry_getvalueraw,
    2054             :                         NET_TRANSPORT_RPC,
    2055             :                         N_("Print a registry value"),
    2056             :                         N_("net rpc registry getvalueraw\n"
    2057             :                            "    Print a registry value (raw version)")
    2058             :                 },
    2059             :                 {
    2060             :                         "setvalue",
    2061             :                         rpc_registry_setvalue,
    2062             :                         NET_TRANSPORT_RPC,
    2063             :                         N_("Set a new registry value"),
    2064             :                         N_("net rpc registry setvalue\n"
    2065             :                            "    Set a new registry value")
    2066             :                 },
    2067             :                 {
    2068             :                         "deletevalue",
    2069             :                         rpc_registry_deletevalue,
    2070             :                         NET_TRANSPORT_RPC,
    2071             :                         N_("Delete a registry value"),
    2072             :                         N_("net rpc registry deletevalue\n"
    2073             :                            "    Delete a registry value")
    2074             :                 },
    2075             :                 {
    2076             :                         "save",
    2077             :                         rpc_registry_save,
    2078             :                         NET_TRANSPORT_RPC,
    2079             :                         N_("Save a registry file"),
    2080             :                         N_("net rpc registry save\n"
    2081             :                            "    Save a registry file")
    2082             :                 },
    2083             :                 {
    2084             :                         "dump",
    2085             :                         rpc_registry_dump,
    2086             :                         NET_TRANSPORT_RPC,
    2087             :                         N_("Dump a registry file"),
    2088             :                         N_("net rpc registry dump\n"
    2089             :                            "    Dump a registry file")
    2090             :                 },
    2091             :                 {
    2092             :                         "copy",
    2093             :                         rpc_registry_copy,
    2094             :                         NET_TRANSPORT_RPC,
    2095             :                         N_("Copy a registry file"),
    2096             :                         N_("net rpc registry copy\n"
    2097             :                            "    Copy a registry file")
    2098             :                 },
    2099             :                 {
    2100             :                         "getsd",
    2101             :                         rpc_registry_getsd,
    2102             :                         NET_TRANSPORT_RPC,
    2103             :                         N_("Get security descriptor"),
    2104             :                         N_("net rpc registry getsd\n"
    2105             :                            "    Get security descriptor")
    2106             :                 },
    2107             :                 {
    2108             :                         "import",
    2109             :                         rpc_registry_import,
    2110             :                         NET_TRANSPORT_RPC,
    2111             :                         N_("Import .reg file"),
    2112             :                         N_("net rpc registry import\n"
    2113             :                            "    Import .reg file")
    2114             :                 },
    2115             :                 {
    2116             :                         "export",
    2117             :                         rpc_registry_export,
    2118             :                         NET_TRANSPORT_RPC,
    2119             :                         N_("Export .reg file"),
    2120             :                         N_("net rpc registry export\n"
    2121             :                            "    Export .reg file")
    2122             :                 },
    2123             :                 {NULL, NULL, 0, NULL, NULL}
    2124             :         };
    2125         122 :         return net_run_function(c, argc, argv, "net rpc registry", func);
    2126             : }

Generated by: LCOV version 1.13