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