s3-net: Added net rpc conf drop command to net rpc conf
[amitay/samba.git] / source3 / utils / net_rpc_conf.c
1 /*
2  *  Samba Unix/Linux SMB client library
3  *  Distributed SMB/CIFS Server Management Utility
4  *  Local configuration interface
5  *  Copyright (C) Vicentiu Ciorbaru 2011
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /*
22  * This is an interface to Samba's configuration.
23  *
24  * This tool supports local as well as remote interaction via rpc
25  * with the configuration stored in the registry.
26  */
27
28
29 #include "includes.h"
30 #include "utils/net.h"
31 #include "rpc_client/cli_pipe.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "rpc_client/init_samr.h"
34 #include "../librpc/gen_ndr/ndr_winreg_c.h"
35 #include "../libcli/registry/util_reg.h"
36 #include "rpc_client/cli_winreg.h"
37 #include "../lib/smbconf/smbconf.h"
38
39 /* internal functions */
40 /**********************************************************
41  *
42  * usage functions
43  *
44  **********************************************************/
45 const char confpath[100] = "Software\\Samba\\smbconf";
46
47 static int rpc_conf_list_usage(struct net_context *c, int argc,
48                                const char **argv)
49 {
50         d_printf("%s net rpc conf list\n", _("Usage:"));
51         return -1;
52 }
53
54 static int rpc_conf_listshares_usage(struct net_context *c, int argc,
55                                      const char **argv)
56 {
57         d_printf("%s net rpc conf listshares\n", _("Usage:"));
58         return -1;
59 }
60
61 static int rpc_conf_showshare_usage(struct net_context *c, int argc,
62                                     const char **argv)
63 {
64         d_printf("%s\n%s",
65                  _("Usage:"),
66                  _("net rpc conf showshare <sharename>\n"));
67         return -1;
68 }
69
70 static NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx,
71                                    struct dcerpc_binding_handle *b,
72                                    struct policy_handle *parent_hnd,
73                                    const char *share_name,
74                                    struct smbconf_service *share,
75                                    WERROR *werr)
76 {
77         TALLOC_CTX *frame = talloc_stackframe();
78
79         NTSTATUS status = NT_STATUS_OK;
80         WERROR result = WERR_OK;
81         WERROR _werr;
82         struct policy_handle child_hnd;
83         int32_t includes_cnt, includes_idx = -1;
84         uint32_t num_vals, i, param_cnt = 0;
85         const char **val_names;
86         enum winreg_Type *types;
87         DATA_BLOB *data;
88         struct winreg_String key;
89         const char **multi_s = NULL;
90         const char *s = NULL;
91         struct smbconf_service tmp_share;
92
93         ZERO_STRUCT(tmp_share);
94
95         key.name = share_name;
96         status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, key, 0,
97                                REG_KEY_READ, &child_hnd, &result);
98
99         if (!(NT_STATUS_IS_OK(status))) {
100                 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
101                                 nt_errstr(status));
102                 goto error;
103         }
104         if (!(W_ERROR_IS_OK(result))) {
105                 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
106                                 win_errstr(result));
107                 goto error;
108         }
109         /* get all the info from the share key */
110         status = dcerpc_winreg_enumvals(frame,
111                         b,
112                         &child_hnd,
113                         &num_vals,
114                         &val_names,
115                         &types,
116                         &data,
117                         &result);
118
119         if (!(NT_STATUS_IS_OK(status))) {
120                 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
121                                 nt_errstr(status));
122                 goto error;
123         }
124         if (!(W_ERROR_IS_OK(result))) {
125                 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
126                                 win_errstr(result));
127                 goto error;
128         }
129         /* check for includes */
130         for (i = 0; i < num_vals; i++) {
131                 if (strcmp(val_names[i], "includes") == 0){
132                         if (!pull_reg_multi_sz(frame,
133                                                &data[i],
134                                                &multi_s))
135                         {
136                                 result = WERR_NOMEM;
137                                 d_fprintf(stderr,
138                                           _("Failed to enumerate values: %s\n"),
139                                           win_errstr(result));
140                                 goto error;
141                         }
142                         includes_idx = i;
143                 }
144         }
145         /* count the number of includes */
146         includes_cnt = 0;
147         if (includes_idx != -1) {
148                 for (includes_cnt = 0;
149                      multi_s[includes_cnt] != NULL;
150                      includes_cnt ++);
151         }
152         /* place the name of the share in the smbconf_service struct */
153         tmp_share.name = talloc_strdup(frame, share_name);
154         if (tmp_share.name == NULL) {
155                 result = WERR_NOMEM;
156                 d_fprintf(stderr, _("Failed to create share: %s\n"),
157                                 win_errstr(result));
158                 goto error;
159         }
160         /* place the number of parameters in the smbconf_service struct */
161         tmp_share.num_params = num_vals;
162         if (includes_idx != -1) {
163                 tmp_share.num_params = num_vals + includes_cnt - 1;
164         }
165         /* allocate memory for the param_names and param_values lists */
166         tmp_share.param_names = talloc_zero_array(frame, char *, tmp_share.num_params);
167         if (tmp_share.param_names == NULL) {
168                 result = WERR_NOMEM;
169                 d_fprintf(stderr, _("Failed to create share: %s\n"),
170                                 win_errstr(result));
171                 goto error;
172         }
173         tmp_share.param_values = talloc_zero_array(frame, char *, tmp_share.num_params);
174         if (tmp_share.param_values == NULL) {
175                 result = WERR_NOMEM;
176                 d_fprintf(stderr, _("Failed to create share: %s\n"),
177                                 win_errstr(result));
178                 goto error;
179         }
180         /* place all params except includes */
181         for (i = 0; i < num_vals; i++) {
182                 if (strcmp(val_names[i], "includes") != 0) {
183                         if (!pull_reg_sz(frame, &data[i], &s)) {
184                                 result = WERR_NOMEM;
185                                 d_fprintf(stderr,
186                                           _("Failed to enumerate values: %s\n"),
187                                           win_errstr(result));
188                                 goto error;
189                         }
190                         /* place param_names */
191                         tmp_share.param_names[param_cnt] = talloc_strdup(frame, val_names[i]);
192                         if (tmp_share.param_names[param_cnt] == NULL) {
193                                 result = WERR_NOMEM;
194                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
195                                                 win_errstr(result));
196                                 goto error;
197                         }
198
199                         /* place param_values */
200                         tmp_share.param_values[param_cnt++] = talloc_strdup(frame, s);
201                         if (tmp_share.param_values[param_cnt - 1] == NULL) {
202                                 result = WERR_NOMEM;
203                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
204                                                 win_errstr(result));
205                                 goto error;
206                         }
207                 }
208         }
209         /* place the includes last */
210         for (i = 0; i < includes_cnt; i++) {
211                 tmp_share.param_names[param_cnt] = talloc_strdup(frame, "include");
212                 if (tmp_share.param_names[param_cnt] == NULL) {
213                                 result = WERR_NOMEM;
214                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
215                                                 win_errstr(result));
216                                 goto error;
217                 }
218
219                 tmp_share.param_values[param_cnt++] = talloc_strdup(frame, multi_s[i]);
220                 if (tmp_share.param_values[param_cnt - 1] == NULL) {
221                                 result = WERR_NOMEM;
222                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
223                                                 win_errstr(result));
224                                 goto error;
225                 }
226         }
227
228         /* move everything to the main memory ctx */
229         for (i = 0; i < param_cnt; i++) {
230                 tmp_share.param_names[i] = talloc_move(mem_ctx, &tmp_share.param_names[i]);
231                 tmp_share.param_values[i] = talloc_move(mem_ctx, &tmp_share.param_values[i]);
232         }
233
234         tmp_share.name = talloc_move(mem_ctx, &tmp_share.name);
235         tmp_share.param_names = talloc_move(mem_ctx, &tmp_share.param_names);
236         tmp_share.param_values = talloc_move(mem_ctx, &tmp_share.param_values);
237         /* out parameter */
238         *share = tmp_share;
239 error:
240         /* close child */
241         dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr);
242         *werr = result;
243         TALLOC_FREE(frame);
244         return status;
245 }
246
247 static int rpc_conf_print_shares(uint32_t num_shares,
248                                  struct smbconf_service *shares)
249 {
250
251         uint32_t share_count, param_count;
252         const char *indent = "\t";
253
254         if (num_shares == 0) {
255                 return 0;
256         }
257
258         for (share_count = 0; share_count < num_shares; share_count++) {
259                 d_printf("\n");
260                 if (shares[share_count].name != NULL) {
261                 d_printf("[%s]\n", shares[share_count].name);
262                 }
263
264                 for (param_count = 0;
265                      param_count < shares[share_count].num_params;
266                      param_count++)
267                 {
268                         d_printf("%s%s = %s\n",
269                                  indent,
270                                  shares[share_count].param_names[param_count],
271                                  shares[share_count].param_values[param_count]);
272                 }
273         }
274         d_printf("\n");
275
276         return 0;
277
278 }
279 static NTSTATUS rpc_conf_open_conf(TALLOC_CTX *mem_ctx,
280                                    struct dcerpc_binding_handle *b,
281                                    uint32_t access_mask,
282                                    struct policy_handle *hive_hnd,
283                                    struct policy_handle *key_hnd,
284                                    WERROR *werr)
285 {
286         TALLOC_CTX *frame = talloc_stackframe();
287         NTSTATUS status = NT_STATUS_OK;
288         WERROR result = WERR_OK;
289         WERROR _werr;
290         struct policy_handle tmp_hive_hnd, tmp_key_hnd;
291         struct winreg_String key;
292
293         ZERO_STRUCT(key);
294
295         status = dcerpc_winreg_OpenHKLM(b, frame, NULL,
296                         access_mask, &tmp_hive_hnd, &result);
297
298         /*
299          * print no error messages if it is a read only open
300          * and key does not exist
301          * error still gets returned
302          */
303
304         if (access_mask == REG_KEY_READ &&
305             W_ERROR_EQUAL(result, WERR_BADFILE))
306         {
307                 goto error;
308         }
309
310         if (!(NT_STATUS_IS_OK(status))) {
311                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
312                                 nt_errstr(status));
313                 goto error;
314         }
315         if (!W_ERROR_IS_OK(result)) {
316                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
317                                 win_errstr(result));
318                 goto error;
319         }
320
321         key.name = confpath;
322         status = dcerpc_winreg_OpenKey(b, frame, &tmp_hive_hnd, key, 0,
323                                        access_mask, &tmp_key_hnd, &result);
324
325         /*
326          * print no error messages if it is a read only open
327          * and key does not exist
328          * error still gets returned
329          */
330
331         if (access_mask == REG_KEY_READ &&
332             W_ERROR_EQUAL(result, WERR_BADFILE))
333         {
334                 goto error;
335         }
336
337         if (!(NT_STATUS_IS_OK(status))) {
338                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
339                                 nt_errstr(status));
340                 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
341                 goto error;
342         }
343         if (!(W_ERROR_IS_OK(result))) {
344                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
345                         win_errstr(result));
346                 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
347                 goto error;
348         }
349
350         *hive_hnd = tmp_hive_hnd;
351         *key_hnd = tmp_key_hnd;
352
353 error:
354         TALLOC_FREE(frame);
355         *werr = result;
356
357         return status;
358 }
359
360 static NTSTATUS rpc_conf_listshares_internal(struct net_context *c,
361                                              const struct dom_sid *domain_sid,
362                                              const char *domain_name,
363                                              struct cli_state *cli,
364                                              struct rpc_pipe_client *pipe_hnd,
365                                              TALLOC_CTX *mem_ctx,
366                                              int argc,
367                                              const char **argv )
368 {
369
370         TALLOC_CTX *frame = talloc_stackframe();
371         NTSTATUS status = NT_STATUS_OK;
372         WERROR werr = WERR_OK;
373         WERROR _werr;
374
375         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
376
377         /* key info */
378         struct policy_handle hive_hnd, key_hnd;
379         uint32_t num_subkeys;
380         uint32_t i;
381         const char **subkeys = NULL;
382
383
384         ZERO_STRUCT(hive_hnd);
385         ZERO_STRUCT(key_hnd);
386
387
388         if (argc != 0 || c->display_usage) {
389                 rpc_conf_listshares_usage(c, argc, argv);
390                 status = NT_STATUS_INVALID_PARAMETER;
391                 goto error;
392         }
393
394
395         status = rpc_conf_open_conf(frame,
396                                     b,
397                                     REG_KEY_READ,
398                                     &hive_hnd,
399                                     &key_hnd,
400                                     &werr);
401
402         if (!(NT_STATUS_IS_OK(status))) {
403                 goto error;
404         }
405
406         if (!(W_ERROR_IS_OK(werr))) {
407                 goto error;
408         }
409
410         status = dcerpc_winreg_enum_keys(frame,
411                                          b,
412                                          &key_hnd,
413                                          &num_subkeys,
414                                          &subkeys,
415                                          &werr);
416
417         if (!(NT_STATUS_IS_OK(status))) {
418                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
419                                 nt_errstr(status));
420                 goto error;
421         }
422
423         if (!(W_ERROR_IS_OK(werr))) {
424                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
425                                 win_errstr(werr));
426                 goto error;
427         }
428
429         for (i = 0; i < num_subkeys; i++) {
430                 d_printf("%s\n", subkeys[i]);
431         }
432
433 error:
434         if (!(W_ERROR_IS_OK(werr))) {
435                 status =  werror_to_ntstatus(werr);
436         }
437
438         dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
439         dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
440
441         TALLOC_FREE(frame);
442         return status;;
443 }
444
445 static NTSTATUS rpc_conf_list_internal(struct net_context *c,
446                                        const struct dom_sid *domain_sid,
447                                        const char *domain_name,
448                                        struct cli_state *cli,
449                                        struct rpc_pipe_client *pipe_hnd,
450                                        TALLOC_CTX *mem_ctx,
451                                        int argc,
452                                        const char **argv )
453 {
454
455         TALLOC_CTX *frame = talloc_stackframe();
456         NTSTATUS status = NT_STATUS_OK;
457         WERROR werr = WERR_OK;
458         WERROR _werr;
459
460         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
461
462         /* key info */
463         struct policy_handle hive_hnd, key_hnd;
464         uint32_t num_subkeys;
465         uint32_t i;
466         struct smbconf_service *shares;
467         const char **subkeys = NULL;
468
469
470         ZERO_STRUCT(hive_hnd);
471         ZERO_STRUCT(key_hnd);
472
473
474         if (argc != 0 || c->display_usage) {
475                 rpc_conf_list_usage(c, argc, argv);
476                 status = NT_STATUS_INVALID_PARAMETER;
477                 goto error;
478         }
479
480         status = rpc_conf_open_conf(frame,
481                                     b,
482                                     REG_KEY_READ,
483                                     &hive_hnd,
484                                     &key_hnd,
485                                     &werr);
486
487         if (!(NT_STATUS_IS_OK(status))) {
488                 goto error;
489         }
490
491         if (!(W_ERROR_IS_OK(werr))) {
492                 goto error;
493         }
494
495         status = dcerpc_winreg_enum_keys(frame,
496                                          b,
497                                          &key_hnd,
498                                          &num_subkeys,
499                                          &subkeys,
500                                          &werr);
501
502         if (!(NT_STATUS_IS_OK(status))) {
503                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
504                                 nt_errstr(status));
505                 goto error;
506         }
507
508         if (!(W_ERROR_IS_OK(werr))) {
509                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
510                                 win_errstr(werr));
511                 goto error;
512         }
513
514         if (num_subkeys == 0) {
515                 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
516                 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
517                 TALLOC_FREE(frame);
518                 return NT_STATUS_OK;
519         }
520
521         /* get info from each subkey */
522         shares = talloc_zero_array(frame, struct smbconf_service, num_subkeys);
523         if (shares == NULL) {
524                 werr = WERR_NOMEM;
525                 d_fprintf(stderr, _("Failed to create shares: %s\n"),
526                                 win_errstr(werr));
527                 goto error;
528
529         }
530
531         for (i = 0; i < num_subkeys; i++) {
532                 /* get each share and place it in the shares array */
533                 status = rpc_conf_get_share(frame,
534                                 b,
535                                 &key_hnd,
536                                 subkeys[i],
537                                 &shares[i],
538                                 &werr);
539                 if (!(NT_STATUS_IS_OK(status))) {
540                         goto error;
541                 }
542                 if (!(W_ERROR_IS_OK(werr))) {
543                         goto error;
544                 }
545
546         }
547         /* print the shares array */
548         rpc_conf_print_shares(num_subkeys, shares);
549
550 error:
551         if (!(W_ERROR_IS_OK(werr))) {
552                 status =  werror_to_ntstatus(werr);
553         }
554
555         dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
556         dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
557
558         TALLOC_FREE(frame);
559         return status;
560
561 }
562
563 static NTSTATUS rpc_conf_showshare_internal(struct net_context *c,
564                                             const struct dom_sid *domain_sid,
565                                             const char *domain_name,
566                                             struct cli_state *cli,
567                                             struct rpc_pipe_client *pipe_hnd,
568                                             TALLOC_CTX *mem_ctx,
569                                             int argc,
570                                             const char **argv )
571 {
572         TALLOC_CTX *frame = talloc_stackframe();
573         NTSTATUS status = NT_STATUS_OK;
574         WERROR werr = WERR_OK;
575         WERROR _werr;
576
577         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
578
579         /* key info */
580         struct policy_handle hive_hnd, key_hnd;
581         struct smbconf_service *service = NULL;
582         const char *sharename = NULL;
583
584
585         ZERO_STRUCT(hive_hnd);
586         ZERO_STRUCT(key_hnd);
587
588
589         if (argc != 1 || c->display_usage) {
590                 rpc_conf_showshare_usage(c, argc, argv);
591                 status = NT_STATUS_INVALID_PARAMETER;
592                 goto error;
593         }
594
595         status = rpc_conf_open_conf(frame,
596                                     b,
597                                     REG_KEY_READ,
598                                     &hive_hnd,
599                                     &key_hnd,
600                                     &werr);
601
602         if (!(NT_STATUS_IS_OK(status))) {
603                 goto error;
604         }
605
606         if (!(W_ERROR_IS_OK(werr))) {
607                 goto error;
608         }
609
610         sharename = talloc_strdup(frame, argv[0]);
611         if (sharename == NULL) {
612                 werr = WERR_NOMEM;
613                 d_fprintf(stderr, _("Failed to create share: %s\n"),
614                                 win_errstr(werr));
615                 goto error;
616         }
617
618         service = talloc(frame, struct smbconf_service);
619         if (service == NULL) {
620                 werr = WERR_NOMEM;
621                 d_fprintf(stderr, _("Failed to create share: %s\n"),
622                                 win_errstr(werr));
623                 goto error;
624         }
625
626         status = rpc_conf_get_share(frame,
627                         b,
628                         &key_hnd,
629                         sharename,
630                         service,
631                         &werr);
632
633         if (!(NT_STATUS_IS_OK(status))) {
634                 goto error;
635         }
636         if (!(W_ERROR_IS_OK(werr))) {
637                 goto error;
638         }
639
640         rpc_conf_print_shares(1, service);
641
642 error:
643         if (!(W_ERROR_IS_OK(werr))) {
644                 status =  werror_to_ntstatus(werr);
645         }
646
647         dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
648         dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
649
650         TALLOC_FREE(frame);
651         return status;
652 }
653
654 static int rpc_conf_drop(struct net_context *c, int argc,
655                                 const char **argv)
656 {
657         d_printf("Function not implemented yet\n");
658         return 0;
659 }
660
661 static int rpc_conf_showshare(struct net_context *c, int argc,
662                                 const char **argv)
663 {
664         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
665                 rpc_conf_showshare_internal, argc, argv );
666 }
667
668 static int rpc_conf_listshares(struct net_context *c, int argc,
669                                 const char **argv)
670 {
671         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
672                 rpc_conf_listshares_internal, argc, argv );
673 }
674
675 static int rpc_conf_list(struct net_context *c, int argc,
676                              const char **argv)
677 {
678         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
679                 rpc_conf_list_internal, argc, argv );
680 }
681
682 /* function calls */
683 int net_rpc_conf(struct net_context *c, int argc,
684                  const char **argv)
685 {
686         struct functable func_table[] = {
687                 {
688                         "list",
689                         rpc_conf_list,
690                         NET_TRANSPORT_RPC,
691                         N_("Dump the complete remote configuration in smb.conf like "
692                            "format."),
693                         N_("net rpc conf list\n"
694                            "    Dump the complete remote configuration in smb.conf "
695                            "like format.")
696
697                 },
698                 {
699                         "listshares",
700                         rpc_conf_listshares,
701                         NET_TRANSPORT_RPC,
702                         N_("List the remote share names."),
703                         N_("net rpc conf list\n"
704                            "    List the remote share names.")
705
706                 },
707                 {
708                         "drop",
709                         rpc_conf_drop,
710                         NET_TRANSPORT_RPC,
711                         N_("Delete the complete remote configuration."),
712                         N_("net rpc conf drop\n"
713                            "    Delete the complete remote configuration.")
714
715                 },
716                 {
717                         "showshare",
718                         rpc_conf_showshare,
719                         NET_TRANSPORT_RPC,
720                         N_("Show the definition of a remote share."),
721                         N_("net rpc conf showshare\n"
722                            "    Show the definition of a remote share.")
723
724                 },
725                 {NULL, NULL, 0, NULL, NULL}
726         };
727
728         return net_run_function(c, argc, argv, "net rpc conf", func_table);
729
730 }