s3-net: Added rpc_conf_open_conf function
[metze/samba/wip.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 NTSTATUS rpc_conf_get_share(TALLOC_CTX *mem_ctx,
55                                    struct dcerpc_binding_handle *b,
56                                    struct policy_handle *parent_hnd,
57                                    const char *share_name,
58                                    struct smbconf_service *share,
59                                    WERROR *werr)
60 {
61         TALLOC_CTX *frame = talloc_stackframe();
62
63         NTSTATUS status = NT_STATUS_OK;
64         WERROR result = WERR_OK;
65         WERROR _werr;
66         struct policy_handle child_hnd;
67         int32_t includes_cnt, includes_idx = -1;
68         uint32_t num_vals, i, param_cnt = 0;
69         const char **val_names;
70         enum winreg_Type *types;
71         DATA_BLOB *data;
72         struct winreg_String key;
73         const char **multi_s = NULL;
74         const char *s = NULL;
75         struct smbconf_service tmp_share;
76
77         ZERO_STRUCT(tmp_share);
78
79         key.name = share_name;
80         status = dcerpc_winreg_OpenKey(b, frame, parent_hnd, key, 0,
81                                REG_KEY_READ, &child_hnd, &result);
82
83         if (!(NT_STATUS_IS_OK(status))) {
84                 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
85                                 nt_errstr(status));
86                 goto error;
87         }
88         if (!(W_ERROR_IS_OK(result))) {
89                 d_fprintf(stderr, _("Failed to open subkey: %s\n"),
90                                 win_errstr(result));
91                 goto error;
92         }
93         /* get all the info from the share key */
94         status = dcerpc_winreg_enumvals(frame,
95                         b,
96                         &child_hnd,
97                         &num_vals,
98                         &val_names,
99                         &types,
100                         &data,
101                         &result);
102
103         if (!(NT_STATUS_IS_OK(status))) {
104                 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
105                                 nt_errstr(status));
106                 goto error;
107         }
108         if (!(W_ERROR_IS_OK(result))) {
109                 d_fprintf(stderr, _("Failed to enumerate values: %s\n"),
110                                 win_errstr(result));
111                 goto error;
112         }
113         /* check for includes */
114         for (i = 0; i < num_vals; i++) {
115                 if (strcmp(val_names[i], "includes") == 0){
116                         if (!pull_reg_multi_sz(frame,
117                                                &data[i],
118                                                &multi_s))
119                         {
120                                 result = WERR_NOMEM;
121                                 d_fprintf(stderr,
122                                           _("Failed to enumerate values: %s\n"),
123                                           win_errstr(result));
124                                 goto error;
125                         }
126                         includes_idx = i;
127                 }
128         }
129         /* count the number of includes */
130         includes_cnt = 0;
131         if (includes_idx != -1) {
132                 for (includes_cnt = 0;
133                      multi_s[includes_cnt] != NULL;
134                      includes_cnt ++);
135         }
136         /* place the name of the share in the smbconf_service struct */
137         tmp_share.name = talloc_strdup(frame, share_name);
138         if (tmp_share.name == NULL) {
139                 result = WERR_NOMEM;
140                 d_fprintf(stderr, _("Failed to create share: %s\n"),
141                                 win_errstr(result));
142                 goto error;
143         }
144         /* place the number of parameters in the smbconf_service struct */
145         tmp_share.num_params = num_vals;
146         if (includes_idx != -1) {
147                 tmp_share.num_params = num_vals + includes_cnt - 1;
148         }
149         /* allocate memory for the param_names and param_values lists */
150         tmp_share.param_names = talloc_zero_array(frame, char *, tmp_share.num_params);
151         if (tmp_share.param_names == NULL) {
152                 result = WERR_NOMEM;
153                 d_fprintf(stderr, _("Failed to create share: %s\n"),
154                                 win_errstr(result));
155                 goto error;
156         }
157         tmp_share.param_values = talloc_zero_array(frame, char *, tmp_share.num_params);
158         if (tmp_share.param_values == NULL) {
159                 result = WERR_NOMEM;
160                 d_fprintf(stderr, _("Failed to create share: %s\n"),
161                                 win_errstr(result));
162                 goto error;
163         }
164         /* place all params except includes */
165         for (i = 0; i < num_vals; i++) {
166                 if (strcmp(val_names[i], "includes") != 0) {
167                         if (!pull_reg_sz(frame, &data[i], &s)) {
168                                 result = WERR_NOMEM;
169                                 d_fprintf(stderr,
170                                           _("Failed to enumerate values: %s\n"),
171                                           win_errstr(result));
172                                 goto error;
173                         }
174                         /* place param_names */
175                         tmp_share.param_names[param_cnt] = talloc_strdup(frame, val_names[i]);
176                         if (tmp_share.param_names[param_cnt] == NULL) {
177                                 result = WERR_NOMEM;
178                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
179                                                 win_errstr(result));
180                                 goto error;
181                         }
182
183                         /* place param_values */
184                         tmp_share.param_values[param_cnt++] = talloc_strdup(frame, s);
185                         if (tmp_share.param_values[param_cnt - 1] == NULL) {
186                                 result = WERR_NOMEM;
187                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
188                                                 win_errstr(result));
189                                 goto error;
190                         }
191                 }
192         }
193         /* place the includes last */
194         for (i = 0; i < includes_cnt; i++) {
195                 tmp_share.param_names[param_cnt] = talloc_strdup(frame, "include");
196                 if (tmp_share.param_names[param_cnt] == NULL) {
197                                 result = WERR_NOMEM;
198                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
199                                                 win_errstr(result));
200                                 goto error;
201                 }
202
203                 tmp_share.param_values[param_cnt++] = talloc_strdup(frame, multi_s[i]);
204                 if (tmp_share.param_values[param_cnt - 1] == NULL) {
205                                 result = WERR_NOMEM;
206                                 d_fprintf(stderr, _("Failed to create share: %s\n"),
207                                                 win_errstr(result));
208                                 goto error;
209                 }
210         }
211
212         /* move everything to the main memory ctx */
213         for (i = 0; i < param_cnt; i++) {
214                 tmp_share.param_names[i] = talloc_move(mem_ctx, &tmp_share.param_names[i]);
215                 tmp_share.param_values[i] = talloc_move(mem_ctx, &tmp_share.param_values[i]);
216         }
217
218         tmp_share.name = talloc_move(mem_ctx, &tmp_share.name);
219         tmp_share.param_names = talloc_move(mem_ctx, &tmp_share.param_names);
220         tmp_share.param_values = talloc_move(mem_ctx, &tmp_share.param_values);
221         /* out parameter */
222         *share = tmp_share;
223 error:
224         /* close child */
225         dcerpc_winreg_CloseKey(b, frame, &child_hnd, &_werr);
226         *werr = result;
227         TALLOC_FREE(frame);
228         return status;
229 }
230
231 static int rpc_conf_print_shares(uint32_t num_shares,
232                                  struct smbconf_service *shares)
233 {
234
235         uint32_t share_count, param_count;
236         const char *indent = "\t";
237
238         if (num_shares == 0) {
239                 return 0;
240         }
241
242         for (share_count = 0; share_count < num_shares; share_count++) {
243                 d_printf("\n");
244                 if (shares[share_count].name != NULL) {
245                 d_printf("[%s]\n", shares[share_count].name);
246                 }
247
248                 for (param_count = 0;
249                      param_count < shares[share_count].num_params;
250                      param_count++)
251                 {
252                         d_printf("%s%s = %s\n",
253                                  indent,
254                                  shares[share_count].param_names[param_count],
255                                  shares[share_count].param_values[param_count]);
256                 }
257         }
258         d_printf("\n");
259
260         return 0;
261
262 }
263 static NTSTATUS rpc_conf_open_conf(TALLOC_CTX *mem_ctx,
264                                    struct dcerpc_binding_handle *b,
265                                    uint32_t access_mask,
266                                    struct policy_handle *hive_hnd,
267                                    struct policy_handle *key_hnd,
268                                    WERROR *werr)
269 {
270         TALLOC_CTX *frame = talloc_stackframe();
271         NTSTATUS status = NT_STATUS_OK;
272         WERROR result = WERR_OK;
273         WERROR _werr;
274         struct policy_handle tmp_hive_hnd, tmp_key_hnd;
275         struct winreg_String key;
276
277         ZERO_STRUCT(key);
278
279         status = dcerpc_winreg_OpenHKLM(b, frame, NULL,
280                         access_mask, &tmp_hive_hnd, &result);
281
282         /*
283          * print no error messages if it is a read only open
284          * and key does not exist
285          * error still gets returned
286          */
287
288         if (access_mask == REG_KEY_READ &&
289             W_ERROR_EQUAL(result, WERR_BADFILE))
290         {
291                 goto error;
292         }
293
294         if (!(NT_STATUS_IS_OK(status))) {
295                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
296                                 nt_errstr(status));
297                 goto error;
298         }
299         if (!W_ERROR_IS_OK(result)) {
300                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
301                                 win_errstr(result));
302                 goto error;
303         }
304
305         key.name = confpath;
306         status = dcerpc_winreg_OpenKey(b, frame, &tmp_hive_hnd, key, 0,
307                                        access_mask, &tmp_key_hnd, &result);
308
309         /*
310          * print no error messages if it is a read only open
311          * and key does not exist
312          * error still gets returned
313          */
314
315         if (access_mask == REG_KEY_READ &&
316             W_ERROR_EQUAL(result, WERR_BADFILE))
317         {
318                 goto error;
319         }
320
321         if (!(NT_STATUS_IS_OK(status))) {
322                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
323                                 nt_errstr(status));
324                 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
325                 goto error;
326         }
327         if (!(W_ERROR_IS_OK(result))) {
328                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
329                         win_errstr(result));
330                 dcerpc_winreg_CloseKey(b, frame, &tmp_hive_hnd, &_werr);
331                 goto error;
332         }
333
334         *hive_hnd = tmp_hive_hnd;
335         *key_hnd = tmp_key_hnd;
336
337 error:
338         TALLOC_FREE(frame);
339         *werr = result;
340
341         return status;
342 }
343
344 static NTSTATUS rpc_conf_list_internal(struct net_context *c,
345                                        const struct dom_sid *domain_sid,
346                                        const char *domain_name,
347                                        struct cli_state *cli,
348                                        struct rpc_pipe_client *pipe_hnd,
349                                        TALLOC_CTX *mem_ctx,
350                                        int argc,
351                                        const char **argv )
352 {
353
354         TALLOC_CTX *frame = talloc_stackframe();
355         NTSTATUS status = NT_STATUS_OK;
356         WERROR werr = WERR_OK;
357         WERROR _werr;
358         struct winreg_String key;
359
360         struct dcerpc_binding_handle *b = pipe_hnd->binding_handle;
361
362         /* key info */
363         struct policy_handle hive_hnd, key_hnd;
364         uint32_t num_subkeys;
365         uint32_t i;
366         struct smbconf_service *shares;
367         const char **subkeys = NULL;
368
369
370         ZERO_STRUCT(key);
371         ZERO_STRUCT(hive_hnd);
372         ZERO_STRUCT(key_hnd);
373
374
375         if (argc != 0 || c->display_usage) {
376                 rpc_conf_list_usage(c, argc, argv);
377                 status = NT_STATUS_INVALID_PARAMETER;
378                 goto error;
379         }
380
381         status = dcerpc_winreg_OpenHKLM(b, frame, NULL,
382                         REG_KEY_READ, &hive_hnd, &werr);
383
384         if (!(NT_STATUS_IS_OK(status))) {
385                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
386                                 nt_errstr(status));
387                 goto error;
388         }
389         if (!W_ERROR_IS_OK(werr)) {
390                 d_fprintf(stderr, _("Failed to open hive: %s\n"),
391                                 win_errstr(werr));
392                 goto error;
393         }
394
395         key.name = confpath;
396         status = dcerpc_winreg_OpenKey(b, frame, &hive_hnd, key, 0,
397                                        REG_KEY_READ, &key_hnd, &werr);
398
399         if (!(NT_STATUS_IS_OK(status))) {
400                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
401                                 nt_errstr(status));
402                 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
403                 goto error;
404         }
405         if (!(W_ERROR_IS_OK(werr))) {
406                 d_fprintf(stderr, _("Failed to open smbconf key: %s\n"),
407                         win_errstr(werr));
408                 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
409                 goto error;
410         }
411
412         status = dcerpc_winreg_enum_keys(frame,
413                                          b,
414                                          &key_hnd,
415                                          &num_subkeys,
416                                          &subkeys,
417                                          &werr);
418
419         if (!(NT_STATUS_IS_OK(status))) {
420                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
421                                 nt_errstr(status));
422                 goto error;
423         }
424
425         if (!(W_ERROR_IS_OK(werr))) {
426                 d_fprintf(stderr, _("Failed to enumerate keys: %s\n"),
427                                 win_errstr(werr));
428                 goto error;
429         }
430
431         if (num_subkeys == 0) {
432                 dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
433                 dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
434                 TALLOC_FREE(frame);
435                 return NT_STATUS_OK;
436         }
437
438         /* get info from each subkey */
439         shares = talloc_zero_array(frame, struct smbconf_service, num_subkeys);
440         if (shares == NULL) {
441                 werr = WERR_NOMEM;
442                 d_fprintf(stderr, _("Failed to create shares: %s\n"),
443                                 win_errstr(werr));
444                 goto error;
445
446         }
447
448         for (i = 0; i < num_subkeys; i++) {
449                 /* get each share and place it in the shares array */
450                 status = rpc_conf_get_share(frame,
451                                 b,
452                                 &key_hnd,
453                                 subkeys[i],
454                                 &shares[i],
455                                 &werr);
456                 if (!(NT_STATUS_IS_OK(status))) {
457                         goto error;
458                 }
459                 if (!(W_ERROR_IS_OK(werr))) {
460                         goto error;
461                 }
462
463         }
464         /* print the shares array */
465         rpc_conf_print_shares(num_subkeys, shares);
466
467 error:
468         if (!(W_ERROR_IS_OK(werr))) {
469                 status =  werror_to_ntstatus(werr);
470         }
471
472         dcerpc_winreg_CloseKey(b, frame, &hive_hnd, &_werr);
473         dcerpc_winreg_CloseKey(b, frame, &key_hnd, &_werr);
474
475         TALLOC_FREE(frame);
476         return status;
477
478 }
479
480
481 static int rpc_conf_list(struct net_context *c, int argc,
482                              const char **argv)
483 {
484         return run_rpc_command(c, NULL, &ndr_table_winreg.syntax_id, 0,
485                 rpc_conf_list_internal, argc, argv );
486 }
487
488 /* function calls */
489 int net_rpc_conf(struct net_context *c, int argc,
490                  const char **argv)
491 {
492         struct functable func_table[] = {
493                 {
494                         "list",
495                         rpc_conf_list,
496                         NET_TRANSPORT_RPC,
497                         N_("Dump the complete remote configuration in smb.conf like "
498                            "format."),
499                         N_("net rpc conf list\n"
500                            "    Dump the complete remote configuration in smb.conf "
501                            "like format.")
502
503                 },
504                 {NULL, NULL, 0, NULL, NULL}
505         };
506
507         return net_run_function(c, argc, argv, "net rpc conf", func_table);
508
509 }