1ad1d74ca0853c7ff70e783853996d5b362ea451
[ira/wip.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_FLAG_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 || c->display_usage) {
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, &ndr_table_winreg.syntax_id, 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_FLAG_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 || c->display_usage) {
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, &ndr_table_winreg.syntax_id, 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_FLAG_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 || c->display_usage) {
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, &ndr_table_winreg.syntax_id, 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 || c->display_usage) {
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, &ndr_table_winreg.syntax_id, 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_FLAG_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 || c->display_usage) {
701                 d_fprintf(stderr,
702                           _("usage: net rpc registry createkey <key>\n"));
703                 return -1;
704         }
705
706         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
707                 rpc_registry_createkey_internal, argc, argv );
708 }
709
710 static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
711                                                 const DOM_SID *domain_sid,
712                                                 const char *domain_name,
713                                                 struct cli_state *cli,
714                                                 struct rpc_pipe_client *pipe_hnd,
715                                                 TALLOC_CTX *mem_ctx,
716                                                 int argc,
717                                                 const char **argv )
718 {
719         uint32 hive;
720         struct policy_handle hive_hnd;
721         struct winreg_String key;
722         NTSTATUS status;
723
724         ZERO_STRUCT(key);
725
726         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
727                 return NT_STATUS_INVALID_PARAMETER;
728         }
729
730         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
731                                        SEC_FLAG_MAXIMUM_ALLOWED,
732                                        &hive_hnd);
733         if (!(NT_STATUS_IS_OK(status))) {
734                 return status;
735         }
736
737         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key, NULL);
738         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
739
740         if (!NT_STATUS_IS_OK(status)) {
741                 d_fprintf(stderr, _("deletekey returned %s\n"),
742                           nt_errstr(status));
743         }
744
745         return status;
746 }
747
748 static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
749 {
750         if (argc != 1 || c->display_usage) {
751                 d_fprintf(stderr,
752                           _("usage: net rpc registry deletekey <key>\n"));
753                 return -1;
754         }
755
756         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
757                 rpc_registry_deletekey_internal, argc, argv );
758 }
759
760 /********************************************************************
761 ********************************************************************/
762
763 static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
764                                                 const DOM_SID *domain_sid,
765                                                 const char *domain_name,
766                                                 struct cli_state *cli,
767                                                 struct rpc_pipe_client *pipe_hnd,
768                                                 TALLOC_CTX *mem_ctx,
769                                                 int argc,
770                                                 const char **argv )
771 {
772         struct policy_handle pol_hive, pol_key;
773         NTSTATUS status;
774         uint32 num_subkeys = 0;
775         uint32 num_values = 0;
776         char **names = NULL, **classes = NULL;
777         NTTIME **modtimes = NULL;
778         uint32 i;
779         struct registry_value **values = NULL;
780
781         if (argc != 1 || c->display_usage) {
782                 d_printf(_("Usage:    net rpc registry enumerate <path>\n"));
783                 d_printf(_("Example:  net rpc registry enumerate "
784                            "'HKLM\\Software\\Samba'\n"));
785                 return NT_STATUS_INVALID_PARAMETER;
786         }
787
788         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
789                                   &pol_hive, &pol_key);
790         if (!NT_STATUS_IS_OK(status)) {
791                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
792                           nt_errstr(status));
793                 return status;
794         }
795
796         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
797                                    &names, &classes, &modtimes);
798         if (!NT_STATUS_IS_OK(status)) {
799                 d_fprintf(stderr, _("enumerating keys failed: %s\n"),
800                           nt_errstr(status));
801                 return status;
802         }
803
804         for (i=0; i<num_subkeys; i++) {
805                 print_registry_key(names[i], modtimes[i]);
806         }
807
808         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
809                                      &names, &values);
810         if (!NT_STATUS_IS_OK(status)) {
811                 d_fprintf(stderr, _("enumerating values failed: %s\n"),
812                           nt_errstr(status));
813                 return status;
814         }
815
816         for (i=0; i<num_values; i++) {
817                 print_registry_value_with_name(names[i], values[i]);
818         }
819
820         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
821         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
822
823         return status;
824 }
825
826 /********************************************************************
827 ********************************************************************/
828
829 static int rpc_registry_enumerate(struct net_context *c, int argc,
830                                   const char **argv )
831 {
832         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
833                 rpc_registry_enumerate_internal, argc, argv );
834 }
835
836 /********************************************************************
837 ********************************************************************/
838
839 static NTSTATUS rpc_registry_save_internal(struct net_context *c,
840                                         const DOM_SID *domain_sid,
841                                         const char *domain_name,
842                                         struct cli_state *cli,
843                                         struct rpc_pipe_client *pipe_hnd,
844                                         TALLOC_CTX *mem_ctx,
845                                         int argc,
846                                         const char **argv )
847 {
848         WERROR result = WERR_GENERAL_FAILURE;
849         struct policy_handle pol_hive, pol_key;
850         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
851         struct winreg_String filename;
852
853         if (argc != 2 || c->display_usage) {
854                 d_printf(_("Usage:    net rpc registry backup <path> "
855                            "<file> \n"));
856                 return NT_STATUS_INVALID_PARAMETER;
857         }
858
859         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
860                                   &pol_hive, &pol_key);
861         if (!NT_STATUS_IS_OK(status)) {
862                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
863                           nt_errstr(status));
864                 return status;
865         }
866
867         filename.name = argv[1];
868         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL, NULL);
869         if ( !W_ERROR_IS_OK(result) ) {
870                 d_fprintf(stderr, _("Unable to save [%s] to %s:%s\n"), argv[0],
871                           cli->desthost, argv[1]);
872         }
873
874         /* cleanup */
875
876         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
877         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
878
879         return status;
880 }
881
882 /********************************************************************
883 ********************************************************************/
884
885 static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
886 {
887         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
888                 rpc_registry_save_internal, argc, argv );
889 }
890
891
892 /********************************************************************
893 ********************************************************************/
894
895 static void dump_values( REGF_NK_REC *nk )
896 {
897         int i, j;
898         char *data_str = NULL;
899         uint32 data_size, data;
900
901         if ( !nk->values )
902                 return;
903
904         for ( i=0; i<nk->num_values; i++ ) {
905                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
906                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
907
908                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
909                 switch ( nk->values[i].type ) {
910                         case REG_SZ:
911                                 rpcstr_pull_talloc(talloc_tos(),
912                                                 &data_str,
913                                                 nk->values[i].data,
914                                                 -1,
915                                                 STR_TERMINATE);
916                                 if (!data_str) {
917                                         break;
918                                 }
919                                 d_printf( "%s", data_str );
920                                 break;
921                         case REG_MULTI_SZ:
922                         case REG_EXPAND_SZ:
923                                 for ( j=0; j<data_size; j++ ) {
924                                         d_printf( "%c", nk->values[i].data[j] );
925                                 }
926                                 break;
927                         case REG_DWORD:
928                                 data = IVAL( nk->values[i].data, 0 );
929                                 d_printf("0x%x", data );
930                                 break;
931                         case REG_BINARY:
932                                 for ( j=0; j<data_size; j++ ) {
933                                         d_printf( "%x", nk->values[i].data[j] );
934                                 }
935                                 break;
936                         default:
937                                 d_printf(_("unknown"));
938                                 break;
939                 }
940
941                 d_printf( "\n" );
942         }
943
944 }
945
946 /********************************************************************
947 ********************************************************************/
948
949 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
950 {
951         REGF_NK_REC *key;
952
953         /* depth first dump of the registry tree */
954
955         while ( (key = regfio_fetch_subkey( file, nk )) ) {
956                 char *regpath;
957                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
958                         break;
959                 }
960                 d_printf("[%s]\n", regpath );
961                 dump_values( key );
962                 d_printf("\n");
963                 dump_registry_tree( file, key, regpath );
964                 SAFE_FREE(regpath);
965         }
966
967         return true;
968 }
969
970 /********************************************************************
971 ********************************************************************/
972
973 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
974                                  REGF_NK_REC *parent, REGF_FILE *outfile,
975                                  const char *parentpath )
976 {
977         REGF_NK_REC *key, *subkey;
978         struct regval_ctr *values = NULL;
979         struct regsubkey_ctr *subkeys = NULL;
980         int i;
981         char *path = NULL;
982         WERROR werr;
983
984         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
985         if (!W_ERROR_IS_OK(werr)) {
986                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
987                           "%s\n", win_errstr(werr)));
988                 return false;
989         }
990
991         if ( !(values = TALLOC_ZERO_P( subkeys, struct regval_ctr )) ) {
992                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
993                 TALLOC_FREE(subkeys);
994                 return false;
995         }
996
997         /* copy values into the struct regval_ctr */
998
999         for ( i=0; i<nk->num_values; i++ ) {
1000                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
1001                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
1002         }
1003
1004         /* copy subkeys into the struct regsubkey_ctr */
1005
1006         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1007                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1008         }
1009
1010         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1011
1012         /* write each one of the subkeys out */
1013
1014         path = talloc_asprintf(subkeys,
1015                         "%s%s%s",
1016                         parentpath,
1017                         parent ? "\\" : "",
1018                         nk->keyname);
1019         if (!path) {
1020                 TALLOC_FREE(subkeys);
1021                 return false;
1022         }
1023
1024         nk->subkey_index = 0;
1025         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1026                 write_registry_tree( infile, subkey, key, outfile, path );
1027         }
1028
1029         d_printf("[%s]\n", path );
1030         TALLOC_FREE(subkeys);
1031
1032         return true;
1033 }
1034
1035 /********************************************************************
1036 ********************************************************************/
1037
1038 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1039 {
1040         REGF_FILE   *registry;
1041         REGF_NK_REC *nk;
1042
1043         if (argc != 1 || c->display_usage) {
1044                 d_printf(_("Usage:    net rpc registry dump <file> \n"));
1045                 return -1;
1046         }
1047
1048         d_printf(_("Opening %s...."), argv[0]);
1049         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1050                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1051                 return 1;
1052         }
1053         d_printf(_("ok\n"));
1054
1055         /* get the root of the registry file */
1056
1057         if ((nk = regfio_rootkey( registry )) == NULL) {
1058                 d_fprintf(stderr, _("Could not get rootkey\n"));
1059                 regfio_close( registry );
1060                 return 1;
1061         }
1062         d_printf("[%s]\n", nk->keyname);
1063         dump_values( nk );
1064         d_printf("\n");
1065
1066         dump_registry_tree( registry, nk, nk->keyname );
1067
1068 #if 0
1069         talloc_report_full( registry->mem_ctx, stderr );
1070 #endif
1071         d_printf(_("Closing registry..."));
1072         regfio_close( registry );
1073         d_printf(_("ok\n"));
1074
1075         return 0;
1076 }
1077
1078 /********************************************************************
1079 ********************************************************************/
1080
1081 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1082 {
1083         REGF_FILE   *infile = NULL, *outfile = NULL;
1084         REGF_NK_REC *nk;
1085         int result = 1;
1086
1087         if (argc != 2 || c->display_usage) {
1088                 d_printf(_("Usage:    net rpc registry copy <srcfile> "
1089                            "<newfile>\n"));
1090                 return -1;
1091         }
1092
1093         d_printf(_("Opening %s...."), argv[0]);
1094         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1095                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1096                 return 1;
1097         }
1098         d_printf(_("ok\n"));
1099
1100         d_printf(_("Opening %s...."), argv[1]);
1101         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1102                 d_fprintf(stderr, _("Failed to open %s for writing\n"),argv[1]);
1103                 goto out;
1104         }
1105         d_printf(_("ok\n"));
1106
1107         /* get the root of the registry file */
1108
1109         if ((nk = regfio_rootkey( infile )) == NULL) {
1110                 d_fprintf(stderr, _("Could not get rootkey\n"));
1111                 goto out;
1112         }
1113         d_printf(_("RootKey: [%s]\n"), nk->keyname);
1114
1115         write_registry_tree( infile, nk, NULL, outfile, "" );
1116
1117         result = 0;
1118
1119 out:
1120
1121         d_printf(_("Closing %s..."), argv[1]);
1122         if (outfile) {
1123                 regfio_close( outfile );
1124         }
1125         d_printf(_("ok\n"));
1126
1127         d_printf(_("Closing %s..."), argv[0]);
1128         if (infile) {
1129                 regfio_close( infile );
1130         }
1131         d_printf(_("ok\n"));
1132
1133         return( result);
1134 }
1135
1136 /********************************************************************
1137 ********************************************************************/
1138
1139 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1140                                             const DOM_SID *domain_sid,
1141                                             const char *domain_name,
1142                                             struct cli_state *cli,
1143                                             struct rpc_pipe_client *pipe_hnd,
1144                                             TALLOC_CTX *mem_ctx,
1145                                             int argc,
1146                                             const char **argv)
1147 {
1148         struct policy_handle pol_hive, pol_key;
1149         NTSTATUS status;
1150         enum ndr_err_code ndr_err;
1151         struct KeySecurityData *sd = NULL;
1152         uint32_t sec_info;
1153         DATA_BLOB blob;
1154         struct security_descriptor sec_desc;
1155         uint32_t access_mask = REG_KEY_READ |
1156                                SEC_FLAG_MAXIMUM_ALLOWED |
1157                                SEC_FLAG_SYSTEM_SECURITY;
1158
1159         if (argc <1 || argc > 2 || c->display_usage) {
1160                 d_printf(_("Usage:    net rpc registry getsd <path> "
1161                            "<secinfo>\n"));
1162                 d_printf(_("Example:  net rpc registry getsd "
1163                            "'HKLM\\Software\\Samba'\n"));
1164                 return NT_STATUS_INVALID_PARAMETER;
1165         }
1166
1167         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1168                                   access_mask,
1169                                   &pol_hive, &pol_key);
1170         if (!NT_STATUS_IS_OK(status)) {
1171                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
1172                           nt_errstr(status));
1173                 return status;
1174         }
1175
1176         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1177         if (!sd) {
1178                 status = NT_STATUS_NO_MEMORY;
1179                 goto out;
1180         }
1181
1182         sd->size = 0x1000;
1183
1184         if (argc >= 2) {
1185                 sscanf(argv[1], "%x", &sec_info);
1186         } else {
1187                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1188         }
1189
1190         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1191         if (!NT_STATUS_IS_OK(status)) {
1192                 d_fprintf(stderr, _("getting sd failed: %s\n"),
1193                           nt_errstr(status));
1194                 goto out;
1195         }
1196
1197         blob.data = sd->data;
1198         blob.length = sd->size;
1199
1200         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &sec_desc,
1201                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1202         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1203                 status = ndr_map_error2ntstatus(ndr_err);
1204                 goto out;
1205         }
1206         status = NT_STATUS_OK;
1207
1208         display_sec_desc(&sec_desc);
1209
1210  out:
1211         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1212         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1213
1214         return status;
1215 }
1216
1217
1218 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1219 {
1220         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
1221                 rpc_registry_getsd_internal, argc, argv);
1222 }
1223
1224 /********************************************************************
1225 ********************************************************************/
1226
1227 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1228 {
1229         struct functable func[] = {
1230                 {
1231                         "enumerate",
1232                         rpc_registry_enumerate,
1233                         NET_TRANSPORT_RPC,
1234                         N_("Enumerate registry keys and values"),
1235                         N_("net rpc registry enumerate\n"
1236                            "    Enumerate registry keys and values")
1237                 },
1238                 {
1239                         "createkey",
1240                         rpc_registry_createkey,
1241                         NET_TRANSPORT_RPC,
1242                         N_("Create a new registry key"),
1243                         N_("net rpc registry createkey\n"
1244                            "    Create a new registry key")
1245                 },
1246                 {
1247                         "deletekey",
1248                         rpc_registry_deletekey,
1249                         NET_TRANSPORT_RPC,
1250                         N_("Delete a registry key"),
1251                         N_("net rpc registry deletekey\n"
1252                            "    Delete a registry key")
1253                 },
1254                 {
1255                         "getvalue",
1256                         rpc_registry_getvalue,
1257                         NET_TRANSPORT_RPC,
1258                         N_("Print a registry value"),
1259                         N_("net rpc registry getvalue\n"
1260                            "    Print a registry value")
1261                 },
1262                 {
1263                         "getvalueraw",
1264                         rpc_registry_getvalueraw,
1265                         NET_TRANSPORT_RPC,
1266                         N_("Print a registry value"),
1267                         N_("net rpc registry getvalueraw\n"
1268                            "    Print a registry value (raw version)")
1269                 },
1270                 {
1271                         "setvalue",
1272                         rpc_registry_setvalue,
1273                         NET_TRANSPORT_RPC,
1274                         N_("Set a new registry value"),
1275                         N_("net rpc registry setvalue\n"
1276                            "    Set a new registry value")
1277                 },
1278                 {
1279                         "deletevalue",
1280                         rpc_registry_deletevalue,
1281                         NET_TRANSPORT_RPC,
1282                         N_("Delete a registry value"),
1283                         N_("net rpc registry deletevalue\n"
1284                            "    Delete a registry value")
1285                 },
1286                 {
1287                         "save",
1288                         rpc_registry_save,
1289                         NET_TRANSPORT_RPC,
1290                         N_("Save a registry file"),
1291                         N_("net rpc registry save\n"
1292                            "    Save a registry file")
1293                 },
1294                 {
1295                         "dump",
1296                         rpc_registry_dump,
1297                         NET_TRANSPORT_RPC,
1298                         N_("Dump a registry file"),
1299                         N_("net rpc registry dump\n"
1300                            "    Dump a registry file")
1301                 },
1302                 {
1303                         "copy",
1304                         rpc_registry_copy,
1305                         NET_TRANSPORT_RPC,
1306                         N_("Copy a registry file"),
1307                         N_("net rpc registry copy\n"
1308                            "    Copy a registry file")
1309                 },
1310                 {
1311                         "getsd",
1312                         rpc_registry_getsd,
1313                         NET_TRANSPORT_RPC,
1314                         N_("Get security descriptor"),
1315                         N_("net rpc registry getsd\n"
1316                            "    Get security descriptior")
1317                 },
1318                 {NULL, NULL, 0, NULL, NULL}
1319         };
1320
1321         return net_run_function(c, argc, argv, "net rpc registry", func);
1322 }