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