s3-registry: avoid using registry_value union.
[nivanova/samba-autobuild/.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 "registry.h"
24 #include "registry/reg_util_token.h"
25 #include "utils/net.h"
26 #include "utils/net_registry_util.h"
27 #include "include/g_lock.h"
28
29 /*
30  *
31  * Helper functions
32  *
33  */
34
35 /**
36  * split given path into hive and remaining path and open the hive key
37  */
38 static WERROR open_hive(TALLOC_CTX *ctx, const char *path,
39                         uint32 desired_access,
40                         struct registry_key **hive,
41                         char **subkeyname)
42 {
43         WERROR werr;
44         NT_USER_TOKEN *token = NULL;
45         char *hivename = NULL;
46         char *tmp_subkeyname = NULL;
47         TALLOC_CTX *tmp_ctx = talloc_stackframe();
48
49         if ((hive == NULL) || (subkeyname == NULL)) {
50                 werr = WERR_INVALID_PARAM;
51                 goto done;
52         }
53
54         werr = split_hive_key(tmp_ctx, path, &hivename, &tmp_subkeyname);
55         if (!W_ERROR_IS_OK(werr)) {
56                 goto done;
57         }
58         *subkeyname = talloc_strdup(ctx, tmp_subkeyname);
59         if (*subkeyname == NULL) {
60                 werr = WERR_NOMEM;
61                 goto done;
62         }
63
64         werr = ntstatus_to_werror(registry_create_admin_token(tmp_ctx, &token));
65         if (!W_ERROR_IS_OK(werr)) {
66                 goto done;
67         }
68
69         werr = reg_openhive(ctx, hivename, desired_access, token, hive);
70         if (!W_ERROR_IS_OK(werr)) {
71                 goto done;
72         }
73
74         werr = WERR_OK;
75
76 done:
77         TALLOC_FREE(tmp_ctx);
78         return werr;
79 }
80
81 static WERROR open_key(TALLOC_CTX *ctx, const char *path,
82                        uint32 desired_access,
83                        struct registry_key **key)
84 {
85         WERROR werr;
86         char *subkey_name = NULL;
87         struct registry_key *hive = NULL;
88         TALLOC_CTX *tmp_ctx = talloc_stackframe();
89
90         if ((path == NULL) || (key == NULL)) {
91                 return WERR_INVALID_PARAM;
92         }
93
94         werr = open_hive(tmp_ctx, path, desired_access, &hive, &subkey_name);
95         if (!W_ERROR_IS_OK(werr)) {
96                 d_fprintf(stderr, _("open_hive failed: %s\n"),
97                           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("%s\n%s",
136                          _("Usage:"),
137                          _("net registry enumerate <path>\n"));
138                 d_printf("%s\n%s",
139                          _("Example:"),
140                          _("net registry enumerate 'HKLM\\Software\\Samba'\n"));
141                 goto done;
142         }
143
144         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
145         if (!W_ERROR_IS_OK(werr)) {
146                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
147                 goto done;
148         }
149
150         for (count = 0;
151              werr = reg_enumkey(ctx, key, count, &subkey_name, &modtime),
152              W_ERROR_IS_OK(werr);
153              count++)
154         {
155                 print_registry_key(subkey_name, &modtime);
156         }
157         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
158                 goto done;
159         }
160
161         for (count = 0;
162              werr = reg_enumvalue(ctx, key, count, &valname, &valvalue),
163              W_ERROR_IS_OK(werr);
164              count++)
165         {
166                 print_registry_value_with_name(valname, valvalue);
167         }
168         if (!W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, werr)) {
169                 goto done;
170         }
171
172         ret = 0;
173 done:
174         TALLOC_FREE(ctx);
175         return ret;
176 }
177
178 static int net_registry_createkey(struct net_context *c, int argc,
179                                   const char **argv)
180 {
181         WERROR werr;
182         enum winreg_CreateAction action;
183         char *subkeyname;
184         struct registry_key *hivekey = NULL;
185         struct registry_key *subkey = NULL;
186         TALLOC_CTX *ctx = talloc_stackframe();
187         int ret = -1;
188
189         if (argc != 1 || c->display_usage) {
190                 d_printf("%s\n%s",
191                          _("Usage:"),
192                          _("net registry createkey <path>\n"));
193                 d_printf("%s\n%s",
194                          _("Example:"),
195                          _("net registry createkey "
196                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
197                 goto done;
198         }
199         if (strlen(argv[0]) == 0) {
200                 d_fprintf(stderr, _("error: zero length key name given\n"));
201                 goto done;
202         }
203
204         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
205         if (!W_ERROR_IS_OK(werr)) {
206                 d_fprintf(stderr, _("open_hive failed: %s\n"),
207                           win_errstr(werr));
208                 goto done;
209         }
210
211         werr = reg_createkey(ctx, hivekey, subkeyname, REG_KEY_WRITE,
212                              &subkey, &action);
213         if (!W_ERROR_IS_OK(werr)) {
214                 d_fprintf(stderr, _("reg_createkey failed: %s\n"),
215                           win_errstr(werr));
216                 goto done;
217         }
218         switch (action) {
219                 case REG_ACTION_NONE:
220                         d_printf(_("createkey did nothing -- huh?\n"));
221                         break;
222                 case REG_CREATED_NEW_KEY:
223                         d_printf(_("createkey created %s\n"), argv[0]);
224                         break;
225                 case REG_OPENED_EXISTING_KEY:
226                         d_printf(_("createkey opened existing %s\n"), argv[0]);
227                         break;
228         }
229
230         ret = 0;
231
232 done:
233         TALLOC_FREE(ctx);
234         return ret;
235 }
236
237 static int net_registry_deletekey(struct net_context *c, int argc,
238                                   const char **argv)
239 {
240         WERROR werr;
241         char *subkeyname;
242         struct registry_key *hivekey = NULL;
243         TALLOC_CTX *ctx = talloc_stackframe();
244         int ret = -1;
245
246         if (argc != 1 || c->display_usage) {
247                 d_printf("%s\n%s",
248                          _("Usage:"),
249                          _("net registry deletekey <path>\n"));
250                 d_printf("%s\n%s",
251                          _("Example:"),
252                          _("net registry deletekey "
253                            "'HKLM\\Software\\Samba\\smbconf.127.0.0.1'\n"));
254                 goto done;
255         }
256         if (strlen(argv[0]) == 0) {
257                 d_fprintf(stderr, _("error: zero length key name given\n"));
258                 goto done;
259         }
260
261         werr = open_hive(ctx, argv[0], REG_KEY_WRITE, &hivekey, &subkeyname);
262         if (!W_ERROR_IS_OK(werr)) {
263                 d_fprintf(stderr, "open_hive %s: %s\n", _("failed"),
264                           win_errstr(werr));
265                 goto done;
266         }
267
268         werr = reg_deletekey(hivekey, subkeyname);
269         if (!W_ERROR_IS_OK(werr)) {
270                 d_fprintf(stderr, "reg_deletekey %s: %s\n", _("failed"),
271                           win_errstr(werr));
272                 goto done;
273         }
274
275         ret = 0;
276
277 done:
278         TALLOC_FREE(ctx);
279         return ret;
280 }
281
282 static int net_registry_getvalue_internal(struct net_context *c, int argc,
283                                           const char **argv, bool raw)
284 {
285         WERROR werr;
286         int ret = -1;
287         struct registry_key *key = NULL;
288         struct registry_value *value = NULL;
289         TALLOC_CTX *ctx = talloc_stackframe();
290
291         if (argc != 2 || c->display_usage) {
292                 d_fprintf(stderr, "%s\n%s",
293                           _("Usage:"),
294                           _("net registry getvalue <key> <valuename>\n"));
295                 goto done;
296         }
297
298         werr = open_key(ctx, argv[0], REG_KEY_READ, &key);
299         if (!W_ERROR_IS_OK(werr)) {
300                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
301                 goto done;
302         }
303
304         werr = reg_queryvalue(ctx, key, argv[1], &value);
305         if (!W_ERROR_IS_OK(werr)) {
306                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
307                           win_errstr(werr));
308                 goto done;
309         }
310
311         print_registry_value(value, raw);
312
313         ret = 0;
314
315 done:
316         TALLOC_FREE(ctx);
317         return ret;
318 }
319
320 static int net_registry_getvalue(struct net_context *c, int argc,
321                                  const char **argv)
322 {
323         return net_registry_getvalue_internal(c, argc, argv, false);
324 }
325
326 static int net_registry_getvalueraw(struct net_context *c, int argc,
327                                     const char **argv)
328 {
329         return net_registry_getvalue_internal(c, argc, argv, true);
330 }
331
332 static int net_registry_setvalue(struct net_context *c, int argc,
333                                  const char **argv)
334 {
335         WERROR werr;
336         struct registry_value value;
337         struct registry_key *key = NULL;
338         int ret = -1;
339         TALLOC_CTX *ctx = talloc_stackframe();
340
341         if (argc < 4 || c->display_usage) {
342                 d_fprintf(stderr, "%s\n%s",
343                           _("Usage:"),
344                           _("net registry setvalue <key> <valuename> "
345                             "<type> [<val>]+\n"));
346                 goto done;
347         }
348
349         if (!strequal(argv[2], "multi_sz") && (argc != 4)) {
350                 d_fprintf(stderr, _("Too many args for type %s\n"), argv[2]);
351                 goto done;
352         }
353
354         if (strequal(argv[2], "dword")) {
355                 uint32_t v = strtoul(argv[3], NULL, 10);
356                 value.type = REG_DWORD;
357                 value.data = data_blob_talloc(ctx, NULL, 4);
358                 SIVAL(value.data.data, 0, v);
359         } else if (strequal(argv[2], "sz")) {
360                 value.type = REG_SZ;
361                 if (!push_reg_sz(ctx, &value.data, argv[3])) {
362                         goto done;
363                 }
364         } else if (strequal(argv[2], "multi_sz")) {
365                 const char **array;
366                 int count = argc - 3;
367                 int i;
368                 value.type = REG_MULTI_SZ;
369                 array = talloc_zero_array(ctx, const char *, count + 1);
370                 if (array == NULL) {
371                         goto done;
372                 }
373                 for (i=0; i < count; i++) {
374                         array[i] = talloc_strdup(array, argv[count+i]);
375                         if (array[i] == NULL) {
376                                 goto done;
377                         }
378                 }
379                 if (!push_reg_multi_sz(ctx, &value.data, array)) {
380                         goto done;
381                 }
382         } else {
383                 d_fprintf(stderr, _("type \"%s\" not implemented\n"), argv[2]);
384                 goto done;
385         }
386
387         werr = open_key(ctx, argv[0], REG_KEY_WRITE, &key);
388         if (!W_ERROR_IS_OK(werr)) {
389                 d_fprintf(stderr, _("open_key failed: %s\n"), win_errstr(werr));
390                 goto done;
391         }
392
393         werr = reg_setvalue(key, argv[1], &value);
394         if (!W_ERROR_IS_OK(werr)) {
395                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
396                           win_errstr(werr));
397                 goto done;
398         }
399
400         ret = 0;
401
402 done:
403         TALLOC_FREE(ctx);
404         return ret;
405 }
406
407 struct net_registry_increment_state {
408         const char *keyname;
409         const char *valuename;
410         uint32_t increment;
411         uint32_t newvalue;
412         WERROR werr;
413 };
414
415 static void net_registry_increment_fn(void *private_data)
416 {
417         struct net_registry_increment_state *state =
418                 (struct net_registry_increment_state *)private_data;
419         struct registry_value *value;
420         struct registry_key *key = NULL;
421         uint32_t v;
422
423         state->werr = open_key(talloc_tos(), state->keyname,
424                                REG_KEY_READ|REG_KEY_WRITE, &key);
425         if (!W_ERROR_IS_OK(state->werr)) {
426                 d_fprintf(stderr, _("open_key failed: %s\n"),
427                           win_errstr(state->werr));
428                 goto done;
429         }
430
431         state->werr = reg_queryvalue(key, key, state->valuename, &value);
432         if (!W_ERROR_IS_OK(state->werr)) {
433                 d_fprintf(stderr, _("reg_queryvalue failed: %s\n"),
434                           win_errstr(state->werr));
435                 goto done;
436         }
437
438         if (value->type != REG_DWORD) {
439                 d_fprintf(stderr, _("value not a DWORD: %s\n"),
440                           str_regtype(value->type));
441                 goto done;
442         }
443
444         if (value->data.length < 4) {
445                 d_fprintf(stderr, _("value too short for regular DWORD\n"));
446                 goto done;
447         }
448
449         v = IVAL(value->data.data, 0);
450         v += state->increment;
451         state->newvalue = v;
452
453         SIVAL(value->data.data, 0, v);
454
455         state->werr = reg_setvalue(key, state->valuename, value);
456         if (!W_ERROR_IS_OK(state->werr)) {
457                 d_fprintf(stderr, _("reg_setvalue failed: %s\n"),
458                           win_errstr(state->werr));
459                 goto done;
460         }
461
462 done:
463         TALLOC_FREE(key);
464         return;
465 }
466
467 static int net_registry_increment(struct net_context *c, int argc,
468                                   const char **argv)
469 {
470         struct net_registry_increment_state state;
471         NTSTATUS status;
472         int ret = -1;
473
474         if (argc < 2 || c->display_usage) {
475                 d_fprintf(stderr, "%s\n%s",
476                           _("Usage:"),
477                           _("net registry increment <key> <valuename> "
478                             "[<increment>]\n"));
479                 goto done;
480         }
481
482         state.keyname = argv[0];
483         state.valuename = argv[1];
484
485         state.increment = 1;
486         if (argc == 3) {
487                 state.increment = strtoul(argv[2], NULL, 10);
488         }
489
490         status = g_lock_do("registry_increment_lock", G_LOCK_WRITE,
491                            timeval_set(600, 0),
492                            net_registry_increment_fn, &state);
493         if (!NT_STATUS_IS_OK(status)) {
494                 d_fprintf(stderr, _("g_lock_do failed: %s\n"),
495                           nt_errstr(status));
496                 goto done;
497         }
498         if (!W_ERROR_IS_OK(state.werr)) {
499                 d_fprintf(stderr, _("increment failed: %s\n"),
500                           win_errstr(state.werr));
501                 goto done;
502         }
503
504         d_printf(_("%u\n"), (unsigned)state.newvalue);
505
506         ret = 0;
507
508 done:
509         return ret;
510 }
511
512 static int net_registry_deletevalue(struct net_context *c, int argc,
513                                     const char **argv)
514 {
515         WERROR werr;
516         struct registry_key *key = NULL;
517         TALLOC_CTX *ctx = talloc_stackframe();
518         int ret = -1;
519
520         if (argc != 2 || c->display_usage) {
521                 d_fprintf(stderr, "%s\n%s",
522                           _("Usage:"),
523                           _("net registry deletevalue <key> <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, "%s%s\n", _("open_key failed: "),
580                           win_errstr(werr));
581                 goto done;
582         }
583
584         werr = reg_getkeysecurity(mem_ctx, key, sd);
585         if (!W_ERROR_IS_OK(werr)) {
586                 d_fprintf(stderr, "%s%s\n", _("reg_getkeysecurity failed: "),
587                           win_errstr(werr));
588                 goto done;
589         }
590
591         werr = WERR_OK;
592
593 done:
594         TALLOC_FREE(ctx);
595         return werr;
596 }
597
598 static int net_registry_getsd(struct net_context *c, int argc,
599                               const char **argv)
600 {
601         WERROR werr;
602         int ret = -1;
603         struct security_descriptor *secdesc = NULL;
604         TALLOC_CTX *ctx = talloc_stackframe();
605
606         if (argc != 1 || c->display_usage) {
607                 d_printf("%s\n%s",
608                          _("Usage:"),
609                          _("net registry getsd <path>\n"));
610                 d_printf("%s\n%s",
611                          _("Example:"),
612                          _("net registry getsd 'HKLM\\Software\\Samba'\n"));
613                 goto done;
614         }
615
616         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
617         if (!W_ERROR_IS_OK(werr)) {
618                 goto done;
619         }
620
621         display_sec_desc(secdesc);
622
623         ret = 0;
624
625 done:
626         TALLOC_FREE(ctx);
627         return ret;
628 }
629
630 static int net_registry_getsd_sddl(struct net_context *c,
631                                    int argc, const char **argv)
632 {
633         WERROR werr;
634         int ret = -1;
635         struct security_descriptor *secdesc = NULL;
636         TALLOC_CTX *ctx = talloc_stackframe();
637
638         if (argc != 1 || c->display_usage) {
639                 d_printf("%s\n%s",
640                          _("Usage:"),
641                          _("net registry getsd_sddl <path>\n"));
642                 d_printf("%s\n%s",
643                          _("Example:"),
644                          _("net registry getsd_sddl 'HKLM\\Software\\Samba'\n"));
645                 goto done;
646         }
647
648         werr = net_registry_getsd_internal(c, ctx, argv[0], &secdesc);
649         if (!W_ERROR_IS_OK(werr)) {
650                 goto done;
651         }
652
653         d_printf("%s\n", sddl_encode(ctx, secdesc, get_global_sam_sid()));
654
655         ret = 0;
656
657 done:
658         TALLOC_FREE(ctx);
659         return ret;
660 }
661
662 static WERROR net_registry_setsd_internal(struct net_context *c,
663                                           TALLOC_CTX *mem_ctx,
664                                           const char *keyname,
665                                           struct security_descriptor *sd)
666 {
667         WERROR werr;
668         struct registry_key *key = NULL;
669         TALLOC_CTX *ctx = talloc_stackframe();
670         uint32_t access_mask = REG_KEY_WRITE |
671                                SEC_FLAG_MAXIMUM_ALLOWED |
672                                SEC_FLAG_SYSTEM_SECURITY;
673
674         /*
675          * net_rpc_regsitry uses SEC_FLAG_SYSTEM_SECURITY, but access
676          * is denied with these perms right now...
677          */
678         access_mask = REG_KEY_WRITE;
679
680         if (strlen(keyname) == 0) {
681                 d_fprintf(stderr, _("error: zero length key name given\n"));
682                 werr = WERR_INVALID_PARAM;
683                 goto done;
684         }
685
686         werr = open_key(ctx, keyname, access_mask, &key);
687         if (!W_ERROR_IS_OK(werr)) {
688                 d_fprintf(stderr, "%s%s\n", _("open_key failed: "),
689                           win_errstr(werr));
690                 goto done;
691         }
692
693         werr = reg_setkeysecurity(key, sd);
694         if (!W_ERROR_IS_OK(werr)) {
695                 d_fprintf(stderr, "%s%s\n", _("reg_setkeysecurity failed: "),
696                           win_errstr(werr));
697                 goto done;
698         }
699
700         werr = WERR_OK;
701
702 done:
703         TALLOC_FREE(ctx);
704         return werr;
705 }
706
707 static int net_registry_setsd_sddl(struct net_context *c,
708                                    int argc, const char **argv)
709 {
710         WERROR werr;
711         int ret = -1;
712         struct security_descriptor *secdesc = NULL;
713         TALLOC_CTX *ctx = talloc_stackframe();
714
715         if (argc != 2 || c->display_usage) {
716                 d_printf("%s\n%s",
717                          _("Usage:"),
718                          _("net registry setsd_sddl <path> <security_descriptor>\n"));
719                 d_printf("%s\n%s",
720                          _("Example:"),
721                          _("net registry setsd_sddl 'HKLM\\Software\\Samba'\n"));
722                 goto done;
723         }
724
725         secdesc = sddl_decode(ctx, argv[1], get_global_sam_sid());
726         if (secdesc == NULL) {
727                 goto done;
728         }
729
730         werr = net_registry_setsd_internal(c, ctx, argv[0], secdesc);
731         if (!W_ERROR_IS_OK(werr)) {
732                 goto done;
733         }
734
735         ret = 0;
736
737 done:
738         TALLOC_FREE(ctx);
739         return ret;
740 }
741
742 int net_registry(struct net_context *c, int argc, const char **argv)
743 {
744         int ret = -1;
745
746         struct functable func[] = {
747                 {
748                         "enumerate",
749                         net_registry_enumerate,
750                         NET_TRANSPORT_LOCAL,
751                         N_("Enumerate registry keys and values"),
752                         N_("net registry enumerate\n"
753                            "    Enumerate registry keys and values")
754                 },
755                 {
756                         "createkey",
757                         net_registry_createkey,
758                         NET_TRANSPORT_LOCAL,
759                         N_("Create a new registry key"),
760                         N_("net registry createkey\n"
761                            "    Create a new registry key")
762                 },
763                 {
764                         "deletekey",
765                         net_registry_deletekey,
766                         NET_TRANSPORT_LOCAL,
767                         N_("Delete a registry key"),
768                         N_("net registry deletekey\n"
769                            "    Delete a registry key")
770                 },
771                 {
772                         "getvalue",
773                         net_registry_getvalue,
774                         NET_TRANSPORT_LOCAL,
775                         N_("Print a registry value"),
776                         N_("net registry getvalue\n"
777                            "    Print a registry value")
778                 },
779                 {
780                         "getvalueraw",
781                         net_registry_getvalueraw,
782                         NET_TRANSPORT_LOCAL,
783                         N_("Print a registry value (raw format)"),
784                         N_("net registry getvalueraw\n"
785                            "    Print a registry value (raw format)")
786                 },
787                 {
788                         "setvalue",
789                         net_registry_setvalue,
790                         NET_TRANSPORT_LOCAL,
791                         N_("Set a new registry value"),
792                         N_("net registry setvalue\n"
793                            "    Set a new registry value")
794                 },
795                 {
796                         "increment",
797                         net_registry_increment,
798                         NET_TRANSPORT_LOCAL,
799                         N_("Increment a DWORD registry value under a lock"),
800                         N_("net registry increment\n"
801                            "    Increment a DWORD registry value under a lock")
802                 },
803                 {
804                         "deletevalue",
805                         net_registry_deletevalue,
806                         NET_TRANSPORT_LOCAL,
807                         N_("Delete a registry value"),
808                         N_("net registry deletevalue\n"
809                            "    Delete a registry value")
810                 },
811                 {
812                         "getsd",
813                         net_registry_getsd,
814                         NET_TRANSPORT_LOCAL,
815                         N_("Get security descriptor"),
816                         N_("net registry getsd\n"
817                            "    Get security descriptor")
818                 },
819                 {
820                         "getsd_sddl",
821                         net_registry_getsd_sddl,
822                         NET_TRANSPORT_LOCAL,
823                         N_("Get security descriptor in sddl format"),
824                         N_("net registry getsd_sddl\n"
825                            "    Get security descriptor in sddl format")
826                 },
827                 {
828                         "setsd_sddl",
829                         net_registry_setsd_sddl,
830                         NET_TRANSPORT_LOCAL,
831                         N_("Set security descriptor from sddl format string"),
832                         N_("net registry setsd_sddl\n"
833                            "    Set security descriptor from sddl format string")
834                 },
835         { NULL, NULL, 0, NULL, NULL }
836         };
837
838         if (!W_ERROR_IS_OK(registry_init_basic())) {
839                 return -1;
840         }
841
842         ret = net_run_function(c, argc, argv, "net registry", func);
843
844         return ret;
845 }