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