r20001: Fix bug 4273, thanks to Pascal Terjan
[tprouty/samba.git] / source / 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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20  
21 #include "includes.h"
22 #include "utils/net.h"
23 #include "regfio.h"
24 #include "reg_objects.h"
25
26 static BOOL reg_hive_key(const char *fullname, uint32 *reg_type,
27                          const char **key_name)
28 {
29         const char *sep;
30         ptrdiff_t len;
31
32         sep = strchr_m(fullname, '\\');
33
34         if (sep != NULL) {
35                 len = sep - fullname;
36                 *key_name = sep+1;
37         }
38         else {
39                 len = strlen(fullname);
40                 *key_name = "";
41         }
42
43         if (strnequal(fullname, "HKLM", len) ||
44             strnequal(fullname, "HKEY_LOCAL_MACHINE", len))
45                 (*reg_type) = HKEY_LOCAL_MACHINE;
46         else if (strnequal(fullname, "HKCR", len) ||
47                  strnequal(fullname, "HKEY_CLASSES_ROOT", len))
48                 (*reg_type) = HKEY_CLASSES_ROOT;
49         else if (strnequal(fullname, "HKU", len) ||
50                  strnequal(fullname, "HKEY_USERS", len))
51                 (*reg_type) = HKEY_USERS;
52         else if (strnequal(fullname, "HKPD", len) ||
53                  strnequal(fullname, "HKEY_PERFORMANCE_DATA", len))
54                 (*reg_type) = HKEY_PERFORMANCE_DATA;
55         else {
56                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
57                           fullname));
58                 return False;
59         }
60
61         return True;
62 }
63
64 static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
65                                  struct rpc_pipe_client *pipe_hnd,
66                                  const char *name, uint32 access_mask,
67                                  struct policy_handle *hive_hnd,
68                                  struct policy_handle *key_hnd)
69 {
70         uint32 hive;
71         NTSTATUS status;
72         struct winreg_String key;
73
74         if (!reg_hive_key(name, &hive, &key.name)) {
75                 return NT_STATUS_INVALID_PARAMETER;
76         }
77
78         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
79                                        hive_hnd);
80         if (!(NT_STATUS_IS_OK(status))) {
81                 return status;
82         }
83
84         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
85                                        access_mask, key_hnd);
86         if (!(NT_STATUS_IS_OK(status))) {
87                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd);
88                 return status;
89         }
90
91         return NT_STATUS_OK;
92 }
93
94 static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
95                                   struct rpc_pipe_client *pipe_hnd,
96                                   struct policy_handle *key_hnd,
97                                   uint32 *pnum_keys, char ***pnames,
98                                   char ***pclasses, NTTIME ***pmodtimes)
99 {
100         TALLOC_CTX *mem_ctx;
101         NTSTATUS status;
102         uint32 num_subkeys, max_subkeylen, max_classlen;
103         uint32 num_values, max_valnamelen, max_valbufsize;
104         uint32 i;
105         NTTIME last_changed_time;
106         uint32 secdescsize;
107         struct winreg_String classname;
108         char **names, **classes;
109         NTTIME **modtimes;
110
111         if (!(mem_ctx = talloc_new(ctx))) {
112                 return NT_STATUS_NO_MEMORY;
113         }
114
115         ZERO_STRUCT(classname);
116         status = rpccli_winreg_QueryInfoKey(
117                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
118                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
119                 &max_valbufsize, &secdescsize, &last_changed_time );
120
121         if (!NT_STATUS_IS_OK(status)) {
122                 goto error;
123         }
124
125         if (num_subkeys == 0) {
126                 *pnum_keys = 0;
127                 TALLOC_FREE(mem_ctx);
128                 return NT_STATUS_OK;
129         }
130
131         if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
132             (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
133             (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
134                                             num_subkeys)))) {
135                 status = NT_STATUS_NO_MEMORY;
136                 goto error;
137         }
138
139         for (i=0; i<num_subkeys; i++) {
140                 char c, n;
141                 struct winreg_StringBuf class_buf;
142                 struct winreg_StringBuf *pclass_buf = &class_buf;
143                 struct winreg_StringBuf name_buf;
144                 NTTIME modtime;
145                 NTTIME *pmodtime = &modtime;
146
147                 c = '\0';
148                 class_buf.name = &c;
149                 class_buf.size = max_classlen+2;
150
151                 n = '\0';
152                 name_buf.name = &n;
153                 name_buf.size = max_subkeylen+2;
154
155                 ZERO_STRUCT(modtime);
156
157                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
158                                                i, &name_buf, &pclass_buf,
159                                                &pmodtime);
160                 
161                 if (W_ERROR_EQUAL(ntstatus_to_werror(status),
162                                   WERR_NO_MORE_ITEMS) ) {
163                         status = NT_STATUS_OK;
164                         break;
165                 }
166                 if (!NT_STATUS_IS_OK(status)) {
167                         goto error;
168                 }
169
170                 classes[i] = NULL;
171
172                 if (pclass_buf && pclass_buf->name &&
173                     (!(classes[i] = talloc_strdup(classes,
174                                                   pclass_buf->name)))) {
175                         status = NT_STATUS_NO_MEMORY;
176                         goto error;
177                 }
178
179                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
180                         status = NT_STATUS_NO_MEMORY;
181                         goto error;
182                 }
183
184                 if ((pmodtime) &&
185                     (!(modtimes[i] = (NTTIME *)talloc_memdup(
186                                modtimes, pmodtime, sizeof(*pmodtime))))) {
187                         status = NT_STATUS_NO_MEMORY;
188                         goto error;
189                 }
190         }
191
192         *pnum_keys = num_subkeys;
193
194         if (pnames) {
195                 *pnames = talloc_move(ctx, &names);
196         }
197         if (pclasses) {
198                 *pclasses = talloc_move(ctx, &classes);
199         }
200         if (pmodtimes) {
201                 *pmodtimes = talloc_move(ctx, &modtimes);
202         }
203
204         status = NT_STATUS_OK;
205
206  error:
207         TALLOC_FREE(mem_ctx);
208         return status;
209 }
210
211 static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
212                                     struct rpc_pipe_client *pipe_hnd,
213                                     struct policy_handle *key_hnd,
214                                     uint32 *pnum_values, char ***pvalnames,
215                                     struct registry_value ***pvalues)
216 {
217         TALLOC_CTX *mem_ctx;
218         NTSTATUS status;
219         uint32 num_subkeys, max_subkeylen, max_classlen;
220         uint32 num_values, max_valnamelen, max_valbufsize;
221         uint32 i;
222         NTTIME last_changed_time;
223         uint32 secdescsize;
224         struct winreg_String classname;
225         struct registry_value **values;
226         char **names;
227
228         if (!(mem_ctx = talloc_new(ctx))) {
229                 return NT_STATUS_NO_MEMORY;
230         }
231
232         ZERO_STRUCT(classname);
233         status = rpccli_winreg_QueryInfoKey(
234                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
235                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
236                 &max_valbufsize, &secdescsize, &last_changed_time );
237
238         if (!NT_STATUS_IS_OK(status)) {
239                 goto error;
240         }
241
242         if (num_values == 0) {
243                 *pnum_values = 0;
244                 TALLOC_FREE(mem_ctx);
245                 return NT_STATUS_OK;
246         }
247
248         if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
249             (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
250                                      num_values)))) {
251                 status = NT_STATUS_NO_MEMORY;
252                 goto error;
253         }
254
255         for (i=0; i<num_values; i++) {
256                 enum winreg_Type type = REG_NONE;
257                 enum winreg_Type *ptype = &type;
258                 uint8 d = 0;
259                 uint8 *data = &d;
260
261                 uint32 data_size;
262                 uint32 *pdata_size = &data_size;
263
264                 uint32 value_length;
265                 uint32 *pvalue_length = &value_length;
266
267                 char n;
268                 struct winreg_ValNameBuf name_buf;
269                 WERROR err;
270
271                 n = '\0';
272                 name_buf.name = &n;
273                 name_buf.size = max_valnamelen + 2;
274
275                 data_size = max_valbufsize;
276                 value_length = 0;
277
278                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
279                                                  i, &name_buf, &ptype,
280                                                  &data, &pdata_size,
281                                                  &pvalue_length );
282
283                 if ( W_ERROR_EQUAL(ntstatus_to_werror(status),
284                                    WERR_NO_MORE_ITEMS) ) {
285                         status = NT_STATUS_OK;
286                         break;
287                 }
288
289                 if (!(NT_STATUS_IS_OK(status))) {
290                         goto error;
291                 }
292
293                 if ((name_buf.name == NULL) || (ptype == NULL) ||
294                     (data == NULL) || (pdata_size == 0) ||
295                     (pvalue_length == NULL)) {
296                         status = NT_STATUS_INVALID_PARAMETER;
297                         goto error;
298                 }
299
300                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
301                         status = NT_STATUS_NO_MEMORY;
302                         goto error;
303                 }
304
305                 err = registry_pull_value(values, &values[i], *ptype, data,
306                                           *pdata_size, *pvalue_length);
307                 if (!W_ERROR_IS_OK(err)) {
308                         status = werror_to_ntstatus(err);
309                         goto error;
310                 }
311         }
312
313         *pnum_values = num_values;
314
315         if (pvalnames) {
316                 *pvalnames = talloc_move(ctx, &names);
317         }
318         if (pvalues) {
319                 *pvalues = talloc_move(ctx, &values);
320         }
321
322         status = NT_STATUS_OK;
323
324  error:
325         TALLOC_FREE(mem_ctx);
326         return status;
327 }
328
329 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
330                                   struct rpc_pipe_client *pipe_hnd,
331                                   struct policy_handle *key_hnd,
332                                   const char *name,
333                                   const struct registry_value *value)
334 {
335         struct winreg_String name_string;
336         DATA_BLOB blob;
337         NTSTATUS result;
338         WERROR err;
339
340         err = registry_push_value(mem_ctx, value, &blob);
341         if (!W_ERROR_IS_OK(err)) {
342                 return werror_to_ntstatus(err);
343         }
344
345         name_string.name = name;
346         result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
347                                         name_string, value->type,
348                                         blob.data, blob.length);
349         TALLOC_FREE(blob.data);
350         return result;
351 }
352
353 static NTSTATUS rpc_registry_setvalue_internal(const DOM_SID *domain_sid,
354                                                const char *domain_name, 
355                                                struct cli_state *cli,
356                                                struct rpc_pipe_client *pipe_hnd,
357                                                TALLOC_CTX *mem_ctx, 
358                                                int argc,
359                                                const char **argv )
360 {
361         struct policy_handle hive_hnd, key_hnd;
362         NTSTATUS status;
363         struct registry_value value;
364
365         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
366                                   &hive_hnd, &key_hnd);
367         if (!NT_STATUS_IS_OK(status)) {
368                 d_fprintf(stderr, "registry_openkey failed: %s\n",
369                           nt_errstr(status));
370                 return status;
371         }
372
373         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
374                 d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
375                 return NT_STATUS_NOT_IMPLEMENTED;
376         }
377
378         if (strequal(argv[2], "dword")) {
379                 value.type = REG_DWORD;
380                 value.v.dword = strtoul(argv[3], NULL, 10);
381         }
382         else if (strequal(argv[2], "sz")) {
383                 value.type = REG_SZ;
384                 value.v.sz.len = strlen(argv[3])+1;
385                 value.v.sz.str = CONST_DISCARD(char *, argv[3]);
386         }
387         else {
388                 d_fprintf(stderr, "type \"%s\" not implemented\n", argv[3]);
389                 status = NT_STATUS_NOT_IMPLEMENTED;
390                 goto error;
391         }
392
393         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
394                                    argv[1], &value);
395
396         if (!NT_STATUS_IS_OK(status)) {
397                 d_fprintf(stderr, "registry_setvalue failed: %s\n",
398                           nt_errstr(status));
399         }
400
401  error:
402         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
403         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
404
405         return NT_STATUS_OK;
406 }
407
408 static int rpc_registry_setvalue( int argc, const char **argv )
409 {
410         if (argc < 4) {
411                 d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
412                           "<valuename> <type> [<val>]+\n");
413                 return -1;
414         }
415
416         return run_rpc_command( NULL, PI_WINREG, 0, 
417                 rpc_registry_setvalue_internal, argc, argv );
418 }
419
420 static NTSTATUS rpc_registry_deletevalue_internal(const DOM_SID *domain_sid,
421                                                   const char *domain_name, 
422                                                   struct cli_state *cli,
423                                                   struct rpc_pipe_client *pipe_hnd,
424                                                   TALLOC_CTX *mem_ctx, 
425                                                   int argc,
426                                                   const char **argv )
427 {
428         struct policy_handle hive_hnd, key_hnd;
429         NTSTATUS status;
430         struct winreg_String valuename;
431
432         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_WRITE,
433                                   &hive_hnd, &key_hnd);
434         if (!NT_STATUS_IS_OK(status)) {
435                 d_fprintf(stderr, "registry_openkey failed: %s\n",
436                           nt_errstr(status));
437                 return status;
438         }
439
440         valuename.name = argv[1];
441
442         status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
443                                            valuename);
444
445         if (!NT_STATUS_IS_OK(status)) {
446                 d_fprintf(stderr, "registry_deletevalue failed: %s\n",
447                           nt_errstr(status));
448         }
449
450         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
451         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
452
453         return NT_STATUS_OK;
454 }
455
456 static int rpc_registry_deletevalue( int argc, const char **argv )
457 {
458         if (argc != 2) {
459                 d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
460                           "<valuename>\n");
461                 return -1;
462         }
463
464         return run_rpc_command( NULL, PI_WINREG, 0, 
465                 rpc_registry_deletevalue_internal, argc, argv );
466 }
467
468 static NTSTATUS rpc_registry_createkey_internal(const DOM_SID *domain_sid,
469                                                 const char *domain_name, 
470                                                 struct cli_state *cli,
471                                                 struct rpc_pipe_client *pipe_hnd,
472                                                 TALLOC_CTX *mem_ctx, 
473                                                 int argc,
474                                                 const char **argv )
475 {
476         uint32 hive;
477         struct policy_handle hive_hnd, key_hnd;
478         struct winreg_String key, keyclass;
479         enum winreg_CreateAction action;
480         enum winreg_CreateAction *paction = &action;
481         NTSTATUS status;
482
483         if (!reg_hive_key(argv[0], &hive, &key.name)) {
484                 return NT_STATUS_INVALID_PARAMETER;
485         }
486
487         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
488                                        REG_KEY_READ|REG_KEY_WRITE,
489                                        &hive_hnd);
490         if (!(NT_STATUS_IS_OK(status))) {
491                 return status;
492         }
493
494         action = REG_ACTION_NONE;
495         keyclass.name = "";
496
497         status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
498                                          keyclass, 0, REG_KEY_READ, NULL,
499                                          &key_hnd, &paction);
500         if (!NT_STATUS_IS_OK(status)) {
501                 d_fprintf(stderr, "createkey returned %s\n",
502                           nt_errstr(status));
503                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
504                 return status;
505         }
506
507         if (paction) {
508                 switch (*paction) {
509                 case REG_ACTION_NONE:
510                         d_printf("createkey did nothing -- huh?\n");
511                         break;
512                 case REG_CREATED_NEW_KEY:
513                         d_printf("createkey created %s\n", argv[0]);
514                         break;
515                 case REG_OPENED_EXISTING_KEY:
516                         d_printf("createkey opened existing %s\n", argv[0]);
517                         break;
518                 }
519         }
520
521         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd);
522         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
523
524         return status;
525 }
526
527 static int rpc_registry_createkey( int argc, const char **argv )
528 {
529         if (argc != 1) {
530                 d_fprintf(stderr, "usage: net rpc registry createkey <key>\n");
531                 return -1;
532         }
533
534         return run_rpc_command( NULL, PI_WINREG, 0, 
535                 rpc_registry_createkey_internal, argc, argv );
536 }
537
538 static NTSTATUS rpc_registry_deletekey_internal(const DOM_SID *domain_sid,
539                                                 const char *domain_name, 
540                                                 struct cli_state *cli,
541                                                 struct rpc_pipe_client *pipe_hnd,
542                                                 TALLOC_CTX *mem_ctx, 
543                                                 int argc,
544                                                 const char **argv )
545 {
546         uint32 hive;
547         struct policy_handle hive_hnd;
548         struct winreg_String key;
549         NTSTATUS status;
550
551         if (!reg_hive_key(argv[0], &hive, &key.name)) {
552                 return NT_STATUS_INVALID_PARAMETER;
553         }
554
555         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, REG_KEY_WRITE,
556                                        &hive_hnd);
557         if (!(NT_STATUS_IS_OK(status))) {
558                 return status;
559         }
560
561         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key);
562         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd);
563
564         if (!NT_STATUS_IS_OK(status)) {
565                 d_fprintf(stderr, "deletekey returned %s\n",
566                           nt_errstr(status));
567         }
568
569         return status;
570 }
571
572 static int rpc_registry_deletekey( int argc, const char **argv )
573 {
574         if (argc != 1) {
575                 d_fprintf(stderr, "usage: net rpc registry deletekey <key>\n");
576                 return -1;
577         }
578
579         return run_rpc_command( NULL, PI_WINREG, 0, 
580                 rpc_registry_deletekey_internal, argc, argv );
581 }
582
583 /********************************************************************
584 ********************************************************************/
585
586 static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
587                                                 const char *domain_name, 
588                                                 struct cli_state *cli,
589                                                 struct rpc_pipe_client *pipe_hnd,
590                                                 TALLOC_CTX *mem_ctx, 
591                                                 int argc,
592                                                 const char **argv )
593 {
594         POLICY_HND pol_hive, pol_key; 
595         NTSTATUS status;
596         uint32 num_subkeys = 0;
597         uint32 num_values = 0;
598         char **names = NULL, **classes = NULL;
599         NTTIME **modtimes = NULL;
600         uint32 i;
601         struct registry_value **values = NULL;
602         
603         if (argc != 1 ) {
604                 d_printf("Usage:    net rpc enumerate <path> [recurse]\n");
605                 d_printf("Example:  net rpc enumerate 'HKLM\\Software\\Samba'\n");
606                 return NT_STATUS_OK;
607         }
608
609         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
610                                   &pol_hive, &pol_key);
611         if (!NT_STATUS_IS_OK(status)) {
612                 d_fprintf(stderr, "registry_openkey failed: %s\n",
613                           nt_errstr(status));
614                 return status;
615         }
616
617         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
618                                    &names, &classes, &modtimes);
619         if (!NT_STATUS_IS_OK(status)) {
620                 d_fprintf(stderr, "enumerating keys failed: %s\n",
621                           nt_errstr(status));
622                 return status;
623         }
624
625         for (i=0; i<num_subkeys; i++) {
626                 d_printf("Keyname   = %s\n", names[i]);
627                 d_printf("Modtime   = %s\n", modtimes[i]
628                          ? http_timestring(nt_time_to_unix(*modtimes[i]))
629                          : "None");
630                 d_printf("\n" );
631         }
632
633         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
634                                      &names, &values);
635         if (!NT_STATUS_IS_OK(status)) {
636                 d_fprintf(stderr, "enumerating values failed: %s\n",
637                           nt_errstr(status));
638                 return status;
639         }
640
641         for (i=0; i<num_values; i++) {
642                 struct registry_value *v = values[i];
643                 d_printf("Valuename  = %s\n", names[i]);
644                 d_printf("Type       = %s\n",
645                          reg_type_lookup(v->type));
646                 switch(v->type) {
647                 case REG_DWORD:
648                         d_printf("Value      = %d\n", v->v.dword);
649                         break;
650                 case REG_SZ:
651                 case REG_EXPAND_SZ:
652                         d_printf("Value      = \"%s\"\n", v->v.sz.str);
653                         break;
654                 case REG_MULTI_SZ: {
655                         uint32 j;
656                         for (j = 0; j < v->v.multi_sz.num_strings; j++) {
657                                 d_printf("Value[%3.3d] = \"%s\"\n", j,
658                                          v->v.multi_sz.strings[j]);
659                         }
660                         break;
661                 }
662                 case REG_BINARY:
663                         d_printf("Value      = %d bytes\n",
664                                  v->v.binary.length);
665                         break;
666                 default:
667                         d_printf("Value      = <unprintable>\n");
668                         break;
669                 }
670                         
671                 d_printf("\n");
672         }
673
674         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
675         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
676
677         return status;
678 }
679
680 /********************************************************************
681 ********************************************************************/
682
683 static int rpc_registry_enumerate( int argc, const char **argv )
684 {
685         return run_rpc_command( NULL, PI_WINREG, 0, 
686                 rpc_registry_enumerate_internal, argc, argv );
687 }
688
689 /********************************************************************
690 ********************************************************************/
691
692 static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
693                                         const char *domain_name, 
694                                         struct cli_state *cli,
695                                         struct rpc_pipe_client *pipe_hnd,
696                                         TALLOC_CTX *mem_ctx, 
697                                         int argc,
698                                         const char **argv )
699 {
700         WERROR result = WERR_GENERAL_FAILURE;
701         POLICY_HND pol_hive, pol_key; 
702         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
703         struct winreg_String filename;
704         
705         if (argc != 2 ) {
706                 d_printf("Usage:    net rpc backup <path> <file> \n");
707                 return NT_STATUS_OK;
708         }
709         
710         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
711                                   &pol_hive, &pol_key);
712         if (!NT_STATUS_IS_OK(status)) {
713                 d_fprintf(stderr, "registry_openkey failed: %s\n",
714                           nt_errstr(status));
715                 return status;
716         }
717
718         filename.name = argv[1];
719         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL  );
720         if ( !W_ERROR_IS_OK(result) ) {
721                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
722         }
723         
724         /* cleanup */
725         
726         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key );
727         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive );
728
729         return status;
730 }
731
732 /********************************************************************
733 ********************************************************************/
734
735 static int rpc_registry_save( int argc, const char **argv )
736 {
737         return run_rpc_command( NULL, PI_WINREG, 0, 
738                 rpc_registry_save_internal, argc, argv );
739 }
740
741
742 /********************************************************************
743 ********************************************************************/
744
745 static void dump_values( REGF_NK_REC *nk )
746 {
747         int i, j;
748         pstring data_str;
749         uint32 data_size, data;
750
751         if ( !nk->values )
752                 return;
753
754         for ( i=0; i<nk->num_values; i++ ) {
755                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
756                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
757
758                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
759                 switch ( nk->values[i].type ) {
760                         case REG_SZ:
761                                 rpcstr_pull( data_str, nk->values[i].data, sizeof(data_str), -1, STR_TERMINATE );
762                                 d_printf( "%s", data_str );
763                                 break;
764                         case REG_MULTI_SZ:
765                         case REG_EXPAND_SZ:
766                                 for ( j=0; j<data_size; j++ ) {
767                                         d_printf( "%c", nk->values[i].data[j] );
768                                 }
769                                 break;
770                         case REG_DWORD:
771                                 data = IVAL( nk->values[i].data, 0 );
772                                 d_printf("0x%x", data );
773                                 break;
774                         case REG_BINARY:
775                                 for ( j=0; j<data_size; j++ ) {
776                                         d_printf( "%x", nk->values[i].data[j] );
777                                 }
778                                 break;
779                         default:
780                                 d_printf("unknown");
781                                 break;
782                 }
783
784                 d_printf( "\n" );
785         }
786
787 }
788
789 /********************************************************************
790 ********************************************************************/
791
792 static BOOL dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
793 {
794         REGF_NK_REC *key;
795         pstring regpath;
796
797         /* depth first dump of the registry tree */
798
799         while ( (key = regfio_fetch_subkey( file, nk )) ) {
800                 pstr_sprintf( regpath, "%s\\%s", parent, key->keyname );
801                 d_printf("[%s]\n", regpath );
802                 dump_values( key );
803                 d_printf("\n");
804                 dump_registry_tree( file, key, regpath );
805         }
806
807         return True;
808 }
809
810 /********************************************************************
811 ********************************************************************/
812
813 static BOOL write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk, 
814                                  REGF_NK_REC *parent, REGF_FILE *outfile,
815                                  const char *parentpath )
816 {
817         REGF_NK_REC *key, *subkey;
818         REGVAL_CTR *values;
819         REGSUBKEY_CTR *subkeys;
820         int i;
821         pstring path;
822
823         if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
824                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
825                 return False;
826         }
827
828         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) ) {
829                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
830                 return False;
831         }
832
833         /* copy values into the REGVAL_CTR */
834         
835         for ( i=0; i<nk->num_values; i++ ) {
836                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
837                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
838         }
839
840         /* copy subkeys into the REGSUBKEY_CTR */
841         
842         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
843                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
844         }
845         
846         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
847
848         /* write each one of the subkeys out */
849
850         pstr_sprintf( path, "%s%s%s", parentpath, parent ? "\\" : "", nk->keyname );
851         nk->subkey_index = 0;
852         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
853                 write_registry_tree( infile, subkey, key, outfile, path );
854         }
855
856         TALLOC_FREE( subkeys );
857
858         d_printf("[%s]\n", path );
859         
860         return True;
861 }
862
863 /********************************************************************
864 ********************************************************************/
865
866 static int rpc_registry_dump( int argc, const char **argv )
867 {
868         REGF_FILE   *registry;
869         REGF_NK_REC *nk;
870         
871         if (argc != 1 ) {
872                 d_printf("Usage:    net rpc dump <file> \n");
873                 return 0;
874         }
875         
876         d_printf("Opening %s....", argv[0]);
877         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
878                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
879                 return 1;
880         }
881         d_printf("ok\n");
882         
883         /* get the root of the registry file */
884         
885         if ((nk = regfio_rootkey( registry )) == NULL) {
886                 d_fprintf(stderr, "Could not get rootkey\n");
887                 regfio_close( registry );
888                 return 1;
889         }
890         d_printf("[%s]\n", nk->keyname);
891         dump_values( nk );
892         d_printf("\n");
893
894         dump_registry_tree( registry, nk, nk->keyname );
895
896 #if 0
897         talloc_report_full( registry->mem_ctx, stderr );
898 #endif  
899         d_printf("Closing registry...");
900         regfio_close( registry );
901         d_printf("ok\n");
902
903         return 0;
904 }
905
906 /********************************************************************
907 ********************************************************************/
908
909 static int rpc_registry_copy( int argc, const char **argv )
910 {
911         REGF_FILE   *infile = NULL, *outfile = NULL;
912         REGF_NK_REC *nk;
913         int result = 1;
914         
915         if (argc != 2 ) {
916                 d_printf("Usage:    net rpc copy <srcfile> <newfile>\n");
917                 return 0;
918         }
919         
920         d_printf("Opening %s....", argv[0]);
921         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
922                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
923                 return 1;
924         }
925         d_printf("ok\n");
926
927         d_printf("Opening %s....", argv[1]);
928         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
929                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
930                 goto out;
931         }
932         d_printf("ok\n");
933         
934         /* get the root of the registry file */
935         
936         if ((nk = regfio_rootkey( infile )) == NULL) {
937                 d_fprintf(stderr, "Could not get rootkey\n");
938                 goto out;
939         }
940         d_printf("RootKey: [%s]\n", nk->keyname);
941
942         write_registry_tree( infile, nk, NULL, outfile, "" );
943
944         result = 0;
945
946 out:
947
948         d_printf("Closing %s...", argv[1]);
949         if (outfile) {
950                 regfio_close( outfile );
951         }
952         d_printf("ok\n");
953
954         d_printf("Closing %s...", argv[0]);
955         if (infile) {
956                 regfio_close( infile );
957         }
958         d_printf("ok\n");
959
960         return( result);
961 }
962
963 /********************************************************************
964 ********************************************************************/
965
966 int net_rpc_registry(int argc, const char **argv) 
967 {
968         struct functable2 func[] = {
969                 { "enumerate", rpc_registry_enumerate,
970                   "Enumerate registry keys and values" },
971                 { "createkey",  rpc_registry_createkey,
972                   "Create a new registry key" },
973                 { "deletekey",  rpc_registry_deletekey,
974                   "Delete a registry key" },
975                 { "setvalue",  rpc_registry_setvalue,
976                   "Set a new registry value" },
977                 { "deletevalue",  rpc_registry_deletevalue,
978                   "Delete a registry value" },
979                 { "save", rpc_registry_save,
980                   "Save a registry file" },
981                 { "dump", rpc_registry_dump,
982                   "Dump a registry file" },
983                 { "copy", rpc_registry_copy,
984                   "Copy a registry file" },
985                 {NULL, NULL, NULL}
986         };
987         
988         return net_run_function2(argc, argv, "net rpc registry", func);
989 }