d9eb9b3c0948794c4d1a05f2a75974aea21098a2
[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         const char *data_str = NULL;
899         uint32 data_size, data;
900         DATA_BLOB blob;
901
902         if ( !nk->values )
903                 return;
904
905         for ( i=0; i<nk->num_values; i++ ) {
906                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
907                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
908
909                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
910                 switch ( nk->values[i].type ) {
911                         case REG_SZ:
912                                 blob = data_blob_const(nk->values[i].data, data_size);
913                                 pull_reg_sz(talloc_tos(), &blob, &data_str);
914                                 if (!data_str) {
915                                         break;
916                                 }
917                                 d_printf( "%s", data_str );
918                                 break;
919                         case REG_MULTI_SZ:
920                         case REG_EXPAND_SZ:
921                                 for ( j=0; j<data_size; j++ ) {
922                                         d_printf( "%c", nk->values[i].data[j] );
923                                 }
924                                 break;
925                         case REG_DWORD:
926                                 data = IVAL( nk->values[i].data, 0 );
927                                 d_printf("0x%x", data );
928                                 break;
929                         case REG_BINARY:
930                                 for ( j=0; j<data_size; j++ ) {
931                                         d_printf( "%x", nk->values[i].data[j] );
932                                 }
933                                 break;
934                         default:
935                                 d_printf(_("unknown"));
936                                 break;
937                 }
938
939                 d_printf( "\n" );
940         }
941
942 }
943
944 /********************************************************************
945 ********************************************************************/
946
947 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
948 {
949         REGF_NK_REC *key;
950
951         /* depth first dump of the registry tree */
952
953         while ( (key = regfio_fetch_subkey( file, nk )) ) {
954                 char *regpath;
955                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
956                         break;
957                 }
958                 d_printf("[%s]\n", regpath );
959                 dump_values( key );
960                 d_printf("\n");
961                 dump_registry_tree( file, key, regpath );
962                 SAFE_FREE(regpath);
963         }
964
965         return true;
966 }
967
968 /********************************************************************
969 ********************************************************************/
970
971 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
972                                  REGF_NK_REC *parent, REGF_FILE *outfile,
973                                  const char *parentpath )
974 {
975         REGF_NK_REC *key, *subkey;
976         struct regval_ctr *values = NULL;
977         struct regsubkey_ctr *subkeys = NULL;
978         int i;
979         char *path = NULL;
980         WERROR werr;
981
982         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
983         if (!W_ERROR_IS_OK(werr)) {
984                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
985                           "%s\n", win_errstr(werr)));
986                 return false;
987         }
988
989         if ( !(values = TALLOC_ZERO_P( subkeys, struct regval_ctr )) ) {
990                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
991                 TALLOC_FREE(subkeys);
992                 return false;
993         }
994
995         /* copy values into the struct regval_ctr */
996
997         for ( i=0; i<nk->num_values; i++ ) {
998                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
999                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
1000         }
1001
1002         /* copy subkeys into the struct regsubkey_ctr */
1003
1004         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1005                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1006         }
1007
1008         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1009
1010         /* write each one of the subkeys out */
1011
1012         path = talloc_asprintf(subkeys,
1013                         "%s%s%s",
1014                         parentpath,
1015                         parent ? "\\" : "",
1016                         nk->keyname);
1017         if (!path) {
1018                 TALLOC_FREE(subkeys);
1019                 return false;
1020         }
1021
1022         nk->subkey_index = 0;
1023         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1024                 write_registry_tree( infile, subkey, key, outfile, path );
1025         }
1026
1027         d_printf("[%s]\n", path );
1028         TALLOC_FREE(subkeys);
1029
1030         return true;
1031 }
1032
1033 /********************************************************************
1034 ********************************************************************/
1035
1036 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1037 {
1038         REGF_FILE   *registry;
1039         REGF_NK_REC *nk;
1040
1041         if (argc != 1 || c->display_usage) {
1042                 d_printf(_("Usage:    net rpc registry dump <file> \n"));
1043                 return -1;
1044         }
1045
1046         d_printf(_("Opening %s...."), argv[0]);
1047         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1048                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1049                 return 1;
1050         }
1051         d_printf(_("ok\n"));
1052
1053         /* get the root of the registry file */
1054
1055         if ((nk = regfio_rootkey( registry )) == NULL) {
1056                 d_fprintf(stderr, _("Could not get rootkey\n"));
1057                 regfio_close( registry );
1058                 return 1;
1059         }
1060         d_printf("[%s]\n", nk->keyname);
1061         dump_values( nk );
1062         d_printf("\n");
1063
1064         dump_registry_tree( registry, nk, nk->keyname );
1065
1066 #if 0
1067         talloc_report_full( registry->mem_ctx, stderr );
1068 #endif
1069         d_printf(_("Closing registry..."));
1070         regfio_close( registry );
1071         d_printf(_("ok\n"));
1072
1073         return 0;
1074 }
1075
1076 /********************************************************************
1077 ********************************************************************/
1078
1079 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1080 {
1081         REGF_FILE   *infile = NULL, *outfile = NULL;
1082         REGF_NK_REC *nk;
1083         int result = 1;
1084
1085         if (argc != 2 || c->display_usage) {
1086                 d_printf(_("Usage:    net rpc registry copy <srcfile> "
1087                            "<newfile>\n"));
1088                 return -1;
1089         }
1090
1091         d_printf(_("Opening %s...."), argv[0]);
1092         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1093                 d_fprintf(stderr, _("Failed to open %s for reading\n"),argv[0]);
1094                 return 1;
1095         }
1096         d_printf(_("ok\n"));
1097
1098         d_printf(_("Opening %s...."), argv[1]);
1099         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1100                 d_fprintf(stderr, _("Failed to open %s for writing\n"),argv[1]);
1101                 goto out;
1102         }
1103         d_printf(_("ok\n"));
1104
1105         /* get the root of the registry file */
1106
1107         if ((nk = regfio_rootkey( infile )) == NULL) {
1108                 d_fprintf(stderr, _("Could not get rootkey\n"));
1109                 goto out;
1110         }
1111         d_printf(_("RootKey: [%s]\n"), nk->keyname);
1112
1113         write_registry_tree( infile, nk, NULL, outfile, "" );
1114
1115         result = 0;
1116
1117 out:
1118
1119         d_printf(_("Closing %s..."), argv[1]);
1120         if (outfile) {
1121                 regfio_close( outfile );
1122         }
1123         d_printf(_("ok\n"));
1124
1125         d_printf(_("Closing %s..."), argv[0]);
1126         if (infile) {
1127                 regfio_close( infile );
1128         }
1129         d_printf(_("ok\n"));
1130
1131         return( result);
1132 }
1133
1134 /********************************************************************
1135 ********************************************************************/
1136
1137 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1138                                             const DOM_SID *domain_sid,
1139                                             const char *domain_name,
1140                                             struct cli_state *cli,
1141                                             struct rpc_pipe_client *pipe_hnd,
1142                                             TALLOC_CTX *mem_ctx,
1143                                             int argc,
1144                                             const char **argv)
1145 {
1146         struct policy_handle pol_hive, pol_key;
1147         NTSTATUS status;
1148         enum ndr_err_code ndr_err;
1149         struct KeySecurityData *sd = NULL;
1150         uint32_t sec_info;
1151         DATA_BLOB blob;
1152         struct security_descriptor sec_desc;
1153         uint32_t access_mask = REG_KEY_READ |
1154                                SEC_FLAG_MAXIMUM_ALLOWED |
1155                                SEC_FLAG_SYSTEM_SECURITY;
1156
1157         if (argc <1 || argc > 2 || c->display_usage) {
1158                 d_printf(_("Usage:    net rpc registry getsd <path> "
1159                            "<secinfo>\n"));
1160                 d_printf(_("Example:  net rpc registry getsd "
1161                            "'HKLM\\Software\\Samba'\n"));
1162                 return NT_STATUS_INVALID_PARAMETER;
1163         }
1164
1165         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1166                                   access_mask,
1167                                   &pol_hive, &pol_key);
1168         if (!NT_STATUS_IS_OK(status)) {
1169                 d_fprintf(stderr, _("registry_openkey failed: %s\n"),
1170                           nt_errstr(status));
1171                 return status;
1172         }
1173
1174         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1175         if (!sd) {
1176                 status = NT_STATUS_NO_MEMORY;
1177                 goto out;
1178         }
1179
1180         sd->size = 0x1000;
1181
1182         if (argc >= 2) {
1183                 sscanf(argv[1], "%x", &sec_info);
1184         } else {
1185                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1186         }
1187
1188         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1189         if (!NT_STATUS_IS_OK(status)) {
1190                 d_fprintf(stderr, _("getting sd failed: %s\n"),
1191                           nt_errstr(status));
1192                 goto out;
1193         }
1194
1195         blob.data = sd->data;
1196         blob.length = sd->size;
1197
1198         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &sec_desc,
1199                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1200         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1201                 status = ndr_map_error2ntstatus(ndr_err);
1202                 goto out;
1203         }
1204         status = NT_STATUS_OK;
1205
1206         display_sec_desc(&sec_desc);
1207
1208  out:
1209         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1210         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1211
1212         return status;
1213 }
1214
1215
1216 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1217 {
1218         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
1219                 rpc_registry_getsd_internal, argc, argv);
1220 }
1221
1222 /********************************************************************
1223 ********************************************************************/
1224
1225 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1226 {
1227         struct functable func[] = {
1228                 {
1229                         "enumerate",
1230                         rpc_registry_enumerate,
1231                         NET_TRANSPORT_RPC,
1232                         N_("Enumerate registry keys and values"),
1233                         N_("net rpc registry enumerate\n"
1234                            "    Enumerate registry keys and values")
1235                 },
1236                 {
1237                         "createkey",
1238                         rpc_registry_createkey,
1239                         NET_TRANSPORT_RPC,
1240                         N_("Create a new registry key"),
1241                         N_("net rpc registry createkey\n"
1242                            "    Create a new registry key")
1243                 },
1244                 {
1245                         "deletekey",
1246                         rpc_registry_deletekey,
1247                         NET_TRANSPORT_RPC,
1248                         N_("Delete a registry key"),
1249                         N_("net rpc registry deletekey\n"
1250                            "    Delete a registry key")
1251                 },
1252                 {
1253                         "getvalue",
1254                         rpc_registry_getvalue,
1255                         NET_TRANSPORT_RPC,
1256                         N_("Print a registry value"),
1257                         N_("net rpc registry getvalue\n"
1258                            "    Print a registry value")
1259                 },
1260                 {
1261                         "getvalueraw",
1262                         rpc_registry_getvalueraw,
1263                         NET_TRANSPORT_RPC,
1264                         N_("Print a registry value"),
1265                         N_("net rpc registry getvalueraw\n"
1266                            "    Print a registry value (raw version)")
1267                 },
1268                 {
1269                         "setvalue",
1270                         rpc_registry_setvalue,
1271                         NET_TRANSPORT_RPC,
1272                         N_("Set a new registry value"),
1273                         N_("net rpc registry setvalue\n"
1274                            "    Set a new registry value")
1275                 },
1276                 {
1277                         "deletevalue",
1278                         rpc_registry_deletevalue,
1279                         NET_TRANSPORT_RPC,
1280                         N_("Delete a registry value"),
1281                         N_("net rpc registry deletevalue\n"
1282                            "    Delete a registry value")
1283                 },
1284                 {
1285                         "save",
1286                         rpc_registry_save,
1287                         NET_TRANSPORT_RPC,
1288                         N_("Save a registry file"),
1289                         N_("net rpc registry save\n"
1290                            "    Save a registry file")
1291                 },
1292                 {
1293                         "dump",
1294                         rpc_registry_dump,
1295                         NET_TRANSPORT_RPC,
1296                         N_("Dump a registry file"),
1297                         N_("net rpc registry dump\n"
1298                            "    Dump a registry file")
1299                 },
1300                 {
1301                         "copy",
1302                         rpc_registry_copy,
1303                         NET_TRANSPORT_RPC,
1304                         N_("Copy a registry file"),
1305                         N_("net rpc registry copy\n"
1306                            "    Copy a registry file")
1307                 },
1308                 {
1309                         "getsd",
1310                         rpc_registry_getsd,
1311                         NET_TRANSPORT_RPC,
1312                         N_("Get security descriptor"),
1313                         N_("net rpc registry getsd\n"
1314                            "    Get security descriptior")
1315                 },
1316                 {NULL, NULL, 0, NULL, NULL}
1317         };
1318
1319         return net_run_function(c, argc, argv, "net rpc registry", func);
1320 }