s3-net: add command registry convert
[obnox/samba-ctdb.git] / source3 / utils / net_registry.c
1 /*
2  * Samba Unix/Linux SMB client library
3  * Distributed SMB/CIFS Server Management Utility
4  * Local registry interface
5  *
6  * Copyright (C) Michael Adam 2008
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include "includes.h"
23 #include "utils/net.h"
24 #include "utils/net_registry_util.h"
25 #include "include/g_lock.h"
26 #include "registry/reg_import.h"
27 #include "registry/reg_format.h"
28 #include <assert.h>
29
30 /*
31  *
32  * Helper functions
33  *
34  */
35
36 /**
37  * split given path into hive and remaining path and open the hive key
38  */
39 static WERROR open_hive(TALLOC_CTX *ctx, const char *path,
40                         uint32 desired_access,
41                         struct registry_key **hive,
42                         char **subkeyname)
43 {
44         WERROR werr;
45         NT_USER_TOKEN *token = NULL;
46         char *hivename = NULL;
47         char *tmp_subkeyname = NULL;
48         TALLOC_CTX *tmp_ctx = talloc_stackframe();
49
50         if ((hive == NULL) || (subkeyname == NULL)) {
51                 werr = WERR_INVALID_PARAM;
52                 goto done;
53         }
54
55         werr = split_hive_key(tmp_ctx, path, &hivename, &tmp_subkeyname);
56         if (!W_ERROR_IS_OK(werr)) {
57                 goto done;
58         }
59         *subkeyname = talloc_strdup(ctx, tmp_subkeyname);
60         if (*subkeyname == NULL) {
61                 werr = WERR_NOMEM;
62                 goto done;
63         }
64
65         werr = ntstatus_to_werror(registry_create_admin_token(tmp_ctx, &token));
66         if (!W_ERROR_IS_OK(werr)) {
67                 goto done;
68         }
69
70         werr = reg_openhive(ctx, hivename, desired_access, token, hive);
71         if (!W_ERROR_IS_OK(werr)) {
72                 goto done;
73         }
74
75         werr = WERR_OK;
76
77 done:
78         TALLOC_FREE(tmp_ctx);
79         return werr;
80 }
81
82 static WERROR open_key(TALLOC_CTX *ctx, const char *path,
83                        uint32 desired_access,
84                        struct registry_key **key)
85 {
86         WERROR werr;
87         char *subkey_name = NULL;
88         struct registry_key *hive = NULL;
89         TALLOC_CTX *tmp_ctx = talloc_stackframe();
90
91         if ((path == NULL) || (key == NULL)) {
92                 return WERR_INVALID_PARAM;
93         }
94
95         werr = open_hive(tmp_ctx, path, desired_access, &hive, &subkey_name);
96         if (!W_ERROR_IS_OK(werr)) {
97                 d_fprintf(stderr, "open_hive failed: %s\n", win_errstr(werr));
98                 goto done;
99         }
100
101         werr = reg_openkey(ctx, hive, subkey_name, desired_access, key);
102         if (!W_ERROR_IS_OK(werr)) {
103                 d_fprintf(stderr, "reg_openkey failed: %s\n",
104                           win_errstr(werr));
105                 goto done;
106         }
107
108         werr = WERR_OK;
109
110 done:
111         TALLOC_FREE(tmp_ctx);
112         return werr;
113 }
114
115 /*
116  *
117  * the main "net registry" function implementations
118  *
119  */
120
121 static int net_registry_enumerate(struct net_context *c, int argc,
122                                   const char **argv)
123 {
124         WERROR werr;
125         struct registry_key *key = NULL;
126         TALLOC_CTX *ctx = talloc_stackframe();
127         char *subkey_name;
128         NTTIME modtime;
129         uint32_t count;
130         char *valname = NULL;
131         struct registry_value *valvalue = NULL;
132         int ret = -1;
133
134         if (argc != 1 || c->display_usage) {
135                 d_printf("Usage:    net registry enumerate <path>\n");
136                 d_printf("Example:  net registry enumerate "
137                          "'HKLM\\Software\\Samba'\n");
138                 goto done;
139         }
140
141         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
142         if (!W_ERROR_IS_OK(werr)) {
143                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
144                 goto done;
145         }
146
147         for (count = 0;
148              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
149              W_ERROR_IS_OK(werr);
150              count++)
151         {
152                 print_registry_key(subkey_name, &modtime);
153         }
154         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
155                 goto done;
156         }
157
158         for (count = 0;
159              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
160              W_ERROR_IS_OK(werr);
161              count++)
162         {
163                 print_registry_value_with_name(valname, valvalue);
164         }
165         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
166                 goto done;
167         }
168
169         ret = 0;
170 done:
171         TALLOC_FREE(ctx);
172         return ret;
173 }
174
175 static int net_registry_createkey(struct net_context *c, int argc,
176                                   const char **argv)
177 {
178         WERROR werr;
179         enum winreg_CreateAction action;
180         char *subkeyname;
181         struct registry_key *hivekey = NULL;
182         struct registry_key *subkey = NULL;
183         TALLOC_CTX *ctx = talloc_stackframe();
184         int ret = -1;
185
186         if (argc != 1 || c->display_usage) {
187                 d_printf("Usage:    net registry createkey <path>\n");
188                 d_printf("Example:  net registry createkey "
189                          "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n");
190                 goto done;
191         }
192         if (strlen(argv[0]) == 0) {
193                 d_fprintf(stderr, "error: zero length key name given\n");
194                 goto done;
195         }
196
197         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
198         if (!W_ERROR_IS_OK(werr)) {
199                 d_fprintf(stderr, "open_hive failed: %s\n", win_errstr(werr));
200                 goto done;
201         }
202
203         werr = reg_createkey(ctx, hivekey, subkeyname, REG_KEY_WRITE,
204                              &subkey, &action);
205         if (!W_ERROR_IS_OK(werr)) {
206                 d_fprintf(stderr, "reg_createkey failed: %s\n",
207                           win_errstr(werr));
208                 goto done;
209         }
210         switch (action) {
211                 case REG_ACTION_NONE:
212                         d_printf("createkey did nothing -- huh?\n");
213                         break;
214                 case REG_CREATED_NEW_KEY:
215                         d_printf("createkey created %s\n", argv[0]);
216                         break;
217                 case REG_OPENED_EXISTING_KEY:
218                         d_printf("createkey opened existing %s\n", argv[0]);
219                         break;
220         }
221
222         ret = 0;
223
224 done:
225         TALLOC_FREE(ctx);
226         return ret;
227 }
228
229 static int net_registry_deletekey(struct net_context *c, int argc,
230                                   const char **argv)
231 {
232         WERROR werr;
233         char *subkeyname;
234         struct registry_key *hivekey = NULL;
235         TALLOC_CTX *ctx = talloc_stackframe();
236         int ret = -1;
237
238         if (argc != 1 || c->display_usage) {
239                 d_printf("Usage:    net registry deletekey <path>\n");
240                 d_printf("Example:  net registry deletekey "
241                          "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n");
242                 goto done;
243         }
244         if (strlen(argv[0]) == 0) {
245                 d_fprintf(stderr, "error: zero length key name given\n");
246                 goto done;
247         }
248
249         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
250         if (!W_ERROR_IS_OK(werr)) {
251                 d_fprintf(stderr, "open_hive failed: %s\n", win_errstr(werr));
252                 goto done;
253         }
254
255         werr = reg_deletekey(hivekey, subkeyname);
256         if (!W_ERROR_IS_OK(werr)) {
257                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
258                           win_errstr(werr));
259                 goto done;
260         }
261
262         ret = 0;
263
264 done:
265         TALLOC_FREE(ctx);
266         return ret;
267 }
268
269 static int net_registry_getvalue_internal(struct net_context *c, int argc,
270                                           const char **argv, bool raw)
271 {
272         WERROR werr;
273         int ret = -1;
274         struct registry_key *key = NULL;
275         struct registry_value *value = NULL;
276         TALLOC_CTX *ctx = talloc_stackframe();
277
278         if (argc != 2 || c->display_usage) {
279                 d_fprintf(stderr, "usage: net rpc registry getvalue <key> "
280                                   "<valuename>\n");
281                 goto done;
282         }
283
284         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
285         if (!W_ERROR_IS_OK(werr)) {
286                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
287                 goto done;
288         }
289
290         werr = reg_queryvalue(ctx, key, argv[1], &value);
291         if (!W_ERROR_IS_OK(werr)) {
292                 d_fprintf(stderr, "reg_queryvalue failed: %s\n",
293                           win_errstr(werr));
294                 goto done;
295         }
296
297         print_registry_value(value, raw);
298
299         ret = 0;
300
301 done:
302         TALLOC_FREE(ctx);
303         return ret;
304 }
305
306 static int net_registry_getvalue(struct net_context *c, int argc,
307                                  const char **argv)
308 {
309         return net_registry_getvalue_internal(c, argc, argv, false);
310 }
311
312 static int net_registry_getvalueraw(struct net_context *c, int argc,
313                                     const char **argv)
314 {
315         return net_registry_getvalue_internal(c, argc, argv, true);
316 }
317
318 static int net_registry_getvaluesraw(struct net_context *c, int argc,
319                                      const char **argv)
320 {
321         WERROR werr;
322         int ret = -1;
323         struct registry_key *key = NULL;
324         TALLOC_CTX *ctx = talloc_stackframe();
325         uint32_t idx;
326
327         if (argc != 1 || c->display_usage) {
328                 d_fprintf(stderr, "usage: net rpc registry getvaluesraw "
329                           "<key>\n");
330                 goto done;
331         }
332
333         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
334         if (!W_ERROR_IS_OK(werr)) {
335                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
336                 goto done;
337         }
338
339         idx = 0;
340         while (true) {
341                 struct registry_value *val;
342
343                 werr = reg_enumvalue(talloc_tos(), key, idx, NULL, &val);
344
345                 if (W_ERROR_EQUAL(werr, WERR_NO_MORE_ITEMS)) {
346                         ret = 0;
347                         break;
348                 }
349                 if (!W_ERROR_IS_OK(werr)) {
350                         break;
351                 }
352                 print_registry_value(val, true);
353                 TALLOC_FREE(val);
354                 idx += 1;
355         }
356 done:
357         TALLOC_FREE(ctx);
358         return ret;
359 }
360
361 static int net_registry_setvalue(struct net_context *c, int argc,
362                                  const char **argv)
363 {
364         WERROR werr;
365         struct registry_value value;
366         struct registry_key *key = NULL;
367         int ret = -1;
368         TALLOC_CTX *ctx = talloc_stackframe();
369
370         if (argc < 4 || c->display_usage) {
371                 d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
372                           "<valuename> <type> [<val>]+\n");
373                 goto done;
374         }
375
376         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
377                 d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
378                 goto done;
379         }
380
381         if (strequal(argv[2], "dword")) {
382                 value.type = REG_DWORD;
383                 value.v.dword = strtoul(argv[3], NULL, 10);
384         } else if (strequal(argv[2], "sz")) {
385                 value.type = REG_SZ;
386                 value.v.sz.len = strlen(argv[3])+1;
387                 value.v.sz.str = CONST_DISCARD(char *, argv[3]);
388         } else if (strequal(argv[2], "multi_sz")) {
389                 value.type = REG_MULTI_SZ;
390                 value.v.multi_sz.num_strings = argc - 3;
391                 value.v.multi_sz.strings = (char **)(argv + 3);
392         } else {
393                 d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
394                 goto done;
395         }
396
397         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
398         if (!W_ERROR_IS_OK(werr)) {
399                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
400                 goto done;
401         }
402
403         werr = reg_setvalue(key, argv[1], &value);
404         if (!W_ERROR_IS_OK(werr)) {
405                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
406                           win_errstr(werr));
407                 goto done;
408         }
409
410         ret = 0;
411
412 done:
413         TALLOC_FREE(ctx);
414         return ret;
415 }
416
417 struct net_registry_increment_state {
418         const char *keyname;
419         const char *valuename;
420         uint32_t increment;
421         uint32_t newvalue;
422         WERROR werr;
423 };
424
425 static void net_registry_increment_fn(void *private_data)
426 {
427         struct net_registry_increment_state *state =
428                 (struct net_registry_increment_state *)private_data;
429         struct registry_value *value;
430         struct registry_key *key = NULL;
431
432         state->werr = open_key(talloc_tos(), state->keyname,
433                                REG_KEY_READ|REG_KEY_WRITE, &key);
434         if (!W_ERROR_IS_OK(state->werr)) {
435                 d_fprintf(stderr, "open_key failed: %s\n",
436                           win_errstr(state->werr));
437                 goto done;
438         }
439
440         state->werr = reg_queryvalue(key, key, state->valuename, &value);
441         if (!W_ERROR_IS_OK(state->werr)) {
442                 d_fprintf(stderr, "reg_queryvalue failed: %s\n",
443                           win_errstr(state->werr));
444                 goto done;
445         }
446
447         if (value->type != REG_DWORD) {
448                 d_fprintf(stderr, "value not a DWORD: %s\n",
449                           reg_type_lookup(value->type));
450                 goto done;
451         }
452
453         value->v.dword += state->increment;
454         state->newvalue = value->v.dword;
455
456         state->werr = reg_setvalue(key, state->valuename, value);
457         if (!W_ERROR_IS_OK(state->werr)) {
458                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
459                           win_errstr(state->werr));
460                 goto done;
461         }
462
463 done:
464         TALLOC_FREE(key);
465         return;
466 }
467
468 static int net_registry_increment(struct net_context *c, int argc,
469                                   const char **argv)
470 {
471         struct net_registry_increment_state state;
472         NTSTATUS status;
473         int ret = -1;
474
475         if (argc < 2 || c->display_usage) {
476                 d_fprintf(stderr, "%s\n%s",
477                           "Usage:",
478                           "net registry increment <key> <valuename> "
479                           "[<increment>]\n");
480                 goto done;
481         }
482
483         state.keyname = argv[0];
484         state.valuename = argv[1];
485
486         state.increment = 1;
487         if (argc == 3) {
488                 state.increment = strtoul(argv[2], NULL, 10);
489         }
490
491         status = g_lock_do("registry_increment_lock", G_LOCK_WRITE,
492                            timeval_set(600, 0),
493                            net_registry_increment_fn, &state);
494         if (!NT_STATUS_IS_OK(status)) {
495                 d_fprintf(stderr, "g_lock_do failed: %s\n",
496                           nt_errstr(status));
497                 goto done;
498         }
499         if (!W_ERROR_IS_OK(state.werr)) {
500                 d_fprintf(stderr, "increment failed: %s\n",
501                           win_errstr(state.werr));
502                 goto done;
503         }
504
505         d_printf("new value: %u\n", (unsigned)state.newvalue);
506
507         ret = 0;
508
509 done:
510         return ret;
511 }
512
513 static int net_registry_deletevalue(struct net_context *c, int argc,
514                                     const char **argv)
515 {
516         WERROR werr;
517         struct registry_key *key = NULL;
518         TALLOC_CTX *ctx = talloc_stackframe();
519         int ret = -1;
520
521         if (argc != 2 || c->display_usage) {
522                 d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
523                           "<valuename>\n");
524                 goto done;
525         }
526
527         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
528         if (!W_ERROR_IS_OK(werr)) {
529                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
530                 goto done;
531         }
532
533         werr = reg_deletevalue(key, argv[1]);
534         if (!W_ERROR_IS_OK(werr)) {
535                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
536                           win_errstr(werr));
537                 goto done;
538         }
539
540         ret = 0;
541
542 done:
543         TALLOC_FREE(ctx);
544         return ret;
545 }
546
547 static WERROR net_registry_getsd_internal(struct net_context *c,
548                                           TALLOC_CTX *mem_ctx,
549                                           const char *keyname,
550                                           struct security_descriptor **sd)
551 {
552         WERROR werr;
553         struct registry_key *key = NULL;
554         TALLOC_CTX *ctx = talloc_stackframe();
555         uint32_t access_mask = REG_KEY_READ |
556                                SEC_FLAG_MAXIMUM_ALLOWED |
557                                SEC_FLAG_SYSTEM_SECURITY;
558
559         /*
560          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
561          * is denied with these perms right now...
562          */
563         access_mask = REG_KEY_READ;
564
565         if (sd == NULL) {
566                 d_fprintf(stderr, "internal error: invalid argument\n");
567                 werr = WERR_INVALID_PARAM;
568                 goto done;
569         }
570
571         if (strlen(keyname) == 0) {
572                 d_fprintf(stderr, "error: zero length key name given\n");
573                 werr = WERR_INVALID_PARAM;
574                 goto done;
575         }
576
577         werr = open_key(ctx, keyname, access_mask, &key);
578         if (!W_ERROR_IS_OK(werr)) {
579                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
580                 goto done;
581         }
582
583         werr = reg_getkeysecurity(mem_ctx, key, sd);
584         if (!W_ERROR_IS_OK(werr)) {
585                 d_fprintf(stderr, "reg_getkeysecurity failed: %s\n",
586                           win_errstr(werr));
587                 goto done;
588         }
589
590         werr = WERR_OK;
591
592 done:
593         TALLOC_FREE(ctx);
594         return werr;
595 }
596
597 static int net_registry_getsd(struct net_context *c, int argc,
598                               const char **argv)
599 {
600         WERROR werr;
601         int ret = -1;
602         struct security_descriptor *secdesc = NULL;
603         TALLOC_CTX *ctx = talloc_stackframe();
604
605         if (argc != 1 || c->display_usage) {
606                 d_printf("Usage:    net registry getsd <path>\n");
607                 d_printf("Example:  net registry getsd "
608                          "'HKLM\\Software\\Samba'\n");
609                 goto done;
610         }
611
612         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
613         if (!W_ERROR_IS_OK(werr)) {
614                 goto done;
615         }
616
617         display_sec_desc(secdesc);
618
619         ret = 0;
620
621 done:
622         TALLOC_FREE(ctx);
623         return ret;
624 }
625
626 static int net_registry_getsd_sddl(struct net_context *c,
627                                    int argc, const char **argv)
628 {
629         WERROR werr;
630         int ret = -1;
631         struct security_descriptor *secdesc = NULL;
632         TALLOC_CTX *ctx = talloc_stackframe();
633
634         if (argc != 1 || c->display_usage) {
635                 d_printf("Usage: net registry getsd_sddl <path>\n");
636                 d_printf("Example: net registry getsd_sddl 'HKLM\\Software\\Samba'\n");
637                 goto done;
638         }
639
640         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
641         if (!W_ERROR_IS_OK(werr)) {
642                 goto done;
643         }
644
645         d_printf("%s\n", sddl_encode(ctx, secdesc, get_global_sam_sid()));
646
647         ret = 0;
648
649 done:
650         TALLOC_FREE(ctx);
651         return ret;
652 }
653
654 static WERROR net_registry_setsd_internal(struct net_context *c,
655                                           TALLOC_CTX *mem_ctx,
656                                           const char *keyname,
657                                           struct security_descriptor *sd)
658 {
659         WERROR werr;
660         struct registry_key *key = NULL;
661         TALLOC_CTX *ctx = talloc_stackframe();
662         uint32_t access_mask = REG_KEY_WRITE |
663                                SEC_FLAG_MAXIMUM_ALLOWED |
664                                SEC_FLAG_SYSTEM_SECURITY;
665
666         /*
667          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
668          * is denied with these perms right now...
669          */
670         access_mask = REG_KEY_WRITE;
671
672         if (strlen(keyname) == 0) {
673                 d_fprintf(stderr, "error: zero length key name given\n");
674                 werr = WERR_INVALID_PARAM;
675                 goto done;
676         }
677
678         werr = open_key(ctx, keyname, access_mask, &key);
679         if (!W_ERROR_IS_OK(werr)) {
680                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
681                 goto done;
682         }
683
684         werr = reg_setkeysecurity(key, sd);
685         if (!W_ERROR_IS_OK(werr)) {
686                 d_fprintf(stderr, "reg_setkeysecurity failed: %s\n",
687                           win_errstr(werr));
688                 goto done;
689         }
690
691         werr = WERR_OK;
692
693 done:
694         TALLOC_FREE(ctx);
695         return werr;
696 }
697
698 static int net_registry_setsd_sddl(struct net_context *c,
699                                    int argc, const char **argv)
700 {
701         WERROR werr;
702         int ret = -1;
703         struct security_descriptor *secdesc = NULL;
704         TALLOC_CTX *ctx = talloc_stackframe();
705
706         if (argc != 2 || c->display_usage) {
707                 d_printf("Usage: net registry setsd_sddl <path> <security_descriptor>\n");
708                 d_printf("Example:\n"
709                          "net registry setsd_sddl 'HKLM\\Software\\Samba'\n");
710                 goto done;
711         }
712
713         secdesc = sddl_decode(ctx, argv[1], get_global_sam_sid());
714         if (secdesc == NULL) {
715                 goto done;
716         }
717
718         werr = net_registry_setsd_internal(c, ctx, argv[0], secdesc);
719         if (!W_ERROR_IS_OK(werr)) {
720                 goto done;
721         }
722
723         ret = 0;
724
725 done:
726         TALLOC_FREE(ctx);
727         return ret;
728 }
729
730 /******************************************************************************/
731 /**
732  * @defgroup net_registry net registry
733  */
734
735 /**
736  * @defgroup net_registry_import Import
737  * @ingroup net_registry
738  * @{
739  */
740
741 struct import_ctx {
742         TALLOC_CTX *mem_ctx;
743 };
744
745
746 static WERROR import_create_key(struct import_ctx* ctx,
747                                 struct registry_key* parent,
748                                 const char* name, void** pkey, bool* existing)
749 {
750         WERROR werr;
751         void* mem_ctx = talloc_new(ctx->mem_ctx);
752
753         struct registry_key* key = NULL;
754         enum winreg_CreateAction action;
755
756         if (parent == NULL) {
757                 char* subkeyname = NULL;
758                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
759                          &parent, &subkeyname);
760                 if (!W_ERROR_IS_OK(werr)) {
761                         d_fprintf(stderr, "open_hive failed: %s\n",
762                                   win_errstr(werr));
763                         goto done;
764                 }
765                 name = subkeyname;
766         }
767
768         action = REG_ACTION_NONE;
769         werr = reg_createkey(mem_ctx, parent, name, REG_KEY_WRITE,
770                              &key, &action);
771         if (!W_ERROR_IS_OK(werr)) {
772                 d_fprintf(stderr, "reg_createkey failed: %s\n",
773                           win_errstr(werr));
774                 goto done;
775         }
776
777         if (action == REG_ACTION_NONE) {
778                 d_fprintf(stderr, "createkey did nothing -- huh?\n");
779                 werr = WERR_FOOBAR;
780                 goto done;
781         }
782
783         if (existing != NULL) {
784                 *existing = (action == REG_OPENED_EXISTING_KEY);
785         }
786
787         if (pkey!=NULL) {
788                 *pkey = talloc_steal(ctx->mem_ctx, key);
789         }
790
791 done:
792         talloc_free(mem_ctx);
793         return werr;
794 }
795
796 static WERROR import_close_key(struct import_ctx* ctx,
797                                struct registry_key* key)
798 {
799         return WERR_OK;
800 }
801
802 static WERROR import_delete_key(struct import_ctx* ctx,
803                                 struct registry_key* parent, const char* name)
804 {
805         WERROR werr;
806         void* mem_ctx = talloc_new(talloc_tos());
807
808         if (parent == NULL) {
809                 char* subkeyname = NULL;
810                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
811                          &parent, &subkeyname);
812                 if (!W_ERROR_IS_OK(werr)) {
813                         d_fprintf(stderr, "open_hive failed: %s\n",
814                                   win_errstr(werr));
815                         goto done;
816                 }
817                 name = subkeyname;
818         }
819
820         werr = reg_deletekey_recursive(mem_ctx, parent, name);
821         if (!W_ERROR_IS_OK(werr)) {
822                 d_fprintf(stderr, "reg_deletekey_recursive %s: %s\n", "failed",
823                           win_errstr(werr));
824                 goto done;
825         }
826
827 done:
828         talloc_free(mem_ctx);
829         return werr;
830 }
831
832 static WERROR import_create_val (struct import_ctx* ctx,
833                                  struct registry_key* parent, const char* name,
834                                  const struct registry_value* value)
835 {
836         WERROR werr;
837
838         if (parent == NULL) {
839                 return WERR_INVALID_PARAM;
840         }
841
842         werr = reg_setvalue(parent, name, value);
843         if (!W_ERROR_IS_OK(werr)) {
844                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
845                           win_errstr(werr));
846         }
847         return werr;
848 }
849
850 static WERROR import_delete_val (struct import_ctx* ctx, struct registry_key* parent, const char* name) {
851         WERROR werr;
852
853         if (parent == NULL) {
854                 return WERR_INVALID_PARAM;
855         }
856
857         werr = reg_deletevalue(parent, name);
858         if (!W_ERROR_IS_OK(werr)) {
859                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
860                           win_errstr(werr));
861         }
862
863         return werr;
864 }
865
866
867 static int net_registry_import(struct net_context *c, int argc,
868                                const char **argv)
869 {
870         struct import_ctx import_ctx;
871         struct reg_import_callback import_callback = {
872                 .openkey     = NULL,
873                 .closekey    = (reg_import_callback_closekey_t)&import_close_key,
874                 .createkey   = (reg_import_callback_createkey_t)&import_create_key,
875                 .deletekey   = (reg_import_callback_deletekey_t)&import_delete_key,
876                 .deleteval   = (reg_import_callback_deleteval_t)&import_delete_val,
877                 .setval.registry_value = (reg_import_callback_setval_registry_value_t)
878                 &import_create_val,
879                 .setval_type           = REGISTRY_VALUE,
880                 .data        = &import_ctx
881         };
882
883         int ret;
884
885         if (argc < 1 || argc > 2 || c->display_usage) {
886                 d_printf("%s\n%s",
887                          "Usage:",
888                          "net registry import <reg> [options]\n");
889                 d_printf("%s\n%s",
890                          "Example:",
891                          "net registry import file.reg enc=CP1252\n");
892                 return -1;
893         }
894
895         ZERO_STRUCT(import_ctx);
896         import_ctx.mem_ctx = talloc_stackframe();
897
898         regdb_open();
899         regdb_transaction_start();
900
901         ret = reg_parse_file(argv[0],
902                              reg_import_adapter(import_ctx.mem_ctx,
903                                                 import_callback),
904                              (argc > 1) ? argv[1] : NULL
905                 );
906         if (ret < 0) {
907                 d_printf("reg_parse_file failed: transaction canceled\n");
908                 regdb_transaction_cancel();
909         } else{
910                 regdb_transaction_commit();
911         }
912
913         regdb_close();
914         talloc_free(import_ctx.mem_ctx);
915
916         return ret;
917 }
918 /**@}*/
919
920 /******************************************************************************/
921
922 /**
923  * @defgroup net_registry_export Export
924  * @ingroup net_registry
925  * @{
926  */
927
928 static int registry_export(TALLOC_CTX *ctx, /*const*/ struct registry_key* key,
929                            struct reg_format* f)
930 {
931         int ret=-1;
932         WERROR werr;
933         uint32_t count;
934
935         struct registry_value *valvalue = NULL;
936         char *valname = NULL;
937
938         struct registry_key* subkey = NULL;
939         char *subkey_name = NULL;
940         NTTIME modtime = 0;
941
942         reg_format_registry_key(f, key, false);
943
944         /* print values */
945         for (count = 0;
946              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
947                      W_ERROR_IS_OK(werr);
948              count++)
949         {
950                 reg_format_registry_value(f, valname, valvalue);
951         }
952         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
953                 d_fprintf(stderr, "reg_enumvalue failed: %s\n",
954                           win_errstr(werr));
955                 goto done;
956         }
957
958         /* recurse on subkeys */
959         for (count = 0;
960              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
961                      W_ERROR_IS_OK(werr);
962              count++)
963         {
964                 werr = reg_openkey(ctx, key, subkey_name, REG_KEY_READ,
965                                    &subkey);
966                 if (!W_ERROR_IS_OK(werr)) {
967                         d_fprintf(stderr, "reg_openkey failed: %s\n",
968                                   win_errstr(werr));
969                         goto done;
970                 }
971
972                 registry_export(ctx, subkey, f);
973         }
974         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
975                 d_fprintf(stderr, "reg_enumkey failed: %s\n",
976                           win_errstr(werr));
977                 goto done;
978         }
979         ret = 0;
980 done:
981         return ret;
982 }
983
984 static int net_registry_export(struct net_context *c, int argc,
985                                const char **argv)
986 {
987         int ret=-1;
988         WERROR werr;
989         struct registry_key *key = NULL;
990         TALLOC_CTX *ctx = talloc_stackframe();
991         struct reg_format* f=NULL;
992
993         if (argc < 2 || argc > 3 || c->display_usage) {
994                 d_printf("%s\n%s",
995                          "Usage:",
996                          "net registry export <path> <file> [opt]\n");
997                 d_printf("%s\n%s",
998                          "Example:",
999                          "net registry export 'HKLM\\Software\\Samba' "
1000                            "samba.reg regedit5\n");
1001                 goto done;
1002         }
1003
1004         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
1005         if (!W_ERROR_IS_OK(werr)) {
1006                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
1007                 goto done;
1008         }
1009
1010         f = reg_format_file(ctx, argv[1], (argc > 2) ? argv[2] : NULL);
1011         if (f == NULL) {
1012                 d_fprintf(stderr, "open file failed: %s\n", strerror(errno));
1013                 goto done;
1014         }
1015
1016         ret = registry_export(ctx, key, f);
1017
1018 done:
1019         TALLOC_FREE(ctx);
1020         return ret;
1021 }
1022 /**@}*/
1023
1024 /******************************************************************************/
1025 /**
1026  * @defgroup net_registry_convert Convert
1027  * @ingroup net_registry
1028  * @{
1029  */
1030
1031 static int net_registry_convert(struct net_context *c, int argc,
1032                                const char **argv)
1033 {
1034         int ret;
1035         void* mem_ctx;
1036         const char* in_opt  = NULL;
1037         const char* out_opt = NULL;
1038
1039         if (argc < 2 || argc > 4|| c->display_usage) {
1040                 d_printf("%s\n%s",
1041                          "Usage:",
1042                          "net registry convert <in> <out> [in_opt] [out_opt]\n"
1043                            "net registry convert <in> <out> [out_opt]\n");
1044                 d_printf("%s\n%s",
1045                          "Example:",
1046                          "net registry convert in.reg out.reg regedit4,enc=CP1252\n");
1047                 return -1;
1048         }
1049
1050         mem_ctx = talloc_stackframe();
1051
1052         switch (argc ) {
1053         case 2:
1054                 break;
1055         case 3:
1056                 out_opt = argv[2];
1057                 break;
1058         case 4:
1059                 out_opt = argv[3];
1060                 in_opt  = argv[2];
1061                 break;
1062         default:
1063                 assert(false);
1064         }
1065
1066
1067         ret = reg_parse_file(argv[0], (struct reg_parse_callback*)
1068                              reg_format_file(mem_ctx, argv[1], out_opt),
1069                              in_opt);
1070
1071         talloc_free(mem_ctx);
1072
1073         return ret;
1074 }
1075 /**@}*/
1076
1077 /******************************************************************************/
1078
1079 int net_registry(struct net_context *c, int argc, const char **argv)
1080 {
1081         int ret = -1;
1082
1083         struct functable func[] = {
1084                 {
1085                         "enumerate",
1086                         net_registry_enumerate,
1087                         NET_TRANSPORT_LOCAL,
1088                         "Enumerate registry keys and values",
1089                         "net registry enumerate\n"
1090                         "    Enumerate registry keys and values"
1091                 },
1092                 {
1093                         "createkey",
1094                         net_registry_createkey,
1095                         NET_TRANSPORT_LOCAL,
1096                         "Create a new registry key",
1097                         "net registry createkey\n"
1098                         "    Create a new registry key"
1099                 },
1100                 {
1101                         "deletekey",
1102                         net_registry_deletekey,
1103                         NET_TRANSPORT_LOCAL,
1104                         "Delete a registry key",
1105                         "net registry deletekey\n"
1106                         "    Delete a registry key"
1107                 },
1108                 {
1109                         "getvalue",
1110                         net_registry_getvalue,
1111                         NET_TRANSPORT_LOCAL,
1112                         "Print a registry value",
1113                         "net registry getvalue\n"
1114                         "    Print a registry value"
1115                 },
1116                 {
1117                         "getvalueraw",
1118                         net_registry_getvalueraw,
1119                         NET_TRANSPORT_LOCAL,
1120                         "Print a registry value (raw format)",
1121                         "net registry getvalueraw\n"
1122                         "    Print a registry value (raw format)"
1123                 },
1124                 {
1125                         "getvaluesraw",
1126                         net_registry_getvaluesraw,
1127                         NET_TRANSPORT_LOCAL,
1128                         "Print all values of a key in raw format",
1129                         "net registry getvaluesraw <key>\n"
1130                         "    Print a registry value (raw format)"
1131                 },
1132                 {
1133                         "setvalue",
1134                         net_registry_setvalue,
1135                         NET_TRANSPORT_LOCAL,
1136                         "Set a new registry value",
1137                         "net registry setvalue\n"
1138                         "    Set a new registry value"
1139                 },
1140                 {
1141                         "increment",
1142                         net_registry_increment,
1143                         NET_TRANSPORT_LOCAL,
1144                         "Increment a DWORD registry value under a lock",
1145                         "net registry increment\n"
1146                         "    Increment a DWORD registry value under a lock"
1147                 },
1148                 {
1149                         "deletevalue",
1150                         net_registry_deletevalue,
1151                         NET_TRANSPORT_LOCAL,
1152                         "Delete a registry value",
1153                         "net registry deletevalue\n"
1154                         "    Delete a registry value"
1155                 },
1156                 {
1157                         "getsd",
1158                         net_registry_getsd,
1159                         NET_TRANSPORT_LOCAL,
1160                         "Get security descriptor",
1161                         "net registry getsd\n"
1162                         "    Get security descriptor"
1163                 },
1164                 {
1165                         "getsd_sddl",
1166                         net_registry_getsd_sddl,
1167                         NET_TRANSPORT_LOCAL,
1168                         "Get security descriptor in sddl format",
1169                         "net registry getsd_sddl\n"
1170                         "    Get security descriptor in sddl format"
1171                 },
1172                 {
1173                         "setsd_sddl",
1174                         net_registry_setsd_sddl,
1175                         NET_TRANSPORT_LOCAL,
1176                         "Set security descriptor from sddl format string",
1177                         "net registry setsd_sddl\n"
1178                         "    Set security descriptor from sddl format string"
1179                 },
1180                 {
1181                         "import",
1182                         net_registry_import,
1183                         NET_TRANSPORT_LOCAL,
1184                         "Import .reg file",
1185                         "net registry import\n"
1186                         "    Import .reg file"
1187                 },
1188                 {
1189                         "export",
1190                         net_registry_export,
1191                         NET_TRANSPORT_LOCAL,
1192                         "Export .reg file",
1193                         "net registry export\n"
1194                            "    Export .reg file"
1195                 },
1196                 {
1197                         "convert",
1198                         net_registry_convert,
1199                         NET_TRANSPORT_LOCAL,
1200                         "Convert .reg file",
1201                         "net registry convert\n"
1202                            "    Convert .reg file"
1203                 },
1204         { NULL, NULL, 0, NULL, NULL }
1205         };
1206
1207         if (!W_ERROR_IS_OK(registry_init_basic())) {
1208                 return -1;
1209         }
1210
1211         ret = net_run_function(c, argc, argv, "net registry", func);
1212
1213         return ret;
1214 }