s3:registry: replace typedef REGVAL_CTR by struct regval_ctr.
[nivanova/samba-autobuild/.git] / source3 / utils / net_rpc_registry.c
1 /* 
2    Samba Unix/Linux SMB client library 
3    Distributed SMB/CIFS Server Management Utility 
4
5    Copyright (C) Gerald (Jerry) Carter          2005-2006
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19  
20 #include "includes.h"
21 #include "utils/net.h"
22 #include "utils/net_registry_util.h"
23 #include "regfio.h"
24 #include "reg_objects.h"
25
26 static bool reg_hive_key(TALLOC_CTX *ctx, const char *fullname,
27                          uint32 *reg_type, const char **key_name)
28 {
29         WERROR werr;
30         char *hivename = NULL;
31         char *tmp_keyname = NULL;
32         bool ret = false;
33         TALLOC_CTX *tmp_ctx = talloc_stackframe();
34
35         werr = split_hive_key(tmp_ctx, fullname, &hivename, &tmp_keyname);
36         if (!W_ERROR_IS_OK(werr)) {
37                 goto done;
38         }
39
40         *key_name = talloc_strdup(ctx, tmp_keyname);
41         if (*key_name == NULL) {
42                 goto done;
43         }
44
45         if (strequal(hivename, "HKLM") ||
46             strequal(hivename, "HKEY_LOCAL_MACHINE"))
47         {
48                 (*reg_type) = HKEY_LOCAL_MACHINE;
49         } else if (strequal(hivename, "HKCR") ||
50                    strequal(hivename, "HKEY_CLASSES_ROOT"))
51         {
52                 (*reg_type) = HKEY_CLASSES_ROOT;
53         } else if (strequal(hivename, "HKU") ||
54                    strequal(hivename, "HKEY_USERS"))
55         {
56                 (*reg_type) = HKEY_USERS;
57         } else if (strequal(hivename, "HKCU") ||
58                    strequal(hivename, "HKEY_CURRENT_USER"))
59         {
60                 (*reg_type) = HKEY_CURRENT_USER;
61         } else if (strequal(hivename, "HKPD") ||
62                    strequal(hivename, "HKEY_PERFORMANCE_DATA"))
63         {
64                 (*reg_type) = HKEY_PERFORMANCE_DATA;
65         } else {
66                 DEBUG(10,("reg_hive_key: unrecognised hive key %s\n",
67                           fullname));
68                 goto done;
69         }
70
71         ret = true;
72
73 done:
74         TALLOC_FREE(tmp_ctx);
75         return ret;
76 }
77
78 static NTSTATUS registry_openkey(TALLOC_CTX *mem_ctx,
79                                  struct rpc_pipe_client *pipe_hnd,
80                                  const char *name, uint32 access_mask,
81                                  struct policy_handle *hive_hnd,
82                                  struct policy_handle *key_hnd)
83 {
84         uint32 hive;
85         NTSTATUS status;
86         struct winreg_String key;
87
88         ZERO_STRUCT(key);
89
90         if (!reg_hive_key(mem_ctx, name, &hive, &key.name)) {
91                 return NT_STATUS_INVALID_PARAMETER;
92         }
93
94         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive, access_mask,
95                                        hive_hnd);
96         if (!(NT_STATUS_IS_OK(status))) {
97                 return status;
98         }
99
100         status = rpccli_winreg_OpenKey(pipe_hnd, mem_ctx, hive_hnd, key, 0,
101                                        access_mask, key_hnd, NULL);
102         if (!(NT_STATUS_IS_OK(status))) {
103                 rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, hive_hnd, NULL);
104                 return status;
105         }
106
107         return NT_STATUS_OK;
108 }
109
110 static NTSTATUS registry_enumkeys(TALLOC_CTX *ctx,
111                                   struct rpc_pipe_client *pipe_hnd,
112                                   struct policy_handle *key_hnd,
113                                   uint32 *pnum_keys, char ***pnames,
114                                   char ***pclasses, NTTIME ***pmodtimes)
115 {
116         TALLOC_CTX *mem_ctx;
117         NTSTATUS status;
118         uint32 num_subkeys, max_subkeylen, max_classlen;
119         uint32 num_values, max_valnamelen, max_valbufsize;
120         uint32 i;
121         NTTIME last_changed_time;
122         uint32 secdescsize;
123         struct winreg_String classname;
124         char **names, **classes;
125         NTTIME **modtimes;
126
127         if (!(mem_ctx = talloc_new(ctx))) {
128                 return NT_STATUS_NO_MEMORY;
129         }
130
131         ZERO_STRUCT(classname);
132         status = rpccli_winreg_QueryInfoKey(
133                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
134                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
135                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
136
137         if (!NT_STATUS_IS_OK(status)) {
138                 goto error;
139         }
140
141         if (num_subkeys == 0) {
142                 *pnum_keys = 0;
143                 TALLOC_FREE(mem_ctx);
144                 return NT_STATUS_OK;
145         }
146
147         if ((!(names = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
148             (!(classes = TALLOC_ZERO_ARRAY(mem_ctx, char *, num_subkeys))) ||
149             (!(modtimes = TALLOC_ZERO_ARRAY(mem_ctx, NTTIME *,
150                                             num_subkeys)))) {
151                 status = NT_STATUS_NO_MEMORY;
152                 goto error;
153         }
154
155         for (i=0; i<num_subkeys; i++) {
156                 char c, n;
157                 struct winreg_StringBuf class_buf;
158                 struct winreg_StringBuf name_buf;
159                 NTTIME modtime;
160                 WERROR werr;
161
162                 c = '\0';
163                 class_buf.name = &c;
164                 class_buf.size = max_classlen+2;
165
166                 n = '\0';
167                 name_buf.name = &n;
168                 name_buf.size = max_subkeylen+2;
169
170                 ZERO_STRUCT(modtime);
171
172                 status = rpccli_winreg_EnumKey(pipe_hnd, mem_ctx, key_hnd,
173                                                i, &name_buf, &class_buf,
174                                                &modtime, &werr);
175
176                 if (W_ERROR_EQUAL(werr,
177                                   WERR_NO_MORE_ITEMS) ) {
178                         status = NT_STATUS_OK;
179                         break;
180                 }
181                 if (!NT_STATUS_IS_OK(status)) {
182                         goto error;
183                 }
184
185                 classes[i] = NULL;
186
187                 if (class_buf.name &&
188                     (!(classes[i] = talloc_strdup(classes, class_buf.name)))) {
189                         status = NT_STATUS_NO_MEMORY;
190                         goto error;
191                 }
192
193                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
194                         status = NT_STATUS_NO_MEMORY;
195                         goto error;
196                 }
197
198                 if ((!(modtimes[i] = (NTTIME *)talloc_memdup(
199                                modtimes, &modtime, sizeof(modtime))))) {
200                         status = NT_STATUS_NO_MEMORY;
201                         goto error;
202                 }
203         }
204
205         *pnum_keys = num_subkeys;
206
207         if (pnames) {
208                 *pnames = talloc_move(ctx, &names);
209         }
210         if (pclasses) {
211                 *pclasses = talloc_move(ctx, &classes);
212         }
213         if (pmodtimes) {
214                 *pmodtimes = talloc_move(ctx, &modtimes);
215         }
216
217         status = NT_STATUS_OK;
218
219  error:
220         TALLOC_FREE(mem_ctx);
221         return status;
222 }
223
224 static NTSTATUS registry_enumvalues(TALLOC_CTX *ctx,
225                                     struct rpc_pipe_client *pipe_hnd,
226                                     struct policy_handle *key_hnd,
227                                     uint32 *pnum_values, char ***pvalnames,
228                                     struct registry_value ***pvalues)
229 {
230         TALLOC_CTX *mem_ctx;
231         NTSTATUS status;
232         uint32 num_subkeys, max_subkeylen, max_classlen;
233         uint32 num_values, max_valnamelen, max_valbufsize;
234         uint32 i;
235         NTTIME last_changed_time;
236         uint32 secdescsize;
237         struct winreg_String classname;
238         struct registry_value **values;
239         char **names;
240
241         if (!(mem_ctx = talloc_new(ctx))) {
242                 return NT_STATUS_NO_MEMORY;
243         }
244
245         ZERO_STRUCT(classname);
246         status = rpccli_winreg_QueryInfoKey(
247                 pipe_hnd, mem_ctx, key_hnd, &classname, &num_subkeys,
248                 &max_subkeylen, &max_classlen, &num_values, &max_valnamelen,
249                 &max_valbufsize, &secdescsize, &last_changed_time, NULL );
250
251         if (!NT_STATUS_IS_OK(status)) {
252                 goto error;
253         }
254
255         if (num_values == 0) {
256                 *pnum_values = 0;
257                 TALLOC_FREE(mem_ctx);
258                 return NT_STATUS_OK;
259         }
260
261         if ((!(names = TALLOC_ARRAY(mem_ctx, char *, num_values))) ||
262             (!(values = TALLOC_ARRAY(mem_ctx, struct registry_value *,
263                                      num_values)))) {
264                 status = NT_STATUS_NO_MEMORY;
265                 goto error;
266         }
267
268         for (i=0; i<num_values; i++) {
269                 enum winreg_Type type = REG_NONE;
270                 uint8 *data = NULL;
271                 uint32 data_size;
272                 uint32 value_length;
273
274                 char n;
275                 struct winreg_ValNameBuf name_buf;
276                 WERROR err;
277
278                 n = '\0';
279                 name_buf.name = &n;
280                 name_buf.size = max_valnamelen + 2;
281
282                 data_size = max_valbufsize;
283                 data = (uint8 *)TALLOC(mem_ctx, data_size);
284                 value_length = 0;
285
286                 status = rpccli_winreg_EnumValue(pipe_hnd, mem_ctx, key_hnd,
287                                                  i, &name_buf, &type,
288                                                  data, &data_size,
289                                                  &value_length, &err);
290
291                 if ( W_ERROR_EQUAL(err,
292                                    WERR_NO_MORE_ITEMS) ) {
293                         status = NT_STATUS_OK;
294                         break;
295                 }
296
297                 if (!(NT_STATUS_IS_OK(status))) {
298                         goto error;
299                 }
300
301                 if (name_buf.name == NULL) {
302                         status = NT_STATUS_INVALID_PARAMETER;
303                         goto error;
304                 }
305
306                 if (!(names[i] = talloc_strdup(names, name_buf.name))) {
307                         status = NT_STATUS_NO_MEMORY;
308                         goto error;
309                 }
310
311                 err = registry_pull_value(values, &values[i], type, data,
312                                           data_size, value_length);
313                 if (!W_ERROR_IS_OK(err)) {
314                         status = werror_to_ntstatus(err);
315                         goto error;
316                 }
317         }
318
319         *pnum_values = num_values;
320
321         if (pvalnames) {
322                 *pvalnames = talloc_move(ctx, &names);
323         }
324         if (pvalues) {
325                 *pvalues = talloc_move(ctx, &values);
326         }
327
328         status = NT_STATUS_OK;
329
330  error:
331         TALLOC_FREE(mem_ctx);
332         return status;
333 }
334
335 static NTSTATUS registry_getsd(TALLOC_CTX *mem_ctx,
336                                struct rpc_pipe_client *pipe_hnd,
337                                struct policy_handle *key_hnd,
338                                uint32_t sec_info,
339                                struct KeySecurityData *sd)
340 {
341         return rpccli_winreg_GetKeySecurity(pipe_hnd, mem_ctx, key_hnd,
342                                             sec_info, sd, NULL);
343 }
344
345
346 static NTSTATUS registry_setvalue(TALLOC_CTX *mem_ctx,
347                                   struct rpc_pipe_client *pipe_hnd,
348                                   struct policy_handle *key_hnd,
349                                   const char *name,
350                                   const struct registry_value *value)
351 {
352         struct winreg_String name_string;
353         DATA_BLOB blob;
354         NTSTATUS result;
355         WERROR err;
356
357         err = registry_push_value(mem_ctx, value, &blob);
358         if (!W_ERROR_IS_OK(err)) {
359                 return werror_to_ntstatus(err);
360         }
361
362         ZERO_STRUCT(name_string);
363
364         name_string.name = name;
365         result = rpccli_winreg_SetValue(pipe_hnd, blob.data, key_hnd,
366                                         name_string, value->type,
367                                         blob.data, blob.length, NULL);
368         TALLOC_FREE(blob.data);
369         return result;
370 }
371
372 static NTSTATUS rpc_registry_setvalue_internal(struct net_context *c,
373                                                const DOM_SID *domain_sid,
374                                                const char *domain_name,
375                                                struct cli_state *cli,
376                                                struct rpc_pipe_client *pipe_hnd,
377                                                TALLOC_CTX *mem_ctx,
378                                                int argc,
379                                                const char **argv )
380 {
381         struct policy_handle hive_hnd, key_hnd;
382         NTSTATUS status;
383         struct registry_value value;
384
385         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
386                                   SEC_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, "usage: net rpc registry createkey <key>\n");
702                 return -1;
703         }
704
705         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
706                 rpc_registry_createkey_internal, argc, argv );
707 }
708
709 static NTSTATUS rpc_registry_deletekey_internal(struct net_context *c,
710                                                 const DOM_SID *domain_sid,
711                                                 const char *domain_name,
712                                                 struct cli_state *cli,
713                                                 struct rpc_pipe_client *pipe_hnd,
714                                                 TALLOC_CTX *mem_ctx,
715                                                 int argc,
716                                                 const char **argv )
717 {
718         uint32 hive;
719         struct policy_handle hive_hnd;
720         struct winreg_String key;
721         NTSTATUS status;
722
723         ZERO_STRUCT(key);
724
725         if (!reg_hive_key(mem_ctx, argv[0], &hive, &key.name)) {
726                 return NT_STATUS_INVALID_PARAMETER;
727         }
728
729         status = rpccli_winreg_Connect(pipe_hnd, mem_ctx, hive,
730                                        SEC_FLAG_MAXIMUM_ALLOWED,
731                                        &hive_hnd);
732         if (!(NT_STATUS_IS_OK(status))) {
733                 return status;
734         }
735
736         status = rpccli_winreg_DeleteKey(pipe_hnd, mem_ctx, &hive_hnd, key, NULL);
737         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &hive_hnd, NULL);
738
739         if (!NT_STATUS_IS_OK(status)) {
740                 d_fprintf(stderr, "deletekey returned %s\n",
741                           nt_errstr(status));
742         }
743
744         return status;
745 }
746
747 static int rpc_registry_deletekey(struct net_context *c, int argc, const char **argv )
748 {
749         if (argc != 1 || c->display_usage) {
750                 d_fprintf(stderr, "usage: net rpc registry deletekey <key>\n");
751                 return -1;
752         }
753
754         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
755                 rpc_registry_deletekey_internal, argc, argv );
756 }
757
758 /********************************************************************
759 ********************************************************************/
760
761 static NTSTATUS rpc_registry_enumerate_internal(struct net_context *c,
762                                                 const DOM_SID *domain_sid,
763                                                 const char *domain_name,
764                                                 struct cli_state *cli,
765                                                 struct rpc_pipe_client *pipe_hnd,
766                                                 TALLOC_CTX *mem_ctx,
767                                                 int argc,
768                                                 const char **argv )
769 {
770         struct policy_handle pol_hive, pol_key;
771         NTSTATUS status;
772         uint32 num_subkeys = 0;
773         uint32 num_values = 0;
774         char **names = NULL, **classes = NULL;
775         NTTIME **modtimes = NULL;
776         uint32 i;
777         struct registry_value **values = NULL;
778
779         if (argc != 1 || c->display_usage) {
780                 d_printf("Usage:    net rpc registry enumerate <path>\n");
781                 d_printf("Example:  net rpc registry enumerate 'HKLM\\Software\\Samba'\n");
782                 return NT_STATUS_INVALID_PARAMETER;
783         }
784
785         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_READ,
786                                   &pol_hive, &pol_key);
787         if (!NT_STATUS_IS_OK(status)) {
788                 d_fprintf(stderr, "registry_openkey failed: %s\n",
789                           nt_errstr(status));
790                 return status;
791         }
792
793         status = registry_enumkeys(mem_ctx, pipe_hnd, &pol_key, &num_subkeys,
794                                    &names, &classes, &modtimes);
795         if (!NT_STATUS_IS_OK(status)) {
796                 d_fprintf(stderr, "enumerating keys failed: %s\n",
797                           nt_errstr(status));
798                 return status;
799         }
800
801         for (i=0; i<num_subkeys; i++) {
802                 print_registry_key(names[i], modtimes[i]);
803         }
804
805         status = registry_enumvalues(mem_ctx, pipe_hnd, &pol_key, &num_values,
806                                      &names, &values);
807         if (!NT_STATUS_IS_OK(status)) {
808                 d_fprintf(stderr, "enumerating values failed: %s\n",
809                           nt_errstr(status));
810                 return status;
811         }
812
813         for (i=0; i<num_values; i++) {
814                 print_registry_value_with_name(names[i], values[i]);
815         }
816
817         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
818         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
819
820         return status;
821 }
822
823 /********************************************************************
824 ********************************************************************/
825
826 static int rpc_registry_enumerate(struct net_context *c, int argc,
827                                   const char **argv )
828 {
829         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
830                 rpc_registry_enumerate_internal, argc, argv );
831 }
832
833 /********************************************************************
834 ********************************************************************/
835
836 static NTSTATUS rpc_registry_save_internal(struct net_context *c,
837                                         const DOM_SID *domain_sid,
838                                         const char *domain_name,
839                                         struct cli_state *cli,
840                                         struct rpc_pipe_client *pipe_hnd,
841                                         TALLOC_CTX *mem_ctx,
842                                         int argc,
843                                         const char **argv )
844 {
845         WERROR result = WERR_GENERAL_FAILURE;
846         struct policy_handle pol_hive, pol_key;
847         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
848         struct winreg_String filename;
849
850         if (argc != 2 || c->display_usage) {
851                 d_printf("Usage:    net rpc registry backup <path> <file> \n");
852                 return NT_STATUS_INVALID_PARAMETER;
853         }
854
855         status = registry_openkey(mem_ctx, pipe_hnd, argv[0], REG_KEY_ALL,
856                                   &pol_hive, &pol_key);
857         if (!NT_STATUS_IS_OK(status)) {
858                 d_fprintf(stderr, "registry_openkey failed: %s\n",
859                           nt_errstr(status));
860                 return status;
861         }
862
863         filename.name = argv[1];
864         status = rpccli_winreg_SaveKey( pipe_hnd, mem_ctx, &pol_key, &filename, NULL, NULL);
865         if ( !W_ERROR_IS_OK(result) ) {
866                 d_fprintf(stderr, "Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
867         }
868
869         /* cleanup */
870
871         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
872         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
873
874         return status;
875 }
876
877 /********************************************************************
878 ********************************************************************/
879
880 static int rpc_registry_save(struct net_context *c, int argc, const char **argv )
881 {
882         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
883                 rpc_registry_save_internal, argc, argv );
884 }
885
886
887 /********************************************************************
888 ********************************************************************/
889
890 static void dump_values( REGF_NK_REC *nk )
891 {
892         int i, j;
893         char *data_str = NULL;
894         uint32 data_size, data;
895
896         if ( !nk->values )
897                 return;
898
899         for ( i=0; i<nk->num_values; i++ ) {
900                 d_printf( "\"%s\" = ", nk->values[i].valuename ? nk->values[i].valuename : "(default)" );
901                 d_printf( "(%s) ", reg_type_lookup( nk->values[i].type ) );
902
903                 data_size = nk->values[i].data_size & ~VK_DATA_IN_OFFSET;
904                 switch ( nk->values[i].type ) {
905                         case REG_SZ:
906                                 rpcstr_pull_talloc(talloc_tos(),
907                                                 &data_str,
908                                                 nk->values[i].data,
909                                                 -1,
910                                                 STR_TERMINATE);
911                                 if (!data_str) {
912                                         break;
913                                 }
914                                 d_printf( "%s", data_str );
915                                 break;
916                         case REG_MULTI_SZ:
917                         case REG_EXPAND_SZ:
918                                 for ( j=0; j<data_size; j++ ) {
919                                         d_printf( "%c", nk->values[i].data[j] );
920                                 }
921                                 break;
922                         case REG_DWORD:
923                                 data = IVAL( nk->values[i].data, 0 );
924                                 d_printf("0x%x", data );
925                                 break;
926                         case REG_BINARY:
927                                 for ( j=0; j<data_size; j++ ) {
928                                         d_printf( "%x", nk->values[i].data[j] );
929                                 }
930                                 break;
931                         default:
932                                 d_printf("unknown");
933                                 break;
934                 }
935
936                 d_printf( "\n" );
937         }
938
939 }
940
941 /********************************************************************
942 ********************************************************************/
943
944 static bool dump_registry_tree( REGF_FILE *file, REGF_NK_REC *nk, const char *parent )
945 {
946         REGF_NK_REC *key;
947
948         /* depth first dump of the registry tree */
949
950         while ( (key = regfio_fetch_subkey( file, nk )) ) {
951                 char *regpath;
952                 if (asprintf(&regpath, "%s\\%s", parent, key->keyname) < 0) {
953                         break;
954                 }
955                 d_printf("[%s]\n", regpath );
956                 dump_values( key );
957                 d_printf("\n");
958                 dump_registry_tree( file, key, regpath );
959                 SAFE_FREE(regpath);
960         }
961
962         return true;
963 }
964
965 /********************************************************************
966 ********************************************************************/
967
968 static bool write_registry_tree( REGF_FILE *infile, REGF_NK_REC *nk,
969                                  REGF_NK_REC *parent, REGF_FILE *outfile,
970                                  const char *parentpath )
971 {
972         REGF_NK_REC *key, *subkey;
973         struct regval_ctr *values = NULL;
974         struct regsubkey_ctr *subkeys = NULL;
975         int i;
976         char *path = NULL;
977         WERROR werr;
978
979         werr = regsubkey_ctr_init(infile->mem_ctx, &subkeys);
980         if (!W_ERROR_IS_OK(werr)) {
981                 DEBUG(0, ("write_registry_tree: regsubkey_ctr_init failed: "
982                           "%s\n", win_errstr(werr)));
983                 return false;
984         }
985
986         if ( !(values = TALLOC_ZERO_P( subkeys, struct regval_ctr )) ) {
987                 DEBUG(0,("write_registry_tree: talloc() failed!\n"));
988                 TALLOC_FREE(subkeys);
989                 return false;
990         }
991
992         /* copy values into the struct regval_ctr */
993
994         for ( i=0; i<nk->num_values; i++ ) {
995                 regval_ctr_addvalue( values, nk->values[i].valuename, nk->values[i].type,
996                         (const char *)nk->values[i].data, (nk->values[i].data_size & ~VK_DATA_IN_OFFSET) );
997         }
998
999         /* copy subkeys into the struct regsubkey_ctr */
1000
1001         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1002                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
1003         }
1004
1005         key = regfio_write_key( outfile, nk->keyname, values, subkeys, nk->sec_desc->sec_desc, parent );
1006
1007         /* write each one of the subkeys out */
1008
1009         path = talloc_asprintf(subkeys,
1010                         "%s%s%s",
1011                         parentpath,
1012                         parent ? "\\" : "",
1013                         nk->keyname);
1014         if (!path) {
1015                 TALLOC_FREE(subkeys);
1016                 return false;
1017         }
1018
1019         nk->subkey_index = 0;
1020         while ( (subkey = regfio_fetch_subkey( infile, nk )) ) {
1021                 write_registry_tree( infile, subkey, key, outfile, path );
1022         }
1023
1024         d_printf("[%s]\n", path );
1025         TALLOC_FREE(subkeys);
1026
1027         return true;
1028 }
1029
1030 /********************************************************************
1031 ********************************************************************/
1032
1033 static int rpc_registry_dump(struct net_context *c, int argc, const char **argv)
1034 {
1035         REGF_FILE   *registry;
1036         REGF_NK_REC *nk;
1037
1038         if (argc != 1 || c->display_usage) {
1039                 d_printf("Usage:    net rpc registry dump <file> \n");
1040                 return -1;
1041         }
1042
1043         d_printf("Opening %s....", argv[0]);
1044         if ( !(registry = regfio_open( argv[0], O_RDONLY, 0)) ) {
1045                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
1046                 return 1;
1047         }
1048         d_printf("ok\n");
1049
1050         /* get the root of the registry file */
1051
1052         if ((nk = regfio_rootkey( registry )) == NULL) {
1053                 d_fprintf(stderr, "Could not get rootkey\n");
1054                 regfio_close( registry );
1055                 return 1;
1056         }
1057         d_printf("[%s]\n", nk->keyname);
1058         dump_values( nk );
1059         d_printf("\n");
1060
1061         dump_registry_tree( registry, nk, nk->keyname );
1062
1063 #if 0
1064         talloc_report_full( registry->mem_ctx, stderr );
1065 #endif
1066         d_printf("Closing registry...");
1067         regfio_close( registry );
1068         d_printf("ok\n");
1069
1070         return 0;
1071 }
1072
1073 /********************************************************************
1074 ********************************************************************/
1075
1076 static int rpc_registry_copy(struct net_context *c, int argc, const char **argv )
1077 {
1078         REGF_FILE   *infile = NULL, *outfile = NULL;
1079         REGF_NK_REC *nk;
1080         int result = 1;
1081
1082         if (argc != 2 || c->display_usage) {
1083                 d_printf("Usage:    net rpc registry copy <srcfile> <newfile>\n");
1084                 return -1;
1085         }
1086
1087         d_printf("Opening %s....", argv[0]);
1088         if ( !(infile = regfio_open( argv[0], O_RDONLY, 0 )) ) {
1089                 d_fprintf(stderr, "Failed to open %s for reading\n", argv[0]);
1090                 return 1;
1091         }
1092         d_printf("ok\n");
1093
1094         d_printf("Opening %s....", argv[1]);
1095         if ( !(outfile = regfio_open( argv[1], (O_RDWR|O_CREAT|O_TRUNC), (S_IREAD|S_IWRITE) )) ) {
1096                 d_fprintf(stderr, "Failed to open %s for writing\n", argv[1]);
1097                 goto out;
1098         }
1099         d_printf("ok\n");
1100
1101         /* get the root of the registry file */
1102
1103         if ((nk = regfio_rootkey( infile )) == NULL) {
1104                 d_fprintf(stderr, "Could not get rootkey\n");
1105                 goto out;
1106         }
1107         d_printf("RootKey: [%s]\n", nk->keyname);
1108
1109         write_registry_tree( infile, nk, NULL, outfile, "" );
1110
1111         result = 0;
1112
1113 out:
1114
1115         d_printf("Closing %s...", argv[1]);
1116         if (outfile) {
1117                 regfio_close( outfile );
1118         }
1119         d_printf("ok\n");
1120
1121         d_printf("Closing %s...", argv[0]);
1122         if (infile) {
1123                 regfio_close( infile );
1124         }
1125         d_printf("ok\n");
1126
1127         return( result);
1128 }
1129
1130 /********************************************************************
1131 ********************************************************************/
1132
1133 static NTSTATUS rpc_registry_getsd_internal(struct net_context *c,
1134                                             const DOM_SID *domain_sid,
1135                                             const char *domain_name,
1136                                             struct cli_state *cli,
1137                                             struct rpc_pipe_client *pipe_hnd,
1138                                             TALLOC_CTX *mem_ctx,
1139                                             int argc,
1140                                             const char **argv)
1141 {
1142         struct policy_handle pol_hive, pol_key;
1143         NTSTATUS status;
1144         enum ndr_err_code ndr_err;
1145         struct KeySecurityData *sd = NULL;
1146         uint32_t sec_info;
1147         DATA_BLOB blob;
1148         struct security_descriptor sec_desc;
1149         uint32_t access_mask = REG_KEY_READ |
1150                                SEC_FLAG_MAXIMUM_ALLOWED |
1151                                SEC_FLAG_SYSTEM_SECURITY;
1152
1153         if (argc <1 || argc > 2 || c->display_usage) {
1154                 d_printf("Usage:    net rpc registry getsd <path> <secinfo>\n");
1155                 d_printf("Example:  net rpc registry getsd 'HKLM\\Software\\Samba'\n");
1156                 return NT_STATUS_INVALID_PARAMETER;
1157         }
1158
1159         status = registry_openkey(mem_ctx, pipe_hnd, argv[0],
1160                                   access_mask,
1161                                   &pol_hive, &pol_key);
1162         if (!NT_STATUS_IS_OK(status)) {
1163                 d_fprintf(stderr, "registry_openkey failed: %s\n",
1164                           nt_errstr(status));
1165                 return status;
1166         }
1167
1168         sd = TALLOC_ZERO_P(mem_ctx, struct KeySecurityData);
1169         if (!sd) {
1170                 status = NT_STATUS_NO_MEMORY;
1171                 goto out;
1172         }
1173
1174         sd->size = 0x1000;
1175
1176         if (argc >= 2) {
1177                 sscanf(argv[1], "%x", &sec_info);
1178         } else {
1179                 sec_info = SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL;
1180         }
1181
1182         status = registry_getsd(mem_ctx, pipe_hnd, &pol_key, sec_info, sd);
1183         if (!NT_STATUS_IS_OK(status)) {
1184                 d_fprintf(stderr, "getting sd failed: %s\n",
1185                           nt_errstr(status));
1186                 goto out;
1187         }
1188
1189         blob.data = sd->data;
1190         blob.length = sd->size;
1191
1192         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &sec_desc,
1193                                        (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
1194         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1195                 status = ndr_map_error2ntstatus(ndr_err);
1196                 goto out;
1197         }
1198         status = NT_STATUS_OK;
1199
1200         display_sec_desc(&sec_desc);
1201
1202  out:
1203         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_key, NULL);
1204         rpccli_winreg_CloseKey(pipe_hnd, mem_ctx, &pol_hive, NULL);
1205
1206         return status;
1207 }
1208
1209
1210 static int rpc_registry_getsd(struct net_context *c, int argc, const char **argv)
1211 {
1212         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
1213                 rpc_registry_getsd_internal, argc, argv);
1214 }
1215
1216 /********************************************************************
1217 ********************************************************************/
1218
1219 int net_rpc_registry(struct net_context *c, int argc, const char **argv)
1220 {
1221         struct functable func[] = {
1222                 {
1223                         "enumerate",
1224                         rpc_registry_enumerate,
1225                         NET_TRANSPORT_RPC,
1226                         "Enumerate registry keys and values",
1227                         "net rpc registry enumerate\n"
1228                         "    Enumerate registry keys and values"
1229                 },
1230                 {
1231                         "createkey",
1232                         rpc_registry_createkey,
1233                         NET_TRANSPORT_RPC,
1234                         "Create a new registry key",
1235                         "net rpc registry createkey\n"
1236                         "    Create a new registry key"
1237                 },
1238                 {
1239                         "deletekey",
1240                         rpc_registry_deletekey,
1241                         NET_TRANSPORT_RPC,
1242                         "Delete a registry key",
1243                         "net rpc registry deletekey\n"
1244                         "    Delete a registry key"
1245                 },
1246                 {
1247                         "getvalue",
1248                         rpc_registry_getvalue,
1249                         NET_TRANSPORT_RPC,
1250                         "Print a registry value",
1251                         "net rpc registry getvalue\n"
1252                         "    Print a registry value"
1253                 },
1254                 {
1255                         "getvalueraw",
1256                         rpc_registry_getvalueraw,
1257                         NET_TRANSPORT_RPC,
1258                         "Print a registry value",
1259                         "net rpc registry getvalueraw\n"
1260                         "    Print a registry value (raw version)"
1261                 },
1262                 {
1263                         "setvalue",
1264                         rpc_registry_setvalue,
1265                         NET_TRANSPORT_RPC,
1266                         "Set a new registry value",
1267                         "net rpc registry setvalue\n"
1268                         "    Set a new registry value"
1269                 },
1270                 {
1271                         "deletevalue",
1272                         rpc_registry_deletevalue,
1273                         NET_TRANSPORT_RPC,
1274                         "Delete a registry value",
1275                         "net rpc registry deletevalue\n"
1276                         "    Delete a registry value"
1277                 },
1278                 {
1279                         "save",
1280                         rpc_registry_save,
1281                         NET_TRANSPORT_RPC,
1282                         "Save a registry file",
1283                         "net rpc registry save\n"
1284                         "    Save a registry file"
1285                 },
1286                 {
1287                         "dump",
1288                         rpc_registry_dump,
1289                         NET_TRANSPORT_RPC,
1290                         "Dump a registry file",
1291                         "net rpc registry dump\n"
1292                         "    Dump a registry file"
1293                 },
1294                 {
1295                         "copy",
1296                         rpc_registry_copy,
1297                         NET_TRANSPORT_RPC,
1298                         "Copy a registry file",
1299                         "net rpc registry copy\n"
1300                         "    Copy a registry file"
1301                 },
1302                 {
1303                         "getsd",
1304                         rpc_registry_getsd,
1305                         NET_TRANSPORT_RPC,
1306                         "Get security descriptor",
1307                         "net rpc registry getsd\n"
1308                         "    Get security descriptior"
1309                 },
1310                 {NULL, NULL, 0, NULL, NULL}
1311         };
1312
1313         return net_run_function(c, argc, argv, "net rpc registry", func);
1314 }