s3:net rpc registry: use regval_ctr_init() instead of direct allocation
[bbaumbach/samba-autobuild/.git] / source3 / utils / net_rpc_registry.c
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 "registry.h"
22 #include "utils/net.h"
23 #include "utils/net_registry_util.h"
24 #include "regfio.h"
25 #include "../librpc/gen_ndr/cli_winreg.h"
26 #include "registry/reg_util_marshalling.h"
27
28 /*******************************************************************
29  connect to a registry hive root (open a registry policy)
30 *******************************************************************/
31
32 static NTSTATUS rpccli_winreg_Connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
33                                       uint32_t reg_type, uint32_t access_mask,
34                                       struct policy_handle *reg_hnd)
35 {
36         ZERO_STRUCTP(reg_hnd);
37
38         switch (reg_type)
39         {
40         case HKEY_CLASSES_ROOT:
41                 return rpccli_winreg_OpenHKCR( cli, mem_ctx, NULL,
42                         access_mask, reg_hnd, NULL);
43
44         case HKEY_LOCAL_MACHINE:
45                 return rpccli_winreg_OpenHKLM( cli, mem_ctx, NULL,
46                         access_mask, reg_hnd, NULL);
47
48         case HKEY_USERS:
49                 return rpccli_winreg_OpenHKU( cli, mem_ctx, NULL,
50                         access_mask, reg_hnd, NULL);
51
52         case HKEY_CURRENT_USER:
53                 return rpccli_winreg_OpenHKCU( cli, mem_ctx, NULL,
54                         access_mask, reg_hnd, NULL);
55
56         case HKEY_PERFORMANCE_DATA:
57                 return rpccli_winreg_OpenHKPD( cli, mem_ctx, NULL,
58                         access_mask, reg_hnd, NULL);
59
60         default:
61                 /* fall through to end of function */
62                 break;
63         }
64
65         return NT_STATUS_INVALID_PARAMETER;
66 }
67
68 static bool reg_hive_key(TALLOC_CTX *ctx, const char *fullname,
69                          uint32 *reg_type, const char **key_name)
70 {
71         WERROR werr;
72         char *hivename = NULL;
73         char *tmp_keyname = NULL;
74         bool ret = false;
75         TALLOC_CTX *tmp_ctx = talloc_stackframe();
76
77         werr = split_hive_key(tmp_ctx, fullname, &hivename, &tmp_keyname);
78         if (!W_ERROR_IS_OK(werr)) {
79                 goto done;
80         }
81
82         *key_name = talloc_strdup(ctx, tmp_keyname);
83         if (*key_name == NULL) {
84                 goto done;
85         }
86
87         if (strequal(hivename, "HKLM") ||
88             strequal(hivename, "HKEY_LOCAL_MACHINE"))
89         {
90                 (*reg_type) = HKEY_LOCAL_MACHINE;
91         } else if (strequal(hivename, "HKCR") ||
92                    strequal(hivename, "HKEY_CLASSES_ROOT"))
93         {
94                 (*reg_type) = HKEY_CLASSES_ROOT;
95         } else if (strequal(hivename, "HKU") ||
96                    strequal(hivename, "HKEY_USERS"))
97         {
98                 (*reg_type) = HKEY_USERS;
99         } else if (strequal(hivename, "HKCU") ||
100                    strequal(hivename, "HKEY_CURRENT_USER"))
101         {
102                 (*reg_type) = HKEY_CURRENT_USER;
103         } else if (strequal(hivename, "HKPD") ||
104                    strequal(hivename, "HKEY_PERFORMANCE_DATA"))
105         {
106                 (*reg_type) = HKEY_PERFORMANCE_DATA;
107         } else {
108                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
109                           fullname));
110                 goto done;
111         }
112
113         ret = true;
114
115 done:
116         TALLOC_FREE(tmp_ctx);
117         return ret;
118 }
119
120 static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
121                                  struct rpc_pipe_client *pipe_hnd,
122                                  const char *name, uint32 access_mask,
123                                  struct policy_handle *hive_hnd,
124                                  struct policy_handle *key_hnd)
125 {
126         uint32 hive;
127         NTSTATUS status;
128         struct winreg_String key;
129
130         ZERO_STRUCT(key);
131
132         if (!reg_hive_key(mem_ctx, name, &hive, &key.name)) {
133                 return NT_STATUS_INVALID_PARAMETER;
134         }
135
136         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
137                                        hive_hnd);
138         if (!(NT_STATUS_IS_OK(status))) {
139                 return status;
140         }
141
142         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
143                                        access_mask, key_hnd, NULL);
144         if (!(NT_STATUS_IS_OK(status))) {
145                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd, NULL);
146                 return status;
147         }
148
149         return NT_STATUS_OK;
150 }
151
152 static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
153                                   struct rpc_pipe_client *pipe_hnd,
154                                   struct policy_handle *key_hnd,
155                                   uint32 *pnum_keys, char ***pnames,
156                                   char ***pclasses, NTTIME ***pmodtimes)
157 {
158         TALLOC_CTX *mem_ctx;
159         NTSTATUS status;
160         uint32 num_subkeys, max_subkeylen, max_classlen;
161         uint32 num_values, max_valnamelen, max_valbufsize;
162         uint32 i;
163         NTTIME last_changed_time;
164         uint32 secdescsize;
165         struct winreg_String classname;
166         char **names, **classes;
167         NTTIME **modtimes;
168
169         if (!(mem_ctx = talloc_new(ctx))) {
170                 return NT_STATUS_NO_MEMORY;
171         }
172
173         ZERO_STRUCT(classname);
174         status = rpccli_winreg_QueryInfoKey(
175                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
176                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
177                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
178
179         if (!NT_STATUS_IS_OK(status)) {
180                 goto error;
181         }
182
183         if (num_subkeys == 0) {
184                 *pnum_keys = 0;
185                 TALLOC_FREE(mem_ctx);
186                 return NT_STATUS_OK;
187         }
188
189         if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
190             (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
191             (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
192                                             num_subkeys)))) {
193                 status = NT_STATUS_NO_MEMORY;
194                 goto error;
195         }
196
197         for (i=0; i<num_subkeys; i++) {
198                 char c, n;
199                 struct winreg_StringBuf class_buf;
200                 struct winreg_StringBuf name_buf;
201                 NTTIME modtime;
202                 WERROR werr;
203
204                 c = '\0';
205                 class_buf.name = &c;
206                 class_buf.size = max_classlen+2;
207
208                 n = '\0';
209                 name_buf.name = &n;
210                 name_buf.size = max_subkeylen+2;
211
212                 ZERO_STRUCT(modtime);
213
214                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
215                                                i, &name_buf, &class_buf,
216                                                &modtime, &werr);
217
218                 if (W_ERROR_EQUAL(werr,
219                                   WERR_NO_MORE_ITEMS) ) {
220                         status = NT_STATUS_OK;
221                         break;
222                 }
223                 if (!NT_STATUS_IS_OK(status)) {
224                         goto error;
225                 }
226
227                 classes[i] = NULL;
228
229                 if (class_buf.name &&
230                     (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
231                         status = NT_STATUS_NO_MEMORY;
232                         goto error;
233                 }
234
235                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
236                         status = NT_STATUS_NO_MEMORY;
237                         goto error;
238                 }
239
240                 if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
241                                modtimes, &modtime, sizeof(modtime))))) {
242                         status = NT_STATUS_NO_MEMORY;
243                         goto error;
244                 }
245         }
246
247         *pnum_keys = num_subkeys;
248
249         if (pnames) {
250                 *pnames = talloc_move(ctx, &names);
251         }
252         if (pclasses) {
253                 *pclasses = talloc_move(ctx, &classes);
254         }
255         if (pmodtimes) {
256                 *pmodtimes = talloc_move(ctx, &modtimes);
257         }
258
259         status = NT_STATUS_OK;
260
261  error:
262         TALLOC_FREE(mem_ctx);
263         return status;
264 }
265
266 static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
267                                     struct rpc_pipe_client *pipe_hnd,
268                                     struct policy_handle *key_hnd,
269                                     uint32 *pnum_values, char ***pvalnames,
270                                     struct registry_value ***pvalues)
271 {
272         TALLOC_CTX *mem_ctx;
273         NTSTATUS status;
274         uint32 num_subkeys, max_subkeylen, max_classlen;
275         uint32 num_values, max_valnamelen, max_valbufsize;
276         uint32 i;
277         NTTIME last_changed_time;
278         uint32 secdescsize;
279         struct winreg_String classname;
280         struct registry_value **values;
281         char **names;
282
283         if (!(mem_ctx = talloc_new(ctx))) {
284                 return NT_STATUS_NO_MEMORY;
285         }
286
287         ZERO_STRUCT(classname);
288         status = rpccli_winreg_QueryInfoKey(
289                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
290                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
291                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
292
293         if (!NT_STATUS_IS_OK(status)) {
294                 goto error;
295         }
296
297         if (num_values == 0) {
298                 *pnum_values = 0;
299                 TALLOC_FREE(mem_ctx);
300                 return NT_STATUS_OK;
301         }
302
303         if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
304             (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
305                                      num_values)))) {
306                 status = NT_STATUS_NO_MEMORY;
307                 goto error;
308         }
309
310         for (i=0; i<num_values; i++) {
311                 enum winreg_Type type = REG_NONE;
312                 uint8 *data = NULL;
313                 uint32 data_size;
314                 uint32 value_length;
315
316                 char n;
317                 struct winreg_ValNameBuf name_buf;
318                 WERROR err;
319
320                 n = '\0';
321                 name_buf.name = &n;
322                 name_buf.size = max_valnamelen + 2;
323
324                 data_size = max_valbufsize;
325                 data = (uint8 *)TALLOC(mem_ctx, data_size);
326                 value_length = 0;
327
328                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
329                                                  i, &name_buf, &type,
330                                                  data, &data_size,
331                                                  &value_length, &err);
332
333                 if ( W_ERROR_EQUAL(err,
334                                    WERR_NO_MORE_ITEMS) ) {
335                         status = NT_STATUS_OK;
336                         break;
337                 }
338
339                 if (!(NT_STATUS_IS_OK(status))) {
340                         goto error;
341                 }
342
343                 if (name_buf.name == NULL) {
344                         status = NT_STATUS_INVALID_PARAMETER;
345                         goto error;
346                 }
347
348                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
349                         status = NT_STATUS_NO_MEMORY;
350                         goto error;
351                 }
352
353                 err = registry_pull_value(values, &values[i], type, data,
354                                           data_size, value_length);
355                 if (!W_ERROR_IS_OK(err)) {
356                         status = werror_to_ntstatus(err);
357                         goto error;
358                 }
359         }
360
361         *pnum_values = num_values;
362
363         if (pvalnames) {
364                 *pvalnames = talloc_move(ctx, &names);
365         }
366         if (pvalues) {
367                 *pvalues = talloc_move(ctx, &values);
368         }
369
370         status = NT_STATUS_OK;
371
372  error:
373         TALLOC_FREE(mem_ctx);
374         return status;
375 }
376
377 static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,
378                                struct rpc_pipe_client *pipe_hnd,
379                                struct policy_handle *key_hnd,
380                                uint32_t sec_info,
381                                struct KeySecurityData *sd)
382 {
383         return rpccli_winreg_GetKeySecurity(pipe_hnd, mem_ctx, key_hnd,
384                                             sec_info, sd, NULL);
385 }
386
387
388 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
389                                   struct rpc_pipe_client *pipe_hnd,
390                                   struct policy_handle *key_hnd,
391                                   const char *name,
392                                   const struct registry_value *value)
393 {
394         struct winreg_String name_string;
395         DATA_BLOB blob;
396         NTSTATUS result;
397         WERROR err;
398
399         err = registry_push_value(mem_ctx, value, &blob);
400         if (!W_ERROR_IS_OK(err)) {
401                 return werror_to_ntstatus(err);
402         }
403
404         ZERO_STRUCT(name_string);
405
406         name_string.name = name;
407         result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
408                                         name_string, value->type,
409                                         blob.data, blob.length, NULL);
410         TALLOC_FREE(blob.data);
411         return result;
412 }
413
414 static NTSTATUS rpc_registry_setvalue_internal(struct net_context *c,
415                                                const struct dom_sid *domain_sid,
416                                                const char *domain_name,
417                                                struct cli_state *cli,
418                                                struct rpc_pipe_client *pipe_hnd,
419                                                TALLOC_CTX *mem_ctx,
420                                                int argc,
421                                                const char **argv )
422 {
423         struct policy_handle hive_hnd, key_hnd;
424         NTSTATUS status;
425         struct registry_value value;
426
427         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
428                                   SEC_FLAG_MAXIMUM_ALLOWED,
429                                   &hive_hnd, &key_hnd);
430         if (!NT_STATUS_IS_OK(status)) {
431                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
432                           nt_errstr(status));
433                 return status;
434         }
435
436         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
437                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
438                 return NT_STATUS_NOT_IMPLEMENTED;
439         }
440
441         if (strequal(argv[2], "dword")) {
442                 value.type = REG_DWORD;
443                 value.v.dword = strtoul(argv[3], NULL, 10);
444         }
445         else if (strequal(argv[2], "sz")) {
446                 value.type = REG_SZ;
447                 value.v.sz.len = strlen(argv[3])+1;
448                 value.v.sz.str = CONST_DISCARD(char *, argv[3]);
449         }
450         else {
451                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
452                 status = NT_STATUS_NOT_IMPLEMENTED;
453                 goto error;
454         }
455
456         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
457                                    argv[1], &value);
458
459         if (!NT_STATUS_IS_OK(status)) {
460                 d_fprintf(stderr, _("registry_setvalue failed: %s\n"),
461                           nt_errstr(status));
462         }
463
464  error:
465         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
466         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
467
468         return NT_STATUS_OK;
469 }
470
471 static int rpc_registry_setvalue(struct net_context *c, int argc,
472                                  const char **argv )
473 {
474         if (argc < 4 || c->display_usage) {
475                 d_fprintf(stderr, "%s\n%s",
476                           _("Usage:"),
477                           _("net rpc registry setvalue <key> <valuename> "
478                             "<type> [<val>]+\n"));
479                 return -1;
480         }
481
482         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
483                 rpc_registry_setvalue_internal, argc, argv );
484 }
485
486 static NTSTATUS rpc_registry_deletevalue_internal(struct net_context *c,
487                                                   const struct dom_sid *domain_sid,
488                                                   const char *domain_name,
489                                                   struct cli_state *cli,
490                                                   struct rpc_pipe_client *pipe_hnd,
491                                                   TALLOC_CTX *mem_ctx,
492                                                   int argc,
493                                                   const char **argv )
494 {
495         struct policy_handle hive_hnd, key_hnd;
496         NTSTATUS status;
497         struct winreg_String valuename;
498
499         ZERO_STRUCT(valuename);
500
501         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
502                                   SEC_FLAG_MAXIMUM_ALLOWED,
503                                   &hive_hnd, &key_hnd);
504         if (!NT_STATUS_IS_OK(status)) {
505                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
506                           nt_errstr(status));
507                 return status;
508         }
509
510         valuename.name = argv[1];
511
512         status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
513                                            valuename, NULL);
514
515         if (!NT_STATUS_IS_OK(status)) {
516                 d_fprintf(stderr, _("registry_deletevalue failed: %s\n"),
517                           nt_errstr(status));
518         }
519
520         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
521         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
522
523         return status;
524 }
525
526 static int rpc_registry_deletevalue(struct net_context *c, int argc,
527                                     const char **argv )
528 {
529         if (argc != 2 || c->display_usage) {
530                 d_fprintf(stderr, "%s\n%s",
531                           _("Usage:"),
532                           _("net rpc registry deletevalue <key> <valuename>\n"));
533                 return -1;
534         }
535
536         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
537                 rpc_registry_deletevalue_internal, argc, argv );
538 }
539
540 static NTSTATUS rpc_registry_getvalue_internal(struct net_context *c,
541                                                const struct dom_sid *domain_sid,
542                                                const char *domain_name,
543                                                struct cli_state *cli,
544                                                struct rpc_pipe_client *pipe_hnd,
545                                                TALLOC_CTX *mem_ctx,
546                                                bool raw,
547                                                int argc,
548                                                const char **argv)
549 {
550         struct policy_handle hive_hnd, key_hnd;
551         NTSTATUS status;
552         WERROR werr;
553         struct winreg_String valuename;
554         struct registry_value *value = NULL;
555         enum winreg_Type type = REG_NONE;
556         uint8_t *data = NULL;
557         uint32_t data_size = 0;
558         uint32_t value_length = 0;
559         TALLOC_CTX *tmp_ctx = talloc_stackframe();
560
561         ZERO_STRUCT(valuename);
562
563         status = registry_openkey(tmp_ctx, pipe_hnd, argv[0],
564                                   SEC_FLAG_MAXIMUM_ALLOWED,
565                                   &hive_hnd, &key_hnd);
566         if (!NT_STATUS_IS_OK(status)) {
567                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
568                           nt_errstr(status));
569                 return status;
570         }
571
572         valuename.name = argv[1];
573
574         /*
575          * call QueryValue once with data == NULL to get the
576          * needed memory size to be allocated, then allocate
577          * data buffer and call again.
578          */
579         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
580                                           &valuename,
581                                           &type,
582                                           data,
583                                           &data_size,
584                                           &value_length,
585                                           NULL);
586
587         if (!NT_STATUS_IS_OK(status)) {
588                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
589                           nt_errstr(status));
590                 goto done;
591         }
592
593         data = (uint8 *)TALLOC(tmp_ctx, data_size);
594         value_length = 0;
595
596         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
597                                           &valuename,
598                                           &type,
599                                           data,
600                                           &data_size,
601                                           &value_length,
602                                           NULL);
603
604         if (!NT_STATUS_IS_OK(status)) {
605                 d_fprintf(stderr, _("registry_queryvalue failed: %s\n"),
606                           nt_errstr(status));
607                 goto done;
608         }
609
610         werr = registry_pull_value(tmp_ctx, &value, type, data,
611                                    data_size, value_length);
612         if (!W_ERROR_IS_OK(werr)) {
613                 status = werror_to_ntstatus(werr);
614                 goto done;
615         }
616
617         print_registry_value(value, raw);
618
619 done:
620         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &key_hnd, NULL);
621         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &hive_hnd, NULL);
622
623         TALLOC_FREE(tmp_ctx);
624
625         return status;
626 }
627
628 static NTSTATUS rpc_registry_getvalue_full(struct net_context *c,
629                                            const struct dom_sid *domain_sid,
630                                            const char *domain_name,
631                                            struct cli_state *cli,
632                                            struct rpc_pipe_client *pipe_hnd,
633                                            TALLOC_CTX *mem_ctx,
634                                            int argc,
635                                            const char **argv)
636 {
637         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
638                                               cli, pipe_hnd, mem_ctx, false,
639                                               argc, argv);
640 }
641
642 static int rpc_registry_getvalue(struct net_context *c, int argc,
643                                  const char **argv)
644 {
645         if (argc != 2 || c->display_usage) {
646                 d_fprintf(stderr, "%s\n%s",
647                           _("Usage:"),
648                           _("net rpc registry getvalue <key> <valuename>\n"));
649                 return -1;
650         }
651
652         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
653                 rpc_registry_getvalue_full, argc, argv);
654 }
655
656 static NTSTATUS rpc_registry_getvalue_raw(struct net_context *c,
657                                           const struct dom_sid *domain_sid,
658                                           const char *domain_name,
659                                           struct cli_state *cli,
660                                           struct rpc_pipe_client *pipe_hnd,
661                                           TALLOC_CTX *mem_ctx,
662                                           int argc,
663                                           const char **argv)
664 {
665         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
666                                               cli, pipe_hnd, mem_ctx, true,
667                                               argc, argv);
668 }
669
670 static int rpc_registry_getvalueraw(struct net_context *c, int argc,
671                                     const char **argv)
672 {
673         if (argc != 2 || c->display_usage) {
674                 d_fprintf(stderr, "%s\n%s",
675                           _("Usage:"),
676                           _("net rpc registry getvalue <key> <valuename>\n"));
677                 return -1;
678         }
679
680         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
681                 rpc_registry_getvalue_raw, argc, argv);
682 }
683
684 static NTSTATUS rpc_registry_createkey_internal(struct net_context *c,
685                                                 const struct dom_sid *domain_sid,
686                                                 const char *domain_name,
687                                                 struct cli_state *cli,
688                                                 struct rpc_pipe_client *pipe_hnd,
689                                                 TALLOC_CTX *mem_ctx,
690                                                 int argc,
691                                                 const char **argv )
692 {
693         uint32 hive;
694         struct policy_handle hive_hnd, key_hnd;
695         struct winreg_String key, keyclass;
696         enum winreg_CreateAction action;
697         NTSTATUS status;
698
699         ZERO_STRUCT(key);
700         ZERO_STRUCT(keyclass);
701
702         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
703                 return NT_STATUS_INVALID_PARAMETER;
704         }
705
706         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
707                                        SEC_FLAG_MAXIMUM_ALLOWED,
708                                        &hive_hnd);
709         if (!(NT_STATUS_IS_OK(status))) {
710                 return status;
711         }
712
713         action = REG_ACTION_NONE;
714         keyclass.name = "";
715
716         status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
717                                          keyclass, 0, REG_KEY_READ, NULL,
718                                          &key_hnd, &action, NULL);
719         if (!NT_STATUS_IS_OK(status)) {
720                 d_fprintf(stderr, _("createkey returned %s\n"),
721                           nt_errstr(status));
722                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
723                 return status;
724         }
725
726         switch (action) {
727                 case REG_ACTION_NONE:
728                         d_printf(_("createkey did nothing -- huh?\n"));
729                         break;
730                 case REG_CREATED_NEW_KEY:
731                         d_printf(_("createkey created %s\n"), argv[0]);
732                         break;
733                 case REG_OPENED_EXISTING_KEY:
734                         d_printf(_("createkey opened existing %s\n"), argv[0]);
735                         break;
736         }
737
738         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
739         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
740
741         return status;
742 }
743
744 static int rpc_registry_createkey(struct net_context *c, int argc,
745                                   const char **argv )
746 {
747         if (argc != 1 || c->display_usage) {
748                 d_fprintf(stderr, "%s\n%s",
749                           _("Usage:"),
750                           _("net rpc registry createkey <key>\n"));
751                 return -1;
752         }
753
754         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
755                 rpc_registry_createkey_internal, argc, argv );
756 }
757
758 static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
759                                                 const struct dom_sid *domain_sid,
760                                                 const char *domain_name,
761                                                 struct cli_state *cli,
762                                                 struct rpc_pipe_client *pipe_hnd,
763                                                 TALLOC_CTX *mem_ctx,
764                                                 int argc,
765                                                 const char **argv )
766 {
767         uint32 hive;
768         struct policy_handle hive_hnd;
769         struct winreg_String key;
770         NTSTATUS status;
771
772         ZERO_STRUCT(key);
773
774         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
775                 return NT_STATUS_INVALID_PARAMETER;
776         }
777
778         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
779                                        SEC_FLAG_MAXIMUM_ALLOWED,
780                                        &hive_hnd);
781         if (!(NT_STATUS_IS_OK(status))) {
782                 return status;
783         }
784
785         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key, NULL);
786         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
787
788         if (!NT_STATUS_IS_OK(status)) {
789                 d_fprintf(stderr, _("deletekey returned %s\n"),
790                           nt_errstr(status));
791         }
792
793         return status;
794 }
795
796 static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
797 {
798         if (argc != 1 || c->display_usage) {
799                 d_fprintf(stderr, "%s\n%s",
800                           _("Usage:"),
801                           _("net rpc registry deletekey <key>\n"));
802                 return -1;
803         }
804
805         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
806                 rpc_registry_deletekey_internal, argc, argv );
807 }
808
809 /********************************************************************
810 ********************************************************************/
811
812 static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
813                                                 const struct dom_sid *domain_sid,
814                                                 const char *domain_name,
815                                                 struct cli_state *cli,
816                                                 struct rpc_pipe_client *pipe_hnd,
817                                                 TALLOC_CTX *mem_ctx,
818                                                 int argc,
819                                                 const char **argv )
820 {
821         struct policy_handle pol_hive, pol_key;
822         NTSTATUS status;
823         uint32 num_subkeys = 0;
824         uint32 num_values = 0;
825         char **names = NULL, **classes = NULL;
826         NTTIME **modtimes = NULL;
827         uint32 i;
828         struct registry_value **values = NULL;
829
830         if (argc != 1 || c->display_usage) {
831                 d_printf("%s\n%s",
832                          _("Usage:"),
833                          _("net rpc registry enumerate <path>\n"));
834                 d_printf("%s  net rpc registry enumerate "
835                          "'HKLM\\Software\\Samba'\n", _("Example:"));
836                 return NT_STATUS_INVALID_PARAMETER;
837         }
838
839         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
840                                   &pol_hive, &pol_key);
841         if (!NT_STATUS_IS_OK(status)) {
842                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
843                           nt_errstr(status));
844                 return status;
845         }
846
847         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
848                                    &names, &classes, &modtimes);
849         if (!NT_STATUS_IS_OK(status)) {
850                 d_fprintf(stderr, _("enumerating keys failed: %s\n"),
851                           nt_errstr(status));
852                 return status;
853         }
854
855         for (i=0; i<num_subkeys; i++) {
856                 print_registry_key(names[i], modtimes[i]);
857         }
858
859         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
860                                      &names, &values);
861         if (!NT_STATUS_IS_OK(status)) {
862                 d_fprintf(stderr, _("enumerating values failed: %s\n"),
863                           nt_errstr(status));
864                 return status;
865         }
866
867         for (i=0; i<num_values; i++) {
868                 print_registry_value_with_name(names[i], values[i]);
869         }
870
871         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
872         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
873
874         return status;
875 }
876
877 /********************************************************************
878 ********************************************************************/
879
880 static int rpc_registry_enumerate(struct net_context *c, int argc,
881                                   const char **argv )
882 {
883         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
884                 rpc_registry_enumerate_internal, argc, argv );
885 }
886
887 /********************************************************************
888 ********************************************************************/
889
890 static NTSTATUS rpc_registry_save_internal(struct net_context *c,
891                                         const struct dom_sid *domain_sid,
892                                         const char *domain_name,
893                                         struct cli_state *cli,
894                                         struct rpc_pipe_client *pipe_hnd,
895                                         TALLOC_CTX *mem_ctx,
896                                         int argc,
897                                         const char **argv )
898 {
899         WERROR result = WERR_GENERAL_FAILURE;
900         struct policy_handle pol_hive, pol_key;
901         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
902         struct winreg_String filename;
903
904         if (argc != 2 || c->display_usage) {
905                 d_printf("%s\n%s",
906                          _("Usage:"),
907                          _("net rpc registry backup <path> <file> \n"));
908                 return NT_STATUS_INVALID_PARAMETER;
909         }
910
911         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
912                                   &pol_hive, &pol_key);
913         if (!NT_STATUS_IS_OK(status)) {
914                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
915                           nt_errstr(status));
916                 return status;
917         }
918
919         filename.name = argv[1];
920         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL, NULL);
921         if ( !W_ERROR_IS_OK(result) ) {
922                 d_fprintf(stderr, _("Unable to save [%s] to %s:%s\n"), argv[0],
923                           cli->desthost, argv[1]);
924         }
925
926         /* cleanup */
927
928         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
929         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
930
931         return status;
932 }
933
934 /********************************************************************
935 ********************************************************************/
936
937 static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
938 {
939         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
940                 rpc_registry_save_internal, argc, argv );
941 }
942
943
944 /********************************************************************
945 ********************************************************************/
946
947 static void dump_values( REGF_NK_REC *nk )
948 {
949         int i, j;
950         const char *data_str = NULL;
951         uint32 data_size, data;
952         DATA_BLOB blob;
953
954         if ( !nk->values )
955                 return;
956
957         for ( i=0; i<nk->num_values; i++ ) {
958                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
959                 d_printf( "(%s) ", str_regtype( nk->values[i].type ) );
960
961                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
962                 switch ( nk->values[i].type ) {
963                         case REG_SZ:
964                                 blob = data_blob_const(nk->values[i].data, data_size);
965                                 pull_reg_sz(talloc_tos(), &blob, &data_str);
966                                 if (!data_str) {
967                                         break;
968                                 }
969                                 d_printf( "%s", data_str );
970                                 break;
971                         case REG_MULTI_SZ:
972                         case REG_EXPAND_SZ:
973                                 for ( j=0; j<data_size; j++ ) {
974                                         d_printf( "%c", nk->values[i].data[j] );
975                                 }
976                                 break;
977                         case REG_DWORD:
978                                 data = IVAL( nk->values[i].data, 0 );
979                                 d_printf("0x%x", data );
980                                 break;
981                         case REG_BINARY:
982                                 for ( j=0; j<data_size; j++ ) {
983                                         d_printf( "%x", nk->values[i].data[j] );
984                                 }
985                                 break;
986                         default:
987                                 d_printf(_("unknown"));
988                                 break;
989                 }
990
991                 d_printf( "\n" );
992         }
993
994 }
995
996 /********************************************************************
997 ********************************************************************/
998
999 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
1000 {
1001         REGF_NK_REC *key;
1002
1003         /* depth first dump of the registry tree */
1004
1005         while ( (key = regfio_fetch_subkey( file, nk )) ) {
1006                 char *regpath;
1007                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
1008                         break;
1009                 }
1010                 d_printf("[%s]\n", regpath );
1011                 dump_values( key );
1012                 d_printf("\n");
1013                 dump_registry_tree( file, key, regpath );
1014                 SAFE_FREE(regpath);
1015         }
1016
1017         return true;
1018 }
1019
1020 /********************************************************************
1021 ********************************************************************/
1022
1023 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
1024                                  REGF_NK_REC *parent, REGF_FILE *outfile,
1025                                  const char *parentpath )
1026 {
1027         REGF_NK_REC *key, *subkey;
1028         struct regval_ctr *values = NULL;
1029         struct regsubkey_ctr *subkeys = NULL;
1030         int i;
1031         char *path = NULL;
1032         WERROR werr;
1033
1034         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
1035         if (!W_ERROR_IS_OK(werr)) {
1036                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
1037                           "%s\n", win_errstr(werr)));
1038                 return false;
1039         }
1040
1041         werr = regval_ctr_init(subkeys, &values);
1042         if (!W_ERROR_IS_OK(werr)) {
1043                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
1044                 TALLOC_FREE(subkeys);
1045                 return false;
1046         }
1047
1048         /* copy values into the struct regval_ctr */
1049
1050         for ( i=0; i<nk->num_values; i++ ) {
1051                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
1052                         nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
1053         }
1054
1055         /* copy subkeys into the struct regsubkey_ctr */
1056
1057         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1058                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1059         }
1060
1061         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1062
1063         /* write each one of the subkeys out */
1064
1065         path = talloc_asprintf(subkeys,
1066                         "%s%s%s",
1067                         parentpath,
1068                         parent ? "\\" : "",
1069                         nk->keyname);
1070         if (!path) {
1071                 TALLOC_FREE(subkeys);
1072                 return false;
1073         }
1074
1075         nk->subkey_index = 0;
1076         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1077                 write_registry_tree( infile, subkey, key, outfile, path );
1078         }
1079
1080         d_printf("[%s]\n", path );
1081         TALLOC_FREE(subkeys);
1082
1083         return true;
1084 }
1085
1086 /********************************************************************
1087 ********************************************************************/
1088
1089 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1090 {
1091         REGF_FILE   *registry;
1092         REGF_NK_REC *nk;
1093
1094         if (argc != 1 || c->display_usage) {
1095                 d_printf("%s\n%s",
1096                          _("Usage:"),
1097                          _("net rpc registry dump <file> \n"));
1098                 return -1;
1099         }
1100
1101         d_printf(_("Opening %s...."), argv[0]);
1102         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1103                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1104                 return 1;
1105         }
1106         d_printf(_("ok\n"));
1107
1108         /* get the root of the registry file */
1109
1110         if ((nk = regfio_rootkey( registry )) == NULL) {
1111                 d_fprintf(stderr, _("Could not get rootkey\n"));
1112                 regfio_close( registry );
1113                 return 1;
1114         }
1115         d_printf("[%s]\n", nk->keyname);
1116         dump_values( nk );
1117         d_printf("\n");
1118
1119         dump_registry_tree( registry, nk, nk->keyname );
1120
1121 #if 0
1122         talloc_report_full( registry->mem_ctx, stderr );
1123 #endif
1124         d_printf(_("Closing registry..."));
1125         regfio_close( registry );
1126         d_printf(_("ok\n"));
1127
1128         return 0;
1129 }
1130
1131 /********************************************************************
1132 ********************************************************************/
1133
1134 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1135 {
1136         REGF_FILE   *infile = NULL, *outfile = NULL;
1137         REGF_NK_REC *nk;
1138         int result = 1;
1139
1140         if (argc != 2 || c->display_usage) {
1141                 d_printf("%s\n%s",
1142                          _("Usage:"),
1143                          _("net rpc registry copy <srcfile> <newfile>\n"));
1144                 return -1;
1145         }
1146
1147         d_printf(_("Opening %s...."), argv[0]);
1148         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1149                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1150                 return 1;
1151         }
1152         d_printf(_("ok\n"));
1153
1154         d_printf(_("Opening %s...."), argv[1]);
1155         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1156                 d_fprintf(stderr, _("Failed to open %s for writing\n"),argv[1]);
1157                 goto out;
1158         }
1159         d_printf(_("ok\n"));
1160
1161         /* get the root of the registry file */
1162
1163         if ((nk = regfio_rootkey( infile )) == NULL) {
1164                 d_fprintf(stderr, _("Could not get rootkey\n"));
1165                 goto out;
1166         }
1167         d_printf(_("RootKey: [%s]\n"), nk->keyname);
1168
1169         write_registry_tree( infile, nk, NULL, outfile, "" );
1170
1171         result = 0;
1172
1173 out:
1174
1175         d_printf(_("Closing %s..."), argv[1]);
1176         if (outfile) {
1177                 regfio_close( outfile );
1178         }
1179         d_printf(_("ok\n"));
1180
1181         d_printf(_("Closing %s..."), argv[0]);
1182         if (infile) {
1183                 regfio_close( infile );
1184         }
1185         d_printf(_("ok\n"));
1186
1187         return( result);
1188 }
1189
1190 /********************************************************************
1191 ********************************************************************/
1192
1193 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1194                                             const struct dom_sid *domain_sid,
1195                                             const char *domain_name,
1196                                             struct cli_state *cli,
1197                                             struct rpc_pipe_client *pipe_hnd,
1198                                             TALLOC_CTX *mem_ctx,
1199                                             int argc,
1200                                             const char **argv)
1201 {
1202         struct policy_handle pol_hive, pol_key;
1203         NTSTATUS status;
1204         enum ndr_err_code ndr_err;
1205         struct KeySecurityData *sd = NULL;
1206         uint32_t sec_info;
1207         DATA_BLOB blob;
1208         struct security_descriptor sec_desc;
1209         uint32_t access_mask = REG_KEY_READ |
1210                                SEC_FLAG_MAXIMUM_ALLOWED |
1211                                SEC_FLAG_SYSTEM_SECURITY;
1212
1213         if (argc <1 || argc > 2 || c->display_usage) {
1214                 d_printf("%s\n%s",
1215                          _("Usage:"),
1216                          _("net rpc registry getsd <path> <secinfo>\n"));
1217                 d_printf("%s  net rpc registry getsd "
1218                            "'HKLM\\Software\\Samba'\n", _("Example:"));
1219                 return NT_STATUS_INVALID_PARAMETER;
1220         }
1221
1222         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1223                                   access_mask,
1224                                   &pol_hive, &pol_key);
1225         if (!NT_STATUS_IS_OK(status)) {
1226                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
1227                           nt_errstr(status));
1228                 return status;
1229         }
1230
1231         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1232         if (!sd) {
1233                 status = NT_STATUS_NO_MEMORY;
1234                 goto out;
1235         }
1236
1237         sd->size = 0x1000;
1238
1239         if (argc >= 2) {
1240                 sscanf(argv[1], "%x", &sec_info);
1241         } else {
1242                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1243         }
1244
1245         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1246         if (!NT_STATUS_IS_OK(status)) {
1247                 d_fprintf(stderr, _("getting sd failed: %s\n"),
1248                           nt_errstr(status));
1249                 goto out;
1250         }
1251
1252         blob.data = sd->data;
1253         blob.length = sd->size;
1254
1255         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
1256                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1257         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1258                 status = ndr_map_error2ntstatus(ndr_err);
1259                 goto out;
1260         }
1261         status = NT_STATUS_OK;
1262
1263         display_sec_desc(&sec_desc);
1264
1265  out:
1266         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1267         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1268
1269         return status;
1270 }
1271
1272
1273 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1274 {
1275         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
1276                 rpc_registry_getsd_internal, argc, argv);
1277 }
1278
1279 /********************************************************************
1280 ********************************************************************/
1281
1282 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1283 {
1284         struct functable func[] = {
1285                 {
1286                         "enumerate",
1287                         rpc_registry_enumerate,
1288                         NET_TRANSPORT_RPC,
1289                         N_("Enumerate registry keys and values"),
1290                         N_("net rpc registry enumerate\n"
1291                            "    Enumerate registry keys and values")
1292                 },
1293                 {
1294                         "createkey",
1295                         rpc_registry_createkey,
1296                         NET_TRANSPORT_RPC,
1297                         N_("Create a new registry key"),
1298                         N_("net rpc registry createkey\n"
1299                            "    Create a new registry key")
1300                 },
1301                 {
1302                         "deletekey",
1303                         rpc_registry_deletekey,
1304                         NET_TRANSPORT_RPC,
1305                         N_("Delete a registry key"),
1306                         N_("net rpc registry deletekey\n"
1307                            "    Delete a registry key")
1308                 },
1309                 {
1310                         "getvalue",
1311                         rpc_registry_getvalue,
1312                         NET_TRANSPORT_RPC,
1313                         N_("Print a registry value"),
1314                         N_("net rpc registry getvalue\n"
1315                            "    Print a registry value")
1316                 },
1317                 {
1318                         "getvalueraw",
1319                         rpc_registry_getvalueraw,
1320                         NET_TRANSPORT_RPC,
1321                         N_("Print a registry value"),
1322                         N_("net rpc registry getvalueraw\n"
1323                            "    Print a registry value (raw version)")
1324                 },
1325                 {
1326                         "setvalue",
1327                         rpc_registry_setvalue,
1328                         NET_TRANSPORT_RPC,
1329                         N_("Set a new registry value"),
1330                         N_("net rpc registry setvalue\n"
1331                            "    Set a new registry value")
1332                 },
1333                 {
1334                         "deletevalue",
1335                         rpc_registry_deletevalue,
1336                         NET_TRANSPORT_RPC,
1337                         N_("Delete a registry value"),
1338                         N_("net rpc registry deletevalue\n"
1339                            "    Delete a registry value")
1340                 },
1341                 {
1342                         "save",
1343                         rpc_registry_save,
1344                         NET_TRANSPORT_RPC,
1345                         N_("Save a registry file"),
1346                         N_("net rpc registry save\n"
1347                            "    Save a registry file")
1348                 },
1349                 {
1350                         "dump",
1351                         rpc_registry_dump,
1352                         NET_TRANSPORT_RPC,
1353                         N_("Dump a registry file"),
1354                         N_("net rpc registry dump\n"
1355                            "    Dump a registry file")
1356                 },
1357                 {
1358                         "copy",
1359                         rpc_registry_copy,
1360                         NET_TRANSPORT_RPC,
1361                         N_("Copy a registry file"),
1362                         N_("net rpc registry copy\n"
1363                            "    Copy a registry file")
1364                 },
1365                 {
1366                         "getsd",
1367                         rpc_registry_getsd,
1368                         NET_TRANSPORT_RPC,
1369                         N_("Get security descriptor"),
1370                         N_("net rpc registry getsd\n"
1371                            "    Get security descriptior")
1372                 },
1373                 {NULL, NULL, 0, NULL, NULL}
1374         };
1375
1376         return net_run_function(c, argc, argv, "net rpc registry", func);
1377 }