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