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