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