net: Use true/false instead of True/False.
[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 "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(struct net_context *c,
373                                                const DOM_SID *domain_sid,
374                                                const char *domain_name,
375                                                struct cli_state *cli,
376                                                struct rpc_pipe_client *pipe_hnd,
377                                                TALLOC_CTX *mem_ctx,
378                                                int argc,
379                                                const char **argv )
380 {
381         struct policy_handle hive_hnd, key_hnd;
382         NTSTATUS status;
383         struct registry_value value;
384
385         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
386                                   SEC_RIGHTS_MAXIMUM_ALLOWED,
387                                   &hive_hnd, &key_hnd);
388         if (!NT_STATUS_IS_OK(status)) {
389                 d_fprintf(stderr, "registry_openkey failed: %s\n",
390                           nt_errstr(status));
391                 return status;
392         }
393
394         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
395                 d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
396                 return NT_STATUS_NOT_IMPLEMENTED;
397         }
398
399         if (strequal(argv[2], "dword")) {
400                 value.type = REG_DWORD;
401                 value.v.dword = strtoul(argv[3], NULL, 10);
402         }
403         else if (strequal(argv[2], "sz")) {
404                 value.type = REG_SZ;
405                 value.v.sz.len = strlen(argv[3])+1;
406                 value.v.sz.str = CONST_DISCARD(char *, argv[3]);
407         }
408         else {
409                 d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
410                 status = NT_STATUS_NOT_IMPLEMENTED;
411                 goto error;
412         }
413
414         status = registry_setvalue(mem_ctx, pipe_hnd, &key_hnd,
415                                    argv[1], &value);
416
417         if (!NT_STATUS_IS_OK(status)) {
418                 d_fprintf(stderr, "registry_setvalue failed: %s\n",
419                           nt_errstr(status));
420         }
421
422  error:
423         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
424         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
425
426         return NT_STATUS_OK;
427 }
428
429 static int rpc_registry_setvalue(struct net_context *c, int argc,
430                                  const char **argv )
431 {
432         if (argc < 4) {
433                 d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
434                           "<valuename> <type> [<val>]+\n");
435                 return -1;
436         }
437
438         return run_rpc_command(c, NULL, PI_WINREG, 0,
439                 rpc_registry_setvalue_internal, argc, argv );
440 }
441
442 static NTSTATUS rpc_registry_deletevalue_internal(struct net_context *c,
443                                                   const DOM_SID *domain_sid,
444                                                   const char *domain_name,
445                                                   struct cli_state *cli,
446                                                   struct rpc_pipe_client *pipe_hnd,
447                                                   TALLOC_CTX *mem_ctx,
448                                                   int argc,
449                                                   const char **argv )
450 {
451         struct policy_handle hive_hnd, key_hnd;
452         NTSTATUS status;
453         struct winreg_String valuename;
454
455         ZERO_STRUCT(valuename);
456
457         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
458                                   SEC_RIGHTS_MAXIMUM_ALLOWED,
459                                   &hive_hnd, &key_hnd);
460         if (!NT_STATUS_IS_OK(status)) {
461                 d_fprintf(stderr, "registry_openkey failed: %s\n",
462                           nt_errstr(status));
463                 return status;
464         }
465
466         valuename.name = argv[1];
467
468         status = rpccli_winreg_DeleteValue(pipe_hnd, mem_ctx, &key_hnd,
469                                            valuename, NULL);
470
471         if (!NT_STATUS_IS_OK(status)) {
472                 d_fprintf(stderr, "registry_deletevalue failed: %s\n",
473                           nt_errstr(status));
474         }
475
476         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
477         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
478
479         return status;
480 }
481
482 static int rpc_registry_deletevalue(struct net_context *c, int argc,
483                                     const char **argv )
484 {
485         if (argc != 2) {
486                 d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
487                           "<valuename>\n");
488                 return -1;
489         }
490
491         return run_rpc_command(c, NULL, PI_WINREG, 0,
492                 rpc_registry_deletevalue_internal, argc, argv );
493 }
494
495 static NTSTATUS rpc_registry_getvalue_internal(struct net_context *c,
496                                                const DOM_SID *domain_sid,
497                                                const char *domain_name,
498                                                struct cli_state *cli,
499                                                struct rpc_pipe_client *pipe_hnd,
500                                                TALLOC_CTX *mem_ctx,
501                                                bool raw,
502                                                int argc,
503                                                const char **argv)
504 {
505         struct policy_handle hive_hnd, key_hnd;
506         NTSTATUS status;
507         WERROR werr;
508         struct winreg_String valuename;
509         struct registry_value *value = NULL;
510         enum winreg_Type type = REG_NONE;
511         uint8_t *data = NULL;
512         uint32_t data_size = 0;
513         uint32_t value_length = 0;
514         TALLOC_CTX *tmp_ctx = talloc_stackframe();
515
516         ZERO_STRUCT(valuename);
517
518         status = registry_openkey(tmp_ctx, pipe_hnd, argv[0],
519                                   SEC_RIGHTS_MAXIMUM_ALLOWED,
520                                   &hive_hnd, &key_hnd);
521         if (!NT_STATUS_IS_OK(status)) {
522                 d_fprintf(stderr, "registry_openkey failed: %s\n",
523                           nt_errstr(status));
524                 return status;
525         }
526
527         valuename.name = argv[1];
528
529         /*
530          * call QueryValue once with data == NULL to get the
531          * needed memory size to be allocated, then allocate
532          * data buffer and call again.
533          */
534         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
535                                           &valuename,
536                                           &type,
537                                           data,
538                                           &data_size,
539                                           &value_length,
540                                           NULL);
541
542         if (!NT_STATUS_IS_OK(status)) {
543                 d_fprintf(stderr, "registry_queryvalue failed: %s\n",
544                           nt_errstr(status));
545                 goto done;
546         }
547
548         data = (uint8 *)TALLOC(tmp_ctx, data_size);
549         value_length = 0;
550
551         status = rpccli_winreg_QueryValue(pipe_hnd, tmp_ctx, &key_hnd,
552                                           &valuename,
553                                           &type,
554                                           data,
555                                           &data_size,
556                                           &value_length,
557                                           NULL);
558
559         if (!NT_STATUS_IS_OK(status)) {
560                 d_fprintf(stderr, "registry_queryvalue failed: %s\n",
561                           nt_errstr(status));
562                 goto done;
563         }
564
565         werr = registry_pull_value(tmp_ctx, &value, type, data,
566                                    data_size, value_length);
567         if (!W_ERROR_IS_OK(werr)) {
568                 status = werror_to_ntstatus(werr);
569                 goto done;
570         }
571
572         print_registry_value(value, raw);
573
574 done:
575         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &key_hnd, NULL);
576         rpccli_winreg_CloseKey(pipe_hnd, tmp_ctx, &hive_hnd, NULL);
577
578         TALLOC_FREE(tmp_ctx);
579
580         return status;
581 }
582
583 static NTSTATUS rpc_registry_getvalue_full(struct net_context *c,
584                                            const DOM_SID *domain_sid,
585                                            const char *domain_name,
586                                            struct cli_state *cli,
587                                            struct rpc_pipe_client *pipe_hnd,
588                                            TALLOC_CTX *mem_ctx,
589                                            int argc,
590                                            const char **argv)
591 {
592         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
593                                               cli, pipe_hnd, mem_ctx, false,
594                                               argc, argv);
595 }
596
597 static int rpc_registry_getvalue(struct net_context *c, int argc,
598                                  const char **argv)
599 {
600         if (argc != 2) {
601                 d_fprintf(stderr, "usage: net rpc registry getvalue <key> "
602                           "<valuename>\n");
603                 return -1;
604         }
605
606         return run_rpc_command(c, NULL, PI_WINREG, 0,
607                 rpc_registry_getvalue_full, argc, argv);
608 }
609
610 static NTSTATUS rpc_registry_getvalue_raw(struct net_context *c,
611                                           const DOM_SID *domain_sid,
612                                           const char *domain_name,
613                                           struct cli_state *cli,
614                                           struct rpc_pipe_client *pipe_hnd,
615                                           TALLOC_CTX *mem_ctx,
616                                           int argc,
617                                           const char **argv)
618 {
619         return rpc_registry_getvalue_internal(c, domain_sid, domain_name,
620                                               cli, pipe_hnd, mem_ctx, true,
621                                               argc, argv);
622 }
623
624 static int rpc_registry_getvalueraw(struct net_context *c, int argc,
625                                     const char **argv)
626 {
627         if (argc != 2) {
628                 d_fprintf(stderr, "usage: net rpc registry getvalue <key> "
629                           "<valuename>\n");
630                 return -1;
631         }
632
633         return run_rpc_command(c, NULL, PI_WINREG, 0,
634                 rpc_registry_getvalue_raw, argc, argv);
635 }
636
637 static NTSTATUS rpc_registry_createkey_internal(struct net_context *c,
638                                                 const DOM_SID *domain_sid,
639                                                 const char *domain_name,
640                                                 struct cli_state *cli,
641                                                 struct rpc_pipe_client *pipe_hnd,
642                                                 TALLOC_CTX *mem_ctx,
643                                                 int argc,
644                                                 const char **argv )
645 {
646         uint32 hive;
647         struct policy_handle hive_hnd, key_hnd;
648         struct winreg_String key, keyclass;
649         enum winreg_CreateAction action;
650         NTSTATUS status;
651
652         ZERO_STRUCT(key);
653         ZERO_STRUCT(keyclass);
654
655         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
656                 return NT_STATUS_INVALID_PARAMETER;
657         }
658
659         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
660                                        SEC_RIGHTS_MAXIMUM_ALLOWED,
661                                        &hive_hnd);
662         if (!(NT_STATUS_IS_OK(status))) {
663                 return status;
664         }
665
666         action = REG_ACTION_NONE;
667         keyclass.name = "";
668
669         status = rpccli_winreg_CreateKey(pipe_hnd, mem_ctx, &hive_hnd, key,
670                                          keyclass, 0, REG_KEY_READ, NULL,
671                                          &key_hnd, &action, NULL);
672         if (!NT_STATUS_IS_OK(status)) {
673                 d_fprintf(stderr, "createkey returned %s\n",
674                           nt_errstr(status));
675                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
676                 return status;
677         }
678
679         switch (action) {
680                 case REG_ACTION_NONE:
681                         d_printf("createkey did nothing -- huh?\n");
682                         break;
683                 case REG_CREATED_NEW_KEY:
684                         d_printf("createkey created %s\n", argv[0]);
685                         break;
686                 case REG_OPENED_EXISTING_KEY:
687                         d_printf("createkey opened existing %s\n", argv[0]);
688                         break;
689         }
690
691         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &key_hnd, NULL);
692         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
693
694         return status;
695 }
696
697 static int rpc_registry_createkey(struct net_context *c, int argc,
698                                   const char **argv )
699 {
700         if (argc != 1) {
701                 d_fprintf(stderr, "usage: net rpc registry createkey <key>\n");
702                 return -1;
703         }
704
705         return run_rpc_command(c, NULL, PI_WINREG, 0,
706                 rpc_registry_createkey_internal, argc, argv );
707 }
708
709 static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
710                                                 const DOM_SID *domain_sid,
711                                                 const char *domain_name,
712                                                 struct cli_state *cli,
713                                                 struct rpc_pipe_client *pipe_hnd,
714                                                 TALLOC_CTX *mem_ctx,
715                                                 int argc,
716                                                 const char **argv )
717 {
718         uint32 hive;
719         struct policy_handle hive_hnd;
720         struct winreg_String key;
721         NTSTATUS status;
722
723         ZERO_STRUCT(key);
724
725         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
726                 return NT_STATUS_INVALID_PARAMETER;
727         }
728
729         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
730                                        SEC_RIGHTS_MAXIMUM_ALLOWED,
731                                        &hive_hnd);
732         if (!(NT_STATUS_IS_OK(status))) {
733                 return status;
734         }
735
736         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key, NULL);
737         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
738
739         if (!NT_STATUS_IS_OK(status)) {
740                 d_fprintf(stderr, "deletekey returned %s\n",
741                           nt_errstr(status));
742         }
743
744         return status;
745 }
746
747 static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
748 {
749         if (argc != 1) {
750                 d_fprintf(stderr, "usage: net rpc registry deletekey <key>\n");
751                 return -1;
752         }
753
754         return run_rpc_command(c, NULL, PI_WINREG, 0,
755                 rpc_registry_deletekey_internal, argc, argv );
756 }
757
758 /********************************************************************
759 ********************************************************************/
760
761 static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
762                                                 const DOM_SID *domain_sid,
763                                                 const char *domain_name,
764                                                 struct cli_state *cli,
765                                                 struct rpc_pipe_client *pipe_hnd,
766                                                 TALLOC_CTX *mem_ctx,
767                                                 int argc,
768                                                 const char **argv )
769 {
770         POLICY_HND pol_hive, pol_key;
771         NTSTATUS status;
772         uint32 num_subkeys = 0;
773         uint32 num_values = 0;
774         char **names = NULL, **classes = NULL;
775         NTTIME **modtimes = NULL;
776         uint32 i;
777         struct registry_value **values = NULL;
778
779         if (argc != 1 ) {
780                 d_printf("Usage:    net rpc registry enumerate <path>\n");
781                 d_printf("Example:  net rpc registry enumerate 'HKLM\\Software\\Samba'\n");
782                 return NT_STATUS_INVALID_PARAMETER;
783         }
784
785         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
786                                   &pol_hive, &pol_key);
787         if (!NT_STATUS_IS_OK(status)) {
788                 d_fprintf(stderr, "registry_openkey failed: %s\n",
789                           nt_errstr(status));
790                 return status;
791         }
792
793         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
794                                    &names, &classes, &modtimes);
795         if (!NT_STATUS_IS_OK(status)) {
796                 d_fprintf(stderr, "enumerating keys failed: %s\n",
797                           nt_errstr(status));
798                 return status;
799         }
800
801         for (i=0; i<num_subkeys; i++) {
802                 print_registry_key(names[i], modtimes[i]);
803         }
804
805         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
806                                      &names, &values);
807         if (!NT_STATUS_IS_OK(status)) {
808                 d_fprintf(stderr, "enumerating values failed: %s\n",
809                           nt_errstr(status));
810                 return status;
811         }
812
813         for (i=0; i<num_values; i++) {
814                 print_registry_value_with_name(names[i], values[i]);
815         }
816
817         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
818         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
819
820         return status;
821 }
822
823 /********************************************************************
824 ********************************************************************/
825
826 static int rpc_registry_enumerate(struct net_context *c, int argc,
827                                   const char **argv )
828 {
829         return run_rpc_command(c, NULL, PI_WINREG, 0,
830                 rpc_registry_enumerate_internal, argc, argv );
831 }
832
833 /********************************************************************
834 ********************************************************************/
835
836 static NTSTATUS rpc_registry_save_internal(struct net_context *c,
837                                         const DOM_SID *domain_sid,
838                                         const char *domain_name,
839                                         struct cli_state *cli,
840                                         struct rpc_pipe_client *pipe_hnd,
841                                         TALLOC_CTX *mem_ctx,
842                                         int argc,
843                                         const char **argv )
844 {
845         WERROR result = WERR_GENERAL_FAILURE;
846         POLICY_HND pol_hive, pol_key;
847         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
848         struct winreg_String filename;
849
850         if (argc != 2 ) {
851                 d_printf("Usage:    net rpc registry backup <path> <file> \n");
852                 return NT_STATUS_INVALID_PARAMETER;
853         }
854
855         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
856                                   &pol_hive, &pol_key);
857         if (!NT_STATUS_IS_OK(status)) {
858                 d_fprintf(stderr, "registry_openkey failed: %s\n",
859                           nt_errstr(status));
860                 return status;
861         }
862
863         filename.name = argv[1];
864         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL, NULL);
865         if ( !W_ERROR_IS_OK(result) ) {
866                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
867         }
868
869         /* cleanup */
870
871         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
872         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
873
874         return status;
875 }
876
877 /********************************************************************
878 ********************************************************************/
879
880 static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
881 {
882         return run_rpc_command(c, NULL, PI_WINREG, 0,
883                 rpc_registry_save_internal, argc, argv );
884 }
885
886
887 /********************************************************************
888 ********************************************************************/
889
890 static void dump_values( REGF_NK_REC *nk )
891 {
892         int i, j;
893         char *data_str = NULL;
894         uint32 data_size, data;
895
896         if ( !nk->values )
897                 return;
898
899         for ( i=0; i<nk->num_values; i++ ) {
900                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
901                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
902
903                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
904                 switch ( nk->values[i].type ) {
905                         case REG_SZ:
906                                 rpcstr_pull_talloc(talloc_tos(),
907                                                 &data_str,
908                                                 nk->values[i].data,
909                                                 -1,
910                                                 STR_TERMINATE);
911                                 if (!data_str) {
912                                         break;
913                                 }
914                                 d_printf( "%s", data_str );
915                                 break;
916                         case REG_MULTI_SZ:
917                         case REG_EXPAND_SZ:
918                                 for ( j=0; j<data_size; j++ ) {
919                                         d_printf( "%c", nk->values[i].data[j] );
920                                 }
921                                 break;
922                         case REG_DWORD:
923                                 data = IVAL( nk->values[i].data, 0 );
924                                 d_printf("0x%x", data );
925                                 break;
926                         case REG_BINARY:
927                                 for ( j=0; j<data_size; j++ ) {
928                                         d_printf( "%x", nk->values[i].data[j] );
929                                 }
930                                 break;
931                         default:
932                                 d_printf("unknown");
933                                 break;
934                 }
935
936                 d_printf( "\n" );
937         }
938
939 }
940
941 /********************************************************************
942 ********************************************************************/
943
944 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
945 {
946         REGF_NK_REC *key;
947
948         /* depth first dump of the registry tree */
949
950         while ( (key = regfio_fetch_subkey( file, nk )) ) {
951                 char *regpath;
952                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
953                         break;
954                 }
955                 d_printf("[%s]\n", regpath );
956                 dump_values( key );
957                 d_printf("\n");
958                 dump_registry_tree( file, key, regpath );
959                 SAFE_FREE(regpath);
960         }
961
962         return true;
963 }
964
965 /********************************************************************
966 ********************************************************************/
967
968 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
969                                  REGF_NK_REC *parent, REGF_FILE *outfile,
970                                  const char *parentpath )
971 {
972         REGF_NK_REC *key, *subkey;
973         REGVAL_CTR *values = NULL;
974         REGSUBKEY_CTR *subkeys = NULL;
975         int i;
976         char *path = NULL;
977
978         if ( !( subkeys = TALLOC_ZERO_P( infile->mem_ctx, REGSUBKEY_CTR )) ) {
979                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
980                 return false;
981         }
982
983         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) ) {
984                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
985                 TALLOC_FREE(subkeys);
986                 return false;
987         }
988
989         /* copy values into the REGVAL_CTR */
990
991         for ( i=0; i<nk->num_values; i++ ) {
992                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
993                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
994         }
995
996         /* copy subkeys into the REGSUBKEY_CTR */
997
998         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
999                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1000         }
1001
1002         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1003
1004         /* write each one of the subkeys out */
1005
1006         path = talloc_asprintf(subkeys,
1007                         "%s%s%s",
1008                         parentpath,
1009                         parent ? "\\" : "",
1010                         nk->keyname);
1011         if (!path) {
1012                 TALLOC_FREE(subkeys);
1013                 return false;
1014         }
1015
1016         nk->subkey_index = 0;
1017         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1018                 write_registry_tree( infile, subkey, key, outfile, path );
1019         }
1020
1021         d_printf("[%s]\n", path );
1022         TALLOC_FREE(subkeys);
1023
1024         return true;
1025 }
1026
1027 /********************************************************************
1028 ********************************************************************/
1029
1030 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1031 {
1032         REGF_FILE   *registry;
1033         REGF_NK_REC *nk;
1034
1035         if (argc != 1 ) {
1036                 d_printf("Usage:    net rpc registry dump <file> \n");
1037                 return -1;
1038         }
1039
1040         d_printf("Opening %s....", argv[0]);
1041         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1042                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
1043                 return 1;
1044         }
1045         d_printf("ok\n");
1046
1047         /* get the root of the registry file */
1048
1049         if ((nk = regfio_rootkey( registry )) == NULL) {
1050                 d_fprintf(stderr, "Could not get rootkey\n");
1051                 regfio_close( registry );
1052                 return 1;
1053         }
1054         d_printf("[%s]\n", nk->keyname);
1055         dump_values( nk );
1056         d_printf("\n");
1057
1058         dump_registry_tree( registry, nk, nk->keyname );
1059
1060 #if 0
1061         talloc_report_full( registry->mem_ctx, stderr );
1062 #endif
1063         d_printf("Closing registry...");
1064         regfio_close( registry );
1065         d_printf("ok\n");
1066
1067         return 0;
1068 }
1069
1070 /********************************************************************
1071 ********************************************************************/
1072
1073 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1074 {
1075         REGF_FILE   *infile = NULL, *outfile = NULL;
1076         REGF_NK_REC *nk;
1077         int result = 1;
1078
1079         if (argc != 2 ) {
1080                 d_printf("Usage:    net rpc registry copy <srcfile> <newfile>\n");
1081                 return -1;
1082         }
1083
1084         d_printf("Opening %s....", argv[0]);
1085         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1086                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
1087                 return 1;
1088         }
1089         d_printf("ok\n");
1090
1091         d_printf("Opening %s....", argv[1]);
1092         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1093                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
1094                 goto out;
1095         }
1096         d_printf("ok\n");
1097
1098         /* get the root of the registry file */
1099
1100         if ((nk = regfio_rootkey( infile )) == NULL) {
1101                 d_fprintf(stderr, "Could not get rootkey\n");
1102                 goto out;
1103         }
1104         d_printf("RootKey: [%s]\n", nk->keyname);
1105
1106         write_registry_tree( infile, nk, NULL, outfile, "" );
1107
1108         result = 0;
1109
1110 out:
1111
1112         d_printf("Closing %s...", argv[1]);
1113         if (outfile) {
1114                 regfio_close( outfile );
1115         }
1116         d_printf("ok\n");
1117
1118         d_printf("Closing %s...", argv[0]);
1119         if (infile) {
1120                 regfio_close( infile );
1121         }
1122         d_printf("ok\n");
1123
1124         return( result);
1125 }
1126
1127 /********************************************************************
1128 ********************************************************************/
1129
1130 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1131                                             const DOM_SID *domain_sid,
1132                                             const char *domain_name,
1133                                             struct cli_state *cli,
1134                                             struct rpc_pipe_client *pipe_hnd,
1135                                             TALLOC_CTX *mem_ctx,
1136                                             int argc,
1137                                             const char **argv)
1138 {
1139         POLICY_HND pol_hive, pol_key;
1140         NTSTATUS status;
1141         enum ndr_err_code ndr_err;
1142         struct KeySecurityData *sd = NULL;
1143         uint32_t sec_info;
1144         DATA_BLOB blob;
1145         struct security_descriptor sec_desc;
1146         uint32_t access_mask = REG_KEY_READ |
1147                                SEC_RIGHT_MAXIMUM_ALLOWED |
1148                                SEC_RIGHT_SYSTEM_SECURITY;
1149
1150         if (argc <1 || argc > 2) {
1151                 d_printf("Usage:    net rpc registry getsd <path> <secinfo>\n");
1152                 d_printf("Example:  net rpc registry getsd 'HKLM\\Software\\Samba'\n");
1153                 return NT_STATUS_INVALID_PARAMETER;
1154         }
1155
1156         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1157                                   access_mask,
1158                                   &pol_hive, &pol_key);
1159         if (!NT_STATUS_IS_OK(status)) {
1160                 d_fprintf(stderr, "registry_openkey failed: %s\n",
1161                           nt_errstr(status));
1162                 return status;
1163         }
1164
1165         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1166         if (!sd) {
1167                 status = NT_STATUS_NO_MEMORY;
1168                 goto out;
1169         }
1170
1171         sd->size = 0x1000;
1172
1173         if (argc >= 2) {
1174                 sscanf(argv[1], "%x", &sec_info);
1175         } else {
1176                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1177         }
1178
1179         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1180         if (!NT_STATUS_IS_OK(status)) {
1181                 d_fprintf(stderr, "getting sd failed: %s\n",
1182                           nt_errstr(status));
1183                 goto out;
1184         }
1185
1186         blob.data = sd->data;
1187         blob.length = sd->size;
1188
1189         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc,
1190                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1191         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1192                 status = ndr_map_error2ntstatus(ndr_err);
1193                 goto out;
1194         }
1195         status = NT_STATUS_OK;
1196
1197         display_sec_desc(&sec_desc);
1198
1199  out:
1200         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1201         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1202
1203         return status;
1204 }
1205
1206
1207 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1208 {
1209         return run_rpc_command(c, NULL, PI_WINREG, 0,
1210                 rpc_registry_getsd_internal, argc, argv);
1211 }
1212
1213 /********************************************************************
1214 ********************************************************************/
1215
1216 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1217 {
1218         struct functable2 func[] = {
1219                 { "enumerate", rpc_registry_enumerate,
1220                   "Enumerate registry keys and values" },
1221                 { "createkey",  rpc_registry_createkey,
1222                   "Create a new registry key" },
1223                 { "deletekey",  rpc_registry_deletekey,
1224                   "Delete a registry key" },
1225                 { "getvalue", rpc_registry_getvalue,
1226                   "Print a registry value" },
1227                 { "getvalueraw", rpc_registry_getvalueraw,
1228                   "Print a registry value" },
1229                 { "setvalue",  rpc_registry_setvalue,
1230                   "Set a new registry value" },
1231                 { "deletevalue",  rpc_registry_deletevalue,
1232                   "Delete a registry value" },
1233                 { "save", rpc_registry_save,
1234                   "Save a registry file" },
1235                 { "dump", rpc_registry_dump,
1236                   "Dump a registry file" },
1237                 { "copy", rpc_registry_copy,
1238                   "Copy a registry file" },
1239                 { "getsd", rpc_registry_getsd,
1240                   "Get security descriptor" },
1241                 {NULL, NULL, NULL}
1242         };
1243
1244         return net_run_function2(c, argc, argv, "net rpc registry", func);
1245 }