0e06936672881fba92cf4ec418a29f4ea2de4aa2
[garming/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 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 #include "includes.h"
22 #include "torture/torture.h"
23 #include "torture/rpc/rpc.h"
24 #include "librpc/gen_ndr/ndr_dfs_c.h"
25 #include "librpc/gen_ndr/ndr_srvsvc_c.h"
26 #include "libnet/libnet.h"
27 #include "libcli/raw/libcliraw.h"
28 #include "torture/util.h"
29 #include "libcli/libcli.h"
30 #include "lib/cmdline/popt_common.h"
31
32 #if 0
33
34 #define SMBTORTURE_DFS_SHARENAME "smbtorture_dfs_share"
35 #define SMBTORTURE_DFS_DIRNAME "\\smbtorture_dfs_dir"
36 #define SMBTORTURE_DFS_PATHNAME "C:"SMBTORTURE_DFS_DIRNAME
37
38 #define IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(x,y)\
39         if (x == DFS_MANAGER_VERSION_W2K3) {\
40                 if (!W_ERROR_EQUAL(y,WERR_NOT_SUPPORTED)) {\
41                         printf("expected WERR_NOT_SUPPORTED\n");\
42                         return False;\
43                 }\
44                 return True;\
45         }\
46
47 static BOOL test_NetShareAdd(TALLOC_CTX *mem_ctx, const char *host, const char *sharename, const char *dir)
48 {
49         NTSTATUS status;
50         struct srvsvc_NetShareInfo2 i;
51         struct libnet_context* libnetctx;
52         struct libnet_AddShare r;
53
54         printf("Creating share %s\n", sharename);
55
56         if (!(libnetctx = libnet_context_init(NULL))) {
57                 return False;
58         }
59
60         libnetctx->cred = cmdline_credentials;
61
62         i.name                  = sharename;
63         i.type                  = STYPE_DISKTREE;
64         i.path                  = dir;
65         i.max_users             = (uint32_t) -1;
66         i.comment               = "created by smbtorture";
67         i.password              = NULL;
68         i.permissions           = 0x0;
69         i.current_users         = 0x0;
70
71         r.level                 = 2;
72         r.in.server_name        = host;
73         r.in.share              = i;
74
75         status = libnet_AddShare(libnetctx, mem_ctx, &r);
76         if (!NT_STATUS_IS_OK(status)) {
77                 d_printf("Failed to add new share: %s (%s)\n", 
78                         nt_errstr(status), r.out.error_string);
79                 return False;
80         }
81
82         return True;
83 }
84
85 static BOOL test_NetShareDel(TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
86 {
87         NTSTATUS status;
88         struct libnet_context* libnetctx;
89         struct libnet_DelShare r;
90
91         printf("Deleting share %s\n", sharename);
92
93         if (!(libnetctx = libnet_context_init(NULL))) {
94                 return False;
95         }
96
97         libnetctx->cred = cmdline_credentials;
98
99         r.in.share_name         = sharename;
100         r.in.server_name        = host;
101
102         status = libnet_DelShare(libnetctx, mem_ctx, &r);
103         if (!NT_STATUS_IS_OK(status)) {
104                 d_printf("Failed to delete share: %s (%s)\n", 
105                         nt_errstr(status), r.out.error_string);
106                 return False;
107         }
108
109         return True;
110 }
111
112 static BOOL test_CreateDir(TALLOC_CTX *mem_ctx, 
113                            struct smbcli_state **cli, 
114                            const char *host, 
115                            const char *share, 
116                            const char *dir)
117 {
118         printf("Creating directory %s\n", dir);
119
120         if (!torture_open_connection_share(mem_ctx, cli, host, share, NULL)) {
121                 return False;
122         }
123
124         if (!torture_setup_dir(*cli, dir)) {
125                 return False;
126         }
127
128         return True;
129 }
130
131 static BOOL test_DeleteDir(struct smbcli_state *cli, const char *dir)
132 {
133         printf("Deleting directory %s\n", dir);
134
135         if (smbcli_deltree(cli->tree, dir) == -1) {
136                 printf("Unable to delete dir %s - %s\n", dir, smbcli_errstr(cli->tree));
137                 return False;
138         }
139
140         return True;
141 }
142
143 static BOOL test_GetManagerVersion(struct torture_context *tctx, struct dcerpc_pipe *p, enum dfs_ManagerVersion *version)
144 {
145         NTSTATUS status;
146         struct dfs_GetManagerVersion r;
147
148         r.out.version = version;
149
150         status = dcerpc_dfs_GetManagerVersion(p, tctx, &r);
151         torture_assert_ntstatus_ok(tctx, status, "GetManagerVersion failed");
152
153         return true;
154 }
155
156 static BOOL test_ManagerInitialize(struct torture_context *tctx, struct dcerpc_pipe *p, const char *host)
157 {
158         NTSTATUS status;
159         enum dfs_ManagerVersion version;
160         struct dfs_ManagerInitialize r;
161
162         printf("Testing ManagerInitialize\n");
163
164         if (!test_GetManagerVersion(tctx, p, &version)) {
165                 return False;
166         }
167
168         r.in.servername = host;
169         r.in.flags = 0;
170
171         status = dcerpc_dfs_ManagerInitialize(p, tctx, &r);
172         if (!NT_STATUS_IS_OK(status)) {
173                 printf("ManagerInitialize failed - %s\n", nt_errstr(status));
174                 return False;
175         } else if (!W_ERROR_IS_OK(r.out.result)) {
176                 printf("dfs_ManagerInitialize failed - %s\n", win_errstr(r.out.result));
177                 IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
178                 return False;
179         }
180
181         return True;
182 }
183
184 static BOOL test_GetInfoLevel(struct torture_context *tctx, struct dcerpc_pipe *p, uint16_t level, const char *root)
185 {
186         NTSTATUS status;
187         struct dfs_GetInfo r;
188
189         torture_comment(tctx, 
190                 talloc_asprintf(tctx, "Testing GetInfo level %u on '%s'\n", level, root));
191
192         r.in.dfs_entry_path = talloc_strdup(tctx, root);
193         r.in.servername = NULL;
194         r.in.sharename = NULL;
195         r.in.level = level;
196
197         status = dcerpc_dfs_GetInfo(p, tctx, &r);
198         torture_assert_ntstatus_ok(tctx, status, "Info failed");
199         torture_assert(tctx, W_ERROR_IS_OK(r.out.result) ||
200                    W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result),
201                         talloc_asprintf(tctx, 
202                                 "dfs_GetInfo failed - %s", win_errstr(r.out.result)));
203
204         return True;
205 }
206
207 static bool test_Info(struct torture_context *tctx, 
208                                           struct dcerpc_pipe *p, const char *root)
209 {
210         BOOL ret = True;
211         /* 103, 104, 105, 106 is only available on Set */
212         uint16_t levels[] = {1, 2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106};
213         int i;
214
215         for (i=0;i<ARRAY_SIZE(levels);i++) {
216                 if (!test_GetInfoLevel(tctx, p, levels[i], root)) {
217                         ret = false;
218                 }
219         }
220         return ret;
221 }
222
223 static bool test_EnumLevel(struct torture_context *tctx, 
224                                                    struct dcerpc_pipe *p, uint16_t level)
225 {
226         NTSTATUS status;
227         struct dfs_EnumEx rex;
228         uint32_t total=0;
229         struct dfs_EnumStruct e;
230         struct dfs_Info1 s;
231         struct dfs_EnumArray1 e1;
232         BOOL ret = True;
233         
234         rex.in.level = level;
235         rex.in.bufsize = (uint32_t)-1;
236         rex.in.total = &total;
237         rex.in.info = &e;
238         rex.in.dfs_name = dfs_name;
239
240         e.level = rex.in.level;
241         e.e.info1 = &e1;
242         e.e.info1->count = 0;
243         e.e.info1->s = &s;
244         s.path = NULL;
245
246         printf("Testing EnumEx level %u on '%s'\n", level, dfs_name);
247
248         status = dcerpc_dfs_EnumEx(p, mem_ctx, &rex);
249         if (!NT_STATUS_IS_OK(status)) {
250                 printf("EnumEx failed - %s\n", nt_errstr(status));
251                 return False;
252         }
253
254         if (level == 1 && rex.out.total) {
255                 int i;
256                 for (i=0;i<*rex.out.total;i++) {
257                         const char *root = talloc_strdup(mem_ctx, rex.out.info->e.info1->s[i].path);
258                         if (!test_GetInfo(p, mem_ctx, root)) {
259                                 ret = False;
260                         }
261                 }
262         }
263
264         if (level == 300 && rex.out.total) {
265                 int i,k;
266                 for (i=0;i<*rex.out.total;i++) {
267                         uint16_t levels[] = {1, 2, 3, 4, 200}; /* 300 */
268                         const char *root = talloc_strdup(mem_ctx, rex.out.info->e.info300->s[i].dom_root);
269                         for (k=0;k<ARRAY_SIZE(levels);k++) {
270                                 if (!test_EnumLevelEx(p, mem_ctx, levels[k], root)) {
271                                         ret = False;
272                                 }
273                         }
274                         if (!test_GetInfo(p, mem_ctx, root)) {
275                                 ret = False;
276                         }
277                 }
278         }
279
280         return ret;
281 }
282
283
284 static BOOL test_EnumLevel(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, uint16_t level)
285 {
286         NTSTATUS status;
287         struct dfs_Enum r;
288         uint32_t total=0;
289         struct dfs_EnumStruct e;
290         struct dfs_Info1 s;
291         struct dfs_EnumArray1 e1;
292         BOOL ret = True;
293         
294         r.in.level = level;
295         r.in.bufsize = (uint32_t)-1;
296         r.in.total = &total;
297         r.in.info = &e;
298
299         e.level = r.in.level;
300         e.e.info1 = &e1;
301         e.e.info1->count = 0;
302         e.e.info1->s = &s;
303         s.path = NULL;
304         
305         status = dcerpc_dfs_Enum(p, tctx, &r);
306         torture_assert_ntstatus_ok(tctx, status, "Enum failed - %s\n", 
307                                                            nt_errstr(status));
308         torture_assert(tctx, W_ERROR_IS_OK(r.out.result) || 
309                    W_ERROR_EQUAL(WERR_NO_MORE_ITEMS, r.out.result),
310                 "dfs_Enum failed - %s", win_errstr(r.out.result));
311
312         if (level == 1 && r.out.total) {
313                 int i;
314                 for (i=0;i<*r.out.total;i++) {
315                         const char *root = r.out.info->e.info1->s[i].path;
316                         if (!test_GetInfo(tctx, p, root)) {
317                                 ret = False;
318                         }
319                 }
320                 
321         }
322
323         return ret;
324 }
325
326
327 static bool test_Enum(struct torture_context *tctx,
328                                           struct dcerpc_pipe *p)
329 {
330         BOOL ret = True;
331         uint16_t levels[] = {1, 2, 3, 4, 200, 300};
332         int i;
333
334         for (i=0;i<ARRAY_SIZE(levels);i++) {
335                 if (!test_EnumLevel(tctx, p, levels[i])) {
336                         ret = false;
337                 }
338         }
339
340         return ret;
341 }
342
343 static BOOL test_EnumEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host)
344 {
345         BOOL ret = True;
346         uint16_t levels[] = {1, 2, 3, 4, 200, 300};
347         int i;
348
349         for (i=0;i<ARRAY_SIZE(levels);i++) {
350                 if (!test_EnumLevelEx(p, mem_ctx, levels[i], host)) {
351                         ret = False;
352                 }
353         }
354
355         return ret;
356 }
357
358 static BOOL test_RemoveStdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
359 {
360         struct dfs_RemoveStdRoot r;
361         NTSTATUS status;
362
363         printf("Testing RemoveStdRoot\n");
364
365         r.in.servername = host;
366         r.in.rootshare  = sharename;
367         r.in.flags      = 0;
368
369         status = dcerpc_dfs_RemoveStdRoot(p, mem_ctx, &r);
370         if (!NT_STATUS_IS_OK(status)) {
371                 printf("RemoveStdRoot failed - %s\n", nt_errstr(status));
372                 return False;
373         } else if (!W_ERROR_IS_OK(r.out.result)) {
374                 printf("dfs_RemoveStdRoot failed - %s\n", win_errstr(r.out.result));
375                 return False;
376         }
377
378         return True;
379 }
380
381 static BOOL test_AddStdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
382 {
383         NTSTATUS status;
384         struct dfs_AddStdRoot r;
385
386         printf("Testing AddStdRoot\n");
387
388         r.in.servername = host;
389         r.in.rootshare  = sharename;
390         r.in.comment    = "standard dfs standalone DFS root created by smbtorture (dfs_AddStdRoot)";
391         r.in.flags      = 0;
392
393         status = dcerpc_dfs_AddStdRoot(p, mem_ctx, &r);
394         if (!NT_STATUS_IS_OK(status)) {
395                 printf("AddStdRoot failed - %s\n", nt_errstr(status));
396                 return False;
397         } else if (!W_ERROR_IS_OK(r.out.result)) {
398                 printf("dfs_AddStdRoot failed - %s\n", win_errstr(r.out.result));
399                 return False;
400         }
401
402         return True;
403 }
404
405 static BOOL test_AddStdRootForced(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host, const char *sharename)
406 {
407         NTSTATUS status;
408         struct dfs_AddStdRootForced r;
409         enum dfs_ManagerVersion version;
410
411         printf("Testing AddStdRootForced\n");
412
413         if (!test_GetManagerVersion(p, mem_ctx, &version)) {
414                 return False;
415         }
416
417         r.in.servername = host;
418         r.in.rootshare  = sharename;
419         r.in.comment    = "standard dfs forced standalone DFS root created by smbtorture (dfs_AddStdRootForced)";
420         r.in.store      = SMBTORTURE_DFS_PATHNAME;
421
422         status = dcerpc_dfs_AddStdRootForced(p, mem_ctx, &r);
423         if (!NT_STATUS_IS_OK(status)) {
424                 printf("AddStdRootForced failed - %s\n", nt_errstr(status));
425                 return False;
426         } else if (!W_ERROR_IS_OK(r.out.result)) {
427                 printf("dfs_AddStdRootForced failed - %s\n", win_errstr(r.out.result));
428                 IS_DFS_VERSION_UNSUPPORTED_CALL_W2K3(version, r.out.result);
429                 return False;
430         }
431
432         return test_RemoveStdRoot(p, mem_ctx, host, sharename);
433 }
434
435 static void test_cleanup_stdroot(struct dcerpc_pipe *p, 
436                                  TALLOC_CTX *mem_ctx, 
437                                  const char *host, 
438                                  const char *sharename, 
439                                  const char *dir)
440 {
441         struct smbcli_state *cli;
442
443         printf("Cleaning up StdRoot\n");
444
445         test_RemoveStdRoot(p, mem_ctx, host, sharename);
446         test_NetShareDel(mem_ctx, host, sharename);
447         torture_open_connection_share(mem_ctx, &cli, host, "C$", NULL);
448         test_DeleteDir(cli, dir);
449         torture_close_connection(cli);
450 }
451
452 static BOOL test_StdRoot(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *host)
453 {
454         const char *sharename = SMBTORTURE_DFS_SHARENAME;
455         const char *dir = SMBTORTURE_DFS_DIRNAME;
456         const char *path = SMBTORTURE_DFS_PATHNAME;
457         struct smbcli_state *cli;
458         BOOL ret;
459
460         printf("Testing StdRoot\n");
461
462         test_cleanup_stdroot(p, mem_ctx, host, sharename, dir);
463
464         ret &= test_CreateDir(mem_ctx, &cli, host, "C$", dir);
465         ret &= test_NetShareAdd(mem_ctx, host, sharename, path);
466         ret &= test_AddStdRoot(p, mem_ctx, host, sharename);
467         ret &= test_RemoveStdRoot(p, mem_ctx, host, sharename);
468         ret &= test_AddStdRootForced(p, mem_ctx, host, sharename);
469         ret &= test_NetShareDel(mem_ctx, host, sharename);
470         ret &= test_DeleteDir(cli, dir);
471
472         torture_close_connection(cli);
473
474         return ret;
475 }
476
477 #endif
478
479 struct torture_suite *torture_rpc_dfs(void)
480 {
481         struct torture_suite *suite = torture_suite_create(
482                                                                         talloc_autofree_context(), "RPC-DFS");
483
484 #if 0
485         struct torture_tcase *tcase = torture_suite_add_rpc_iface_tcase(suite, 
486                                                                                                 "dfs", &dcerpc_table_netdfs);
487
488         torture_rpc_tcase_add_test(tcase, "GetManagerVersion", 
489                                                            test_GetManagerVersion);
490
491 #if 0
492         torture_rpc_tcase_add_test(tcase, "Add", 
493                                                            test_Add);
494 #endif
495
496         torture_rpc_tcase_add_test(tcase, "Enum", test_Enum);
497         torture_rpc_tcase_add_test(tcase, "EnumEx", test_EnumEx);
498         torture_rpc_tcase_add_test(tcase, "ManagerInitialize", 
499                                                            test_ManagerInitialize);
500         torture_rpc_tcase_add_test(tcase, "StdRoot", 
501                                                            test_StdRoot);
502
503         talloc_free(mem_ctx);
504
505 #endif
506
507         return suite;
508 }