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