s3:net registry: ignore WERR_BADFILE when --force is given in deletekey[_recursive]
[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_internal(struct net_context *c, int argc,
230                                            const char **argv,
231                                            bool recursive)
232 {
233         WERROR werr;
234         char *subkeyname;
235         struct registry_key *hivekey = NULL;
236         TALLOC_CTX *ctx = talloc_stackframe();
237         int ret = -1;
238
239         if (argc != 1 || c->display_usage) {
240                 d_printf("Usage:    net registry deletekey <path>\n");
241                 d_printf("Example:  net registry deletekey "
242                          "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n");
243                 goto done;
244         }
245         if (strlen(argv[0]) == 0) {
246                 d_fprintf(stderr, "error: zero length key name given\n");
247                 goto done;
248         }
249
250         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
251         if (!W_ERROR_IS_OK(werr)) {
252                 d_fprintf(stderr, "open_hive failed: %s\n", win_errstr(werr));
253                 goto done;
254         }
255
256         if (recursive) {
257                 werr = reg_deletekey_recursive(hivekey, subkeyname);
258         } else {
259                 werr = reg_deletekey(hivekey, subkeyname);
260         }
261         if (!W_ERROR_IS_OK(werr) &&
262             !(c->opt_force && W_ERROR_EQUAL(werr, WERR_BADFILE)))
263         {
264                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
265                           win_errstr(werr));
266                 goto done;
267         }
268
269         ret = 0;
270
271 done:
272         TALLOC_FREE(ctx);
273         return ret;
274 }
275
276 static int net_registry_deletekey(struct net_context *c, int argc,
277                                   const char **argv)
278 {
279         return net_registry_deletekey_internal(c, argc, argv, false);
280 }
281
282 static int net_registry_deletekey_recursive(struct net_context *c, int argc,
283                                             const char **argv)
284 {
285         return net_registry_deletekey_internal(c, argc, argv, true);
286 }
287
288 static int net_registry_getvalue_internal(struct net_context *c, int argc,
289                                           const char **argv, bool raw)
290 {
291         WERROR werr;
292         int ret = -1;
293         struct registry_key *key = NULL;
294         struct registry_value *value = NULL;
295         TALLOC_CTX *ctx = talloc_stackframe();
296
297         if (argc != 2 || c->display_usage) {
298                 d_fprintf(stderr, "usage: net rpc registry getvalue <key> "
299                                   "<valuename>\n");
300                 goto done;
301         }
302
303         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
304         if (!W_ERROR_IS_OK(werr)) {
305                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
306                 goto done;
307         }
308
309         werr = reg_queryvalue(ctx, key, argv[1], &value);
310         if (!W_ERROR_IS_OK(werr)) {
311                 d_fprintf(stderr, "reg_queryvalue failed: %s\n",
312                           win_errstr(werr));
313                 goto done;
314         }
315
316         print_registry_value(value, raw);
317
318         ret = 0;
319
320 done:
321         TALLOC_FREE(ctx);
322         return ret;
323 }
324
325 static int net_registry_getvalue(struct net_context *c, int argc,
326                                  const char **argv)
327 {
328         return net_registry_getvalue_internal(c, argc, argv, false);
329 }
330
331 static int net_registry_getvalueraw(struct net_context *c, int argc,
332                                     const char **argv)
333 {
334         return net_registry_getvalue_internal(c, argc, argv, true);
335 }
336
337 static int net_registry_getvaluesraw(struct net_context *c, int argc,
338                                      const char **argv)
339 {
340         WERROR werr;
341         int ret = -1;
342         struct registry_key *key = NULL;
343         TALLOC_CTX *ctx = talloc_stackframe();
344         uint32_t idx;
345
346         if (argc != 1 || c->display_usage) {
347                 d_fprintf(stderr, "usage: net rpc registry getvaluesraw "
348                           "<key>\n");
349                 goto done;
350         }
351
352         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
353         if (!W_ERROR_IS_OK(werr)) {
354                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
355                 goto done;
356         }
357
358         idx = 0;
359         while (true) {
360                 struct registry_value *val;
361
362                 werr = reg_enumvalue(talloc_tos(), key, idx, NULL, &val);
363
364                 if (W_ERROR_EQUAL(werr, WERR_NO_MORE_ITEMS)) {
365                         ret = 0;
366                         break;
367                 }
368                 if (!W_ERROR_IS_OK(werr)) {
369                         break;
370                 }
371                 print_registry_value(val, true);
372                 TALLOC_FREE(val);
373                 idx += 1;
374         }
375 done:
376         TALLOC_FREE(ctx);
377         return ret;
378 }
379
380 static int net_registry_setvalue(struct net_context *c, int argc,
381                                  const char **argv)
382 {
383         WERROR werr;
384         struct registry_value value;
385         struct registry_key *key = NULL;
386         int ret = -1;
387         TALLOC_CTX *ctx = talloc_stackframe();
388
389         if (argc < 4 || c->display_usage) {
390                 d_fprintf(stderr, "usage: net rpc registry setvalue <key> "
391                           "<valuename> <type> [<val>]+\n");
392                 goto done;
393         }
394
395         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
396                 d_fprintf(stderr, "Too many args for type %s\n", argv[2]);
397                 goto done;
398         }
399
400         if (strequal(argv[2], "dword")) {
401                 value.type = REG_DWORD;
402                 value.v.dword = strtoul(argv[3], NULL, 10);
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         } else if (strequal(argv[2], "multi_sz")) {
408                 value.type = REG_MULTI_SZ;
409                 value.v.multi_sz.num_strings = argc - 3;
410                 value.v.multi_sz.strings = (char **)(argv + 3);
411         } else {
412                 d_fprintf(stderr, "type \"%s\" not implemented\n", argv[2]);
413                 goto done;
414         }
415
416         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
417         if (!W_ERROR_IS_OK(werr)) {
418                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
419                 goto done;
420         }
421
422         werr = reg_setvalue(key, argv[1], &value);
423         if (!W_ERROR_IS_OK(werr)) {
424                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
425                           win_errstr(werr));
426                 goto done;
427         }
428
429         ret = 0;
430
431 done:
432         TALLOC_FREE(ctx);
433         return ret;
434 }
435
436 struct net_registry_increment_state {
437         const char *keyname;
438         const char *valuename;
439         uint32_t increment;
440         uint32_t newvalue;
441         WERROR werr;
442 };
443
444 static void net_registry_increment_fn(void *private_data)
445 {
446         struct net_registry_increment_state *state =
447                 (struct net_registry_increment_state *)private_data;
448         struct registry_value *value;
449         struct registry_key *key = NULL;
450
451         state->werr = open_key(talloc_tos(), state->keyname,
452                                REG_KEY_READ|REG_KEY_WRITE, &key);
453         if (!W_ERROR_IS_OK(state->werr)) {
454                 d_fprintf(stderr, "open_key failed: %s\n",
455                           win_errstr(state->werr));
456                 goto done;
457         }
458
459         state->werr = reg_queryvalue(key, key, state->valuename, &value);
460         if (!W_ERROR_IS_OK(state->werr)) {
461                 d_fprintf(stderr, "reg_queryvalue failed: %s\n",
462                           win_errstr(state->werr));
463                 goto done;
464         }
465
466         if (value->type != REG_DWORD) {
467                 d_fprintf(stderr, "value not a DWORD: %s\n",
468                           reg_type_lookup(value->type));
469                 goto done;
470         }
471
472         value->v.dword += state->increment;
473         state->newvalue = value->v.dword;
474
475         state->werr = reg_setvalue(key, state->valuename, value);
476         if (!W_ERROR_IS_OK(state->werr)) {
477                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
478                           win_errstr(state->werr));
479                 goto done;
480         }
481
482 done:
483         TALLOC_FREE(key);
484         return;
485 }
486
487 static int net_registry_increment(struct net_context *c, int argc,
488                                   const char **argv)
489 {
490         struct net_registry_increment_state state;
491         NTSTATUS status;
492         int ret = -1;
493
494         if (argc < 2 || c->display_usage) {
495                 d_fprintf(stderr, "%s\n%s",
496                           "Usage:",
497                           "net registry increment <key> <valuename> "
498                           "[<increment>]\n");
499                 goto done;
500         }
501
502         state.keyname = argv[0];
503         state.valuename = argv[1];
504
505         state.increment = 1;
506         if (argc == 3) {
507                 state.increment = strtoul(argv[2], NULL, 10);
508         }
509
510         status = g_lock_do("registry_increment_lock", G_LOCK_WRITE,
511                            timeval_set(600, 0),
512                            net_registry_increment_fn, &state);
513         if (!NT_STATUS_IS_OK(status)) {
514                 d_fprintf(stderr, "g_lock_do failed: %s\n",
515                           nt_errstr(status));
516                 goto done;
517         }
518         if (!W_ERROR_IS_OK(state.werr)) {
519                 d_fprintf(stderr, "increment failed: %s\n",
520                           win_errstr(state.werr));
521                 goto done;
522         }
523
524         d_printf("new value: %u\n", (unsigned)state.newvalue);
525
526         ret = 0;
527
528 done:
529         return ret;
530 }
531
532 static int net_registry_deletevalue(struct net_context *c, int argc,
533                                     const char **argv)
534 {
535         WERROR werr;
536         struct registry_key *key = NULL;
537         TALLOC_CTX *ctx = talloc_stackframe();
538         int ret = -1;
539
540         if (argc != 2 || c->display_usage) {
541                 d_fprintf(stderr, "usage: net rpc registry deletevalue <key> "
542                           "<valuename>\n");
543                 goto done;
544         }
545
546         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
547         if (!W_ERROR_IS_OK(werr)) {
548                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
549                 goto done;
550         }
551
552         werr = reg_deletevalue(key, argv[1]);
553         if (!W_ERROR_IS_OK(werr)) {
554                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
555                           win_errstr(werr));
556                 goto done;
557         }
558
559         ret = 0;
560
561 done:
562         TALLOC_FREE(ctx);
563         return ret;
564 }
565
566 static WERROR net_registry_getsd_internal(struct net_context *c,
567                                           TALLOC_CTX *mem_ctx,
568                                           const char *keyname,
569                                           struct security_descriptor **sd)
570 {
571         WERROR werr;
572         struct registry_key *key = NULL;
573         TALLOC_CTX *ctx = talloc_stackframe();
574         uint32_t access_mask = REG_KEY_READ |
575                                SEC_FLAG_MAXIMUM_ALLOWED |
576                                SEC_FLAG_SYSTEM_SECURITY;
577
578         /*
579          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
580          * is denied with these perms right now...
581          */
582         access_mask = REG_KEY_READ;
583
584         if (sd == NULL) {
585                 d_fprintf(stderr, "internal error: invalid argument\n");
586                 werr = WERR_INVALID_PARAM;
587                 goto done;
588         }
589
590         if (strlen(keyname) == 0) {
591                 d_fprintf(stderr, "error: zero length key name given\n");
592                 werr = WERR_INVALID_PARAM;
593                 goto done;
594         }
595
596         werr = open_key(ctx, keyname, access_mask, &key);
597         if (!W_ERROR_IS_OK(werr)) {
598                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
599                 goto done;
600         }
601
602         werr = reg_getkeysecurity(mem_ctx, key, sd);
603         if (!W_ERROR_IS_OK(werr)) {
604                 d_fprintf(stderr, "reg_getkeysecurity failed: %s\n",
605                           win_errstr(werr));
606                 goto done;
607         }
608
609         werr = WERR_OK;
610
611 done:
612         TALLOC_FREE(ctx);
613         return werr;
614 }
615
616 static int net_registry_getsd(struct net_context *c, int argc,
617                               const char **argv)
618 {
619         WERROR werr;
620         int ret = -1;
621         struct security_descriptor *secdesc = NULL;
622         TALLOC_CTX *ctx = talloc_stackframe();
623
624         if (argc != 1 || c->display_usage) {
625                 d_printf("Usage:    net registry getsd <path>\n");
626                 d_printf("Example:  net registry getsd "
627                          "'HKLM\\Software\\Samba'\n");
628                 goto done;
629         }
630
631         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
632         if (!W_ERROR_IS_OK(werr)) {
633                 goto done;
634         }
635
636         display_sec_desc(secdesc);
637
638         ret = 0;
639
640 done:
641         TALLOC_FREE(ctx);
642         return ret;
643 }
644
645 static int net_registry_getsd_sddl(struct net_context *c,
646                                    int argc, const char **argv)
647 {
648         WERROR werr;
649         int ret = -1;
650         struct security_descriptor *secdesc = NULL;
651         TALLOC_CTX *ctx = talloc_stackframe();
652
653         if (argc != 1 || c->display_usage) {
654                 d_printf("Usage: net registry getsd_sddl <path>\n");
655                 d_printf("Example: net registry getsd_sddl 'HKLM\\Software\\Samba'\n");
656                 goto done;
657         }
658
659         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
660         if (!W_ERROR_IS_OK(werr)) {
661                 goto done;
662         }
663
664         d_printf("%s\n", sddl_encode(ctx, secdesc, get_global_sam_sid()));
665
666         ret = 0;
667
668 done:
669         TALLOC_FREE(ctx);
670         return ret;
671 }
672
673 static WERROR net_registry_setsd_internal(struct net_context *c,
674                                           TALLOC_CTX *mem_ctx,
675                                           const char *keyname,
676                                           struct security_descriptor *sd)
677 {
678         WERROR werr;
679         struct registry_key *key = NULL;
680         TALLOC_CTX *ctx = talloc_stackframe();
681         uint32_t access_mask = REG_KEY_WRITE |
682                                SEC_FLAG_MAXIMUM_ALLOWED |
683                                SEC_FLAG_SYSTEM_SECURITY;
684
685         /*
686          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
687          * is denied with these perms right now...
688          */
689         access_mask = REG_KEY_WRITE;
690
691         if (strlen(keyname) == 0) {
692                 d_fprintf(stderr, "error: zero length key name given\n");
693                 werr = WERR_INVALID_PARAM;
694                 goto done;
695         }
696
697         werr = open_key(ctx, keyname, access_mask, &key);
698         if (!W_ERROR_IS_OK(werr)) {
699                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
700                 goto done;
701         }
702
703         werr = reg_setkeysecurity(key, sd);
704         if (!W_ERROR_IS_OK(werr)) {
705                 d_fprintf(stderr, "reg_setkeysecurity failed: %s\n",
706                           win_errstr(werr));
707                 goto done;
708         }
709
710         werr = WERR_OK;
711
712 done:
713         TALLOC_FREE(ctx);
714         return werr;
715 }
716
717 static int net_registry_setsd_sddl(struct net_context *c,
718                                    int argc, const char **argv)
719 {
720         WERROR werr;
721         int ret = -1;
722         struct security_descriptor *secdesc = NULL;
723         TALLOC_CTX *ctx = talloc_stackframe();
724
725         if (argc != 2 || c->display_usage) {
726                 d_printf("Usage: net registry setsd_sddl <path> <security_descriptor>\n");
727                 d_printf("Example:\n"
728                          "net registry setsd_sddl 'HKLM\\Software\\Samba'\n");
729                 goto done;
730         }
731
732         secdesc = sddl_decode(ctx, argv[1], get_global_sam_sid());
733         if (secdesc == NULL) {
734                 goto done;
735         }
736
737         werr = net_registry_setsd_internal(c, ctx, argv[0], secdesc);
738         if (!W_ERROR_IS_OK(werr)) {
739                 goto done;
740         }
741
742         ret = 0;
743
744 done:
745         TALLOC_FREE(ctx);
746         return ret;
747 }
748
749 /******************************************************************************/
750 /**
751  * @defgroup net_registry net registry
752  */
753
754 /**
755  * @defgroup net_registry_import Import
756  * @ingroup net_registry
757  * @{
758  */
759
760 struct import_ctx {
761         TALLOC_CTX *mem_ctx;
762 };
763
764
765 static WERROR import_create_key(struct import_ctx* ctx,
766                                 struct registry_key* parent,
767                                 const char* name, void** pkey, bool* existing)
768 {
769         WERROR werr;
770         void* mem_ctx = talloc_new(ctx->mem_ctx);
771
772         struct registry_key* key = NULL;
773         enum winreg_CreateAction action;
774
775         if (parent == NULL) {
776                 char* subkeyname = NULL;
777                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
778                          &parent, &subkeyname);
779                 if (!W_ERROR_IS_OK(werr)) {
780                         d_fprintf(stderr, "open_hive failed: %s\n",
781                                   win_errstr(werr));
782                         goto done;
783                 }
784                 name = subkeyname;
785         }
786
787         action = REG_ACTION_NONE;
788         werr = reg_createkey(mem_ctx, parent, name, REG_KEY_WRITE,
789                              &key, &action);
790         if (!W_ERROR_IS_OK(werr)) {
791                 d_fprintf(stderr, "reg_createkey failed: %s\n",
792                           win_errstr(werr));
793                 goto done;
794         }
795
796         if (action == REG_ACTION_NONE) {
797                 d_fprintf(stderr, "createkey did nothing -- huh?\n");
798                 werr = WERR_FOOBAR;
799                 goto done;
800         }
801
802         if (existing != NULL) {
803                 *existing = (action == REG_OPENED_EXISTING_KEY);
804         }
805
806         if (pkey!=NULL) {
807                 *pkey = talloc_steal(ctx->mem_ctx, key);
808         }
809
810 done:
811         talloc_free(mem_ctx);
812         return werr;
813 }
814
815 static WERROR import_close_key(struct import_ctx* ctx,
816                                struct registry_key* key)
817 {
818         return WERR_OK;
819 }
820
821 static WERROR import_delete_key(struct import_ctx* ctx,
822                                 struct registry_key* parent, const char* name)
823 {
824         WERROR werr;
825         void* mem_ctx = talloc_new(talloc_tos());
826
827         if (parent == NULL) {
828                 char* subkeyname = NULL;
829                 werr = open_hive(mem_ctx, name, REG_KEY_WRITE,
830                          &parent, &subkeyname);
831                 if (!W_ERROR_IS_OK(werr)) {
832                         d_fprintf(stderr, "open_hive failed: %s\n",
833                                   win_errstr(werr));
834                         goto done;
835                 }
836                 name = subkeyname;
837         }
838
839         werr = reg_deletekey_recursive(parent, name);
840         if (!W_ERROR_IS_OK(werr)) {
841                 d_fprintf(stderr, "reg_deletekey_recursive %s: %s\n", "failed",
842                           win_errstr(werr));
843                 goto done;
844         }
845
846 done:
847         talloc_free(mem_ctx);
848         return werr;
849 }
850
851 static WERROR import_create_val (struct import_ctx* ctx,
852                                  struct registry_key* parent, const char* name,
853                                  const struct registry_value* value)
854 {
855         WERROR werr;
856
857         if (parent == NULL) {
858                 return WERR_INVALID_PARAM;
859         }
860
861         werr = reg_setvalue(parent, name, value);
862         if (!W_ERROR_IS_OK(werr)) {
863                 d_fprintf(stderr, "reg_setvalue failed: %s\n",
864                           win_errstr(werr));
865         }
866         return werr;
867 }
868
869 static WERROR import_delete_val (struct import_ctx* ctx, struct registry_key* parent, const char* name) {
870         WERROR werr;
871
872         if (parent == NULL) {
873                 return WERR_INVALID_PARAM;
874         }
875
876         werr = reg_deletevalue(parent, name);
877         if (!W_ERROR_IS_OK(werr)) {
878                 d_fprintf(stderr, "reg_deletekey failed: %s\n",
879                           win_errstr(werr));
880         }
881
882         return werr;
883 }
884
885
886 static int net_registry_import(struct net_context *c, int argc,
887                                const char **argv)
888 {
889         struct import_ctx import_ctx;
890         struct reg_import_callback import_callback = {
891                 .openkey     = NULL,
892                 .closekey    = (reg_import_callback_closekey_t)&import_close_key,
893                 .createkey   = (reg_import_callback_createkey_t)&import_create_key,
894                 .deletekey   = (reg_import_callback_deletekey_t)&import_delete_key,
895                 .deleteval   = (reg_import_callback_deleteval_t)&import_delete_val,
896                 .setval.registry_value = (reg_import_callback_setval_registry_value_t)
897                 &import_create_val,
898                 .setval_type           = REGISTRY_VALUE,
899                 .data        = &import_ctx
900         };
901
902         int ret;
903
904         if (argc < 1 || argc > 2 || c->display_usage) {
905                 d_printf("%s\n%s",
906                          "Usage:",
907                          "net registry import <reg> [options]\n");
908                 d_printf("%s\n%s",
909                          "Example:",
910                          "net registry import file.reg enc=CP1252\n");
911                 return -1;
912         }
913
914         ZERO_STRUCT(import_ctx);
915         import_ctx.mem_ctx = talloc_stackframe();
916
917         regdb_open();
918         regdb_transaction_start();
919
920         ret = reg_parse_file(argv[0],
921                              reg_import_adapter(import_ctx.mem_ctx,
922                                                 import_callback),
923                              (argc > 1) ? argv[1] : NULL
924                 );
925         if (ret < 0) {
926                 d_printf("reg_parse_file failed: transaction canceled\n");
927                 regdb_transaction_cancel();
928         } else{
929                 regdb_transaction_commit();
930         }
931
932         regdb_close();
933         talloc_free(import_ctx.mem_ctx);
934
935         return ret;
936 }
937 /**@}*/
938
939 /******************************************************************************/
940
941 /**
942  * @defgroup net_registry_export Export
943  * @ingroup net_registry
944  * @{
945  */
946
947 static int registry_export(TALLOC_CTX *ctx, /*const*/ struct registry_key* key,
948                            struct reg_format* f)
949 {
950         int ret=-1;
951         WERROR werr;
952         uint32_t count;
953
954         struct registry_value *valvalue = NULL;
955         char *valname = NULL;
956
957         struct registry_key* subkey = NULL;
958         char *subkey_name = NULL;
959         NTTIME modtime = 0;
960
961         reg_format_registry_key(f, key, false);
962
963         /* print values */
964         for (count = 0;
965              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
966                      W_ERROR_IS_OK(werr);
967              count++)
968         {
969                 reg_format_registry_value(f, valname, valvalue);
970         }
971         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
972                 d_fprintf(stderr, "reg_enumvalue failed: %s\n",
973                           win_errstr(werr));
974                 goto done;
975         }
976
977         /* recurse on subkeys */
978         for (count = 0;
979              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
980                      W_ERROR_IS_OK(werr);
981              count++)
982         {
983                 werr = reg_openkey(ctx, key, subkey_name, REG_KEY_READ,
984                                    &subkey);
985                 if (!W_ERROR_IS_OK(werr)) {
986                         d_fprintf(stderr, "reg_openkey failed: %s\n",
987                                   win_errstr(werr));
988                         goto done;
989                 }
990
991                 registry_export(ctx, subkey, f);
992         }
993         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
994                 d_fprintf(stderr, "reg_enumkey failed: %s\n",
995                           win_errstr(werr));
996                 goto done;
997         }
998         ret = 0;
999 done:
1000         return ret;
1001 }
1002
1003 static int net_registry_export(struct net_context *c, int argc,
1004                                const char **argv)
1005 {
1006         int ret=-1;
1007         WERROR werr;
1008         struct registry_key *key = NULL;
1009         TALLOC_CTX *ctx = talloc_stackframe();
1010         struct reg_format* f=NULL;
1011
1012         if (argc < 2 || argc > 3 || c->display_usage) {
1013                 d_printf("%s\n%s",
1014                          "Usage:",
1015                          "net registry export <path> <file> [opt]\n");
1016                 d_printf("%s\n%s",
1017                          "Example:",
1018                          "net registry export 'HKLM\\Software\\Samba' "
1019                            "samba.reg regedit5\n");
1020                 goto done;
1021         }
1022
1023         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
1024         if (!W_ERROR_IS_OK(werr)) {
1025                 d_fprintf(stderr, "open_key failed: %s\n", win_errstr(werr));
1026                 goto done;
1027         }
1028
1029         f = reg_format_file(ctx, argv[1], (argc > 2) ? argv[2] : NULL);
1030         if (f == NULL) {
1031                 d_fprintf(stderr, "open file failed: %s\n", strerror(errno));
1032                 goto done;
1033         }
1034
1035         ret = registry_export(ctx, key, f);
1036
1037 done:
1038         TALLOC_FREE(ctx);
1039         return ret;
1040 }
1041 /**@}*/
1042
1043 /******************************************************************************/
1044 /**
1045  * @defgroup net_registry_convert Convert
1046  * @ingroup net_registry
1047  * @{
1048  */
1049
1050 static int net_registry_convert(struct net_context *c, int argc,
1051                                const char **argv)
1052 {
1053         int ret;
1054         void* mem_ctx;
1055         const char* in_opt  = NULL;
1056         const char* out_opt = NULL;
1057
1058         if (argc < 2 || argc > 4|| c->display_usage) {
1059                 d_printf("%s\n%s",
1060                          "Usage:",
1061                          "net registry convert <in> <out> [in_opt] [out_opt]\n"
1062                            "net registry convert <in> <out> [out_opt]\n");
1063                 d_printf("%s\n%s",
1064                          "Example:",
1065                          "net registry convert in.reg out.reg regedit4,enc=CP1252\n");
1066                 return -1;
1067         }
1068
1069         mem_ctx = talloc_stackframe();
1070
1071         switch (argc ) {
1072         case 2:
1073                 break;
1074         case 3:
1075                 out_opt = argv[2];
1076                 break;
1077         case 4:
1078                 out_opt = argv[3];
1079                 in_opt  = argv[2];
1080                 break;
1081         default:
1082                 assert(false);
1083         }
1084
1085
1086         ret = reg_parse_file(argv[0], (struct reg_parse_callback*)
1087                              reg_format_file(mem_ctx, argv[1], out_opt),
1088                              in_opt);
1089
1090         talloc_free(mem_ctx);
1091
1092         return ret;
1093 }
1094 /**@}*/
1095
1096 /******************************************************************************/
1097
1098 int net_registry(struct net_context *c, int argc, const char **argv)
1099 {
1100         int ret = -1;
1101
1102         struct functable func[] = {
1103                 {
1104                         "enumerate",
1105                         net_registry_enumerate,
1106                         NET_TRANSPORT_LOCAL,
1107                         "Enumerate registry keys and values",
1108                         "net registry enumerate\n"
1109                         "    Enumerate registry keys and values"
1110                 },
1111                 {
1112                         "createkey",
1113                         net_registry_createkey,
1114                         NET_TRANSPORT_LOCAL,
1115                         "Create a new registry key",
1116                         "net registry createkey\n"
1117                         "    Create a new registry key"
1118                 },
1119                 {
1120                         "deletekey",
1121                         net_registry_deletekey,
1122                         NET_TRANSPORT_LOCAL,
1123                         "Delete a registry key",
1124                         "net registry deletekey\n"
1125                         "    Delete a registry key"
1126                 },
1127                 {
1128                         "deletekey_recursive",
1129                         net_registry_deletekey_recursive,
1130                         NET_TRANSPORT_LOCAL,
1131                         N_("Delete a registry key with subkeys"),
1132                         N_("net registry deletekey_recursive\n"
1133                            "    Delete a registry key with subkeys")
1134                 },
1135                 {
1136                         "getvalue",
1137                         net_registry_getvalue,
1138                         NET_TRANSPORT_LOCAL,
1139                         "Print a registry value",
1140                         "net registry getvalue\n"
1141                         "    Print a registry value"
1142                 },
1143                 {
1144                         "getvalueraw",
1145                         net_registry_getvalueraw,
1146                         NET_TRANSPORT_LOCAL,
1147                         "Print a registry value (raw format)",
1148                         "net registry getvalueraw\n"
1149                         "    Print a registry value (raw format)"
1150                 },
1151                 {
1152                         "getvaluesraw",
1153                         net_registry_getvaluesraw,
1154                         NET_TRANSPORT_LOCAL,
1155                         "Print all values of a key in raw format",
1156                         "net registry getvaluesraw <key>\n"
1157                         "    Print a registry value (raw format)"
1158                 },
1159                 {
1160                         "setvalue",
1161                         net_registry_setvalue,
1162                         NET_TRANSPORT_LOCAL,
1163                         "Set a new registry value",
1164                         "net registry setvalue\n"
1165                         "    Set a new registry value"
1166                 },
1167                 {
1168                         "increment",
1169                         net_registry_increment,
1170                         NET_TRANSPORT_LOCAL,
1171                         "Increment a DWORD registry value under a lock",
1172                         "net registry increment\n"
1173                         "    Increment a DWORD registry value under a lock"
1174                 },
1175                 {
1176                         "deletevalue",
1177                         net_registry_deletevalue,
1178                         NET_TRANSPORT_LOCAL,
1179                         "Delete a registry value",
1180                         "net registry deletevalue\n"
1181                         "    Delete a registry value"
1182                 },
1183                 {
1184                         "getsd",
1185                         net_registry_getsd,
1186                         NET_TRANSPORT_LOCAL,
1187                         "Get security descriptor",
1188                         "net registry getsd\n"
1189                         "    Get security descriptor"
1190                 },
1191                 {
1192                         "getsd_sddl",
1193                         net_registry_getsd_sddl,
1194                         NET_TRANSPORT_LOCAL,
1195                         "Get security descriptor in sddl format",
1196                         "net registry getsd_sddl\n"
1197                         "    Get security descriptor in sddl format"
1198                 },
1199                 {
1200                         "setsd_sddl",
1201                         net_registry_setsd_sddl,
1202                         NET_TRANSPORT_LOCAL,
1203                         "Set security descriptor from sddl format string",
1204                         "net registry setsd_sddl\n"
1205                         "    Set security descriptor from sddl format string"
1206                 },
1207                 {
1208                         "import",
1209                         net_registry_import,
1210                         NET_TRANSPORT_LOCAL,
1211                         "Import .reg file",
1212                         "net registry import\n"
1213                         "    Import .reg file"
1214                 },
1215                 {
1216                         "export",
1217                         net_registry_export,
1218                         NET_TRANSPORT_LOCAL,
1219                         "Export .reg file",
1220                         "net registry export\n"
1221                            "    Export .reg file"
1222                 },
1223                 {
1224                         "convert",
1225                         net_registry_convert,
1226                         NET_TRANSPORT_LOCAL,
1227                         "Convert .reg file",
1228                         "net registry convert\n"
1229                            "    Convert .reg file"
1230                 },
1231         { NULL, NULL, 0, NULL, NULL }
1232         };
1233
1234         if (!W_ERROR_IS_OK(registry_init_basic())) {
1235                 return -1;
1236         }
1237
1238         ret = net_run_function(c, argc, argv, "net registry", func);
1239
1240         return ret;
1241 }