r26111: Fix an uninitialized variable
[gd/samba-autobuild/.git] / source4 / torture / rpc / dfs.c
1 /*
2    Unix SMB/CIFS implementation.
3    test suite for rpc dfs operations
4
5    Copyright (C) Andrew Tridgell 2003
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 2 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, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "torture/torture.h"
24 #include "torture/rpc/rpc.h"
25 #include "librpc/gen_ndr/ndr_dfs_c.h"
26 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
27 #include "libnet/libnet.h"
28 #include "libcli/raw/libcliraw.h"
29 #include "torture/util.h"
30 #include "libcli/libcli.h"
31 #include "lib/cmdline/popt_common.h"
32
33 #define SMBTORTURE_DFS_SHARENAME "smbtorture_dfs_share"
34 #define SMBTORTURE_DFS_DIRNAME "\\smbtorture_dfs_dir"
35 #define SMBTORTURE_DFS_PATHNAME "C:"SMBTORTURE_DFS_DIRNAME
36
37 #define IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(x,y)\
38         if (x == DFS_MANAGER_VERSION_W2K3) {\
39                 if (!W_ERROR_EQUAL(y,WERR_NOT_SUPPORTED)) {\
40                         printf("expected WERR_NOT_SUPPORTED\n");\
41                         return false;\
42                 }\
43                 return true;\
44         }\
45
46 static bool test_NetShareAdd(TALLOC_CTX *mem_ctx,
47                              const char *host,
48                              const char *sharename,
49                              const char *dir)
50 {
51         NTSTATUS status;
52         struct srvsvc_NetShareInfo2 i;
53         struct libnet_context* libnetctx;
54         struct libnet_AddShare r;
55
56         printf("Creating share %s\n", sharename);
57
58         if (!(libnetctx = libnet_context_init(NULL))) {
59                 return false;
60         }
61
62         libnetctx->cred = cmdline_credentials;
63
64         i.name                  = sharename;
65         i.type                  = STYPE_DISKTREE;
66         i.path                  = dir;
67         i.max_users             = (uint32_t) -1;
68         i.comment               = "created by smbtorture";
69         i.password              = NULL;
70         i.permissions           = 0x0;
71         i.current_users         = 0x0;
72
73         r.level                 = 2;
74         r.in.server_name        = host;
75         r.in.share              = i;
76
77         status = libnet_AddShare(libnetctx, mem_ctx, &r);
78         if (!NT_STATUS_IS_OK(status)) {
79                 d_printf("Failed to add new share: %s (%s)\n",
80                         nt_errstr(status), r.out.error_string);
81                 return false;
82         }
83
84         return true;
85 }
86
87 static bool test_NetShareDel(TALLOC_CTX *mem_ctx,
88                              const char *host,
89                              const char *sharename)
90 {
91         NTSTATUS status;
92         struct libnet_context* libnetctx;
93         struct libnet_DelShare r;
94
95         printf("Deleting share %s\n", sharename);
96
97         if (!(libnetctx = libnet_context_init(NULL))) {
98                 return false;
99         }
100
101         libnetctx->cred = cmdline_credentials;
102
103         r.in.share_name         = sharename;
104         r.in.server_name        = host;
105
106         status = libnet_DelShare(libnetctx, mem_ctx, &r);
107         if (!NT_STATUS_IS_OK(status)) {
108                 d_printf("Failed to delete share: %s (%s)\n",
109                         nt_errstr(status), r.out.error_string);
110                 return false;
111         }
112
113         return true;
114 }
115
116 static bool test_CreateDir(TALLOC_CTX *mem_ctx,
117                            struct smbcli_state **cli,
118                            const char *host,
119                            const char *share,
120                            const char *dir)
121 {
122         printf("Creating directory %s\n", dir);
123
124         if (!torture_open_connection_share(mem_ctx, cli, host, share, NULL)) {
125                 return false;
126         }
127
128         if (!torture_setup_dir(*cli, dir)) {
129                 return false;
130         }
131
132         return true;
133 }
134
135 static bool test_DeleteDir(struct smbcli_state *cli,
136                            const char *dir)
137 {
138         printf("Deleting directory %s\n", dir);
139
140         if (smbcli_deltree(cli->tree, dir) == -1) {
141                 printf("Unable to delete dir %s - %s\n", dir,
142                         smbcli_errstr(cli->tree));
143                 return false;
144         }
145
146         return true;
147 }
148
149 static bool test_GetManagerVersion(struct dcerpc_pipe *p,
150                                    TALLOC_CTX *mem_ctx,
151                                    enum dfs_ManagerVersion *version)
152 {
153         NTSTATUS status;
154         struct dfs_GetManagerVersion r;
155
156         r.out.version = version;
157
158         status = dcerpc_dfs_GetManagerVersion(p, mem_ctx, &r);
159         if (!NT_STATUS_IS_OK(status)) {
160                 printf("GetManagerVersion failed - %s\n", nt_errstr(status));
161                 return false;
162         }
163
164         return true;
165 }
166
167 static bool test_ManagerInitialize(struct dcerpc_pipe *p,
168                                    TALLOC_CTX *mem_ctx,
169                                    const char *host)
170 {
171         NTSTATUS status;
172         enum dfs_ManagerVersion version;
173         struct dfs_ManagerInitialize r;
174
175         printf("Testing ManagerInitialize\n");
176
177         if (!test_GetManagerVersion(p, mem_ctx, &version)) {
178                 return false;
179         }
180
181         r.in.servername = host;
182         r.in.flags = 0;
183
184         status = dcerpc_dfs_ManagerInitialize(p, mem_ctx, &r);
185         if (!NT_STATUS_IS_OK(status)) {
186                 printf("ManagerInitialize failed - %s\n", nt_errstr(status));
187                 return false;
188         } else if (!W_ERROR_IS_OK(r.out.result)) {
189                 printf("dfs_ManagerInitialize failed - %s\n",
190                         win_errstr(r.out.result));
191                 IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
192                 return false;
193         }
194
195         return true;
196 }
197
198 static bool test_GetInfoLevel(struct dcerpc_pipe *p,
199                               TALLOC_CTX *mem_ctx,
200                               uint16_t level,
201                               const char *root)
202 {
203         NTSTATUS status;
204         struct dfs_GetInfo r;
205
206         printf("Testing GetInfo level %u on '%s'\n", level, root);
207
208         r.in.dfs_entry_path = talloc_strdup(mem_ctx, root);
209         r.in.servername = NULL;
210         r.in.sharename = NULL;
211         r.in.level = level;
212
213         status = dcerpc_dfs_GetInfo(p, mem_ctx, &r);
214         if (!NT_STATUS_IS_OK(status)) {
215                 printf("GetInfo failed - %s\n", nt_errstr(status));
216                 return false;
217         } else if (!W_ERROR_IS_OK(r.out.result) &&
218                    !W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result)) {
219                 printf("dfs_GetInfo failed - %s\n", win_errstr(r.out.result));
220                 return false;
221         }
222
223         return true;
224 }
225
226 static bool test_GetInfo(struct dcerpc_pipe *p,
227                          TALLOC_CTX *mem_ctx,
228                          const char *root)
229 {
230         bool ret = true;
231         /* 103, 104, 105, 106 is only available on Set */
232         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106};
233         int i;
234
235         for (i=0;i<ARRAY_SIZE(levels);i++) {
236                 if (!test_GetInfoLevel(p, mem_ctx, levels[i], root)) {
237                         ret = false;
238                 }
239         }
240         return ret;
241 }
242
243 static bool test_EnumLevelEx(struct dcerpc_pipe *p,
244                              TALLOC_CTX *mem_ctx,
245                              uint16_t level,
246                              const char *dfs_name)
247 {
248         NTSTATUS status;
249         struct dfs_EnumEx rex;
250         uint32_t total=0;
251         struct dfs_EnumStruct e;
252         struct dfs_Info1 s;
253         struct dfs_EnumArray1 e1;
254         bool ret = true;
255
256         rex.in.level = level;
257         rex.in.bufsize = (uint32_t)-1;
258         rex.in.total = &total;
259         rex.in.info = &e;
260         rex.in.dfs_name = dfs_name;
261
262         e.level = rex.in.level;
263         e.e.info1 = &e1;
264         e.e.info1->count = 0;
265         e.e.info1->s = &s;
266         s.path = NULL;
267
268         printf("Testing EnumEx level %u on '%s'\n", level, dfs_name);
269
270         status = dcerpc_dfs_EnumEx(p, mem_ctx, &rex);
271         if (!NT_STATUS_IS_OK(status)) {
272                 printf("EnumEx failed - %s\n", nt_errstr(status));
273                 return false;
274         }
275
276         if (level == 1 && rex.out.total) {
277                 int i;
278                 for (i=0;i<*rex.out.total;i++) {
279                         const char *root = talloc_strdup(mem_ctx,
280                                 rex.out.info->e.info1->s[i].path);
281                         if (!test_GetInfo(p, mem_ctx, root)) {
282                                 ret = false;
283                         }
284                 }
285         }
286
287         if (level == 300 && rex.out.total) {
288                 int i,k;
289                 for (i=0;i<*rex.out.total;i++) {
290                         uint16_t levels[] = {1, 2, 3, 4, 200}; /* 300 */
291                         const char *root = talloc_strdup(mem_ctx,
292                                 rex.out.info->e.info300->s[i].dom_root);
293                         for (k=0;k<ARRAY_SIZE(levels);k++) {
294                                 if (!test_EnumLevelEx(p, mem_ctx,
295                                                       levels[k], root))
296                                 {
297                                         ret = false;
298                                 }
299                         }
300                         if (!test_GetInfo(p, mem_ctx, root)) {
301                                 ret = false;
302                         }
303                 }
304         }
305
306         return ret;
307 }
308
309
310 static bool test_EnumLevel(struct dcerpc_pipe *p,
311                            TALLOC_CTX *mem_ctx,
312                            uint16_t level)
313 {
314         NTSTATUS status;
315         struct dfs_Enum r;
316         uint32_t total=0;
317         struct dfs_EnumStruct e;
318         struct dfs_Info1 s;
319         struct dfs_EnumArray1 e1;
320         bool ret = true;
321
322         r.in.level = level;
323         r.in.bufsize = (uint32_t)-1;
324         r.in.total = &total;
325         r.in.info = &e;
326
327         e.level = r.in.level;
328         e.e.info1 = &e1;
329         e.e.info1->count = 0;
330         e.e.info1->s = &s;
331         s.path = NULL;
332
333         printf("Testing Enum level %u\n", level);
334
335         status = dcerpc_dfs_Enum(p, mem_ctx, &r);
336         if (!NT_STATUS_IS_OK(status)) {
337                 printf("Enum failed - %s\n", nt_errstr(status));
338                 return false;
339         } else if (!W_ERROR_IS_OK(r.out.result) &&
340                    !W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result)) {
341                 printf("dfs_Enum failed - %s\n", win_errstr(r.out.result));
342                 return false;
343         }
344
345         if (level == 1 && r.out.total) {
346                 int i;
347                 for (i=0;i<*r.out.total;i++) {
348                         const char *root = r.out.info->e.info1->s[i].path;
349                         if (!test_GetInfo(p, mem_ctx, root)) {
350                                 ret = false;
351                         }
352                 }
353
354         }
355
356         return ret;
357 }
358
359
360 static bool test_Enum(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
361 {
362         bool ret = true;
363         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 200, 300};
364         int i;
365
366         for (i=0;i<ARRAY_SIZE(levels);i++) {
367                 if (!test_EnumLevel(p, mem_ctx, levels[i])) {
368                         ret = false;
369                 }
370         }
371
372         return ret;
373 }
374
375 static bool test_EnumEx(struct dcerpc_pipe *p,
376                         TALLOC_CTX *mem_ctx,
377                         const char *host)
378 {
379         bool ret = true;
380         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 200, 300};
381         int i;
382
383         for (i=0;i<ARRAY_SIZE(levels);i++) {
384                 if (!test_EnumLevelEx(p, mem_ctx, levels[i], host)) {
385                         ret = false;
386                 }
387         }
388
389         return ret;
390 }
391
392 static bool test_RemoveStdRoot(struct dcerpc_pipe *p,
393                                TALLOC_CTX *mem_ctx,
394                                const char *host,
395                                const char *sharename)
396 {
397         struct dfs_RemoveStdRoot r;
398         NTSTATUS status;
399
400         printf("Testing RemoveStdRoot\n");
401
402         r.in.servername = host;
403         r.in.rootshare  = sharename;
404         r.in.flags      = 0;
405
406         status = dcerpc_dfs_RemoveStdRoot(p, mem_ctx, &r);
407         if (!NT_STATUS_IS_OK(status)) {
408                 printf("RemoveStdRoot failed - %s\n", nt_errstr(status));
409                 return false;
410         } else if (!W_ERROR_IS_OK(r.out.result)) {
411                 printf("dfs_RemoveStdRoot failed - %s\n",
412                         win_errstr(r.out.result));
413                 return false;
414         }
415
416         return true;
417 }
418
419 static bool test_AddStdRoot(struct dcerpc_pipe *p,
420                             TALLOC_CTX *mem_ctx,
421                             const char *host,
422                             const char *sharename)
423 {
424         NTSTATUS status;
425         struct dfs_AddStdRoot r;
426
427         printf("Testing AddStdRoot\n");
428
429         r.in.servername = host;
430         r.in.rootshare  = sharename;
431         r.in.comment    = "standard dfs standalone DFS root created by smbtorture (dfs_AddStdRoot)";
432         r.in.flags      = 0;
433
434         status = dcerpc_dfs_AddStdRoot(p, mem_ctx, &r);
435         if (!NT_STATUS_IS_OK(status)) {
436                 printf("AddStdRoot failed - %s\n", nt_errstr(status));
437                 return false;
438         } else if (!W_ERROR_IS_OK(r.out.result)) {
439                 printf("dfs_AddStdRoot failed - %s\n",
440                         win_errstr(r.out.result));
441                 return false;
442         }
443
444         return true;
445 }
446
447 static bool test_AddStdRootForced(struct dcerpc_pipe *p,
448                                   TALLOC_CTX *mem_ctx,
449                                   const char *host,
450                                   const char *sharename)
451 {
452         NTSTATUS status;
453         struct dfs_AddStdRootForced r;
454         enum dfs_ManagerVersion version;
455
456         printf("Testing AddStdRootForced\n");
457
458         if (!test_GetManagerVersion(p, mem_ctx, &version)) {
459                 return false;
460         }
461
462         r.in.servername = host;
463         r.in.rootshare  = sharename;
464         r.in.comment    = "standard dfs forced standalone DFS root created by smbtorture (dfs_AddStdRootForced)";
465         r.in.store      = SMBTORTURE_DFS_PATHNAME;
466
467         status = dcerpc_dfs_AddStdRootForced(p, mem_ctx, &r);
468         if (!NT_STATUS_IS_OK(status)) {
469                 printf("AddStdRootForced failed - %s\n", nt_errstr(status));
470                 return false;
471         } else if (!W_ERROR_IS_OK(r.out.result)) {
472                 printf("dfs_AddStdRootForced failed - %s\n",
473                         win_errstr(r.out.result));
474                 IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
475                 return false;
476         }
477
478         return test_RemoveStdRoot(p, mem_ctx, host, sharename);
479 }
480
481 static void test_cleanup_stdroot(struct dcerpc_pipe *p,
482                                  TALLOC_CTX *mem_ctx,
483                                  const char *host,
484                                  const char *sharename,
485                                  const char *dir)
486 {
487         struct smbcli_state *cli;
488
489         printf("Cleaning up StdRoot\n");
490
491         test_RemoveStdRoot(p, mem_ctx, host, sharename);
492         test_NetShareDel(mem_ctx, host, sharename);
493         torture_open_connection_share(mem_ctx, &cli, host, "C$", NULL);
494         test_DeleteDir(cli, dir);
495         torture_close_connection(cli);
496 }
497
498 static bool test_StdRoot(struct dcerpc_pipe *p,
499                          TALLOC_CTX *mem_ctx,
500                          const char *host)
501 {
502         const char *sharename = SMBTORTURE_DFS_SHARENAME;
503         const char *dir = SMBTORTURE_DFS_DIRNAME;
504         const char *path = SMBTORTURE_DFS_PATHNAME;
505         struct smbcli_state *cli;
506         bool ret = true;
507
508         printf("Testing StdRoot\n");
509
510         test_cleanup_stdroot(p, mem_ctx, host, sharename, dir);
511
512         ret &= test_CreateDir(mem_ctx, &cli, host, "C$", dir);
513         ret &= test_NetShareAdd(mem_ctx, host, sharename, path);
514         ret &= test_AddStdRoot(p, mem_ctx, host, sharename);
515         ret &= test_RemoveStdRoot(p, mem_ctx, host, sharename);
516         ret &= test_AddStdRootForced(p, mem_ctx, host, sharename);
517         ret &= test_NetShareDel(mem_ctx, host, sharename);
518         ret &= test_DeleteDir(cli, dir);
519
520         torture_close_connection(cli);
521
522         return ret;
523 }
524
525 static bool test_GetDcAddress(struct dcerpc_pipe *p,
526                               TALLOC_CTX *mem_ctx,
527                               const char *host)
528 {
529         NTSTATUS status;
530         struct dfs_GetDcAddress r;
531         uint8_t is_root = 0;
532         uint32_t ttl = 0;
533         const char *ptr;
534
535         printf("Testing GetDcAddress\n");
536
537         ptr = host;
538
539         r.in.servername = host;
540         r.in.server_fullname = r.out.server_fullname = &ptr;
541         r.in.is_root = r.out.is_root = &is_root;
542         r.in.ttl = r.out.ttl = &ttl;
543
544         status = dcerpc_dfs_GetDcAddress(p, mem_ctx, &r);
545         if (!NT_STATUS_IS_OK(status)) {
546                 printf("GetDcAddress failed - %s\n", nt_errstr(status));
547                 return false;
548         } else if (!W_ERROR_IS_OK(r.out.result)) {
549                 printf("dfs_GetDcAddress failed - %s\n",
550                         win_errstr(r.out.result));
551                 return false;
552         }
553
554         return true;
555 }
556
557 static bool test_SetDcAddress(struct dcerpc_pipe *p,
558                               TALLOC_CTX *mem_ctx,
559                               const char *host)
560 {
561         NTSTATUS status;
562         struct dfs_SetDcAddress r;
563
564         printf("Testing SetDcAddress\n");
565
566         r.in.servername = host;
567         r.in.server_fullname = host;
568         r.in.flags = 0;
569         r.in.ttl = 1000;
570
571         status = dcerpc_dfs_SetDcAddress(p, mem_ctx, &r);
572         if (!NT_STATUS_IS_OK(status)) {
573                 printf("SetDcAddress failed - %s\n", nt_errstr(status));
574                 return false;
575         } else if (!W_ERROR_IS_OK(r.out.result)) {
576                 printf("dfs_SetDcAddress failed - %s\n",
577                         win_errstr(r.out.result));
578                 return false;
579         }
580
581         return true;
582 }
583
584 static bool test_DcAddress(struct dcerpc_pipe *p,
585                            TALLOC_CTX *mem_ctx,
586                            const char *host)
587 {
588         if (!test_GetDcAddress(p, mem_ctx, host)) {
589                 return false;
590         }
591
592         if (!test_SetDcAddress(p, mem_ctx, host)) {
593                 return false;
594         }
595
596         return true;
597 }
598
599 static bool test_FlushFtTable(struct dcerpc_pipe *p,
600                               TALLOC_CTX *mem_ctx,
601                               const char *host,
602                               const char *sharename)
603 {
604         NTSTATUS status;
605         struct dfs_FlushFtTable r;
606         enum dfs_ManagerVersion version;
607
608         printf("Testing FlushFtTable\n");
609
610         if (!test_GetManagerVersion(p, mem_ctx, &version)) {
611                 return false;
612         }
613
614         r.in.servername = host;
615         r.in.rootshare = sharename;
616
617         status = dcerpc_dfs_FlushFtTable(p, mem_ctx, &r);
618         if (!NT_STATUS_IS_OK(status)) {
619                 printf("FlushFtTable failed - %s\n", nt_errstr(status));
620                 return false;
621         } else if (!W_ERROR_IS_OK(r.out.result)) {
622                 printf("dfs_FlushFtTable failed - %s\n",
623                         win_errstr(r.out.result));
624                 IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
625                 return false;
626         }
627
628         return true;
629 }
630
631 static bool test_FtRoot(struct dcerpc_pipe *p,
632                         TALLOC_CTX *mem_ctx,
633                         const char *host)
634 {
635         const char *sharename = SMBTORTURE_DFS_SHARENAME;
636
637         return test_FlushFtTable(p, mem_ctx, host, sharename);
638 }
639
640 bool torture_rpc_dfs(struct torture_context *torture)
641 {
642         NTSTATUS status;
643         struct dcerpc_pipe *p;
644         bool ret = true;
645         enum dfs_ManagerVersion version;
646         const char *host = torture_setting_string(torture, "host", NULL);
647
648         status = torture_rpc_connection(torture, &p, &ndr_table_netdfs);
649         torture_assert_ntstatus_ok(torture, status, "Unable to connect");
650
651         ret &= test_GetManagerVersion(p, torture, &version);
652         ret &= test_ManagerInitialize(p, torture, host);
653         ret &= test_Enum(p, torture);
654         ret &= test_EnumEx(p, torture, host);
655         ret &= test_StdRoot(p, torture, host);
656         ret &= test_FtRoot(p, torture, host);
657         ret &= test_DcAddress(p, torture, host);
658
659         return ret;
660 }